Use spaces in api.txt
authorArt Cancro <ajc@citadel.org>
Wed, 31 Aug 2022 21:52:45 +0000 (17:52 -0400)
committerArt Cancro <ajc@citadel.org>
Wed, 31 Aug 2022 21:52:45 +0000 (17:52 -0400)
citadel/citadel.lock [new file with mode: 0644]
citadel/config.mk [new file with mode: 0644]
citadel/obsolete.txt [new file with mode: 0644]
ctdlsh/main.c~ [new file with mode: 0644]
textclient/citadel_ipc.c
textclient/config.mk [new file with mode: 0644]
webcit-ng/api.txt
webcit-ng/static/css/webcit.css
webcit-ng/static/index.html

diff --git a/citadel/citadel.lock b/citadel/citadel.lock
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/citadel/config.mk b/citadel/config.mk
new file mode 100644 (file)
index 0000000..864c60f
--- /dev/null
@@ -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 (file)
index 0000000..541be58
--- /dev/null
@@ -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 (file)
index 0000000..9326524
--- /dev/null
@@ -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);
+}
index 2c885af82a7cd4c5d95748e5fa43aec36ddfd63f..3853a7bbd2ed1fcea591c7ebe966123af10554ba 100644 (file)
@@ -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 (file)
index 0000000..da064d2
--- /dev/null
@@ -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
index 972b5efd5522571d46b0794746c93035aa725bbb..cbab2b92c02a2c0362e0013bb8e8047cc5bc84fe 100644 (file)
@@ -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)
index b6a347dde84ae2a814a05dfb8731ebc5ab93d1be..a9a99f7caa41cd1b5068e69503c87f1b8317be3d 100644 (file)
        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;
 }
index 763598b305a76c91a145799c7a16f26fd271055b..fff7dc870c1f14a8bb092a462da93e17b0425dbb 100644 (file)
 MODAL LOADING
 </div>
 
-<div class="ctdl-grid-container">
+<div class="ctdl-main-grid-container">
 
-       <div class="ctdl-grid-item-1" id="banner">
+       <div class="ctdl-grid-banner-item" id="banner">
                <button onClick="sidebar_open();"><i class="fa fa-bars"></i>Menu</button>
-               <span class="w3-bar-item" id="ctdl-logo">CITADEL</span>
+               <span id="ctdl-logo">CITADEL</span>
                <span id="ctdl_banner_title" class="w3-bar-item">---</span>
-               <button id="ctdl-newmsg-button" style="display:none" class="w3-bar-item w3-button" onClick="entmsg_dispatcher();">enter</button>
-               <button id="ctdl-ungoto-button" style="display:none" class="w3-bar-item w3-button" onClick="gotonext(0);">ungoto</button>
-               <button id="ctdl-skip-button" style="display:none" class="w3-bar-item w3-button" onClick="gotonext(1);">skip</button>
-               <button id="ctdl-goto-button" style="display:none" class="w3-bar-item w3-button" onClick="gotonext(2);">goto</button>
-               <button id="lilo" class="w3-bar-item w3-button">Login</button>
+               <button id="ctdl-newmsg-button" style="display:none" onClick="entmsg_dispatcher();">enter</button>
+               <button id="ctdl-ungoto-button" style="display:none" onClick="gotonext(0);">ungoto</button>
+               <button id="ctdl-skip-button" style="display:none" onClick="gotonext(1);">skip</button>
+               <button id="ctdl-goto-button" style="display:none" onClick="gotonext(2);">goto</button>
+               <button id="lilo">Login</button>
        </div>
 
-       <div class="ctdl-grid-item-2" id="navbar">
+       <div class="ctdl-grid-navbar-item" id="navbar">
                <ul id="ctdl-sidebar" class="ctdl-sidebar-class">
                        <li><i class="fa fa-user-circle fa-3x"></i>
                        <li><span id="current_user">Not logged in.</span><br>
@@ -52,11 +52,11 @@ MODAL LOADING
                </ul>
        </div>
 
-       <div class="ctdl-grid-item-3" id="ctdl-main">
+       <div class="ctdl-grid-main-item" id="ctdl-main">
                Loading...
        </div>
 
-</div><!--class="ctdl-grid-container"-->
+</div><!--class="ctdl-main-grid-container"-->
 
 <script type="text/javascript" src="js/defs.js"></script>
 <script type="text/javascript" src="js/util.js"></script>