mirror of
https://forge.fsky.io/lda/Parsee.git
synced 2026-03-13 13:45:10 +00:00
[MOD] Import PNG media.
This commit is contained in:
parent
9d9453f96a
commit
1f3d738bb4
12 changed files with 87 additions and 42 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -18,3 +18,4 @@ tags
|
||||||
|
|
||||||
# Whitelists
|
# Whitelists
|
||||||
!etc/*
|
!etc/*
|
||||||
|
!etc/**
|
||||||
|
|
|
||||||
18
Makefile
18
Makefile
|
|
@ -2,6 +2,9 @@
|
||||||
# ================================
|
# ================================
|
||||||
# TODO: Consider making something akin to a configure script that checks
|
# TODO: Consider making something akin to a configure script that checks
|
||||||
# for dependencies, or maybe even use *autoconf* (the devil!)
|
# for dependencies, or maybe even use *autoconf* (the devil!)
|
||||||
|
#
|
||||||
|
# TODO: Either get rid of the GNU extensions, or use a script/program
|
||||||
|
# to build Parsee on a POSIXly environment. I'd dig parsee-buildout, tbf.
|
||||||
|
|
||||||
|
|
||||||
# =========================== Parsee Flags =============================
|
# =========================== Parsee Flags =============================
|
||||||
|
|
@ -31,13 +34,13 @@ LDFLAGS=-L $(CYTO_LIB) -lCytoplasm -O3 -g
|
||||||
AFLAGS=-C "$(ETC)/ayadoc/style.css" -p "$(NAME)"
|
AFLAGS=-C "$(ETC)/ayadoc/style.css" -p "$(NAME)"
|
||||||
BINARY=parsee
|
BINARY=parsee
|
||||||
# ============================ Compilation =================================
|
# ============================ Compilation =================================
|
||||||
SRC_FILES:=$(shell find $(SOURCE) -name '*.c')
|
SRC_FILES:=$(shell find $(SOURCE) -name '*.c') $(shell find $(ETC)/media -name '*.png')
|
||||||
OBJ_FILES:=${subst $(SOURCE)/,$(OBJECT)/,$(patsubst %.c, %.o, $(SRC_FILES))}
|
OBJ_FILES:=${subst $(ETC)/media/,$(OBJECT)/,${subst $(SOURCE)/,$(OBJECT)/,$(patsubst %.png, %.o, $(patsubst %.c, %.o, $(SRC_FILES)))}}
|
||||||
|
|
||||||
CPP_FILES:=$(shell find $(INCLUDES) -name '*.h')
|
CPP_FILES:=$(shell find $(INCLUDES) -name '*.h')
|
||||||
AYA_FILES:=${subst $(INCLUDES)/,$(AYAS)/,$(patsubst %.h, %.html, $(CPP_FILES))}
|
AYA_FILES:=${subst $(INCLUDES)/,$(AYAS)/,$(patsubst %.h, %.html, $(CPP_FILES))}
|
||||||
|
|
||||||
all: binary utils
|
all: utils binary
|
||||||
|
|
||||||
binary: $(OBJ_FILES)
|
binary: $(OBJ_FILES)
|
||||||
$(CC) $(LDFLAGS) $(OBJ_FILES) -o $(BINARY)
|
$(CC) $(LDFLAGS) $(OBJ_FILES) -o $(BINARY)
|
||||||
|
|
@ -47,9 +50,16 @@ tags: $(SRC_FILES)
|
||||||
clean:
|
clean:
|
||||||
rm -rf $(OBJECT) $(BINARY) $(AYAS)
|
rm -rf $(OBJECT) $(BINARY) $(AYAS)
|
||||||
|
|
||||||
|
$(OBJECT)/%.o: $(ETC)/media/%.png
|
||||||
|
@mkdir -p $(shell dirname "$@")
|
||||||
|
@echo "const char media_$(shell basename $< .png)[] =" > $@.c
|
||||||
|
@base64 $< | \
|
||||||
|
sed -e 's/^\(.*\)$$/ "\1"/' | \
|
||||||
|
sed -e '$$ s/^\(.*\)$$/\1;/' >> $@.c
|
||||||
|
$(CC) -c $(CFLAGS) $@.c -o $@
|
||||||
$(OBJECT)/%.o: $(SOURCE)/%.c
|
$(OBJECT)/%.o: $(SOURCE)/%.c
|
||||||
@mkdir -p $(shell dirname "$@")
|
@mkdir -p $(shell dirname "$@")
|
||||||
$(CC) -c $(CFLAGS) $< -o $@
|
$(CC) -c $(CFLAGS) $< -o $@
|
||||||
|
|
||||||
utils:
|
utils:
|
||||||
(cd tools && make)
|
(cd tools && make)
|
||||||
|
|
|
||||||
32
README.MD
32
README.MD
|
|
@ -1,15 +1,16 @@
|
||||||
# Parsee - the jealous XMPP<=>Matrix bridge
|
# Parsee - the jealous XMPP<=>Matrix bridge
|
||||||
Parsee is a Matrix<=>XMPP bridge written in C99, with Cytoplasm, similar to Bifrost, but it is NOT a drop-in replacment.
|
Parsee is a Matrix<=>XMPP bridge written in C99, with Cytoplasm, similar to Bifrost, but it is
|
||||||
|
NOT a drop-in replacment.
|
||||||
|
|
||||||
## Why?
|
## Why?
|
||||||
### Naming
|
### Naming
|
||||||
The name 'Parsee' is actually a reference to [Parsee Mizuhashi](https://en.touhouwiki.net/wiki/Parsee_Mizuhashi), a
|
The name 'Parsee' is actually a reference to [Parsee Mizuhashi](https://en.touhouwiki.net/wiki/Parsee_Mizuhashi),
|
||||||
"*bridge* princess".
|
a "*bridge* princess".
|
||||||
|
|
||||||
### Reasoning (personal to LDA)
|
### Reasoning (personal to LDA)
|
||||||
I hate Bifrost. I also wanted to dip my toes in XMPP, XML, and bridges a bit. Also, as a sister project to KappaChat,
|
I hate Bifrost. I also wanted to dip my toes in XMPP, XML, and bridges a bit. Also, as a sister
|
||||||
this means that I can integrate Parsee with KappaChat however I wish it to be, which allows me to mess around with a
|
project to KappaChat, this means that I can integrate Parsee with KappaChat however I wish it
|
||||||
codebase I'm already familiar with.
|
to be, which allows me to mess around with a codebase I'm already familiar with.
|
||||||
A more "up-to-date" reason may be to have a small, 'Just Werks' bridging solution *that is good*.
|
A more "up-to-date" reason may be to have a small, 'Just Werks' bridging solution *that is good*.
|
||||||
|
|
||||||
Well, I'm *trying* to do that, at least.
|
Well, I'm *trying* to do that, at least.
|
||||||
|
|
@ -31,10 +32,13 @@ $ make ayadoc # If you want to build HTML documentation
|
||||||
$ make [PREFIX=(install path)] install # To install Parsee.
|
$ make [PREFIX=(install path)] install # To install Parsee.
|
||||||
```
|
```
|
||||||
If there are any Cytoplasm-related build failures, you may want to check the Makefile to
|
If there are any Cytoplasm-related build failures, you may want to check the Makefile to
|
||||||
change a few variables (you can set `CYTO_INC` and `CYTO_LIB`)
|
change a few variables (you can set `CYTO_INC` and `CYTO_LIB` for Cytoplasm's include and
|
||||||
|
library paths specifically.)
|
||||||
|
|
||||||
### DEPENDENCIES
|
### DEPENDENCIES
|
||||||
Parsee tries to avoid dependencies aside from [Cytoplasm](https://git.telodendria.io/Telodendria/Cytoplasm). Itself optionally depends on a good POSIX implementation, and optionally OpenSSL/LMDB (highly recommended, but you can get away without those).
|
Parsee tries to avoid dependencies aside from [Cytoplasm](https://git.telodendria.io/Telodendria/Cytoplasm).
|
||||||
|
Itself optionally depends on a good POSIX implementation, and optionally OpenSSL/LMDB (highly recommended, but
|
||||||
|
you can get away without those if you're adventurous).
|
||||||
|
|
||||||
## RUNNING
|
## RUNNING
|
||||||
First off, you may want to configure Parsee by running the `config` tool(generally named
|
First off, you may want to configure Parsee by running the `config` tool(generally named
|
||||||
|
|
@ -62,19 +66,20 @@ returns with a landing page, then this side works. You can read it for some more
|
||||||
Currently, the main sources of documentation are the Ayadocs(for headers) and the manpages
|
Currently, the main sources of documentation are the Ayadocs(for headers) and the manpages
|
||||||
(see `etc/man`)
|
(see `etc/man`)
|
||||||
|
|
||||||
## TODOS
|
## TODOS before 1.0 rolls around
|
||||||
- Add [libomemo](https://github.com/gkdr/libomemo) as an optional dependency.
|
- Add [libomemo](https://github.com/gkdr/libomemo) or something as an optional dependency.
|
||||||
- It depends on more stuff anyways, and I don't want to weigh down the
|
- It depends on more stuff anyways, and I don't want to weigh down the
|
||||||
dependency list of Parsee for that.
|
dependency list of Parsee for that.
|
||||||
- Matrix's libolm is deprecated. They replaced it with a Rust version that
|
- Matrix's libolm is deprecated. They replaced it with a Rust version that
|
||||||
pulls in *way too many* dependencies, and that lacks a C binding. We may
|
pulls in *way too many* dependencies, and that lacks a C binding. We may
|
||||||
put in the work of either forking off libolm or making a binding to KappaChat.
|
put in the work of either forking off libolm or making a binding to KappaChat.
|
||||||
|
- Josh did infact tell me that maybe C bindings may happen. I'd be
|
||||||
|
willing to help out, but IDK. In any case, this will at best be an
|
||||||
|
extension packagers may integrate properly.
|
||||||
- Get rid of the '?'-syntax and use another invalid Matrix char/valid XMPP char
|
- Get rid of the '?'-syntax and use another invalid Matrix char/valid XMPP char
|
||||||
('$'?) for escaped?
|
('$'?) for escaped?
|
||||||
- PROPER FUCKING AVATARS
|
- PROPER FUCKING AVATARS
|
||||||
XEP-0084 IS THE WORST PIECE OF SHIT KNOWN TO MAN. If any Jabberbros want to
|
XMPP->Matrix is decent, Matrix->XMPP is effectiveny not done
|
||||||
look at terrible code/XML and suggest things to have *proper* avatar support,
|
|
||||||
I'm all in.
|
|
||||||
- Consider making room/MUC admins/owners be able to plumb instead of it being
|
- Consider making room/MUC admins/owners be able to plumb instead of it being
|
||||||
restricted to Parsee admins, with permission from MUC owners, too
|
restricted to Parsee admins, with permission from MUC owners, too
|
||||||
- Limiting to admins may be a way to "control" consent for both, but this is
|
- Limiting to admins may be a way to "control" consent for both, but this is
|
||||||
|
|
@ -85,6 +90,7 @@ restricted to Parsee admins, with permission from MUC owners, too
|
||||||
support XMPP->Matrix bridging.
|
support XMPP->Matrix bridging.
|
||||||
- Manage MUC DMs in a reasonable manner. Thanks `@freeoffers4u:matrix.org` for being
|
- Manage MUC DMs in a reasonable manner. Thanks `@freeoffers4u:matrix.org` for being
|
||||||
a fucking annoyance and DMing an old Parsee semi-anon user for no clear reason.
|
a fucking annoyance and DMing an old Parsee semi-anon user for no clear reason.
|
||||||
|
- Deadlocks. It's always deadlocks.
|
||||||
|
|
||||||
## DONATING/CONTRIBUTING
|
## DONATING/CONTRIBUTING
|
||||||
If you know things about XMPP or Matrix, yet aren't familiar with C99, or just
|
If you know things about XMPP or Matrix, yet aren't familiar with C99, or just
|
||||||
|
|
|
||||||
27
XEPS-TBD.TXT
27
XEPS-TBD.TXT
|
|
@ -1,6 +1,19 @@
|
||||||
XEPs current supported are in src/XMPPThread, at the IQ disco advertising.
|
XEPs current supported are in src/XMPPThread, at the IQ disco advertising.
|
||||||
|
|
||||||
Somewhat implemented XEPs:
|
Somewhat implemented XEPs:
|
||||||
|
v https://xmpp.org/extensions/xep-0050.html
|
||||||
|
Ad-hoc commands that bridge maintainers can deal with XMPP-style are
|
||||||
|
also a nice to have.
|
||||||
|
There are commands, but not a lot of them as of now, and localisation
|
||||||
|
is missing.
|
||||||
|
v https://xmpp.org/extensions/xep-0421.html
|
||||||
|
Using the occupant ID in semi-anonymous MUCs is a desirable property.
|
||||||
|
I dont know of a lot of places that don't use the occupant ID anymore
|
||||||
|
within Parsee.
|
||||||
|
v "also it [Bifrost] doesn't respect voice either"
|
||||||
|
As far as I am aware, works.
|
||||||
|
v https://xmpp.org/extensions/xep-0425.html
|
||||||
|
As mentionned in #2, moderation _needs_ to be done.
|
||||||
~ https://xmpp.org/extensions/xep-0085.html
|
~ https://xmpp.org/extensions/xep-0085.html
|
||||||
Only XMPP->Matrix at the moment. Still need to figure out how to
|
Only XMPP->Matrix at the moment. Still need to figure out how to
|
||||||
get typing indicators as an AS.
|
get typing indicators as an AS.
|
||||||
|
|
@ -12,17 +25,6 @@ Somewhat implemented XEPs:
|
||||||
~ https://xmpp.org/extensions/xep-0184.html
|
~ https://xmpp.org/extensions/xep-0184.html
|
||||||
Only Matrix->XMPP as of now. Requesting data from Matrix ASes without
|
Only Matrix->XMPP as of now. Requesting data from Matrix ASes without
|
||||||
/sync seems like a non-option as of now, which _sucks_.
|
/sync seems like a non-option as of now, which _sucks_.
|
||||||
~ https://xmpp.org/extensions/xep-0050.html
|
|
||||||
Ad-hoc commands that bridge maintainers can deal with XMPP-style are
|
|
||||||
also a nice to have.
|
|
||||||
There are commands, but not a lot of them as of now, and localisation
|
|
||||||
is missing.
|
|
||||||
~ https://xmpp.org/extensions/xep-0421.html
|
|
||||||
Using the occupant ID in semi-anonymous MUCs is a desirable property.
|
|
||||||
I dont know of a lot of places that don't use the occupant ID anymore
|
|
||||||
within Parsee.
|
|
||||||
~ https://xmpp.org/extensions/xep-0425.html
|
|
||||||
As mentionned in #2, moderation _needs_ to be done.
|
|
||||||
|
|
||||||
For future XEPs:
|
For future XEPs:
|
||||||
- https://xmpp.org/extensions/xep-0449.html
|
- https://xmpp.org/extensions/xep-0449.html
|
||||||
|
|
@ -44,9 +46,8 @@ THESE I WANT TO SEND THEM A NICE, BRIGHT GIFT:
|
||||||
|
|
||||||
|
|
||||||
Not XEPs, but ideas that _needs_ to be added:
|
Not XEPs, but ideas that _needs_ to be added:
|
||||||
v "also it [Bifrost] doesn't respect voice either" -> Send a form on moderated
|
|
||||||
MUCs (which is standard, so its not too bad!). Currently WIP, and barely tested.
|
|
||||||
~ "GIVE THE PUPPETS APPROPRIATE PLS/ROLES" - Hydro/t4d
|
~ "GIVE THE PUPPETS APPROPRIATE PLS/ROLES" - Hydro/t4d
|
||||||
|
Happens on Matrix. I'll need to handle that on XMPP as well.
|
||||||
- Standalone/Static Parsee, ideally as small as it can be(if not as APE).
|
- Standalone/Static Parsee, ideally as small as it can be(if not as APE).
|
||||||
- Kappa-like extension system(maybe bridging more than just Matrix-XMPP.)
|
- Kappa-like extension system(maybe bridging more than just Matrix-XMPP.)
|
||||||
- https://www.youtube.com/watch?v=InL414iDZmY
|
- https://www.youtube.com/watch?v=InL414iDZmY
|
||||||
|
|
|
||||||
5
etc/media/README
Normal file
5
etc/media/README
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
This directory is for any PNG media that needs to be integrated into Parsee.
|
||||||
|
Each file here is Base64-encoded then defined as a const char[] symbol with
|
||||||
|
the name being a function of the PNG filename: N(FILE.png)=media_FILE
|
||||||
|
|
||||||
|
NOTE: Medias should be about ~1024B MAX. Avoid to stride for anything larger.
|
||||||
BIN
etc/media/parsee_logo.png
Normal file
BIN
etc/media/parsee_logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 871 B |
|
|
@ -19,7 +19,6 @@ ASUpload(const ParseeConfig *c, Stream *from, unsigned int size, char *mime)
|
||||||
HashMap *reply;
|
HashMap *reply;
|
||||||
if (!c || !from)
|
if (!c || !from)
|
||||||
{
|
{
|
||||||
Log(LOG_ERR, "No ASUpload input (c=%p from=%p)", c, from);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -224,8 +224,9 @@ Main(Array *args, HashMap *env)
|
||||||
}
|
}
|
||||||
|
|
||||||
Log(LOG_NOTICE, "Starting up local cronjobs...");
|
Log(LOG_NOTICE, "Starting up local cronjobs...");
|
||||||
cron = CronCreate( 10 SECONDS );
|
cron = CronCreate( 30 MINUTES );
|
||||||
CronEvery(cron, 5 MINUTES, ParseeCleanup, conf.handlerArgs);
|
CronEvery(cron, 1 HOURS, ParseeCleanup, conf.handlerArgs);
|
||||||
|
ParseeCleanup(conf.handlerArgs);
|
||||||
|
|
||||||
CronStart(cron);
|
CronStart(cron);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ ComputeKPad(char *key, uint8_t pad, uint8_t *kopad)
|
||||||
{
|
{
|
||||||
size_t klen;
|
size_t klen;
|
||||||
uint8_t *kp;
|
uint8_t *kp;
|
||||||
|
uint8_t kpi[64] = { 0 };
|
||||||
size_t i;
|
size_t i;
|
||||||
if ((klen = strlen(key)) <= 64)
|
if ((klen = strlen(key)) <= 64)
|
||||||
{
|
{
|
||||||
|
|
@ -25,14 +26,16 @@ ComputeKPad(char *key, uint8_t pad, uint8_t *kopad)
|
||||||
klen = 32;
|
klen = 32;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memset(kpi, 0x00, 64);
|
||||||
|
memcpy(kpi, kp, klen);
|
||||||
|
Free(kp);
|
||||||
|
|
||||||
/* Now that we have K', lets compute it XORd with opad */
|
/* Now that we have K', lets compute it XORd with opad */
|
||||||
for (i = 0; i < 64; i++)
|
for (i = 0; i < 64; i++)
|
||||||
{
|
{
|
||||||
uint8_t byte = i < klen ? kp[i] : 0x00;
|
uint8_t byte = kpi[i];
|
||||||
kopad[i] = byte ^ pad;
|
kopad[i] = byte ^ pad;
|
||||||
}
|
}
|
||||||
|
|
||||||
Free(kp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,8 @@ RouteHead(RouteMedia, arr, argp)
|
||||||
params = HttpRequestParams(args->ctx);
|
params = HttpRequestParams(args->ctx);
|
||||||
hmac = HashMapGet(params, "hmac");
|
hmac = HashMapGet(params, "hmac");
|
||||||
|
|
||||||
/* TODO: Make it check the DB for its validicity. "Purging" would be useful.
|
/* TODO: Make it check the DB for its validicity. "Purging" would be
|
||||||
*/
|
* useful, alongside checking if someone isn't just a little idiotic. */
|
||||||
{
|
{
|
||||||
char *concat = StrConcat(3, server, "/", identi);
|
char *concat = StrConcat(3, server, "/", identi);
|
||||||
chkmak = ParseeHMACS(args->data->id, concat);
|
chkmak = ParseeHMACS(args->data->id, concat);
|
||||||
|
|
@ -32,12 +32,18 @@ RouteHead(RouteMedia, arr, argp)
|
||||||
}
|
}
|
||||||
if (!server || !identi || !hmac || !StrEquals(hmac, chkmak))
|
if (!server || !identi || !hmac || !StrEquals(hmac, chkmak))
|
||||||
{
|
{
|
||||||
|
char *err =
|
||||||
|
hmac && StrEquals(hmac, chkmak) ?
|
||||||
|
"No server/identifier/HMAC code" :
|
||||||
|
"Hah! You _dirty_ little liar! Try a little harder!";
|
||||||
Free(chkmak);
|
Free(chkmak);
|
||||||
HttpResponseStatus(args->ctx, HTTP_BAD_REQUEST);
|
HttpResponseStatus(args->ctx, HTTP_BAD_REQUEST);
|
||||||
return MatrixCreateError("M_NOT_YET_UPLOADED", "No server/identifier");
|
return MatrixCreateError("M_NOT_YET_UPLOADED", err);
|
||||||
}
|
}
|
||||||
Free(chkmak);
|
Free(chkmak);
|
||||||
|
|
||||||
|
/* Proxy the media through an authenticated endpoint if the HMAC
|
||||||
|
* is valid. */
|
||||||
server = HttpUrlEncode(server);
|
server = HttpUrlEncode(server);
|
||||||
identi = HttpUrlEncode(identi);
|
identi = HttpUrlEncode(identi);
|
||||||
path = StrConcat(4, "/_matrix/media/v3/download/", server, "/", identi);
|
path = StrConcat(4, "/_matrix/media/v3/download/", server, "/", identi);
|
||||||
|
|
|
||||||
|
|
@ -76,6 +76,7 @@ RouteHead(RouteRoot, arr, argp)
|
||||||
{
|
{
|
||||||
P("<title>%s Lander</title>", NAME);
|
P("<title>%s Lander</title>", NAME);
|
||||||
P("<meta charset='UTF-8'/>");
|
P("<meta charset='UTF-8'/>");
|
||||||
|
P("<link rel='icon' href='data:image/png;base64,%s'/>", media_parsee_logo);
|
||||||
P("<style>");
|
P("<style>");
|
||||||
{
|
{
|
||||||
P("html {");
|
P("html {");
|
||||||
|
|
@ -83,6 +84,15 @@ RouteHead(RouteRoot, arr, argp)
|
||||||
P("color: #eee;");
|
P("color: #eee;");
|
||||||
P("font-family: sans-serif;");
|
P("font-family: sans-serif;");
|
||||||
P("}");
|
P("}");
|
||||||
|
P("#cols {");
|
||||||
|
P("column-count: 3;");
|
||||||
|
P("min-width: 100%;");
|
||||||
|
P("max-width: 100%;");
|
||||||
|
P("width: 100%;");
|
||||||
|
P("}");
|
||||||
|
P("img {");
|
||||||
|
P("image-rendering: pixelated;");
|
||||||
|
P("}");
|
||||||
P("blockquote {");
|
P("blockquote {");
|
||||||
P("border-left: 2px solid #ccc;");
|
P("border-left: 2px solid #ccc;");
|
||||||
P("margin: 1.5em 10px;");
|
P("margin: 1.5em 10px;");
|
||||||
|
|
@ -105,9 +115,9 @@ RouteHead(RouteRoot, arr, argp)
|
||||||
|
|
||||||
P("<body>");
|
P("<body>");
|
||||||
{
|
{
|
||||||
P("<center><h1>");
|
P("<center>");
|
||||||
P("Your %s is running, all with that %s!", NAME, CODE);
|
P("<h1>Your %s is running, all with that %s!</h1>", NAME, CODE);
|
||||||
P("</h1></center>");
|
P("</center>");
|
||||||
P("<hr/>");
|
P("<hr/>");
|
||||||
P("<blockquote><i>");
|
P("<blockquote><i>");
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -97,6 +97,9 @@ typedef struct Argument {
|
||||||
#define MB * 1024 KB
|
#define MB * 1024 KB
|
||||||
#define GB * 1024 MB
|
#define GB * 1024 MB
|
||||||
|
|
||||||
|
/* A base64-encoded Parsee logo */
|
||||||
|
extern const char media_parsee_logo[];
|
||||||
|
|
||||||
/** Generates a valid, getopt-style argument list from a end-terminated
|
/** Generates a valid, getopt-style argument list from a end-terminated
|
||||||
* argument list.
|
* argument list.
|
||||||
* ------------
|
* ------------
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue