📄 xmerl_uri.erl
字号:
% ``The contents of this file are subject to the Erlang Public License,%% Version 1.1, (the "License"); you may not use this file except in%% compliance with the License. You should have received a copy of the%% Erlang Public License along with this software. If not, it can be%% retrieved via the world wide web at http://www.erlang.org/.%% %% Software distributed under the License is distributed on an "AS IS"%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See%% the License for the specific language governing rights and limitations%% under the License.%% %% The Initial Developer of the Original Code is Ericsson Utvecklings AB.%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings%% AB. All Rights Reserved.''%% %% $Id$%%% Author : Johan Blom <Johan.Blom@mobilearts.se>%%% Description :%%% Implements various scheme dependent subsets (e.g. HTTP, FTP etc) based on%%% RFC 2396, Uniform Resource Identifiers (URI): Generic Syntax%%% RFC 2732, Format for Literal IPv6 Addresses in URL's%%% Supported schemes:%%% HTTP - Source RFC 2396, RFC 2616%%% FTP - (Not yet!) Source RFC 2396, RFC 1738, RFC 959%%% SIP - Source RFC 2396, RFC 3261%%% SMS - (Not yet!) Source draft-wilde-sms-uri-03, April 16 2002 and%%% draft-allocchio-gstn-04, August 2002%%% H323 - (Not yet!) Source RFC 3508-module(xmerl_uri).-author('johan.blom@mobilearts.se').-export([parse/1,resolve/2% scan_abspath/1 ]).%%% Parse URI and return {Scheme,Path}%%% Note that Scheme specific parsing/validation is not handled here!resolve(_Root,_Rel) -> ok.%%% See "http://www.isi.edu/in-notes/iana/assignments/url-schemes" for a list of%%% defined URL schemes and references to its sources.parse(URI) -> case parse_scheme(URI) of {http,Cont} -> parse_http(Cont,http); {https,Cont} -> parse_http(Cont,https); {ftp,Cont} -> parse_ftp(Cont,ftp); {sip,Cont} -> parse_sip(Cont,sip); {sips,Cont} -> parse_sip(Cont,sips); {sms,Cont} -> parse_sms(Cont,sms); % Note: From old draft {error,Error} -> {error,Error}; {Scheme,Cont} -> {Scheme,Cont} end.%%% Parse the scheme.parse_scheme(URI) -> parse_scheme(URI,[]).parse_scheme([H|URI],Acc) when $a=<H,H=<$z; $A=<H,H=<$Z -> parse_scheme2(URI,[H|Acc]);parse_scheme(_,_) -> {error,no_scheme}.parse_scheme2([H|URI],Acc) when $a=<H,H=<$z; $A=<H,H=<$Z; $0=<H,H=<$9; H==$-;H==$+;H==$. -> parse_scheme2(URI,[H|Acc]);parse_scheme2([$:|URI],Acc) -> {list_to_atom(lists:reverse(Acc)),URI};parse_scheme2(_,_) -> {error,no_scheme}.%%% ............................................................................-define(HTTP_DEFAULT_PORT, 80).-define(HTTPS_DEFAULT_PORT, 443).%%% HTTP (Source RFC 2396, RFC 2616) %%% http_URL = "*" | absoluteURI | abs_path [ "?" query ] | authority%%% http_URL = "http:" "//" host [ ":" port ] [ abs_path [ "?" query ]]%%% Returns a tuple {http,Host,Port,Path,Query} where%%% Host = string() Host value%%% Port = string() Port value%%% Path = string() Absolute path%%% Query = string() Query or Fragment valueparse_http("//"++C0,Scheme) -> case scan_hostport(C0,Scheme) of {C1,Host,Port} -> case scan_pathquery(C1) of {error,Error} -> {error,Error}; {Path,Query} -> {Scheme,Host,Port,Path,Query} end; {error,Error} -> {error,Error} end;parse_http(_,_) -> {error,invalid_url}.scan_pathquery(C0) -> case scan_abspath(C0) of {error,Error} -> {error,Error}; {[],[]} -> % Add implicit path {"/",""}; {"?"++C1,Path} -> case scan_query(C1,[]) of {error,Error} -> {error,Error}; Query -> {Path,"?"++Query} end; {"#"++C1,Path} -> % 'query' and 'fragment' are both defined as '*uric' case scan_query(C1,[]) of {error,Error} -> {error,Error}; Fragment -> {Path,"#"++Fragment} end; {[],Path} -> {Path,""} end.%%% ............................................................................%%% FIXME!!! This is just a quick hack that doesn't work!-define(FTP_DEFAULT_PORT, 80).%%% FTP (Source RFC 2396, RFC 1738, RFC 959)%%% Note: This BNF has been modified to better fit with RFC 2396%%% ftp_URL = "ftp:" "//" [ ftp_userinfo ] host [ ":" port ] ftp_abs_path%%% ftp_userinfo = ftp_user [ ":" ftp_password ]%%% ftp_abs_path = "/" ftp_path_segments [ ";type=" ftp_type ]%%% ftp_path_segments = ftp_segment *( "/" ftp_segment)%%% ftp_segment = *[ ftp_uchar | "?" | ":" | "@" | "&" | "=" ]%%% ftp_type = "A" | "I" | "D" | "a" | "i" | "d"%%% ftp_user = *[ ftp_uchar | ";" | "?" | "&" | "=" ]%%% ftp_password = *[ ftp_uchar | ";" | "?" | "&" | "=" ]%%% ftp_uchar = ftp_unreserved | escaped%%% ftp_unreserved = alphanum | mark | "$" | "+" | ","parse_ftp("//"++C0,Scheme) -> case ftp_userinfo(C0) of {error, Error} -> {error,Error}; {C1,Creds} -> case scan_hostport(C1,Scheme) of {C2,Host,Port} -> case scan_abspath(C2) of {error,Error} -> {error,Error}; {[],[]} -> % Add implicit path {Scheme,Creds,Host,Port,"/"}; {[],Path} -> {Scheme,Creds,Host,Port,Path} end; {error,Error} -> {error,Error} end end.ftp_userinfo(C0) -> User="", Password="", {C0,{User,Password}}.%%% .........................................................................-define(SIP_DEFAULT_PORT, 5060).-define(SIPTLS_DEFAULT_PORT, 5061).%%% SIP (Source RFC 2396, RFC 3261)%%% sip_URL = "sip:" [ sip_userinfo "@" ] host [ ":" port ] %%% sip_uri-parameters [ sip_headers ]%%% sip_userinfo = (sip_user | sip_telephone-subscriber) %%% [ ":" sip_password ]%%% sip_user = *( unreserved | escaped | %%% "&" | "=" | "+" | "$" | "," | ";" | "?" | "/")%%% sip_telephone-subscriber = See RFC2806%%% sip_password = *( unreserved | escaped |%%% "&" | "=" | "+" | "$" | "," )%%% sip_uri-parameters = *( ";" sip_uri-parameter )%%% sip_uri-parameter = sip_transport-param | sip_user-param |%%% sip_method-param | sip_ttl-param |%%% sip_maddr-param | sip_lr-param | sip_other-param%%% sip_transport-param = "transport=" ( "udp" | "tcp" | "sctp" | "tls" | token)%%% sip_user-param = "user=" ( "phone" | "ip" | token)%%% sip_method-param = "method=" sip_Method%%% sip_ttl-param = "ttl=" sip_ttl%%% sip_maddr-param = "maddr=" host%%% sip_lr-param = "lr"%%% sip_other-param = 1*sip_paramchar [ "=" 1*sip_paramchar ]%%% sip_Method = "INVITE" | "ACK" | "OPTIONS" | "BYE" |%%% "CANCEL" | "REGISTER" | token%%% sip_ttl = 1*3DIGIT ; 0 to 255%%% sip_paramchar = sip_param-unreserved | unreserved | escaped%%% sip_param-unreserved = "[" | "]" | "/" | ":" | "&" | "+" | "$"%%% sip_headers = "?" sip_header *( "&" sip_header )%%% sip_header = sip_hname "=" sip_hvalue%%% sip_hname = 1*( sip_hnv-unreserved | unreserved | escaped )%%% sip_hvalue = *( sip_hnv-unreserved / unreserved / escaped )%%% sip_hnv-unreserved = "[" | "]" | "/" | "?" | ":" | "+" | "$"%%% Note:%%% - FIXME: Headers not parsedparse_sip(C0,Scheme) -> case string:tokens(C0,"@") of [Userinfo,Hostport] -> {User,Pass}=sip_userinfo(Userinfo), {C1,Host,Port}=scan_hostport(Hostport,Scheme), {C2,Parameters}=scan_parameters(C1), Headers=scan_headers(C2), {Scheme,User,Pass,Host,Port,Parameters,Headers}; [Hostport] -> {C1,Host,Port}=scan_hostport(Hostport,Scheme), {C2,Parameters}=scan_parameters(C1), Headers=scan_headers(C2), {Scheme,none,none,Host,Port,Parameters,Headers} end.%%% FIXME! User can be telephone subscribersip_userinfo(Userinfo) -> case string:tokens(Userinfo,":") of [User,Pass] -> {User,Pass}; [User] -> {User,none} end.scan_parameters(C1) -> ParList=string:tokens(C1,";"), scan_parameters2(ParList,[], []).
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -