about summary refs log blame commit diff stats
path: root/html.c
blob: 1f78adbd4e5407f92e3394c7c9c068bafc52a272 (plain) (tree)














































































































































































































































































































                                                                              
#include <sys/types.h>
#include <sys/stat.h>

#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include "gemtext.h"

static int
_case_text(struct gemtext *line, char **out, size_t *outlen)
{
	char *app;

	*outlen += gemtext_text_strlen(line);
	*outlen += 7; /* <p></p> */

	app = realloc(*out, (*outlen+1));
	if (app == NULL)
		return -1;
	*out = app;

	strlcat(*out, "<p>", (*outlen+1));
	strlcat(*out, gemtext_text_string(line), (*outlen)+1);
	strlcat(*out, "</p>", (*outlen)+1);

	return 0;
}

static int
_case_link(struct gemtext *line, char **out, size_t *outlen)
{
	char *app;

	*outlen += gemtext_link_link_strlen(line);
	*outlen += gemtext_link_label_strlen(line);
	*outlen += 22; /* <p><a href=""></a></p> */

	app = realloc(*out, (*outlen)+1);
	if (app == NULL)
		return -1;
	*out = app;

	strlcat(*out, "<p><a href=\"", (*outlen)+1);
	strlcat(*out, gemtext_link_link_string(line), (*outlen)+1);
	strlcat(*out, "\">", (*outlen)+1);
	if (gemtext_link_has_label(line))
		strlcat(*out, gemtext_link_label_string(line), (*outlen)+1);
	strlcat(*out, "</a></p>", (*outlen)+1);

	return 0;
}

static int
_case_pre(struct gemtext *line, char **out, size_t *outlen)
{
	char *app;

	*outlen += gemtext_pre_strlen(line);
	*outlen += 18; /* <p><pre></pre></p> */

	app = realloc(*out, (*outlen)+1);
	if (app == NULL)
		return -1;
	*out = app;

	strlcat(*out, "<p><pre>", (*outlen)+1);
	strlcat(*out, gemtext_pre_string(line), (*outlen)+1);
	strlcat(*out, "</pre></p>", (*outlen)+1);

	return 0;
}

static int
_case_h1(struct gemtext *line, char **out, size_t *outlen)
{
	char *app;

	*outlen += gemtext_h1_strlen(line);
	*outlen += 9; /* <h1></h1> */

	app = realloc(*out, (*outlen)+1);
	if (app == NULL)
		return -1;
	*out = app;

	strlcat(*out, "<h1>", (*outlen)+1);
	strlcat(*out, gemtext_h1_string(line), (*outlen)+1);
	strlcat(*out, "</h1>", (*outlen)+1);

	return 0;
}

static int
_case_h2(struct gemtext *line, char **out, size_t *outlen)
{
	char *app;

	*outlen += gemtext_h2_strlen(line);
	*outlen += 9; /* <h2></h2> */

	app = realloc(*out, (*outlen)+1);
	if (app == NULL)
		return -1;
	*out = app;

	strlcat(*out, "<h2>", (*outlen)+1);
	strlcat(*out, gemtext_h2_string(line), (*outlen)+1);
	strlcat(*out, "</h2>", (*outlen)+1);

	return 0;
}

static int
_case_h3(struct gemtext *line, char **out, size_t *outlen)
{
	char *app;

	*outlen += gemtext_h3_strlen(line);
	*outlen += 9; /* <h3></h3> */

	app = realloc(*out, (*outlen)+1);
	if (app == NULL)
		return -1;
	*out = app;

	strlcat(*out, "<h3>", (*outlen)+1);
	strlcat(*out, gemtext_h3_string(line), (*outlen)+1);
	strlcat(*out, "</h3>", (*outlen)+1);

	return 0;
}

