@@ -243,10 +243,103 @@
243 243 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
db_step(&q);
244 244 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
db_finalize(&q);
245 245 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
blob_reset(&b);
246 246 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
247 247 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
248 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
249 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ /*
250 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** This routine receives raw (user-entered) message text and transforms
251 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** it into HTML that is safe to insert using innerHTML.
252 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ **
253 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** * HTML in the original text is escaped.
254 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ **
255 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** * Hyperlinks are identified and tagged. Hyperlinks are:
256 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ **
257 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** - Undelimited text of the form https:... or http:...
258 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** - Any text enclosed within [...]
259 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ **
260 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** Space to hold the returned string is obtained from fossil_malloc()
261 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** and must be freed by the caller.
262 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ */
263 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ static char *chat_format_to_html(const char *zMsg){
264 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ char *zSafe = mprintf("%h", zMsg);
265 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ int i, j, k;
266 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ Blob out;
267 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ char zClose[20];
268 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ blob_init(&out, 0, 0);
269 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ for(i=j=0; zSafe[i]; i++){
270 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( zSafe[i]=='[' ){
271 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ for(k=i+1; zSafe[k] && zSafe[k]!=']'; k++){}
272 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( zSafe[k]==']' ){
273 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zSafe[k] = 0;
274 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( j<i ){
275 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ blob_append(&out, zSafe + j, i-j);
276 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ j = i;
277 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
278 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ wiki_resolve_hyperlink(&out, WIKI_NOBADLINKS|WIKI_TARGET_BLANK,
279 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zSafe+i+1, zClose, sizeof(zClose), zSafe, 0);
280 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zSafe[k] = ']';
281 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ j++;
282 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ blob_append(&out, zSafe + j, k - j);
283 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ blob_append(&out, zClose, -1);
284 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ i = k;
285 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ j = k+1;
286 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ continue;
287 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
288 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }else if( zSafe[i]=='h'
289 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ && (strncmp(zSafe+i,"http:",5)==0
290 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ || strncmp(zSafe+i,"https:",6)==0) ){
291 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ for(k=i+1; zSafe[k] && !fossil_isspace(zSafe[k]); k++){}
292 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( zSafe[k] && k>i+7 ){
293 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ char c = zSafe[k];
294 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( !fossil_isalnum(zSafe[k-1]) && zSafe[k-1]!='/' ){
295 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ k--;
296 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ c = zSafe[k];
297 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
298 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( j<i ){
299 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ blob_append(&out, zSafe + j, i-j);
300 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ j = i;
301 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
302 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zSafe[k] = 0;
303 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ wiki_resolve_hyperlink(&out, WIKI_NOBADLINKS|WIKI_TARGET_BLANK,
304 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zSafe+i, zClose, sizeof(zClose), zSafe, 0);
305 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zSafe[k] = c;
306 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ blob_append(&out, zSafe + j, k - j);
307 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ blob_append(&out, zClose, -1);
308 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ i = j = k;
309 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ continue;
310 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
311 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
312 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
313 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( j<i ){
314 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ blob_append(&out, zSafe+j, j-i);
315 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
316 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ fossil_free(zSafe);
317 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ return blob_str(&out);
318 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
319 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
320 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ /*
321 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** COMMAND: test-chat-formatter
322 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ **
323 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** Usage: %fossil test-chat-formatter STRING ...
324 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ **
325 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** Transform each argument string into HTML that will display the
326 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** chat message. This is used to test the formatter and to verify
327 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** that a malicious message text will not cause HTML or JS injection
328 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** into the chat display in a browser.
329 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ */
330 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ void chat_test_formatter_cmd(void){
331 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ int i;
332 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ char *zOut;
333 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ db_find_and_open_repository(0,0);
334 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ g.perm.Hyperlink = 1;
335 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ for(i=0; i<g.argc; i++){
336 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zOut = chat_format_to_html(g.argv[i]);
337 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ fossil_print("[%d]: %s\n", i, zOut);
338 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ fossil_free(zOut);
339 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
340 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
248 341 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
249 342 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
/*
250 343 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
** WEBPAGE: chat-poll
251 344 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
**
252 345 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
** The chat page generated by /chat using a XHR to this page in order
@@ -336,14 +429,11 @@
336 429 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
zSep = ",\n";
337 430 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
blob_appendf(&json, "{\"msgid\":%d,\"mtime\":%!j,", id, zDate);
338 431 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
blob_appendf(&json, "\"xfrom\":%!j,", zFrom);
339 432 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
blob_appendf(&json, "\"uclr\":%!j,", hash_color(zFrom));
340 433 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
341 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- /* TBD: Convert the raw message into HTML, perhaps by running it
342 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- ** through a text formatter, or putting markup on @name phrases,
343 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- ** etc. */
344 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- zMsg = mprintf("%h", zRawMsg ? zRawMsg : "");
434 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zMsg = chat_format_to_html(zRawMsg ? zRawMsg : "");
345 435 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
blob_appendf(&json, "\"xmsg\":%!j,", zMsg);
346 436 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
fossil_free(zMsg);
347 437 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
348 438 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if( nByte==0 ){
349 439 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
blob_appendf(&json, "\"fsize\":0");
350 440 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!