@@ -269,6 +269,22 @@ static cmark_node *match(cmark_syntax_extension *ext, cmark_parser *parser,
269269 // inline was finished in inlines.c.
270270}
271271
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+
272288static void postprocess_text (cmark_parser * parser , cmark_node * text , int offset , int depth ) {
273289 // postprocess_text can recurse very deeply if there is a very long line of
274290 // '@' 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,
278294 uint8_t * data = text -> as .literal .data ,
279295 * at ;
280296 size_t size = text -> as .literal .len ;
297+ bool auto_mailto = true;
298+ bool is_xmpp = false;
281299 int rewind , max_rewind ,
282300 nb = 0 , np = 0 , ns = 0 ;
283301
@@ -304,8 +322,18 @@ static void postprocess_text(cmark_parser *parser, cmark_node *text, int offset,
304322 if (strchr (".+-_" , c ) != NULL )
305323 continue ;
306324
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+ }
309337
310338 break ;
311339 }
@@ -325,6 +353,8 @@ static void postprocess_text(cmark_parser *parser, cmark_node *text, int offset,
325353 nb ++ ;
326354 else if (c == '.' && link_end < size - 1 && cmark_isalnum (data [link_end + 1 ]))
327355 np ++ ;
356+ else if (c == '/' && is_xmpp )
357+ continue ;
328358 else if (c != '-' && c != '_' )
329359 break ;
330360 }
@@ -347,7 +377,8 @@ static void postprocess_text(cmark_parser *parser, cmark_node *text, int offset,
347377 cmark_node * link_node = cmark_node_new_with_mem (CMARK_NODE_LINK , parser -> mem );
348378 cmark_strbuf buf ;
349379 cmark_strbuf_init (parser -> mem , & buf , 10 );
350- cmark_strbuf_puts (& buf , "mailto:" );
380+ if (auto_mailto )
381+ cmark_strbuf_puts (& buf , "mailto:" );
351382 cmark_strbuf_put (& buf , data - rewind , (bufsize_t )(link_end + rewind ));
352383 link_node -> as .link .url = cmark_chunk_buf_detach (& buf );
353384
0 commit comments