mirror of
https://git.sr.ht/~sircmpwn/gmni
synced 2024-11-22 20:32:03 +01:00
Add static library for gmni
This commit is contained in:
parent
49c0c523c6
commit
122fb0a9fd
2
.gitignore
vendored
2
.gitignore
vendored
@ -4,3 +4,5 @@ gmni
|
||||
gmnlm
|
||||
*.1
|
||||
*.o
|
||||
*.a
|
||||
*.pc
|
||||
|
27
Makefile
27
Makefile
@ -1,6 +1,7 @@
|
||||
.POSIX:
|
||||
.SUFFIXES:
|
||||
OUTDIR=.build
|
||||
VERSION=0.0.0
|
||||
include $(OUTDIR)/config.mk
|
||||
include $(OUTDIR)/cppcache
|
||||
|
||||
@ -12,9 +13,26 @@ gmnlm: $(gmnlm_objects)
|
||||
@printf 'CCLD\t$@\n'
|
||||
@$(CC) $(LDFLAGS) -o $@ $(gmnlm_objects) $(LIBS)
|
||||
|
||||
libgmni.a: $(libgmni.a_objects)
|
||||
@printf 'AR\t$@\n'
|
||||
@$(AR) -rcs $@ $(libgmni.a_objects)
|
||||
|
||||
doc/gmni.1: doc/gmni.scd
|
||||
doc/gmnlm.1: doc/gmnlm.scd
|
||||
|
||||
libgmni.pc:
|
||||
@printf 'GEN\t$@\n'
|
||||
@printf 'prefix=%s\n' "$(PREFIX)" > $@
|
||||
@printf 'exec_prefix=$${prefix}\n' >> $@
|
||||
@printf 'includedir=$${prefix}/include\n' >> $@
|
||||
@printf 'libdir=$${prefix}/lib\n' >> $@
|
||||
@printf 'Name: libgmni\n' >> $@
|
||||
@printf 'Version: %s\n' "$(VERSION)" >> $@
|
||||
@printf 'Description: The gmni client library\n' >> $@
|
||||
@printf 'Requires: libssl libcrypto\n' >> $@
|
||||
@printf 'Cflags: -I$${includedir}/gmni\n' >> $@
|
||||
@printf 'Libs: -L$${libdir} -lgmni\n' >> $@
|
||||
|
||||
.SUFFIXES: .c .o .scd .1
|
||||
|
||||
.c.o:
|
||||
@ -22,7 +40,7 @@ doc/gmnlm.1: doc/gmnlm.scd
|
||||
@touch $(OUTDIR)/cppcache
|
||||
@grep $< $(OUTDIR)/cppcache >/dev/null || \
|
||||
$(CPP) $(CFLAGS) -MM -MT $@ $< >> $(OUTDIR)/cppcache
|
||||
@$(CC) -c $(CFLAGS) -o $@ $<
|
||||
@$(CC) -c -fPIC $(CFLAGS) -o $@ $<
|
||||
|
||||
.scd.1:
|
||||
@printf 'SCDOC\t$@\n'
|
||||
@ -31,7 +49,7 @@ doc/gmnlm.1: doc/gmnlm.scd
|
||||
docs: doc/gmni.1 doc/gmnlm.1
|
||||
|
||||
clean:
|
||||
@rm -f gmni gmnlm doc/gmni.1 doc/gmnlm.1 $(gmnlm_objects) $(gmni_objects)
|
||||
@rm -f gmni gmnlm libgmni.a libgmni.pc doc/gmni.1 doc/gmnlm.1 $(gmnlm_objects) $(gmni_objects)
|
||||
|
||||
distclean: clean
|
||||
@rm -rf "$(OUTDIR)"
|
||||
@ -41,6 +59,11 @@ install: all
|
||||
mkdir -p $(MANDIR)/man1
|
||||
install -Dm755 gmni $(BINDIR)/gmni
|
||||
install -Dm755 gmnlm $(BINDIR)/gmnlm
|
||||
install -Dm755 libgmni.a $(LIBDIR)/libgmni.a
|
||||
install -Dm644 include/gmni/gmni.h $(INCLUDEDIR)/gmni/gmni.h
|
||||
install -Dm644 include/gmni/tofu.h $(INCLUDEDIR)/gmni/tofu.h
|
||||
install -Dm644 include/gmni/url.h $(INCLUDEDIR)/gmni/url.h
|
||||
install -Dm644 libgmni.pc $(LIBDIR)/pkgconfig
|
||||
install -Dm644 doc/gmni.1 $(MANDIR)/man1/gmni.1
|
||||
install -Dm644 doc/gmnlm.1 $(MANDIR)/man1/gmnlm.1
|
||||
|
||||
|
@ -134,6 +134,7 @@ run_configure() {
|
||||
_INSTDIR=\$(DESTDIR)\$(PREFIX)
|
||||
BINDIR?=${BINDIR:-\$(_INSTDIR)/bin}
|
||||
LIBDIR?=${LIBDIR:-\$(_INSTDIR)/lib}
|
||||
INCLUDEDIR?=${INCLUDEDIR:-\$(_INSTDIR)/include}
|
||||
MANDIR?=${MANDIR:-\$(_INSTDIR)/share/man}
|
||||
CACHE=\$(OUTDIR)/cache
|
||||
CFLAGS=${CFLAGS}
|
||||
@ -146,7 +147,7 @@ run_configure() {
|
||||
|
||||
for target in $all
|
||||
do
|
||||
$target >>"$outdir"/config.mk
|
||||
${target//./_} >>"$outdir"/config.mk
|
||||
done
|
||||
echo done
|
||||
|
||||
|
17
configure
vendored
17
configure
vendored
@ -23,6 +23,21 @@ gmnlm() {
|
||||
src/util.c
|
||||
}
|
||||
|
||||
all="gmni gmnlm"
|
||||
libgmni_a() {
|
||||
genrules libgmni.a \
|
||||
src/client.c \
|
||||
src/escape.c \
|
||||
src/tofu.c \
|
||||
src/url.c \
|
||||
src/util.c \
|
||||
src/parser.c
|
||||
}
|
||||
|
||||
libgmni_pc() {
|
||||
:
|
||||
}
|
||||
|
||||
all="gmni gmnlm libgmni.a libgmni.pc"
|
||||
|
||||
|
||||
run_configure
|
||||
|
164
include/gmni.h
164
include/gmni.h
@ -1,164 +0,0 @@
|
||||
#ifndef GEMINI_CLIENT_H
|
||||
#define GEMINI_CLIENT_H
|
||||
#include <netdb.h>
|
||||
#include <openssl/ssl.h>
|
||||
#include <stdbool.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
enum gemini_result {
|
||||
GEMINI_OK,
|
||||
GEMINI_ERR_OOM,
|
||||
GEMINI_ERR_INVALID_URL,
|
||||
GEMINI_ERR_NOT_GEMINI,
|
||||
GEMINI_ERR_RESOLVE,
|
||||
GEMINI_ERR_CONNECT,
|
||||
GEMINI_ERR_SSL,
|
||||
GEMINI_ERR_SSL_VERIFY,
|
||||
GEMINI_ERR_IO,
|
||||
GEMINI_ERR_PROTOCOL,
|
||||
};
|
||||
|
||||
enum gemini_status {
|
||||
GEMINI_STATUS_INPUT = 10,
|
||||
GEMINI_STATUS_SENSITIVE_INPUT = 11,
|
||||
GEMINI_STATUS_SUCCESS = 20,
|
||||
GEMINI_STATUS_REDIRECT_TEMPORARY = 30,
|
||||
GEMINI_STATUS_REDIRECT_PERMANENT = 31,
|
||||
GEMINI_STATUS_TEMPORARY_FAILURE = 40,
|
||||
GEMINI_STATUS_SERVER_UNAVAILABLE = 41,
|
||||
GEMINI_STATUS_CGI_ERROR = 42,
|
||||
GEMINI_STATUS_PROXY_ERROR = 43,
|
||||
GEMINI_STATUS_SLOW_DOWN = 44,
|
||||
GEMINI_STATUS_PERMANENT_FAILURE = 50,
|
||||
GEMINI_STATUS_NOT_FOUND = 51,
|
||||
GEMINI_STATUS_GONE = 52,
|
||||
GEMINI_STATUS_PROXY_REQUEST_REFUSED = 53,
|
||||
GEMINI_STATUS_BAD_REQUEST = 59,
|
||||
GEMINI_STATUS_CLIENT_CERTIFICATE_REQUIRED = 60,
|
||||
GEMINI_STATUS_CERTIFICATE_NOT_AUTHORIZED = 61,
|
||||
GEMINI_STATUS_CERTIFICATE_NOT_VALID = 62,
|
||||
};
|
||||
|
||||
enum gemini_status_class {
|
||||
GEMINI_STATUS_CLASS_INPUT = 10,
|
||||
GEMINI_STATUS_CLASS_SUCCESS = 20,
|
||||
GEMINI_STATUS_CLASS_REDIRECT = 30,
|
||||
GEMINI_STATUS_CLASS_TEMPORARY_FAILURE = 40,
|
||||
GEMINI_STATUS_CLASS_PERMANENT_FAILURE = 50,
|
||||
GEMINI_STATUS_CLASS_CLIENT_CERTIFICATE_REQUIRED = 60,
|
||||
};
|
||||
|
||||
struct gemini_response {
|
||||
enum gemini_status status;
|
||||
char *meta;
|
||||
|
||||
// Response body may be read from here if appropriate:
|
||||
BIO *bio;
|
||||
|
||||
// Connection state
|
||||
SSL_CTX *ssl_ctx;
|
||||
SSL *ssl;
|
||||
int fd;
|
||||
};
|
||||
|
||||
struct gemini_options {
|
||||
// If NULL, an SSL context will be created. If unset, the ssl field
|
||||
// must also be NULL.
|
||||
SSL_CTX *ssl_ctx;
|
||||
|
||||
// If ai_family != AF_UNSPEC (the default value on most systems), the
|
||||
// client will connect to this address and skip name resolution.
|
||||
struct addrinfo *addr;
|
||||
|
||||
// If non-NULL, these hints are provided to getaddrinfo. Useful, for
|
||||
// example, to force IPv4/IPv6.
|
||||
struct addrinfo *hints;
|
||||
};
|
||||
|
||||
// Requests the specified URL via the gemini protocol. If options is non-NULL,
|
||||
// it may specify some additional configuration to adjust client behavior.
|
||||
//
|
||||
// Returns a value indicating the success of the request.
|
||||
//
|
||||
// Caller must call gemini_response_finish afterwards to clean up resources
|
||||
// before exiting or re-using it for another request.
|
||||
enum gemini_result gemini_request(const char *url,
|
||||
struct gemini_options *options,
|
||||
struct gemini_response *resp);
|
||||
|
||||
// Must be called after gemini_request in order to free up the resources
|
||||
// allocated during the request.
|
||||
void gemini_response_finish(struct gemini_response *resp);
|
||||
|
||||
// Returns a user-friendly string describing an error.
|
||||
const char *gemini_strerr(enum gemini_result r, struct gemini_response *resp);
|
||||
|
||||
// Returns the given URL with the input response set to the specified value.
|
||||
// The caller must free the string.
|
||||
char *gemini_input_url(const char *url, const char *input);
|
||||
|
||||
// Returns the general response class (i.e. with the second digit set to zero)
|
||||
// of the given Gemini status code.
|
||||
enum gemini_status_class gemini_response_class(enum gemini_status status);
|
||||
|
||||
enum gemini_tok {
|
||||
GEMINI_TEXT,
|
||||
GEMINI_LINK,
|
||||
GEMINI_PREFORMATTED_BEGIN,
|
||||
GEMINI_PREFORMATTED_END,
|
||||
GEMINI_PREFORMATTED_TEXT,
|
||||
GEMINI_HEADING,
|
||||
GEMINI_LIST_ITEM,
|
||||
GEMINI_QUOTE,
|
||||
};
|
||||
|
||||
struct gemini_token {
|
||||
enum gemini_tok token;
|
||||
|
||||
// The token field determines which of the union members is valid.
|
||||
union {
|
||||
char *text;
|
||||
|
||||
struct {
|
||||
char *text;
|
||||
char *url; // May be NULL
|
||||
} link;
|
||||
|
||||
char *preformatted;
|
||||
|
||||
struct {
|
||||
char *title;
|
||||
int level; // 1, 2, or 3
|
||||
} heading;
|
||||
|
||||
char *list_item;
|
||||
char *quote_text;
|
||||
};
|
||||
};
|
||||
|
||||
struct gemini_parser {
|
||||
BIO *f;
|
||||
char *buf;
|
||||
size_t bufsz;
|
||||
size_t bufln;
|
||||
bool preformatted;
|
||||
};
|
||||
|
||||
// Initializes a text/gemini parser which reads from the specified BIO.
|
||||
void gemini_parser_init(struct gemini_parser *p, BIO *f);
|
||||
|
||||
// Finishes this text/gemini parser and frees up its resources.
|
||||
void gemini_parser_finish(struct gemini_parser *p);
|
||||
|
||||
// Reads the next token from a text/gemini file.
|
||||
//
|
||||
// Returns 0 on success, 1 on EOF, and -1 on failure.
|
||||
//
|
||||
// Caller must call gemini_token_finish before exiting or re-using the token
|
||||
// parameter.
|
||||
int gemini_parser_next(struct gemini_parser *p, struct gemini_token *token);
|
||||
|
||||
// Must be called after gemini_next to free up resources for the next token.
|
||||
void gemini_token_finish(struct gemini_token *token);
|
||||
|
||||
#endif
|
@ -1,49 +0,0 @@
|
||||
#ifndef GEMINI_TOFU_H
|
||||
#define GEMINI_TOFU_H
|
||||
#include <limits.h>
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <time.h>
|
||||
|
||||
enum tofu_error {
|
||||
TOFU_VALID,
|
||||
// Expired, wrong CN, etc.
|
||||
TOFU_INVALID_CERT,
|
||||
// Cert is valid but we haven't seen it before
|
||||
TOFU_UNTRUSTED_CERT,
|
||||
// Cert is valid but we already trust another cert for this host
|
||||
TOFU_FINGERPRINT_MISMATCH,
|
||||
};
|
||||
|
||||
enum tofu_action {
|
||||
TOFU_ASK,
|
||||
TOFU_FAIL,
|
||||
TOFU_TRUST_ONCE,
|
||||
TOFU_TRUST_ALWAYS,
|
||||
};
|
||||
|
||||
struct known_host {
|
||||
char *host, *fingerprint;
|
||||
time_t expires;
|
||||
int lineno;
|
||||
struct known_host *next;
|
||||
};
|
||||
|
||||
// Called when the user needs to be prompted to agree to trust an unknown
|
||||
// certificate. Return true to trust this certificate.
|
||||
typedef enum tofu_action (tofu_callback_t)(enum tofu_error error,
|
||||
const char *fingerprint, struct known_host *host, void *data);
|
||||
|
||||
struct gemini_tofu {
|
||||
char known_hosts_path[PATH_MAX+1];
|
||||
struct known_host *known_hosts;
|
||||
int lineno;
|
||||
tofu_callback_t *callback;
|
||||
void *cb_data;
|
||||
};
|
||||
|
||||
void gemini_tofu_init(struct gemini_tofu *tofu,
|
||||
SSL_CTX *ssl_ctx, tofu_callback_t *cb, void *data);
|
||||
void gemini_tofu_finish(struct gemini_tofu *tofu);
|
||||
|
||||
#endif
|
103
include/url.h
103
include/url.h
@ -1,103 +0,0 @@
|
||||
#ifndef URLAPI_H
|
||||
#define URLAPI_H
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
* are also available at https://curl.haxx.se/docs/copyright.html.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the COPYING file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
/* the error codes for the URL API */
|
||||
typedef enum {
|
||||
CURLUE_OK,
|
||||
CURLUE_BAD_HANDLE, /* 1 */
|
||||
CURLUE_BAD_PARTPOINTER, /* 2 */
|
||||
CURLUE_MALFORMED_INPUT, /* 3 */
|
||||
CURLUE_BAD_PORT_NUMBER, /* 4 */
|
||||
CURLUE_UNSUPPORTED_SCHEME, /* 5 */
|
||||
CURLUE_URLDECODE, /* 6 */
|
||||
CURLUE_OUT_OF_MEMORY, /* 7 */
|
||||
CURLUE_USER_NOT_ALLOWED, /* 8 */
|
||||
CURLUE_UNKNOWN_PART, /* 9 */
|
||||
CURLUE_NO_SCHEME, /* 10 */
|
||||
CURLUE_NO_USER, /* 11 */
|
||||
CURLUE_NO_PASSWORD, /* 12 */
|
||||
CURLUE_NO_OPTIONS, /* 13 */
|
||||
CURLUE_NO_HOST, /* 14 */
|
||||
CURLUE_NO_PORT, /* 15 */
|
||||
CURLUE_NO_QUERY, /* 16 */
|
||||
CURLUE_NO_FRAGMENT /* 17 */
|
||||
} CURLUcode;
|
||||
|
||||
typedef enum {
|
||||
CURLUPART_URL,
|
||||
CURLUPART_SCHEME,
|
||||
CURLUPART_USER,
|
||||
CURLUPART_PASSWORD,
|
||||
CURLUPART_OPTIONS,
|
||||
CURLUPART_HOST,
|
||||
CURLUPART_PORT,
|
||||
CURLUPART_PATH,
|
||||
CURLUPART_QUERY,
|
||||
CURLUPART_FRAGMENT
|
||||
} CURLUPart;
|
||||
|
||||
#define CURLU_PATH_AS_IS (1<<4) /* leave dot sequences */
|
||||
#define CURLU_DISALLOW_USER (1<<5) /* no user+password allowed */
|
||||
#define CURLU_URLDECODE (1<<6) /* URL decode on get */
|
||||
#define CURLU_URLENCODE (1<<7) /* URL encode on set */
|
||||
#define CURLU_APPENDQUERY (1<<8) /* append a form style part */
|
||||
|
||||
typedef struct Curl_URL CURLU;
|
||||
|
||||
/*
|
||||
* curl_url() creates a new CURLU handle and returns a pointer to it.
|
||||
* Must be freed with curl_url_cleanup().
|
||||
*/
|
||||
struct Curl_URL *curl_url(void);
|
||||
|
||||
/*
|
||||
* curl_url_cleanup() frees the CURLU handle and related resources used for
|
||||
* the URL parsing. It will not free strings previously returned with the URL
|
||||
* API.
|
||||
*/
|
||||
void curl_url_cleanup(struct Curl_URL *handle);
|
||||
|
||||
/*
|
||||
* curl_url_dup() duplicates a CURLU handle and returns a new copy. The new
|
||||
* handle must also be freed with curl_url_cleanup().
|
||||
*/
|
||||
struct Curl_URL *curl_url_dup(struct Curl_URL *in);
|
||||
|
||||
/*
|
||||
* curl_url_get() extracts a specific part of the URL from a CURLU
|
||||
* handle. Returns error code. The returned pointer MUST be freed with
|
||||
* free() afterwards.
|
||||
*/
|
||||
CURLUcode curl_url_get(struct Curl_URL *handle, CURLUPart what,
|
||||
char **part, unsigned int flags);
|
||||
|
||||
/*
|
||||
* curl_url_set() sets a specific part of the URL in a CURLU handle. Returns
|
||||
* error code. The passed in string will be copied. Passing a NULL instead of
|
||||
* a part string, clears that part.
|
||||
*/
|
||||
CURLUcode curl_url_set(struct Curl_URL *handle, CURLUPart what,
|
||||
const char *part, unsigned int flags);
|
||||
|
||||
#endif
|
@ -9,8 +9,8 @@
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include "gmni.h"
|
||||
#include "url.h"
|
||||
#include <gmni/gmni.h>
|
||||
#include <gmni/url.h>
|
||||
|
||||
static enum gemini_result
|
||||
gemini_get_addrinfo(struct Curl_URL *uri, struct gemini_options *options,
|
||||
|
@ -12,8 +12,8 @@
|
||||
#include <sys/types.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
#include "gmni.h"
|
||||
#include "tofu.h"
|
||||
#include <gmni/gmni.h>
|
||||
#include <gmni/tofu.h>
|
||||
#include "util.h"
|
||||
|
||||
static void
|
||||
|
@ -14,9 +14,9 @@
|
||||
#include <sys/wait.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
#include "gmni.h"
|
||||
#include "tofu.h"
|
||||
#include "url.h"
|
||||
#include <gmni/gmni.h>
|
||||
#include <gmni/tofu.h>
|
||||
#include <gmni/url.h>
|
||||
#include "util.h"
|
||||
|
||||
struct link {
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "gmni.h"
|
||||
#include <gmni/gmni.h>
|
||||
|
||||
void
|
||||
gemini_parser_init(struct gemini_parser *p, BIO *f)
|
||||
|
@ -10,8 +10,8 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include "gmni.h"
|
||||
#include "tofu.h"
|
||||
#include <gmni/gmni.h>
|
||||
#include <gmni/tofu.h>
|
||||
#include "util.h"
|
||||
|
||||
static int
|
||||
|
@ -31,7 +31,7 @@
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include "escape.h"
|
||||
#include "url.h"
|
||||
#include <gmni/url.h>
|
||||
|
||||
/* Provided by gmni */
|
||||
static char *
|
||||
|
@ -7,7 +7,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include "gmni.h"
|
||||
#include <gmni/gmni.h>
|
||||
#include "util.h"
|
||||
|
||||
static void
|
||||
|
Loading…
Reference in New Issue
Block a user