/* * Copyright (c) 2003, 2005, 2006 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include "sm/generic.h" SM_RCSID("@(#)$Id: rfc2821local.c,v 1.6 2006/06/11 03:37:32 ca Exp $") #include "sm/assert.h" #include "sm/error.h" #include "sm/memops.h" #include "sm/ctype.h" #include "sm/rfc2821.h" #include "sm/rfc2822.h" /* ** T2821_EXTRACT_LOCAL -- extract localpart from a valid address ** ** Parameters: ** rpool -- rpool ** addr -- address ** delim_type -- type of delimiter (e.g., '+' or T2821_ENDTOK) ** plocal -- local part of address (output) ** ** Returns: ** usual error code ** ** NOTE: delim_type doesn't work, because '+', '-', ... ** are NOT delimiters right now. ** What will break if those are made delimiters? ** a@b-c.d would be parsed differently ** Make them only delimiters in localpart? Context sensitive ** scanning is probably a bad idea... ** Moreover, it breaks syntax checks in the parser. ** Summary: the local part should be treated only here... ** Do we need a real scanner/parse for it? It might be ** possible to "escape" delimiters, e.g., \+, even though ** that's not allowed in RFC 2821, so a simple strchr() ** doesn't work reliably. */ sm_ret_T t2821_extract_local(sm_rpool_P rpool, sm_a2821_T *addr, int delim_type, sm_a2821_T **plocal) { sm_t2821_P tok; sm_t2821_P t; sm_ret_T ret; SM_REQUIRE(addr != NULL); SM_REQUIRE(plocal != NULL); tok = A2821_FIRST(addr); if (tok->sm_t2821_type != T2821_LEFT) return sm_error_perm(SM_EM_ADDR, R2821_ERR_LEFT); /* XXX? */ tok = T2821_NEXT(tok); if (tok == NULL || tok == A2821_END(addr) || tok->sm_t2821_type == T2821_AT) return sm_error_perm(SM_EM_ADDR, R2821_ERR_LOCAL); /* XXX? */ /* ** Copy localpart of address. ** Note: if there's only a localpart (allowed for ) ** then it "stops" at T2821_RIGHT, not T2821_AT. */ while (tok != NULL && tok != A2821_END(addr) && tok->sm_t2821_type != T2821_AT && tok->sm_t2821_type != T2821_RIGHT && tok->sm_t2821_type != delim_type) { ret = t2821_cp_token(rpool, tok, &t); if (sm_is_err(ret)) goto error; tok = T2821_NEXT(tok); A2821_INSERT_TAIL(*plocal, t); } return SM_SUCCESS; error: /* remove unconnected token */ if (t != NULL) t2821_free(rpool, t); /* should cleanup addr, need to remember old value, free new ones */ return ret; }