summaryrefslogtreecommitdiff
path: root/common.c
blob: 552e9af090d3cfba1764ecd0409045d3cec6c08a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <ctype.h>

enum { FieldUnixTimestamp = 0, FieldTimeFormatted, FieldTitle, FieldLink,
       FieldContent, FieldContentType, FieldId, FieldAuthor, FieldFeedType,
       FieldFeedName, FieldFeedUrl, FieldBaseSiteUrl, FieldLast };

const int FieldSeparator = '\t';

char *
afgets(char **p, size_t *size, FILE *fp) {
	char buf[BUFSIZ], *alloc = NULL;
	size_t n, len = 0, allocsiz;
	int end = 0;

	while(fgets(buf, sizeof(buf), fp)) {
		n = strlen(buf);
		if(buf[n - 1] == '\n') { /* dont store newlines. */
			buf[n - 1] = '\0';
			n--;
			end = 1; /* newline found, end */
		}
		len += n;
		allocsiz = len + 1;
		if(allocsiz > *size) {
			if((alloc = realloc(*p, allocsiz))) {
				*p = alloc;
				*size = allocsiz;
			} else {
				free(*p);
				*p = NULL;
				fputs("error: could not realloc\n", stderr);
				exit(EXIT_FAILURE);
				return NULL;
			}
		}
		strncpy((*p + (len - n)), buf, n);
		if(end || feof(fp))
			break;
	}
	if(*p && len > 0) {
		(*p)[len] = '\0';
		return *p;
	}
	return NULL;
}

void /* print link; if link is relative use baseurl to make it absolute */
printlink(const char *link, const char *baseurl) {
	const char *ebaseproto, *ebasedomain, *p;
	int isrelative;

	/* protocol part */
	for(p = link; *p && (isalpha(*p) || isdigit(*p) || *p == '+' || *p == '-' || *p == '.'); p++);
	isrelative = strncmp(p, "://", strlen("://"));
	if(isrelative) { /* relative link (baseurl is used). */
		if((ebaseproto = strstr(baseurl, "://"))) {
			ebaseproto += strlen("://");
			fwrite(baseurl, 1, ebaseproto - baseurl, stdout);
		} else {
			ebaseproto = baseurl;
			if(*baseurl || (link[0] == '/' && link[1] == '/'))
				fputs("http://", stdout);
		}
		if(link[0] == '/') { /* relative to baseurl domain (not path).  */
			if(link[1] == '/') /* absolute url but with protocol from baseurl. */
				link += 2;
			else if((ebasedomain = strchr(ebaseproto, '/'))) /* relative to baseurl and baseurl path. */
				fwrite(ebaseproto, 1, ebasedomain - ebaseproto, stdout);
			else
				fputs(ebaseproto, stdout);
		} else if((ebasedomain = strrchr(ebaseproto, '/'))) /* relative to baseurl and baseurl path. */
			fwrite(ebaseproto, 1, ebasedomain - ebaseproto + 1, stdout);
		else {
			fputs(ebaseproto, stdout);
			if(*baseurl && *link)
				fputc('/', stdout);
		}
	}
	fputs(link, stdout);
}

unsigned int
parseline(char **line, size_t *size, char **fields, unsigned int maxfields, FILE *fp, int separator) {
	unsigned int i = 0;
	char *prev, *s;

	if(afgets(line, size, fp)) {
		for(prev = *line; (s = strchr(prev, separator)) && i <= maxfields; i++) {
			*s = '\0'; /* null terminate string. */
			fields[i] = prev;
			prev = s + 1;
		}
		fields[i] = prev;
		for(i++; i < maxfields; i++) /* make non-parsed fields empty. */
			fields[i] = "";
	}
	return i;
}

void
printtime(time_t t) {
	char buf[32];
	struct tm temp = { 0 }, *mktm;

	if(!(mktm = localtime_r(&t, &temp)))
		return;
	mktm->tm_isdst = -1;

	if(!strftime(buf, sizeof(buf) - 1, "%Y-%m-%d %H:%M", mktm))
		return;
	fputs(buf, stdout);
}