#include #include #include "epg2vdr.h" #include "update.h" int loglevel = 4; cDbConnection* connection = 0; int fileExists(const char* path) { return access(path, F_OK) == 0; } cEvent::cEvent(tEventID EventID) { schedule = NULL; eventID = EventID; tableID = 0xFF; version = 0xFF; title = NULL; shortText = NULL; description = NULL; components = NULL; memset(contents, 0, sizeof(contents)); parentalRating = 0; startTime = 0; duration = 0; vps = 0; } cEvent::~cEvent() { } int cEvent::Compare(const cListObject &ListObject) const { return 0; } void cEvent::SetTitle(const char* t) { title = strcpyrealloc(title, t); } void cEvent::SetShortText(const char *ShortText) { shortText = strcpyrealloc(shortText, ShortText); } void cEvent::SetDescription(const char *Description) { description = strcpyrealloc(description, Description); } void cEvent::SetStartTime(time_t StartTime) { } void cEvent::SetDuration(int Duration) { } // --- tChannelID ------------------------------------------------------------ const tChannelID tChannelID::InvalidID; tChannelID tChannelID::FromString(const char *s) { // char *sourcebuf = NULL; // int nid; // int tid; // int sid; // int rid = 0; // int fields = sscanf(s, "%a[^-]-%d-%d-%d-%d", &sourcebuf, &nid, &tid, &sid, &rid); // if (fields == 4 || fields == 5) { // int source = cSource::FromString(sourcebuf); // free(sourcebuf); // if (source >= 0) // return tChannelID(source, nid, tid, sid, rid); // } return tChannelID::InvalidID; } // cString tChannelID::ToString(void) const // { // char buffer[256]; // snprintf(buffer, sizeof(buffer), rid ? "%s-%d-%d-%d-%d" : "%s-%d-%d-%d", *cSource::ToString(source), nid, tid, sid, rid); // return buffer; // } tChannelID &tChannelID::ClrPolarization(void) { while (tid > 100000) tid -= 100000; return *this; } //*************************************************************************** // Parse XML Event //*************************************************************************** int parseEvent(cDbRow* event, xmlNode* node) { const char* name; char* content; for (xmlNodePtr n = node->xmlChildrenNode; n; n = n->next) { if (n->type != XML_ELEMENT_NODE) continue; name = (const char*)n->name; content = (char*)xmlNodeGetContent(n); printf("\t%s = '%s'\n", name, content); if (cDbService::FieldDef* f = cEventFields::toField(name)) { if (f->format == cDbService::ffAscii) event->setValue(f->index, content); else event->setValue(f->index, atoi(content)); } else printf("Ignoring unexpected element <%s>\n", name); xmlFree(content); } return success; } //*************************************************************************** // //*************************************************************************** MemoryStruct data; //*************************************************************************** // Download Episodes and store to filesystem //*************************************************************************** int downloadEpisodes(Table* episodeDb) { // #CKO // cSvdrpClient cl("eplists.constabel.net", 2006 /*port*/); cSvdrpClient cl("bauerl", 2006 /*port*/); string fileName; string linkName; int isLink = 0; cEpisodeFiles files; int code; int abort = 0; char command[50]; int withutf8 = yes; if (cl.open() != 0) { printf("Open connection to '%s' failed, aborting transfer!\n", "eplists.constabel.net"); return fail; } printf("Starting episode download ...\n"); // select characterset printf("request charset ...\n"); if (!cl.send(withutf8 ? "CHARSET utf-8\n": "CHARSET iso-8859-1\n")) { tell(0, "Send '%s' failed, aborting transfer!", command); cl.close(); return fail; } // check for characterset confirmation cList csconf; if (cl.receive(&csconf) != 225) { tell(0, "SVDRPCL: did not receive charset confirmation. Closing..."); cl.abort(); return fail; } if (csconf.First() && csconf.First()->Text()) tell(0, "Got '%s'", csconf.First()->Text()); // identify myself sprintf(command, "HELLO %s v%s (%s)\n", "epgd", VERSION, VERSION_DATE); printf("send %s", command); cl.send(command); cl.receive(); // GET // sprintf(command, "GET all\n"); // #CKO sprintf(command, "TGET newer than 4 days\n"); // #CKO printf("send %s", command); if (!cl.send(command)) { printf("Send '%s' failed, aborting transfer!\n", command); cl.close(); return fail; } cList* result = new cList; while (!abort && (code = cl.receive(result)) != codeCommunicationEnd) { switch (code) { case codeFileInfo: { if (result->Count() < 2) { if (loglevel > 1) printf("Protocol violation, aborting!\n"); abort = 1; } else { linkName = ""; fileName = result->Next(result->First())->Text(); isLink = fileName != "not a link"; if (!isLink) fileName = result->First()->Text(); else linkName = result->First()->Text(); } break; } case codeFileContent: { if (isLink) { files.Add(new cEpisodeFile(fileName, linkName)); } else { for (cLine* l = result->First(); l; l = result->Next(l)) { if (strcmp(l->Text(), "End of data") == 0) { result->Del(l); break; } } if (result->Count()) { // create episode file and adopt the result files.Add(new cEpisodeFile(fileName, "", result)); // create new result object since cEpisodeFile adopted the current result = new cList; } } break; } case codeTransferEnd: { abort = 1; break; } } result->Clear(); } printf("Received %d episode files\n", files.Count()); files.storeToFile("./epl/"); files.storeToTable(episodeDb); delete result; cl.close(); return 0; } //*************************************************************************** // Update Map Table //*************************************************************************** int updateChannelMap(cChannelMap* chanmap, const char* dbpath) { Table* mapDb; int count = 0; mapDb = new Table(connection, "channelmap", cChannelMapFields::fields); if (mapDb->open() != success) { tell(0, "Could not access sqlite database %s for table %s", dbpath, mapDb->TableName()); return fail; } mapDb->truncate(); tell(0, "Update map"); for (cChanMap::iterator iter = chanmap->chanmap.begin(); iter != chanmap->chanmap.end(); iter++) { const char* extid = iter->first; tell(0, "Update map for extid %s", extid); for (int index = 0; index < chanmap->GetChanCount(extid); index++) { mapDb->clear(); mapDb->setValue(cChannelMapFields::fiExtId, extid); mapDb->setValue(cChannelMapFields::fiChannelId, chanmap->GetChanStr(extid, index)); mapDb->setValue(cChannelMapFields::fiSource, chanmap->isNull(extid) ? "epgdata" : "vdr"); mapDb->store(); tell(0, "insert '%s' to extid %s in map", chanmap->GetChanStr(extid, index), extid); count++; } } tell(0, "Update channel map done with %d entries", count); delete mapDb; return success; } //*************************************************************************** // Main //*************************************************************************** int main(int argc, char** argv) { int res; if (argc < 1) { printf("Usage: %s \n", argv[0]); return 1; } Table::setConfPath("./configs/epg2vdr"); cDbConnection::setHost("bauerl"); // #CKO cDbConnection::setEncoding("utf8"); connection = new cDbConnection(); // ------------------------------------------------ // Image Table Test Table* imageDb = new Table(connection, "images", cImageFields::fields, cImageFields::views); if (imageDb->open() != success) { printf("Opening database 'images' failed\n"); delete imageDb; return 1; } // imageDb->clear(); // imageDb->setValue(cImageFields::fiEventId, 1212); // imageDb->setValue(cImageFields::fiLfn, 0); // imageDb->setValue(cImageFields::fiName, "1212.jpg"); // imageDb->store(); imageDb->clear(); imageDb->setValue(cImageFields::fiLfn, 1); // limit to config for (int res = imageDb->find(cImageFields::viAllLessLfn); res; res = imageDb->fetch(cImageFields::viAllLessLfn)) { int eventid = imageDb->getIntValue(cImageFields::fiEventId); const char* image = imageDb->getStrValue(cImageFields::fiName); int lfn = imageDb->getIntValue(cImageFields::fiLfn); char* destfile; asprintf(&destfile, "./%s", image); // get image if missing if (!fileExists(destfile) && !imageDb->isNull(cImageFields::fiImage)) { printf("Store image '%s' with %ld bytes\n", destfile, imageDb->getStrValueSize(cImageFields::fiImage)); if (FILE* fh1 = fopen(destfile, "w")) { fwrite(imageDb->getStrValue(cImageFields::fiImage), 1, imageDb->getStrValueSize(cImageFields::fiImage), fh1); fclose(fh1); } else { printf("can't write image to '%s', error was '%m'\n", destfile); } } free(destfile); } imageDb->resetFetch(cImageFields::viAllLessLfn); imageDb->clear(); imageDb->setValue(cImageFields::fiLfn, 1); // limit to config // delete imageDb; // return 0; for (int res = imageDb->find(cImageFields::viAllLessLfn); res; res = imageDb->fetch(cImageFields::viAllLessLfn)) { int eventid = imageDb->getIntValue(cImageFields::fiEventId); const char* image = imageDb->getStrValue(cImageFields::fiName); int lfn = imageDb->getIntValue(cImageFields::fiLfn); // if (lfn != 0) tell(0, "Got lfn %d from table, max is %d", lfn, EPG2VDRConfig.maximagesperevent); char* destfile; asprintf(&destfile, "./%s", image); printf("Check for '%s'\n", destfile); // import the images from the FS into the table if (fileExists(destfile)) { printf("Found '%s' import to database\n", destfile); if (FILE* fh1 = fopen(destfile, "r")) { int size = 200000; char* buf = (char*)calloc(size, sizeof(char)); size = fread(buf, 1, size, fh1); if (size > 0 || size < 200000) { printf("Copy image '%s' with %d bytes to table\n", destfile, size); imageDb->setValue(cImageFields::fiImage, buf, size); imageDb->store(); } free(buf); fclose(fh1); } else { tell(1, "Can't open image '%s', error was '%m'", destfile); } } free(destfile); } imageDb->resetFetch(cImageFields::viAllLessLfn); delete imageDb; return 0; // ------------------------------------------------ // Constabel Test Table* episodesDb = new Table(connection, "episodes", cEpisodeFields::fields, cEpisodeFields::views); if (episodesDb->open() != success) { printf("Opening database 'episodes' failed\n"); delete episodesDb; return 1; } // test insert ... episodesDb->clear(); episodesDb->setValue(cEpisodeFields::fiCompName, "TESTSERIE1"); episodesDb->setValue(cEpisodeFields::fiCompPartName, "TESTSERIE"); episodesDb->setValue(cEpisodeFields::fiEpisodeName, "PART1"); episodesDb->setValue(cEpisodeFields::fiPartName, "part1"); episodesDb->setValue(cEpisodeFields::fiLang, "de"); episodesDb->store(); episodesDb->clear(); episodesDb->setValue(cEpisodeFields::fiCompName, "TESTSERIE1"); episodesDb->setValue(cEpisodeFields::fiCompPartName, "TESTSERIE"); episodesDb->setValue(cEpisodeFields::fiLang, "de"); if (episodesDb->find()) { printf("Got: %s\n", episodesDb->getStrValue(cEpisodeFields::fiEpisodeName)); printf("Got: %s\n", episodesDb->getStrValue(cEpisodeFields::fiPartName)); } downloadEpisodes(episodesDb); // evaluateEpisodes(episodesDb, evtDb); delete episodesDb; // ------------------------------------------------ // Test Episodes Table ... printf("\n----------------------------------\n"); Table* epiDb = new Table(connection, "episodes", cEpisodeFields::fields, cEpisodeFields::views); if (epiDb->open() != success) { printf("Opening database 'episodes' failed\n"); delete epiDb; return 1; } int days = na; epiDb->clear(); epiDb->setValue(cEpisodeFields::fiCompName, "TESTSERIE"); epiDb->setValue(cEpisodeFields::fiCompPartName, "TESTSERIE"); epiDb->setValue(cEpisodeFields::fiEpisodeName, "test serie"); epiDb->setValue(cEpisodeFields::fiPartName, "part1"); epiDb->setValue(cEpisodeFields::fiLang, "de"); epiDb->store(); epiDb->clear(); if (epiDb->find(cEpisodeFields::viMaxUpdSp)) { printf("found - max updsp is (%ld)\n", epiDb->getIntValue(cEpisodeFields::fiMaxUpdSp)); if (epiDb->getIntValue(cEpisodeFields::fiMaxUpdSp)) days = (time(0) - epiDb->getIntValue(cEpisodeFields::fiMaxUpdSp)) / 60 / 60 / 24; } epiDb->resetFetch(cEpisodeFields::viMaxUpdSp); printf("episodes have to get %d days\n", days); delete epiDb; // ------------------------------------------------ // Test EPG Table ... printf("\n----------------------------------\n"); Table* db = new Table(connection, "events", cEventFields::fields, cEventFields::views); if (db->open() != success) { printf("Opening database 'events' failed\n"); delete db; return 1; } db->setValue(cEventFields::fiEventId, 4711); db->setValue(cEventFields::fiSource, "epgdata"); db->setValue(cEventFields::fiTitle, "Test Title"); db->setValue(cEventFields::fiCompTitle, "TESTTITLE"); db->setValue(cEventFields::fiChannelId, "11"); db->setValue(cEventFields::fiCategory, "cat 11"); db->store(); db->clear(); db->setValue(cEventFields::fiEventId, 4712); db->setValue(cEventFields::fiSource, "epgdata"); db->setValue(cEventFields::fiShortText, "blablabla"); db->setValue(cEventFields::fiTitle, "Test Title 12"); db->setValue(cEventFields::fiCompTitle, "TESTTITLE"); db->setValue(cEventFields::fiChannelId, "11"); db->setValue(cEventFields::fiFileRef, "test-1234"); db->setValue(cEventFields::fiCategory, "cat 12"); db->setValue(cEventFields::fiLongDescription, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"); db->store(); db->clear(); db->setValue(cEventFields::fiEventId, 4713); db->setValue(cEventFields::fiSource, "epgdata"); db->setValue(cEventFields::fiTitle, "Test Title what the fuck ..."); db->setValue(cEventFields::fiChannelId, "11"); db->setValue(cEventFields::fiFileRef, "test-11111"); db->setValue(cEventFields::fiCategory, "cat 13"); db->setValue(cEventFields::fiCompTitle, "TESTTITLEWHATTHEFUCK"); db->store(); // fetch via view printf("lookup events for channel 11 via lview\n"); db->clear(); db->setValue(cEventFields::fiChannelId, "11"); db->setValue(cEventFields::fiSource, "epgdata"); for (res = db->find(cEventFields::viByChannel); res; res = db->fetch(cEventFields::viByChannel)) { if (!db->find()) printf("FATAL!\n"); int id = db->getIntValue(cEventFields::fiEventId); printf(" -> found event '%s'(%d) [%s] '%s'\n", db->getStrValue(cEventFields::fiTitle), id, db->getStrValue(cEventFields::fiCompTitle), db->getStrValue(cEventFields::fiCategory)); if (!db->find(cEventFields::viVdr)) // perform select to load view fields { printf("Fatal can't lookup event %d\n", id); continue; } db->resetFetch(cEventFields::viVdr); } db->resetFetch(cEventFields::viByChannel); int count; db->countWhere("source = 'epgdata'", count); printf("source 'epgdata' -> %d\n", count); db->countWhere("source = 'vdr'", count); printf("source 'vdr' -> %d\n", count); db->countWhere("", count); printf("all events -> %d\n", count); delete db; return 0; printf("\n"); // --------------------------------- printf("lookup events by comptitle 'TESTTITLE' lview\n"); db->setValue(cEventFields::fiCompTitle, "TESTTITLE"); for (int res = db->find(cEventFields::viByCompTitle); res; res = db->fetch(cEventFields::viByCompTitle)) { if (!db->find()) printf("FATAL!\n"); printf(" -> found (%ld) '%s' by comptitle [%s]\n", db->getIntValue(cEventFields::fiEventId), db->getStrValue(cEventFields::fiTitle), db->getStrValue(cEventFields::fiCompTitle)); } db->resetFetch(cEventFields::viByCompTitle); printf("\n"); printf("lookup event by db-view\n"); db->clear(); db->setValue(cEventFields::fiEventId, 4712); db->setValue(cEventFields::fiChannelId, "11"); if (db->find(cEventFields::viVdr)) { if (!db->find()) printf("FATAL!\n"); int id = db->getIntValue(cEventFields::fiEventId); printf(" -> found event '%s'(%d) [%s] '%s'\n", db->getStrValue(cEventFields::fiTitle), id, db->getStrValue(cEventFields::fiCompTitle), db->getStrValue(cEventFields::fiShortText) ); printf(" -> [%s]\n", db->getStrValue(cEventFields::fiDescription)); } db->resetFetch(cEventFields::viVdr); delete db; return 0; printf("----------------------------------\n"); // delete db; // ------------------------------------------------ // Test Image Table ... printf("\n----------------------------------\n"); Table* imgDb = new Table(connection, "images", cImageFields::fields, cImageFields::views); if (imgDb->open() != success) { printf("Opening database 'images' failed\n"); delete imgDb; return 1; } imgDb->setValue(cImageFields::fiEventId, 4711); imgDb->setValue(cImageFields::fiLfn, 0); imgDb->setValue(cImageFields::fiName, "ok 1"); imgDb->store(); imgDb->setValue(cImageFields::fiEventId, 4711); imgDb->setValue(cImageFields::fiLfn, 1); imgDb->setValue(cImageFields::fiName, "fail"); imgDb->store(); imgDb->setValue(cImageFields::fiEventId, 4713); imgDb->setValue(cImageFields::fiLfn, 0); imgDb->setValue(cImageFields::fiName, "ok 2"); imgDb->store(); // fetch via view imgDb->clear(); imgDb->setValue(cImageFields::fiLfn, 1); for (res = imgDb->find(cImageFields::viAllLessLfn); res; res = imgDb->fetch(cImageFields::viAllLessLfn)) { int id = imgDb->getIntValue(cImageFields::fiEventId); printf(" -> found image (%d) via view, name is '%s', lfn is (%ld)\n", id, imgDb->getStrValue(cImageFields::fiName), imgDb->getIntValue(cImageFields::fiLfn)); } imgDb->resetFetch(cImageFields::viAllLessLfn); printf("----------------------------------\n"); delete imgDb; // ------------------------------------------------ return 0; // ------------------------------------------------ // Test File Table ... Table* fileDb = new Table(connection, "fileref", cFileRef::fields); fileDb->open(); fileDb->setValue(cEventFields::fiName, "test"); if (fileDb->find()) printf("found with tag %s\n", fileDb->getStrValue(cFileRef::fiTag)); else printf("NOT found\n"); fileDb->setValue(cFileRef::fiTag, "1234"); fileDb->setValue(cFileRef::fiFileRef, "test-1234"); fileDb->store(); delete fileDb; // ------------------------------------------------ return 0; // ------------------------------------------------ // Test XML parsing xmlDocPtr xml = 0; xml = xmlParseFile("test.xml"); if (!xml) { printf("Failed to parse test.xml\n"); return 1; } xmlNodePtr xmlRoot = xmlDocGetRootElement(xml); for (xmlNodePtr node = xmlRoot->xmlChildrenNode; node; node = node->next) { cDbRow* evt = 0; char* prop = 0; tEventID id; // skip all unexpected elements if (node->type != XML_ELEMENT_NODE || strcmp((char*)node->name, "event") != 0) continue; // get/check id if (!(prop = (char*)xmlGetProp(node, (xmlChar*)"id")) || !*prop || !(id = atoi(prop))) { xmlFree(prop); printf("Missing event id, ignoring!\n"); continue; } xmlFree(prop); // create event evt = new cDbRow(cEventFields::fields); evt->setValue(cEventFields::fiEventId, id); evt->setValue(cEventFields::fiSource, "epgdata"); printf("event %ld\n", evt->getIntValue(cEventFields::fiEventId)); if (parseEvent(evt, node) != success) delete evt; } xmlFreeDoc(xml); return 0; }