99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
** point a web-browser at /chat and the screen fills with the latest
** chat messages, and waits for new one.
**
** Other /chat-OP pages are used by XHR requests from this page to
** send new chat message, delete older messages, or poll for changes.
*/
void chat_webpage(void){
int iPingTcp;
login_check_credentials();
if( !g.perm.Chat ){
login_needed(g.anon.Chat);
return;
}
iPingTcp = atoi(PD("ping","0"));
if( iPingTcp<1000 || iPingTcp>65535 ) iPingTcp = 0;
if( iPingTcp ) style_disable_csp();
style_set_current_feature("chat");
style_header("Chat");
@ <form accept-encoding="utf-8" id="chat-form" autocomplete="off">
@ <div id='chat-input-area'>
@ <div id='chat-input-line'>
@ <input type="text" name="msg" id="chat-input-single" \
@ placeholder="Type message here." autocomplete="off">
|
<
<
<
<
|
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
|
** point a web-browser at /chat and the screen fills with the latest
** chat messages, and waits for new one.
**
** Other /chat-OP pages are used by XHR requests from this page to
** send new chat message, delete older messages, or poll for changes.
*/
void chat_webpage(void){
login_check_credentials();
if( !g.perm.Chat ){
login_needed(g.anon.Chat);
return;
}
style_set_current_feature("chat");
style_header("Chat");
@ <form accept-encoding="utf-8" id="chat-form" autocomplete="off">
@ <div id='chat-input-area'>
@ <div id='chat-input-line'>
@ <input type="text" name="msg" id="chat-input-single" \
@ placeholder="Type message here." autocomplete="off">
|
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
|
@ <script nonce="%h(style_nonce())">/* chat.c:%d(__LINE__) */
/* We need an onload handler to ensure that window.fossil is
initialized before the chat init code runs. */
@ window.addEventListener('load', function(){
@ document.body.classList.add('chat')
@ /*^^^for skins which add their own BODY tag */;
@ window.fossil.config.chat = {
@ pingTcp: %d(iPingTcp),
@ initSize: %d(db_get_int("chat-initial-history",50)),
@ imagesInline: !!%d(db_get_boolean("chat-inline-images",1))
@ };
cgi_append_content(builtin_text("chat.js"),-1);
@ }, false);
@ </script>
|
|
|
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
|
@ <script nonce="%h(style_nonce())">/* chat.c:%d(__LINE__) */
/* We need an onload handler to ensure that window.fossil is
initialized before the chat init code runs. */
@ window.addEventListener('load', function(){
@ document.body.classList.add('chat')
@ /*^^^for skins which add their own BODY tag */;
@ window.fossil.config.chat = {
@ fromcli: %h(PB("cli")?"true":"false"),
@ initSize: %d(db_get_int("chat-initial-history",50)),
@ imagesInline: !!%d(db_get_boolean("chat-inline-images",1))
@ };
cgi_append_content(builtin_text("chat.js"),-1);
@ }, false);
@ </script>
|
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
|
" VALUES(julianday('now'), %Q, %d);\n"
"COMMIT;",
mdel, g.zLogin, mdel
);
}
/*
** WEBPAGE: chat-ping
**
** HTTP requests coming to this page from a loopback IP address cause
** a single \007 (bel) character to be written on the controlling TTY.
** This is used to implement an audiable alert by local web clients.
*/
void chat_ping_webpage(void){
const char *zIpAddr = PD("REMOTE_ADDR","nil");
if( cgi_is_loopback(zIpAddr) ){
cgi_append_header("Access-Control-Allow-Origin: *\r\n");
fputc(7, stderr);
}
}
/*
** WEBPAGE: chat-audio-received
**
** Responds with an audio stream suitable for use as a /chat
** new-message-arrived notification.
*/
void chat_audio_alert(void){
Blob audio = empty_blob;
int n = 0;
const char * zAudio =
(const char *)builtin_file("sounds/chat-received.wav", &n);
blob_init(&audio, zAudio, n);
cgi_set_content_type("audio/wav");
cgi_set_content(&audio);
}
/*
** COMMAND: chat
**
** Usage: %fossil chat ?URL?
**
** Bring up a window to the chatroom feature of the Fossil repository
** at URL. Or if URL is not specified, use the default remote repository.
** Event notifications on this session cause the U+0007 character to
** be sent to the TTY on which the "fossil chat" command is run, thus
** causing an auditory notification.
*/
void chat_command(void){
const char *zUrl = 0;
size_t i;
char *azArgv[5];
db_find_and_open_repository(0,0);
if( g.argc==3 ){
zUrl = g.argv[2];
}else if( g.argc!=2 ){
usage("?URL?");
}else{
zUrl = db_get("last-sync-url",0);
if( zUrl==0 ){
fossil_fatal("no \"remote\" repository defined. Use a URL argument");
}
url_parse(zUrl, 0);
if( g.url.port==g.url.dfltPort ){
zUrl = mprintf(
"%s://%T%T",
g.url.protocol, g.url.name, g.url.path
);
}else{
zUrl = mprintf(
"%s://%T:%d%T",
g.url.protocol, g.url.name, g.url.port, g.url.path
);
}
}
if( strncmp(zUrl,"http://",7)!=0 && strncmp("https://",zUrl,8)!=0 ){
fossil_fatal("Not a valid URL: %s", zUrl);
}
azArgv[0] = g.argv[0];
azArgv[1] = "ui";
azArgv[2] = "--internal-chat-url";
i = strlen(zUrl);
if( i && zUrl[i-1]=='/' ) i--;
azArgv[3] = mprintf("%.*s/chat?ping=%%d", i, zUrl);
azArgv[4] = 0;
g.argv = azArgv;
g.argc = 4;
cmd_webserver();
}
|
|
<
<
<
<
<
<
<
<
<
<
<
|
<
<
|
<
<
|
|
|
|
<
<
<
|
|
|
|
<
<
|
<
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
<
|
<
<
<
<
<
|
|
<
<
<
|
|
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
|
" VALUES(julianday('now'), %Q, %d);\n"
"COMMIT;",
mdel, g.zLogin, mdel
);
}
/*
** WEBPAGE: chat-alert
**
** Return the sound file that should be played when a new chat message
** arrives.
*/
void chat_audio_alert(void){
Blob audio = empty_blob;
int n = 0;
const char * zAudio =
(const char *)builtin_file("sounds/plunk.wav", &n);
blob_init(&audio, zAudio, n);
cgi_set_content_type("audio/wav");
cgi_set_content(&audio);
}
/*
** COMMAND: chat
**
** Usage: %fossil chat
**
** Bring up a web-browser window to the chatroom of the default
** remote Fossil repository.
*/
void chat_command(void){
const char *zUrl;
const char *zBrowser;
char *zCmd;
db_find_and_open_repository(0,0);
if( g.argc!=2 ){
usage("");
}
zUrl = db_get("last-sync-url",0);
if( zUrl==0 ){
fossil_fatal("no \"remote\" repository defined");
}
url_parse(zUrl, 0);
if( g.url.port==g.url.dfltPort ){
zUrl = mprintf(
"%s://%T%T",
g.url.protocol, g.url.name, g.url.path
);
}else{
zUrl = mprintf(
"%s://%T:%d%T",
g.url.protocol, g.url.name, g.url.port, g.url.path
);
}
zBrowser = fossil_web_browser();
if( zBrowser==0 ) return;
zCmd = mprintf("%s \"%s/chat?cli\" &", zBrowser, zUrl);
fossil_system(zCmd);
}
|