@@ -269,6 +269,22 @@ static cmark_node *match(cmark_syntax_extension *ext, cmark_parser *parser,
269
269
// inline was finished in inlines.c.
270
270
}
271
271
272
+ static bool validate_protocol (char protocol [], uint8_t * data , int rewind ) {
273
+ size_t len = strlen (protocol );
274
+
275
+ // Check that the protocol matches
276
+ for (int i = 1 ; i <= len ; i ++ ) {
277
+ if (data [- rewind - i ] != protocol [len - i ]) {
278
+ return false;
279
+ }
280
+ }
281
+
282
+ char prev_char = data [- rewind - len - 1 ];
283
+
284
+ // Make sure the character before the protocol is non-alphanumeric
285
+ return !cmark_isalnum (prev_char );
286
+ }
287
+
272
288
static void postprocess_text (cmark_parser * parser , cmark_node * text , int offset , int depth ) {
273
289
// postprocess_text can recurse very deeply if there is a very long line of
274
290
// '@' only. Stop at a reasonable depth to ensure it cannot crash.
@@ -278,6 +294,8 @@ static void postprocess_text(cmark_parser *parser, cmark_node *text, int offset,
278
294
uint8_t * data = text -> as .literal .data ,
279
295
* at ;
280
296
size_t size = text -> as .literal .len ;
297
+ bool auto_mailto = true;
298
+ bool is_xmpp = false;
281
299
int rewind , max_rewind ,
282
300
nb = 0 , np = 0 , ns = 0 ;
283
301
@@ -304,8 +322,18 @@ static void postprocess_text(cmark_parser *parser, cmark_node *text, int offset,
304
322
if (strchr (".+-_" , c ) != NULL )
305
323
continue ;
306
324
307
- if (c == '/' )
308
- ns ++ ;
325
+ if (strchr (":" , c ) != NULL ) {
326
+ if (validate_protocol ("mailto:" , data , rewind )) {
327
+ auto_mailto = false;
328
+ continue ;
329
+ }
330
+
331
+ if (validate_protocol ("xmpp:" , data , rewind )) {
332
+ auto_mailto = false;
333
+ is_xmpp = true;
334
+ continue ;
335
+ }
336
+ }
309
337
310
338
break ;
311
339
}
@@ -325,6 +353,8 @@ static void postprocess_text(cmark_parser *parser, cmark_node *text, int offset,
325
353
nb ++ ;
326
354
else if (c == '.' && link_end < size - 1 && cmark_isalnum (data [link_end + 1 ]))
327
355
np ++ ;
356
+ else if (c == '/' && is_xmpp )
357
+ continue ;
328
358
else if (c != '-' && c != '_' )
329
359
break ;
330
360
}
@@ -347,7 +377,8 @@ static void postprocess_text(cmark_parser *parser, cmark_node *text, int offset,
347
377
cmark_node * link_node = cmark_node_new_with_mem (CMARK_NODE_LINK , parser -> mem );
348
378
cmark_strbuf buf ;
349
379
cmark_strbuf_init (parser -> mem , & buf , 10 );
350
- cmark_strbuf_puts (& buf , "mailto:" );
380
+ if (auto_mailto )
381
+ cmark_strbuf_puts (& buf , "mailto:" );
351
382
cmark_strbuf_put (& buf , data - rewind , (bufsize_t )(link_end + rewind ));
352
383
link_node -> as .link .url = cmark_chunk_buf_detach (& buf );
353
384
0 commit comments