From a7151621005861c28d5ed726229c5ad2d5a57eec Mon Sep 17 00:00:00 2001 From: "Steffen (Daode) Nurpmeso" Date: Wed, 28 Sep 2016 16:05:16 +0200 Subject: [PATCH] Add a RFC 6068 url_mailto_to_address() hack for List-Post: --- cmd3.c | 14 ++++++-------- mime_param.c | 2 +- nailfuns.h | 6 +++++- nam_a_grp.c | 4 ++-- urlcrecry.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 70 insertions(+), 12 deletions(-) diff --git a/cmd3.c b/cmd3.c index 397930cf1..18574165d 100644 --- a/cmd3.c +++ b/cmd3.c @@ -314,15 +314,13 @@ jnext_msg: if (mft != NULL || (hf & HF_LIST_REPLY) || ok_blook(followup_to)) { /* Learn about a possibly sending mailing list; use do for break; */ if ((cp = hfield1("list-post", mp)) != NULL) do { - struct name *x = lextract(cp, GEXTRA | GSKIN); - if (x == NULL || x->n_flink != NULL || - !is_prefix("mailto:", x->n_name) || - /* XXX the mailto: prefix causes failure (":" invalid character) - * XXX which is why need to recreate a struct name with an - * XXX updated name; this is terribly wasteful and can't we find + struct name *x; + + if ((x = lextract(cp, GEXTRA | GSKIN)) == NULL || x->n_flink != NULL || + (cp = url_mailto_to_address(x->n_name)) == NULL || + /* XXX terribly wasteful to create a new name, and can't we find * XXX a way to mitigate that?? */ - is_addr_invalid(x = nalloc(x->n_name + sizeof("mailto:") -1, - GEXTRA | GSKIN), EACM_STRICT)) { + is_addr_invalid(x = nalloc(cp, GEXTRA | GSKIN), EACM_STRICT)) { if (options & OPT_D_V) n_err(_("Message contains invalid \"List-Post:\" header\n")); cp = NULL; diff --git a/mime_param.c b/mime_param.c index 5e4883c05..4ea2b2e28 100644 --- a/mime_param.c +++ b/mime_param.c @@ -466,7 +466,7 @@ __rfc2231_join(struct rfc2231_joiner *head, char **result, char const **emsg) cp += 2; i -= 3; } else { - jhex_putc: +jhex_putc: sin.s[sin.l++] = c; --i; } diff --git a/nailfuns.h b/nailfuns.h index 8100849f1..0c02df159 100644 --- a/nailfuns.h +++ b/nailfuns.h @@ -1429,7 +1429,7 @@ FL char const * mime_type_mimepart_handler(struct mimepart const *mpp); /* Allocate a single element of a name list, initialize its name field to the * passed name and return it */ -FL struct name * nalloc(char *str, enum gfield ntype); +FL struct name * nalloc(char const *str, enum gfield ntype); /* Like nalloc(), but initialize from content of np */ FL struct name * ndup(struct name *np, enum gfield ntype); @@ -2081,6 +2081,10 @@ FL char * urlxdec(char const *cp SALLOC_DEBUG_ARGS); # define urlxdec(CP) urlxdec(CP, __FILE__, __LINE__) #endif +/* Parse a RFC 6058 'mailto' URI to a single to: (TODO yes, for now hacky). + * Return NULL or something that can be converted to a struct name */ +FL char * url_mailto_to_address(char const *mailtop); + #ifdef HAVE_SOCKETS /* Return port of urlp->url_proto (and set irv_or_null), or NULL if unknown */ FL char const * url_servbyname(struct url const *urlp, ui16_t *irv_or_null); diff --git a/nam_a_grp.c b/nam_a_grp.c index 9b5df867a..cfeb04f29 100644 --- a/nam_a_grp.c +++ b/nam_a_grp.c @@ -886,7 +886,7 @@ _mlmux_linkout(struct group *gp) #endif /* HAVE_REGEX */ FL struct name * -nalloc(char *str, enum gfield ntype) +nalloc(char const *str, enum gfield ntype) { struct addrguts ag; struct str in, out; @@ -954,7 +954,7 @@ jskipfullextra: #ifdef HAVE_IDNA if (!(ag.ag_n_flags & NAME_IDNA)) { #endif - in.s = str; + in.s = UNCONST(str); in.l = ag.ag_ilen; #ifdef HAVE_IDNA } else { diff --git a/urlcrecry.c b/urlcrecry.c index f7aebbfd5..174a964a6 100644 --- a/urlcrecry.c +++ b/urlcrecry.c @@ -587,6 +587,62 @@ FL char * return n; } +FL char * +url_mailto_to_address(char const *mailtop){ /* TODO hack! RFC 6068; factory? */ + size_t i; + char *rv; + char const *mailtop_orig; + NYD_ENTER; + + if(!is_prefix("mailto:", mailtop_orig = mailtop)){ + rv = NULL; + goto jleave; + } + mailtop += sizeof("mailto:") -1; + + /* TODO This is all intermediate, and for now just enough to understand + * TODO a little bit of a little more advanced List-Post: headers. */ + /* Strip any hfield additions, keep only to addr-spec's */ + if((rv = strchr(mailtop, '?')) != NULL) + rv = savestrbuf(mailtop, i = PTR2SIZE(rv - mailtop)); + else + rv = savestrbuf(mailtop, i = strlen(mailtop)); + + i = strlen(rv); + + /* Simply perform percent-decoding if there is a percent % */ + if(memchr(rv, '%', i) != NULL){ + char *rv_base; + bool_t err; + + for(err = FAL0, mailtop = rv_base = rv; i > 0;){ + char c; + + if((c = *mailtop++) == '%'){ + si32_t cc; + + if(i < 3 || (cc = mime_hexseq_to_char(mailtop)) < 0){ + if(!err && (err = TRU1, options & OPT_D_V)) + n_err(_("Invalid RFC 6068 'mailto' URL: %s\n"), mailtop_orig); + goto jhex_putc; + } + *rv++ = (char)cc; + mailtop += 2; + i -= 3; + }else{ +jhex_putc: + *rv++ = c; + --i; + } + } + *rv = '\0'; + rv = rv_base; + } +jleave: + NYD_LEAVE; + return rv; +} + #ifdef HAVE_SOCKETS /* Note: not indented for that -- later: file:// etc.! */ FL char const * url_servbyname(struct url const *urlp, ui16_t *irv_or_null) -- 2.11.4.GIT