handlers.c: make itemAction more modular
This commit is contained in:
parent
453e36317f
commit
73b0cad54f
2
Makefile
2
Makefile
@ -2,7 +2,7 @@ PREFIX = ~/.local
|
||||
VERSION = 0.1
|
||||
|
||||
# CC = cc
|
||||
SRC = minrss.c util.c net.c
|
||||
SRC = minrss.c util.c net.c handlers.c
|
||||
OBJ = $(SRC:.c=.o)
|
||||
PKG_CONFIG = pkg-config
|
||||
CURL_CONFIG = curl-config
|
||||
|
@ -49,6 +49,3 @@ static const int maxRedirs = 10;
|
||||
// Restrict allowed protocols for curl using a bitmask.
|
||||
// For more information: https://curl.se/libcurl/c/CURLOPT_PROTOCOLS.html
|
||||
static const int curlProtocols = CURLPROTO_HTTPS | CURLPROTO_HTTP;
|
||||
|
||||
// File extension used for each article.
|
||||
static const char fileExt[] = ".html";
|
||||
|
137
handlers.c
Normal file
137
handlers.c
Normal file
@ -0,0 +1,137 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "util.h"
|
||||
|
||||
enum feedFormat {
|
||||
NONE,
|
||||
RSS,
|
||||
ATOM,
|
||||
};
|
||||
|
||||
typedef struct itemStruct itemStruct;
|
||||
struct itemStruct {
|
||||
char *title;
|
||||
char *link;
|
||||
char *description;
|
||||
itemStruct *next;
|
||||
};
|
||||
|
||||
void
|
||||
freeItem(itemStruct *item)
|
||||
{
|
||||
// Free the memory used by an article.
|
||||
|
||||
char **mems[] = {
|
||||
&item->title,
|
||||
&item->link,
|
||||
&item->description,
|
||||
};
|
||||
|
||||
for (unsigned long int i = 0; i < LEN(mems); i++) {
|
||||
if (*mems[i])
|
||||
free(*mems[i]);
|
||||
}
|
||||
|
||||
free(item);
|
||||
}
|
||||
|
||||
FILE *
|
||||
openFile(const char *folder, char *fileName, char *fileExt)
|
||||
{
|
||||
// [folder]/[fileName][fileExt]
|
||||
// caller's responsibility to sanitize names
|
||||
|
||||
if (!folder) {
|
||||
logMsg(1, "NULL folder");
|
||||
return NULL;
|
||||
} else if (!fileName) {
|
||||
logMsg(1, "NULL file base name");
|
||||
return NULL;
|
||||
} else if (!fileExt) {
|
||||
logMsg(1, "NULL file extension");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t folderLen = strlen(folder);
|
||||
size_t extLen = strlen(fileExt);
|
||||
size_t fileNameLen = strlen(fileName);
|
||||
|
||||
// +1 for null terminator and +1 for path separator
|
||||
size_t pathLen = folderLen + 1 + fileNameLen + extLen + 1;
|
||||
|
||||
char *filePath;
|
||||
|
||||
if (fileName[0])
|
||||
filePath = ecalloc(pathLen, sizeof(char));
|
||||
else {
|
||||
logMsg(1, "Invalid filename.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memcpy(filePath, folder, folderLen * sizeof(char));
|
||||
|
||||
filePath[folderLen] = fsep();
|
||||
filePath[pathLen - 1] = '\0';
|
||||
|
||||
memcpy(filePath + folderLen + 1, fileName, fileNameLen * sizeof(char));
|
||||
memcpy(filePath + pathLen - extLen - 1, fileExt, extLen * sizeof(char));
|
||||
|
||||
FILE *itemFile = fopen(filePath, "a");
|
||||
free (filePath);
|
||||
free (fileName);
|
||||
|
||||
return itemFile;
|
||||
}
|
||||
|
||||
static void
|
||||
outputHtml(itemStruct *item, FILE *f)
|
||||
{
|
||||
fprintf(f, "<h1>%s</h1><br>\n", item->title);
|
||||
fprintf(f, "<a href=\"%s\">Link</a><br>\n", san(item->link));
|
||||
fprintf(f, "%s", san(item->description));
|
||||
}
|
||||
|
||||
void
|
||||
itemAction(itemStruct *item, const char *folder)
|
||||
{
|
||||
// Receives a linked list of articles to process.
|
||||
|
||||
itemStruct *cur = item;
|
||||
itemStruct *prev;
|
||||
|
||||
unsigned long long int newItems = 0;
|
||||
|
||||
while (cur) {
|
||||
prev = cur;
|
||||
FILE *itemFile = openFile(folder, san(cur->title), ".html");
|
||||
|
||||
// Do not overwrite files
|
||||
if (!ftell(itemFile)) {
|
||||
outputHtml(cur, itemFile);
|
||||
newItems++;
|
||||
}
|
||||
|
||||
fclose(itemFile);
|
||||
cur = cur->next;
|
||||
freeItem(prev);
|
||||
}
|
||||
|
||||
if (newItems)
|
||||
logMsg(2, "%s : %d new articles\n", folder, newItems);
|
||||
}
|
||||
|
||||
void
|
||||
finish(char *url, long responseCode)
|
||||
{
|
||||
// Executed after a download finishes
|
||||
|
||||
if (responseCode == 200)
|
||||
logMsg(4, "Finished downloading %s\n", url);
|
||||
else if (!responseCode)
|
||||
logMsg(1, "Can not reach %s: ensure the protocol is enabled and the site is accessible.\n", url);
|
||||
else
|
||||
logMsg(1, "HTTP %ld for %s\n", responseCode, url);
|
||||
}
|
17
handlers.h
Normal file
17
handlers.h
Normal file
@ -0,0 +1,17 @@
|
||||
enum feedFormat {
|
||||
NONE,
|
||||
RSS,
|
||||
ATOM,
|
||||
};
|
||||
|
||||
typedef struct itemStruct itemStruct;
|
||||
struct itemStruct {
|
||||
char *title;
|
||||
char *link;
|
||||
char *description;
|
||||
itemStruct *next;
|
||||
};
|
||||
|
||||
void freeItem(itemStruct *item);
|
||||
void itemAction(itemStruct *item, const char *folder);
|
||||
void finish(char *url, long responseCode);
|
116
minrss.c
116
minrss.c
@ -20,45 +20,13 @@ You should have received a copy of the GNU General Public License along with thi
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "util.h"
|
||||
#include "net.h"
|
||||
#include "handlers.h"
|
||||
#include "config.h"
|
||||
|
||||
#define TAGIS(X, Y) (!xmlStrcmp(X->name, (const xmlChar *) Y))
|
||||
|
||||
enum feedFormat {
|
||||
NONE,
|
||||
RSS,
|
||||
ATOM,
|
||||
};
|
||||
|
||||
typedef struct itemStruct itemStruct;
|
||||
struct itemStruct {
|
||||
char *title;
|
||||
char *link;
|
||||
char *description;
|
||||
itemStruct *next;
|
||||
};
|
||||
|
||||
void
|
||||
freeItem(itemStruct *item)
|
||||
{
|
||||
// Free the memory used by an article.
|
||||
|
||||
char **mems[] = {
|
||||
&item->title,
|
||||
&item->link,
|
||||
&item->description,
|
||||
};
|
||||
|
||||
for (unsigned long int i = 0; i < LEN(mems); i++) {
|
||||
if (*mems[i])
|
||||
free(*mems[i]);
|
||||
}
|
||||
|
||||
free(item);
|
||||
}
|
||||
|
||||
static int
|
||||
parseXml(xmlDocPtr doc,
|
||||
const char *feedName,
|
||||
@ -275,86 +243,6 @@ readDoc(char *content,
|
||||
return stat;
|
||||
}
|
||||
|
||||
void
|
||||
itemAction(itemStruct *item, const char *folder)
|
||||
{
|
||||
// Receives a link list of articles to process.
|
||||
|
||||
itemStruct *cur = item;
|
||||
|
||||
unsigned long long int newItems = 0;
|
||||
|
||||
size_t folderLen = strlen(folder);
|
||||
size_t extLen = strlen(fileExt);
|
||||
|
||||
while (cur) {
|
||||
char *filePath;
|
||||
char *fileName = san(cur->title, 1);
|
||||
size_t fileNameLen = strlen(fileName);
|
||||
|
||||
itemStruct *prev = cur;
|
||||
|
||||
|
||||
// +1 for null terminator and +1 for path separator
|
||||
size_t pathLen = folderLen + fileNameLen + extLen + 2;
|
||||
|
||||
if (fileName[0])
|
||||
filePath = ecalloc(pathLen, sizeof(char));
|
||||
else {
|
||||
logMsg(1, "Invalid article title.\n");
|
||||
|
||||
cur = cur->next;
|
||||
freeItem(prev);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
memcpy(filePath, folder, folderLen * sizeof(char));
|
||||
|
||||
filePath[folderLen] = fsep();
|
||||
filePath[pathLen - 1] = '\0';
|
||||
|
||||
memcpy(filePath + folderLen + 1, fileName, fileNameLen * sizeof(char));
|
||||
memcpy(filePath + pathLen - extLen - 1, fileExt, extLen * sizeof(char));
|
||||
|
||||
FILE *itemFile = fopen(filePath, "a");
|
||||
|
||||
free(filePath);
|
||||
free(fileName);
|
||||
|
||||
|
||||
// Do not overwrite files
|
||||
if (!ftell(itemFile)) {
|
||||
newItems++;
|
||||
|
||||
fprintf(itemFile, "<h1>%s</h1><br>\n", cur->title);
|
||||
fprintf(itemFile, "<a href=\"%s\">Link</a><br>\n", san(cur->link, 0));
|
||||
fprintf(itemFile, "%s", san(cur->description, 0));
|
||||
}
|
||||
|
||||
fclose(itemFile);
|
||||
|
||||
cur = cur->next;
|
||||
freeItem(prev);
|
||||
}
|
||||
|
||||
if (newItems)
|
||||
logMsg(2, "%s : %d new articles\n", folder, newItems);
|
||||
}
|
||||
|
||||
void
|
||||
finish(char *url, long responseCode)
|
||||
{
|
||||
// Executed after a download finishes
|
||||
|
||||
if (responseCode == 200)
|
||||
logMsg(4, "Finished downloading %s\n", url);
|
||||
else if (!responseCode)
|
||||
logMsg(1, "Can not reach %s: ensure the protocol is enabled and the site is accessible.\n", url);
|
||||
else
|
||||
logMsg(1, "HTTP %ld for %s\n", responseCode, url);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
|
4
util.c
4
util.c
@ -61,12 +61,10 @@ erealloc(void *p, size_t size)
|
||||
}
|
||||
|
||||
char *
|
||||
san(char *str, int rep)
|
||||
san(char *str)
|
||||
{
|
||||
if (!str)
|
||||
return "";
|
||||
if (!rep)
|
||||
return str;
|
||||
|
||||
unsigned long long int len = strlen(str);
|
||||
unsigned long long int offset = 0;
|
||||
|
2
util.h
2
util.h
@ -14,5 +14,5 @@ You should have received a copy of the GNU General Public License along with thi
|
||||
void logMsg(int argc, char *msg, ...);
|
||||
void *ecalloc(size_t nmemb, size_t size);
|
||||
void *erealloc(void *p, size_t nmemb);
|
||||
char *san(char *str, int rep);
|
||||
char *san(char *str);
|
||||
char fsep();
|
||||
|
Loading…
Reference in New Issue
Block a user