/* ** Copyright (c) 2020 D. Richard Hipp ** ** This program is free software; you can redistribute it and/or ** modify it under the terms of the Simplified BSD License (also ** known as the "2-Clause License" or "FreeBSD License".) ** ** This program is distributed in the hope that it will be useful, ** but without any warranty; without even the implied warranty of ** merchantability or fitness for a particular purpose. ** ** Author contact information: ** drh@hwaci.com ** http://www.hwaci.com/drh/ ** ******************************************************************************* ** ** This file contains code used to implement the Fossil chatroom. ** ** Initial design goals: ** ** * Keep it simple. This chatroom is not intended as a competitor ** or replacement for IRC, Discord, Telegram, Slack, etc. The goal ** is zero- or near-zero-configuration, not an abundance of features. ** ** * Intended as a place for insiders to have ephemeral conversations ** about a project. This is not a public gather place. Think ** "boardroom", not "corner pub". ** ** * One chatroom per repository. ** ** * Chat content lives in a single repository. It is never synced. ** Content expires and is deleted after a set interval (a week or so). ** ** Notification is accomplished using the "hanging GET" or "long poll" design ** in which a GET request is issued but the server does not send a reply until ** new content arrives. Newer Web Sockets and Server Sent Event protocols are ** more elegant, but are not compatible with CGI, and would thus complicate ** configuration. */ #include "config.h" #include #include "chat.h" /* ** WEBPAGE: chat ** ** Start up a browser-based chat session. */ void chat_webpage(void){ login_check_credentials(); style_set_current_feature("chat"); if( !g.perm.Chat ){ style_header("Chat Not Authorized"); @

Not Authorized

@

You do not have permission to use the chatroom on this @ repository.

style_finish_page(); return; } style_header("Chat"); @ @
@
@
@ @ @
@
@ File: @ @
@
@
@
/* New chat messages get inserted immediately after this element */ @ style_finish_page(); } /* Definition of repository tables used by chat */ static const char zChatSchema1[] = @ CREATE TABLE chat( @ msgid INTEGER PRIMARY KEY AUTOINCREMENT, @ mtime JULIANDAY, @ xfrom TEXT, @ xmsg TEXT, @ file BLOB, @ fname TEXT, @ fmime TEXT @ ); ; /* ** Make sure the repository data tables used by chat exist. Create them ** if they do not. */ static void chat_create_tables(void){ if( !db_table_exists("repository","chat") ){ db_multi_exec(zChatSchema1/*works-like:""*/); } } /* ** WEBPAGE: chat-send ** ** This page receives (via XHR) a new chat-message and/or a new file ** to be entered into the chat history. */ void chat_send_webpage(void){ login_check_credentials(); if( !g.perm.Chat ) return; chat_create_tables(); } /* ** WEBPAGE: chat-poll ** ** The chat page generated by /chat using a XHR to this page in order ** to ask for new chat content. The "name" argument should begin with ** an integer which is the largest "msgid" that the chat page currently ** holds. If newer content is available, this routine returns that ** content straight away. If no new content is available, this webpage ** blocks until the new content becomes available. In this way, the ** system implements "hanging-GET" or "long-poll" style event notification. ** ** The reply from this webpage is JSON that describes the new content. ** Format of the json: ** ** { ** "msg": [ ** { ** "msgid": integer // message id ** "mtime": text // When sent: YYYY-MM-DD HH:MM:SS UTC ** "xfrom": text // Login name of sender ** "uclr": text // Color string associated with the user ** "xmsg": text // HTML text of the message ** "fsize": integer // file attachment size in bytes ** "fname": text // Name of file attachment ** "fmime": text // MIME-type of file attachment ** } ** ] ** } ** ** The "fname" and "fmime" fields are only present if "fsize" is greater ** than zero. The "xmsg" field may be an empty string if "fsize" is zero. ** ** The "msgid" values will be in increasing order. */ void chat_poll_webpage(void){ login_check_credentials(); if( !g.perm.Chat ) return; chat_create_tables(); cgi_set_content_type("text/json"); } /* ** WEBPAGE: chat-download ** ** Download the CHAT.FILE attachment associated with a single chat ** entry. The "name" query parameter begins with an integer that ** identifies the particular chat message. */ void chat_download_webpage(void){ login_check_credentials(); if( !g.perm.Chat ) return; chat_create_tables(); }