📄 httpd_util.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$%%-module(httpd_util).-export([key1search/2, key1search/3, lookup/2, lookup/3, multi_lookup/2, lookup_mime/2, lookup_mime/3, lookup_mime_default/2, lookup_mime_default/3, reason_phrase/1, message/3, rfc1123_date/0, rfc1123_date/1, day/1, month/1, decode_hex/1, decode_base64/1, encode_base64/1, flatlength/1, split_path/1, split_script_path/1, suffix/1, to_upper/1, to_lower/1, split/3, uniq/1, make_name/2,make_name/3,make_name/4,strip/1, hexlist_to_integer/1,integer_to_hexlist/1, convert_request_date/1,create_etag/1,create_etag/2, convert_netscapecookie_date/1, enable_debug/1, valid_options/3]).-export([encode_hex/1]).-include_lib("kernel/include/file.hrl").%% We will not make the change to use base64 in stdlib in inets just yet.%% it will be included in the next major release of inets. -compile({nowarn_deprecated_function, {http_base_64, encode, 1}}).-compile({nowarn_deprecated_function, {http_base_64, decode, 1}}).-deprecated([{to_lower, 1, next_major_release}, {to_upper, 1, next_major_release}, {decode_base64, 1, next_major_release}, {encode_base64, 1, next_major_release} ]).%% key1searchkey1search(TupleList,Key) -> key1search(TupleList,Key,undefined).key1search(TupleList,Key,Undefined) -> case lists:keysearch(Key,1,TupleList) of {value,{Key,Value}} -> Value; false -> Undefined end.%% lookuplookup(Table,Key) -> lookup(Table,Key,undefined).lookup(Table,Key,Undefined) -> case catch ets:lookup(Table,Key) of [{Key,Value}|_] -> Value; _-> Undefined end.%% multi_lookupmulti_lookup(Table,Key) -> remove_key(ets:lookup(Table,Key)).remove_key([]) -> [];remove_key([{_Key, Value}| Rest]) -> [Value | remove_key(Rest)].%% lookup_mimelookup_mime(ConfigDB,Suffix) -> lookup_mime(ConfigDB,Suffix,undefined).lookup_mime(ConfigDB,Suffix,Undefined) -> [{mime_types,MimeTypesDB}|_]=ets:lookup(ConfigDB,mime_types), case ets:lookup(MimeTypesDB,Suffix) of [] -> Undefined; [{Suffix,MimeType}|_] -> MimeType end.%% lookup_mime_defaultlookup_mime_default(ConfigDB,Suffix) -> lookup_mime_default(ConfigDB,Suffix,undefined).lookup_mime_default(ConfigDB,Suffix,Undefined) -> [{mime_types,MimeTypesDB}|_]=ets:lookup(ConfigDB,mime_types), case ets:lookup(MimeTypesDB,Suffix) of [] -> case ets:lookup(ConfigDB,default_type) of [] -> Undefined; [{default_type,DefaultType}|_] -> DefaultType end; [{Suffix,MimeType}|_] -> MimeType end.%%% RFC 2616, HTTP 1.1 Status codesreason_phrase(100) -> "Continue";reason_phrase(101) -> "Switching Protocols" ;reason_phrase(200) -> "OK" ;reason_phrase(201) -> "Created" ;reason_phrase(202) -> "Accepted" ;reason_phrase(203) -> "Non-Authoritative Information" ;reason_phrase(204) -> "No Content" ;reason_phrase(205) -> "Reset Content" ;reason_phrase(206) -> "Partial Content" ;reason_phrase(300) -> "Multiple Choices" ;reason_phrase(301) -> "Moved Permanently" ;reason_phrase(302) -> "Moved Temporarily" ;reason_phrase(303) -> "See Other" ;reason_phrase(304) -> "Not Modified" ;reason_phrase(305) -> "Use Proxy" ;reason_phrase(306) -> "(unused)" ;reason_phrase(307) -> "Temporary Redirect" ;reason_phrase(400) -> "Bad Request";reason_phrase(401) -> "Unauthorized";reason_phrase(402) -> "Payment Required";reason_phrase(403) -> "Forbidden" ;reason_phrase(404) -> "Object Not Found" ;reason_phrase(405) -> "Method Not Allowed" ;reason_phrase(406) -> "Not Acceptable" ;reason_phrase(407) -> "Proxy Authentication Required" ;reason_phrase(408) -> "Request Time-out" ;reason_phrase(409) -> "Conflict" ;reason_phrase(410) -> "Gone" ;reason_phrase(411) -> "Length Required" ;reason_phrase(412) -> "Precondition Failed" ;reason_phrase(413) -> "Request Entity Too Large" ;reason_phrase(414) -> "Request-URI Too Large" ;reason_phrase(415) -> "Unsupported Media Type" ;reason_phrase(416) -> "Requested Range Not Satisfiable" ;reason_phrase(417) -> "Expectation Failed" ;reason_phrase(500) -> "Internal Server Error" ;reason_phrase(501) -> "Not Implemented" ;reason_phrase(502) -> "Bad Gateway" ;reason_phrase(503) -> "Service Unavailable" ;reason_phrase(504) -> "Gateway Time-out" ;reason_phrase(505) -> "HTTP Version not supported";%%% RFC 2518, HTTP Extensions for Distributed Authoring -- WEBDAVreason_phrase(102) -> "Processing";reason_phrase(207) -> "Multi-Status";reason_phrase(422) -> "Unprocessable Entity";reason_phrase(423) -> "Locked";reason_phrase(424) -> "Failed Dependency";reason_phrase(507) -> "Insufficient Storage";%%% (Work in Progress) WebDAV Advanced Collectionsreason_phrase(425) -> "";%%% RFC 2817, HTTP Upgrade to TLSreason_phrase(426) -> "Upgrade Required";%%% RFC 3229, Delta encoding in HTTPreason_phrase(226) -> "IM Used";reason_phrase(_) -> "Internal Server Error".%% messagemessage(301,URL,_) -> "The document has moved <A HREF=\""++URL++"\">here</A>.";message(304, _URL,_) -> "The document has not been changed.";message(400,none,_) -> "Your browser sent a query that this server could not understand.";message(400,Msg,_) -> "Your browser sent a query that this server could not understand. "++Msg;message(401,none,_) -> "This server could not verify that youare authorized to access the document you requested. Either you supplied the wrongcredentials (e.g., bad password), or yourbrowser doesn't understand how to supplythe credentials required.";message(403,RequestURI,_) -> "You don't have permission to access "++RequestURI++" on this server.";message(404,RequestURI,_) -> "The requested URL "++RequestURI++" was not found on this server.";message(408, Timeout, _) -> Timeout;message(412,none,_) -> "The requested preconditions where false";message(413, Reason,_) -> "Entity: " ++ Reason;message(414,ReasonPhrase,_) -> "Message "++ReasonPhrase++".";message(416,ReasonPhrase,_) -> ReasonPhrase;message(500,_,ConfigDB) -> ServerAdmin=lookup(ConfigDB,server_admin,"unknown@unknown"), "The server encountered an internal error or " "misconfiguration and was unable to complete " "your request.<P>Please contact the server administrator " ++ ServerAdmin ++ ", and inform them of the time the error occurred " "and anything you might have done that may have caused the error.";message(501,{Method, RequestURI, HTTPVersion}, _ConfigDB) -> if atom(Method) -> atom_to_list(Method)++ " to "++RequestURI++" ("++HTTPVersion++") not supported."; list(Method) -> Method++ " to "++RequestURI++" ("++HTTPVersion++") not supported." end;message(503, String, _ConfigDB) -> "This service in unavailable due to: "++String.%%convert_rfc_date(Date)->{{YYYY,MM,DD},{HH,MIN,SEC}}convert_request_date([D,A,Y,DateType| Rest])-> Func=case DateType of $\, -> fun convert_rfc1123_date/1; $\ -> fun convert_ascii_date/1; _ -> fun convert_rfc850_date/1 end, case catch Func([D,A,Y,DateType| Rest]) of {ok,Date} -> Date; _Error-> bad_date end.convert_rfc850_date(DateStr) -> [_WeekDay,Date,Time,_TimeZone|_Rest] = string:tokens(DateStr," "), convert_rfc850_date(Date,Time).convert_rfc850_date([D1,D2,_, M,O,N,_, Y1,Y2|_Rest],[H1,H2,_Col,M1,M2,_Col,S1,S2|_Rest2])-> Year=list_to_integer([50,48,Y1,Y2]), Day=list_to_integer([D1,D2]), Month = http_util:convert_month([M,O,N]), Hour=list_to_integer([H1,H2]), Min=list_to_integer([M1,M2]), Sec=list_to_integer([S1,S2]), {ok,{{Year,Month,Day},{Hour,Min,Sec}}}.convert_ascii_date([_D,_A,_Y,_SP, M,O,N,_SP, D1,D2,_SP, H1,H2,_Col, M1,M2,_Col, S1,S2,_SP, Y1,Y2,Y3,Y4| _Rest])-> Year=list_to_integer([Y1,Y2,Y3,Y4]), Day=case D1 of $\ -> list_to_integer([D2]); _-> list_to_integer([D1,D2]) end, Month=http_util:convert_month([M,O,N]), Hour=list_to_integer([H1,H2]), Min=list_to_integer([M1,M2]), Sec=list_to_integer([S1,S2]), {ok,{{Year,Month,Day},{Hour,Min,Sec}}}.convert_rfc1123_date([_D,_A,_Y,_C,_SP, D1,D2,_SP, M,O,N,_SP, Y1,Y2,Y3,Y4,_SP, H1,H2,_Col, M1,M2,_Col, S1,S2|_Rest]) -> Year=list_to_integer([Y1,Y2,Y3,Y4]), Day=list_to_integer([D1,D2]), Month=http_util:convert_month([M,O,N]), Hour=list_to_integer([H1,H2]), Min=list_to_integer([M1,M2]), Sec=list_to_integer([S1,S2]), {ok,{{Year,Month,Day},{Hour,Min,Sec}}}.convert_netscapecookie_date(Date)-> case (catch http_util:convert_netscapecookie_date(Date)) of Ret = {ok, _} -> Ret; _ -> {error,bad_date} end.%% rfc1123_daterfc1123_date() -> {{YYYY,MM,DD},{Hour,Min,Sec}} = calendar:universal_time(), DayNumber = calendar:day_of_the_week({YYYY,MM,DD}), lists:flatten( io_lib:format("~s, ~2.2.0w ~3.s ~4.4.0w ~2.2.0w:~2.2.0w:~2.2.0w GMT", [day(DayNumber),DD,month(MM),YYYY,Hour,Min,Sec])).rfc1123_date(undefined) -> undefined;rfc1123_date(LocalTime) -> {{YYYY,MM,DD},{Hour,Min,Sec}} = case calendar:local_time_to_universal_time_dst(LocalTime) of [Gmt] -> Gmt; [_,Gmt] -> Gmt end, DayNumber = calendar:day_of_the_week({YYYY,MM,DD}), lists:flatten( io_lib:format("~s, ~2.2.0w ~3.s ~4.4.0w ~2.2.0w:~2.2.0w:~2.2.0w GMT", [day(DayNumber),DD,month(MM),YYYY,Hour,Min,Sec])).%% uniquniq([]) -> [];uniq([First,First|Rest]) -> uniq([First|Rest]);uniq([First|Rest]) -> [First|uniq(Rest)].%% dayday(1) -> "Mon";day(2) -> "Tue";day(3) -> "Wed";day(4) -> "Thu";day(5) -> "Fri";day(6) -> "Sat"; day(7) -> "Sun".%% monthmonth(1) -> "Jan";month(2) -> "Feb";month(3) -> "Mar";month(4) -> "Apr";month(5) -> "May";month(6) -> "Jun";month(7) -> "Jul";month(8) -> "Aug";month(9) -> "Sep";month(10) -> "Oct";month(11) -> "Nov";
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -