diff options
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | encode.c | 34 | ||||
-rw-r--r-- | gemtext.c | 12 | ||||
-rw-r--r-- | gemtext.h | 10 | ||||
-rw-r--r-- | gemtext_encode.3 | 39 | ||||
-rw-r--r-- | gemtext_type.3 | 18 | ||||
-rw-r--r-- | html.c | 303 |
7 files changed, 391 insertions, 27 deletions
diff --git a/Makefile b/Makefile index 452443d..22e6c93 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ TARGET_LIB_STATIC = libgemtext.a PREFIX = /usr -OBJS = decode.o encode.o free.o gemtext.o gemtext_list.o strlcat.o strlcpy.o +OBJS = decode.o encode.o html.o free.o gemtext.o gemtext_list.o strlcat.o strlcpy.o MANPAGES = gemtext_decode.3 gemtext_encode.3 gemtext_free.3\ gemtext_text_new.3 gemtext_text_string.3 gemtext_type.3\ gemtext_list_append.3 diff --git a/encode.c b/encode.c index dc13d23..75afb18 100644 --- a/encode.c +++ b/encode.c @@ -23,7 +23,7 @@ _case_link(struct gemtext *t) { struct gemtext_link *link; char *ret; - int retlen; + size_t retlen; retlen = 0; link = (struct gemtext_link *)t; @@ -55,7 +55,7 @@ _case_pre(struct gemtext *t) { struct gemtext_pre *pre; char *ret; - int retlen; + size_t retlen; retlen = 0; pre = (struct gemtext_pre *)t; @@ -81,7 +81,7 @@ _case_h1(struct gemtext *t) { struct gemtext_h1 *h1; char *ret; - int retlen; + size_t retlen; retlen = 0; h1 = (struct gemtext_h1 *)t; @@ -105,7 +105,7 @@ _case_h2(struct gemtext *t) { struct gemtext_h2 *h2; char *ret; - int retlen; + size_t retlen; retlen = 0; h2 = (struct gemtext_h2 *)t; @@ -129,7 +129,7 @@ _case_h3(struct gemtext *t) { struct gemtext_h3 *h3; char *ret; - int retlen; + size_t retlen; retlen = 0; h3 = (struct gemtext_h3 *)t; @@ -154,7 +154,7 @@ _case_ul(struct gemtext *t) { struct gemtext_ul *ul; char *ret; - int retlen; + size_t retlen; retlen = 0; ul = (struct gemtext_ul *)t; @@ -178,7 +178,7 @@ _case_qt(struct gemtext *t) { struct gemtext_qt *qt; char *ret; - int retlen; + size_t retlen; retlen = 0; qt = (struct gemtext_qt *)t; @@ -198,9 +198,9 @@ _case_qt(struct gemtext *t) } static char * -_line_append(char *dst, const char *src, int *len) +_line_append(char *dst, const char *src, size_t *len) { - int rlen; + size_t rlen; char *ret; rlen = *len; @@ -223,7 +223,7 @@ _line_append(char *dst, const char *src, int *len) } int -gemtext_encode(struct gemtext *line, char **text, int *len) +gemtext_encode(struct gemtext *line, char **text, size_t *len) { switch (line->type) { case GEMTEXT_TEXT: @@ -292,7 +292,7 @@ int gemtext_encode_fd(struct gemtext *line, int fd) { char *text; - int len; + size_t len; int ecode; if (gemtext_encode(line, &text, &len) == -1) @@ -325,11 +325,11 @@ gemtext_encode_file(struct gemtext *line, const char *path) } int -gemtext_list_encode(struct gemtext **list, char **text, int *len) +gemtext_list_encode(struct gemtext **list, char **text, size_t *len) { int i; - int encbuflen; - int retbuflen; + size_t encbuflen; + size_t retbuflen; char *encbuf; char *appbuf; char *retbuf; @@ -362,7 +362,7 @@ int gemtext_list_encode_fd(struct gemtext **list, int fd) { char *text; - int len; + size_t len; int ecode; if (gemtext_list_encode(list, &text, &len) == -1) @@ -382,9 +382,11 @@ gemtext_list_encode_file(struct gemtext **list, const char *path) int fd; int ecode; - fd = open(path, O_WRONLY); + fd = open(path, 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); ecode = gemtext_list_encode_fd(list, fd); close(fd); diff --git a/gemtext.c b/gemtext.c index 79e6c84..40d8bac 100644 --- a/gemtext.c +++ b/gemtext.c @@ -178,6 +178,14 @@ gemtext_type(struct gemtext *t) return t->type; } +int +gemtext_link_has_label(struct gemtext *t) +{ + if (((struct gemtext_link *)t)->name) + return 1; + return 0; +} + char * gemtext_text_string(struct gemtext *t) { @@ -247,7 +255,9 @@ gemtext_link_link_strlen(struct gemtext *t) size_t gemtext_link_label_strlen(struct gemtext *t) { - return strlen(((struct gemtext_link *)t)->name); + if (gemtext_link_has_label(t)) + return strlen(((struct gemtext_link *)t)->name); + return 0; } size_t diff --git a/gemtext.h b/gemtext.h index 06f27ea..809e7c6 100644 --- a/gemtext.h +++ b/gemtext.h @@ -67,13 +67,18 @@ struct gemtext **gemtext_list_decode_fd(int); struct gemtext **gemtext_list_decode_file(const char *); /* encode.c */ -int gemtext_encode(struct gemtext *, char **, int *); +int gemtext_encode(struct gemtext *, char **, size_t *); int gemtext_encode_fd(struct gemtext *, int); int gemtext_encode_file(struct gemtext *, const char *); -int gemtext_list_encode(struct gemtext **, char **, int *); +int gemtext_list_encode(struct gemtext **, char **, size_t *); int gemtext_list_encode_fd(struct gemtext **, int); int gemtext_list_encode_file(struct gemtext **, const char *); +/* html.c */ +int gemtext_list_encode_to_html(struct gemtext **, char **, size_t *); +int gemtext_list_encode_to_html_fd(struct gemtext **, int); +int gemtext_list_encode_to_html_file(struct gemtext **, const char *); + /* gemtext.c */ struct gemtext *gemtext_text_new(const char *); struct gemtext *gemtext_link_new(const char *, const char *); @@ -84,6 +89,7 @@ struct gemtext *gemtext_h3_new(const char *); struct gemtext *gemtext_ul_new(const char *); struct gemtext *gemtext_qt_new(const char *); int gemtext_type(struct gemtext *); +int gemtext_link_has_label(struct gemtext *); char *gemtext_text_string(struct gemtext *); char *gemtext_link_link_string(struct gemtext *); char *gemtext_link_label_string(struct gemtext *); diff --git a/gemtext_encode.3 b/gemtext_encode.3 index 046d21e..28fb5cc 100644 --- a/gemtext_encode.3 +++ b/gemtext_encode.3 @@ -15,7 +15,7 @@ .Fo gemtext_encode .Fa "struct gemtext *line" .Fa "char **textptr" -.Fa "int *lenptr" +.Fa "size_t *lenptr" .Fc .Ft int .Fo gemtext_encode_fd @@ -31,7 +31,7 @@ .Fo gemtext_list_encode .Fa "struct gemtext **list" .Fa "char **textptr" -.Fa "int *lenptr" +.Fa "size_t *lenptr" .Fc .Ft int .Fo gemtext_list_encode_fd @@ -43,6 +43,22 @@ .Fa "struct gemtext **list" .Fa "const char *path" .Fc +.Ft int +.Fo gemtext_list_encode_to_html +.Fa "struct gemtext **list" +.Fa "char **textptr" +.Fa "size_t *lenptr" +.Fc +.Ft int +.Fo gemtext_list_encode_to_html_fd +.Fa "struct gemtext **list" +.Fa "int fd" +.Fc +.Ft int +.Fo gemtext_list_encode_to_html_file +.Fa "struct gemtext **list" +.Fa "const char *path" +.Fc .Sh DESCRIPTION .Fn gemtext_encode encodes @@ -52,7 +68,7 @@ to and sets pointer pointed to by .Em textptr to the encoded text and sets -.Em int +.Em size_t pointed to by .Em lenptr to the size of the encoded text excluding terminating NULL byte, this can be discarded by setting @@ -88,14 +104,27 @@ behave the same as the family of functions, except they operate on a list of .Em struct gemtext* terminated by a NULL pointer. +.Pp +.Fn gemtext_list_encode_to_html , +.Fn gemtext_list_encode_to_html_fd +and +.Fn gemtext_list_encode_to_html_file +behave the same as the +.Fn gemtext_list_encode +family of functions, except the output provided in +.Em textptr +is formatted in HTML instead of gemtext. .Sh RETURN VALUES .Fn gemtext_encode , .Fn gemtext_encode_fd , .Fn gemtext_encode_file , .Fn gemtext_list_encode , -.Fn gemtext_list_encode_fd +.Fn gemtext_list_encode_fd , +.Fn gemtext_list_encode_file , +.Fn gemtext_list_encode_to_html , +.Fn gemtext_list_encode_to_html_fd and -.Fn gemtext_list_encode_file +.Fn gemtext_list_encode_to_html_file all return .Em 0 on success or diff --git a/gemtext_type.3 b/gemtext_type.3 index 32ec3b9..34436c0 100644 --- a/gemtext_type.3 +++ b/gemtext_type.3 @@ -2,16 +2,30 @@ .Dt gemtext 3 .Os .Sh NAME -.Nm gemtext_type -.Nd show gemtext line type +.Nm gemtext_type , +.Nm gemtext_link_has_label +.Nd read information from gemtext objects .Sh SYNOPSIS .In gemtext.h .Ft int .Fn gemtext_type "struct gemtext *line" +.Ft int +.Fn gemtext_link_has_label "struct gemtext *line" .Sh DESCRIPTION .Fn gemtext_type returns the type of gemtext object specified in .Em line . +.Pp +.Fn gemtext_link_has_label +operates under the assumption that +.Em line +is of type +.Em GEMTEXT_LINK +and returns non-zero if link object contained in +.Em line +has a label, or +.Em 0 +if it doesn't. .Sh TYPES This is a list of all possible return values for .Fn gemtext_type : diff --git a/html.c b/html.c new file mode 100644 index 0000000..1f78adb --- /dev/null +++ b/html.c @@ -0,0 +1,303 @@ +#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; +} |