summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
author Dave Woodfall2020-09-12 03:52:02 +0200
committer Willy Sudiarto Raharjo2020-09-12 18:44:59 +0200
commita689188b56c0b494c0aefefdd4d93780d0cf48e7 (patch)
tree7b0e5a18f74d45a4f9c51a8f38238177177febe6
parent69ce7e253e572491a5aea319bd7377d8ae4a08db (diff)
downloadslackbuilds-a689188b56c0b494c0aefefdd4d93780d0cf48e7.tar.gz
network/felinks: Added (A fork of Elinks, the web browser).
Signed-off-by: Willy Sudiarto Raharjo <willysr@slackbuilds.org>
-rw-r--r--network/felinks/README72
-rw-r--r--network/felinks/felinks.SlackBuild196
-rw-r--r--network/felinks/felinks.info10
-rw-r--r--network/felinks/patches/0001-gopher_html_links.patch37
-rw-r--r--network/felinks/patches/0002-gopher_index_queries.patch113
-rw-r--r--network/felinks/patches/0003-gopher_directory_links.patch26
-rw-r--r--network/felinks/patches/0005-gopher_newlines_tabs_entity-2.patch50
-rw-r--r--network/felinks/patches/0006-gopher-indexes_nocr.patch19
-rw-r--r--network/felinks/patches/0008-gopher-html-entities.patch47
-rw-r--r--network/felinks/slack-desc19
10 files changed, 589 insertions, 0 deletions
diff --git a/network/felinks/README b/network/felinks/README
new file mode 100644
index 0000000000..5a878fde58
--- /dev/null
+++ b/network/felinks/README
@@ -0,0 +1,72 @@
+Felinks is a maintained and up-to-date fork of ELinks, an advanced web
+browser.
+
+ELinks is an advanced and well-established feature-rich text mode web
+(HTTP/FTP/..) browser. ELinks can render both frames and tables, is
+highly customizable and can be extended via scripts. It is very portable
+and runs on a variety of platforms. The ELinks official website is
+available at http://elinks.cz
+
+NOTE: Felinks will conflict with Elinks, so currently only one can be
+installed at a time.
+
+There are a number of options that can be used to add support for
+other protocols etc. To enable or disable an option use the following
+method:
+
+ MOUSE=no ./elinks.SlackBuild
+or
+ MOUSE=no sh elinks.SlackBuild
+
+Multiple options can be combined.
+
+Category Description Default Value
+
+System:
+
+FASTMEM Direct use of system alloc no
+CGI Local CGI support no
+COMBINING Unicode combining characters no (experimental)
+UTF8 UTF-8 support yes
+IPV6 IPv6 support yes
+HTMLHL HTML highlighting using DOM engine no
+LZMA LZMA encoding support no
+TRE REGEX SEARCH SUPPORT yes
+BROTLI BROTLI COMPRESSION yes
+DEBUG Debug support (disables fastmem) no
+XTERM Xterm support (Enables X11) no
+X11 X11 support no
+
+UI:
+
+MOUSE Mouse support yes
+GPM GPM (mouse) support yes
+EXMODE Exmode (ex/vi CLI) no
+
+Colours:
+
+COLS88 88 Colours no
+COLS256 256 Colours no
+COLSTRUE True Colours no
+
+Scripting:
+
+GUILE no
+PERL no
+PYTHON (python3 required) no
+LUA yes
+
+Protocols:
+
+BITTORRENT no
+DATA yes
+FSP no
+FTP yes
+FINGER no
+GOPHER no
+NNTP no
+SMB no
+
+OPTIONAL:
+
+python3 for python support (still experimental).
diff --git a/network/felinks/felinks.SlackBuild b/network/felinks/felinks.SlackBuild
new file mode 100644
index 0000000000..b503d6ed01
--- /dev/null
+++ b/network/felinks/felinks.SlackBuild
@@ -0,0 +1,196 @@
+#!/bin/sh
+
+# Slackware build script for felinks
+# Copyright 2014 David Woodfall <dave@dawoodfall.net>
+# All rights reserved.
+#
+# Redistribution and use of this script, with or without modification, is
+# permitted provided that the following conditions are met:
+#
+# 1. Redistributions of this script must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY EXPRESS OR IMPLIED
+# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+# EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+PRGNAM=felinks
+VERSION=${VERSION:-0.13.5}
+BUILD=${BUILD:-1}
+TAG=${TAG:-_SBo}
+
+if [ -z "$ARCH" ]; then
+ case "$( uname -m )" in
+ i?86) ARCH=i586 ;;
+ arm*) ARCH=arm ;;
+ *) ARCH=$( uname -m ) ;;
+ esac
+fi
+
+CWD=$(pwd)
+TMP=${TMP:-/tmp/SBo}
+PKG=$TMP/package-$PRGNAM
+OUTPUT=${OUTPUT:-/tmp}
+
+# Added -fno-strict-aliasing -Wno-pointer-sign for a much more peaceful build
+if [ "$ARCH" = "i486" ]; then
+ SLKCFLAGS="-O2 -march=i486 -mtune=i686 -fno-strict-aliasing -Wno-pointer-sign"
+ LIBDIRSUFFIX=""
+elif [ "$ARCH" = "i586" ]; then
+ SLKCFLAGS="-O2 -march=i586 -mtune=i686 -fno-strict-aliasing -Wno-pointer-sign"
+ LIBDIRSUFFIX=""
+elif [ "$ARCH" = "i686" ]; then
+ SLKCFLAGS="-O2 -march=i686 -mtune=i686 -fno-strict-aliasing -Wno-pointer-sign"
+ LIBDIRSUFFIX=""
+elif [ "$ARCH" = "x86_64" ]; then
+ SLKCFLAGS="-O2 -fPIC -fno-strict-aliasing -Wno-pointer-sign"
+ # fix for multilib
+ SLKLDFLAGS="-m64"
+ LIBDIRSUFFIX="64"
+else
+ SLKCFLAGS="-O2"
+ LIBDIRSUFFIX=""
+fi
+
+set -e
+
+rm -rf $PKG
+mkdir -p $TMP $PKG $OUTPUT
+cd $TMP
+rm -rf $PRGNAM-$VERSION
+tar xvf $CWD/$PRGNAM-$VERSION.tar.?z
+cd $PRGNAM-$VERSION
+chown -R root:root .
+find -L . \
+ \( -perm 777 -o -perm 775 -o -perm 750 -o -perm 711 -o -perm 555 \
+ -o -perm 511 \) -exec chmod 755 {} \; -o \
+ \( -perm 666 -o -perm 664 -o -perm 640 -o -perm 600 -o -perm 444 \
+ -o -perm 440 -o -perm 400 \) -exec chmod 644 {} \;
+
+for patch in $CWD/patches/*; do
+ printf "\n%s\n" "Applying Patch $( basename $patch )"
+ patch --verbose -p1 < $patch
+done
+
+## System
+[ "${FASTMEM:-no}" = "yes" ] && fastmem="--enable-fastmem"
+[ "${DEBUG:-no}" = "yes" ] && debug="--enable-debug --disable-fastmem"
+[ "$DEBUG" = "yes" ] && SLKCFLAGS="-ggdb $SLKCFLAGS"
+[ "${CGI:-no}" = "yes" ] && cgi="--enable-cgi"
+[ "${COMBINING:-no}" = "yes" ] && combining="--enable-combining"
+[ "${UTF8:-yes}" = "no" ] && utf8="--disable-utf-8"
+[ "${IPV6:-yes}" = "no" ] && ipv6="--disable-ipv6"
+[ "${HTMLHL:-no}" = "yes" ] && htmlhl="--enable-html-highlight"
+[ "${LZMA:-no}" = "yes" ] && lzma="--with-lzma"
+[ "${TRE:-no}" = "no" ] && tre="--without-tre"
+[ "${BROTLI:-no}" = "no" ] && brotli="--without-brotli"
+[ "${LIBDOM:-no}" = "yes" ] && libdom="--with-libdom"
+[ "${XTERM:-no}" = "no" ] && xterm="--without-xterm"
+[ "$XTERM" = "yes" ] && X11="yes"
+[ "${X11:-no}" = "no" ] && x11="--without-x"
+
+# UI
+[ "${MOUSE:-yes}" = "no" ] && mouse="--disable-mouse"
+[ "${GPM:-yes}" = "no" ] && gpm="--without-gpm"
+[ "${EXMODE:-no}" = "yes" ] && exmode="--enable-exmode"
+
+# Colours
+[ "${COLS88:-no}" = "yes" ] && cols88="--enable-88-colors"
+[ "${COLS256:-no}" = "yes" ] && cols256="--enable-256-colors"
+[ "${COLSTRUE:-no}" = "yes" ] && colstrue="--enable-true-colors"
+
+# Scripting
+[ "${GUILE:-no}" = "yes" ] && guile="--with-guile"
+[ "${PERL:-no}" = "yes" ] && perl="--with-perl"
+[ "${PYTHON:-no}" = "yes" ] && python="--with-python"
+[ "${LUA:-yes}" = "no" ] && lua="--without-lua"
+[ "${ECMA:-yes}" = "no" ] && ecma="--disable-sm-scripting"
+
+# Protocols
+[ "${BITTORRENT:-no}" = "yes" ] && bittorrent="--enable-bittorrent"
+[ "${DATA:-yes}" = "no" ] && data="--disable-data"
+[ "${FSP:-no}" = "yes" ] && fsp="--enable-fsp"
+[ "${FTP:-yes}" = "no" ] && ftp="--disable-ftp"
+[ "${FINGER:-no}" = "yes" ] && finger="--enable-finger"
+[ "${GOPHER:-no}" = "yes" ] && gopher="--enable-gopher"
+[ "${NNTP:-no}" = "yes" ] && nntp="--enable-nntp"
+[ "${SMB:-no}" = "yes" ] && smb="--enable-smb"
+
+./autogen.sh
+CFLAGS="$SLKCFLAGS -L/usr/lib$LIBDIRSUFFIX" \
+LDFLAGS="$SLKLDFLAGS" \
+ ./configure \
+ --prefix=/usr \
+ --libdir=/usr/lib$LIBDIRSUFFIX \
+ --sysconfdir=/etc \
+ --localstatedir=/var \
+ --mandir=/usr/man \
+ --infodir=/usr/info \
+ --docdir=/usr/doc/$PRGNAM-$VERSION \
+ $fastmem \
+ $debug \
+ $cgi \
+ $combining \
+ $utf8 \
+ $ipv6 \
+ $htmlhl \
+ $lzma \
+ $tre \
+ $brotli \
+ $libdom \
+ $xterm \
+ $x11 \
+ $mouse \
+ $gpm \
+ $exmode \
+ $cols88 \
+ $cols256 \
+ $colstrue \
+ $guile \
+ $perl \
+ $python \
+ $lua \
+ $ecma \
+ $bittorrent \
+ $data \
+ $fsp \
+ $ftp \
+ $finger \
+ $gopher \
+ $nntp \
+ $smb \
+ --build=$ARCH-slackware-linux
+
+ make
+ make install DESTDIR=$PKG
+
+# Don't clobber the one supplied by glibc-i18n.
+rm -f $PKG/usr/share/locale/locale.alias
+
+if [ "$DEBUG" = "no" ]; then
+ find $PKG -print0 | xargs -0 file | grep -e "executable" -e "shared object" |
+ grep ELF | cut -f 1 -d : | xargs strip --strip-unneeded 2> /dev/null || true
+fi
+
+find $PKG/usr/man -type f -exec gzip -9 {} \;
+for i in $( find $PKG/usr/man -type l ) ; do ln -s $( readlink $i ).gz $i.gz ; rm $i ; done
+
+mkdir -p $PKG/usr/doc/$PRGNAM-$VERSION
+cp -a \
+ AUTHORS BUGS COPYING NEWS README SITES THANKS TODO \
+ ChangeLog doc/*txt contrib \
+ $PKG/usr/doc/$PRGNAM-$VERSION
+cat $CWD/$PRGNAM.SlackBuild > $PKG/usr/doc/$PRGNAM-$VERSION/$PRGNAM.SlackBuild
+
+mkdir -p $PKG/install
+cat $CWD/slack-desc > $PKG/install/slack-desc
+
+cd $PKG
+/sbin/makepkg -l y -c n $OUTPUT/$PRGNAM-$VERSION-$ARCH-$BUILD$TAG.${PKGTYPE:-tgz}
diff --git a/network/felinks/felinks.info b/network/felinks/felinks.info
new file mode 100644
index 0000000000..fd41cb6e6a
--- /dev/null
+++ b/network/felinks/felinks.info
@@ -0,0 +1,10 @@
+PRGNAM="felinks"
+VERSION="0.13.5"
+HOMEPAGE="https://github.com/rkd77/felinks"
+DOWNLOAD="https://github.com/rkd77/felinks/archive/v0.13.5/felinks-0.13.5.tar.gz"
+MD5SUM="ac27ad36cadcd705506290fcb5ab6031"
+DOWNLOAD_x86_64=""
+MD5SUM_x86_64=""
+REQUIRES=""
+MAINTAINER="Dave Woodfall"
+EMAIL="dave@slackbuilds.org"
diff --git a/network/felinks/patches/0001-gopher_html_links.patch b/network/felinks/patches/0001-gopher_html_links.patch
new file mode 100644
index 0000000000..38a2dd0b10
--- /dev/null
+++ b/network/felinks/patches/0001-gopher_html_links.patch
@@ -0,0 +1,37 @@
+################################################################
+# Fix for HTML links that contain URL:http://
+# dave@slackbuilds.org
+###############################################################
+diff -Naur a/src/protocol/gopher/gopher.c b/src/protocol/gopher/gopher.c
+--- a/src/protocol/gopher/gopher.c 2013-12-18 15:38:57.000000000 +0000
++++ b/src/protocol/gopher/gopher.c 2020-01-08 05:34:02.300498220 +0000
+@@ -277,6 +277,10 @@
+ struct string command;
+ enum gopher_entity entity = DEFAULT_GOPHER_ENTITY;
+ unsigned char *selector = conn->uri->data;
++ unsigned char const* URI = "hURI%3";
++ unsigned char const* URL = "hURL%3";
++ unsigned char const* CURI = "HURI%3";
++ unsigned char const* CURL = "HURL%3";
+ int selectorlen = conn->uri->datalen;
+ struct gopher_entity_info *entity_info;
+ size_t size;
+@@ -288,6 +292,18 @@
+ selectorlen--;
+ }
+
++ if(strstr(selector, URL) != NULL || strstr(selector, URI) != NULL) {
++ entity = GOPHER_HTML;
++ selector++;
++ selectorlen--;
++ }
++
++ if(strstr(selector, CURL) != NULL || strstr(selector, CURI) != NULL) {
++ entity = GOPHER_CHTML;
++ selector++;
++ selectorlen--;
++ }
++
+ /* This is probably a hack. It serves as a work around when no entity is
+ * available in the Gopher URI. Instead of segfaulting later the content
+ * will be served as application/octet-stream. However, it could
diff --git a/network/felinks/patches/0002-gopher_index_queries.patch b/network/felinks/patches/0002-gopher_index_queries.patch
new file mode 100644
index 0000000000..662fd13a7f
--- /dev/null
+++ b/network/felinks/patches/0002-gopher_index_queries.patch
@@ -0,0 +1,113 @@
+#######################################################################
+# Fix for type 7 entities.
+# dave@slackbuilds.org
+#######################################################################
+diff -Naur '--exclude=.git' bb/src/protocol/gopher/gopher.c cc/src/protocol/gopher/gopher.c
+--- bb/src/protocol/gopher/gopher.c 2020-01-13 22:35:13.663935305 +0000
++++ cc/src/protocol/gopher/gopher.c 2020-01-13 23:16:00.053003768 +0000
+@@ -197,7 +197,7 @@
+ command->length = strlen(command->source);
+ }
+
+-static struct connection_state init_gopher_index_cache_entry(struct connection *conn);
++/* static struct connection_state init_gopher_index_cache_entry(struct connection *conn); */
+
+ static struct connection_state
+ add_gopher_command(struct connection *conn, struct string *command,
+@@ -205,7 +205,7 @@
+ unsigned char *selector, int selectorlen)
+ {
+ unsigned char *query;
+- int querylen;
++ int querylen = 0;
+
+ if (!init_string(command))
+ return connection_state(S_OUT_OF_MEM);
+@@ -218,13 +218,14 @@
+ /* Exclude '?' */
+ if (query) selectorlen -= 1;
+ query = NULL;
+- querylen = 0;
+- } else {
+- query += 1;
++ } else if (entity == GOPHER_INDEX) {
++ /* fix query size to not include the search= part */
++ query += 8;
+ querylen = selector + selectorlen - query;
+ /* Exclude '?' */
+- selectorlen -= querylen + 1;
+- if (querylen >= 7 && !c_strncasecmp(query, "search=", 7)) {
++ /* fix selector length to fit with query */
++ selectorlen -= querylen + 8;
++ if (querylen >= 7 && !c_strncasecmp(query, "submit=", 7)) {
+ query += 7;
+ querylen -= 7;
+ }
+@@ -233,9 +234,11 @@
+ switch (entity) {
+ case GOPHER_INDEX:
+ /* No search required? */
++ /* Don't display the form page */
+ if (!query) {
+ done_string(command);
+- return init_gopher_index_cache_entry(conn);
++ add_uri_decoded(command, selector, selectorlen, 0);
++ break;
+ }
+
+ add_uri_decoded(command, selector, selectorlen, 0);
+@@ -371,13 +374,14 @@
+ add_gopher_search_field(struct string *buffer, const unsigned char *text,
+ const unsigned char *addr)
+ {
++ /* Not *every* query is a search! */
+ add_format_to_string(buffer,
+ "<form action=\"%s\">"
+ "<table>"
+ "<td> </td>"
+ "<td>%s:</td>"
+- "<td><input maxlength=\"256\" name=\"search\" value=\"\"></td>"
+- "<td><input type=submit value=\"Search\"></td>"
++ "<td><input maxlength=\"256\" name=\"submit\" value=\"\"></td>"
++ "<td><input type=submit value=\"Submit\"></td>"
+ "</table>"
+ "</form>",
+ addr, text);
+@@ -662,6 +666,7 @@
+ }
+
+ /* Display a Gopher Index document. */
++/* Use the page that the gopher site sends us
+ static struct connection_state
+ init_gopher_index_cache_entry(struct connection *conn)
+ {
+@@ -674,9 +679,9 @@
+
+ where = get_uri_string(conn->uri, URI_PUBLIC);
+
+- /* TODO: Use different function when using UTF-8
++ TODO: Use different function when using UTF-8
+ * in terminal (decode_uri_for_display replaces
+- * bytes of UTF-8 characters width '*'). */
++ * bytes of UTF-8 characters width '*'). *
+ if (where) decode_uri_for_display(where);
+
+ add_format_to_string(&buffer,
+@@ -695,7 +700,7 @@
+
+ mem_free_if(where);
+
+- /* FIXME: I think this needs a form or something */
++ * FIXME: I think this needs a form or something *
+
+ add_fragment(conn->cached, conn->from, buffer.source, buffer.length);
+ conn->from += buffer.length;
+@@ -707,7 +712,7 @@
+ ? connection_state(S_OK)
+ : connection_state(S_OUT_OF_MEM);
+ }
+-
++*/
+
+ static void
+ read_gopher_response_data(struct socket *socket, struct read_buffer *rb)
diff --git a/network/felinks/patches/0003-gopher_directory_links.patch b/network/felinks/patches/0003-gopher_directory_links.patch
new file mode 100644
index 0000000000..15a89fac2f
--- /dev/null
+++ b/network/felinks/patches/0003-gopher_directory_links.patch
@@ -0,0 +1,26 @@
+#######################################################################
+# Fix remote directory links.
+# dave@slackbuilds.org
+#######################################################################
+diff -Naur -x .git bb/src/protocol/gopher/gopher.c cc/src/protocol/gopher/gopher.c
+--- bb/src/protocol/gopher/gopher.c 2020-01-13 23:22:18.918292198 +0000
++++ cc/src/protocol/gopher/gopher.c 2020-01-13 23:21:00.631960039 +0000
+@@ -321,6 +321,18 @@
+ selectorlen++;
+ }
+
++ if (entity_info->type == '1') {
++ if (strchr(selector, '1') == (char *) selector) {
++ selector++;
++ selectorlen--;
++ }
++ else {
++ if ((char *) selector == "/1") {
++ selectorlen--;
++ }
++ }
++ }
++
+ state = add_gopher_command(conn, &command, entity, selector, selectorlen);
+ if (!is_in_state(state, S_CONN))
+ return state;
diff --git a/network/felinks/patches/0005-gopher_newlines_tabs_entity-2.patch b/network/felinks/patches/0005-gopher_newlines_tabs_entity-2.patch
new file mode 100644
index 0000000000..2885a67e76
--- /dev/null
+++ b/network/felinks/patches/0005-gopher_newlines_tabs_entity-2.patch
@@ -0,0 +1,50 @@
+diff -Naur a/src/protocol/gopher/gopher.c b/src/protocol/gopher/gopher.c
+--- a/src/protocol/gopher/gopher.c 2020-01-31 16:50:36.000000000 +0000
++++ b/src/protocol/gopher/gopher.c 2020-05-14 06:21:44.523952135 +0000
+@@ -283,7 +283,7 @@
+
+ /* Get entity type, and selector string. */
+ /* Pick up gopher_entity */
+- if (selectorlen > 1 && selector[1] == '/') {
++ if (selectorlen > 1) {
+ entity = *selector++;
+ selectorlen--;
+ }
+@@ -308,6 +308,18 @@
+ selectorlen--;
+ }
+
++ if (entity_info->type == '1') {
++ if (strchr(selector, '1') == (char *) selector) {
++ selector++;
++ selectorlen--;
++ }
++ else {
++ if ((char *) selector == "/1") {
++ selectorlen--;
++ }
++ }
++ }
++
+ state = add_gopher_command(conn, &command, entity, selector, selectorlen);
+ if (!is_in_state(state, S_CONN))
+ return state;
+@@ -548,7 +560,8 @@
+
+ } else if (address.length > 0
+ && strlcmp(address.source, address.length - 1,
+- "gopher://error.host:1/", -1)) {
++ "gopher://error.host:1/", -1)
++ && selector) {
+ add_gopher_link(buffer, name, address.source);
+
+ } else {
+@@ -571,7 +584,7 @@
+ if (data[0] == ASCII_CR && data[1] == ASCII_LF)
+ return data + 2;
+
+- if (data[0] == ASCII_LF)
++ if (data[0] == ASCII_CR || data[0] == ASCII_LF)
+ return data + 1;
+ }
+
diff --git a/network/felinks/patches/0006-gopher-indexes_nocr.patch b/network/felinks/patches/0006-gopher-indexes_nocr.patch
new file mode 100644
index 0000000000..9e4a441db6
--- /dev/null
+++ b/network/felinks/patches/0006-gopher-indexes_nocr.patch
@@ -0,0 +1,19 @@
+#######################################################################
+# Fix index listings with only LF and no CRs.
+# dave@slackbuilds.org
+#######################################################################
+diff -Naur '--exclude=.git' bb/src/protocol/gopher/gopher.c cc/src/protocol/gopher/gopher.c
+--- bb/src/protocol/gopher/gopher.c 2020-01-14 06:42:11.030536586 +0000
++++ cc/src/protocol/gopher/gopher.c 2020-01-14 06:42:26.710000886 +0000
+@@ -757,6 +757,11 @@
+ switch (gopher->entity->type) {
+ case GOPHER_DIRECTORY:
+ case GOPHER_INDEX:
++ /* Lines with no carriage returns */
++ if (strchr(rb->data, ASCII_CR) == NULL) {
++ strncat(rb->data, "\r\n", 2);
++ rb->length += 3;
++ }
+ state = read_gopher_directory_data(conn, rb);
+ break;
+
diff --git a/network/felinks/patches/0008-gopher-html-entities.patch b/network/felinks/patches/0008-gopher-html-entities.patch
new file mode 100644
index 0000000000..750d1a49de
--- /dev/null
+++ b/network/felinks/patches/0008-gopher-html-entities.patch
@@ -0,0 +1,47 @@
+###################################################################
+# Encode < > to HTML.
+###################################################################
+diff -Naur '--exclude=.git' bb/src/protocol/gopher/gopher.c cc/src/protocol/gopher/gopher.c
+--- bb/src/protocol/gopher/gopher.c 2020-01-14 03:26:41.791778387 +0000
++++ cc/src/protocol/gopher/gopher.c 2020-01-14 06:19:56.964025440 +0000
+@@ -620,6 +620,25 @@
+ return line[0] == '.' && !line[1] ? NULL : line;
+ }
+
++/* substring replacement */
++static void
++str_replace(char * in_string, char * s_string, char * r_string)
++{
++ /* max == replace all characters */
++ char temp[strlen(in_string) * (strlen(r_string) - strlen(s_string)) + 1];
++ char * pos;
++
++ if (!(pos = strstr(in_string, s_string)))
++ return;
++
++ strncpy(temp, in_string, pos - in_string);
++ temp[pos - in_string] = 0;
++ sprintf(temp + (pos - in_string), "%s%s", r_string, pos + 1);
++ in_string[0] = 0;
++ strcpy(in_string, temp);
++ return str_replace(in_string, s_string, r_string);
++}
++
+ /* Parse a Gopher Menu document */
+ static struct connection_state
+ read_gopher_directory_data(struct connection *conn, struct read_buffer *rb)
+@@ -639,6 +658,14 @@
+ return connection_state(S_OUT_OF_MEM);
+ }
+
++ /* Lines with characters that need to be converted to html */
++ if (strstr(rb->data, "<")) {
++ str_replace(rb->data, "<", "&lt;");
++ }
++ if (strstr(rb->data, ">")) {
++ str_replace(rb->data, ">", "&gt;");
++ }
++
+ while ((end = get_gopher_line_end(rb->data, rb->length))) {
+ unsigned char *line = check_gopher_last_line(rb->data, end);
+
diff --git a/network/felinks/slack-desc b/network/felinks/slack-desc
new file mode 100644
index 0000000000..1a0bba4cc9
--- /dev/null
+++ b/network/felinks/slack-desc
@@ -0,0 +1,19 @@
+# HOW TO EDIT THIS FILE:
+# The "handy ruler" below makes it easier to edit a package description. Line
+# up the first '|' above the ':' following the base package name, and the '|'
+# on the right side marks the last column you can put a character in. You must
+# make exactly 11 lines for the formatting to be correct. It's also
+# customary to leave one space after the ':'.
+
+ |-----handy-ruler------------------------------------------------------|
+felinks: felinks (A fork of Elinks, the web browser)
+felinks:
+felinks: Felinks is a maintained and up-to-date fork of ELinks, an advanced
+felinks: web browser.
+felinks:
+felinks: https://github.com/rkd77/felinks
+felinks:
+felinks:
+felinks:
+felinks:
+felinks: