Fossil SCM

Add the /chat-delete page that can be used to by an XHR to delete a particular chat message.

drh 2020-12-23 15:35 chatroom-dev
Commit 2480ce94653f2b9a0faa998b1c25975b2adb792c0dd5827cc8f38ae7393fe443
1 file changed +62 -11
+62 -11
--- src/chat.c
+++ src/chat.c
@@ -152,16 +152,17 @@
152152
/* Definition of repository tables used by chat
153153
*/
154154
static const char zChatSchema1[] =
155155
@ CREATE TABLE repository.chat(
156156
@ msgid INTEGER PRIMARY KEY AUTOINCREMENT,
157
-@ mtime JULIANDAY,
158
-@ xfrom TEXT,
159
-@ xmsg TEXT,
160
-@ file BLOB,
161
-@ fname TEXT,
162
-@ fmime TEXT
157
+@ mtime JULIANDAY, -- Time for this entry - Julianday Zulu
158
+@ xfrom TEXT, -- Login of the sender
159
+@ xmsg TEXT, -- Raw, unformatted text of the message
160
+@ file BLOB, -- Text of the uploaded file, or NULL
161
+@ fname TEXT, -- Filename of the uploaded file, or NULL
162
+@ fmime TEXT, -- MIMEType of the upload file, or NULL
163
+@ mdel INT -- msgid of another message to delete
163164
@ );
164165
;
165166
166167
167168
/*
@@ -169,10 +170,12 @@
169170
** if they do not.
170171
*/
171172
static void chat_create_tables(void){
172173
if( !db_table_exists("repository","chat") ){
173174
db_multi_exec(zChatSchema1/*works-like:""*/);
175
+ }else if( !db_table_has_column("repository","chat","mdel") ){
176
+ db_multi_exec("ALTER TABLE chat ADD COLUMN mdel INT");
174177
}
175178
}
176179
177180
/*
178181
** WEBPAGE: chat-send
@@ -235,18 +238,21 @@
235238
** | "uclr": text // Color string associated with the user
236239
** | "xmsg": text // HTML text of the message
237240
** | "fsize": integer // file attachment size in bytes
238241
** | "fname": text // Name of file attachment
239242
** | "fmime": text // MIME-type of file attachment
243
+** | "mdel": integer // message id of prior message to delete
240244
** | }
241245
** | ]
242246
** | }
243247
**
244248
** The "fname" and "fmime" fields are only present if "fsize" is greater
245249
** than zero. The "xmsg" field may be an empty string if "fsize" is zero.
246250
**
247251
** The "msgid" values will be in increasing order.
252
+**
253
+** The "mdel" will only exist if "xmsg" is an empty string and "fsize" is zero.
248254
*/
249255
void chat_poll_webpage(void){
250256
Blob json; /* The json to be constructed and returned */
251257
sqlite3_int64 dataVersion; /* Data version. Used for polling. */
252258
sqlite3_int64 newDataVers;
@@ -258,11 +264,12 @@
258264
if( !g.perm.Chat ) return;
259265
chat_create_tables();
260266
cgi_set_content_type("text/json");
261267
dataVersion = db_int64(0, "PRAGMA data_version");
262268
db_prepare(&q1,
263
- "SELECT msgid, datetime(mtime), xfrom, xmsg, length(file), fname, fmime"
269
+ "SELECT msgid, datetime(mtime), xfrom, xmsg, length(file),"
270
+ " fname, fmime, mdel"
264271
" FROM chat"
265272
" WHERE msgid>%d"
266273
" ORDER BY msgid",
267274
msgid
268275
);
@@ -272,13 +279,14 @@
272279
while( db_step(&q1)==SQLITE_ROW ){
273280
int id = db_column_int(&q1, 0);
274281
const char *zDate = db_column_text(&q1, 1);
275282
const char *zFrom = db_column_text(&q1, 2);
276283
const char *zRawMsg = db_column_text(&q1, 3);
277
- const int nByte = db_column_int(&q1, 4);
284
+ int nByte = db_column_int(&q1, 4);
278285
const char *zFName = db_column_text(&q1, 5);
279286
const char *zFMime = db_column_text(&q1, 6);
287
+ int iToDel = db_column_int(&q1, 7);
280288
char *zMsg;
281289
cnt++;
282290
blob_append(&json, zSep, -1);
283291
zSep = ",\n";
284292
blob_appendf(&json, "{\"msgid\":%d,\"mtime\":%!j,", id, zDate);
@@ -286,20 +294,25 @@
286294
blob_appendf(&json, "\"uclr\":%!j,", hash_color(zFrom));
287295
288296
/* TBD: Convert the raw message into HTML, perhaps by running it
289297
** through a text formatter, or putting markup on @name phrases,
290298
** etc. */
291
- zMsg = mprintf("%h", zRawMsg);
299
+ zMsg = mprintf("%h", zRawMsg ? zRawMsg : "");
292300
blob_appendf(&json, "\"xmsg\":%!j,", zMsg);
293301
fossil_free(zMsg);
294302
295303
if( nByte==0 ){
296
- blob_appendf(&json, "\"fsize\":0}");
304
+ blob_appendf(&json, "\"fsize\":0");
297305
}else{
298
- blob_appendf(&json, "\"fsize\":%d,\"fname\":%!j,\"fmime\":%!j}",
306
+ blob_appendf(&json, "\"fsize\":%d,\"fname\":%!j,\"fmime\":%!j",
299307
nByte, zFName, zFMime);
300308
}
309
+ if( iToDel ){
310
+ blob_appendf(&json, ",\"mdel\":%d}", iToDel);
311
+ }else{
312
+ blob_append(&json, "}", 1);
313
+ }
301314
}
302315
if( cnt ){
303316
blob_append(&json, "\n]}", 3);
304317
cgi_set_content(&json);
305318
break;
@@ -341,5 +354,43 @@
341354
if( zMime==0 ) return;
342355
db_blob(&r, "SELECT file FROM chat WHERE msgid=%d", msgid);
343356
cgi_set_content_type(zMime);
344357
cgi_set_content(&r);
345358
}
359
+
360
+
361
+/*
362
+** WEBPAGE: chat-delete
363
+**
364
+** Delete the chat entry identified by the name query parameter.
365
+** Invoking fetch("chat-delete/"+msgid) from javascript in the client
366
+** will delete a chat entry from the CHAT table.
367
+**
368
+** This routine both deletes the identified chat entry and also inserts
369
+** a new entry with the current timestamp and with:
370
+**
371
+** * xmsg = NULL
372
+** * file = NULL
373
+** * mdel = The msgid of the row that was deleted
374
+**
375
+** This new entry will then be propagated to all listeners so that they
376
+** will know to delete their copies of the message too.
377
+*/
378
+void chat_delete_webpage(void){
379
+ int mdel;
380
+ char *zOwner;
381
+ login_check_credentials();
382
+ if( !g.perm.Chat ) return;
383
+ chat_create_tables();
384
+ mdel = atoi(PD("name","0"));
385
+ zOwner = db_text(0, "SELECT xfrom FROM chat WHERE msgid=%d", mdel);
386
+ if( zOwner==0 ) return;
387
+ if( fossil_strcmp(zOwner, g.zLogin)!=0 && !g.perm.Admin ) return;
388
+ db_multi_exec(
389
+ "BEGIN;\n"
390
+ "DELETE FROM chat WHERE msgid=%d;\n"
391
+ "INSERT INTO chat(mtime, xfrom, mdel)"
392
+ " VALUES(julianday('now'), %Q, %d);\n"
393
+ "COMMIT;",
394
+ mdel, g.zLogin, mdel
395
+ );
396
+}
346397
--- src/chat.c
+++ src/chat.c
@@ -152,16 +152,17 @@
152 /* Definition of repository tables used by chat
153 */
154 static const char zChatSchema1[] =
155 @ CREATE TABLE repository.chat(
156 @ msgid INTEGER PRIMARY KEY AUTOINCREMENT,
157 @ mtime JULIANDAY,
158 @ xfrom TEXT,
159 @ xmsg TEXT,
160 @ file BLOB,
161 @ fname TEXT,
162 @ fmime TEXT
 
163 @ );
164 ;
165
166
167 /*
@@ -169,10 +170,12 @@
169 ** if they do not.
170 */
171 static void chat_create_tables(void){
172 if( !db_table_exists("repository","chat") ){
173 db_multi_exec(zChatSchema1/*works-like:""*/);
 
 
174 }
175 }
176
177 /*
178 ** WEBPAGE: chat-send
@@ -235,18 +238,21 @@
235 ** | "uclr": text // Color string associated with the user
236 ** | "xmsg": text // HTML text of the message
237 ** | "fsize": integer // file attachment size in bytes
238 ** | "fname": text // Name of file attachment
239 ** | "fmime": text // MIME-type of file attachment
 
240 ** | }
241 ** | ]
242 ** | }
243 **
244 ** The "fname" and "fmime" fields are only present if "fsize" is greater
245 ** than zero. The "xmsg" field may be an empty string if "fsize" is zero.
246 **
247 ** The "msgid" values will be in increasing order.
 
 
248 */
249 void chat_poll_webpage(void){
250 Blob json; /* The json to be constructed and returned */
251 sqlite3_int64 dataVersion; /* Data version. Used for polling. */
252 sqlite3_int64 newDataVers;
@@ -258,11 +264,12 @@
258 if( !g.perm.Chat ) return;
259 chat_create_tables();
260 cgi_set_content_type("text/json");
261 dataVersion = db_int64(0, "PRAGMA data_version");
262 db_prepare(&q1,
263 "SELECT msgid, datetime(mtime), xfrom, xmsg, length(file), fname, fmime"
 
264 " FROM chat"
265 " WHERE msgid>%d"
266 " ORDER BY msgid",
267 msgid
268 );
@@ -272,13 +279,14 @@
272 while( db_step(&q1)==SQLITE_ROW ){
273 int id = db_column_int(&q1, 0);
274 const char *zDate = db_column_text(&q1, 1);
275 const char *zFrom = db_column_text(&q1, 2);
276 const char *zRawMsg = db_column_text(&q1, 3);
277 const int nByte = db_column_int(&q1, 4);
278 const char *zFName = db_column_text(&q1, 5);
279 const char *zFMime = db_column_text(&q1, 6);
 
280 char *zMsg;
281 cnt++;
282 blob_append(&json, zSep, -1);
283 zSep = ",\n";
284 blob_appendf(&json, "{\"msgid\":%d,\"mtime\":%!j,", id, zDate);
@@ -286,20 +294,25 @@
286 blob_appendf(&json, "\"uclr\":%!j,", hash_color(zFrom));
287
288 /* TBD: Convert the raw message into HTML, perhaps by running it
289 ** through a text formatter, or putting markup on @name phrases,
290 ** etc. */
291 zMsg = mprintf("%h", zRawMsg);
292 blob_appendf(&json, "\"xmsg\":%!j,", zMsg);
293 fossil_free(zMsg);
294
295 if( nByte==0 ){
296 blob_appendf(&json, "\"fsize\":0}");
297 }else{
298 blob_appendf(&json, "\"fsize\":%d,\"fname\":%!j,\"fmime\":%!j}",
299 nByte, zFName, zFMime);
300 }
 
 
 
 
 
301 }
302 if( cnt ){
303 blob_append(&json, "\n]}", 3);
304 cgi_set_content(&json);
305 break;
@@ -341,5 +354,43 @@
341 if( zMime==0 ) return;
342 db_blob(&r, "SELECT file FROM chat WHERE msgid=%d", msgid);
343 cgi_set_content_type(zMime);
344 cgi_set_content(&r);
345 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
346
--- src/chat.c
+++ src/chat.c
@@ -152,16 +152,17 @@
152 /* Definition of repository tables used by chat
153 */
154 static const char zChatSchema1[] =
155 @ CREATE TABLE repository.chat(
156 @ msgid INTEGER PRIMARY KEY AUTOINCREMENT,
157 @ mtime JULIANDAY, -- Time for this entry - Julianday Zulu
158 @ xfrom TEXT, -- Login of the sender
159 @ xmsg TEXT, -- Raw, unformatted text of the message
160 @ file BLOB, -- Text of the uploaded file, or NULL
161 @ fname TEXT, -- Filename of the uploaded file, or NULL
162 @ fmime TEXT, -- MIMEType of the upload file, or NULL
163 @ mdel INT -- msgid of another message to delete
164 @ );
165 ;
166
167
168 /*
@@ -169,10 +170,12 @@
170 ** if they do not.
171 */
172 static void chat_create_tables(void){
173 if( !db_table_exists("repository","chat") ){
174 db_multi_exec(zChatSchema1/*works-like:""*/);
175 }else if( !db_table_has_column("repository","chat","mdel") ){
176 db_multi_exec("ALTER TABLE chat ADD COLUMN mdel INT");
177 }
178 }
179
180 /*
181 ** WEBPAGE: chat-send
@@ -235,18 +238,21 @@
238 ** | "uclr": text // Color string associated with the user
239 ** | "xmsg": text // HTML text of the message
240 ** | "fsize": integer // file attachment size in bytes
241 ** | "fname": text // Name of file attachment
242 ** | "fmime": text // MIME-type of file attachment
243 ** | "mdel": integer // message id of prior message to delete
244 ** | }
245 ** | ]
246 ** | }
247 **
248 ** The "fname" and "fmime" fields are only present if "fsize" is greater
249 ** than zero. The "xmsg" field may be an empty string if "fsize" is zero.
250 **
251 ** The "msgid" values will be in increasing order.
252 **
253 ** The "mdel" will only exist if "xmsg" is an empty string and "fsize" is zero.
254 */
255 void chat_poll_webpage(void){
256 Blob json; /* The json to be constructed and returned */
257 sqlite3_int64 dataVersion; /* Data version. Used for polling. */
258 sqlite3_int64 newDataVers;
@@ -258,11 +264,12 @@
264 if( !g.perm.Chat ) return;
265 chat_create_tables();
266 cgi_set_content_type("text/json");
267 dataVersion = db_int64(0, "PRAGMA data_version");
268 db_prepare(&q1,
269 "SELECT msgid, datetime(mtime), xfrom, xmsg, length(file),"
270 " fname, fmime, mdel"
271 " FROM chat"
272 " WHERE msgid>%d"
273 " ORDER BY msgid",
274 msgid
275 );
@@ -272,13 +279,14 @@
279 while( db_step(&q1)==SQLITE_ROW ){
280 int id = db_column_int(&q1, 0);
281 const char *zDate = db_column_text(&q1, 1);
282 const char *zFrom = db_column_text(&q1, 2);
283 const char *zRawMsg = db_column_text(&q1, 3);
284 int nByte = db_column_int(&q1, 4);
285 const char *zFName = db_column_text(&q1, 5);
286 const char *zFMime = db_column_text(&q1, 6);
287 int iToDel = db_column_int(&q1, 7);
288 char *zMsg;
289 cnt++;
290 blob_append(&json, zSep, -1);
291 zSep = ",\n";
292 blob_appendf(&json, "{\"msgid\":%d,\"mtime\":%!j,", id, zDate);
@@ -286,20 +294,25 @@
294 blob_appendf(&json, "\"uclr\":%!j,", hash_color(zFrom));
295
296 /* TBD: Convert the raw message into HTML, perhaps by running it
297 ** through a text formatter, or putting markup on @name phrases,
298 ** etc. */
299 zMsg = mprintf("%h", zRawMsg ? zRawMsg : "");
300 blob_appendf(&json, "\"xmsg\":%!j,", zMsg);
301 fossil_free(zMsg);
302
303 if( nByte==0 ){
304 blob_appendf(&json, "\"fsize\":0");
305 }else{
306 blob_appendf(&json, "\"fsize\":%d,\"fname\":%!j,\"fmime\":%!j",
307 nByte, zFName, zFMime);
308 }
309 if( iToDel ){
310 blob_appendf(&json, ",\"mdel\":%d}", iToDel);
311 }else{
312 blob_append(&json, "}", 1);
313 }
314 }
315 if( cnt ){
316 blob_append(&json, "\n]}", 3);
317 cgi_set_content(&json);
318 break;
@@ -341,5 +354,43 @@
354 if( zMime==0 ) return;
355 db_blob(&r, "SELECT file FROM chat WHERE msgid=%d", msgid);
356 cgi_set_content_type(zMime);
357 cgi_set_content(&r);
358 }
359
360
361 /*
362 ** WEBPAGE: chat-delete
363 **
364 ** Delete the chat entry identified by the name query parameter.
365 ** Invoking fetch("chat-delete/"+msgid) from javascript in the client
366 ** will delete a chat entry from the CHAT table.
367 **
368 ** This routine both deletes the identified chat entry and also inserts
369 ** a new entry with the current timestamp and with:
370 **
371 ** * xmsg = NULL
372 ** * file = NULL
373 ** * mdel = The msgid of the row that was deleted
374 **
375 ** This new entry will then be propagated to all listeners so that they
376 ** will know to delete their copies of the message too.
377 */
378 void chat_delete_webpage(void){
379 int mdel;
380 char *zOwner;
381 login_check_credentials();
382 if( !g.perm.Chat ) return;
383 chat_create_tables();
384 mdel = atoi(PD("name","0"));
385 zOwner = db_text(0, "SELECT xfrom FROM chat WHERE msgid=%d", mdel);
386 if( zOwner==0 ) return;
387 if( fossil_strcmp(zOwner, g.zLogin)!=0 && !g.perm.Admin ) return;
388 db_multi_exec(
389 "BEGIN;\n"
390 "DELETE FROM chat WHERE msgid=%d;\n"
391 "INSERT INTO chat(mtime, xfrom, mdel)"
392 " VALUES(julianday('now'), %Q, %d);\n"
393 "COMMIT;",
394 mdel, g.zLogin, mdel
395 );
396 }
397

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button