From 58f686487cf5f14d5da5357c67f2e6624dbde027 Mon Sep 17 00:00:00 2001 From: Art Cancro Date: Sat, 25 Feb 2017 20:52:05 -0500 Subject: [PATCH] Move back to single threaded structure for rss feed puller --- citadel/include/ctdl_module.h | 1 + citadel/modules/expire/serv_expire.c | 20 +- citadel/modules/rssclient/rss_atom_parser.c | 107 +- citadel/modules/rssclient/serv_rssclient.c | 1009 ++----------------- 4 files changed, 158 insertions(+), 979 deletions(-) diff --git a/citadel/include/ctdl_module.h b/citadel/include/ctdl_module.h index ccd01c831..5fae2e0c8 100644 --- a/citadel/include/ctdl_module.h +++ b/citadel/include/ctdl_module.h @@ -247,6 +247,7 @@ void CtdlPutRoomLock(struct ctdlroom *qrbuf); typedef void (*ForEachRoomCallBack)(struct ctdlroom *EachRoom, void *out_data); void CtdlForEachRoom(ForEachRoomCallBack CB, void *in_data); typedef void (*ForEachRoomNetCfgCallBack)(struct ctdlroom *EachRoom, void *out_data, OneRoomNetCfg *OneRNCFG); +char *LoadRoomNetConfigFile(long roomnum); void CtdlForEachNetCfgRoom(ForEachRoomNetCfgCallBack CB, void *in_data); void SaveChangedConfigs(void); void CtdlDeleteRoom(struct ctdlroom *qrbuf); diff --git a/citadel/modules/expire/serv_expire.c b/citadel/modules/expire/serv_expire.c index 76bd626fb..94999b9d7 100644 --- a/citadel/modules/expire/serv_expire.c +++ b/citadel/modules/expire/serv_expire.c @@ -704,24 +704,24 @@ int PurgeUseTable(StrBuf *ErrMsg) { syslog(LOG_DEBUG, "Purge use table: phase 1"); cdb_rewind(CDB_USETABLE); - while(cdbut = cdb_next_item(CDB_USETABLE), cdbut != NULL) { - - /* - * TODODRW: change this to create a new function time_t cdb_get_timestamp( struct cdbdata *) - * this will release this file from the serv_network.h - * Maybe it could be a macro that extracts and casts the reult - */ + while(cdbut = cdb_next_item(CDB_USETABLE), cdbut != NULL) + { if (cdbut->len > sizeof(struct UseTable)) memcpy(&ut, cdbut->ptr, sizeof(struct UseTable)); - else { + else + { memset(&ut, 0, sizeof(struct UseTable)); memcpy(&ut, cdbut->ptr, cdbut->len); } cdb_free(cdbut); - if ( (time(NULL) - ut.ut_timestamp) > USETABLE_RETAIN ) { + syslog(LOG_DEBUG, "UT: [%s] at %s", ut.ut_msgid, asctime(localtime(&ut.ut_timestamp))); // FIXME take this out ajc + + if ( (time(NULL) - ut.ut_timestamp) > USETABLE_RETAIN ) + { uptr = (struct UPurgeList *) malloc(sizeof(struct UPurgeList)); - if (uptr != NULL) { + if (uptr != NULL) + { uptr->next = ul; safestrncpy(uptr->up_key, ut.ut_msgid, sizeof uptr->up_key); ul = uptr; diff --git a/citadel/modules/rssclient/rss_atom_parser.c b/citadel/modules/rssclient/rss_atom_parser.c index fdba27577..7bdb94baf 100644 --- a/citadel/modules/rssclient/rss_atom_parser.c +++ b/citadel/modules/rssclient/rss_atom_parser.c @@ -58,26 +58,6 @@ int RSSAtomParserDebugEnabled = 0; #define N ((rss_aggregator*)IO->Data)->Cfg.QRnumber -#define DBGLOG(LEVEL) if ((LEVEL != LOG_DEBUG) || (RSSAtomParserDebugEnabled != 0)) - -#define EVRSSATOM_syslog(LEVEL, FORMAT, ...) \ - DBGLOG(LEVEL) syslog(LEVEL, \ - "%s[%ld]CC[%d][%ld]RSSP" FORMAT, \ - IOSTR, IO->ID, CCID, N, __VA_ARGS__) - -#define EVRSSATOMM_syslog(LEVEL, FORMAT) \ - DBGLOG(LEVEL) syslog(LEVEL, \ - "%s[%ld]CC[%d][%ld]RSSP" FORMAT, \ - IOSTR, IO->ID, CCID, N) - -#define EVRSSATOMCS_syslog(LEVEL, FORMAT, ...) \ - DBGLOG(LEVEL) syslog(LEVEL, "%s[%ld][%ld]RSSP" FORMAT, \ - IOSTR, IO->ID, N, __VA_ARGS__) - -#define EVRSSATOMSM_syslog(LEVEL, FORMAT) \ - DBGLOG(LEVEL) syslog(LEVEL, "%s[%ld][%ld]RSSP" FORMAT, \ - IOSTR, IO->ID, N) - /* * Convert an RDF/RSS datestamp into a time_t */ @@ -146,8 +126,7 @@ void RSS_item_rss_start (StrBuf *CData, rss_aggregator *RSSAggr, const char** Attr) { - AsyncIO *IO = &RSSAggr->IO; - EVRSSATOMM_syslog(LOG_DEBUG, "RSS: This is an RSS feed.\n"); + syslog(LOG_DEBUG, "RSS: This is an RSS feed."); RSSAggr->ItemType = RSS_RSS; } @@ -156,8 +135,7 @@ void RSS_item_rdf_start(StrBuf *CData, rss_aggregator *RSSAggr, const char** Attr) { - AsyncIO *IO = &RSSAggr->IO; - EVRSSATOMM_syslog(LOG_DEBUG, "RSS: This is an RDF feed.\n"); + syslog(LOG_DEBUG, "RSS: This is an RDF feed."); RSSAggr->ItemType = RSS_RSS; } @@ -166,8 +144,7 @@ void ATOM_item_feed_start(StrBuf *CData, rss_aggregator *RSSAggr, const char** Attr) { - AsyncIO *IO = &RSSAggr->IO; - EVRSSATOMM_syslog(LOG_DEBUG, "RSS: This is an ATOM feed.\n"); + syslog(LOG_DEBUG, "RSS: This is an ATOM feed."); RSSAggr->ItemType = RSS_ATOM; } @@ -536,8 +513,7 @@ void RSS_item_rss_end(StrBuf *CData, rss_aggregator *RSSAggr, const char** Attr) { - AsyncIO *IO = &RSSAggr->IO; - EVRSSATOMM_syslog(LOG_DEBUG, "End of feed detected. Closing parser.\n"); + syslog(LOG_DEBUG, "End of feed detected. Closing parser."); ri->done_parsing = 1; } @@ -546,8 +522,7 @@ void RSS_item_rdf_end(StrBuf *CData, rss_aggregator *RSSAggr, const char** Attr) { - AsyncIO *IO = &RSSAggr->IO; - EVRSSATOMM_syslog(LOG_DEBUG, "End of feed detected. Closing parser.\n"); + syslog(LOG_DEBUG, "End of feed detected. Closing parser."); ri->done_parsing = 1; } @@ -624,7 +599,6 @@ void rss_remember_item(rss_item *ri, rss_aggregator *RSSAggr) struct MD5Context md5context; u_char rawdigest[MD5_DIGEST_LEN]; StrBuf *guid; - AsyncIO *IO = &RSSAggr->IO; int n; SaveMsg = (networker_save_message *) malloc(sizeof(networker_save_message)); @@ -654,7 +628,7 @@ void rss_remember_item(rss_item *ri, rss_aggregator *RSSAggr) } /* translate Item into message. */ - EVRSSATOMM_syslog(LOG_DEBUG, "RSS: translating item...\n"); + syslog(LOG_DEBUG, "RSS: translating item..."); if (ri->description == NULL) ri->description = NewStrBufPlain(HKEY("")); StrBufSpaceToBlank(ri->description); SaveMsg->Msg.cm_magic = CTDLMESSAGE_MAGIC; @@ -715,7 +689,6 @@ void rss_xml_start(void *data, const char *supplied_el, const char **attr) { rss_xml_handler *h; rss_aggregator *RSSAggr = (rss_aggregator*) data; - AsyncIO *IO = &RSSAggr->IO; rss_item *ri = RSSAggr->Item; void *pv; const char *pel; @@ -740,10 +713,11 @@ void rss_xml_start(void *data, const char *supplied_el, const char **attr) pel - supplied_el - 1, &v)) { - EVRSSATOM_syslog(LOG_DEBUG, + syslog(LOG_DEBUG, "RSS: START ignoring " - "because of wrong namespace [%s]\n", - supplied_el); + "because of wrong namespace [%s]", + supplied_el + ); return; } } @@ -773,23 +747,24 @@ void rss_xml_start(void *data, const char *supplied_el, const char **attr) attr); } else - EVRSSATOM_syslog(LOG_DEBUG, - "RSS: START unhandled: [%s] [%s]...\n", + syslog(LOG_DEBUG, + "RSS: START unhandled: [%s] [%s]...", pel, - supplied_el); + supplied_el + ); } else - EVRSSATOM_syslog(LOG_DEBUG, - "RSS: START unhandled: [%s] [%s]...\n", + syslog(LOG_DEBUG, + "RSS: START unhandled: [%s] [%s]...", pel, - supplied_el); + supplied_el + ); } void rss_xml_end(void *data, const char *supplied_el) { rss_xml_handler *h; rss_aggregator *RSSAggr = (rss_aggregator*) data; - AsyncIO *IO = &RSSAggr->IO; rss_item *ri = RSSAggr->Item; const char *pel; char *sep = NULL; @@ -800,7 +775,7 @@ void rss_xml_end(void *data, const char *supplied_el) while (sep = strchr(pel, ':'), sep) { pel = sep + 1; } - EVRSSATOM_syslog(LOG_DEBUG, "RSS: END %s...\n", supplied_el); + syslog(LOG_DEBUG, "RSS: END %s...", supplied_el); if (pel != supplied_el) { void *v; @@ -810,9 +785,9 @@ void rss_xml_end(void *data, const char *supplied_el) pel - supplied_el - 1, &v)) { - EVRSSATOM_syslog(LOG_DEBUG, + syslog(LOG_DEBUG, "RSS: END ignoring because of wrong namespace" - "[%s] = [%s]\n", + "[%s] = [%s]", supplied_el, ChrPtr(RSSAggr->CData)); FlushStrBuf(RSSAggr->CData); @@ -842,15 +817,15 @@ void rss_xml_end(void *data, const char *supplied_el) h->Handler(RSSAggr->CData, ri, RSSAggr, NULL); } else - EVRSSATOM_syslog(LOG_DEBUG, - "RSS: END unhandled: [%s] [%s] = [%s]...\n", + syslog(LOG_DEBUG, + "RSS: END unhandled: [%s] [%s] = [%s]...", pel, supplied_el, ChrPtr(RSSAggr->CData)); } else - EVRSSATOM_syslog(LOG_DEBUG, - "RSS: END unhandled: [%s] [%s] = [%s]...\n", + syslog(LOG_DEBUG, + "RSS: END unhandled: [%s] [%s] = [%s]...", pel, supplied_el, ChrPtr(RSSAggr->CData)); @@ -859,18 +834,6 @@ void rss_xml_end(void *data, const char *supplied_el) -/* - * Callback function for passing libcurl's output to expat for parsing - * we don't do streamed parsing so expat can handle non-utf8 documents -size_t rss_libcurl_callback(void *ptr, size_t size, size_t nmemb, void *stream) -{ - XML_Parse((XML_Parser)stream, ptr, (size * nmemb), 0); - return (size*nmemb); -} - */ - - - eNextState RSSAggregator_ParseReply(AsyncIO *IO) { StrBuf *Buf; @@ -905,11 +868,11 @@ eNextState RSSAggregator_ParseReply(AsyncIO *IO) else ptr = "UTF-8"; - EVRSSATOM_syslog(LOG_DEBUG, "RSS: Now parsing [%s] \n", ChrPtr(RSSAggr->Url)); + syslog(LOG_DEBUG, "RSS: Now parsing [%s]", ChrPtr(RSSAggr->Url)); RSSAggr->xp = XML_ParserCreateNS(ptr, ':'); if (!RSSAggr->xp) { - EVRSSATOMM_syslog(LOG_ALERT, "Cannot create XML parser!\n"); + syslog(LOG_ALERT, "Cannot create XML parser!"); return eAbort; } FlushStrBuf(RSSAggr->Key); @@ -920,19 +883,18 @@ eNextState RSSAggregator_ParseReply(AsyncIO *IO) XML_SetUserData(RSSAggr->xp, RSSAggr); XML_SetCdataSectionHandler(RSSAggr->xp, rss_xml_cdata_start, - rss_xml_cdata_end); - + rss_xml_cdata_end + ); len = StrLength(IO->HttpReq.ReplyData); ptr = SmashStrBuf(&IO->HttpReq.ReplyData); XML_Parse(RSSAggr->xp, ptr, len, 0); free (ptr); - if (ri->done_parsing == 0) + if (ri->done_parsing == 0) { XML_Parse(RSSAggr->xp, "", 0, 1); + } - - EVRSSATOM_syslog(LOG_DEBUG, "RSS: XML Status [%s] \n", - XML_ErrorString(XML_GetErrorCode(RSSAggr->xp))); + syslog(LOG_DEBUG, "RSS: XML Status [%s]", XML_ErrorString(XML_GetErrorCode(RSSAggr->xp))); XML_ParserFree(RSSAggr->xp); flush_rss_item(ri); @@ -944,6 +906,8 @@ eNextState RSSAggregator_ParseReply(AsyncIO *IO) RSSAggr->Pos = GetNewHashPos(RSSAggr->Messages, 1); +#if 0 +// FIXME ajc if (GetNextHashPos(RSSAggr->Messages, RSSAggr->Pos, &len, @@ -952,8 +916,11 @@ eNextState RSSAggregator_ParseReply(AsyncIO *IO) return NextDBOperation(IO, RSS_FetchNetworkUsetableEntry); } else { +#endif return eAbort; +#if 0 } +#endif } diff --git a/citadel/modules/rssclient/serv_rssclient.c b/citadel/modules/rssclient/serv_rssclient.c index b9742266b..909587d62 100644 --- a/citadel/modules/rssclient/serv_rssclient.c +++ b/citadel/modules/rssclient/serv_rssclient.c @@ -1,7 +1,7 @@ /* * Bring external RSS feeds into rooms. * - * Copyright (c) 2007-2016 by the citadel.org team + * Copyright (c) 2007-2017 by the citadel.org team * * This program is open source software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3. @@ -48,822 +48,169 @@ #include "citadel_dirs.h" #include "md5.h" #include "context.h" -#include "event_client.h" #include "rss_atom_parser.h" - -#define TMP_MSGDATA 0xFF -#define TMP_SHORTER_URL_OFFSET 0xFE -#define TMP_SHORTER_URLS 0xFD - -time_t last_run = 0L; - -pthread_mutex_t RSSQueueMutex; /* locks the access to the following vars: */ -HashList *RSSQueueRooms = NULL; /* rss_room_counter */ -HashList *RSSFetchUrls = NULL; /*->rss_aggregator;->RefCount access locked*/ - -eNextState RSSAggregator_Terminate(AsyncIO *IO); -eNextState RSSAggregator_TerminateDB(AsyncIO *IO); -eNextState RSSAggregator_ShutdownAbort(AsyncIO *IO); -struct CitContext rss_CC; - -struct rssnetcfg *rnclist = NULL; -int RSSClientDebugEnabled = 0; -#define N ((rss_aggregator*)IO->Data)->Cfg.QRnumber - -#define DBGLOG(LEVEL) if ((LEVEL != LOG_DEBUG) || (RSSClientDebugEnabled != 0)) - -#define EVRSSC_syslog(LEVEL, FORMAT, ...) \ - DBGLOG(LEVEL) syslog(LEVEL, \ - "%s[%ld]CC[%d][%ld]RSS" FORMAT, \ - IOSTR, IO->ID, CCID, N, __VA_ARGS__) - -#define EVRSSCM_syslog(LEVEL, FORMAT) \ - DBGLOG(LEVEL) syslog(LEVEL, \ - "%s[%ld]CC[%d][%ld]RSS" FORMAT, \ - IOSTR, IO->ID, CCID, N) - -#define EVRSSQ_syslog(LEVEL, FORMAT, ...) \ - DBGLOG(LEVEL) syslog(LEVEL, "RSS" FORMAT, \ - __VA_ARGS__) -#define EVRSSQM_syslog(LEVEL, FORMAT) \ - DBGLOG(LEVEL) syslog(LEVEL, "RSS" FORMAT) - -#define EVRSSCSM_syslog(LEVEL, FORMAT) \ - DBGLOG(LEVEL) syslog(LEVEL, "%s[%ld][%ld]RSS" FORMAT, \ - IOSTR, IO->ID, N) - -typedef enum _RSSState { - eRSSCreated, - eRSSFetching, - eRSSFailure, - eRSSParsing, - eRSSUT -} RSSState; -ConstStr RSSStates[] = { - {HKEY("Aggregator created")}, - {HKEY("Fetching content")}, - {HKEY("Failed")}, - {HKEY("parsing content")}, - {HKEY("checking usetable")} +struct rssroom { + struct rssroom *next; + char *room; }; - -static size_t GetLocationString( void *ptr, size_t size, size_t nmemb, void *userdata) -{ -#define LOCATION "location" - if (strncasecmp((char*)ptr, LOCATION, sizeof(LOCATION) - 1) == 0) - { - AsyncIO *IO = (AsyncIO *) userdata; - rss_aggregator *RSSAggr = (rss_aggregator *)IO->Data; - - char *pch = (char*) ptr; - char *pche; - - pche = pch + (size * nmemb); - pch += sizeof(LOCATION); - - while (isspace(*pch) || (*pch == ':')) - pch ++; - - while (isspace(*pche) || (*pche == '\0')) - pche--; - if (RSSAggr->RedirectUrl == NULL) { - RSSAggr->RedirectUrl = NewStrBufPlain(pch, pche - pch + 1); - } - else { - FlushStrBuf(RSSAggr->RedirectUrl); - StrBufPlain(RSSAggr->RedirectUrl, pch, pche - pch + 1); - } - } - return size * nmemb; -} +struct rssurl { + struct rssurl *next; + char *url; + struct rssroom *rooms; +}; -static void SetRSSState(AsyncIO *IO, RSSState State) -{ - CitContext* CCC = IO->CitContext; - if (CCC != NULL) { - memcpy(CCC->cs_clientname, RSSStates[State].Key, RSSStates[State].len + 1); - } -} +time_t last_run = 0L; +struct CitContext rss_CC; +struct rssurl *rsstodo = NULL; -void DeleteRoomReference(long QRnumber) +// Add a feed/room pair into the todo list +// +void rssclient_push_todo(char *rssurl, char *roomname) { - HashPos *At; - long HKLen; - const char *HK; - void *vData = NULL; - rss_room_counter *pRoomC; - - At = GetNewHashPos(RSSQueueRooms, 0); - - if (GetHashPosFromKey(RSSQueueRooms, LKEY(QRnumber), At)) - { - GetHashPos(RSSQueueRooms, At, &HKLen, &HK, &vData); - if (vData != NULL) - { - pRoomC = (rss_room_counter *) vData; - pRoomC->count --; - if (pRoomC->count == 0) - DeleteEntryFromHash(RSSQueueRooms, At); - } - } - DeleteHashPos(&At); -} + struct rssurl *r = NULL; + struct rssurl *thisone = NULL; + struct rssroom *newroom = NULL; -void UnlinkRooms(rss_aggregator *RSSAggr) -{ - DeleteRoomReference(RSSAggr->Cfg.QRnumber); - if (RSSAggr->OtherQRnumbers != NULL) - { - long HKLen; - const char *HK; - HashPos *At; - void *vData; + syslog(LOG_DEBUG, "rssclient_push_todo(%s, %s)", rssurl, roomname); - At = GetNewHashPos(RSSAggr->OtherQRnumbers, 0); - while (! server_shutting_down && - GetNextHashPos(RSSAggr->OtherQRnumbers, - At, - &HKLen, &HK, - &vData) && - (vData != NULL)) - { - pRSSConfig *Data = (pRSSConfig*) vData; - DeleteRoomReference(Data->QRnumber); + for (r=rsstodo; r!=NULL; r=r->next) { + if (!strcasecmp(r->url, rssurl)) { + thisone = r; } - - DeleteHashPos(&At); } -} - -void UnlinkRSSAggregator(rss_aggregator *RSSAggr) -{ - HashPos *At; - - pthread_mutex_lock(&RSSQueueMutex); - UnlinkRooms(RSSAggr); - - At = GetNewHashPos(RSSFetchUrls, 0); - if (GetHashPosFromKey(RSSFetchUrls, SKEY(RSSAggr->Url), At)) - { - DeleteEntryFromHash(RSSFetchUrls, At); + if (thisone == NULL) { + thisone = malloc(sizeof(struct rssurl)); + thisone->url = strdup(rssurl); + thisone->rooms = NULL; + thisone->next = rsstodo; + rsstodo = thisone; } - DeleteHashPos(&At); - last_run = time(NULL); - pthread_mutex_unlock(&RSSQueueMutex); -} - -void DeleteRssCfg(void *vptr) -{ - rss_aggregator *RSSAggr = (rss_aggregator *)vptr; - AsyncIO *IO = &RSSAggr->IO; - - if (IO->CitContext != NULL) { - EVRSSCM_syslog(LOG_DEBUG, "RSS: destroying"); - } - - FreeStrBuf(&RSSAggr->Url); - FreeStrBuf(&RSSAggr->RedirectUrl); - FreeStrBuf(&RSSAggr->rooms); - FreeStrBuf(&RSSAggr->CData); - FreeStrBuf(&RSSAggr->Key); - DeleteHash(&RSSAggr->OtherQRnumbers); - - DeleteHashPos (&RSSAggr->Pos); - DeleteHash (&RSSAggr->Messages); - if (RSSAggr->recp.recp_room != NULL) - free(RSSAggr->recp.recp_room); - - - if (RSSAggr->Item != NULL) - { - flush_rss_item(RSSAggr->Item); - - free(RSSAggr->Item); - } - - FreeAsyncIOContents(&RSSAggr->IO); - memset(RSSAggr, 0, sizeof(rss_aggregator)); - free(RSSAggr); -} - -eNextState RSSAggregator_Terminate(AsyncIO *IO) -{ - rss_aggregator *RSSAggr = (rss_aggregator *)IO->Data; - - EVRSSCM_syslog(LOG_DEBUG, "RSS: Terminating."); - - StopCurlWatchers(IO); - UnlinkRSSAggregator(RSSAggr); - return eAbort; -} - -eNextState RSSAggregator_TerminateDB(AsyncIO *IO) -{ - rss_aggregator *RSSAggr = (rss_aggregator *)IO->Data; - - EVRSSCM_syslog(LOG_DEBUG, "RSS: Terminating."); - - StopDBWatchers(&RSSAggr->IO); - UnlinkRSSAggregator(RSSAggr); - return eAbort; + newroom = malloc(sizeof(struct rssroom)); + newroom->room = strdup(roomname); + newroom->next = thisone->rooms; + thisone->rooms = newroom; } -eNextState RSSAggregator_ShutdownAbort(AsyncIO *IO) -{ - const char *pUrl; - rss_aggregator *RSSAggr = (rss_aggregator *)IO->Data; - - pUrl = IO->ConnectMe->PlainUrl; - if (pUrl == NULL) - pUrl = ""; - - EVRSSC_syslog(LOG_DEBUG, "RSS: Aborting by shutdown: %s.", pUrl); - StopCurlWatchers(IO); - UnlinkRSSAggregator(RSSAggr); - return eAbort; -} - -void AppendLink(StrBuf *Message, - StrBuf *link, - StrBuf *LinkTitle, - const char *Title) +// Callback function for curl +// +size_t rss_pof_write_data(void *buffer, size_t size, size_t nmemb, void *userp) { - if (StrLength(link) > 0) - { - StrBufAppendBufPlain(Message, HKEY(""), 0); - if (StrLength(LinkTitle) > 0) - StrBufAppendBuf(Message, LinkTitle, 0); - else if ((Title != NULL) && !IsEmptyStr(Title)) - StrBufAppendBufPlain(Message, Title, -1, 0); - else - StrBufAppendBuf(Message, link, 0); - StrBufAppendBufPlain(Message, HKEY("
\n"), 0); - } + StrBuf *Downloaded = (StrBuf *)userp; + size_t bytes = size * nmemb; + StrBufAppendBufPlain(Downloaded, buffer, bytes, 0); + return(bytes); } -int rss_format_item(AsyncIO *IO, networker_save_message *SaveMsg) +// pull one feed (possibly multiple rooms) +// +void rss_pull_one_feed(struct rssurl *url) { - StrBuf *Message; - int msglen = 0; - - if (StrLength(SaveMsg->description) + - StrLength(SaveMsg->link) + - StrLength(SaveMsg->linkTitle) + - StrLength(SaveMsg->reLink) + - StrLength(SaveMsg->reLinkTitle) + - StrLength(SaveMsg->title) == 0) - { - EVRSSCM_syslog(LOG_INFO, "Refusing to save empty message."); - return 0; - } - - CM_Flush(&SaveMsg->Msg); + struct rssroom *r; + CURL *curl; + CURLcode res; + StrBuf *Downloaded = NULL; - if (SaveMsg->author_or_creator != NULL) { + syslog(LOG_DEBUG, "rss_pull_one_feed(%s)", url->url); - char *From; - StrBuf *Encoded = NULL; - int FromAt; - - From = html_to_ascii(ChrPtr(SaveMsg->author_or_creator), - StrLength(SaveMsg->author_or_creator), - 512, 0); - StrBufPlain(SaveMsg->author_or_creator, From, -1); - StrBufTrim(SaveMsg->author_or_creator); - free(From); - - FromAt = strchr(ChrPtr(SaveMsg->author_or_creator), '@') != NULL; - if (!FromAt && StrLength (SaveMsg->author_email) > 0) - { - StrBufRFC2047encode(&Encoded, SaveMsg->author_or_creator); - CM_SetAsFieldSB(&SaveMsg->Msg, eAuthor, &Encoded); - CM_SetAsFieldSB(&SaveMsg->Msg, eMessagePath, &SaveMsg->author_email); - } - else - { - if (FromAt) - { - CM_SetAsFieldSB(&SaveMsg->Msg, eAuthor, &SaveMsg->author_or_creator); - CM_CopyField(&SaveMsg->Msg, eMessagePath, eAuthor); - } - else - { - StrBufRFC2047encode(&Encoded, - SaveMsg->author_or_creator); - CM_SetAsFieldSB(&SaveMsg->Msg, eAuthor, &Encoded); - CM_SetField(&SaveMsg->Msg, eMessagePath, HKEY("rss@localhost")); - - } - } - } - else { - CM_SetField(&SaveMsg->Msg, eAuthor, HKEY("rss")); + curl = curl_easy_init(); + if (!curl) { + return; } - CM_SetField(&SaveMsg->Msg, eNodeName, CtdlGetConfigStr("c_nodename"), strlen(CtdlGetConfigStr("c_nodename"))); - if (SaveMsg->title != NULL) { - long len; - char *Sbj; - StrBuf *Encoded, *QPEncoded; - - QPEncoded = NULL; - StrBufSpaceToBlank(SaveMsg->title); - len = StrLength(SaveMsg->title); - Sbj = html_to_ascii(ChrPtr(SaveMsg->title), len, 512, 0); - if (!IsEmptyStr(Sbj)) { - len = strlen(Sbj); - if ((Sbj[len - 1] == '\n')) - { - len --; - Sbj[len] = '\0'; - } - Encoded = NewStrBufPlain(Sbj, len); - + Downloaded = NewStrBuf(); - StrBufTrim(Encoded); - StrBufRFC2047encode(&QPEncoded, Encoded); - - CM_SetAsFieldSB(&SaveMsg->Msg, eMsgSubject, &QPEncoded); - FreeStrBuf(&Encoded); - } - if (Sbj != NULL) { - free(Sbj); - } + curl_easy_setopt(curl, CURLOPT_URL, url->url); + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); // Follow redirects + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, rss_pof_write_data); // What to do with downloaded data + curl_easy_setopt(curl, CURLOPT_WRITEDATA, Downloaded); // Give it our StrBuf to work with + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 20L); // Time out after 20 seconds + res = curl_easy_perform(curl); // Perform the request + if (res != CURLE_OK) { + syslog(LOG_WARNING, "Failed to load feed: %s", curl_easy_strerror(res)); } - if (SaveMsg->link == NULL) - SaveMsg->link = NewStrBufPlain(HKEY("")); - -#if 0 /* temporarily disable shorter urls. */ - SaveMsg->Msg.cm_fields[TMP_SHORTER_URLS] = - GetShorterUrls(SaveMsg->description); -#endif + curl_easy_cleanup(curl); - msglen += 1024 + StrLength(SaveMsg->link) + StrLength(SaveMsg->description) ; + // FIXME parse the feed, dummeh ... it's in ChrPtr(Downloaded) - Message = NewStrBufPlain(NULL, msglen); - - StrBufPlain(Message, HKEY( - "Content-type: text/html; charset=\"UTF-8\"\r\n\r\n" - "\n")); -#if 0 /* disable shorter url for now. */ - SaveMsg->Msg.cm_fields[TMP_SHORTER_URL_OFFSET] = StrLength(Message); -#endif - StrBufAppendBuf(Message, SaveMsg->description, 0); - StrBufAppendBufPlain(Message, HKEY("

\n"), 0); - - AppendLink(Message, SaveMsg->link, SaveMsg->linkTitle, NULL); - AppendLink(Message, SaveMsg->reLink, SaveMsg->reLinkTitle, "Reply to this"); - StrBufAppendBufPlain(Message, HKEY("\n"), 0); - - SaveMsg->Message = Message; - return 1; -} - -eNextState RSSSaveMessage(AsyncIO *IO) -{ - long len; - const char *Key; - rss_aggregator *RSSAggr = (rss_aggregator *) IO->Data; - - if (rss_format_item(IO, RSSAggr->ThisMsg)) - { - CM_SetAsFieldSB(&RSSAggr->ThisMsg->Msg, eMesageText, &RSSAggr->ThisMsg->Message); - CtdlSubmitMsg(&RSSAggr->ThisMsg->Msg, &RSSAggr->recp, NULL, 0); - - /* write the uidl to the use table so we don't store this item again */ - CheckIfAlreadySeen("RSS Item Insert", RSSAggr->ThisMsg->MsgGUID, EvGetNow(IO), 0, eWrite, CCID, IO->ID); + for (r=url->rooms; r!=NULL; r=r->next) { + syslog(LOG_DEBUG, "Saving item to %s", r->room); + // FIXME save to rooms } - if (GetNextHashPos(RSSAggr->Messages, - RSSAggr->Pos, - &len, &Key, - (void**) &RSSAggr->ThisMsg)) - return NextDBOperation(IO, RSS_FetchNetworkUsetableEntry); - else - return eAbort; + FreeStrBuf(&Downloaded); } -eNextState RSS_FetchNetworkUsetableEntry(AsyncIO *IO) -{ - static const time_t antiExpire = USETABLE_ANTIEXPIRE_HIRES; -#ifndef DEBUG_RSS - time_t seenstamp = 0; - const char *Key; - long len; - rss_aggregator *Ctx = (rss_aggregator *) IO->Data; - - /* Find out if we've already seen this item */ -// todo: expiry? - SetRSSState(IO, eRSSUT); - seenstamp = CheckIfAlreadySeen("RSS Item Seen", - Ctx->ThisMsg->MsgGUID, - EvGetNow(IO), - antiExpire, - eCheckUpdate, - CCID, IO->ID); - if (seenstamp != 0) - { - /* Item has already been seen */ - EVRSSC_syslog(LOG_DEBUG, - "%s has already been seen - %ld < %ld", - ChrPtr(Ctx->ThisMsg->MsgGUID), - seenstamp, antiExpire); - - SetRSSState(IO, eRSSParsing); - if (GetNextHashPos(Ctx->Messages, - Ctx->Pos, - &len, &Key, - (void**) &Ctx->ThisMsg)) - return NextDBOperation( - IO, - RSS_FetchNetworkUsetableEntry); - else - return eAbort; - } - else -#endif - { - /* Item has already been seen */ - EVRSSC_syslog(LOG_DEBUG, - "%s Parsing - %ld >= %ld", - ChrPtr(Ctx->ThisMsg->MsgGUID), - seenstamp, antiExpire); - SetRSSState(IO, eRSSParsing); - - NextDBOperation(IO, RSSSaveMessage); - return eSendMore; - } - return eSendMore; -} - -void UpdateLastKnownGood(pRSSConfig *pCfg, time_t now) +// We have a list, now download the feeds +// +void rss_pull_feeds(void) { - OneRoomNetCfg *pRNCfg; - begin_critical_section(S_NETCONFIGS); - pRNCfg = CtdlGetNetCfgForRoom(pCfg->QRnumber); - if (pRNCfg != NULL) - { - RSSCfgLine *RSSCfg = (RSSCfgLine *)pRNCfg->NetConfigs[rssclient]; - - while (RSSCfg != NULL) - { - if (RSSCfg == pCfg->pCfg) - break; + struct rssurl *r; + struct rssroom *rr; - RSSCfg = RSSCfg->next; - } - if (RSSCfg != NULL) - { - RSSCfg->last_known_good = now; + while (rsstodo != NULL) { + rss_pull_one_feed(rsstodo); + r = rsstodo; + rsstodo = rsstodo->next; + while (r->rooms != NULL) { + rr = r->rooms; + r->rooms = r->rooms->next; + free(rr->room); + free(rr); } + free(r->url); + free(r); } - SaveRoomNetConfigFile(pRNCfg, pCfg->QRnumber); - FreeRoomNetworkStruct(&pRNCfg); - end_critical_section(S_NETCONFIGS); } -eNextState RSSAggregator_AnalyseReply(AsyncIO *IO) -{ - HashPos *it = NULL; - long len; - const char *Key; - pRSSConfig *pCfg; - u_char rawdigest[MD5_DIGEST_LEN]; - struct MD5Context md5context; - StrBuf *guid; - rss_aggregator *Ctx = (rss_aggregator *) IO->Data; - - - if ((IO->HttpReq.httpcode >= 300) && (IO->HttpReq.httpcode < 400) && (Ctx->RedirectUrl != NULL)) - { - StrBuf *ErrMsg; - long lens[2]; - const char *strs[2]; - - SetRSSState(IO, eRSSFailure); - ErrMsg = NewStrBuf(); - if (IO) { - EVRSSC_syslog(LOG_INFO, "need a 200, got a %ld !", - IO->HttpReq.httpcode); - } - strs[0] = ChrPtr(Ctx->Url); - lens[0] = StrLength(Ctx->Url); - strs[1] = ChrPtr(Ctx->rooms); - lens[1] = StrLength(Ctx->rooms); - - if (IO->HttpReq.CurlError == NULL) - IO->HttpReq.CurlError = ""; - - StrBufPrintf(ErrMsg, - "Error while RSS-Aggregation Run of %s\n" - " need a 200, got a %ld !\n" - " Curl Error message: \n%s / %s\n" - " Redirect header points to: %s\n" - " Response text was: \n" - " \n %s\n", - ChrPtr(Ctx->Url), - IO->HttpReq.httpcode, - IO->HttpReq.errdesc, - IO->HttpReq.CurlError, - ChrPtr(Ctx->RedirectUrl), - ChrPtr(IO->HttpReq.ReplyData) - ); - - CtdlAideFPMessage( - ChrPtr(ErrMsg), - "RSS Aggregation run failure", - 2, strs, (long*) &lens, - CCID, - IO->ID, - EvGetNow(IO)); - - FreeStrBuf(&ErrMsg); - EVRSSC_syslog(LOG_DEBUG, - "RSS feed returned an invalid http status code. <%s>", - ChrPtr(Ctx->Url), - IO->HttpReq.httpcode); - return eAbort; - } - else if (IO->HttpReq.httpcode != 200) - { - StrBuf *ErrMsg; - long lens[2]; - const char *strs[2]; - - SetRSSState(IO, eRSSFailure); - ErrMsg = NewStrBuf(); - if (IO) { - EVRSSC_syslog(LOG_ALERT, "need a 200, got a %ld !", - IO->HttpReq.httpcode); - } - strs[0] = ChrPtr(Ctx->Url); - lens[0] = StrLength(Ctx->Url); - - strs[1] = ChrPtr(Ctx->rooms); - lens[1] = StrLength(Ctx->rooms); - - if (IO->HttpReq.CurlError == NULL) - IO->HttpReq.CurlError = ""; - - StrBufPrintf(ErrMsg, - "Error while RSS-Aggregation Run of %s\n" - " need a 200, got a %ld !\n" - " Curl Error message: \n%s / %s\n" - " Response text was: \n" - " \n %s\n", - ChrPtr(Ctx->Url), - IO->HttpReq.httpcode, - IO->HttpReq.errdesc, - IO->HttpReq.CurlError, - ChrPtr(IO->HttpReq.ReplyData) - ); - - CtdlAideFPMessage( - ChrPtr(ErrMsg), - "RSS Aggregation run failure", - 2, strs, (long*) &lens, - CCID, - IO->ID, - EvGetNow(IO)); - - FreeStrBuf(&ErrMsg); - EVRSSC_syslog(LOG_DEBUG, - "RSS feed returned an invalid http status code. <%s>", - ChrPtr(Ctx->Url), - IO->HttpReq.httpcode); - return eAbort; - } - - pCfg = &Ctx->Cfg; - - while (pCfg != NULL) - { - UpdateLastKnownGood (pCfg, EvGetNow(IO)); - if ((Ctx->roomlist_parts > 1) && - (it == NULL)) - { - it = GetNewHashPos(RSSFetchUrls, 0); - } - if (it != NULL) - { - void *vptr; - if (GetNextHashPos(Ctx->OtherQRnumbers, it, &len, &Key, &vptr)) - pCfg = vptr; - else - pCfg = NULL; - } - else - pCfg = NULL; - } - DeleteHashPos (&it); - - SetRSSState(IO, eRSSUT); - - MD5Init(&md5context); - - MD5Update(&md5context, - (const unsigned char*)SKEY(IO->HttpReq.ReplyData)); - - MD5Update(&md5context, - (const unsigned char*)SKEY(Ctx->Url)); - - MD5Final(rawdigest, &md5context); - guid = NewStrBufPlain(NULL, - MD5_DIGEST_LEN * 2 + 12 /* _rss2ctdl*/); - StrBufHexEscAppend(guid, NULL, rawdigest, MD5_DIGEST_LEN); - StrBufAppendBufPlain(guid, HKEY("_rssFM"), 0); - if (StrLength(guid) > 40) - StrBufCutAt(guid, 40, NULL); - /* Find out if we've already seen this item */ - -#ifndef DEBUG_RSS - - if (CheckIfAlreadySeen("RSS Whole", - guid, - EvGetNow(IO), - EvGetNow(IO) - USETABLE_ANTIEXPIRE, - eUpdate, - CCID, IO->ID) - != 0) - { - FreeStrBuf(&guid); - - EVRSSC_syslog(LOG_DEBUG, "RSS feed already seen. <%s>", ChrPtr(Ctx->Url)); - return eAbort; - } - FreeStrBuf(&guid); -#endif - SetRSSState(IO, eRSSParsing); - return RSSAggregator_ParseReply(IO); -} - -eNextState RSSAggregator_FinishHttp(AsyncIO *IO) +// Scan a room's netconfig looking for RSS feed parsing requests +// +void rssclient_scan_room(struct ctdlroom *qrbuf, void *data) { - return CurlQueueDBOperation(IO, RSSAggregator_AnalyseReply); -} - -/* - * Begin a feed parse - */ -int rss_do_fetching(rss_aggregator *RSSAggr) -{ - AsyncIO *IO = &RSSAggr->IO; - rss_item *ri; - time_t now; - CURLcode sta; - CURL *chnd; - - - now = time(NULL); - - if ((RSSAggr->next_poll != 0) && (now < RSSAggr->next_poll)) - return 0; - - ri = (rss_item*) malloc(sizeof(rss_item)); - memset(ri, 0, sizeof(rss_item)); - RSSAggr->Item = ri; - - if (! InitcURLIOStruct(&RSSAggr->IO, - RSSAggr, - "Citadel RSS Client", - RSSAggregator_FinishHttp, - RSSAggregator_Terminate, - RSSAggregator_TerminateDB, - RSSAggregator_ShutdownAbort)) - { - EVRSSCM_syslog(LOG_ALERT, "Unable to initialize libcurl."); - return 0; - } - chnd = IO->HttpReq.chnd; - OPT(HEADERDATA, IO); - OPT(HEADERFUNCTION, GetLocationString); - SetRSSState(IO, eRSSCreated); - - safestrncpy(((CitContext*)RSSAggr->IO.CitContext)->cs_host, - ChrPtr(RSSAggr->Url), - sizeof(((CitContext*)RSSAggr->IO.CitContext)->cs_host)); - - EVRSSC_syslog(LOG_DEBUG, "Fetching RSS feed <%s>", ChrPtr(RSSAggr->Url)); - ParseURL(&RSSAggr->IO.ConnectMe, RSSAggr->Url, 80); - CurlPrepareURL(RSSAggr->IO.ConnectMe); - - SetRSSState(IO, eRSSFetching); - QueueCurlContext(&RSSAggr->IO); - return 1; -} + char *serialized_config = NULL; + int num_configs = 0; + char cfgline[SIZ]; + int i = 0; -/* - * Scan a room's netconfig to determine whether it is requesting any RSS feeds - */ -void rssclient_scan_room(struct ctdlroom *qrbuf, void *data, OneRoomNetCfg *OneRNCFG) -{ - const RSSCfgLine *RSSCfg = (RSSCfgLine *)OneRNCFG->NetConfigs[rssclient]; - rss_aggregator *RSSAggr = NULL; - rss_aggregator *use_this_RSSAggr = NULL; - void *vptr; - - EVRSSQ_syslog(LOG_DEBUG, "rssclient_scan_room(%s)", qrbuf->QRname); - pthread_mutex_lock(&RSSQueueMutex); - if (GetHash(RSSQueueRooms, LKEY(qrbuf->QRnumber), &vptr)) - { - EVRSSQ_syslog(LOG_DEBUG, - "rssclient: [%ld] %s already in progress.", - qrbuf->QRnumber, - qrbuf->QRname); - pthread_mutex_unlock(&RSSQueueMutex); + serialized_config = LoadRoomNetConfigFile(qrbuf->QRnumber); + if (!serialized_config) { return; } - pthread_mutex_unlock(&RSSQueueMutex); - - if (server_shutting_down) return; - - while (RSSCfg != NULL) - { - pthread_mutex_lock(&RSSQueueMutex); - GetHash(RSSFetchUrls, SKEY(RSSCfg->Url), &vptr); - use_this_RSSAggr = (rss_aggregator *)vptr; - if (use_this_RSSAggr != NULL) - { - pRSSConfig *pRSSCfg; - - StrBufAppendBufPlain(use_this_RSSAggr->rooms, qrbuf->QRname, -1, 0); - if (use_this_RSSAggr->roomlist_parts==1) - { - use_this_RSSAggr->OtherQRnumbers - = NewHash(1, lFlathash); + num_configs = num_tokens(serialized_config, '\n'); + for (i=0; iQRnumber = qrbuf->QRnumber; - pRSSCfg->pCfg = RSSCfg; - - Put(use_this_RSSAggr->OtherQRnumbers, - LKEY(qrbuf->QRnumber), - pRSSCfg, - NULL); - use_this_RSSAggr->roomlist_parts++; - - pthread_mutex_unlock(&RSSQueueMutex); - - RSSCfg = RSSCfg->next; - continue; + rssclient_push_todo(cfgline, qrbuf->QRname); } - pthread_mutex_unlock(&RSSQueueMutex); - - RSSAggr = (rss_aggregator *) malloc( - sizeof(rss_aggregator)); - - memset (RSSAggr, 0, sizeof(rss_aggregator)); - RSSAggr->Cfg.QRnumber = qrbuf->QRnumber; - RSSAggr->Cfg.pCfg = RSSCfg; - RSSAggr->roomlist_parts = 1; - RSSAggr->Url = NewStrBufDup(RSSCfg->Url); - - RSSAggr->ItemType = RSS_UNSET; - - RSSAggr->rooms = NewStrBufPlain( - qrbuf->QRname, -1); - - pthread_mutex_lock(&RSSQueueMutex); - - Put(RSSFetchUrls, - SKEY(RSSAggr->Url), - RSSAggr, - DeleteRssCfg); - - pthread_mutex_unlock(&RSSQueueMutex); - RSSCfg = RSSCfg->next; } + + free(serialized_config); } + /* * Scan for rooms that have RSS client requests configured */ void rssclient_scan(void) { - int RSSRoomCount, RSSCount; - rss_aggregator *rptr = NULL; - void *vrptr = NULL; - HashPos *it; - long len; - const char *Key; time_t now = time(NULL); /* Run no more than once every 15 minutes. */ if ((now - last_run) < 900) { - EVRSSQ_syslog(LOG_DEBUG, + syslog(LOG_DEBUG, "Client: polling interval not yet reached; last run was %ldm%lds ago", ((now - last_run) / 60), ((now - last_run) % 60) @@ -871,159 +218,22 @@ void rssclient_scan(void) { return; } - /* - * This is a simple concurrency check to make sure only one rssclient - * run is done at a time. - */ - pthread_mutex_lock(&RSSQueueMutex); - RSSCount = GetCount(RSSFetchUrls); - RSSRoomCount = GetCount(RSSQueueRooms); - pthread_mutex_unlock(&RSSQueueMutex); - - if ((RSSRoomCount > 0) || (RSSCount > 0)) { - EVRSSQ_syslog(LOG_DEBUG, - "rssclient: concurrency check failed; %d rooms and %d url's are queued", - RSSRoomCount, RSSCount - ); - abort(); - return; - } - become_session(&rss_CC); - EVRSSQM_syslog(LOG_DEBUG, "rssclient started"); - CtdlForEachNetCfgRoom(rssclient_scan_room, NULL); - - if (GetCount(RSSFetchUrls) > 0) - { - pthread_mutex_lock(&RSSQueueMutex); - EVRSSQ_syslog(LOG_DEBUG, - "rssclient starting %d Clients", - GetCount(RSSFetchUrls)); - - it = GetNewHashPos(RSSFetchUrls, 0); - while (!server_shutting_down && - GetNextHashPos(RSSFetchUrls, it, &len, &Key, &vrptr) && - (vrptr != NULL)) { - rptr = (rss_aggregator *)vrptr; - if (!rss_do_fetching(rptr)) - UnlinkRSSAggregator(rptr); - } - DeleteHashPos(&it); - pthread_mutex_unlock(&RSSQueueMutex); - } - else - EVRSSQM_syslog(LOG_DEBUG, "Nothing to do."); - - EVRSSQM_syslog(LOG_DEBUG, "rssclient ended"); + syslog(LOG_DEBUG, "rssclient started"); + CtdlForEachRoom(rssclient_scan_room, NULL); + rss_pull_feeds(); + syslog(LOG_DEBUG, "rssclient ended"); + last_run = time(NULL); return; } -void rss_cleanup(void) -{ - /* citthread_mutex_destroy(&RSSQueueMutex); TODO */ - DeleteHash(&RSSFetchUrls); - DeleteHash(&RSSQueueRooms); -} - -void LogDebugEnableRSSClient(const int n) -{ - RSSClientDebugEnabled = n; -} - - -typedef struct __RSSVetoInfo { - StrBuf *ErrMsg; - time_t Now; - int Veto; -}RSSVetoInfo; - -void rssclient_veto_scan_room(struct ctdlroom *qrbuf, void *data, OneRoomNetCfg *OneRNCFG) -{ - RSSVetoInfo *Info = (RSSVetoInfo *) data; - const RSSCfgLine *RSSCfg = (RSSCfgLine *)OneRNCFG->NetConfigs[rssclient]; - - while (RSSCfg != NULL) - { - if ((RSSCfg->last_known_good != 0) && - (RSSCfg->last_known_good + USETABLE_ANTIEXPIRE < Info->Now)) - { - StrBufAppendPrintf(Info->ErrMsg, - "RSS feed not seen for a %d days:: <", - (Info->Now - RSSCfg->last_known_good) / (24 * 60 * 60)); - - StrBufAppendBuf(Info->ErrMsg, RSSCfg->Url, 0); - StrBufAppendBufPlain(Info->ErrMsg, HKEY(">\n"), 0); - } - RSSCfg = RSSCfg->next; - } -} - -int RSSCheckUsetableVeto(StrBuf *ErrMsg) -{ - RSSVetoInfo Info; - - Info.ErrMsg = ErrMsg; - Info.Now = time (NULL); - Info.Veto = 0; - - CtdlForEachNetCfgRoom(rssclient_veto_scan_room, &Info); - - return Info.Veto;; -} - - - - -void ParseRSSClientCfgLine(const CfgLineType *ThisOne, StrBuf *Line, const char *LinePos, OneRoomNetCfg *OneRNCFG) -{ - RSSCfgLine *RSSCfg; - - RSSCfg = (RSSCfgLine *) malloc (sizeof(RSSCfgLine)); - RSSCfg->Url = NewStrBufPlain (NULL, StrLength (Line)); - - - StrBufExtract_NextToken(RSSCfg->Url, Line, &LinePos, '|'); - RSSCfg->last_known_good = StrBufExtractNext_long(Line, &LinePos, '|'); - - - RSSCfg->next = (RSSCfgLine *)OneRNCFG->NetConfigs[ThisOne->C]; - OneRNCFG->NetConfigs[ThisOne->C] = (RoomNetCfgLine*) RSSCfg; -} - -void SerializeRSSClientCfgLine(const CfgLineType *ThisOne, StrBuf *OutputBuffer, OneRoomNetCfg *RNCfg, RoomNetCfgLine *data) -{ - RSSCfgLine *RSSCfg = (RSSCfgLine*) data; - - StrBufAppendBufPlain(OutputBuffer, CKEY(ThisOne->Str), 0); - StrBufAppendBufPlain(OutputBuffer, HKEY("|"), 0); - StrBufAppendBufPlain(OutputBuffer, SKEY(RSSCfg->Url), 0); - StrBufAppendPrintf(OutputBuffer, "|%ld\n", RSSCfg->last_known_good); -} - -void DeleteRSSClientCfgLine(const CfgLineType *ThisOne, RoomNetCfgLine **data) -{ - RSSCfgLine *RSSCfg = (RSSCfgLine*) *data; - - FreeStrBuf(&RSSCfg->Url); - free(*data); - *data = NULL; -} - CTDL_MODULE_INIT(rssclient) { if (!threading) { - CtdlRegisterTDAPVetoHook (RSSCheckUsetableVeto, CDB_USETABLE, 0); - - CtdlREGISTERRoomCfgType(rssclient, ParseRSSClientCfgLine, 0, 1, SerializeRSSClientCfgLine, DeleteRSSClientCfgLine); - pthread_mutex_init(&RSSQueueMutex, NULL); - RSSQueueRooms = NewHash(1, lFlathash); - RSSFetchUrls = NewHash(1, NULL); - syslog(LOG_INFO, "%s\n", curl_version()); + syslog(LOG_INFO, "%s", curl_version()); CtdlRegisterSessionHook(rssclient_scan, EVT_TIMER, PRIO_AGGR + 300); - CtdlRegisterEVCleanupHook(rss_cleanup); - CtdlRegisterDebugFlagHook(HKEY("rssclient"), LogDebugEnableRSSClient, &RSSClientDebugEnabled); } else { @@ -1031,3 +241,4 @@ CTDL_MODULE_INIT(rssclient) } return "rssclient"; } + -- 2.30.2