static int
_case_ul(struct gemtext *line, char **out, size_t *outlen)
{
	char *app;

	*outlen += gemtext_ul_strlen(line);
	*outlen += 9; /* <li></li> */

	app = realloc(*out, (*outlen)+1);
	if (app == NULL)
		return -1;
	*out = app;

	strlcat(*out, "<li>", (*outlen)+1);
	strlcat(*out, gemtext_ul_string(line), (*outlen)+1);
	strlcat(*out, "</li>", (*outlen)+1);

	return 0;
}

static int
_case_qt(struct gemtext *line, char **out, size_t *outlen)
{
	char *app;

	*outlen += gemtext_qt_strlen(line);
	*outlen += 25; /* <blockquote></blockquote> */

	app = realloc(*out, (*outlen)+1);
	if (app == NULL)
		return -1;
	*out = app;

	strlcat(*out, "<blockquote>", (*outlen)+1);
	strlcat(*out, gemtext_qt_string(line), (*outlen)+1);
	strlcat(*out, "</blockquote>", (*outlen)+1);

	return 0;
}

int
gemtext_list_encode_to_html(struct gemtext **list, char **out, size_t *outlen)
{
	char *app;
	int i;
	int ulindic;

	*out = NULL;
	*outlen = 0;
	ulindic = 0;

	*out = malloc(1);
	if (*out == NULL)
		return -1;
	*out[0] = '\0'; /* for strlcat() */

	for (i = 0; list[i] != NULL; i++) {
		if (gemtext_type(list[i]) != GEMTEXT_UL && ulindic) {
			*outlen += 5; /* </ul> */
			app = realloc(*out, (*outlen)+1);
			if (app == NULL) {
				free(*out);
				return -1;
			}
			*out = app;
			strlcat(*out, "</ul>", (*outlen)+1);
			ulindic = 0;
		}
		switch (gemtext_type(list[i])) {
		case GEMTEXT_TEXT:
			if (_case_text(list[i], out, outlen) == -1) {
				free(*out);
				return -1;
			}
			break;
		case GEMTEXT_LINK:
			if (_case_link(list[i], out, outlen) == -1) {
				free(*out);
				return -1;
			}
			break;
		case GEMTEXT_PRE:
			if (_case_pre(list[i], out, outlen) == -1) {
				free(*out);
				return -1;
			}
			break;
		case GEMTEXT_H1:
			if (_case_h1(list[i], out, outlen) == -1) {
				free(*out);
				return -1;
			}
			break;
		case GEMTEXT_H2:
			if (_case_h2(list[i], out, outlen) == -1) {
				free(*out);
				return -1;
			}
			break;
		case GEMTEXT_H3:
			if (_case_h3(list[i], out, outlen) == -1) {
				free(*out);
				return -1;
			}
			break;
		case GEMTEXT_UL:
			if (!ulindic) {
				*outlen += 4; /* <ul> */
				app = realloc(*out, (*outlen)+1);
				if (app == NULL) {
					free(*out);
					return -1;
				}
				*out = app;
				strlcat(*out, "<ul>", (*outlen)+1);
				ulindic = 1;
			}
			if (_case_ul(list[i], out, outlen) == -1) {
				free(*out);
				return -1;
			}
			break;
		case GEMTEXT_QT:
			if (_case_qt(list[i], out, outlen) == -1) {
				free(*out);
				return -1;
			}
			break;
		}
	}

	return 0;
}

int
gemtext_list_encode_to_html_fd(struct gemtext **list, int fd)
{
	char *out;
	size_t len;

	if (gemtext_list_encode_to_html(list, &out, &len) == -1)
		return -1;
	if (write(fd, out, len) == -1) {
		free(out);
		return -1;
	}
	free(out);

	return 0;
}

int
gemtext_list_encode_to_html_file(struct gemtext **list, const char *file)
{
	int fd;

	fd = open(file, O_WRONLY|O_TRUNC|O_CREAT);
	if (fd == -1)
		return -1;
	/* file does not have to be owned by user, so errors are expected */
	fchmod(fd, 0644);
	if (gemtext_list_encode_to_html_fd(list, fd) == -1) {
		close(fd);
		return -1;
	}
	close(fd);

	return 0;
}