📄 sip_parse_uri.c
字号:
* ":" / "@" / "&" / "=" / "+" / "$" / "," */static voidsip_uri_parse_abs_path(_sip_uri_t *outurl, char *scan, char *uend){ if (scan == uend || *scan != '/') return; outurl->sip_uri_path.sip_str_ptr = scan; outurl->sip_uri_path.sip_str_len = uend - scan; ++scan; while (scan < uend && (SIP_URI_ISPCHAR(*scan) || SIP_URI_ISUNRESERVED(*scan) || SIP_URI_ISURLESCAPE(scan, uend) || *scan == '/' || *scan == ';')) { ++scan; } if (scan < uend) outurl->sip_uri_errflags |= SIP_URIERR_PATH;}/* * reg-name = 1*( unreserved / escaped / "$" / "," / ";" * / ":" / "@" / "&" / "=" / "+" ) */static voidsip_uri_parse_abs_regname(_sip_uri_t *outurl, char *scan, char *uend){ if (scan == uend) return; outurl->sip_uri_regname.sip_str_ptr = scan; outurl->sip_uri_regname.sip_str_len = uend - scan; while (scan < uend && (SIP_URI_ISUNRESERVED(*scan) || SIP_URI_ISURLESCAPE(scan, uend) || SIP_URI_ISREGNAME(*scan))) { ++scan; } if (scan < uend) outurl->sip_uri_errflags |= SIP_URIERR_REGNAME;}/* * The format of the password is supposed to be :XXX * password = *( unreserved / escaped / "&" / "=" / "+" / "$" / "," ) */static voidsip_uri_parse_password(_sip_uri_t *outurl, char *scan, char *uend){ if (scan == uend || *scan != ':' || scan + 1 == uend) return; ++scan; outurl->sip_uri_password.sip_str_ptr = scan; outurl->sip_uri_password.sip_str_len = uend - scan; while (scan < uend && (SIP_URI_ISUNRESERVED(*scan) || SIP_URI_ISURLESCAPE(scan, uend) || SIP_URI_ISOTHER(*scan) || *scan == '&')) { ++scan; } if (scan < uend) outurl->sip_uri_errflags |= SIP_URIERR_PASS;}/* * user = 1*( unreserved / escaped / user-unreserved ) * user-unreserved = "&" / "=" / "+" / "$" / "," / ";" / "?" / "/" */static voidsip_uri_parse_user(_sip_uri_t *outurl, char *scan, char *uend){ if (scan == uend) { outurl->sip_uri_errflags |= SIP_URIERR_USER; return; } outurl->sip_uri_user.sip_str_ptr = scan; outurl->sip_uri_user.sip_str_len = uend - scan; if (sip_uri_parse_tel(scan, uend)) { outurl->sip_uri_isteluser = B_TRUE; } else { while (scan < uend && (SIP_URI_ISUNRESERVED(*scan) || SIP_URI_ISURLESCAPE(scan, uend) || SIP_URI_ISUSER(*scan))) { ++scan; } if (scan < uend) outurl->sip_uri_errflags |= SIP_URIERR_USER; }}/* * the format of port is supposed to be :XXX * port = 1*DIGIT */static voidsip_uri_parse_port(_sip_uri_t *outurl, char *scan, char *uend){ if (scan == uend || *scan != ':' || scan + 1 == uend) { outurl->sip_uri_errflags |= SIP_URIERR_PORT; return; } ++scan; /* parse numeric port number */ if (SIP_URI_ISDIGIT(*scan)) { outurl->sip_uri_port = *scan - '0'; while (++scan < uend && SIP_URI_ISDIGIT(*scan)) { outurl->sip_uri_port = outurl->sip_uri_port * 10 + (*scan - '0'); if (outurl->sip_uri_port > 0xffff) { outurl->sip_uri_errflags |= SIP_URIERR_PORT; outurl->sip_uri_port = 0; break; } } } if (scan < uend) { outurl->sip_uri_errflags |= SIP_URIERR_PORT; outurl->sip_uri_port = 0; }}/* * parse an IPv4 address * 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT * advances pscan to end of IPv4 address, or after last "." that was * a valid IPv4 or domain name. * returns 1 if ipv4 found, 0 otherwise */static intsip_uri_parse_ipv4(char *scan, char *uend){ int j = 0; int val = 0; for (j = 0; j < 4; ++j) { if (!SIP_URI_ISDIGIT(*scan)) break; val = *scan - '0'; while (++scan < uend && SIP_URI_ISDIGIT(*scan)) { val = val * 10 + (*scan - '0'); if (val > 255) return (0); } if (j < 3) { if (*scan != '.') break; ++scan; } } if (j == 4 && scan == uend) return (1); return (0);}/* * parse an IPv6 address * IPv6address = hexpart [ ":" IPv4address ] * IPv4address = 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT * hexpart = hexseq | hexseq "::" [ hexseq ] | "::" [ hexseq ] * hexseq = hex4 *( ":" hex4) * hex4 = 1*4HEXDIG * if not found, leaves pscan unchanged, otherwise advances to end * returns 1 if valid, * 0 if invalid */static intsip_uri_parse_ipv6(char *scan, char *uend){ char *mark; unsigned j = 0; /* index for addr */ unsigned val = 0; /* hex value */ int zpad = 0; /* index of :: delimiter */ if (*scan != '[') return (0); ++scan; j = 0; /* check for leading "::", set zpad to the position of the "::" */ if (scan + 1 < uend && scan[0] == ':' && scan[1] == ':') { zpad = 0; scan += 2; } else { zpad = -1; } /* loop through up to 16 bytes of IPv6 address */ while (scan < uend && j < 15) { if (!SIP_URI_ISHEX(*scan)) break; mark = scan; val = SIP_URI_HEXVAL(*scan); while (++scan < uend && SIP_URI_ISHEX(*scan)) { val = val * 16 + SIP_URI_HEXVAL(*scan); if (val > 0xffff) return (0); } /* always require a delimiter or ] */ if (scan == uend) return (0); if (*scan == '.' && (j == 12 || (zpad != -1 && j < 12)) && mark < uend && sip_uri_parse_ipv4(mark, uend - 1) && *(uend - 1) == ']') { mark = uend - 1; j += 4; scan = mark + 1; break; } /* set address */ j += 2; /* check for delimiter or ] */ if (*scan == ':') { /* found ":" delimiter, check for "::" */ if (++scan < uend && *scan == ':') { if (zpad != -1) return (0); zpad = j; if (++scan < uend && *scan == ']') { ++scan; break; } } } else if (*scan == ']' && (j == 16 || zpad != -1)) { ++scan; break; } else { /* not a valid delimiter */ return (0); } } if (zpad == -1 && j < 16) return (0); if (zpad != -1) { if (j > 15) return (0); } if (scan == uend) return (1); return (0);}/* * hostname = *( domainlabel "." ) toplabel [ "." ] * domainlabel = alphanum / alphanum *( alphanum / "-" ) alphanum * toplabel = ALPHA / ALPHA *( alphanum / "-" ) alphanum */static intsip_uri_parse_hostname(char *scan, char *uend){ int sawalpha = 0; if (scan < uend && SIP_URI_ISALNUM(*scan)) { do { sawalpha = SIP_URI_ISALPHA(*scan); while (SIP_URI_ISHOST(*scan)) ++scan; if (*scan != '.') break; ++scan; } while (scan < uend && SIP_URI_ISALNUM(*scan)); } if (sawalpha && scan == uend) return (1); return (0);}/* * parse the network path portion of a full URL */static voidsip_uri_parse_netpath(_sip_uri_t *outurl, char **pscan, char *uend, boolean_t issip){ char *mark = (char *)0; char *mark2 = (char *)0; char *scan = *pscan; int gothost = 0; /* look for the first high-level delimiter */ mark = scan; while (scan < uend && *scan != '@') ++scan; /* handle userinfo section of URL */ if (scan < uend && *scan == '@') { /* parse user */ mark2 = mark; while (mark < scan && *mark != ':') ++mark; sip_uri_parse_user(outurl, mark2, mark); /* parse password */ if (*mark == ':') sip_uri_parse_password(outurl, mark, scan); mark = ++scan; } scan = mark; if (scan < uend && *scan == '[') { /* look for an IPv6 address */ while (scan < uend && *scan != ']') ++scan; if (scan < uend) { ++scan; if (sip_uri_parse_ipv6(mark, scan)) gothost = 1; } } else { while (scan < uend && ((issip && !SIP_URI_ISSIPHDELIM(*scan)) || (!issip && !SIP_URI_ISABSHDELIM(*scan)))) { ++scan; } /* look for an IPv4 address */ if (mark < scan && SIP_URI_ISDIGIT(*mark) && sip_uri_parse_ipv4(mark, scan)) { gothost = 1; } /* look for a valid host name */ if (!gothost && mark < scan && sip_uri_parse_hostname(mark, scan)) { gothost = 1; } } /* handle invalid host name */ if (!gothost) outurl->sip_uri_errflags |= SIP_URIERR_HOST; /* save host name */ outurl->sip_uri_host.sip_str_ptr = mark; outurl->sip_uri_host.sip_str_len = scan - mark; mark = scan; /* parse the port number */ if (scan < uend && *scan == ':') { while (scan < uend && ((issip && !SIP_URI_ISSIPDELIM(*scan)) || (!issip && !SIP_URI_ISABSDELIM(*scan)))) { ++scan; } sip_uri_parse_port(outurl, mark, scan); } /* set return pointer */ *pscan = scan;}/* * parse a URL * URL = SIP-URI / SIPS-URI / absoluteURI */voidsip_uri_parse_it(_sip_uri_t *outurl, sip_str_t *uri_str){ char *mark; char *scan; char *uend; char *str = uri_str->sip_str_ptr; unsigned urlen = uri_str->sip_str_len; /* reset output parameters */ (void) memset(outurl, 0, sizeof (sip_uri_t)); /* strip enclosing angle brackets */ if (urlen > 1 && str[0] == '<' && str[urlen-1] == '>') { urlen -= 2; ++str; } uend = str + urlen; /* strip off space prefix and trailing spaces */ while (str < uend && isspace(*str)) { ++str; --urlen; } while (str < uend && isspace(*(uend - 1))) { --uend; --urlen; } /* strip off "URL:" prefix */ if (urlen > 4 && sip_uri_url_casecmp(str, "URL:", 4) == 0) { str += 4; urlen -= 4; } /* parse the scheme name */ mark = scan = str; while (scan < uend && *scan != ':') ++scan; if (scan == uend || !sip_uri_parse_scheme(outurl, mark, scan)) { outurl->sip_uri_errflags |= SIP_URIERR_SCHEME; return; } if ((outurl->sip_uri_scheme.sip_str_len == SIP_SCHEME_LEN && !memcmp(outurl->sip_uri_scheme.sip_str_ptr, SIP_SCHEME, SIP_SCHEME_LEN)) || (outurl->sip_uri_scheme.sip_str_len == SIPS_SCHEME_LEN && !memcmp(outurl->sip_uri_scheme.sip_str_ptr, SIPS_SCHEME, SIPS_SCHEME_LEN))) { outurl->sip_uri_issip = B_TRUE; } else { outurl->sip_uri_issip = B_FALSE; } ++scan; /* skip ':' */ if (outurl->sip_uri_issip) { /* parse SIP URL */ sip_uri_parse_netpath(outurl, &scan, uend, B_TRUE); /* parse parameters */ if (scan < uend && *scan == ';') { mark = scan; while (scan < uend && *scan != '?') ++scan; sip_uri_parse_params(outurl, mark, scan); } /* parse headers */ if (scan < uend && *scan == '?') sip_uri_parse_headers(outurl, scan, uend); } else if (scan < uend && scan[0] == '/') { /* parse absoluteURL */ ++scan; /* * parse authority * authority = srvr / reg-name * srvr = [ [ userinfo "@" ] hostport ] * reg-name = 1*(unreserved / escaped / "$" / "," * / ";" / ":" / "@" / "&" / "=" / "+") */ if (scan < uend && *scan == '/') { ++scan; mark = scan; /* take authority as srvr */ sip_uri_parse_netpath(outurl, &scan, uend, B_FALSE); /* * if srvr failed, take it as reg-name * parse reg-name */ if (outurl->sip_uri_errflags & SIP_URIERR_USER || outurl->sip_uri_errflags & SIP_URIERR_PASS || outurl->sip_uri_errflags & SIP_URIERR_HOST || outurl->sip_uri_errflags & SIP_URIERR_PORT) { scan = mark; while (scan < uend && *scan != '/' && *scan != '?') { ++scan; } sip_uri_parse_abs_regname(outurl, mark, scan); if (!(outurl->sip_uri_errflags & SIP_URIERR_REGNAME)) { /* * remove error info of user, * password, host, port */ outurl->sip_uri_user.sip_str_ptr = NULL; outurl->sip_uri_user.sip_str_len = 0; outurl->sip_uri_errflags &= ~SIP_URIERR_USER; outurl->sip_uri_password.sip_str_ptr = NULL; outurl->sip_uri_password.sip_str_len = 0; outurl->sip_uri_errflags &= ~SIP_URIERR_PASS; outurl->sip_uri_host.sip_str_ptr = NULL; outurl->sip_uri_host.sip_str_len = 0; outurl->sip_uri_errflags &= ~SIP_URIERR_HOST; outurl->sip_uri_port = 0; outurl->sip_uri_errflags &= ~SIP_URIERR_PORT; } } } else { /* there is no net-path */ --scan; } /* parse abs-path */ if (scan < uend && *scan == '/') { mark = scan; while (scan < uend && *scan != '?') ++scan; sip_uri_parse_abs_path(outurl, mark, scan); } /* parse query */ if (scan < uend && *scan == '?') sip_uri_parse_abs_query(outurl, scan, uend); } else { /* parse opaque-part */ sip_uri_parse_abs_opaque(outurl, scan, uend); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -