summary refs log tree commit diff stats
path: root/html.c
diff options
context:
space:
mode:
Diffstat (limited to 'html.c')
-rw-r--r--html.c256
1 files changed, 256 insertions, 0 deletions
diff --git a/html.c b/html.c
new file mode 100644
index 0000000..fa83f2c
--- /dev/null
+++ b/html.c
@@ -0,0 +1,256 @@
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <fcntl.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <gemtext.h>
+
+#include "gemlog.h"
+
+/* TODO: allow user to specify custom header/footer */
+#define HTML_HEADER_BEGIN "<!DOCTYPE html><html><head><meta charset=\"UTF-8\"><meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">"
+#define HTML_HEADER_END   "</head><body>"
+#define HTML_FOOTER       "</body></html>"
+
+static int
+gemlog_write_html_text(struct gemtext *text, int fd)
+{
+	if (write(fd, "<p>", strlen("<p>")) == -1)
+		return -1;
+	if (write(fd, ((struct gemtext_text *)text)->text, strlen(((struct gemtext_text *)text)->text)) == -1)
+		return -1;
+	if (write(fd, "</p>\n", strlen("</p>\n")) == -1)
+		return -1;
+	return 0;
+}
+
+static int
+gemlog_write_html_link(struct gemtext *text, int fd)
+{
+	if (write(fd, "<p><a href=\"", strlen("<p><a href=\"")) == -1)
+		return -1;
+	if (write(fd, ((struct gemtext_link *)text)->link, strlen(((struct gemtext_link *)text)->link)) == -1)
+		return -1;
+	if (write(fd, "\">", strlen("\">")) == -1)
+		return -1;
+	if (((struct gemtext_link *)text)->name) {
+		if (write(fd, ((struct gemtext_link *)text)->name, strlen(((struct gemtext_link *)text)->name)) == -1)
+			return -1;
+	}
+	if (write(fd, "</a></p>\n", strlen("</a></p>\n")) == -1)
+		return -1;
+	return 0;
+}
+
+static int
+gemlog_write_html_pre(struct gemtext *text, int fd)
+{
+	if (write(fd, "<p><pre>", strlen("<p><pre>")) == -1)
+		return -1;
+	if (write(fd, ((struct gemtext_pre *)text)->text, strlen(((struct gemtext_pre *)text)->text)) == -1)
+		return -1;
+	if (write(fd, "</pre></p>\n", strlen("</pre></p>\n")) == -1)
+		return -1;
+	return 0;
+}
+
+static int
+gemlog_write_html_h1(struct gemtext *text, int fd)
+{
+	if (write(fd, "<h1>", strlen("<h1>")) == -1)
+		return -1;
+	if (write(fd, ((struct gemtext_h1 *)text)->text, strlen(((struct gemtext_h1 *)text)->text)) == -1)
+		return -1;
+	if (write(fd, "</h1>\n", strlen("</h1>\n")) == -1)
+		return -1;
+	return 0;
+}
+
+static int
+gemlog_write_html_h2(struct gemtext *text, int fd)
+{
+	if (write(fd, "<h2>", strlen("<h2>")) == -1)
+		return -1;
+	if (write(fd, ((struct gemtext_h2 *)text)->text, strlen(((struct gemtext_h2 *)text)->text)) == -1)
+		return -1;
+	if (write(fd, "</h2>\n", strlen("</h2>\n")) == -1)
+		return -1;
+	return 0;
+}
+
+static int
+gemlog_write_html_h3(struct gemtext *text, int fd)
+{
+	if (write(fd, "<h3>", strlen("<h3>")) == -1)
+		return -1;
+	if (write(fd, ((struct gemtext_h3 *)text)->text, strlen(((struct gemtext_h3 *)text)->text)) == -1)
+		return -1;
+	if (write(fd, "</h3>\n", strlen("</h3>\n")) == -1)
+		return -1;
+	return 0;
+}
+
+static int
+gemlog_write_html_ul(struct gemtext *text, int fd)
+{
+	if (write(fd, "<li>", strlen("<li>")) == -1)
+		return -1;
+	if (write(fd, ((struct gemtext_ul *)text)->text, strlen(((struct gemtext_ul *)text)->text)) == -1)
+		return -1;
+	if (write(fd, "</li>\n", strlen("</li>\n")) == -1)
+		return -1;
+	return 0;
+}
+
+static int
+gemlog_write_html_qt(struct gemtext *text, int fd)
+{
+	if (write(fd, "<blockquote>", strlen("<blockquote>")) == -1)
+		return -1;
+	if (write(fd, ((struct gemtext_qt *)text)->text, strlen(((struct gemtext_qt *)text)->text)) == -1)
+		return -1;
+	if (write(fd, "</blockquote>\n", strlen("</blockquote>\n")) == -1)
+		return -1;
+	return 0;
+}
+
+int
+gemlog_write_html(struct gemlog_entry **feed, const char *path)
+{
+	int i;
+	int x;
+	int ulindicator;
+	int fd;
+	char pathbuf[PATH_MAX+1];
+	char fmtbuf[PATH_MAX+1];
+
+	if (mkdir(path, 0755) == -1) {
+		if (errno != EEXIST)
+			return -1;
+	}
+
+	for (i = 0; feed[i] != NULL; i++) {
+		strlcpy(pathbuf, path, sizeof(pathbuf));
+		strlcat(pathbuf, "/", sizeof(pathbuf));
+		snprintf(fmtbuf, sizeof(fmtbuf), "%d", feed[i]->date.tm_year+1900);
+		strlcat(pathbuf, fmtbuf, sizeof(pathbuf));
+		if (mkdir(pathbuf, 0755) == -1) {
+			if (errno != EEXIST)
+				return -1;
+		}
+
+		strlcat(pathbuf, "/", sizeof(pathbuf));
+		snprintf(fmtbuf, sizeof(fmtbuf), "%d", feed[i]->date.tm_mon+1);
+		strlcat(pathbuf, fmtbuf, sizeof(pathbuf));
+		if (mkdir(pathbuf, 0755) == -1) {
+			if (errno != EEXIST)
+				return -1;
+		}
+
+		strlcat(pathbuf, "/", sizeof(pathbuf));
+		snprintf(fmtbuf, sizeof(fmtbuf), "%d", feed[i]->date.tm_mday);
+		strlcat(pathbuf, fmtbuf, sizeof(pathbuf));
+		if (mkdir(pathbuf, 0755) == -1) {
+			if (errno != EEXIST)
+				return -1;
+		}
+
+		strlcat(pathbuf, "/", sizeof(pathbuf));
+		snprintf(fmtbuf, sizeof(fmtbuf), "%d", feed[i]->date.tm_hour);
+		strlcat(pathbuf, fmtbuf, sizeof(pathbuf));
+		if (mkdir(pathbuf, 0755) == -1) {
+			if (errno != EEXIST)
+				return -1;
+		}
+
+		strlcat(pathbuf, "/", sizeof(pathbuf));
+		strlcat(pathbuf, GEMLOG_CONTENT_HTML_FILENAME, sizeof(pathbuf));
+		fd = open(pathbuf, O_WRONLY|O_CREAT|O_TRUNC);
+		if (fd == -1)
+			return -1;
+		if (chmod(pathbuf, 0644) == -1) {
+			close(fd);
+			return -1;
+		}
+
+		/* write header */
+		if (write(fd, HTML_HEADER_BEGIN, strlen(HTML_HEADER_BEGIN)) == -1) {
+			close(fd);
+			return -1;
+		}
+		if (write(fd, "<title>", strlen("<title>")) == -1) {
+			close(fd);
+			return -1;
+		}
+		if (write(fd, feed[i]->title, strlen(feed[i]->title)) == -1) {
+			close(fd);
+			return -1;
+		}
+		if (write(fd, "</title>", strlen("</title>")) == -1) {
+			close(fd);
+			return -1;
+		}
+		if (write(fd, HTML_HEADER_END, strlen(HTML_HEADER_END)) == -1) {
+			close(fd);
+			return -1;
+		}
+
+		ulindicator = 0;
+		for (x = 0; feed[i]->content[x] != NULL; x++) {
+			if (ulindicator) {
+				if (gemtext_type(feed[i]->content[x]) != GEMTEXT_UL) {
+					if (write(fd, "</ul>\n", strlen("</ul>\n")) == -1) {
+						close(fd);
+						return -1;
+					}
+					ulindicator = 0;
+				}
+			}
+			switch (gemtext_type(feed[i]->content[x])) {
+			case GEMTEXT_TEXT:
+				gemlog_write_html_text(feed[i]->content[x], fd);
+				break;
+			case GEMTEXT_LINK:
+				gemlog_write_html_link(feed[i]->content[x], fd);
+				break;
+			case GEMTEXT_PRE:
+				gemlog_write_html_pre(feed[i]->content[x], fd);
+				break;
+			case GEMTEXT_H1:
+				gemlog_write_html_h1(feed[i]->content[x], fd);
+				break;
+			case GEMTEXT_H2:
+				gemlog_write_html_h2(feed[i]->content[x], fd);
+				break;
+			case GEMTEXT_H3:
+				gemlog_write_html_h3(feed[i]->content[x], fd);
+				break;
+			case GEMTEXT_UL:
+				if (!ulindicator) {
+					if (write(fd, "<ul>\n", strlen("<ul>\n")) == -1) {
+						close(fd);
+						return -1;
+					}
+					ulindicator = 1;
+				}
+				gemlog_write_html_ul(feed[i]->content[x], fd);
+				break;
+			case GEMTEXT_QT:
+				gemlog_write_html_qt(feed[i]->content[x], fd);
+				break;
+			default:
+				close(fd);
+				return -1;
+			}
+		}
+		close(fd);
+	}
+
+	return 0;
+}