char *parse_addr_spec(char *const buffer, const char *const end, struct to_body *const to_b, const int allow_comma_sep) { int status; int saved_status; char *tmp, *foo; saved_status = START_TO; /* fixes gcc 4.x warning */ status = START_TO; memset(to_b, 0, sizeof(struct to_body)); to_b->error = PARSE_OK; foo = 0; for(tmp = buffer; tmp < end; tmp++) { switch(*tmp) { case ' ': case '\t': switch(status) { case F_CRLF: case F_LF: case F_CR: /*previous=crlf and now =' '*/ status = saved_status; break; case URI_ENCLOSED: to_b->uri.len = tmp - to_b->uri.s; status = E_URI_ENCLOSED; break; case URI_OR_TOKEN: foo = tmp; status = MAYBE_URI_END; break; case DISPLAY_TOKEN: foo = tmp; status = DISPLAY_TOKEN_SP; break; } break; case '\n': switch(status) { case URI_OR_TOKEN: foo = tmp; status = MAYBE_URI_END; case MAYBE_URI_END: case DISPLAY_TOKEN_SP: case E_DISPLAY_QUOTED: case END: saved_status = status; status = F_LF; break; case DISPLAY_TOKEN: foo = tmp; saved_status = DISPLAY_TOKEN_SP; status = F_LF; break; case F_CR: status = F_CRLF; break; case F_CRLF: case F_LF: status = saved_status; goto endofheader; default: LM_ERR("unexpected char [%c] in status %d: [%.*s] .\n", *tmp, status, (int)(tmp - buffer), ZSW(buffer)); goto error; } break; case '\r': switch(status) { case URI_OR_TOKEN: foo = tmp; status = MAYBE_URI_END; case MAYBE_URI_END: case DISPLAY_TOKEN_SP: case E_DISPLAY_QUOTED: case END: saved_status = status; status = F_CR; break; case DISPLAY_TOKEN: foo = tmp; saved_status = DISPLAY_TOKEN_SP; status = F_CR; break; case F_CRLF: case F_CR: case F_LF: status = saved_status; goto endofheader; default: LM_ERR("unexpected char [%c] in status %d: [%.*s] .\n", *tmp, status, (int)(tmp - buffer), ZSW(buffer)); goto error; } break; case 0: switch(status) { case URI_OR_TOKEN: case MAYBE_URI_END: to_b->uri.len = tmp - to_b->uri.s; case END: saved_status = status = END; goto endofheader; default: LM_ERR("unexpected char [%c] in status %d: [%.*s] .\n", *tmp, status, (int)(tmp - buffer), ZSW(buffer)); goto error; } break; case '\\': switch(status) { case DISPLAY_QUOTED: tmp++; /* jump over next char */ break; default: LM_ERR("unexpected char [%c] in status %d: [%.*s] .\n", *tmp, status, (int)(tmp - buffer), ZSW(buffer)); goto error; } break; case '<': switch(status) { case START_TO: to_b->body.s = tmp; status = S_URI_ENCLOSED; break; case DISPLAY_QUOTED: break; case E_DISPLAY_QUOTED: status = S_URI_ENCLOSED; break; case URI_OR_TOKEN: case DISPLAY_TOKEN: to_b->display.len = tmp - to_b->display.s; status = S_URI_ENCLOSED; break; case DISPLAY_TOKEN_SP: case MAYBE_URI_END: to_b->display.len = foo - to_b->display.s; status = S_URI_ENCLOSED; break; case F_CRLF: case F_LF: case F_CR: /*previous=crlf and now !=' '*/ goto endofheader; default: LM_ERR("unexpected char [%c] in status %d: [%.*s] .\n", *tmp, status, (int)(tmp - buffer), ZSW(buffer)); goto error; } break; case '>': switch(status) { case DISPLAY_QUOTED: break; case URI_ENCLOSED: to_b->uri.len = tmp - to_b->uri.s; case E_URI_ENCLOSED: status = END; foo = 0; break; case F_CRLF: case F_LF: case F_CR: /*previous=crlf and now !=' '*/ goto endofheader; default: LM_ERR("unexpected char [%c] in status %d: [%.*s] .\n", *tmp, status, (int)(tmp - buffer), ZSW(buffer)); goto error; } break; case '"': switch(status) { case START_TO: to_b->body.s = tmp; to_b->display.s = tmp; status = DISPLAY_QUOTED; break; case DISPLAY_QUOTED: status = E_DISPLAY_QUOTED; to_b->display.len = tmp - to_b->display.s + 1; break; case F_CRLF: case F_LF: case F_CR: /*previous=crlf and now !=' '*/ goto endofheader; default: LM_ERR("unexpected char [%c] in status %d: [%.*s] .\n", *tmp, status, (int)(tmp - buffer), buffer); goto error; } break; case ';': switch(status) { case DISPLAY_QUOTED: case URI_ENCLOSED: break; case URI_OR_TOKEN: foo = tmp; case MAYBE_URI_END: to_b->uri.len = foo - to_b->uri.s; case END: to_b->body.len = tmp - to_b->body.s; tmp = parse_to_param( tmp, end, to_b, allow_comma_sep, &saved_status); goto endofheader; case F_CRLF: case F_LF: case F_CR: /*previous=crlf and now !=' '*/ goto endofheader; default: LM_ERR("unexpected char [%c] in status %d: [%.*s] .\n", *tmp, status, (int)(tmp - buffer), buffer); goto error; } break; case ',': if(allow_comma_sep) { switch(status) { case DISPLAY_QUOTED: case URI_ENCLOSED: break; case URI_OR_TOKEN: foo = tmp; case MAYBE_URI_END: to_b->uri.len = foo - to_b->uri.s; case END: to_b->body.len = tmp - to_b->body.s; saved_status = END; goto endofheader; case F_CRLF: case F_LF: case F_CR: /*previous=crlf and now !=' '*/ goto endofheader; default: LM_ERR("unexpected char [%c] in status %d: [%.*s] " ".\n", *tmp, status, (int)(tmp - buffer), buffer); goto error; } break; } /* If commas not allowed treat as a default character */ default: switch(status) { case START_TO: to_b->uri.s = to_b->body.s = tmp; status = URI_OR_TOKEN; to_b->display.s = tmp; break; case S_URI_ENCLOSED: to_b->uri.s = tmp; status = URI_ENCLOSED; break; case MAYBE_URI_END: case DISPLAY_TOKEN_SP: status = DISPLAY_TOKEN; case DISPLAY_QUOTED: case DISPLAY_TOKEN: case URI_ENCLOSED: case URI_OR_TOKEN: break; case F_CRLF: case F_LF: case F_CR: /*previous=crlf and now !=' '*/ goto endofheader; default: LM_DBG("spitting out [%c] in status %d\n", *tmp, status); goto error; } } /*char switch*/ } /*for*/ /* Reached end of buffer */ switch(status) { case URI_OR_TOKEN: case MAYBE_URI_END: case END: saved_status = status; foo = tmp; } endofheader: if(to_b->display.len == 0) to_b->display.s = 0; status = saved_status; LM_DBG("end of header reached, state=%d\n", status); /* check if error*/ switch(status) { case URI_OR_TOKEN: case MAYBE_URI_END: to_b->uri.len = foo - to_b->uri.s; case END: to_b->body.len = tmp - to_b->body.s; case E_PARA_VALUE: break; default: LM_ERR("invalid To - unexpected " "end of header in state %d\n", status); goto error; } return tmp; error: free_to_params(to_b); to_b->error = PARSE_ERROR; return tmp; }
char* parse_to(char* buffer, char *end, struct to_body *to_b) { int status; int saved_status; char *tmp; char *end_mark; status=START_TO; saved_status=START_TO; to_b->error=PARSE_OK; to_b->uri.len = 0; to_b->uri.s= 0; to_b->display.len = 0; to_b->display.s = 0; end_mark=0; for( tmp=buffer; tmp<end; tmp++) { switch(*tmp) { case ' ': case '\t': switch (status) { case F_CRLF: case F_LF: case F_CR: /*previous=crlf and now =' '*/ status=saved_status; break; case URI_ENCLOSED: to_b->uri.len = tmp - to_b->uri.s; status = E_URI_ENCLOSED; break; case URI_OR_TOKEN: status = MAYBE_URI_END; end_mark = tmp; break; case DISPLAY_TOKEN: end_mark = tmp; status = DISPLAY_TOKEN2; break; } break; case '\n': switch (status) { case URI_OR_TOKEN: end_mark = tmp; status = MAYBE_URI_END; case MAYBE_URI_END: case DISPLAY_TOKEN: case DISPLAY_TOKEN2: case E_DISPLAY_QUOTED: case END: saved_status=status; status=F_LF; break; case F_CR: status=F_CRLF; break; case F_CRLF: case F_LF: status=saved_status; goto endofheader; default: goto parse_error; } break; case '\r': switch (status) { case URI_OR_TOKEN: end_mark = tmp; status = MAYBE_URI_END; case MAYBE_URI_END: case DISPLAY_TOKEN: case DISPLAY_TOKEN2: case E_DISPLAY_QUOTED: case END: saved_status=status; status=F_CR; break; case F_CRLF: case F_CR: case F_LF: status=saved_status; goto endofheader; default: goto parse_error; } break; case 0: switch (status) { case URI_OR_TOKEN: case MAYBE_URI_END: to_b->uri.len = tmp - to_b->uri.s; case END: saved_status = status = END; goto endofheader; default: goto parse_error; } break; case '\\': switch (status) { case DISPLAY_QUOTED: tmp++; /* jump over next char */ break; default: goto parse_error; } break; case '<': switch (status) { case START_TO: to_b->body.s=tmp; status = S_URI_ENCLOSED; break; case DISPLAY_QUOTED: break; case E_DISPLAY_QUOTED: status = S_URI_ENCLOSED; break; case URI_OR_TOKEN: case DISPLAY_TOKEN: end_mark = tmp; case DISPLAY_TOKEN2: case MAYBE_URI_END: to_b->display.len=end_mark-to_b->display.s; status = S_URI_ENCLOSED; break; case F_CRLF: case F_LF: case F_CR: /*previous=crlf and now !=' '*/ goto endofheader; default: goto parse_error; } break; case '>': switch (status) { case DISPLAY_QUOTED: break; case URI_ENCLOSED: to_b->uri.len = tmp - to_b->uri.s; case E_URI_ENCLOSED: status = END; break; case F_CRLF: case F_LF: case F_CR: /*previous=crlf and now !=' '*/ goto endofheader; default: goto parse_error; } break; case '"': switch (status) { case START_TO: to_b->body.s = tmp; to_b->display.s = tmp; status = DISPLAY_QUOTED; break; case DISPLAY_QUOTED: status = E_DISPLAY_QUOTED; to_b->display.len = tmp-to_b->display.s+1; break; case F_CRLF: case F_LF: case F_CR: /*previous=crlf and now !=' '*/ goto endofheader; default: goto parse_error; } break; case ';' : switch (status) { case DISPLAY_QUOTED: case DISPLAY_TOKEN: case URI_ENCLOSED: break; case URI_OR_TOKEN: end_mark = tmp; case MAYBE_URI_END: to_b->uri.len = end_mark - to_b->uri.s; case END: to_b->body.len = tmp-to_b->body.s; tmp = parse_to_param(tmp,end,to_b,&saved_status); goto endofheader; case F_CRLF: case F_LF: case F_CR: /*previous=crlf and now !=' '*/ goto endofheader; default: goto parse_error; } break; default: switch (status) { case START_TO: to_b->uri.s = to_b->body.s = tmp; status = URI_OR_TOKEN; to_b->display.s=tmp; break; case S_URI_ENCLOSED: to_b->uri.s=tmp; status=URI_ENCLOSED; break; case MAYBE_URI_END: case DISPLAY_TOKEN2: status = DISPLAY_TOKEN; case DISPLAY_QUOTED: case DISPLAY_TOKEN: case URI_ENCLOSED: case URI_OR_TOKEN: break; case F_CRLF: case F_LF: case F_CR: /*previous=crlf and now !=' '*/ goto endofheader; default: LM_DBG("spitting out [%c] in status %d\n", *tmp,status ); goto error; } }/*char switch*/ }/*for*/ endofheader: if (to_b->display.len==0) to_b->display.s=0; status=saved_status; LM_DBG("end of header reached, state=%d\n", status); /* check if error*/ switch(status){ case MAYBE_URI_END: to_b->uri.len = end_mark - to_b->uri.s; case END: to_b->body.len = tmp - to_b->body.s; case E_PARA_VALUE: break; default: LM_ERR("unexpected end of header in state %d\n", status); goto error; } LM_DBG("display={%.*s}, ruri={%.*s}\n", to_b->display.len, ZSW(to_b->display.s), to_b->uri.len, ZSW(to_b->uri.s)); return tmp; parse_error: LM_ERR("unexpected char [%c] in status %d: <<%.*s>> .\n", *tmp,status, (int)(tmp-buffer), buffer); error: to_b->error=PARSE_ERROR; return tmp; }
char* parse_to(char* buffer, char *end, struct to_body *to_b) { int status; int saved_status; char *tmp,*foo; status=START_TO; saved_status=START_TO; to_b->error=PARSE_OK; to_b->uri.len = 0; to_b->uri.s= 0; to_b->display.len = 0; to_b->display.s = 0; foo=0; for( tmp=buffer; tmp<end; tmp++) { switch(*tmp) { case ' ': case '\t': switch (status) { case F_CRLF: case F_LF: case F_CR: /*previous=crlf and now =' '*/ status=saved_status; break; case URI_ENCLOSED: to_b->uri.len = tmp - to_b->uri.s; status = E_URI_ENCLOSED; break; case URI_OR_TOKEN: foo = tmp; status = MAYBE_URI_END; break; } break; case '\n': switch (status) { case URI_OR_TOKEN: foo = tmp; status = MAYBE_URI_END; case MAYBE_URI_END: case DISPLAY_TOKEN: case E_DISPLAY_QUOTED: case END: saved_status=status; status=F_LF; break; case F_CR: status=F_CRLF; break; case F_CRLF: case F_LF: status=saved_status; goto endofheader; default: LOG( L_ERR , "ERROR: parse_to : unexpected char [%c] " "in status %d: <<%.*s>> .\n", *tmp,status, (int)(tmp-buffer), ZSW(buffer)); goto error; } break; case '\r': switch (status) { case URI_OR_TOKEN: foo = tmp; status = MAYBE_URI_END; case MAYBE_URI_END: case DISPLAY_TOKEN: case E_DISPLAY_QUOTED: case END: saved_status=status; status=F_CR; break; case F_CRLF: case F_CR: case F_LF: status=saved_status; goto endofheader; default: LOG( L_ERR , "ERROR: parse_to : unexpected char [%c] " "in status %d: <<%.*s>> .\n", *tmp,status, (int)(tmp-buffer), ZSW(buffer)); goto error; } break; case 0: switch (status) { case URI_OR_TOKEN: case MAYBE_URI_END: to_b->uri.len = tmp - to_b->uri.s; case END: saved_status = status = END; goto endofheader; default: LOG( L_ERR , "ERROR: parse_to : unexpected char [%c] " "in status %d: <<%.*s>> .\n", *tmp,status, (int)(tmp-buffer), ZSW(buffer)); goto error; } break; case '\\': switch (status) { case DISPLAY_QUOTED: tmp++; /* jump over next char */ break; default: LOG( L_ERR , "ERROR: parse_to : unexpected char [%c] " "in status %d: <<%.*s>> .\n", *tmp,status, (int)(tmp-buffer), ZSW(buffer)); goto error; } break; case '<': switch (status) { case START_TO: to_b->body.s=tmp; status = S_URI_ENCLOSED; break; case DISPLAY_QUOTED: break; case E_DISPLAY_QUOTED: status = S_URI_ENCLOSED; break; case URI_OR_TOKEN: case DISPLAY_TOKEN: case MAYBE_URI_END: to_b->display.len=foo-to_b->display.s; status = S_URI_ENCLOSED; break; case F_CRLF: case F_LF: case F_CR: /*previous=crlf and now !=' '*/ goto endofheader; default: LOG( L_ERR , "ERROR: parse_to : unexpected char [%c] " "in status %d: <<%.*s>> .\n", *tmp,status, (int)(tmp-buffer), ZSW(buffer)); goto error; } break; case '>': switch (status) { case DISPLAY_QUOTED: break; case URI_ENCLOSED: to_b->uri.len = tmp - to_b->uri.s; case E_URI_ENCLOSED: status = END; foo = 0; break; case F_CRLF: case F_LF: case F_CR: /*previous=crlf and now !=' '*/ goto endofheader; default: LOG( L_ERR , "ERROR: parse_to : unexpected char [%c] " "in status %d: <<%.*s>> .\n", *tmp,status, (int)(tmp-buffer), ZSW(buffer)); goto error; } break; case '"': switch (status) { case START_TO: to_b->body.s = tmp; to_b->display.s = tmp; status = DISPLAY_QUOTED; break; case DISPLAY_QUOTED: status = E_DISPLAY_QUOTED; to_b->display.len = tmp-to_b->display.s+1; break; case F_CRLF: case F_LF: case F_CR: /*previous=crlf and now !=' '*/ goto endofheader; default: LOG( L_ERR , "ERROR: parse_to : unexpected char [%c] " "in status %d: <<%.*s>> .\n", *tmp,status, (int)(tmp-buffer), buffer); goto error; } break; case ';' : switch (status) { case DISPLAY_QUOTED: case URI_ENCLOSED: break; case URI_OR_TOKEN: foo = tmp; case MAYBE_URI_END: to_b->uri.len = foo - to_b->uri.s; case END: to_b->body.len = tmp-to_b->body.s; tmp = parse_to_param(tmp,end,to_b,&saved_status); goto endofheader; case F_CRLF: case F_LF: case F_CR: /*previous=crlf and now !=' '*/ goto endofheader; default: LOG( L_ERR , "ERROR: parse_to : unexpected char [%c] " "in status %d: <<%.*s>> .\n", *tmp,status, (int)(tmp-buffer), buffer); goto error; } break; default: switch (status) { case START_TO: to_b->uri.s = to_b->body.s = tmp; status = URI_OR_TOKEN; to_b->display.s=tmp; break; case S_URI_ENCLOSED: to_b->uri.s=tmp; status=URI_ENCLOSED; break; case MAYBE_URI_END: status = DISPLAY_TOKEN; case DISPLAY_QUOTED: case DISPLAY_TOKEN: case URI_ENCLOSED: case URI_OR_TOKEN: break; case F_CRLF: case F_LF: case F_CR: /*previous=crlf and now !=' '*/ goto endofheader; default: DBG("DEBUG:parse_to: spitting out [%c] in status %d\n", *tmp,status ); goto error; } }/*char switch*/ }/*for*/ endofheader: if (to_b->display.len==0) to_b->display.s=0; status=saved_status; DBG("DEBUG:parse_to:end of header reached, state=%d\n", status); /* check if error*/ switch(status) { case MAYBE_URI_END: to_b->uri.len = foo - to_b->uri.s; case END: to_b->body.len = tmp - to_b->body.s; case E_PARA_VALUE: break; default: LOG(L_ERR, "ERROR: parse_to: invalid To - unexpected " "end of header in state %d\n", status); goto error; } return tmp; error: to_b->error=PARSE_ERROR; return tmp; }