From 68377f09f7208685abf389cf9e096d9f1fbce6f8 Mon Sep 17 00:00:00 2001 From: Art Cancro Date: Wed, 31 Aug 2022 17:52:45 -0400 Subject: [PATCH] Use spaces in api.txt --- citadel/citadel.lock | 0 citadel/config.mk | 4 + citadel/obsolete.txt | 43 ++++++++ ctdlsh/main.c~ | 175 ++++++++++++++++++++++++++++++++ textclient/citadel_ipc.c | 36 +++---- textclient/config.mk | 5 + webcit-ng/api.txt | 61 ++++++----- webcit-ng/static/css/webcit.css | 16 +-- webcit-ng/static/index.html | 22 ++-- 9 files changed, 290 insertions(+), 72 deletions(-) create mode 100644 citadel/citadel.lock create mode 100644 citadel/config.mk create mode 100644 citadel/obsolete.txt create mode 100644 ctdlsh/main.c~ create mode 100644 textclient/config.mk diff --git a/citadel/citadel.lock b/citadel/citadel.lock new file mode 100644 index 000000000..e69de29bb diff --git a/citadel/config.mk b/citadel/config.mk new file mode 100644 index 000000000..864c60f48 --- /dev/null +++ b/citadel/config.mk @@ -0,0 +1,4 @@ +# config.mk is generated by configure +CTDLDIR := /root/citadel/citadel +CFLAGS := -ggdb -DHAVE_OPENSSL -DBUILD_ID=\"v957-38-g71c3e52b0\" -DCTDLDIR=\"/root/citadel/citadel\" +LDFLAGS := -lssl -lcrypto -lz diff --git a/citadel/obsolete.txt b/citadel/obsolete.txt new file mode 100644 index 000000000..541be5817 --- /dev/null +++ b/citadel/obsolete.txt @@ -0,0 +1,43 @@ +HAVE_ARPA_NAMESER_H +HAVE_CONNECT +HAVE_DB_H +HAVE_DIRENT_H +HAVE_FCNTL_H +HAVE_GETHOSTBYNAME +HAVE_GETLOADAVG +HAVE_GETTEXT +HAVE_GETUTXLINE +HAVE_INTTYPES_H +HAVE_LIBPTHREAD +HAVE_LIBRT +HAVE_LIMITS_H +HAVE_MALLOC_H +HAVE_MKDIR +HAVE_MKFIFO +HAVE_MKTIME +HAVE_NETINET_IN_H +HAVE_PATHS_H +HAVE_PTHREAD_CANCEL +HAVE_RMDIR +HAVE_SELECT +HAVE_SOCKET +HAVE_STDINT_H +HAVE_STDLIB_H +HAVE_STRCASECMP +HAVE_STRERROR +HAVE_STRFTIME_L +HAVE_STRNCASECMP +HAVE_SYSLOG_H +HAVE_SYS_IOCTL_H +HAVE_SYS_STAT_H +HAVE_SYS_TIME_H +HAVE_SYS_TYPES_H +HAVE_SYS_WAIT_H +HAVE_TERMIOS_H +HAVE_UNISTD_H +HAVE_USELOCALE +HAVE_UTMPX_H +HAVE_UTMP_H +HAVE_UT_HOST +HAVE_UT_TYPE +HAVE_VPRINTF diff --git a/ctdlsh/main.c~ b/ctdlsh/main.c~ new file mode 100644 index 000000000..93265244e --- /dev/null +++ b/ctdlsh/main.c~ @@ -0,0 +1,175 @@ +/* + * (c) 2009-2020 by Art Cancro and citadel.org + * This program is open source. It runs great on the Linux operating system. + * It's released under the General Public License (GPL) version 3. + */ + +#include "ctdlsh.h" + + +/* + * Commands understood by ctdlsh + */ +typedef struct { + char *name; + ctdlsh_cmdfunc_t *func; + char *doc; +} COMMAND; + +COMMAND commands[] = { + {"?", cmd_help, "Display this message"}, + {"help", cmd_help, "Display this message"}, + {"date", cmd_datetime, "Print the server's date and time"}, + {"config", cmd_config, "Configure the Citadel server"}, + {"export", cmd_export, "Export all Citadel databases"}, + {"shutdown", cmd_shutdown, "Shut down the Citadel server"}, + {"time", cmd_datetime, "Print the server's date and time"}, + {"passwd", cmd_passwd, "Set or change an account password"}, + {"who", cmd_who, "Display a list of online users"}, + {"mailq", cmd_mailq, "Show the outbound email queue"}, + {NULL, NULL, NULL} +}; + + + +int cmd_help(int sock, char *cmdbuf) +{ + int i; + + for (i = 0; commands[i].func != NULL; ++i) { + printf("%10s %s\n", commands[i].name, commands[i].doc); + } +} + + +int do_one_command(int server_socket, char *cmd) +{ + int i; + int ret; + for (i = 0; commands[i].func != NULL; ++i) { + if (!strncasecmp(cmd, commands[i].name, strlen(commands[i].name))) { + ret = (*commands[i].func) (server_socket, cmd); + } + } + return ret; +} + +char *command_name_generator(const char *text, int state) +{ + static int list_index, len; + char *name; + + if (!state) { + list_index = 0; + len = strlen(text); + } + + while (name = commands[list_index++].name) { + if (strncmp(name, text, len) == 0) { + return strdup(name); + } + } + + return NULL; +} + + +char **command_name_completion(const char *text, int start, int end) +{ + rl_attempted_completion_over = 1; + return rl_completion_matches(text, command_name_generator); +} + + +void do_main_loop(int server_socket) +{ + char *cmd = NULL; + char prompt[1024]; + char buf[1024]; + char server_reply[1024]; + int i; + int ret = (-1); + + strcpy(prompt, "> "); + + /* Do an INFO command and learn the hostname for the prompt */ + sock_puts(server_socket, "INFO"); + sock_getln(server_socket, buf, sizeof buf); + if (buf[0] == '1') { + i = 0; + while (sock_getln(server_socket, buf, sizeof buf), strcmp(buf, "000")) { + if (i == 1) { + sprintf(prompt, "\n%s> ", buf); + } + ++i; + } + } + + /* Here we go ... main command loop */ + rl_attempted_completion_function = command_name_completion; + while ( (cmd = readline(prompt)) , cmd ) { + if (*cmd) { + add_history(cmd); + ret = do_one_command(server_socket, cmd); + } + free(cmd); + } +} + + +/* + * If you don't know what main() does by now you probably shouldn't be reading this code. + */ +int main(int argc, char **argv) +{ + int server_socket = 0; + char buf[1024]; + int i; + char *ctdldir = CTDLDIR; + char cmd[1024] = { 0 }; + int exitcode = 0; + + for (i = 1; i < argc; ++i) { + if (!strcmp(argv[i], "-h")) { + ctdldir = argv[++i]; + } else { + if (strlen(cmd) > 0) { + strcat(cmd, " "); + } + strcat(cmd, argv[i]); + } + } + + int is_interactive = ((strlen(cmd) == 0) ? 1 : 0); + + if (is_interactive) { + printf("\nCitadel administration shell (c) 2009-2020 by citadel.org\n" + "This is open source software made available to you under the terms\n" + "of the GNU General Public License v3. All other rights reserved.\n"); + printf("Connecting to Citadel server in %s...\n", ctdldir); + } + + sprintf(buf, "%s/citadel-admin.socket", ctdldir); + server_socket = uds_connectsock(buf); + if (server_socket < 0) { + exit(1); + } + + sock_getln(server_socket, buf, sizeof buf); + if (buf[0] == '2') { + if (is_interactive) { + printf("Connected: %s\n", buf); + do_main_loop(server_socket); + } else { + exitcode = do_one_command(server_socket, cmd); + } + } + + sock_puts(server_socket, "QUIT"); + sock_getln(server_socket, buf, sizeof buf); + if (is_interactive) { + printf("%s\n", buf); + } + close(server_socket); + exit(exitcode); +} diff --git a/textclient/citadel_ipc.c b/textclient/citadel_ipc.c index 2c885af82..3853a7bbd 100644 --- a/textclient/citadel_ipc.c +++ b/textclient/citadel_ipc.c @@ -153,8 +153,7 @@ const char *svn_revision(void); /* * Does nothing. The server should always return 200. */ -int CtdlIPCNoop(CtdlIPC * ipc) -{ +int CtdlIPCNoop(CtdlIPC * ipc) { char aaa[128]; return CtdlIPCGenericCommand(ipc, "NOOP", NULL, 0, NULL, NULL, aaa); @@ -165,8 +164,7 @@ int CtdlIPCNoop(CtdlIPC * ipc) * Does nothing interesting. The server should always return 200 * along with your string. */ -int CtdlIPCEcho(CtdlIPC * ipc, const char *arg, char *cret) -{ +int CtdlIPCEcho(CtdlIPC * ipc, const char *arg, char *cret) { int ret; char *aaa; @@ -217,8 +215,7 @@ int CtdlIPCQuit(CtdlIPC * ipc) { * Asks the server to log out. Should always return 200, even if no user * was logged in. The user will not be logged in after this! */ -int CtdlIPCLogout(CtdlIPC * ipc) -{ +int CtdlIPCLogout(CtdlIPC * ipc) { int ret; char aaa[SIZ]; @@ -236,8 +233,7 @@ int CtdlIPCLogout(CtdlIPC * ipc) * username is able to log in, with the username correctly spelled in cret. * Returns various 500 error codes if the user doesn't exist, etc. */ -int CtdlIPCTryLogin(CtdlIPC * ipc, const char *username, char *cret) -{ +int CtdlIPCTryLogin(CtdlIPC * ipc, const char *username, char *cret) { int ret; char *aaa; @@ -261,8 +257,7 @@ int CtdlIPCTryLogin(CtdlIPC * ipc, const char *username, char *cret) * Second stage of authentication - provide password. The server returns * 200 and several arguments in cret relating to the user's account. */ -int CtdlIPCTryPassword(CtdlIPC * ipc, const char *passwd, char *cret) -{ +int CtdlIPCTryPassword(CtdlIPC * ipc, const char *passwd, char *cret) { int ret; char *aaa; @@ -289,8 +284,7 @@ int CtdlIPCTryPassword(CtdlIPC * ipc, const char *passwd, char *cret) * user - intended for use by system administrators to create accounts on * behalf of other users. */ -int CtdlIPCCreateUser(CtdlIPC * ipc, const char *username, int selfservice, char *cret) -{ +int CtdlIPCCreateUser(CtdlIPC * ipc, const char *username, int selfservice, char *cret) { int ret; char *aaa; @@ -313,8 +307,7 @@ int CtdlIPCCreateUser(CtdlIPC * ipc, const char *username, int selfservice, char /* * Changes the user's password. Returns 200 if changed, errors otherwise. */ -int CtdlIPCChangePassword(CtdlIPC * ipc, const char *passwd, char *cret) -{ +int CtdlIPCChangePassword(CtdlIPC * ipc, const char *passwd, char *cret) { int ret; char *aaa; @@ -338,8 +331,7 @@ int CtdlIPCChangePassword(CtdlIPC * ipc, const char *passwd, char *cret) /* Caller must free the march list */ /* Room types are defined in enum RoomList; keep these in sync! */ /* floor is -1 for all, or floornum */ -int CtdlIPCKnownRooms(CtdlIPC * ipc, enum RoomList which, int floor, struct march **listing, char *cret) -{ +int CtdlIPCKnownRooms(CtdlIPC * ipc, enum RoomList which, int floor, struct march **listing, char *cret) { int ret; struct march *march = NULL; static char *proto[] = { "LKRA", "LKRN", "LKRO", "LZRM", "LRMS", "LPRM" }; @@ -399,8 +391,7 @@ int CtdlIPCKnownRooms(CtdlIPC * ipc, enum RoomList which, int floor, struct marc /* GETU */ /* Caller must free the struct ctdluser; caller may pass an existing one */ -int CtdlIPCGetConfig(CtdlIPC * ipc, struct ctdluser **uret, char *cret) -{ +int CtdlIPCGetConfig(CtdlIPC * ipc, struct ctdluser **uret, char *cret) { int ret; if (!cret) @@ -421,8 +412,7 @@ int CtdlIPCGetConfig(CtdlIPC * ipc, struct ctdluser **uret, char *cret) /* SETU */ -int CtdlIPCSetConfig(CtdlIPC * ipc, struct ctdluser *uret, char *cret) -{ +int CtdlIPCSetConfig(CtdlIPC * ipc, struct ctdluser *uret, char *cret) { char aaa[48]; if (!uret) @@ -436,8 +426,7 @@ int CtdlIPCSetConfig(CtdlIPC * ipc, struct ctdluser *uret, char *cret) /* RENU */ -int CtdlIPCRenameUser(CtdlIPC * ipc, char *oldname, char *newname, char *cret) -{ +int CtdlIPCRenameUser(CtdlIPC * ipc, char *oldname, char *newname, char *cret) { int ret; char cmd[256]; @@ -455,8 +444,7 @@ int CtdlIPCRenameUser(CtdlIPC * ipc, char *oldname, char *newname, char *cret) /* GOTO */ -int CtdlIPCGotoRoom(CtdlIPC * ipc, const char *room, const char *passwd, struct ctdlipcroom **rret, char *cret) -{ +int CtdlIPCGotoRoom(CtdlIPC * ipc, const char *room, const char *passwd, struct ctdlipcroom **rret, char *cret) { int ret; char *aaa; diff --git a/textclient/config.mk b/textclient/config.mk new file mode 100644 index 000000000..da064d22e --- /dev/null +++ b/textclient/config.mk @@ -0,0 +1,5 @@ +CFLAGS := -Wformat-truncation=0 -ggdb -DHAVE_OPENSSL +LDFLAGS := -lssl -lcrypto -lz +PREFIX := /usr/local +BINDIR := /usr/local/bin +CTDLDIR := /usr/local/citadel diff --git a/webcit-ng/api.txt b/webcit-ng/api.txt index 972b5efd5..cbab2b92c 100644 --- a/webcit-ng/api.txt +++ b/webcit-ng/api.txt @@ -1,34 +1,33 @@ +Method URL Function +------ ------------------------------ ------------------------------------- +GET / Site root will redirect to a landing page +GET /ctdl/f/ returns a JSON-encoded list of accessible floors +GET /ctdl/r/ returns a JSON-encoded list of accessible rooms +OPTIONS /ctdl/r/ROOMNAME/ returns just what you'd expect +PROPFIND /ctdl/r/ROOMNAME/ Show a bunch of crap +GET /ctdl/r/ROOMNAME/ Returns information about the room (name, view, etc.) in JSON format +GET /ctdl/r/ROOMNAME/info.txt Returns the room info banner for this room +GET /ctdl/r/ROOMNAME/msgs.all JSON array of message list in room +GET /ctdl/r/ROOMNAME/msgs.new JSON array of message list in room (new messages) +GET /ctdl/r/ROOMNAME/mailbox JSON dictionary of a mailbox summary in this room +GET /ctdl/r/ROOMNAME/stat JSON dictionary of the server STAT command (room name and modification time) +GET /ctdl/r/ROOMNAME/MSGNUM Retrieve the content of an individual message +GET /ctdl/r/ROOMNAME/MSGNUM/json Retrieve an individual message in a room, encapsulated in JSON +DELETE /ctdl/r/ROOMNAME/MSGNUM Deletes a message from a room -Method URL Function ------- ------------------------------ ------------------------------------- -GET / Site root will redirect to a landing page -GET /ctdl/f/ returns a JSON-encoded list of accessible floors -GET /ctdl/r/ returns a JSON-encoded list of accessible rooms -OPTIONS /ctdl/r/ROOMNAME/ returns just what you'd expect -PROPFIND /ctdl/r/ROOMNAME/ Show a bunch of crap -GET /ctdl/r/ROOMNAME/ Returns information about the room (name, view, etc.) in JSON format -GET /ctdl/r/ROOMNAME/info.txt Returns the room info banner for this room -GET /ctdl/r/ROOMNAME/msgs.all JSON array of message list in room -GET /ctdl/r/ROOMNAME/msgs.new JSON array of message list in room (new messages) -GET /ctdl/r/ROOMNAME/mailbox JSON dictionary of a mailbox summary in this room -GET /ctdl/r/ROOMNAME/stat JSON dictionary of the server STAT command (room name and modification time) -GET /ctdl/r/ROOMNAME/MSGNUM Retrieve the content of an individual message -GET /ctdl/r/ROOMNAME/MSGNUM/json Retrieve an individual message in a room, encapsulated in JSON -DELETE /ctdl/r/ROOMNAME/MSGNUM Deletes a message from a room +PUT /ctdl/r/ROOMNAME/xxx DAV operation to insert a new message into a room + Accepted parameters: + wefw List of message references + subj Message subject + The returned ETag will be the new message number. -PUT /ctdl/r/ROOMNAME/xxx DAV operation to insert a new message into a room - Accepted parameters: - wefw List of message references - subj Message subject - The returned ETag will be the new message number. +GET /ctdl/r/ROOMNAME/slrp Set the "Last Read Pointer" for the room + Accepted parameters: + last The number of the most recently seen message -GET /ctdl/r/ROOMNAME/slrp Set the "Last Read Pointer" for the room - Accepted parameters: - last The number of the most recently seen message - -GET /ctdl/c/info Returns a JSON representation of the output of an INFO server command -POST /ctdl/a/login Send it a your credentials and it will log you in -GET /ctdl/a/whoami -GET /ctdl/u/USERNAME/userpic Returns an image containing the photo/avatar of the specified user -GET /ctdl/s/ Static content (html, css, js, images...) -GET /.well-known/ Static content (RFC5785 compliant paths) +GET /ctdl/c/info Returns a JSON representation of the output of an INFO server command +POST /ctdl/a/login Send it a your credentials and it will log you in +GET /ctdl/a/whoami +GET /ctdl/u/USERNAME/userpic Returns an image containing the photo/avatar of the specified user +GET /ctdl/s/ Static content (html, css, js, images...) +GET /.well-known/ Static content (RFC5785 compliant paths) diff --git a/webcit-ng/static/css/webcit.css b/webcit-ng/static/css/webcit.css index b6a347dde..a9a99f7ca 100644 --- a/webcit-ng/static/css/webcit.css +++ b/webcit-ng/static/css/webcit.css @@ -10,21 +10,21 @@ margin: 0; } -.ctdl-grid-item-1 { /* These grid items will be referenced in the grid container */ +.ctdl-grid-banner-item { /* These grid items will be referenced in the grid container */ grid-area: header; } -.ctdl-grid-item-2 { +.ctdl-grid-navbar-item { grid-area: menu; } -.ctdl-grid-item-3 { +.ctdl-grid-main-item { grid-area: main; overflow-x: hidden; overflow-y: auto; } -.ctdl-grid-container { /* This is so mind-bogglingly simple I can't believe it works */ +.ctdl-main-grid-container { /* This is so mind-bogglingly simple I can't believe it works */ display: grid; grid-template-areas: 'header header header header header header' @@ -42,7 +42,7 @@ height: 100vh; } -.ctdl-grid-container > div { +.ctdl-main-grid-container > div { background-color: #DDEEFF; text-align: left; padding: 10px 0; @@ -69,12 +69,16 @@ html,body,h1,h2,h3,h4,h5 { .ctdl-sidebar-class button { width: 100%; - background-color: blue; text-align: left; background-color: #888888; color: #FFFFFF; } +.ctdl-grid-banner-item button { + background-color: #888888; + color: #FFFFFF; +} + .ctdl-msg-reading-pane { background-color: #456789; } diff --git a/webcit-ng/static/index.html b/webcit-ng/static/index.html index 763598b30..fff7dc870 100644 --- a/webcit-ng/static/index.html +++ b/webcit-ng/static/index.html @@ -19,20 +19,20 @@ MODAL LOADING -
+
-