From a42cd7aaabfdb3ecc0a538548e8dbcc7ca860b2d Mon Sep 17 00:00:00 2001 From: root Date: Sat, 23 Mar 2013 00:06:21 -0700 Subject: Sat Mar 23 00:06:20 PDT 2013 --- community/couchdb/PKGBUILD | 10 +- community/couchdb/build-fix.patch | 5568 +++++++++++++++++++++++++++++++++++++ 2 files changed, 5574 insertions(+), 4 deletions(-) create mode 100644 community/couchdb/build-fix.patch (limited to 'community/couchdb') diff --git a/community/couchdb/PKGBUILD b/community/couchdb/PKGBUILD index c09195ce1..8fd1b505d 100644 --- a/community/couchdb/PKGBUILD +++ b/community/couchdb/PKGBUILD @@ -1,4 +1,4 @@ -# $Id: PKGBUILD 82681 2013-01-23 00:15:50Z eric $ +# $Id: PKGBUILD 86802 2013-03-22 11:40:46Z spupykin $ # Maintainer: Sergej Pupykin # Contributor: Vitaliy Berdinskikh ur6lad[at]i.ua # Contributor: Michael Fellinger @@ -19,16 +19,18 @@ backup=('etc/couchdb/local.ini' source=("http://apache-mirror.rbc.ru/pub/apache/couchdb/$pkgver/apache-couchdb-$pkgver.tar.gz"{,.asc} "couchdb.service" "couchdb.tmpfiles" - "couchdb.rc") + "couchdb.rc" + "build-fix.patch") md5sums=('df75b03e56c2431ede7625200f0d44a7' 'e6e943c1da93cfcb41a4286daa80195d' '8914a7ffc6745f94106d96206709acb4' '1e254ebe32eeb061be64193bafa35dbf' - 'a75ee9b310a950eea13b07274b7a0669') + 'a75ee9b310a950eea13b07274b7a0669' + '71afe48505dfc07ba2091786b4650fa2') build() { cd "$srcdir/apache-$pkgname-$pkgver" - + patch -p1 <$srcdir/build-fix.patch ./configure --prefix=/usr \ --sysconfdir=/etc \ --localstatedir=/var diff --git a/community/couchdb/build-fix.patch b/community/couchdb/build-fix.patch new file mode 100644 index 000000000..d847b3cf2 --- /dev/null +++ b/community/couchdb/build-fix.patch @@ -0,0 +1,5568 @@ +diff -wbBur apache-couchdb-1.2.1/src/Makefile.am apache-couchdb-1.2.1.q/src/Makefile.am +--- apache-couchdb-1.2.1/src/Makefile.am 2012-12-21 01:24:07.000000000 +0400 ++++ apache-couchdb-1.2.1.q/src/Makefile.am 2013-03-22 15:28:06.836935634 +0400 +@@ -10,4 +10,4 @@ + ## License for the specific language governing permissions and limitations under + ## the License. + +-SUBDIRS = couchdb ejson erlang-oauth etap ibrowse mochiweb snappy ++SUBDIRS = couchdb ejson erlang-oauth ibrowse mochiweb snappy +diff -wbBur apache-couchdb-1.2.1/src/Makefile.in apache-couchdb-1.2.1.q/src/Makefile.in +--- apache-couchdb-1.2.1/src/Makefile.in 2012-12-21 01:28:49.000000000 +0400 ++++ apache-couchdb-1.2.1.q/src/Makefile.in 2013-03-22 15:28:11.563602246 +0400 +@@ -267,7 +267,7 @@ + version_release = @version_release@ + version_revision = @version_revision@ + version_stage = @version_stage@ +-SUBDIRS = couchdb ejson erlang-oauth etap ibrowse mochiweb snappy ++SUBDIRS = couchdb ejson erlang-oauth ibrowse mochiweb snappy + all: all-recursive + + .SUFFIXES: +diff -wbBur apache-couchdb-1.2.1/src/mochiweb/mochifmt.erl apache-couchdb-1.2.1.q/src/mochiweb/mochifmt.erl +--- apache-couchdb-1.2.1/src/mochiweb/mochifmt.erl 2012-12-21 01:24:07.000000000 +0400 ++++ apache-couchdb-1.2.1.q/src/mochiweb/mochifmt.erl 2013-03-22 15:26:58.000000000 +0400 +@@ -369,8 +369,8 @@ + %% + %% Tests + %% +--include_lib("eunit/include/eunit.hrl"). + -ifdef(TEST). ++-include_lib("eunit/include/eunit.hrl"). + + tokenize_test() -> + {?MODULE, [{raw, "ABC"}]} = tokenize("ABC"), +diff -wbBur apache-couchdb-1.2.1/src/mochiweb/mochifmt_records.erl apache-couchdb-1.2.1.q/src/mochiweb/mochifmt_records.erl +--- apache-couchdb-1.2.1/src/mochiweb/mochifmt_records.erl 2012-12-21 01:24:07.000000000 +0400 ++++ apache-couchdb-1.2.1.q/src/mochiweb/mochifmt_records.erl 2013-03-22 15:26:58.000000000 +0400 +@@ -9,11 +9,15 @@ + %% M:format("{0.bar}", [#rec{bar=foo}]). + %% foo + +--module(mochifmt_records, [Recs]). ++-module(mochifmt_records). + -author('bob@mochimedia.com'). +--export([get_value/2]). ++-export([new/1, get_value/3]). + +-get_value(Key, Rec) when is_tuple(Rec) and is_atom(element(1, Rec)) -> ++new([{_Rec, RecFields}]=Recs) when is_list(RecFields) -> ++ {?MODULE, Recs}. ++ ++get_value(Key, Rec, {?MODULE, Recs}) ++ when is_tuple(Rec) and is_atom(element(1, Rec)) -> + try begin + Atom = list_to_existing_atom(Key), + {_, Fields} = proplists:lookup(element(1, Rec), Recs), +@@ -21,7 +25,7 @@ + end + catch error:_ -> mochifmt:get_value(Key, Rec) + end; +-get_value(Key, Args) -> ++get_value(Key, Args, {?MODULE, _Recs}) -> + mochifmt:get_value(Key, Args). + + get_rec_index(Atom, [Atom | _], Index) -> +@@ -33,6 +37,6 @@ + %% + %% Tests + %% +--include_lib("eunit/include/eunit.hrl"). + -ifdef(TEST). ++-include_lib("eunit/include/eunit.hrl"). + -endif. +diff -wbBur apache-couchdb-1.2.1/src/mochiweb/mochifmt_std.erl apache-couchdb-1.2.1.q/src/mochiweb/mochifmt_std.erl +--- apache-couchdb-1.2.1/src/mochiweb/mochifmt_std.erl 2012-12-21 01:24:07.000000000 +0400 ++++ apache-couchdb-1.2.1.q/src/mochiweb/mochifmt_std.erl 2013-03-22 15:26:58.000000000 +0400 +@@ -3,28 +3,31 @@ + + %% @doc Template module for a mochifmt formatter. + +--module(mochifmt_std, []). ++-module(mochifmt_std). + -author('bob@mochimedia.com'). +--export([format/2, get_value/2, format_field/2, get_field/2, convert_field/2]). ++-export([new/0, format/3, get_value/3, format_field/3, get_field/3, convert_field/3]). + +-format(Format, Args) -> ++new() -> ++ {?MODULE}. ++ ++format(Format, Args, {?MODULE}=THIS) -> + mochifmt:format(Format, Args, THIS). + +-get_field(Key, Args) -> ++get_field(Key, Args, {?MODULE}=THIS) -> + mochifmt:get_field(Key, Args, THIS). + +-convert_field(Key, Args) -> ++convert_field(Key, Args, {?MODULE}) -> + mochifmt:convert_field(Key, Args). + +-get_value(Key, Args) -> ++get_value(Key, Args, {?MODULE}) -> + mochifmt:get_value(Key, Args). + +-format_field(Arg, Format) -> ++format_field(Arg, Format, {?MODULE}=THIS) -> + mochifmt:format_field(Arg, Format, THIS). + + %% + %% Tests + %% +--include_lib("eunit/include/eunit.hrl"). + -ifdef(TEST). ++-include_lib("eunit/include/eunit.hrl"). + -endif. +diff -wbBur apache-couchdb-1.2.1/src/mochiweb/mochiglobal.erl apache-couchdb-1.2.1.q/src/mochiweb/mochiglobal.erl +--- apache-couchdb-1.2.1/src/mochiweb/mochiglobal.erl 2012-12-21 01:24:07.000000000 +0400 ++++ apache-couchdb-1.2.1.q/src/mochiweb/mochiglobal.erl 2013-03-22 15:26:58.000000000 +0400 +@@ -30,7 +30,7 @@ + put(_K, V, Mod) -> + Bin = compile(Mod, V), + code:purge(Mod), +- code:load_binary(Mod, atom_to_list(Mod) ++ ".erl", Bin), ++ {module, Mod} = code:load_binary(Mod, atom_to_list(Mod) ++ ".erl", Bin), + ok. + + -spec delete(atom()) -> boolean(). +@@ -77,8 +77,8 @@ + %% + %% Tests + %% +--include_lib("eunit/include/eunit.hrl"). + -ifdef(TEST). ++-include_lib("eunit/include/eunit.hrl"). + get_put_delete_test() -> + K = '$$test$$mochiglobal', + delete(K), +diff -wbBur apache-couchdb-1.2.1/src/mochiweb/mochihex.erl apache-couchdb-1.2.1.q/src/mochiweb/mochihex.erl +--- apache-couchdb-1.2.1/src/mochiweb/mochihex.erl 2012-12-21 01:24:07.000000000 +0400 ++++ apache-couchdb-1.2.1.q/src/mochiweb/mochihex.erl 2013-03-22 15:26:58.000000000 +0400 +@@ -8,9 +8,6 @@ + + -export([to_hex/1, to_bin/1, to_int/1, dehex/1, hexdigit/1]). + +-%% @type iolist() = [char() | binary() | iolist()] +-%% @type iodata() = iolist() | binary() +- + %% @spec to_hex(integer | iolist()) -> string() + %% @doc Convert an iolist to a hexadecimal string. + to_hex(0) -> +@@ -68,8 +65,8 @@ + %% + %% Tests + %% +--include_lib("eunit/include/eunit.hrl"). + -ifdef(TEST). ++-include_lib("eunit/include/eunit.hrl"). + + to_hex_test() -> + "ff000ff1" = to_hex([255, 0, 15, 241]), +diff -wbBur apache-couchdb-1.2.1/src/mochiweb/mochijson2.erl apache-couchdb-1.2.1.q/src/mochiweb/mochijson2.erl +--- apache-couchdb-1.2.1/src/mochiweb/mochijson2.erl 2012-12-21 01:24:07.000000000 +0400 ++++ apache-couchdb-1.2.1.q/src/mochiweb/mochijson2.erl 2013-03-22 15:26:58.000000000 +0400 +@@ -40,9 +40,9 @@ + -module(mochijson2). + -author('bob@mochimedia.com'). + -export([encoder/1, encode/1]). +--export([decoder/1, decode/1]). ++-export([decoder/1, decode/1, decode/2]). + +-% This is a macro to placate syntax highlighters.. ++%% This is a macro to placate syntax highlighters.. + -define(Q, $\"). + -define(ADV_COL(S, N), S#decoder{offset=N+S#decoder.offset, + column=N+S#decoder.column}). +@@ -64,15 +64,14 @@ + -define(IS_WHITESPACE(C), + (C =:= $\s orelse C =:= $\t orelse C =:= $\r orelse C =:= $\n)). + +-%% @type iolist() = [char() | binary() | iolist()] +-%% @type iodata() = iolist() | binary() + %% @type json_string() = atom | binary() + %% @type json_number() = integer() | float() + %% @type json_array() = [json_term()] + %% @type json_object() = {struct, [{json_string(), json_term()}]} ++%% @type json_eep18_object() = {[{json_string(), json_term()}]} + %% @type json_iolist() = {json, iolist()} + %% @type json_term() = json_string() | json_number() | json_array() | +-%% json_object() | json_iolist() ++%% json_object() | json_eep18_object() | json_iolist() + + -record(encoder, {handler=null, + utf8=false}). +@@ -102,6 +101,14 @@ + State = parse_decoder_options(Options, #decoder{}), + fun (O) -> json_decode(O, State) end. + ++%% @spec decode(iolist(), [{format, proplist | eep18 | struct}]) -> json_term() ++%% @doc Decode the given iolist to Erlang terms using the given object format ++%% for decoding, where proplist returns JSON objects as [{binary(), json_term()}] ++%% proplists, eep18 returns JSON objects as {[binary(), json_term()]}, and struct ++%% returns them as-is. ++decode(S, Options) -> ++ json_decode(S, parse_decoder_options(Options, #decoder{})). ++ + %% @spec decode(iolist()) -> json_term() + %% @doc Decode the given iolist to Erlang terms. + decode(S) -> +@@ -119,7 +126,10 @@ + parse_decoder_options([], State) -> + State; + parse_decoder_options([{object_hook, Hook} | Rest], State) -> +- parse_decoder_options(Rest, State#decoder{object_hook=Hook}). ++ parse_decoder_options(Rest, State#decoder{object_hook=Hook}); ++parse_decoder_options([{format, Format} | Rest], State) ++ when Format =:= struct orelse Format =:= eep18 orelse Format =:= proplist -> ++ parse_decoder_options(Rest, State#decoder{object_hook=Format}). + + json_encode(true, _State) -> + <<"true">>; +@@ -139,6 +149,10 @@ + json_encode_proplist(Props, State); + json_encode({struct, Props}, State) when is_list(Props) -> + json_encode_proplist(Props, State); ++json_encode({Props}, State) when is_list(Props) -> ++ json_encode_proplist(Props, State); ++json_encode({}, State) -> ++ json_encode_proplist([], State); + json_encode(Array, State) when is_list(Array) -> + json_encode_array(Array, State); + json_encode({array, Array}, State) when is_list(Array) -> +@@ -318,8 +332,12 @@ + decode_object(B, S1) + end. + +-make_object(V, #decoder{object_hook=null}) -> ++make_object(V, #decoder{object_hook=N}) when N =:= null orelse N =:= struct -> + V; ++make_object({struct, P}, #decoder{object_hook=eep18}) -> ++ {P}; ++make_object({struct, P}, #decoder{object_hook=proplist}) -> ++ P; + make_object(V, #decoder{object_hook=Hook}) -> + Hook(V). + +@@ -559,8 +577,8 @@ + %% + %% Tests + %% +--include_lib("eunit/include/eunit.hrl"). + -ifdef(TEST). ++-include_lib("eunit/include/eunit.hrl"). + + + %% testing constructs borrowed from the Yaws JSON implementation. +@@ -838,12 +856,34 @@ + + handler_test() -> + ?assertEqual( +- {'EXIT',{json_encode,{bad_term,{}}}}, +- catch encode({})), +- F = fun ({}) -> [] end, ++ {'EXIT',{json_encode,{bad_term,{x,y}}}}, ++ catch encode({x,y})), ++ F = fun ({x,y}) -> [] end, + ?assertEqual( + <<"[]">>, +- iolist_to_binary((encoder([{handler, F}]))({}))), ++ iolist_to_binary((encoder([{handler, F}]))({x, y}))), + ok. + ++encode_empty_test_() -> ++ [{A, ?_assertEqual(<<"{}">>, iolist_to_binary(encode(B)))} ++ || {A, B} <- [{"eep18 {}", {}}, ++ {"eep18 {[]}", {[]}}, ++ {"{struct, []}", {struct, []}}]]. ++ ++encode_test_() -> ++ P = [{<<"k">>, <<"v">>}], ++ JSON = iolist_to_binary(encode({struct, P})), ++ [{atom_to_list(F), ++ ?_assertEqual(JSON, iolist_to_binary(encode(decode(JSON, [{format, F}]))))} ++ || F <- [struct, eep18, proplist]]. ++ ++format_test_() -> ++ P = [{<<"k">>, <<"v">>}], ++ JSON = iolist_to_binary(encode({struct, P})), ++ [{atom_to_list(F), ++ ?_assertEqual(A, decode(JSON, [{format, F}]))} ++ || {F, A} <- [{struct, {struct, P}}, ++ {eep18, {P}}, ++ {proplist, P}]]. ++ + -endif. +diff -wbBur apache-couchdb-1.2.1/src/mochiweb/mochijson.erl apache-couchdb-1.2.1.q/src/mochiweb/mochijson.erl +--- apache-couchdb-1.2.1/src/mochiweb/mochijson.erl 2012-12-21 01:24:07.000000000 +0400 ++++ apache-couchdb-1.2.1.q/src/mochiweb/mochijson.erl 2013-03-22 15:26:58.000000000 +0400 +@@ -15,8 +15,6 @@ + -define(INC_COL(S), S#decoder{column=1+S#decoder.column}). + -define(INC_LINE(S), S#decoder{column=1, line=1+S#decoder.line}). + +-%% @type iolist() = [char() | binary() | iolist()] +-%% @type iodata() = iolist() | binary() + %% @type json_string() = atom | string() | binary() + %% @type json_number() = integer() | float() + %% @type json_array() = {array, [json_term()]} +@@ -406,8 +404,8 @@ + %% + %% Tests + %% +--include_lib("eunit/include/eunit.hrl"). + -ifdef(TEST). ++-include_lib("eunit/include/eunit.hrl"). + + %% testing constructs borrowed from the Yaws JSON implementation. + +diff -wbBur apache-couchdb-1.2.1/src/mochiweb/mochilists.erl apache-couchdb-1.2.1.q/src/mochiweb/mochilists.erl +--- apache-couchdb-1.2.1/src/mochiweb/mochilists.erl 2012-12-21 01:24:07.000000000 +0400 ++++ apache-couchdb-1.2.1.q/src/mochiweb/mochilists.erl 2013-03-22 15:26:58.000000000 +0400 +@@ -55,8 +55,8 @@ + %% + %% Tests + %% +--include_lib("eunit/include/eunit.hrl"). + -ifdef(TEST). ++-include_lib("eunit/include/eunit.hrl"). + + set_defaults_test() -> + ?assertEqual( +diff -wbBur apache-couchdb-1.2.1/src/mochiweb/mochilogfile2.erl apache-couchdb-1.2.1.q/src/mochiweb/mochilogfile2.erl +--- apache-couchdb-1.2.1/src/mochiweb/mochilogfile2.erl 2012-12-21 01:24:07.000000000 +0400 ++++ apache-couchdb-1.2.1.q/src/mochiweb/mochilogfile2.erl 2013-03-22 15:26:58.000000000 +0400 +@@ -57,8 +57,8 @@ + %% + %% Tests + %% +--include_lib("eunit/include/eunit.hrl"). + -ifdef(TEST). ++-include_lib("eunit/include/eunit.hrl"). + name_test() -> + D = mochitemp:mkdtemp(), + FileName = filename:join(D, "open_close_test.log"), +diff -wbBur apache-couchdb-1.2.1/src/mochiweb/mochinum.erl apache-couchdb-1.2.1.q/src/mochiweb/mochinum.erl +--- apache-couchdb-1.2.1/src/mochiweb/mochinum.erl 2012-12-21 01:24:07.000000000 +0400 ++++ apache-couchdb-1.2.1.q/src/mochiweb/mochinum.erl 2013-03-22 15:26:58.000000000 +0400 +@@ -243,8 +243,8 @@ + %% + %% Tests + %% +--include_lib("eunit/include/eunit.hrl"). + -ifdef(TEST). ++-include_lib("eunit/include/eunit.hrl"). + + int_ceil_test() -> + ?assertEqual(1, int_ceil(0.0001)), +diff -wbBur apache-couchdb-1.2.1/src/mochiweb/mochitemp.erl apache-couchdb-1.2.1.q/src/mochiweb/mochitemp.erl +--- apache-couchdb-1.2.1/src/mochiweb/mochitemp.erl 2012-12-21 01:24:07.000000000 +0400 ++++ apache-couchdb-1.2.1.q/src/mochiweb/mochitemp.erl 2013-03-22 15:26:58.000000000 +0400 +@@ -135,8 +135,9 @@ + %% + %% Tests + %% +--include_lib("eunit/include/eunit.hrl"). + -ifdef(TEST). ++-include_lib("eunit/include/eunit.hrl"). ++ + pushenv(L) -> + [{K, os:getenv(K)} || K <- L]. + popenv(L) -> +diff -wbBur apache-couchdb-1.2.1/src/mochiweb/mochiutf8.erl apache-couchdb-1.2.1.q/src/mochiweb/mochiutf8.erl +--- apache-couchdb-1.2.1/src/mochiweb/mochiutf8.erl 2012-12-21 01:24:07.000000000 +0400 ++++ apache-couchdb-1.2.1.q/src/mochiweb/mochiutf8.erl 2013-03-22 15:26:58.000000000 +0400 +@@ -5,8 +5,9 @@ + %% invalid bytes. + + -module(mochiutf8). +--export([valid_utf8_bytes/1, codepoint_to_bytes/1, bytes_to_codepoints/1]). +--export([bytes_foldl/3, codepoint_foldl/3, read_codepoint/1, len/1]). ++-export([valid_utf8_bytes/1, codepoint_to_bytes/1, codepoints_to_bytes/1]). ++-export([bytes_to_codepoints/1, bytes_foldl/3, codepoint_foldl/3]). ++-export([read_codepoint/1, len/1]). + + %% External API + +@@ -192,8 +193,8 @@ + %% + %% Tests + %% +--include_lib("eunit/include/eunit.hrl"). + -ifdef(TEST). ++-include_lib("eunit/include/eunit.hrl"). + + binary_skip_bytes_test() -> + ?assertEqual(<<"foo">>, +diff -wbBur apache-couchdb-1.2.1/src/mochiweb/mochiweb_acceptor.erl apache-couchdb-1.2.1.q/src/mochiweb/mochiweb_acceptor.erl +--- apache-couchdb-1.2.1/src/mochiweb/mochiweb_acceptor.erl 2012-12-21 01:24:07.000000000 +0400 ++++ apache-couchdb-1.2.1.q/src/mochiweb/mochiweb_acceptor.erl 2013-03-22 15:26:58.000000000 +0400 +@@ -14,10 +14,10 @@ + proc_lib:spawn_link(?MODULE, init, [Server, Listen, Loop]). + + init(Server, Listen, Loop) -> +- T1 = now(), ++ T1 = os:timestamp(), + case catch mochiweb_socket:accept(Listen) of + {ok, Socket} -> +- gen_server:cast(Server, {accepted, self(), timer:now_diff(now(), T1)}), ++ gen_server:cast(Server, {accepted, self(), timer:now_diff(os:timestamp(), T1)}), + call_loop(Loop, Socket); + {error, closed} -> + exit(normal); +@@ -35,6 +35,8 @@ + + call_loop({M, F}, Socket) -> + M:F(Socket); ++call_loop({M, F, [A1]}, Socket) -> ++ M:F(Socket, A1); + call_loop({M, F, A}, Socket) -> + erlang:apply(M, F, [Socket | A]); + call_loop(Loop, Socket) -> +@@ -43,6 +45,6 @@ + %% + %% Tests + %% +--include_lib("eunit/include/eunit.hrl"). + -ifdef(TEST). ++-include_lib("eunit/include/eunit.hrl"). + -endif. +diff -wbBur apache-couchdb-1.2.1/src/mochiweb/mochiweb.app.src apache-couchdb-1.2.1.q/src/mochiweb/mochiweb.app.src +--- apache-couchdb-1.2.1/src/mochiweb/mochiweb.app.src 2012-12-21 01:24:07.000000000 +0400 ++++ apache-couchdb-1.2.1.q/src/mochiweb/mochiweb.app.src 2013-03-22 15:26:58.000000000 +0400 +@@ -1,9 +1,9 @@ + %% This is generated from src/mochiweb.app.src + {application, mochiweb, + [{description, "MochiMedia Web Server"}, +- {vsn, "1.4.1"}, ++ {vsn, "2.5.0"}, + {modules, []}, + {registered, []}, +- {mod, {mochiweb_app, []}}, + {env, []}, +- {applications, [kernel, stdlib, crypto, inets]}]}. ++ {applications, [kernel, stdlib, crypto, inets, ssl, xmerl, ++ compiler, syntax_tools]}]}. +diff -wbBur apache-couchdb-1.2.1/src/mochiweb/mochiweb_charref.erl apache-couchdb-1.2.1.q/src/mochiweb/mochiweb_charref.erl +--- apache-couchdb-1.2.1/src/mochiweb/mochiweb_charref.erl 2012-12-21 01:24:07.000000000 +0400 ++++ apache-couchdb-1.2.1.q/src/mochiweb/mochiweb_charref.erl 2013-03-22 15:26:58.000000000 +0400 +@@ -1,17 +1,17 @@ + %% @author Bob Ippolito + %% @copyright 2007 Mochi Media, Inc. + +-%% @doc Converts HTML 4 charrefs and entities to codepoints. ++%% @doc Converts HTML 5 charrefs and entities to codepoints (or lists of code points). + -module(mochiweb_charref). + -export([charref/1]). + + %% External API. + +-%% @spec charref(S) -> integer() | undefined + %% @doc Convert a decimal charref, hex charref, or html entity to a unicode + %% codepoint, or return undefined on failure. + %% The input should not include an ampersand or semicolon. + %% charref("#38") = 38, charref("#x26") = 38, charref("amp") = 38. ++-spec charref(binary() | string()) -> integer() | [integer()] | undefined. + charref(B) when is_binary(B) -> + charref(binary_to_list(B)); + charref([$#, C | L]) when C =:= $x orelse C =:= $X -> +@@ -29,266 +29,2141 @@ + + %% Internal API. + +-entity("nbsp") -> 160; +-entity("iexcl") -> 161; +-entity("cent") -> 162; +-entity("pound") -> 163; +-entity("curren") -> 164; +-entity("yen") -> 165; +-entity("brvbar") -> 166; +-entity("sect") -> 167; +-entity("uml") -> 168; +-entity("copy") -> 169; +-entity("ordf") -> 170; +-entity("laquo") -> 171; +-entity("not") -> 172; +-entity("shy") -> 173; +-entity("reg") -> 174; +-entity("macr") -> 175; +-entity("deg") -> 176; +-entity("plusmn") -> 177; +-entity("sup2") -> 178; +-entity("sup3") -> 179; +-entity("acute") -> 180; +-entity("micro") -> 181; +-entity("para") -> 182; +-entity("middot") -> 183; +-entity("cedil") -> 184; +-entity("sup1") -> 185; +-entity("ordm") -> 186; +-entity("raquo") -> 187; +-entity("frac14") -> 188; +-entity("frac12") -> 189; +-entity("frac34") -> 190; +-entity("iquest") -> 191; +-entity("Agrave") -> 192; +-entity("Aacute") -> 193; +-entity("Acirc") -> 194; +-entity("Atilde") -> 195; +-entity("Auml") -> 196; +-entity("Aring") -> 197; +-entity("AElig") -> 198; +-entity("Ccedil") -> 199; +-entity("Egrave") -> 200; +-entity("Eacute") -> 201; +-entity("Ecirc") -> 202; +-entity("Euml") -> 203; +-entity("Igrave") -> 204; +-entity("Iacute") -> 205; +-entity("Icirc") -> 206; +-entity("Iuml") -> 207; +-entity("ETH") -> 208; +-entity("Ntilde") -> 209; +-entity("Ograve") -> 210; +-entity("Oacute") -> 211; +-entity("Ocirc") -> 212; +-entity("Otilde") -> 213; +-entity("Ouml") -> 214; +-entity("times") -> 215; +-entity("Oslash") -> 216; +-entity("Ugrave") -> 217; +-entity("Uacute") -> 218; +-entity("Ucirc") -> 219; +-entity("Uuml") -> 220; +-entity("Yacute") -> 221; +-entity("THORN") -> 222; +-entity("szlig") -> 223; +-entity("agrave") -> 224; +-entity("aacute") -> 225; +-entity("acirc") -> 226; +-entity("atilde") -> 227; +-entity("auml") -> 228; +-entity("aring") -> 229; +-entity("aelig") -> 230; +-entity("ccedil") -> 231; +-entity("egrave") -> 232; +-entity("eacute") -> 233; +-entity("ecirc") -> 234; +-entity("euml") -> 235; +-entity("igrave") -> 236; +-entity("iacute") -> 237; +-entity("icirc") -> 238; +-entity("iuml") -> 239; +-entity("eth") -> 240; +-entity("ntilde") -> 241; +-entity("ograve") -> 242; +-entity("oacute") -> 243; +-entity("ocirc") -> 244; +-entity("otilde") -> 245; +-entity("ouml") -> 246; +-entity("divide") -> 247; +-entity("oslash") -> 248; +-entity("ugrave") -> 249; +-entity("uacute") -> 250; +-entity("ucirc") -> 251; +-entity("uuml") -> 252; +-entity("yacute") -> 253; +-entity("thorn") -> 254; +-entity("yuml") -> 255; +-entity("fnof") -> 402; +-entity("Alpha") -> 913; +-entity("Beta") -> 914; +-entity("Gamma") -> 915; +-entity("Delta") -> 916; +-entity("Epsilon") -> 917; +-entity("Zeta") -> 918; +-entity("Eta") -> 919; +-entity("Theta") -> 920; +-entity("Iota") -> 921; +-entity("Kappa") -> 922; +-entity("Lambda") -> 923; +-entity("Mu") -> 924; +-entity("Nu") -> 925; +-entity("Xi") -> 926; +-entity("Omicron") -> 927; +-entity("Pi") -> 928; +-entity("Rho") -> 929; +-entity("Sigma") -> 931; +-entity("Tau") -> 932; +-entity("Upsilon") -> 933; +-entity("Phi") -> 934; +-entity("Chi") -> 935; +-entity("Psi") -> 936; +-entity("Omega") -> 937; +-entity("alpha") -> 945; +-entity("beta") -> 946; +-entity("gamma") -> 947; +-entity("delta") -> 948; +-entity("epsilon") -> 949; +-entity("zeta") -> 950; +-entity("eta") -> 951; +-entity("theta") -> 952; +-entity("iota") -> 953; +-entity("kappa") -> 954; +-entity("lambda") -> 955; +-entity("mu") -> 956; +-entity("nu") -> 957; +-entity("xi") -> 958; +-entity("omicron") -> 959; +-entity("pi") -> 960; +-entity("rho") -> 961; +-entity("sigmaf") -> 962; +-entity("sigma") -> 963; +-entity("tau") -> 964; +-entity("upsilon") -> 965; +-entity("phi") -> 966; +-entity("chi") -> 967; +-entity("psi") -> 968; +-entity("omega") -> 969; +-entity("thetasym") -> 977; +-entity("upsih") -> 978; +-entity("piv") -> 982; +-entity("bull") -> 8226; +-entity("hellip") -> 8230; +-entity("prime") -> 8242; +-entity("Prime") -> 8243; +-entity("oline") -> 8254; +-entity("frasl") -> 8260; +-entity("weierp") -> 8472; +-entity("image") -> 8465; +-entity("real") -> 8476; +-entity("trade") -> 8482; +-entity("alefsym") -> 8501; +-entity("larr") -> 8592; +-entity("uarr") -> 8593; +-entity("rarr") -> 8594; +-entity("darr") -> 8595; +-entity("harr") -> 8596; +-entity("crarr") -> 8629; +-entity("lArr") -> 8656; +-entity("uArr") -> 8657; +-entity("rArr") -> 8658; +-entity("dArr") -> 8659; +-entity("hArr") -> 8660; +-entity("forall") -> 8704; +-entity("part") -> 8706; +-entity("exist") -> 8707; +-entity("empty") -> 8709; +-entity("nabla") -> 8711; +-entity("isin") -> 8712; +-entity("notin") -> 8713; +-entity("ni") -> 8715; +-entity("prod") -> 8719; +-entity("sum") -> 8721; +-entity("minus") -> 8722; +-entity("lowast") -> 8727; +-entity("radic") -> 8730; +-entity("prop") -> 8733; +-entity("infin") -> 8734; +-entity("ang") -> 8736; +-entity("and") -> 8743; +-entity("or") -> 8744; +-entity("cap") -> 8745; +-entity("cup") -> 8746; +-entity("int") -> 8747; +-entity("there4") -> 8756; +-entity("sim") -> 8764; +-entity("cong") -> 8773; +-entity("asymp") -> 8776; +-entity("ne") -> 8800; +-entity("equiv") -> 8801; +-entity("le") -> 8804; +-entity("ge") -> 8805; +-entity("sub") -> 8834; +-entity("sup") -> 8835; +-entity("nsub") -> 8836; +-entity("sube") -> 8838; +-entity("supe") -> 8839; +-entity("oplus") -> 8853; +-entity("otimes") -> 8855; +-entity("perp") -> 8869; +-entity("sdot") -> 8901; +-entity("lceil") -> 8968; +-entity("rceil") -> 8969; +-entity("lfloor") -> 8970; +-entity("rfloor") -> 8971; +-entity("lang") -> 9001; +-entity("rang") -> 9002; +-entity("loz") -> 9674; +-entity("spades") -> 9824; +-entity("clubs") -> 9827; +-entity("hearts") -> 9829; +-entity("diams") -> 9830; +-entity("quot") -> 34; +-entity("amp") -> 38; +-entity("lt") -> 60; +-entity("gt") -> 62; +-entity("OElig") -> 338; +-entity("oelig") -> 339; +-entity("Scaron") -> 352; +-entity("scaron") -> 353; +-entity("Yuml") -> 376; +-entity("circ") -> 710; +-entity("tilde") -> 732; +-entity("ensp") -> 8194; +-entity("emsp") -> 8195; +-entity("thinsp") -> 8201; +-entity("zwnj") -> 8204; +-entity("zwj") -> 8205; +-entity("lrm") -> 8206; +-entity("rlm") -> 8207; +-entity("ndash") -> 8211; +-entity("mdash") -> 8212; +-entity("lsquo") -> 8216; +-entity("rsquo") -> 8217; +-entity("sbquo") -> 8218; +-entity("ldquo") -> 8220; +-entity("rdquo") -> 8221; +-entity("bdquo") -> 8222; +-entity("dagger") -> 8224; +-entity("Dagger") -> 8225; +-entity("permil") -> 8240; +-entity("lsaquo") -> 8249; +-entity("rsaquo") -> 8250; +-entity("euro") -> 8364; +-entity(_) -> undefined. ++%% [2011-10-14] Generated from: ++%% http://www.w3.org/TR/html5/named-character-references.html + ++entity("AElig") -> 16#000C6; ++entity("AMP") -> 16#00026; ++entity("Aacute") -> 16#000C1; ++entity("Abreve") -> 16#00102; ++entity("Acirc") -> 16#000C2; ++entity("Acy") -> 16#00410; ++entity("Afr") -> 16#1D504; ++entity("Agrave") -> 16#000C0; ++entity("Alpha") -> 16#00391; ++entity("Amacr") -> 16#00100; ++entity("And") -> 16#02A53; ++entity("Aogon") -> 16#00104; ++entity("Aopf") -> 16#1D538; ++entity("ApplyFunction") -> 16#02061; ++entity("Aring") -> 16#000C5; ++entity("Ascr") -> 16#1D49C; ++entity("Assign") -> 16#02254; ++entity("Atilde") -> 16#000C3; ++entity("Auml") -> 16#000C4; ++entity("Backslash") -> 16#02216; ++entity("Barv") -> 16#02AE7; ++entity("Barwed") -> 16#02306; ++entity("Bcy") -> 16#00411; ++entity("Because") -> 16#02235; ++entity("Bernoullis") -> 16#0212C; ++entity("Beta") -> 16#00392; ++entity("Bfr") -> 16#1D505; ++entity("Bopf") -> 16#1D539; ++entity("Breve") -> 16#002D8; ++entity("Bscr") -> 16#0212C; ++entity("Bumpeq") -> 16#0224E; ++entity("CHcy") -> 16#00427; ++entity("COPY") -> 16#000A9; ++entity("Cacute") -> 16#00106; ++entity("Cap") -> 16#022D2; ++entity("CapitalDifferentialD") -> 16#02145; ++entity("Cayleys") -> 16#0212D; ++entity("Ccaron") -> 16#0010C; ++entity("Ccedil") -> 16#000C7; ++entity("Ccirc") -> 16#00108; ++entity("Cconint") -> 16#02230; ++entity("Cdot") -> 16#0010A; ++entity("Cedilla") -> 16#000B8; ++entity("CenterDot") -> 16#000B7; ++entity("Cfr") -> 16#0212D; ++entity("Chi") -> 16#003A7; ++entity("CircleDot") -> 16#02299; ++entity("CircleMinus") -> 16#02296; ++entity("CirclePlus") -> 16#02295; ++entity("CircleTimes") -> 16#02297; ++entity("ClockwiseContourIntegral") -> 16#02232; ++entity("CloseCurlyDoubleQuote") -> 16#0201D; ++entity("CloseCurlyQuote") -> 16#02019; ++entity("Colon") -> 16#02237; ++entity("Colone") -> 16#02A74; ++entity("Congruent") -> 16#02261; ++entity("Conint") -> 16#0222F; ++entity("ContourIntegral") -> 16#0222E; ++entity("Copf") -> 16#02102; ++entity("Coproduct") -> 16#02210; ++entity("CounterClockwiseContourIntegral") -> 16#02233; ++entity("Cross") -> 16#02A2F; ++entity("Cscr") -> 16#1D49E; ++entity("Cup") -> 16#022D3; ++entity("CupCap") -> 16#0224D; ++entity("DD") -> 16#02145; ++entity("DDotrahd") -> 16#02911; ++entity("DJcy") -> 16#00402; ++entity("DScy") -> 16#00405; ++entity("DZcy") -> 16#0040F; ++entity("Dagger") -> 16#02021; ++entity("Darr") -> 16#021A1; ++entity("Dashv") -> 16#02AE4; ++entity("Dcaron") -> 16#0010E; ++entity("Dcy") -> 16#00414; ++entity("Del") -> 16#02207; ++entity("Delta") -> 16#00394; ++entity("Dfr") -> 16#1D507; ++entity("DiacriticalAcute") -> 16#000B4; ++entity("DiacriticalDot") -> 16#002D9; ++entity("DiacriticalDoubleAcute") -> 16#002DD; ++entity("DiacriticalGrave") -> 16#00060; ++entity("DiacriticalTilde") -> 16#002DC; ++entity("Diamond") -> 16#022C4; ++entity("DifferentialD") -> 16#02146; ++entity("Dopf") -> 16#1D53B; ++entity("Dot") -> 16#000A8; ++entity("DotDot") -> 16#020DC; ++entity("DotEqual") -> 16#02250; ++entity("DoubleContourIntegral") -> 16#0222F; ++entity("DoubleDot") -> 16#000A8; ++entity("DoubleDownArrow") -> 16#021D3; ++entity("DoubleLeftArrow") -> 16#021D0; ++entity("DoubleLeftRightArrow") -> 16#021D4; ++entity("DoubleLeftTee") -> 16#02AE4; ++entity("DoubleLongLeftArrow") -> 16#027F8; ++entity("DoubleLongLeftRightArrow") -> 16#027FA; ++entity("DoubleLongRightArrow") -> 16#027F9; ++entity("DoubleRightArrow") -> 16#021D2; ++entity("DoubleRightTee") -> 16#022A8; ++entity("DoubleUpArrow") -> 16#021D1; ++entity("DoubleUpDownArrow") -> 16#021D5; ++entity("DoubleVerticalBar") -> 16#02225; ++entity("DownArrow") -> 16#02193; ++entity("DownArrowBar") -> 16#02913; ++entity("DownArrowUpArrow") -> 16#021F5; ++entity("DownBreve") -> 16#00311; ++entity("DownLeftRightVector") -> 16#02950; ++entity("DownLeftTeeVector") -> 16#0295E; ++entity("DownLeftVector") -> 16#021BD; ++entity("DownLeftVectorBar") -> 16#02956; ++entity("DownRightTeeVector") -> 16#0295F; ++entity("DownRightVector") -> 16#021C1; ++entity("DownRightVectorBar") -> 16#02957; ++entity("DownTee") -> 16#022A4; ++entity("DownTeeArrow") -> 16#021A7; ++entity("Downarrow") -> 16#021D3; ++entity("Dscr") -> 16#1D49F; ++entity("Dstrok") -> 16#00110; ++entity("ENG") -> 16#0014A; ++entity("ETH") -> 16#000D0; ++entity("Eacute") -> 16#000C9; ++entity("Ecaron") -> 16#0011A; ++entity("Ecirc") -> 16#000CA; ++entity("Ecy") -> 16#0042D; ++entity("Edot") -> 16#00116; ++entity("Efr") -> 16#1D508; ++entity("Egrave") -> 16#000C8; ++entity("Element") -> 16#02208; ++entity("Emacr") -> 16#00112; ++entity("EmptySmallSquare") -> 16#025FB; ++entity("EmptyVerySmallSquare") -> 16#025AB; ++entity("Eogon") -> 16#00118; ++entity("Eopf") -> 16#1D53C; ++entity("Epsilon") -> 16#00395; ++entity("Equal") -> 16#02A75; ++entity("EqualTilde") -> 16#02242; ++entity("Equilibrium") -> 16#021CC; ++entity("Escr") -> 16#02130; ++entity("Esim") -> 16#02A73; ++entity("Eta") -> 16#00397; ++entity("Euml") -> 16#000CB; ++entity("Exists") -> 16#02203; ++entity("ExponentialE") -> 16#02147; ++entity("Fcy") -> 16#00424; ++entity("Ffr") -> 16#1D509; ++entity("FilledSmallSquare") -> 16#025FC; ++entity("FilledVerySmallSquare") -> 16#025AA; ++entity("Fopf") -> 16#1D53D; ++entity("ForAll") -> 16#02200; ++entity("Fouriertrf") -> 16#02131; ++entity("Fscr") -> 16#02131; ++entity("GJcy") -> 16#00403; ++entity("GT") -> 16#0003E; ++entity("Gamma") -> 16#00393; ++entity("Gammad") -> 16#003DC; ++entity("Gbreve") -> 16#0011E; ++entity("Gcedil") -> 16#00122; ++entity("Gcirc") -> 16#0011C; ++entity("Gcy") -> 16#00413; ++entity("Gdot") -> 16#00120; ++entity("Gfr") -> 16#1D50A; ++entity("Gg") -> 16#022D9; ++entity("Gopf") -> 16#1D53E; ++entity("GreaterEqual") -> 16#02265; ++entity("GreaterEqualLess") -> 16#022DB; ++entity("GreaterFullEqual") -> 16#02267; ++entity("GreaterGreater") -> 16#02AA2; ++entity("GreaterLess") -> 16#02277; ++entity("GreaterSlantEqual") -> 16#02A7E; ++entity("GreaterTilde") -> 16#02273; ++entity("Gscr") -> 16#1D4A2; ++entity("Gt") -> 16#0226B; ++entity("HARDcy") -> 16#0042A; ++entity("Hacek") -> 16#002C7; ++entity("Hat") -> 16#0005E; ++entity("Hcirc") -> 16#00124; ++entity("Hfr") -> 16#0210C; ++entity("HilbertSpace") -> 16#0210B; ++entity("Hopf") -> 16#0210D; ++entity("HorizontalLine") -> 16#02500; ++entity("Hscr") -> 16#0210B; ++entity("Hstrok") -> 16#00126; ++entity("HumpDownHump") -> 16#0224E; ++entity("HumpEqual") -> 16#0224F; ++entity("IEcy") -> 16#00415; ++entity("IJlig") -> 16#00132; ++entity("IOcy") -> 16#00401; ++entity("Iacute") -> 16#000CD; ++entity("Icirc") -> 16#000CE; ++entity("Icy") -> 16#00418; ++entity("Idot") -> 16#00130; ++entity("Ifr") -> 16#02111; ++entity("Igrave") -> 16#000CC; ++entity("Im") -> 16#02111; ++entity("Imacr") -> 16#0012A; ++entity("ImaginaryI") -> 16#02148; ++entity("Implies") -> 16#021D2; ++entity("Int") -> 16#0222C; ++entity("Integral") -> 16#0222B; ++entity("Intersection") -> 16#022C2; ++entity("InvisibleComma") -> 16#02063; ++entity("InvisibleTimes") -> 16#02062; ++entity("Iogon") -> 16#0012E; ++entity("Iopf") -> 16#1D540; ++entity("Iota") -> 16#00399; ++entity("Iscr") -> 16#02110; ++entity("Itilde") -> 16#00128; ++entity("Iukcy") -> 16#00406; ++entity("Iuml") -> 16#000CF; ++entity("Jcirc") -> 16#00134; ++entity("Jcy") -> 16#00419; ++entity("Jfr") -> 16#1D50D; ++entity("Jopf") -> 16#1D541; ++entity("Jscr") -> 16#1D4A5; ++entity("Jsercy") -> 16#00408; ++entity("Jukcy") -> 16#00404; ++entity("KHcy") -> 16#00425; ++entity("KJcy") -> 16#0040C; ++entity("Kappa") -> 16#0039A; ++entity("Kcedil") -> 16#00136; ++entity("Kcy") -> 16#0041A; ++entity("Kfr") -> 16#1D50E; ++entity("Kopf") -> 16#1D542; ++entity("Kscr") -> 16#1D4A6; ++entity("LJcy") -> 16#00409; ++entity("LT") -> 16#0003C; ++entity("Lacute") -> 16#00139; ++entity("Lambda") -> 16#0039B; ++entity("Lang") -> 16#027EA; ++entity("Laplacetrf") -> 16#02112; ++entity("Larr") -> 16#0219E; ++entity("Lcaron") -> 16#0013D; ++entity("Lcedil") -> 16#0013B; ++entity("Lcy") -> 16#0041B; ++entity("LeftAngleBracket") -> 16#027E8; ++entity("LeftArrow") -> 16#02190; ++entity("LeftArrowBar") -> 16#021E4; ++entity("LeftArrowRightArrow") -> 16#021C6; ++entity("LeftCeiling") -> 16#02308; ++entity("LeftDoubleBracket") -> 16#027E6; ++entity("LeftDownTeeVector") -> 16#02961; ++entity("LeftDownVector") -> 16#021C3; ++entity("LeftDownVectorBar") -> 16#02959; ++entity("LeftFloor") -> 16#0230A; ++entity("LeftRightArrow") -> 16#02194; ++entity("LeftRightVector") -> 16#0294E; ++entity("LeftTee") -> 16#022A3; ++entity("LeftTeeArrow") -> 16#021A4; ++entity("LeftTeeVector") -> 16#0295A; ++entity("LeftTriangle") -> 16#022B2; ++entity("LeftTriangleBar") -> 16#029CF; ++entity("LeftTriangleEqual") -> 16#022B4; ++entity("LeftUpDownVector") -> 16#02951; ++entity("LeftUpTeeVector") -> 16#02960; ++entity("LeftUpVector") -> 16#021BF; ++entity("LeftUpVectorBar") -> 16#02958; ++entity("LeftVector") -> 16#021BC; ++entity("LeftVectorBar") -> 16#02952; ++entity("Leftarrow") -> 16#021D0; ++entity("Leftrightarrow") -> 16#021D4; ++entity("LessEqualGreater") -> 16#022DA; ++entity("LessFullEqual") -> 16#02266; ++entity("LessGreater") -> 16#02276; ++entity("LessLess") -> 16#02AA1; ++entity("LessSlantEqual") -> 16#02A7D; ++entity("LessTilde") -> 16#02272; ++entity("Lfr") -> 16#1D50F; ++entity("Ll") -> 16#022D8; ++entity("Lleftarrow") -> 16#021DA; ++entity("Lmidot") -> 16#0013F; ++entity("LongLeftArrow") -> 16#027F5; ++entity("LongLeftRightArrow") -> 16#027F7; ++entity("LongRightArrow") -> 16#027F6; ++entity("Longleftarrow") -> 16#027F8; ++entity("Longleftrightarrow") -> 16#027FA; ++entity("Longrightarrow") -> 16#027F9; ++entity("Lopf") -> 16#1D543; ++entity("LowerLeftArrow") -> 16#02199; ++entity("LowerRightArrow") -> 16#02198; ++entity("Lscr") -> 16#02112; ++entity("Lsh") -> 16#021B0; ++entity("Lstrok") -> 16#00141; ++entity("Lt") -> 16#0226A; ++entity("Map") -> 16#02905; ++entity("Mcy") -> 16#0041C; ++entity("MediumSpace") -> 16#0205F; ++entity("Mellintrf") -> 16#02133; ++entity("Mfr") -> 16#1D510; ++entity("MinusPlus") -> 16#02213; ++entity("Mopf") -> 16#1D544; ++entity("Mscr") -> 16#02133; ++entity("Mu") -> 16#0039C; ++entity("NJcy") -> 16#0040A; ++entity("Nacute") -> 16#00143; ++entity("Ncaron") -> 16#00147; ++entity("Ncedil") -> 16#00145; ++entity("Ncy") -> 16#0041D; ++entity("NegativeMediumSpace") -> 16#0200B; ++entity("NegativeThickSpace") -> 16#0200B; ++entity("NegativeThinSpace") -> 16#0200B; ++entity("NegativeVeryThinSpace") -> 16#0200B; ++entity("NestedGreaterGreater") -> 16#0226B; ++entity("NestedLessLess") -> 16#0226A; ++entity("NewLine") -> 16#0000A; ++entity("Nfr") -> 16#1D511; ++entity("NoBreak") -> 16#02060; ++entity("NonBreakingSpace") -> 16#000A0; ++entity("Nopf") -> 16#02115; ++entity("Not") -> 16#02AEC; ++entity("NotCongruent") -> 16#02262; ++entity("NotCupCap") -> 16#0226D; ++entity("NotDoubleVerticalBar") -> 16#02226; ++entity("NotElement") -> 16#02209; ++entity("NotEqual") -> 16#02260; ++entity("NotEqualTilde") -> [16#02242, 16#00338]; ++entity("NotExists") -> 16#02204; ++entity("NotGreater") -> 16#0226F; ++entity("NotGreaterEqual") -> 16#02271; ++entity("NotGreaterFullEqual") -> [16#02267, 16#00338]; ++entity("NotGreaterGreater") -> [16#0226B, 16#00338]; ++entity("NotGreaterLess") -> 16#02279; ++entity("NotGreaterSlantEqual") -> [16#02A7E, 16#00338]; ++entity("NotGreaterTilde") -> 16#02275; ++entity("NotHumpDownHump") -> [16#0224E, 16#00338]; ++entity("NotHumpEqual") -> [16#0224F, 16#00338]; ++entity("NotLeftTriangle") -> 16#022EA; ++entity("NotLeftTriangleBar") -> [16#029CF, 16#00338]; ++entity("NotLeftTriangleEqual") -> 16#022EC; ++entity("NotLess") -> 16#0226E; ++entity("NotLessEqual") -> 16#02270; ++entity("NotLessGreater") -> 16#02278; ++entity("NotLessLess") -> [16#0226A, 16#00338]; ++entity("NotLessSlantEqual") -> [16#02A7D, 16#00338]; ++entity("NotLessTilde") -> 16#02274; ++entity("NotNestedGreaterGreater") -> [16#02AA2, 16#00338]; ++entity("NotNestedLessLess") -> [16#02AA1, 16#00338]; ++entity("NotPrecedes") -> 16#02280; ++entity("NotPrecedesEqual") -> [16#02AAF, 16#00338]; ++entity("NotPrecedesSlantEqual") -> 16#022E0; ++entity("NotReverseElement") -> 16#0220C; ++entity("NotRightTriangle") -> 16#022EB; ++entity("NotRightTriangleBar") -> [16#029D0, 16#00338]; ++entity("NotRightTriangleEqual") -> 16#022ED; ++entity("NotSquareSubset") -> [16#0228F, 16#00338]; ++entity("NotSquareSubsetEqual") -> 16#022E2; ++entity("NotSquareSuperset") -> [16#02290, 16#00338]; ++entity("NotSquareSupersetEqual") -> 16#022E3; ++entity("NotSubset") -> [16#02282, 16#020D2]; ++entity("NotSubsetEqual") -> 16#02288; ++entity("NotSucceeds") -> 16#02281; ++entity("NotSucceedsEqual") -> [16#02AB0, 16#00338]; ++entity("NotSucceedsSlantEqual") -> 16#022E1; ++entity("NotSucceedsTilde") -> [16#0227F, 16#00338]; ++entity("NotSuperset") -> [16#02283, 16#020D2]; ++entity("NotSupersetEqual") -> 16#02289; ++entity("NotTilde") -> 16#02241; ++entity("NotTildeEqual") -> 16#02244; ++entity("NotTildeFullEqual") -> 16#02247; ++entity("NotTildeTilde") -> 16#02249; ++entity("NotVerticalBar") -> 16#02224; ++entity("Nscr") -> 16#1D4A9; ++entity("Ntilde") -> 16#000D1; ++entity("Nu") -> 16#0039D; ++entity("OElig") -> 16#00152; ++entity("Oacute") -> 16#000D3; ++entity("Ocirc") -> 16#000D4; ++entity("Ocy") -> 16#0041E; ++entity("Odblac") -> 16#00150; ++entity("Ofr") -> 16#1D512; ++entity("Ograve") -> 16#000D2; ++entity("Omacr") -> 16#0014C; ++entity("Omega") -> 16#003A9; ++entity("Omicron") -> 16#0039F; ++entity("Oopf") -> 16#1D546; ++entity("OpenCurlyDoubleQuote") -> 16#0201C; ++entity("OpenCurlyQuote") -> 16#02018; ++entity("Or") -> 16#02A54; ++entity("Oscr") -> 16#1D4AA; ++entity("Oslash") -> 16#000D8; ++entity("Otilde") -> 16#000D5; ++entity("Otimes") -> 16#02A37; ++entity("Ouml") -> 16#000D6; ++entity("OverBar") -> 16#0203E; ++entity("OverBrace") -> 16#023DE; ++entity("OverBracket") -> 16#023B4; ++entity("OverParenthesis") -> 16#023DC; ++entity("PartialD") -> 16#02202; ++entity("Pcy") -> 16#0041F; ++entity("Pfr") -> 16#1D513; ++entity("Phi") -> 16#003A6; ++entity("Pi") -> 16#003A0; ++entity("PlusMinus") -> 16#000B1; ++entity("Poincareplane") -> 16#0210C; ++entity("Popf") -> 16#02119; ++entity("Pr") -> 16#02ABB; ++entity("Precedes") -> 16#0227A; ++entity("PrecedesEqual") -> 16#02AAF; ++entity("PrecedesSlantEqual") -> 16#0227C; ++entity("PrecedesTilde") -> 16#0227E; ++entity("Prime") -> 16#02033; ++entity("Product") -> 16#0220F; ++entity("Proportion") -> 16#02237; ++entity("Proportional") -> 16#0221D; ++entity("Pscr") -> 16#1D4AB; ++entity("Psi") -> 16#003A8; ++entity("QUOT") -> 16#00022; ++entity("Qfr") -> 16#1D514; ++entity("Qopf") -> 16#0211A; ++entity("Qscr") -> 16#1D4AC; ++entity("RBarr") -> 16#02910; ++entity("REG") -> 16#000AE; ++entity("Racute") -> 16#00154; ++entity("Rang") -> 16#027EB; ++entity("Rarr") -> 16#021A0; ++entity("Rarrtl") -> 16#02916; ++entity("Rcaron") -> 16#00158; ++entity("Rcedil") -> 16#00156; ++entity("Rcy") -> 16#00420; ++entity("Re") -> 16#0211C; ++entity("ReverseElement") -> 16#0220B; ++entity("ReverseEquilibrium") -> 16#021CB; ++entity("ReverseUpEquilibrium") -> 16#0296F; ++entity("Rfr") -> 16#0211C; ++entity("Rho") -> 16#003A1; ++entity("RightAngleBracket") -> 16#027E9; ++entity("RightArrow") -> 16#02192; ++entity("RightArrowBar") -> 16#021E5; ++entity("RightArrowLeftArrow") -> 16#021C4; ++entity("RightCeiling") -> 16#02309; ++entity("RightDoubleBracket") -> 16#027E7; ++entity("RightDownTeeVector") -> 16#0295D; ++entity("RightDownVector") -> 16#021C2; ++entity("RightDownVectorBar") -> 16#02955; ++entity("RightFloor") -> 16#0230B; ++entity("RightTee") -> 16#022A2; ++entity("RightTeeArrow") -> 16#021A6; ++entity("RightTeeVector") -> 16#0295B; ++entity("RightTriangle") -> 16#022B3; ++entity("RightTriangleBar") -> 16#029D0; ++entity("RightTriangleEqual") -> 16#022B5; ++entity("RightUpDownVector") -> 16#0294F; ++entity("RightUpTeeVector") -> 16#0295C; ++entity("RightUpVector") -> 16#021BE; ++entity("RightUpVectorBar") -> 16#02954; ++entity("RightVector") -> 16#021C0; ++entity("RightVectorBar") -> 16#02953; ++entity("Rightarrow") -> 16#021D2; ++entity("Ropf") -> 16#0211D; ++entity("RoundImplies") -> 16#02970; ++entity("Rrightarrow") -> 16#021DB; ++entity("Rscr") -> 16#0211B; ++entity("Rsh") -> 16#021B1; ++entity("RuleDelayed") -> 16#029F4; ++entity("SHCHcy") -> 16#00429; ++entity("SHcy") -> 16#00428; ++entity("SOFTcy") -> 16#0042C; ++entity("Sacute") -> 16#0015A; ++entity("Sc") -> 16#02ABC; ++entity("Scaron") -> 16#00160; ++entity("Scedil") -> 16#0015E; ++entity("Scirc") -> 16#0015C; ++entity("Scy") -> 16#00421; ++entity("Sfr") -> 16#1D516; ++entity("ShortDownArrow") -> 16#02193; ++entity("ShortLeftArrow") -> 16#02190; ++entity("ShortRightArrow") -> 16#02192; ++entity("ShortUpArrow") -> 16#02191; ++entity("Sigma") -> 16#003A3; ++entity("SmallCircle") -> 16#02218; ++entity("Sopf") -> 16#1D54A; ++entity("Sqrt") -> 16#0221A; ++entity("Square") -> 16#025A1; ++entity("SquareIntersection") -> 16#02293; ++entity("SquareSubset") -> 16#0228F; ++entity("SquareSubsetEqual") -> 16#02291; ++entity("SquareSuperset") -> 16#02290; ++entity("SquareSupersetEqual") -> 16#02292; ++entity("SquareUnion") -> 16#02294; ++entity("Sscr") -> 16#1D4AE; ++entity("Star") -> 16#022C6; ++entity("Sub") -> 16#022D0; ++entity("Subset") -> 16#022D0; ++entity("SubsetEqual") -> 16#02286; ++entity("Succeeds") -> 16#0227B; ++entity("SucceedsEqual") -> 16#02AB0; ++entity("SucceedsSlantEqual") -> 16#0227D; ++entity("SucceedsTilde") -> 16#0227F; ++entity("SuchThat") -> 16#0220B; ++entity("Sum") -> 16#02211; ++entity("Sup") -> 16#022D1; ++entity("Superset") -> 16#02283; ++entity("SupersetEqual") -> 16#02287; ++entity("Supset") -> 16#022D1; ++entity("THORN") -> 16#000DE; ++entity("TRADE") -> 16#02122; ++entity("TSHcy") -> 16#0040B; ++entity("TScy") -> 16#00426; ++entity("Tab") -> 16#00009; ++entity("Tau") -> 16#003A4; ++entity("Tcaron") -> 16#00164; ++entity("Tcedil") -> 16#00162; ++entity("Tcy") -> 16#00422; ++entity("Tfr") -> 16#1D517; ++entity("Therefore") -> 16#02234; ++entity("Theta") -> 16#00398; ++entity("ThickSpace") -> [16#0205F, 16#0200A]; ++entity("ThinSpace") -> 16#02009; ++entity("Tilde") -> 16#0223C; ++entity("TildeEqual") -> 16#02243; ++entity("TildeFullEqual") -> 16#02245; ++entity("TildeTilde") -> 16#02248; ++entity("Topf") -> 16#1D54B; ++entity("TripleDot") -> 16#020DB; ++entity("Tscr") -> 16#1D4AF; ++entity("Tstrok") -> 16#00166; ++entity("Uacute") -> 16#000DA; ++entity("Uarr") -> 16#0219F; ++entity("Uarrocir") -> 16#02949; ++entity("Ubrcy") -> 16#0040E; ++entity("Ubreve") -> 16#0016C; ++entity("Ucirc") -> 16#000DB; ++entity("Ucy") -> 16#00423; ++entity("Udblac") -> 16#00170; ++entity("Ufr") -> 16#1D518; ++entity("Ugrave") -> 16#000D9; ++entity("Umacr") -> 16#0016A; ++entity("UnderBar") -> 16#0005F; ++entity("UnderBrace") -> 16#023DF; ++entity("UnderBracket") -> 16#023B5; ++entity("UnderParenthesis") -> 16#023DD; ++entity("Union") -> 16#022C3; ++entity("UnionPlus") -> 16#0228E; ++entity("Uogon") -> 16#00172; ++entity("Uopf") -> 16#1D54C; ++entity("UpArrow") -> 16#02191; ++entity("UpArrowBar") -> 16#02912; ++entity("UpArrowDownArrow") -> 16#021C5; ++entity("UpDownArrow") -> 16#02195; ++entity("UpEquilibrium") -> 16#0296E; ++entity("UpTee") -> 16#022A5; ++entity("UpTeeArrow") -> 16#021A5; ++entity("Uparrow") -> 16#021D1; ++entity("Updownarrow") -> 16#021D5; ++entity("UpperLeftArrow") -> 16#02196; ++entity("UpperRightArrow") -> 16#02197; ++entity("Upsi") -> 16#003D2; ++entity("Upsilon") -> 16#003A5; ++entity("Uring") -> 16#0016E; ++entity("Uscr") -> 16#1D4B0; ++entity("Utilde") -> 16#00168; ++entity("Uuml") -> 16#000DC; ++entity("VDash") -> 16#022AB; ++entity("Vbar") -> 16#02AEB; ++entity("Vcy") -> 16#00412; ++entity("Vdash") -> 16#022A9; ++entity("Vdashl") -> 16#02AE6; ++entity("Vee") -> 16#022C1; ++entity("Verbar") -> 16#02016; ++entity("Vert") -> 16#02016; ++entity("VerticalBar") -> 16#02223; ++entity("VerticalLine") -> 16#0007C; ++entity("VerticalSeparator") -> 16#02758; ++entity("VerticalTilde") -> 16#02240; ++entity("VeryThinSpace") -> 16#0200A; ++entity("Vfr") -> 16#1D519; ++entity("Vopf") -> 16#1D54D; ++entity("Vscr") -> 16#1D4B1; ++entity("Vvdash") -> 16#022AA; ++entity("Wcirc") -> 16#00174; ++entity("Wedge") -> 16#022C0; ++entity("Wfr") -> 16#1D51A; ++entity("Wopf") -> 16#1D54E; ++entity("Wscr") -> 16#1D4B2; ++entity("Xfr") -> 16#1D51B; ++entity("Xi") -> 16#0039E; ++entity("Xopf") -> 16#1D54F; ++entity("Xscr") -> 16#1D4B3; ++entity("YAcy") -> 16#0042F; ++entity("YIcy") -> 16#00407; ++entity("YUcy") -> 16#0042E; ++entity("Yacute") -> 16#000DD; ++entity("Ycirc") -> 16#00176; ++entity("Ycy") -> 16#0042B; ++entity("Yfr") -> 16#1D51C; ++entity("Yopf") -> 16#1D550; ++entity("Yscr") -> 16#1D4B4; ++entity("Yuml") -> 16#00178; ++entity("ZHcy") -> 16#00416; ++entity("Zacute") -> 16#00179; ++entity("Zcaron") -> 16#0017D; ++entity("Zcy") -> 16#00417; ++entity("Zdot") -> 16#0017B; ++entity("ZeroWidthSpace") -> 16#0200B; ++entity("Zeta") -> 16#00396; ++entity("Zfr") -> 16#02128; ++entity("Zopf") -> 16#02124; ++entity("Zscr") -> 16#1D4B5; ++entity("aacute") -> 16#000E1; ++entity("abreve") -> 16#00103; ++entity("ac") -> 16#0223E; ++entity("acE") -> [16#0223E, 16#00333]; ++entity("acd") -> 16#0223F; ++entity("acirc") -> 16#000E2; ++entity("acute") -> 16#000B4; ++entity("acy") -> 16#00430; ++entity("aelig") -> 16#000E6; ++entity("af") -> 16#02061; ++entity("afr") -> 16#1D51E; ++entity("agrave") -> 16#000E0; ++entity("alefsym") -> 16#02135; ++entity("aleph") -> 16#02135; ++entity("alpha") -> 16#003B1; ++entity("amacr") -> 16#00101; ++entity("amalg") -> 16#02A3F; ++entity("amp") -> 16#00026; ++entity("and") -> 16#02227; ++entity("andand") -> 16#02A55; ++entity("andd") -> 16#02A5C; ++entity("andslope") -> 16#02A58; ++entity("andv") -> 16#02A5A; ++entity("ang") -> 16#02220; ++entity("ange") -> 16#029A4; ++entity("angle") -> 16#02220; ++entity("angmsd") -> 16#02221; ++entity("angmsdaa") -> 16#029A8; ++entity("angmsdab") -> 16#029A9; ++entity("angmsdac") -> 16#029AA; ++entity("angmsdad") -> 16#029AB; ++entity("angmsdae") -> 16#029AC; ++entity("angmsdaf") -> 16#029AD; ++entity("angmsdag") -> 16#029AE; ++entity("angmsdah") -> 16#029AF; ++entity("angrt") -> 16#0221F; ++entity("angrtvb") -> 16#022BE; ++entity("angrtvbd") -> 16#0299D; ++entity("angsph") -> 16#02222; ++entity("angst") -> 16#000C5; ++entity("angzarr") -> 16#0237C; ++entity("aogon") -> 16#00105; ++entity("aopf") -> 16#1D552; ++entity("ap") -> 16#02248; ++entity("apE") -> 16#02A70; ++entity("apacir") -> 16#02A6F; ++entity("ape") -> 16#0224A; ++entity("apid") -> 16#0224B; ++entity("apos") -> 16#00027; ++entity("approx") -> 16#02248; ++entity("approxeq") -> 16#0224A; ++entity("aring") -> 16#000E5; ++entity("ascr") -> 16#1D4B6; ++entity("ast") -> 16#0002A; ++entity("asymp") -> 16#02248; ++entity("asympeq") -> 16#0224D; ++entity("atilde") -> 16#000E3; ++entity("auml") -> 16#000E4; ++entity("awconint") -> 16#02233; ++entity("awint") -> 16#02A11; ++entity("bNot") -> 16#02AED; ++entity("backcong") -> 16#0224C; ++entity("backepsilon") -> 16#003F6; ++entity("backprime") -> 16#02035; ++entity("backsim") -> 16#0223D; ++entity("backsimeq") -> 16#022CD; ++entity("barvee") -> 16#022BD; ++entity("barwed") -> 16#02305; ++entity("barwedge") -> 16#02305; ++entity("bbrk") -> 16#023B5; ++entity("bbrktbrk") -> 16#023B6; ++entity("bcong") -> 16#0224C; ++entity("bcy") -> 16#00431; ++entity("bdquo") -> 16#0201E; ++entity("becaus") -> 16#02235; ++entity("because") -> 16#02235; ++entity("bemptyv") -> 16#029B0; ++entity("bepsi") -> 16#003F6; ++entity("bernou") -> 16#0212C; ++entity("beta") -> 16#003B2; ++entity("beth") -> 16#02136; ++entity("between") -> 16#0226C; ++entity("bfr") -> 16#1D51F; ++entity("bigcap") -> 16#022C2; ++entity("bigcirc") -> 16#025EF; ++entity("bigcup") -> 16#022C3; ++entity("bigodot") -> 16#02A00; ++entity("bigoplus") -> 16#02A01; ++entity("bigotimes") -> 16#02A02; ++entity("bigsqcup") -> 16#02A06; ++entity("bigstar") -> 16#02605; ++entity("bigtriangledown") -> 16#025BD; ++entity("bigtriangleup") -> 16#025B3; ++entity("biguplus") -> 16#02A04; ++entity("bigvee") -> 16#022C1; ++entity("bigwedge") -> 16#022C0; ++entity("bkarow") -> 16#0290D; ++entity("blacklozenge") -> 16#029EB; ++entity("blacksquare") -> 16#025AA; ++entity("blacktriangle") -> 16#025B4; ++entity("blacktriangledown") -> 16#025BE; ++entity("blacktriangleleft") -> 16#025C2; ++entity("blacktriangleright") -> 16#025B8; ++entity("blank") -> 16#02423; ++entity("blk12") -> 16#02592; ++entity("blk14") -> 16#02591; ++entity("blk34") -> 16#02593; ++entity("block") -> 16#02588; ++entity("bne") -> [16#0003D, 16#020E5]; ++entity("bnequiv") -> [16#02261, 16#020E5]; ++entity("bnot") -> 16#02310; ++entity("bopf") -> 16#1D553; ++entity("bot") -> 16#022A5; ++entity("bottom") -> 16#022A5; ++entity("bowtie") -> 16#022C8; ++entity("boxDL") -> 16#02557; ++entity("boxDR") -> 16#02554; ++entity("boxDl") -> 16#02556; ++entity("boxDr") -> 16#02553; ++entity("boxH") -> 16#02550; ++entity("boxHD") -> 16#02566; ++entity("boxHU") -> 16#02569; ++entity("boxHd") -> 16#02564; ++entity("boxHu") -> 16#02567; ++entity("boxUL") -> 16#0255D; ++entity("boxUR") -> 16#0255A; ++entity("boxUl") -> 16#0255C; ++entity("boxUr") -> 16#02559; ++entity("boxV") -> 16#02551; ++entity("boxVH") -> 16#0256C; ++entity("boxVL") -> 16#02563; ++entity("boxVR") -> 16#02560; ++entity("boxVh") -> 16#0256B; ++entity("boxVl") -> 16#02562; ++entity("boxVr") -> 16#0255F; ++entity("boxbox") -> 16#029C9; ++entity("boxdL") -> 16#02555; ++entity("boxdR") -> 16#02552; ++entity("boxdl") -> 16#02510; ++entity("boxdr") -> 16#0250C; ++entity("boxh") -> 16#02500; ++entity("boxhD") -> 16#02565; ++entity("boxhU") -> 16#02568; ++entity("boxhd") -> 16#0252C; ++entity("boxhu") -> 16#02534; ++entity("boxminus") -> 16#0229F; ++entity("boxplus") -> 16#0229E; ++entity("boxtimes") -> 16#022A0; ++entity("boxuL") -> 16#0255B; ++entity("boxuR") -> 16#02558; ++entity("boxul") -> 16#02518; ++entity("boxur") -> 16#02514; ++entity("boxv") -> 16#02502; ++entity("boxvH") -> 16#0256A; ++entity("boxvL") -> 16#02561; ++entity("boxvR") -> 16#0255E; ++entity("boxvh") -> 16#0253C; ++entity("boxvl") -> 16#02524; ++entity("boxvr") -> 16#0251C; ++entity("bprime") -> 16#02035; ++entity("breve") -> 16#002D8; ++entity("brvbar") -> 16#000A6; ++entity("bscr") -> 16#1D4B7; ++entity("bsemi") -> 16#0204F; ++entity("bsim") -> 16#0223D; ++entity("bsime") -> 16#022CD; ++entity("bsol") -> 16#0005C; ++entity("bsolb") -> 16#029C5; ++entity("bsolhsub") -> 16#027C8; ++entity("bull") -> 16#02022; ++entity("bullet") -> 16#02022; ++entity("bump") -> 16#0224E; ++entity("bumpE") -> 16#02AAE; ++entity("bumpe") -> 16#0224F; ++entity("bumpeq") -> 16#0224F; ++entity("cacute") -> 16#00107; ++entity("cap") -> 16#02229; ++entity("capand") -> 16#02A44; ++entity("capbrcup") -> 16#02A49; ++entity("capcap") -> 16#02A4B; ++entity("capcup") -> 16#02A47; ++entity("capdot") -> 16#02A40; ++entity("caps") -> [16#02229, 16#0FE00]; ++entity("caret") -> 16#02041; ++entity("caron") -> 16#002C7; ++entity("ccaps") -> 16#02A4D; ++entity("ccaron") -> 16#0010D; ++entity("ccedil") -> 16#000E7; ++entity("ccirc") -> 16#00109; ++entity("ccups") -> 16#02A4C; ++entity("ccupssm") -> 16#02A50; ++entity("cdot") -> 16#0010B; ++entity("cedil") -> 16#000B8; ++entity("cemptyv") -> 16#029B2; ++entity("cent") -> 16#000A2; ++entity("centerdot") -> 16#000B7; ++entity("cfr") -> 16#1D520; ++entity("chcy") -> 16#00447; ++entity("check") -> 16#02713; ++entity("checkmark") -> 16#02713; ++entity("chi") -> 16#003C7; ++entity("cir") -> 16#025CB; ++entity("cirE") -> 16#029C3; ++entity("circ") -> 16#002C6; ++entity("circeq") -> 16#02257; ++entity("circlearrowleft") -> 16#021BA; ++entity("circlearrowright") -> 16#021BB; ++entity("circledR") -> 16#000AE; ++entity("circledS") -> 16#024C8; ++entity("circledast") -> 16#0229B; ++entity("circledcirc") -> 16#0229A; ++entity("circleddash") -> 16#0229D; ++entity("cire") -> 16#02257; ++entity("cirfnint") -> 16#02A10; ++entity("cirmid") -> 16#02AEF; ++entity("cirscir") -> 16#029C2; ++entity("clubs") -> 16#02663; ++entity("clubsuit") -> 16#02663; ++entity("colon") -> 16#0003A; ++entity("colone") -> 16#02254; ++entity("coloneq") -> 16#02254; ++entity("comma") -> 16#0002C; ++entity("commat") -> 16#00040; ++entity("comp") -> 16#02201; ++entity("compfn") -> 16#02218; ++entity("complement") -> 16#02201; ++entity("complexes") -> 16#02102; ++entity("cong") -> 16#02245; ++entity("congdot") -> 16#02A6D; ++entity("conint") -> 16#0222E; ++entity("copf") -> 16#1D554; ++entity("coprod") -> 16#02210; ++entity("copy") -> 16#000A9; ++entity("copysr") -> 16#02117; ++entity("crarr") -> 16#021B5; ++entity("cross") -> 16#02717; ++entity("cscr") -> 16#1D4B8; ++entity("csub") -> 16#02ACF; ++entity("csube") -> 16#02AD1; ++entity("csup") -> 16#02AD0; ++entity("csupe") -> 16#02AD2; ++entity("ctdot") -> 16#022EF; ++entity("cudarrl") -> 16#02938; ++entity("cudarrr") -> 16#02935; ++entity("cuepr") -> 16#022DE; ++entity("cuesc") -> 16#022DF; ++entity("cularr") -> 16#021B6; ++entity("cularrp") -> 16#0293D; ++entity("cup") -> 16#0222A; ++entity("cupbrcap") -> 16#02A48; ++entity("cupcap") -> 16#02A46; ++entity("cupcup") -> 16#02A4A; ++entity("cupdot") -> 16#0228D; ++entity("cupor") -> 16#02A45; ++entity("cups") -> [16#0222A, 16#0FE00]; ++entity("curarr") -> 16#021B7; ++entity("curarrm") -> 16#0293C; ++entity("curlyeqprec") -> 16#022DE; ++entity("curlyeqsucc") -> 16#022DF; ++entity("curlyvee") -> 16#022CE; ++entity("curlywedge") -> 16#022CF; ++entity("curren") -> 16#000A4; ++entity("curvearrowleft") -> 16#021B6; ++entity("curvearrowright") -> 16#021B7; ++entity("cuvee") -> 16#022CE; ++entity("cuwed") -> 16#022CF; ++entity("cwconint") -> 16#02232; ++entity("cwint") -> 16#02231; ++entity("cylcty") -> 16#0232D; ++entity("dArr") -> 16#021D3; ++entity("dHar") -> 16#02965; ++entity("dagger") -> 16#02020; ++entity("daleth") -> 16#02138; ++entity("darr") -> 16#02193; ++entity("dash") -> 16#02010; ++entity("dashv") -> 16#022A3; ++entity("dbkarow") -> 16#0290F; ++entity("dblac") -> 16#002DD; ++entity("dcaron") -> 16#0010F; ++entity("dcy") -> 16#00434; ++entity("dd") -> 16#02146; ++entity("ddagger") -> 16#02021; ++entity("ddarr") -> 16#021CA; ++entity("ddotseq") -> 16#02A77; ++entity("deg") -> 16#000B0; ++entity("delta") -> 16#003B4; ++entity("demptyv") -> 16#029B1; ++entity("dfisht") -> 16#0297F; ++entity("dfr") -> 16#1D521; ++entity("dharl") -> 16#021C3; ++entity("dharr") -> 16#021C2; ++entity("diam") -> 16#022C4; ++entity("diamond") -> 16#022C4; ++entity("diamondsuit") -> 16#02666; ++entity("diams") -> 16#02666; ++entity("die") -> 16#000A8; ++entity("digamma") -> 16#003DD; ++entity("disin") -> 16#022F2; ++entity("div") -> 16#000F7; ++entity("divide") -> 16#000F7; ++entity("divideontimes") -> 16#022C7; ++entity("divonx") -> 16#022C7; ++entity("djcy") -> 16#00452; ++entity("dlcorn") -> 16#0231E; ++entity("dlcrop") -> 16#0230D; ++entity("dollar") -> 16#00024; ++entity("dopf") -> 16#1D555; ++entity("dot") -> 16#002D9; ++entity("doteq") -> 16#02250; ++entity("doteqdot") -> 16#02251; ++entity("dotminus") -> 16#02238; ++entity("dotplus") -> 16#02214; ++entity("dotsquare") -> 16#022A1; ++entity("doublebarwedge") -> 16#02306; ++entity("downarrow") -> 16#02193; ++entity("downdownarrows") -> 16#021CA; ++entity("downharpoonleft") -> 16#021C3; ++entity("downharpoonright") -> 16#021C2; ++entity("drbkarow") -> 16#02910; ++entity("drcorn") -> 16#0231F; ++entity("drcrop") -> 16#0230C; ++entity("dscr") -> 16#1D4B9; ++entity("dscy") -> 16#00455; ++entity("dsol") -> 16#029F6; ++entity("dstrok") -> 16#00111; ++entity("dtdot") -> 16#022F1; ++entity("dtri") -> 16#025BF; ++entity("dtrif") -> 16#025BE; ++entity("duarr") -> 16#021F5; ++entity("duhar") -> 16#0296F; ++entity("dwangle") -> 16#029A6; ++entity("dzcy") -> 16#0045F; ++entity("dzigrarr") -> 16#027FF; ++entity("eDDot") -> 16#02A77; ++entity("eDot") -> 16#02251; ++entity("eacute") -> 16#000E9; ++entity("easter") -> 16#02A6E; ++entity("ecaron") -> 16#0011B; ++entity("ecir") -> 16#02256; ++entity("ecirc") -> 16#000EA; ++entity("ecolon") -> 16#02255; ++entity("ecy") -> 16#0044D; ++entity("edot") -> 16#00117; ++entity("ee") -> 16#02147; ++entity("efDot") -> 16#02252; ++entity("efr") -> 16#1D522; ++entity("eg") -> 16#02A9A; ++entity("egrave") -> 16#000E8; ++entity("egs") -> 16#02A96; ++entity("egsdot") -> 16#02A98; ++entity("el") -> 16#02A99; ++entity("elinters") -> 16#023E7; ++entity("ell") -> 16#02113; ++entity("els") -> 16#02A95; ++entity("elsdot") -> 16#02A97; ++entity("emacr") -> 16#00113; ++entity("empty") -> 16#02205; ++entity("emptyset") -> 16#02205; ++entity("emptyv") -> 16#02205; ++entity("emsp") -> 16#02003; ++entity("emsp13") -> 16#02004; ++entity("emsp14") -> 16#02005; ++entity("eng") -> 16#0014B; ++entity("ensp") -> 16#02002; ++entity("eogon") -> 16#00119; ++entity("eopf") -> 16#1D556; ++entity("epar") -> 16#022D5; ++entity("eparsl") -> 16#029E3; ++entity("eplus") -> 16#02A71; ++entity("epsi") -> 16#003B5; ++entity("epsilon") -> 16#003B5; ++entity("epsiv") -> 16#003F5; ++entity("eqcirc") -> 16#02256; ++entity("eqcolon") -> 16#02255; ++entity("eqsim") -> 16#02242; ++entity("eqslantgtr") -> 16#02A96; ++entity("eqslantless") -> 16#02A95; ++entity("equals") -> 16#0003D; ++entity("equest") -> 16#0225F; ++entity("equiv") -> 16#02261; ++entity("equivDD") -> 16#02A78; ++entity("eqvparsl") -> 16#029E5; ++entity("erDot") -> 16#02253; ++entity("erarr") -> 16#02971; ++entity("escr") -> 16#0212F; ++entity("esdot") -> 16#02250; ++entity("esim") -> 16#02242; ++entity("eta") -> 16#003B7; ++entity("eth") -> 16#000F0; ++entity("euml") -> 16#000EB; ++entity("euro") -> 16#020AC; ++entity("excl") -> 16#00021; ++entity("exist") -> 16#02203; ++entity("expectation") -> 16#02130; ++entity("exponentiale") -> 16#02147; ++entity("fallingdotseq") -> 16#02252; ++entity("fcy") -> 16#00444; ++entity("female") -> 16#02640; ++entity("ffilig") -> 16#0FB03; ++entity("fflig") -> 16#0FB00; ++entity("ffllig") -> 16#0FB04; ++entity("ffr") -> 16#1D523; ++entity("filig") -> 16#0FB01; ++entity("fjlig") -> [16#00066, 16#0006A]; ++entity("flat") -> 16#0266D; ++entity("fllig") -> 16#0FB02; ++entity("fltns") -> 16#025B1; ++entity("fnof") -> 16#00192; ++entity("fopf") -> 16#1D557; ++entity("forall") -> 16#02200; ++entity("fork") -> 16#022D4; ++entity("forkv") -> 16#02AD9; ++entity("fpartint") -> 16#02A0D; ++entity("frac12") -> 16#000BD; ++entity("frac13") -> 16#02153; ++entity("frac14") -> 16#000BC; ++entity("frac15") -> 16#02155; ++entity("frac16") -> 16#02159; ++entity("frac18") -> 16#0215B; ++entity("frac23") -> 16#02154; ++entity("frac25") -> 16#02156; ++entity("frac34") -> 16#000BE; ++entity("frac35") -> 16#02157; ++entity("frac38") -> 16#0215C; ++entity("frac45") -> 16#02158; ++entity("frac56") -> 16#0215A; ++entity("frac58") -> 16#0215D; ++entity("frac78") -> 16#0215E; ++entity("frasl") -> 16#02044; ++entity("frown") -> 16#02322; ++entity("fscr") -> 16#1D4BB; ++entity("gE") -> 16#02267; ++entity("gEl") -> 16#02A8C; ++entity("gacute") -> 16#001F5; ++entity("gamma") -> 16#003B3; ++entity("gammad") -> 16#003DD; ++entity("gap") -> 16#02A86; ++entity("gbreve") -> 16#0011F; ++entity("gcirc") -> 16#0011D; ++entity("gcy") -> 16#00433; ++entity("gdot") -> 16#00121; ++entity("ge") -> 16#02265; ++entity("gel") -> 16#022DB; ++entity("geq") -> 16#02265; ++entity("geqq") -> 16#02267; ++entity("geqslant") -> 16#02A7E; ++entity("ges") -> 16#02A7E; ++entity("gescc") -> 16#02AA9; ++entity("gesdot") -> 16#02A80; ++entity("gesdoto") -> 16#02A82; ++entity("gesdotol") -> 16#02A84; ++entity("gesl") -> [16#022DB, 16#0FE00]; ++entity("gesles") -> 16#02A94; ++entity("gfr") -> 16#1D524; ++entity("gg") -> 16#0226B; ++entity("ggg") -> 16#022D9; ++entity("gimel") -> 16#02137; ++entity("gjcy") -> 16#00453; ++entity("gl") -> 16#02277; ++entity("glE") -> 16#02A92; ++entity("gla") -> 16#02AA5; ++entity("glj") -> 16#02AA4; ++entity("gnE") -> 16#02269; ++entity("gnap") -> 16#02A8A; ++entity("gnapprox") -> 16#02A8A; ++entity("gne") -> 16#02A88; ++entity("gneq") -> 16#02A88; ++entity("gneqq") -> 16#02269; ++entity("gnsim") -> 16#022E7; ++entity("gopf") -> 16#1D558; ++entity("grave") -> 16#00060; ++entity("gscr") -> 16#0210A; ++entity("gsim") -> 16#02273; ++entity("gsime") -> 16#02A8E; ++entity("gsiml") -> 16#02A90; ++entity("gt") -> 16#0003E; ++entity("gtcc") -> 16#02AA7; ++entity("gtcir") -> 16#02A7A; ++entity("gtdot") -> 16#022D7; ++entity("gtlPar") -> 16#02995; ++entity("gtquest") -> 16#02A7C; ++entity("gtrapprox") -> 16#02A86; ++entity("gtrarr") -> 16#02978; ++entity("gtrdot") -> 16#022D7; ++entity("gtreqless") -> 16#022DB; ++entity("gtreqqless") -> 16#02A8C; ++entity("gtrless") -> 16#02277; ++entity("gtrsim") -> 16#02273; ++entity("gvertneqq") -> [16#02269, 16#0FE00]; ++entity("gvnE") -> [16#02269, 16#0FE00]; ++entity("hArr") -> 16#021D4; ++entity("hairsp") -> 16#0200A; ++entity("half") -> 16#000BD; ++entity("hamilt") -> 16#0210B; ++entity("hardcy") -> 16#0044A; ++entity("harr") -> 16#02194; ++entity("harrcir") -> 16#02948; ++entity("harrw") -> 16#021AD; ++entity("hbar") -> 16#0210F; ++entity("hcirc") -> 16#00125; ++entity("hearts") -> 16#02665; ++entity("heartsuit") -> 16#02665; ++entity("hellip") -> 16#02026; ++entity("hercon") -> 16#022B9; ++entity("hfr") -> 16#1D525; ++entity("hksearow") -> 16#02925; ++entity("hkswarow") -> 16#02926; ++entity("hoarr") -> 16#021FF; ++entity("homtht") -> 16#0223B; ++entity("hookleftarrow") -> 16#021A9; ++entity("hookrightarrow") -> 16#021AA; ++entity("hopf") -> 16#1D559; ++entity("horbar") -> 16#02015; ++entity("hscr") -> 16#1D4BD; ++entity("hslash") -> 16#0210F; ++entity("hstrok") -> 16#00127; ++entity("hybull") -> 16#02043; ++entity("hyphen") -> 16#02010; ++entity("iacute") -> 16#000ED; ++entity("ic") -> 16#02063; ++entity("icirc") -> 16#000EE; ++entity("icy") -> 16#00438; ++entity("iecy") -> 16#00435; ++entity("iexcl") -> 16#000A1; ++entity("iff") -> 16#021D4; ++entity("ifr") -> 16#1D526; ++entity("igrave") -> 16#000EC; ++entity("ii") -> 16#02148; ++entity("iiiint") -> 16#02A0C; ++entity("iiint") -> 16#0222D; ++entity("iinfin") -> 16#029DC; ++entity("iiota") -> 16#02129; ++entity("ijlig") -> 16#00133; ++entity("imacr") -> 16#0012B; ++entity("image") -> 16#02111; ++entity("imagline") -> 16#02110; ++entity("imagpart") -> 16#02111; ++entity("imath") -> 16#00131; ++entity("imof") -> 16#022B7; ++entity("imped") -> 16#001B5; ++entity("in") -> 16#02208; ++entity("incare") -> 16#02105; ++entity("infin") -> 16#0221E; ++entity("infintie") -> 16#029DD; ++entity("inodot") -> 16#00131; ++entity("int") -> 16#0222B; ++entity("intcal") -> 16#022BA; ++entity("integers") -> 16#02124; ++entity("intercal") -> 16#022BA; ++entity("intlarhk") -> 16#02A17; ++entity("intprod") -> 16#02A3C; ++entity("iocy") -> 16#00451; ++entity("iogon") -> 16#0012F; ++entity("iopf") -> 16#1D55A; ++entity("iota") -> 16#003B9; ++entity("iprod") -> 16#02A3C; ++entity("iquest") -> 16#000BF; ++entity("iscr") -> 16#1D4BE; ++entity("isin") -> 16#02208; ++entity("isinE") -> 16#022F9; ++entity("isindot") -> 16#022F5; ++entity("isins") -> 16#022F4; ++entity("isinsv") -> 16#022F3; ++entity("isinv") -> 16#02208; ++entity("it") -> 16#02062; ++entity("itilde") -> 16#00129; ++entity("iukcy") -> 16#00456; ++entity("iuml") -> 16#000EF; ++entity("jcirc") -> 16#00135; ++entity("jcy") -> 16#00439; ++entity("jfr") -> 16#1D527; ++entity("jmath") -> 16#00237; ++entity("jopf") -> 16#1D55B; ++entity("jscr") -> 16#1D4BF; ++entity("jsercy") -> 16#00458; ++entity("jukcy") -> 16#00454; ++entity("kappa") -> 16#003BA; ++entity("kappav") -> 16#003F0; ++entity("kcedil") -> 16#00137; ++entity("kcy") -> 16#0043A; ++entity("kfr") -> 16#1D528; ++entity("kgreen") -> 16#00138; ++entity("khcy") -> 16#00445; ++entity("kjcy") -> 16#0045C; ++entity("kopf") -> 16#1D55C; ++entity("kscr") -> 16#1D4C0; ++entity("lAarr") -> 16#021DA; ++entity("lArr") -> 16#021D0; ++entity("lAtail") -> 16#0291B; ++entity("lBarr") -> 16#0290E; ++entity("lE") -> 16#02266; ++entity("lEg") -> 16#02A8B; ++entity("lHar") -> 16#02962; ++entity("lacute") -> 16#0013A; ++entity("laemptyv") -> 16#029B4; ++entity("lagran") -> 16#02112; ++entity("lambda") -> 16#003BB; ++entity("lang") -> 16#027E8; ++entity("langd") -> 16#02991; ++entity("langle") -> 16#027E8; ++entity("lap") -> 16#02A85; ++entity("laquo") -> 16#000AB; ++entity("larr") -> 16#02190; ++entity("larrb") -> 16#021E4; ++entity("larrbfs") -> 16#0291F; ++entity("larrfs") -> 16#0291D; ++entity("larrhk") -> 16#021A9; ++entity("larrlp") -> 16#021AB; ++entity("larrpl") -> 16#02939; ++entity("larrsim") -> 16#02973; ++entity("larrtl") -> 16#021A2; ++entity("lat") -> 16#02AAB; ++entity("latail") -> 16#02919; ++entity("late") -> 16#02AAD; ++entity("lates") -> [16#02AAD, 16#0FE00]; ++entity("lbarr") -> 16#0290C; ++entity("lbbrk") -> 16#02772; ++entity("lbrace") -> 16#0007B; ++entity("lbrack") -> 16#0005B; ++entity("lbrke") -> 16#0298B; ++entity("lbrksld") -> 16#0298F; ++entity("lbrkslu") -> 16#0298D; ++entity("lcaron") -> 16#0013E; ++entity("lcedil") -> 16#0013C; ++entity("lceil") -> 16#02308; ++entity("lcub") -> 16#0007B; ++entity("lcy") -> 16#0043B; ++entity("ldca") -> 16#02936; ++entity("ldquo") -> 16#0201C; ++entity("ldquor") -> 16#0201E; ++entity("ldrdhar") -> 16#02967; ++entity("ldrushar") -> 16#0294B; ++entity("ldsh") -> 16#021B2; ++entity("le") -> 16#02264; ++entity("leftarrow") -> 16#02190; ++entity("leftarrowtail") -> 16#021A2; ++entity("leftharpoondown") -> 16#021BD; ++entity("leftharpoonup") -> 16#021BC; ++entity("leftleftarrows") -> 16#021C7; ++entity("leftrightarrow") -> 16#02194; ++entity("leftrightarrows") -> 16#021C6; ++entity("leftrightharpoons") -> 16#021CB; ++entity("leftrightsquigarrow") -> 16#021AD; ++entity("leftthreetimes") -> 16#022CB; ++entity("leg") -> 16#022DA; ++entity("leq") -> 16#02264; ++entity("leqq") -> 16#02266; ++entity("leqslant") -> 16#02A7D; ++entity("les") -> 16#02A7D; ++entity("lescc") -> 16#02AA8; ++entity("lesdot") -> 16#02A7F; ++entity("lesdoto") -> 16#02A81; ++entity("lesdotor") -> 16#02A83; ++entity("lesg") -> [16#022DA, 16#0FE00]; ++entity("lesges") -> 16#02A93; ++entity("lessapprox") -> 16#02A85; ++entity("lessdot") -> 16#022D6; ++entity("lesseqgtr") -> 16#022DA; ++entity("lesseqqgtr") -> 16#02A8B; ++entity("lessgtr") -> 16#02276; ++entity("lesssim") -> 16#02272; ++entity("lfisht") -> 16#0297C; ++entity("lfloor") -> 16#0230A; ++entity("lfr") -> 16#1D529; ++entity("lg") -> 16#02276; ++entity("lgE") -> 16#02A91; ++entity("lhard") -> 16#021BD; ++entity("lharu") -> 16#021BC; ++entity("lharul") -> 16#0296A; ++entity("lhblk") -> 16#02584; ++entity("ljcy") -> 16#00459; ++entity("ll") -> 16#0226A; ++entity("llarr") -> 16#021C7; ++entity("llcorner") -> 16#0231E; ++entity("llhard") -> 16#0296B; ++entity("lltri") -> 16#025FA; ++entity("lmidot") -> 16#00140; ++entity("lmoust") -> 16#023B0; ++entity("lmoustache") -> 16#023B0; ++entity("lnE") -> 16#02268; ++entity("lnap") -> 16#02A89; ++entity("lnapprox") -> 16#02A89; ++entity("lne") -> 16#02A87; ++entity("lneq") -> 16#02A87; ++entity("lneqq") -> 16#02268; ++entity("lnsim") -> 16#022E6; ++entity("loang") -> 16#027EC; ++entity("loarr") -> 16#021FD; ++entity("lobrk") -> 16#027E6; ++entity("longleftarrow") -> 16#027F5; ++entity("longleftrightarrow") -> 16#027F7; ++entity("longmapsto") -> 16#027FC; ++entity("longrightarrow") -> 16#027F6; ++entity("looparrowleft") -> 16#021AB; ++entity("looparrowright") -> 16#021AC; ++entity("lopar") -> 16#02985; ++entity("lopf") -> 16#1D55D; ++entity("loplus") -> 16#02A2D; ++entity("lotimes") -> 16#02A34; ++entity("lowast") -> 16#02217; ++entity("lowbar") -> 16#0005F; ++entity("loz") -> 16#025CA; ++entity("lozenge") -> 16#025CA; ++entity("lozf") -> 16#029EB; ++entity("lpar") -> 16#00028; ++entity("lparlt") -> 16#02993; ++entity("lrarr") -> 16#021C6; ++entity("lrcorner") -> 16#0231F; ++entity("lrhar") -> 16#021CB; ++entity("lrhard") -> 16#0296D; ++entity("lrm") -> 16#0200E; ++entity("lrtri") -> 16#022BF; ++entity("lsaquo") -> 16#02039; ++entity("lscr") -> 16#1D4C1; ++entity("lsh") -> 16#021B0; ++entity("lsim") -> 16#02272; ++entity("lsime") -> 16#02A8D; ++entity("lsimg") -> 16#02A8F; ++entity("lsqb") -> 16#0005B; ++entity("lsquo") -> 16#02018; ++entity("lsquor") -> 16#0201A; ++entity("lstrok") -> 16#00142; ++entity("lt") -> 16#0003C; ++entity("ltcc") -> 16#02AA6; ++entity("ltcir") -> 16#02A79; ++entity("ltdot") -> 16#022D6; ++entity("lthree") -> 16#022CB; ++entity("ltimes") -> 16#022C9; ++entity("ltlarr") -> 16#02976; ++entity("ltquest") -> 16#02A7B; ++entity("ltrPar") -> 16#02996; ++entity("ltri") -> 16#025C3; ++entity("ltrie") -> 16#022B4; ++entity("ltrif") -> 16#025C2; ++entity("lurdshar") -> 16#0294A; ++entity("luruhar") -> 16#02966; ++entity("lvertneqq") -> [16#02268, 16#0FE00]; ++entity("lvnE") -> [16#02268, 16#0FE00]; ++entity("mDDot") -> 16#0223A; ++entity("macr") -> 16#000AF; ++entity("male") -> 16#02642; ++entity("malt") -> 16#02720; ++entity("maltese") -> 16#02720; ++entity("map") -> 16#021A6; ++entity("mapsto") -> 16#021A6; ++entity("mapstodown") -> 16#021A7; ++entity("mapstoleft") -> 16#021A4; ++entity("mapstoup") -> 16#021A5; ++entity("marker") -> 16#025AE; ++entity("mcomma") -> 16#02A29; ++entity("mcy") -> 16#0043C; ++entity("mdash") -> 16#02014; ++entity("measuredangle") -> 16#02221; ++entity("mfr") -> 16#1D52A; ++entity("mho") -> 16#02127; ++entity("micro") -> 16#000B5; ++entity("mid") -> 16#02223; ++entity("midast") -> 16#0002A; ++entity("midcir") -> 16#02AF0; ++entity("middot") -> 16#000B7; ++entity("minus") -> 16#02212; ++entity("minusb") -> 16#0229F; ++entity("minusd") -> 16#02238; ++entity("minusdu") -> 16#02A2A; ++entity("mlcp") -> 16#02ADB; ++entity("mldr") -> 16#02026; ++entity("mnplus") -> 16#02213; ++entity("models") -> 16#022A7; ++entity("mopf") -> 16#1D55E; ++entity("mp") -> 16#02213; ++entity("mscr") -> 16#1D4C2; ++entity("mstpos") -> 16#0223E; ++entity("mu") -> 16#003BC; ++entity("multimap") -> 16#022B8; ++entity("mumap") -> 16#022B8; ++entity("nGg") -> [16#022D9, 16#00338]; ++entity("nGt") -> [16#0226B, 16#020D2]; ++entity("nGtv") -> [16#0226B, 16#00338]; ++entity("nLeftarrow") -> 16#021CD; ++entity("nLeftrightarrow") -> 16#021CE; ++entity("nLl") -> [16#022D8, 16#00338]; ++entity("nLt") -> [16#0226A, 16#020D2]; ++entity("nLtv") -> [16#0226A, 16#00338]; ++entity("nRightarrow") -> 16#021CF; ++entity("nVDash") -> 16#022AF; ++entity("nVdash") -> 16#022AE; ++entity("nabla") -> 16#02207; ++entity("nacute") -> 16#00144; ++entity("nang") -> [16#02220, 16#020D2]; ++entity("nap") -> 16#02249; ++entity("napE") -> [16#02A70, 16#00338]; ++entity("napid") -> [16#0224B, 16#00338]; ++entity("napos") -> 16#00149; ++entity("napprox") -> 16#02249; ++entity("natur") -> 16#0266E; ++entity("natural") -> 16#0266E; ++entity("naturals") -> 16#02115; ++entity("nbsp") -> 16#000A0; ++entity("nbump") -> [16#0224E, 16#00338]; ++entity("nbumpe") -> [16#0224F, 16#00338]; ++entity("ncap") -> 16#02A43; ++entity("ncaron") -> 16#00148; ++entity("ncedil") -> 16#00146; ++entity("ncong") -> 16#02247; ++entity("ncongdot") -> [16#02A6D, 16#00338]; ++entity("ncup") -> 16#02A42; ++entity("ncy") -> 16#0043D; ++entity("ndash") -> 16#02013; ++entity("ne") -> 16#02260; ++entity("neArr") -> 16#021D7; ++entity("nearhk") -> 16#02924; ++entity("nearr") -> 16#02197; ++entity("nearrow") -> 16#02197; ++entity("nedot") -> [16#02250, 16#00338]; ++entity("nequiv") -> 16#02262; ++entity("nesear") -> 16#02928; ++entity("nesim") -> [16#02242, 16#00338]; ++entity("nexist") -> 16#02204; ++entity("nexists") -> 16#02204; ++entity("nfr") -> 16#1D52B; ++entity("ngE") -> [16#02267, 16#00338]; ++entity("nge") -> 16#02271; ++entity("ngeq") -> 16#02271; ++entity("ngeqq") -> [16#02267, 16#00338]; ++entity("ngeqslant") -> [16#02A7E, 16#00338]; ++entity("nges") -> [16#02A7E, 16#00338]; ++entity("ngsim") -> 16#02275; ++entity("ngt") -> 16#0226F; ++entity("ngtr") -> 16#0226F; ++entity("nhArr") -> 16#021CE; ++entity("nharr") -> 16#021AE; ++entity("nhpar") -> 16#02AF2; ++entity("ni") -> 16#0220B; ++entity("nis") -> 16#022FC; ++entity("nisd") -> 16#022FA; ++entity("niv") -> 16#0220B; ++entity("njcy") -> 16#0045A; ++entity("nlArr") -> 16#021CD; ++entity("nlE") -> [16#02266, 16#00338]; ++entity("nlarr") -> 16#0219A; ++entity("nldr") -> 16#02025; ++entity("nle") -> 16#02270; ++entity("nleftarrow") -> 16#0219A; ++entity("nleftrightarrow") -> 16#021AE; ++entity("nleq") -> 16#02270; ++entity("nleqq") -> [16#02266, 16#00338]; ++entity("nleqslant") -> [16#02A7D, 16#00338]; ++entity("nles") -> [16#02A7D, 16#00338]; ++entity("nless") -> 16#0226E; ++entity("nlsim") -> 16#02274; ++entity("nlt") -> 16#0226E; ++entity("nltri") -> 16#022EA; ++entity("nltrie") -> 16#022EC; ++entity("nmid") -> 16#02224; ++entity("nopf") -> 16#1D55F; ++entity("not") -> 16#000AC; ++entity("notin") -> 16#02209; ++entity("notinE") -> [16#022F9, 16#00338]; ++entity("notindot") -> [16#022F5, 16#00338]; ++entity("notinva") -> 16#02209; ++entity("notinvb") -> 16#022F7; ++entity("notinvc") -> 16#022F6; ++entity("notni") -> 16#0220C; ++entity("notniva") -> 16#0220C; ++entity("notnivb") -> 16#022FE; ++entity("notnivc") -> 16#022FD; ++entity("npar") -> 16#02226; ++entity("nparallel") -> 16#02226; ++entity("nparsl") -> [16#02AFD, 16#020E5]; ++entity("npart") -> [16#02202, 16#00338]; ++entity("npolint") -> 16#02A14; ++entity("npr") -> 16#02280; ++entity("nprcue") -> 16#022E0; ++entity("npre") -> [16#02AAF, 16#00338]; ++entity("nprec") -> 16#02280; ++entity("npreceq") -> [16#02AAF, 16#00338]; ++entity("nrArr") -> 16#021CF; ++entity("nrarr") -> 16#0219B; ++entity("nrarrc") -> [16#02933, 16#00338]; ++entity("nrarrw") -> [16#0219D, 16#00338]; ++entity("nrightarrow") -> 16#0219B; ++entity("nrtri") -> 16#022EB; ++entity("nrtrie") -> 16#022ED; ++entity("nsc") -> 16#02281; ++entity("nsccue") -> 16#022E1; ++entity("nsce") -> [16#02AB0, 16#00338]; ++entity("nscr") -> 16#1D4C3; ++entity("nshortmid") -> 16#02224; ++entity("nshortparallel") -> 16#02226; ++entity("nsim") -> 16#02241; ++entity("nsime") -> 16#02244; ++entity("nsimeq") -> 16#02244; ++entity("nsmid") -> 16#02224; ++entity("nspar") -> 16#02226; ++entity("nsqsube") -> 16#022E2; ++entity("nsqsupe") -> 16#022E3; ++entity("nsub") -> 16#02284; ++entity("nsubE") -> [16#02AC5, 16#00338]; ++entity("nsube") -> 16#02288; ++entity("nsubset") -> [16#02282, 16#020D2]; ++entity("nsubseteq") -> 16#02288; ++entity("nsubseteqq") -> [16#02AC5, 16#00338]; ++entity("nsucc") -> 16#02281; ++entity("nsucceq") -> [16#02AB0, 16#00338]; ++entity("nsup") -> 16#02285; ++entity("nsupE") -> [16#02AC6, 16#00338]; ++entity("nsupe") -> 16#02289; ++entity("nsupset") -> [16#02283, 16#020D2]; ++entity("nsupseteq") -> 16#02289; ++entity("nsupseteqq") -> [16#02AC6, 16#00338]; ++entity("ntgl") -> 16#02279; ++entity("ntilde") -> 16#000F1; ++entity("ntlg") -> 16#02278; ++entity("ntriangleleft") -> 16#022EA; ++entity("ntrianglelefteq") -> 16#022EC; ++entity("ntriangleright") -> 16#022EB; ++entity("ntrianglerighteq") -> 16#022ED; ++entity("nu") -> 16#003BD; ++entity("num") -> 16#00023; ++entity("numero") -> 16#02116; ++entity("numsp") -> 16#02007; ++entity("nvDash") -> 16#022AD; ++entity("nvHarr") -> 16#02904; ++entity("nvap") -> [16#0224D, 16#020D2]; ++entity("nvdash") -> 16#022AC; ++entity("nvge") -> [16#02265, 16#020D2]; ++entity("nvgt") -> [16#0003E, 16#020D2]; ++entity("nvinfin") -> 16#029DE; ++entity("nvlArr") -> 16#02902; ++entity("nvle") -> [16#02264, 16#020D2]; ++entity("nvlt") -> [16#0003C, 16#020D2]; ++entity("nvltrie") -> [16#022B4, 16#020D2]; ++entity("nvrArr") -> 16#02903; ++entity("nvrtrie") -> [16#022B5, 16#020D2]; ++entity("nvsim") -> [16#0223C, 16#020D2]; ++entity("nwArr") -> 16#021D6; ++entity("nwarhk") -> 16#02923; ++entity("nwarr") -> 16#02196; ++entity("nwarrow") -> 16#02196; ++entity("nwnear") -> 16#02927; ++entity("oS") -> 16#024C8; ++entity("oacute") -> 16#000F3; ++entity("oast") -> 16#0229B; ++entity("ocir") -> 16#0229A; ++entity("ocirc") -> 16#000F4; ++entity("ocy") -> 16#0043E; ++entity("odash") -> 16#0229D; ++entity("odblac") -> 16#00151; ++entity("odiv") -> 16#02A38; ++entity("odot") -> 16#02299; ++entity("odsold") -> 16#029BC; ++entity("oelig") -> 16#00153; ++entity("ofcir") -> 16#029BF; ++entity("ofr") -> 16#1D52C; ++entity("ogon") -> 16#002DB; ++entity("ograve") -> 16#000F2; ++entity("ogt") -> 16#029C1; ++entity("ohbar") -> 16#029B5; ++entity("ohm") -> 16#003A9; ++entity("oint") -> 16#0222E; ++entity("olarr") -> 16#021BA; ++entity("olcir") -> 16#029BE; ++entity("olcross") -> 16#029BB; ++entity("oline") -> 16#0203E; ++entity("olt") -> 16#029C0; ++entity("omacr") -> 16#0014D; ++entity("omega") -> 16#003C9; ++entity("omicron") -> 16#003BF; ++entity("omid") -> 16#029B6; ++entity("ominus") -> 16#02296; ++entity("oopf") -> 16#1D560; ++entity("opar") -> 16#029B7; ++entity("operp") -> 16#029B9; ++entity("oplus") -> 16#02295; ++entity("or") -> 16#02228; ++entity("orarr") -> 16#021BB; ++entity("ord") -> 16#02A5D; ++entity("order") -> 16#02134; ++entity("orderof") -> 16#02134; ++entity("ordf") -> 16#000AA; ++entity("ordm") -> 16#000BA; ++entity("origof") -> 16#022B6; ++entity("oror") -> 16#02A56; ++entity("orslope") -> 16#02A57; ++entity("orv") -> 16#02A5B; ++entity("oscr") -> 16#02134; ++entity("oslash") -> 16#000F8; ++entity("osol") -> 16#02298; ++entity("otilde") -> 16#000F5; ++entity("otimes") -> 16#02297; ++entity("otimesas") -> 16#02A36; ++entity("ouml") -> 16#000F6; ++entity("ovbar") -> 16#0233D; ++entity("par") -> 16#02225; ++entity("para") -> 16#000B6; ++entity("parallel") -> 16#02225; ++entity("parsim") -> 16#02AF3; ++entity("parsl") -> 16#02AFD; ++entity("part") -> 16#02202; ++entity("pcy") -> 16#0043F; ++entity("percnt") -> 16#00025; ++entity("period") -> 16#0002E; ++entity("permil") -> 16#02030; ++entity("perp") -> 16#022A5; ++entity("pertenk") -> 16#02031; ++entity("pfr") -> 16#1D52D; ++entity("phi") -> 16#003C6; ++entity("phiv") -> 16#003D5; ++entity("phmmat") -> 16#02133; ++entity("phone") -> 16#0260E; ++entity("pi") -> 16#003C0; ++entity("pitchfork") -> 16#022D4; ++entity("piv") -> 16#003D6; ++entity("planck") -> 16#0210F; ++entity("planckh") -> 16#0210E; ++entity("plankv") -> 16#0210F; ++entity("plus") -> 16#0002B; ++entity("plusacir") -> 16#02A23; ++entity("plusb") -> 16#0229E; ++entity("pluscir") -> 16#02A22; ++entity("plusdo") -> 16#02214; ++entity("plusdu") -> 16#02A25; ++entity("pluse") -> 16#02A72; ++entity("plusmn") -> 16#000B1; ++entity("plussim") -> 16#02A26; ++entity("plustwo") -> 16#02A27; ++entity("pm") -> 16#000B1; ++entity("pointint") -> 16#02A15; ++entity("popf") -> 16#1D561; ++entity("pound") -> 16#000A3; ++entity("pr") -> 16#0227A; ++entity("prE") -> 16#02AB3; ++entity("prap") -> 16#02AB7; ++entity("prcue") -> 16#0227C; ++entity("pre") -> 16#02AAF; ++entity("prec") -> 16#0227A; ++entity("precapprox") -> 16#02AB7; ++entity("preccurlyeq") -> 16#0227C; ++entity("preceq") -> 16#02AAF; ++entity("precnapprox") -> 16#02AB9; ++entity("precneqq") -> 16#02AB5; ++entity("precnsim") -> 16#022E8; ++entity("precsim") -> 16#0227E; ++entity("prime") -> 16#02032; ++entity("primes") -> 16#02119; ++entity("prnE") -> 16#02AB5; ++entity("prnap") -> 16#02AB9; ++entity("prnsim") -> 16#022E8; ++entity("prod") -> 16#0220F; ++entity("profalar") -> 16#0232E; ++entity("profline") -> 16#02312; ++entity("profsurf") -> 16#02313; ++entity("prop") -> 16#0221D; ++entity("propto") -> 16#0221D; ++entity("prsim") -> 16#0227E; ++entity("prurel") -> 16#022B0; ++entity("pscr") -> 16#1D4C5; ++entity("psi") -> 16#003C8; ++entity("puncsp") -> 16#02008; ++entity("qfr") -> 16#1D52E; ++entity("qint") -> 16#02A0C; ++entity("qopf") -> 16#1D562; ++entity("qprime") -> 16#02057; ++entity("qscr") -> 16#1D4C6; ++entity("quaternions") -> 16#0210D; ++entity("quatint") -> 16#02A16; ++entity("quest") -> 16#0003F; ++entity("questeq") -> 16#0225F; ++entity("quot") -> 16#00022; ++entity("rAarr") -> 16#021DB; ++entity("rArr") -> 16#021D2; ++entity("rAtail") -> 16#0291C; ++entity("rBarr") -> 16#0290F; ++entity("rHar") -> 16#02964; ++entity("race") -> [16#0223D, 16#00331]; ++entity("racute") -> 16#00155; ++entity("radic") -> 16#0221A; ++entity("raemptyv") -> 16#029B3; ++entity("rang") -> 16#027E9; ++entity("rangd") -> 16#02992; ++entity("range") -> 16#029A5; ++entity("rangle") -> 16#027E9; ++entity("raquo") -> 16#000BB; ++entity("rarr") -> 16#02192; ++entity("rarrap") -> 16#02975; ++entity("rarrb") -> 16#021E5; ++entity("rarrbfs") -> 16#02920; ++entity("rarrc") -> 16#02933; ++entity("rarrfs") -> 16#0291E; ++entity("rarrhk") -> 16#021AA; ++entity("rarrlp") -> 16#021AC; ++entity("rarrpl") -> 16#02945; ++entity("rarrsim") -> 16#02974; ++entity("rarrtl") -> 16#021A3; ++entity("rarrw") -> 16#0219D; ++entity("ratail") -> 16#0291A; ++entity("ratio") -> 16#02236; ++entity("rationals") -> 16#0211A; ++entity("rbarr") -> 16#0290D; ++entity("rbbrk") -> 16#02773; ++entity("rbrace") -> 16#0007D; ++entity("rbrack") -> 16#0005D; ++entity("rbrke") -> 16#0298C; ++entity("rbrksld") -> 16#0298E; ++entity("rbrkslu") -> 16#02990; ++entity("rcaron") -> 16#00159; ++entity("rcedil") -> 16#00157; ++entity("rceil") -> 16#02309; ++entity("rcub") -> 16#0007D; ++entity("rcy") -> 16#00440; ++entity("rdca") -> 16#02937; ++entity("rdldhar") -> 16#02969; ++entity("rdquo") -> 16#0201D; ++entity("rdquor") -> 16#0201D; ++entity("rdsh") -> 16#021B3; ++entity("real") -> 16#0211C; ++entity("realine") -> 16#0211B; ++entity("realpart") -> 16#0211C; ++entity("reals") -> 16#0211D; ++entity("rect") -> 16#025AD; ++entity("reg") -> 16#000AE; ++entity("rfisht") -> 16#0297D; ++entity("rfloor") -> 16#0230B; ++entity("rfr") -> 16#1D52F; ++entity("rhard") -> 16#021C1; ++entity("rharu") -> 16#021C0; ++entity("rharul") -> 16#0296C; ++entity("rho") -> 16#003C1; ++entity("rhov") -> 16#003F1; ++entity("rightarrow") -> 16#02192; ++entity("rightarrowtail") -> 16#021A3; ++entity("rightharpoondown") -> 16#021C1; ++entity("rightharpoonup") -> 16#021C0; ++entity("rightleftarrows") -> 16#021C4; ++entity("rightleftharpoons") -> 16#021CC; ++entity("rightrightarrows") -> 16#021C9; ++entity("rightsquigarrow") -> 16#0219D; ++entity("rightthreetimes") -> 16#022CC; ++entity("ring") -> 16#002DA; ++entity("risingdotseq") -> 16#02253; ++entity("rlarr") -> 16#021C4; ++entity("rlhar") -> 16#021CC; ++entity("rlm") -> 16#0200F; ++entity("rmoust") -> 16#023B1; ++entity("rmoustache") -> 16#023B1; ++entity("rnmid") -> 16#02AEE; ++entity("roang") -> 16#027ED; ++entity("roarr") -> 16#021FE; ++entity("robrk") -> 16#027E7; ++entity("ropar") -> 16#02986; ++entity("ropf") -> 16#1D563; ++entity("roplus") -> 16#02A2E; ++entity("rotimes") -> 16#02A35; ++entity("rpar") -> 16#00029; ++entity("rpargt") -> 16#02994; ++entity("rppolint") -> 16#02A12; ++entity("rrarr") -> 16#021C9; ++entity("rsaquo") -> 16#0203A; ++entity("rscr") -> 16#1D4C7; ++entity("rsh") -> 16#021B1; ++entity("rsqb") -> 16#0005D; ++entity("rsquo") -> 16#02019; ++entity("rsquor") -> 16#02019; ++entity("rthree") -> 16#022CC; ++entity("rtimes") -> 16#022CA; ++entity("rtri") -> 16#025B9; ++entity("rtrie") -> 16#022B5; ++entity("rtrif") -> 16#025B8; ++entity("rtriltri") -> 16#029CE; ++entity("ruluhar") -> 16#02968; ++entity("rx") -> 16#0211E; ++entity("sacute") -> 16#0015B; ++entity("sbquo") -> 16#0201A; ++entity("sc") -> 16#0227B; ++entity("scE") -> 16#02AB4; ++entity("scap") -> 16#02AB8; ++entity("scaron") -> 16#00161; ++entity("sccue") -> 16#0227D; ++entity("sce") -> 16#02AB0; ++entity("scedil") -> 16#0015F; ++entity("scirc") -> 16#0015D; ++entity("scnE") -> 16#02AB6; ++entity("scnap") -> 16#02ABA; ++entity("scnsim") -> 16#022E9; ++entity("scpolint") -> 16#02A13; ++entity("scsim") -> 16#0227F; ++entity("scy") -> 16#00441; ++entity("sdot") -> 16#022C5; ++entity("sdotb") -> 16#022A1; ++entity("sdote") -> 16#02A66; ++entity("seArr") -> 16#021D8; ++entity("searhk") -> 16#02925; ++entity("searr") -> 16#02198; ++entity("searrow") -> 16#02198; ++entity("sect") -> 16#000A7; ++entity("semi") -> 16#0003B; ++entity("seswar") -> 16#02929; ++entity("setminus") -> 16#02216; ++entity("setmn") -> 16#02216; ++entity("sext") -> 16#02736; ++entity("sfr") -> 16#1D530; ++entity("sfrown") -> 16#02322; ++entity("sharp") -> 16#0266F; ++entity("shchcy") -> 16#00449; ++entity("shcy") -> 16#00448; ++entity("shortmid") -> 16#02223; ++entity("shortparallel") -> 16#02225; ++entity("shy") -> 16#000AD; ++entity("sigma") -> 16#003C3; ++entity("sigmaf") -> 16#003C2; ++entity("sigmav") -> 16#003C2; ++entity("sim") -> 16#0223C; ++entity("simdot") -> 16#02A6A; ++entity("sime") -> 16#02243; ++entity("simeq") -> 16#02243; ++entity("simg") -> 16#02A9E; ++entity("simgE") -> 16#02AA0; ++entity("siml") -> 16#02A9D; ++entity("simlE") -> 16#02A9F; ++entity("simne") -> 16#02246; ++entity("simplus") -> 16#02A24; ++entity("simrarr") -> 16#02972; ++entity("slarr") -> 16#02190; ++entity("smallsetminus") -> 16#02216; ++entity("smashp") -> 16#02A33; ++entity("smeparsl") -> 16#029E4; ++entity("smid") -> 16#02223; ++entity("smile") -> 16#02323; ++entity("smt") -> 16#02AAA; ++entity("smte") -> 16#02AAC; ++entity("smtes") -> [16#02AAC, 16#0FE00]; ++entity("softcy") -> 16#0044C; ++entity("sol") -> 16#0002F; ++entity("solb") -> 16#029C4; ++entity("solbar") -> 16#0233F; ++entity("sopf") -> 16#1D564; ++entity("spades") -> 16#02660; ++entity("spadesuit") -> 16#02660; ++entity("spar") -> 16#02225; ++entity("sqcap") -> 16#02293; ++entity("sqcaps") -> [16#02293, 16#0FE00]; ++entity("sqcup") -> 16#02294; ++entity("sqcups") -> [16#02294, 16#0FE00]; ++entity("sqsub") -> 16#0228F; ++entity("sqsube") -> 16#02291; ++entity("sqsubset") -> 16#0228F; ++entity("sqsubseteq") -> 16#02291; ++entity("sqsup") -> 16#02290; ++entity("sqsupe") -> 16#02292; ++entity("sqsupset") -> 16#02290; ++entity("sqsupseteq") -> 16#02292; ++entity("squ") -> 16#025A1; ++entity("square") -> 16#025A1; ++entity("squarf") -> 16#025AA; ++entity("squf") -> 16#025AA; ++entity("srarr") -> 16#02192; ++entity("sscr") -> 16#1D4C8; ++entity("ssetmn") -> 16#02216; ++entity("ssmile") -> 16#02323; ++entity("sstarf") -> 16#022C6; ++entity("star") -> 16#02606; ++entity("starf") -> 16#02605; ++entity("straightepsilon") -> 16#003F5; ++entity("straightphi") -> 16#003D5; ++entity("strns") -> 16#000AF; ++entity("sub") -> 16#02282; ++entity("subE") -> 16#02AC5; ++entity("subdot") -> 16#02ABD; ++entity("sube") -> 16#02286; ++entity("subedot") -> 16#02AC3; ++entity("submult") -> 16#02AC1; ++entity("subnE") -> 16#02ACB; ++entity("subne") -> 16#0228A; ++entity("subplus") -> 16#02ABF; ++entity("subrarr") -> 16#02979; ++entity("subset") -> 16#02282; ++entity("subseteq") -> 16#02286; ++entity("subseteqq") -> 16#02AC5; ++entity("subsetneq") -> 16#0228A; ++entity("subsetneqq") -> 16#02ACB; ++entity("subsim") -> 16#02AC7; ++entity("subsub") -> 16#02AD5; ++entity("subsup") -> 16#02AD3; ++entity("succ") -> 16#0227B; ++entity("succapprox") -> 16#02AB8; ++entity("succcurlyeq") -> 16#0227D; ++entity("succeq") -> 16#02AB0; ++entity("succnapprox") -> 16#02ABA; ++entity("succneqq") -> 16#02AB6; ++entity("succnsim") -> 16#022E9; ++entity("succsim") -> 16#0227F; ++entity("sum") -> 16#02211; ++entity("sung") -> 16#0266A; ++entity("sup") -> 16#02283; ++entity("sup1") -> 16#000B9; ++entity("sup2") -> 16#000B2; ++entity("sup3") -> 16#000B3; ++entity("supE") -> 16#02AC6; ++entity("supdot") -> 16#02ABE; ++entity("supdsub") -> 16#02AD8; ++entity("supe") -> 16#02287; ++entity("supedot") -> 16#02AC4; ++entity("suphsol") -> 16#027C9; ++entity("suphsub") -> 16#02AD7; ++entity("suplarr") -> 16#0297B; ++entity("supmult") -> 16#02AC2; ++entity("supnE") -> 16#02ACC; ++entity("supne") -> 16#0228B; ++entity("supplus") -> 16#02AC0; ++entity("supset") -> 16#02283; ++entity("supseteq") -> 16#02287; ++entity("supseteqq") -> 16#02AC6; ++entity("supsetneq") -> 16#0228B; ++entity("supsetneqq") -> 16#02ACC; ++entity("supsim") -> 16#02AC8; ++entity("supsub") -> 16#02AD4; ++entity("supsup") -> 16#02AD6; ++entity("swArr") -> 16#021D9; ++entity("swarhk") -> 16#02926; ++entity("swarr") -> 16#02199; ++entity("swarrow") -> 16#02199; ++entity("swnwar") -> 16#0292A; ++entity("szlig") -> 16#000DF; ++entity("target") -> 16#02316; ++entity("tau") -> 16#003C4; ++entity("tbrk") -> 16#023B4; ++entity("tcaron") -> 16#00165; ++entity("tcedil") -> 16#00163; ++entity("tcy") -> 16#00442; ++entity("tdot") -> 16#020DB; ++entity("telrec") -> 16#02315; ++entity("tfr") -> 16#1D531; ++entity("there4") -> 16#02234; ++entity("therefore") -> 16#02234; ++entity("theta") -> 16#003B8; ++entity("thetasym") -> 16#003D1; ++entity("thetav") -> 16#003D1; ++entity("thickapprox") -> 16#02248; ++entity("thicksim") -> 16#0223C; ++entity("thinsp") -> 16#02009; ++entity("thkap") -> 16#02248; ++entity("thksim") -> 16#0223C; ++entity("thorn") -> 16#000FE; ++entity("tilde") -> 16#002DC; ++entity("times") -> 16#000D7; ++entity("timesb") -> 16#022A0; ++entity("timesbar") -> 16#02A31; ++entity("timesd") -> 16#02A30; ++entity("tint") -> 16#0222D; ++entity("toea") -> 16#02928; ++entity("top") -> 16#022A4; ++entity("topbot") -> 16#02336; ++entity("topcir") -> 16#02AF1; ++entity("topf") -> 16#1D565; ++entity("topfork") -> 16#02ADA; ++entity("tosa") -> 16#02929; ++entity("tprime") -> 16#02034; ++entity("trade") -> 16#02122; ++entity("triangle") -> 16#025B5; ++entity("triangledown") -> 16#025BF; ++entity("triangleleft") -> 16#025C3; ++entity("trianglelefteq") -> 16#022B4; ++entity("triangleq") -> 16#0225C; ++entity("triangleright") -> 16#025B9; ++entity("trianglerighteq") -> 16#022B5; ++entity("tridot") -> 16#025EC; ++entity("trie") -> 16#0225C; ++entity("triminus") -> 16#02A3A; ++entity("triplus") -> 16#02A39; ++entity("trisb") -> 16#029CD; ++entity("tritime") -> 16#02A3B; ++entity("trpezium") -> 16#023E2; ++entity("tscr") -> 16#1D4C9; ++entity("tscy") -> 16#00446; ++entity("tshcy") -> 16#0045B; ++entity("tstrok") -> 16#00167; ++entity("twixt") -> 16#0226C; ++entity("twoheadleftarrow") -> 16#0219E; ++entity("twoheadrightarrow") -> 16#021A0; ++entity("uArr") -> 16#021D1; ++entity("uHar") -> 16#02963; ++entity("uacute") -> 16#000FA; ++entity("uarr") -> 16#02191; ++entity("ubrcy") -> 16#0045E; ++entity("ubreve") -> 16#0016D; ++entity("ucirc") -> 16#000FB; ++entity("ucy") -> 16#00443; ++entity("udarr") -> 16#021C5; ++entity("udblac") -> 16#00171; ++entity("udhar") -> 16#0296E; ++entity("ufisht") -> 16#0297E; ++entity("ufr") -> 16#1D532; ++entity("ugrave") -> 16#000F9; ++entity("uharl") -> 16#021BF; ++entity("uharr") -> 16#021BE; ++entity("uhblk") -> 16#02580; ++entity("ulcorn") -> 16#0231C; ++entity("ulcorner") -> 16#0231C; ++entity("ulcrop") -> 16#0230F; ++entity("ultri") -> 16#025F8; ++entity("umacr") -> 16#0016B; ++entity("uml") -> 16#000A8; ++entity("uogon") -> 16#00173; ++entity("uopf") -> 16#1D566; ++entity("uparrow") -> 16#02191; ++entity("updownarrow") -> 16#02195; ++entity("upharpoonleft") -> 16#021BF; ++entity("upharpoonright") -> 16#021BE; ++entity("uplus") -> 16#0228E; ++entity("upsi") -> 16#003C5; ++entity("upsih") -> 16#003D2; ++entity("upsilon") -> 16#003C5; ++entity("upuparrows") -> 16#021C8; ++entity("urcorn") -> 16#0231D; ++entity("urcorner") -> 16#0231D; ++entity("urcrop") -> 16#0230E; ++entity("uring") -> 16#0016F; ++entity("urtri") -> 16#025F9; ++entity("uscr") -> 16#1D4CA; ++entity("utdot") -> 16#022F0; ++entity("utilde") -> 16#00169; ++entity("utri") -> 16#025B5; ++entity("utrif") -> 16#025B4; ++entity("uuarr") -> 16#021C8; ++entity("uuml") -> 16#000FC; ++entity("uwangle") -> 16#029A7; ++entity("vArr") -> 16#021D5; ++entity("vBar") -> 16#02AE8; ++entity("vBarv") -> 16#02AE9; ++entity("vDash") -> 16#022A8; ++entity("vangrt") -> 16#0299C; ++entity("varepsilon") -> 16#003F5; ++entity("varkappa") -> 16#003F0; ++entity("varnothing") -> 16#02205; ++entity("varphi") -> 16#003D5; ++entity("varpi") -> 16#003D6; ++entity("varpropto") -> 16#0221D; ++entity("varr") -> 16#02195; ++entity("varrho") -> 16#003F1; ++entity("varsigma") -> 16#003C2; ++entity("varsubsetneq") -> [16#0228A, 16#0FE00]; ++entity("varsubsetneqq") -> [16#02ACB, 16#0FE00]; ++entity("varsupsetneq") -> [16#0228B, 16#0FE00]; ++entity("varsupsetneqq") -> [16#02ACC, 16#0FE00]; ++entity("vartheta") -> 16#003D1; ++entity("vartriangleleft") -> 16#022B2; ++entity("vartriangleright") -> 16#022B3; ++entity("vcy") -> 16#00432; ++entity("vdash") -> 16#022A2; ++entity("vee") -> 16#02228; ++entity("veebar") -> 16#022BB; ++entity("veeeq") -> 16#0225A; ++entity("vellip") -> 16#022EE; ++entity("verbar") -> 16#0007C; ++entity("vert") -> 16#0007C; ++entity("vfr") -> 16#1D533; ++entity("vltri") -> 16#022B2; ++entity("vnsub") -> [16#02282, 16#020D2]; ++entity("vnsup") -> [16#02283, 16#020D2]; ++entity("vopf") -> 16#1D567; ++entity("vprop") -> 16#0221D; ++entity("vrtri") -> 16#022B3; ++entity("vscr") -> 16#1D4CB; ++entity("vsubnE") -> [16#02ACB, 16#0FE00]; ++entity("vsubne") -> [16#0228A, 16#0FE00]; ++entity("vsupnE") -> [16#02ACC, 16#0FE00]; ++entity("vsupne") -> [16#0228B, 16#0FE00]; ++entity("vzigzag") -> 16#0299A; ++entity("wcirc") -> 16#00175; ++entity("wedbar") -> 16#02A5F; ++entity("wedge") -> 16#02227; ++entity("wedgeq") -> 16#02259; ++entity("weierp") -> 16#02118; ++entity("wfr") -> 16#1D534; ++entity("wopf") -> 16#1D568; ++entity("wp") -> 16#02118; ++entity("wr") -> 16#02240; ++entity("wreath") -> 16#02240; ++entity("wscr") -> 16#1D4CC; ++entity("xcap") -> 16#022C2; ++entity("xcirc") -> 16#025EF; ++entity("xcup") -> 16#022C3; ++entity("xdtri") -> 16#025BD; ++entity("xfr") -> 16#1D535; ++entity("xhArr") -> 16#027FA; ++entity("xharr") -> 16#027F7; ++entity("xi") -> 16#003BE; ++entity("xlArr") -> 16#027F8; ++entity("xlarr") -> 16#027F5; ++entity("xmap") -> 16#027FC; ++entity("xnis") -> 16#022FB; ++entity("xodot") -> 16#02A00; ++entity("xopf") -> 16#1D569; ++entity("xoplus") -> 16#02A01; ++entity("xotime") -> 16#02A02; ++entity("xrArr") -> 16#027F9; ++entity("xrarr") -> 16#027F6; ++entity("xscr") -> 16#1D4CD; ++entity("xsqcup") -> 16#02A06; ++entity("xuplus") -> 16#02A04; ++entity("xutri") -> 16#025B3; ++entity("xvee") -> 16#022C1; ++entity("xwedge") -> 16#022C0; ++entity("yacute") -> 16#000FD; ++entity("yacy") -> 16#0044F; ++entity("ycirc") -> 16#00177; ++entity("ycy") -> 16#0044B; ++entity("yen") -> 16#000A5; ++entity("yfr") -> 16#1D536; ++entity("yicy") -> 16#00457; ++entity("yopf") -> 16#1D56A; ++entity("yscr") -> 16#1D4CE; ++entity("yucy") -> 16#0044E; ++entity("yuml") -> 16#000FF; ++entity("zacute") -> 16#0017A; ++entity("zcaron") -> 16#0017E; ++entity("zcy") -> 16#00437; ++entity("zdot") -> 16#0017C; ++entity("zeetrf") -> 16#02128; ++entity("zeta") -> 16#003B6; ++entity("zfr") -> 16#1D537; ++entity("zhcy") -> 16#00436; ++entity("zigrarr") -> 16#021DD; ++entity("zopf") -> 16#1D56B; ++entity("zscr") -> 16#1D4CF; ++entity("zwj") -> 16#0200D; ++entity("zwnj") -> 16#0200C; ++entity(_) -> undefined. + + %% + %% Tests + %% +--include_lib("eunit/include/eunit.hrl"). + -ifdef(TEST). ++-include_lib("eunit/include/eunit.hrl"). + + exhaustive_entity_test() -> + T = mochiweb_cover:clause_lookup_table(?MODULE, entity), +diff -wbBur apache-couchdb-1.2.1/src/mochiweb/mochiweb_cookies.erl apache-couchdb-1.2.1.q/src/mochiweb/mochiweb_cookies.erl +--- apache-couchdb-1.2.1/src/mochiweb/mochiweb_cookies.erl 2012-12-21 01:24:07.000000000 +0400 ++++ apache-couchdb-1.2.1.q/src/mochiweb/mochiweb_cookies.erl 2013-03-22 15:26:58.000000000 +0400 +@@ -23,6 +23,7 @@ + + %% @type proplist() = [{Key::string(), Value::string()}]. + %% @type header() = {Name::string(), Value::string()}. ++%% @type int_seconds() = integer(). + + %% @spec cookie(Key::string(), Value::string()) -> header() + %% @doc Short-hand for cookie(Key, Value, []). +@@ -30,7 +31,7 @@ + cookie(Key, Value, []). + + %% @spec cookie(Key::string(), Value::string(), Options::[Option]) -> header() +-%% where Option = {max_age, integer()} | {local_time, {date(), time()}} ++%% where Option = {max_age, int_seconds()} | {local_time, {date(), time()}} + %% | {domain, string()} | {path, string()} + %% | {secure, true | false} | {http_only, true | false} + %% +@@ -115,12 +116,33 @@ + orelse erlang:error({cookie_quoting_required, V}), + V. + ++ ++%% Return a date in the form of: Wdy, DD-Mon-YYYY HH:MM:SS GMT ++%% See also: rfc2109: 10.1.2 ++rfc2109_cookie_expires_date(LocalTime) -> ++ {{YYYY,MM,DD},{Hour,Min,Sec}} = ++ case calendar:local_time_to_universal_time_dst(LocalTime) of ++ [] -> ++ {Date, {Hour1, Min1, Sec1}} = LocalTime, ++ LocalTime2 = {Date, {Hour1 + 1, Min1, Sec1}}, ++ case calendar:local_time_to_universal_time_dst(LocalTime2) of ++ [Gmt] -> Gmt; ++ [_,Gmt] -> Gmt ++ end; ++ [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", ++ [httpd_util:day(DayNumber),DD,httpd_util:month(MM),YYYY,Hour,Min,Sec])). ++ + add_seconds(Secs, LocalTime) -> + Greg = calendar:datetime_to_gregorian_seconds(LocalTime), + calendar:gregorian_seconds_to_datetime(Greg + Secs). + + age_to_cookie_date(Age, LocalTime) -> +- httpd_util:rfc1123_date(add_seconds(Age, LocalTime)). ++ rfc2109_cookie_expires_date(add_seconds(Age, LocalTime)). + + %% @spec parse_cookie(string()) -> [{K::string(), V::string()}] + %% @doc Parse the contents of a Cookie header field, ignoring cookie +@@ -203,8 +225,8 @@ + %% + %% Tests + %% +--include_lib("eunit/include/eunit.hrl"). + -ifdef(TEST). ++-include_lib("eunit/include/eunit.hrl"). + + quote_test() -> + %% ?assertError eunit macro is not compatible with coverage module +@@ -293,14 +315,14 @@ + C2 = {"Set-Cookie", + "Customer=WILE_E_COYOTE; " + "Version=1; " +- "Expires=Tue, 15 May 2007 13:45:33 GMT; " ++ "Expires=Tue, 15-May-2007 13:45:33 GMT; " + "Max-Age=0"}, + C2 = cookie("Customer", "WILE_E_COYOTE", + [{max_age, -111}, {local_time, LocalTime}]), + C3 = {"Set-Cookie", + "Customer=WILE_E_COYOTE; " + "Version=1; " +- "Expires=Wed, 16 May 2007 13:45:50 GMT; " ++ "Expires=Wed, 16-May-2007 13:45:50 GMT; " + "Max-Age=86417"}, + C3 = cookie("Customer", "WILE_E_COYOTE", + [{max_age, 86417}, {local_time, LocalTime}]), +diff -wbBur apache-couchdb-1.2.1/src/mochiweb/mochiweb_cover.erl apache-couchdb-1.2.1.q/src/mochiweb/mochiweb_cover.erl +--- apache-couchdb-1.2.1/src/mochiweb/mochiweb_cover.erl 2012-12-21 01:24:07.000000000 +0400 ++++ apache-couchdb-1.2.1.q/src/mochiweb/mochiweb_cover.erl 2013-03-22 15:26:58.000000000 +0400 +@@ -46,8 +46,8 @@ + %% + %% Tests + %% +--include_lib("eunit/include/eunit.hrl"). + -ifdef(TEST). ++-include_lib("eunit/include/eunit.hrl"). + foo_table(a) -> b; + foo_table("a") -> <<"b">>; + foo_table(123) -> {4, 3, 2}; +diff -wbBur apache-couchdb-1.2.1/src/mochiweb/mochiweb_echo.erl apache-couchdb-1.2.1.q/src/mochiweb/mochiweb_echo.erl +--- apache-couchdb-1.2.1/src/mochiweb/mochiweb_echo.erl 2012-12-21 01:24:07.000000000 +0400 ++++ apache-couchdb-1.2.1.q/src/mochiweb/mochiweb_echo.erl 2013-03-22 15:26:58.000000000 +0400 +@@ -11,11 +11,14 @@ + mochiweb_socket_server:stop(?MODULE). + + start() -> +- mochiweb_socket_server:start([{name, ?MODULE}, ++ mochiweb_socket_server:start([{link, false} | options()]). ++ ++options() -> ++ [{name, ?MODULE}, + {port, 6789}, + {ip, "127.0.0.1"}, + {max, 1}, +- {loop, {?MODULE, loop}}]). ++ {loop, {?MODULE, loop}}]. + + loop(Socket) -> + case mochiweb_socket:recv(Socket, 0, 30000) of +@@ -33,6 +36,6 @@ + %% + %% Tests + %% +--include_lib("eunit/include/eunit.hrl"). + -ifdef(TEST). ++-include_lib("eunit/include/eunit.hrl"). + -endif. +diff -wbBur apache-couchdb-1.2.1/src/mochiweb/mochiweb.erl apache-couchdb-1.2.1.q/src/mochiweb/mochiweb.erl +--- apache-couchdb-1.2.1/src/mochiweb/mochiweb.erl 2012-12-21 01:24:07.000000000 +0400 ++++ apache-couchdb-1.2.1.q/src/mochiweb/mochiweb.erl 2013-03-22 15:26:58.000000000 +0400 +@@ -6,22 +6,9 @@ + -module(mochiweb). + -author('bob@mochimedia.com'). + +--export([start/0, stop/0]). + -export([new_request/1, new_response/1]). + -export([all_loaded/0, all_loaded/1, reload/0]). +- +-%% @spec start() -> ok +-%% @doc Start the MochiWeb server. +-start() -> +- ensure_started(crypto), +- application:start(mochiweb). +- +-%% @spec stop() -> ok +-%% @doc Stop the MochiWeb server. +-stop() -> +- Res = application:stop(mochiweb), +- application:stop(crypto), +- Res. ++-export([ensure_started/1]). + + reload() -> + [c:l(Module) || Module <- all_loaded()]. +@@ -78,8 +65,8 @@ + Code, + mochiweb_headers:make(Headers)). + +-%% Internal API +- ++%% @spec ensure_started(App::atom()) -> ok ++%% @doc Start the given App if it has not been started already. + ensure_started(App) -> + case application:start(App) of + ok -> +@@ -92,8 +78,8 @@ + %% + %% Tests + %% +--include_lib("eunit/include/eunit.hrl"). + -ifdef(TEST). ++-include_lib("eunit/include/eunit.hrl"). + + -record(treq, {path, body= <<>>, xreply= <<>>}). + +@@ -112,7 +98,7 @@ + ssl -> + ServerOpts0 ++ [{ssl, true}, {ssl_opts, ssl_cert_opts()}] + end, +- {ok, Server} = mochiweb_http:start(ServerOpts), ++ {ok, Server} = mochiweb_http:start_link(ServerOpts), + Port = mochiweb_socket_server:get(Server, port), + Res = (catch ClientFun(Transport, Port)), + mochiweb_http:stop(Server), +@@ -123,6 +109,8 @@ + "/foo/bar/baz wibble quux" = R:get(path), + ok. + ++-define(LARGE_TIMEOUT, 60). ++ + single_http_GET_test() -> + do_GET(plain, 1). + +@@ -135,11 +123,13 @@ + multiple_https_GET_test() -> + do_GET(ssl, 3). + +-hundred_http_GET_test() -> +- do_GET(plain, 100). +- +-hundred_https_GET_test() -> +- do_GET(ssl, 100). ++hundred_http_GET_test_() -> % note the underscore ++ {timeout, ?LARGE_TIMEOUT, ++ fun() -> ?assertEqual(ok, do_GET(plain,100)) end}. ++ ++hundred_https_GET_test_() -> % note the underscore ++ {timeout, ?LARGE_TIMEOUT, ++ fun() -> ?assertEqual(ok, do_GET(ssl,100)) end}. + + single_128_http_POST_test() -> + do_POST(plain, 128, 1). +@@ -165,11 +155,13 @@ + multiple_100K_https_POST_test() -> + do_POST(ssl, 102400, 3). + +-hundred_128_http_POST_test() -> +- do_POST(plain, 128, 100). +- +-hundred_128_https_POST_test() -> +- do_POST(ssl, 128, 100). ++hundred_128_http_POST_test_() -> % note the underscore ++ {timeout, ?LARGE_TIMEOUT, ++ fun() -> ?assertEqual(ok, do_POST(plain, 128, 100)) end}. ++ ++hundred_128_https_POST_test_() -> % note the underscore ++ {timeout, ?LARGE_TIMEOUT, ++ fun() -> ?assertEqual(ok, do_POST(ssl, 128, 100)) end}. + + do_GET(Transport, Times) -> + PathPrefix = "/whatever/", +diff -wbBur apache-couchdb-1.2.1/src/mochiweb/mochiweb_headers.erl apache-couchdb-1.2.1.q/src/mochiweb/mochiweb_headers.erl +--- apache-couchdb-1.2.1/src/mochiweb/mochiweb_headers.erl 2012-12-21 01:24:07.000000000 +0400 ++++ apache-couchdb-1.2.1.q/src/mochiweb/mochiweb_headers.erl 2013-03-22 15:26:58.000000000 +0400 +@@ -6,7 +6,7 @@ + -module(mochiweb_headers). + -author('bob@mochimedia.com'). + -export([empty/0, from_list/1, insert/3, enter/3, get_value/2, lookup/2]). +--export([delete_any/2, get_primary_value/2]). ++-export([delete_any/2, get_primary_value/2, get_combined_value/2]). + -export([default/3, enter_from_list/2, default_from_list/2]). + -export([to_list/1, make/1]). + -export([from_binary/1]). +@@ -24,8 +24,8 @@ + %% @doc Construct a headers() from the given list. + make(L) when is_list(L) -> + from_list(L); +-%% assume a tuple is already mochiweb_headers. +-make(T) when is_tuple(T) -> ++%% assume a non-list is already mochiweb_headers. ++make(T) -> + T. + + %% @spec from_binary(iolist()) -> headers() +@@ -112,6 +112,34 @@ + lists:takewhile(fun (C) -> C =/= $; end, V) + end. + ++%% @spec get_combined_value(key(), headers()) -> string() | undefined ++%% @doc Return the value from the given header using a case insensitive search. ++%% If the value of the header is a comma-separated list where holds values ++%% are all identical, the identical value will be returned. ++%% undefined will be returned for keys that are not present or the ++%% values in the list are not the same. ++%% ++%% NOTE: The process isn't designed for a general purpose. If you need ++%% to access all values in the combined header, please refer to ++%% '''tokenize_header_value/1'''. ++%% ++%% Section 4.2 of the RFC 2616 (HTTP 1.1) describes multiple message-header ++%% fields with the same field-name may be present in a message if and only ++%% if the entire field-value for that header field is defined as a ++%% comma-separated list [i.e., #(values)]. ++get_combined_value(K, T) -> ++ case get_value(K, T) of ++ undefined -> ++ undefined; ++ V -> ++ case sets:to_list(sets:from_list(tokenize_header_value(V))) of ++ [Val] -> ++ Val; ++ _ -> ++ undefined ++ end ++ end. ++ + %% @spec lookup(key(), headers()) -> {value, {key(), string()}} | none + %% @doc Return the case preserved key and value for the given header using + %% a case insensitive search. none will be returned for keys that are +@@ -164,6 +192,49 @@ + + %% Internal API + ++tokenize_header_value(undefined) -> ++ undefined; ++tokenize_header_value(V) -> ++ reversed_tokens(trim_and_reverse(V, false), [], []). ++ ++trim_and_reverse([S | Rest], Reversed) when S=:=$ ; S=:=$\n; S=:=$\t -> ++ trim_and_reverse(Rest, Reversed); ++trim_and_reverse(V, false) -> ++ trim_and_reverse(lists:reverse(V), true); ++trim_and_reverse(V, true) -> ++ V. ++ ++reversed_tokens([], [], Acc) -> ++ Acc; ++reversed_tokens([], Token, Acc) -> ++ [Token | Acc]; ++reversed_tokens("\"" ++ Rest, [], Acc) -> ++ case extract_quoted_string(Rest, []) of ++ {String, NewRest} -> ++ reversed_tokens(NewRest, [], [String | Acc]); ++ undefined -> ++ undefined ++ end; ++reversed_tokens("\"" ++ _Rest, _Token, _Acc) -> ++ undefined; ++reversed_tokens([C | Rest], [], Acc) when C=:=$ ;C=:=$\n;C=:=$\t;C=:=$, -> ++ reversed_tokens(Rest, [], Acc); ++reversed_tokens([C | Rest], Token, Acc) when C=:=$ ;C=:=$\n;C=:=$\t;C=:=$, -> ++ reversed_tokens(Rest, [], [Token | Acc]); ++reversed_tokens([C | Rest], Token, Acc) -> ++ reversed_tokens(Rest, [C | Token], Acc); ++reversed_tokens(_, _, _) -> ++ undefeined. ++ ++extract_quoted_string([], _Acc) -> ++ undefined; ++extract_quoted_string("\"\\" ++ Rest, Acc) -> ++ extract_quoted_string(Rest, "\"" ++ Acc); ++extract_quoted_string("\"" ++ Rest, Acc) -> ++ {Acc, Rest}; ++extract_quoted_string([C | Rest], Acc) -> ++ extract_quoted_string(Rest, [C | Acc]). ++ + expand({array, L}) -> + mochiweb_util:join(lists:reverse(L), ", "); + expand(V) -> +@@ -195,8 +266,8 @@ + %% + %% Tests. + %% +--include_lib("eunit/include/eunit.hrl"). + -ifdef(TEST). ++-include_lib("eunit/include/eunit.hrl"). + + make_test() -> + Identity = make([{hdr, foo}]), +@@ -237,6 +308,37 @@ + get_primary_value(<<"baz">>, H)), + ok. + ++get_combined_value_test() -> ++ H = make([{hdr, foo}, {baz, <<"wibble,taco">>}, {content_length, "123, 123"}, ++ {test, " 123, 123, 123 , 123,123 "}, ++ {test2, "456, 123, 123 , 123"}, ++ {test3, "123"}, {test4, " 123, "}]), ++ ?assertEqual( ++ "foo", ++ get_combined_value(hdr, H)), ++ ?assertEqual( ++ undefined, ++ get_combined_value(bar, H)), ++ ?assertEqual( ++ undefined, ++ get_combined_value(<<"baz">>, H)), ++ ?assertEqual( ++ "123", ++ get_combined_value(<<"content_length">>, H)), ++ ?assertEqual( ++ "123", ++ get_combined_value(<<"test">>, H)), ++ ?assertEqual( ++ undefined, ++ get_combined_value(<<"test2">>, H)), ++ ?assertEqual( ++ "123", ++ get_combined_value(<<"test3">>, H)), ++ ?assertEqual( ++ "123", ++ get_combined_value(<<"test4">>, H)), ++ ok. ++ + set_cookie_test() -> + H = make([{"set-cookie", foo}, {"set-cookie", bar}, {"set-cookie", baz}]), + ?assertEqual( +@@ -296,4 +398,23 @@ + [] = ?MODULE:to_list(?MODULE:from_binary([<<"\r\n\r\n">>])), + ok. + ++tokenize_header_value_test() -> ++ ?assertEqual(["a quote in a \"quote\"."], ++ tokenize_header_value("\"a quote in a \\\"quote\\\".\"")), ++ ?assertEqual(["abc"], tokenize_header_value("abc")), ++ ?assertEqual(["abc", "def"], tokenize_header_value("abc def")), ++ ?assertEqual(["abc", "def"], tokenize_header_value("abc , def")), ++ ?assertEqual(["abc", "def"], tokenize_header_value(",abc ,, def,,")), ++ ?assertEqual(["abc def"], tokenize_header_value("\"abc def\" ")), ++ ?assertEqual(["abc, def"], tokenize_header_value("\"abc, def\"")), ++ ?assertEqual(["\\a\\$"], tokenize_header_value("\"\\a\\$\"")), ++ ?assertEqual(["abc def", "foo, bar", "12345", ""], ++ tokenize_header_value("\"abc def\" \"foo, bar\" , 12345, \"\"")), ++ ?assertEqual(undefined, ++ tokenize_header_value(undefined)), ++ ?assertEqual(undefined, ++ tokenize_header_value("umatched quote\"")), ++ ?assertEqual(undefined, ++ tokenize_header_value("\"unmatched quote")). ++ + -endif. +diff -wbBur apache-couchdb-1.2.1/src/mochiweb/mochiweb_html.erl apache-couchdb-1.2.1.q/src/mochiweb/mochiweb_html.erl +--- apache-couchdb-1.2.1/src/mochiweb/mochiweb_html.erl 2012-12-21 01:24:07.000000000 +0400 ++++ apache-couchdb-1.2.1.q/src/mochiweb/mochiweb_html.erl 2013-03-22 15:26:58.000000000 +0400 +@@ -95,7 +95,12 @@ + to_tokens({Tag0, [], Acc}); + to_tokens({Tag0, Attrs, Acc}) -> + Tag = to_tag(Tag0), +- to_tokens([{Tag, Acc}], [{start_tag, Tag, Attrs, is_singleton(Tag)}]). ++ case is_singleton(Tag) of ++ true -> ++ to_tokens([], [{start_tag, Tag, Attrs, true}]); ++ false -> ++ to_tokens([{Tag, Acc}], [{start_tag, Tag, Attrs, false}]) ++ end. + + %% @spec to_html([html_token()] | html_node()) -> iolist() + %% @doc Convert a list of html_token() to a HTML document. +@@ -312,7 +317,8 @@ + {Tag, S1} = tokenize_literal(B, ?ADV_COL(S, 2)), + {S2, _} = find_gt(B, S1), + {{end_tag, Tag}, S2}; +- <<_:O/binary, "<", C, _/binary>> when ?IS_WHITESPACE(C) -> ++ <<_:O/binary, "<", C, _/binary>> ++ when ?IS_WHITESPACE(C); not ?IS_LITERAL_SAFE(C) -> + %% This isn't really strict HTML + {{data, Data, _Whitespace}, S1} = tokenize_data(B, ?INC_COL(S)), + {{data, <<$<, Data/binary>>, false}, S1}; +@@ -501,8 +507,6 @@ + tokenize_quoted_attr_value(B, S1, [Data|Acc], Q); + <<_:O/binary, Q, _/binary>> -> + { iolist_to_binary(lists:reverse(Acc)), ?INC_COL(S) }; +- <<_:O/binary, $\n, _/binary>> -> +- { iolist_to_binary(lists:reverse(Acc)), ?INC_LINE(S) }; + <<_:O/binary, C, _/binary>> -> + tokenize_quoted_attr_value(B, ?INC_COL(S), [C|Acc], Q) + end. +@@ -603,32 +607,33 @@ + end. + + tokenize_charref(Bin, S=#decoder{offset=O}) -> +- tokenize_charref(Bin, S, O). ++ try ++ tokenize_charref(Bin, S, O) ++ catch ++ throw:invalid_charref -> ++ {{data, <<"&">>, false}, S} ++ end. + + tokenize_charref(Bin, S=#decoder{offset=O}, Start) -> + case Bin of + <<_:O/binary>> -> +- <<_:Start/binary, Raw/binary>> = Bin, +- {{data, Raw, false}, S}; ++ throw(invalid_charref); + <<_:O/binary, C, _/binary>> when ?IS_WHITESPACE(C) + orelse C =:= ?SQUOTE + orelse C =:= ?QUOTE + orelse C =:= $/ + orelse C =:= $> -> +- Len = O - Start, +- <<_:Start/binary, Raw:Len/binary, _/binary>> = Bin, +- {{data, Raw, false}, S}; ++ throw(invalid_charref); + <<_:O/binary, $;, _/binary>> -> + Len = O - Start, + <<_:Start/binary, Raw:Len/binary, _/binary>> = Bin, + Data = case mochiweb_charref:charref(Raw) of + undefined -> +- Start1 = Start - 1, +- Len1 = Len + 2, +- <<_:Start1/binary, R:Len1/binary, _/binary>> = Bin, +- R; +- Unichar -> +- mochiutf8:codepoint_to_bytes(Unichar) ++ throw(invalid_charref); ++ Unichar when is_integer(Unichar) -> ++ mochiutf8:codepoint_to_bytes(Unichar); ++ Unichars when is_list(Unichars) -> ++ unicode:characters_to_binary(Unichars) + end, + {{data, Data, false}, ?INC_COL(S)}; + _ -> +@@ -759,8 +764,8 @@ + %% + %% Tests + %% +--include_lib("eunit/include/eunit.hrl"). + -ifdef(TEST). ++-include_lib("eunit/include/eunit.hrl"). + + to_html_test() -> + ?assertEqual( +@@ -1232,6 +1237,14 @@ + { <<"img">>, [ { <<"src">>, <<"/images/icon>.png">> } ], [] } + ]}, + mochiweb_html:parse(D2)), ++ ++ %% Quoted attributes can contain whitespace and newlines ++ D3 = <<"">>, ++ ?assertEqual( ++ {<<"html">>,[],[ ++ { <<"a">>, [ { <<"href">>, <<"#">> }, {<<"onclick">>, <<"javascript: test(1,\ntrue);">>} ], [] } ++ ]}, ++ mochiweb_html:parse(D3)), + ok. + + parse_missing_attr_name_test() -> +@@ -1261,4 +1274,59 @@ + mochiweb_html:parse(D0)), + ok. + ++to_html_singleton_test() -> ++ D0 = <<"">>, ++ T0 = {<<"link">>,[],[]}, ++ ?assertEqual(D0, iolist_to_binary(to_html(T0))), ++ ++ D1 = <<"">>, ++ T1 = {<<"head">>,[],[{<<"link">>,[],[]}]}, ++ ?assertEqual(D1, iolist_to_binary(to_html(T1))), ++ ++ D2 = <<"">>, ++ T2 = {<<"head">>,[],[{<<"link">>,[],[]}, {<<"link">>,[],[]}]}, ++ ?assertEqual(D2, iolist_to_binary(to_html(T2))), ++ ++ %% Make sure singletons are converted to singletons. ++ D3 = <<"">>, ++ T3 = {<<"head">>,[],[{<<"link">>,[],[<<"funny">>]}]}, ++ ?assertEqual(D3, iolist_to_binary(to_html(T3))), ++ ++ D4 = <<"">>, ++ T4 = {<<"link">>,[],[<<"funny">>]}, ++ ?assertEqual(D4, iolist_to_binary(to_html(T4))), ++ ++ ok. ++ ++parse_amp_test_() -> ++ [?_assertEqual( ++ {<<"html">>,[], ++ [{<<"body">>,[{<<"onload">>,<<"javascript:A('1&2')">>}],[]}]}, ++ mochiweb_html:parse("")), ++ ?_assertEqual( ++ {<<"html">>,[], ++ [{<<"body">>,[{<<"onload">>,<<"javascript:A('1& 2')">>}],[]}]}, ++ mochiweb_html:parse("")), ++ ?_assertEqual( ++ {<<"html">>,[], ++ [{<<"body">>,[],[<<"& ">>]}]}, ++ mochiweb_html:parse("& ")), ++ ?_assertEqual( ++ {<<"html">>,[], ++ [{<<"body">>,[],[<<"&">>]}]}, ++ mochiweb_html:parse("&"))]. ++ ++parse_unescaped_lt_test() -> ++ D1 = <<"
< < Back
">>, ++ ?assertEqual( ++ {<<"div">>, [], [<<" < < ">>, {<<"a">>, [{<<"href">>, <<"/">>}], ++ [<<"Back">>]}]}, ++ mochiweb_html:parse(D1)), ++ ++ D2 = <<"
<< Back
">>, ++ ?assertEqual( ++ {<<"div">>, [], [<<" << ">>, {<<"a">>, [{<<"href">>, <<"/">>}], ++ [<<"Back">>]}]}, ++ mochiweb_html:parse(D2)). ++ + -endif. +diff -wbBur apache-couchdb-1.2.1/src/mochiweb/mochiweb_http.erl apache-couchdb-1.2.1.q/src/mochiweb/mochiweb_http.erl +--- apache-couchdb-1.2.1/src/mochiweb/mochiweb_http.erl 2012-12-21 01:24:07.000000000 +0400 ++++ apache-couchdb-1.2.1.q/src/mochiweb/mochiweb_http.erl 2013-03-22 15:26:58.000000000 +0400 +@@ -5,13 +5,13 @@ + + -module(mochiweb_http). + -author('bob@mochimedia.com'). +--export([start/0, start/1, stop/0, stop/1]). +--export([loop/2, default_body/1]). ++-export([start/1, start_link/1, stop/0, stop/1]). ++-export([loop/2]). + -export([after_response/2, reentry/1]). + -export([parse_range_request/1, range_skip_length/2]). + +--define(REQUEST_RECV_TIMEOUT, 300000). % timeout waiting for request line +--define(HEADERS_RECV_TIMEOUT, 30000). % timeout waiting for headers ++-define(REQUEST_RECV_TIMEOUT, 300000). %% timeout waiting for request line ++-define(HEADERS_RECV_TIMEOUT, 30000). %% timeout waiting for headers + + -define(MAX_HEADERS, 1000). + -define(DEFAULTS, [{name, ?MODULE}, +@@ -19,9 +19,7 @@ + + parse_options(Options) -> + {loop, HttpLoop} = proplists:lookup(loop, Options), +- Loop = fun (S) -> +- ?MODULE:loop(S, HttpLoop) +- end, ++ Loop = {?MODULE, loop, [HttpLoop]}, + Options1 = [{loop, Loop} | proplists:delete(loop, Options)], + mochilists:set_defaults(?DEFAULTS, Options1). + +@@ -31,15 +29,12 @@ + stop(Name) -> + mochiweb_socket_server:stop(Name). + +-start() -> +- start([{ip, "127.0.0.1"}, +- {loop, {?MODULE, default_body}}]). +- + %% @spec start(Options) -> ServerRet + %% Options = [option()] + %% Option = {name, atom()} | {ip, string() | tuple()} | {backlog, integer()} + %% | {nodelay, boolean()} | {acceptor_pool_size, integer()} + %% | {ssl, boolean()} | {profile_fun, undefined | (Props) -> ok} ++%% | {link, false} + %% @doc Start a mochiweb server. + %% profile_fun is used to profile accept timing. + %% After each accept, if defined, profile_fun is called with a proplist of a subset of the mochiweb_socket_server state and timing information. +@@ -48,62 +43,18 @@ + start(Options) -> + mochiweb_socket_server:start(parse_options(Options)). + +-frm(Body) -> +- ["" +- "
" +- "" +- "" +- "
" +- "
" +- "
" +- "" +- "" +- "" +- "
" +- "
", Body, "
" +- ""]. +- +-default_body(Req, M, "/chunked") when M =:= 'GET'; M =:= 'HEAD' -> +- Res = Req:ok({"text/plain", [], chunked}), +- Res:write_chunk("First chunk\r\n"), +- timer:sleep(5000), +- Res:write_chunk("Last chunk\r\n"), +- Res:write_chunk(""); +-default_body(Req, M, _Path) when M =:= 'GET'; M =:= 'HEAD' -> +- Body = io_lib:format("~p~n", [[{parse_qs, Req:parse_qs()}, +- {parse_cookie, Req:parse_cookie()}, +- Req:dump()]]), +- Req:ok({"text/html", +- [mochiweb_cookies:cookie("mochiweb_http", "test_cookie")], +- frm(Body)}); +-default_body(Req, 'POST', "/multipart") -> +- Body = io_lib:format("~p~n", [[{parse_qs, Req:parse_qs()}, +- {parse_cookie, Req:parse_cookie()}, +- {body, Req:recv_body()}, +- Req:dump()]]), +- Req:ok({"text/html", [], frm(Body)}); +-default_body(Req, 'POST', _Path) -> +- Body = io_lib:format("~p~n", [[{parse_qs, Req:parse_qs()}, +- {parse_cookie, Req:parse_cookie()}, +- {parse_post, Req:parse_post()}, +- Req:dump()]]), +- Req:ok({"text/html", [], frm(Body)}); +-default_body(Req, _Method, _Path) -> +- Req:respond({501, [], []}). +- +-default_body(Req) -> +- default_body(Req, Req:get(method), Req:get(path)). ++start_link(Options) -> ++ mochiweb_socket_server:start_link(parse_options(Options)). + + loop(Socket, Body) -> +- mochiweb_socket:setopts(Socket, [{packet, http}]), ++ ok = mochiweb_socket:setopts(Socket, [{packet, http}]), + request(Socket, Body). + + request(Socket, Body) -> +- mochiweb_socket:setopts(Socket, [{active, once}]), ++ ok = mochiweb_socket:setopts(Socket, [{active, once}]), + receive + {Protocol, _, {http_request, Method, Path, Version}} when Protocol == http orelse Protocol == ssl -> +- mochiweb_socket:setopts(Socket, [{packet, httph}]), ++ ok = mochiweb_socket:setopts(Socket, [{packet, httph}]), + headers(Socket, {Method, Path, Version}, [], Body, 0); + {Protocol, _, {http_error, "\r\n"}} when Protocol == http orelse Protocol == ssl -> + request(Socket, Body); +@@ -112,6 +63,13 @@ + {tcp_closed, _} -> + mochiweb_socket:close(Socket), + exit(normal); ++ {ssl_closed, _} -> ++ mochiweb_socket:close(Socket), ++ exit(normal); ++ {tcp_error,_,emsgsize} -> ++ % R15B02 returns this then closes the socket, so close and exit ++ mochiweb_socket:close(Socket), ++ exit(normal); + _Other -> + handle_invalid_request(Socket) + after ?REQUEST_RECV_TIMEOUT -> +@@ -126,10 +84,10 @@ + + headers(Socket, Request, Headers, _Body, ?MAX_HEADERS) -> + %% Too many headers sent, bad request. +- mochiweb_socket:setopts(Socket, [{packet, raw}]), ++ ok = mochiweb_socket:setopts(Socket, [{packet, raw}]), + handle_invalid_request(Socket, Request, Headers); + headers(Socket, Request, Headers, Body, HeaderCount) -> +- mochiweb_socket:setopts(Socket, [{active, once}]), ++ ok = mochiweb_socket:setopts(Socket, [{active, once}]), + receive + {Protocol, _, http_eoh} when Protocol == http orelse Protocol == ssl -> + Req = new_request(Socket, Request, Headers), +@@ -141,6 +99,10 @@ + {tcp_closed, _} -> + mochiweb_socket:close(Socket), + exit(normal); ++ {tcp_error,_,emsgsize} -> ++ % R15B02 returns this then closes the socket, so close and exit ++ mochiweb_socket:close(Socket), ++ exit(normal); + _Other -> + handle_invalid_request(Socket, Request, Headers) + after ?HEADERS_RECV_TIMEOUT -> +@@ -148,14 +110,19 @@ + exit(normal) + end. + ++call_body({M, F, A}, Req) -> ++ erlang:apply(M, F, [Req | A]); + call_body({M, F}, Req) -> + M:F(Req); + call_body(Body, Req) -> + Body(Req). + ++-spec handle_invalid_request(term()) -> no_return(). + handle_invalid_request(Socket) -> +- handle_invalid_request(Socket, {'GET', {abs_path, "/"}, {0,9}}, []). ++ handle_invalid_request(Socket, {'GET', {abs_path, "/"}, {0,9}}, []), ++ exit(normal). + ++-spec handle_invalid_request(term(), term(), term()) -> no_return(). + handle_invalid_request(Socket, Request, RevHeaders) -> + Req = new_request(Socket, Request, RevHeaders), + Req:respond({400, [], []}), +@@ -163,7 +130,7 @@ + exit(normal). + + new_request(Socket, Request, RevHeaders) -> +- mochiweb_socket:setopts(Socket, [{packet, raw}]), ++ ok = mochiweb_socket:setopts(Socket, [{packet, raw}]), + mochiweb:new_request({Socket, Request, lists:reverse(RevHeaders)}). + + after_response(Body, Req) -> +@@ -174,6 +141,7 @@ + exit(normal); + false -> + Req:cleanup(), ++ erlang:garbage_collect(), + ?MODULE:loop(Socket, Body) + end. + +@@ -211,6 +179,8 @@ + invalid_range; + {Start, End} when 0 =< Start, Start =< End, End < Size -> + {Start, End - Start + 1}; ++ {Start, End} when 0 =< Start, Start =< End, End >= Size -> ++ {Start, Size - Start}; + {_OutOfRange, _End} -> + invalid_range + end. +@@ -218,8 +188,8 @@ + %% + %% Tests + %% +--include_lib("eunit/include/eunit.hrl"). + -ifdef(TEST). ++-include_lib("eunit/include/eunit.hrl"). + + range_test() -> + %% valid, single ranges +@@ -265,19 +235,23 @@ + BodySizeLess1 = BodySize - 1, + ?assertEqual({BodySizeLess1, 1}, + range_skip_length({BodySize - 1, none}, BodySize)), ++ ?assertEqual({BodySizeLess1, 1}, ++ range_skip_length({BodySize - 1, BodySize+5}, BodySize)), ++ ?assertEqual({BodySizeLess1, 1}, ++ range_skip_length({BodySize - 1, BodySize}, BodySize)), + + %% out of range, return whole thing + ?assertEqual({0, BodySize}, + range_skip_length({none, BodySize + 1}, BodySize)), + ?assertEqual({0, BodySize}, + range_skip_length({none, -1}, BodySize)), ++ ?assertEqual({0, BodySize}, ++ range_skip_length({0, BodySize + 1}, BodySize)), + + %% invalid ranges + ?assertEqual(invalid_range, + range_skip_length({-1, 30}, BodySize)), + ?assertEqual(invalid_range, +- range_skip_length({0, BodySize + 1}, BodySize)), +- ?assertEqual(invalid_range, + range_skip_length({-1, BodySize + 1}, BodySize)), + ?assertEqual(invalid_range, + range_skip_length({BodySize, 40}, BodySize)), +diff -wbBur apache-couchdb-1.2.1/src/mochiweb/mochiweb_io.erl apache-couchdb-1.2.1.q/src/mochiweb/mochiweb_io.erl +--- apache-couchdb-1.2.1/src/mochiweb/mochiweb_io.erl 2012-12-21 01:24:07.000000000 +0400 ++++ apache-couchdb-1.2.1.q/src/mochiweb/mochiweb_io.erl 2013-03-22 15:26:58.000000000 +0400 +@@ -38,9 +38,6 @@ + %% + %% Tests + %% +--include_lib("eunit/include/eunit.hrl"). + -ifdef(TEST). +- +- +- ++-include_lib("eunit/include/eunit.hrl"). + -endif. +diff -wbBur apache-couchdb-1.2.1/src/mochiweb/mochiweb_mime.erl apache-couchdb-1.2.1.q/src/mochiweb/mochiweb_mime.erl +--- apache-couchdb-1.2.1/src/mochiweb/mochiweb_mime.erl 2012-12-21 01:24:07.000000000 +0400 ++++ apache-couchdb-1.2.1.q/src/mochiweb/mochiweb_mime.erl 2013-03-22 15:26:58.000000000 +0400 +@@ -11,72 +11,393 @@ + %% @doc Given a filename extension (e.g. ".html") return a guess for the MIME + %% type such as "text/html". Will return the atom undefined if no good + %% guess is available. +-from_extension(".html") -> +- "text/html"; +-from_extension(".xhtml") -> +- "application/xhtml+xml"; +-from_extension(".xml") -> +- "application/xml"; +-from_extension(".css") -> +- "text/css"; ++ ++from_extension(".stl") -> ++ "application/SLA"; ++from_extension(".stp") -> ++ "application/STEP"; ++from_extension(".step") -> ++ "application/STEP"; ++from_extension(".dwg") -> ++ "application/acad"; ++from_extension(".ez") -> ++ "application/andrew-inset"; ++from_extension(".ccad") -> ++ "application/clariscad"; ++from_extension(".drw") -> ++ "application/drafting"; ++from_extension(".tsp") -> ++ "application/dsptype"; ++from_extension(".dxf") -> ++ "application/dxf"; ++from_extension(".xls") -> ++ "application/excel"; ++from_extension(".unv") -> ++ "application/i-deas"; ++from_extension(".jar") -> ++ "application/java-archive"; ++from_extension(".hqx") -> ++ "application/mac-binhex40"; ++from_extension(".cpt") -> ++ "application/mac-compactpro"; ++from_extension(".pot") -> ++ "application/vnd.ms-powerpoint"; ++from_extension(".ppt") -> ++ "application/vnd.ms-powerpoint"; ++from_extension(".dms") -> ++ "application/octet-stream"; ++from_extension(".lha") -> ++ "application/octet-stream"; ++from_extension(".lzh") -> ++ "application/octet-stream"; ++from_extension(".oda") -> ++ "application/oda"; ++from_extension(".ogg") -> ++ "application/ogg"; ++from_extension(".ogm") -> ++ "application/ogg"; ++from_extension(".pdf") -> ++ "application/pdf"; ++from_extension(".pgp") -> ++ "application/pgp"; ++from_extension(".ai") -> ++ "application/postscript"; ++from_extension(".eps") -> ++ "application/postscript"; ++from_extension(".ps") -> ++ "application/postscript"; ++from_extension(".prt") -> ++ "application/pro_eng"; ++from_extension(".rtf") -> ++ "application/rtf"; ++from_extension(".smi") -> ++ "application/smil"; ++from_extension(".smil") -> ++ "application/smil"; ++from_extension(".sol") -> ++ "application/solids"; ++from_extension(".vda") -> ++ "application/vda"; ++from_extension(".xlm") -> ++ "application/vnd.ms-excel"; ++from_extension(".cod") -> ++ "application/vnd.rim.cod"; ++from_extension(".pgn") -> ++ "application/x-chess-pgn"; ++from_extension(".cpio") -> ++ "application/x-cpio"; ++from_extension(".csh") -> ++ "application/x-csh"; ++from_extension(".deb") -> ++ "application/x-debian-package"; ++from_extension(".dcr") -> ++ "application/x-director"; ++from_extension(".dir") -> ++ "application/x-director"; ++from_extension(".dxr") -> ++ "application/x-director"; ++from_extension(".gz") -> ++ "application/x-gzip"; ++from_extension(".hdf") -> ++ "application/x-hdf"; ++from_extension(".ipx") -> ++ "application/x-ipix"; ++from_extension(".ips") -> ++ "application/x-ipscript"; + from_extension(".js") -> + "application/x-javascript"; +-from_extension(".jpg") -> +- "image/jpeg"; +-from_extension(".gif") -> +- "image/gif"; +-from_extension(".png") -> +- "image/png"; ++from_extension(".skd") -> ++ "application/x-koan"; ++from_extension(".skm") -> ++ "application/x-koan"; ++from_extension(".skp") -> ++ "application/x-koan"; ++from_extension(".skt") -> ++ "application/x-koan"; ++from_extension(".latex") -> ++ "application/x-latex"; ++from_extension(".lsp") -> ++ "application/x-lisp"; ++from_extension(".scm") -> ++ "application/x-lotusscreencam"; ++from_extension(".mif") -> ++ "application/x-mif"; ++from_extension(".com") -> ++ "application/x-msdos-program"; ++from_extension(".exe") -> ++ "application/octet-stream"; ++from_extension(".cdf") -> ++ "application/x-netcdf"; ++from_extension(".nc") -> ++ "application/x-netcdf"; ++from_extension(".pl") -> ++ "application/x-perl"; ++from_extension(".pm") -> ++ "application/x-perl"; ++from_extension(".rar") -> ++ "application/x-rar-compressed"; ++from_extension(".sh") -> ++ "application/x-sh"; ++from_extension(".shar") -> ++ "application/x-shar"; + from_extension(".swf") -> + "application/x-shockwave-flash"; +-from_extension(".zip") -> +- "application/zip"; +-from_extension(".bz2") -> +- "application/x-bzip2"; +-from_extension(".gz") -> +- "application/x-gzip"; ++from_extension(".sit") -> ++ "application/x-stuffit"; ++from_extension(".sv4cpio") -> ++ "application/x-sv4cpio"; ++from_extension(".sv4crc") -> ++ "application/x-sv4crc"; ++from_extension(".tar.gz") -> ++ "application/x-tar-gz"; ++from_extension(".tgz") -> ++ "application/x-tar-gz"; + from_extension(".tar") -> + "application/x-tar"; +-from_extension(".tgz") -> +- "application/x-gzip"; ++from_extension(".tcl") -> ++ "application/x-tcl"; ++from_extension(".texi") -> ++ "application/x-texinfo"; ++from_extension(".texinfo") -> ++ "application/x-texinfo"; ++from_extension(".man") -> ++ "application/x-troff-man"; ++from_extension(".me") -> ++ "application/x-troff-me"; ++from_extension(".ms") -> ++ "application/x-troff-ms"; ++from_extension(".roff") -> ++ "application/x-troff"; ++from_extension(".t") -> ++ "application/x-troff"; ++from_extension(".tr") -> ++ "application/x-troff"; ++from_extension(".ustar") -> ++ "application/x-ustar"; ++from_extension(".src") -> ++ "application/x-wais-source"; ++from_extension(".zip") -> ++ "application/zip"; ++from_extension(".tsi") -> ++ "audio/TSP-audio"; ++from_extension(".au") -> ++ "audio/basic"; ++from_extension(".snd") -> ++ "audio/basic"; ++from_extension(".kar") -> ++ "audio/midi"; ++from_extension(".mid") -> ++ "audio/midi"; ++from_extension(".midi") -> ++ "audio/midi"; ++from_extension(".mp2") -> ++ "audio/mpeg"; ++from_extension(".mp3") -> ++ "audio/mpeg"; ++from_extension(".mpga") -> ++ "audio/mpeg"; ++from_extension(".aif") -> ++ "audio/x-aiff"; ++from_extension(".aifc") -> ++ "audio/x-aiff"; ++from_extension(".aiff") -> ++ "audio/x-aiff"; ++from_extension(".m3u") -> ++ "audio/x-mpegurl"; ++from_extension(".wax") -> ++ "audio/x-ms-wax"; ++from_extension(".wma") -> ++ "audio/x-ms-wma"; ++from_extension(".rpm") -> ++ "audio/x-pn-realaudio-plugin"; ++from_extension(".ram") -> ++ "audio/x-pn-realaudio"; ++from_extension(".rm") -> ++ "audio/x-pn-realaudio"; ++from_extension(".ra") -> ++ "audio/x-realaudio"; ++from_extension(".wav") -> ++ "audio/x-wav"; ++from_extension(".pdb") -> ++ "chemical/x-pdb"; ++from_extension(".ras") -> ++ "image/cmu-raster"; ++from_extension(".gif") -> ++ "image/gif"; ++from_extension(".ief") -> ++ "image/ief"; ++from_extension(".jpe") -> ++ "image/jpeg"; ++from_extension(".jpeg") -> ++ "image/jpeg"; ++from_extension(".jpg") -> ++ "image/jpeg"; ++from_extension(".jp2") -> ++ "image/jp2"; ++from_extension(".png") -> ++ "image/png"; ++from_extension(".tif") -> ++ "image/tiff"; ++from_extension(".tiff") -> ++ "image/tiff"; ++from_extension(".pnm") -> ++ "image/x-portable-anymap"; ++from_extension(".pbm") -> ++ "image/x-portable-bitmap"; ++from_extension(".pgm") -> ++ "image/x-portable-graymap"; ++from_extension(".ppm") -> ++ "image/x-portable-pixmap"; ++from_extension(".rgb") -> ++ "image/x-rgb"; ++from_extension(".xbm") -> ++ "image/x-xbitmap"; ++from_extension(".xwd") -> ++ "image/x-xwindowdump"; ++from_extension(".iges") -> ++ "model/iges"; ++from_extension(".igs") -> ++ "model/iges"; ++from_extension(".mesh") -> ++ "model/mesh"; ++from_extension(".") -> ++ ""; ++from_extension(".msh") -> ++ "model/mesh"; ++from_extension(".silo") -> ++ "model/mesh"; ++from_extension(".vrml") -> ++ "model/vrml"; ++from_extension(".wrl") -> ++ "model/vrml"; ++from_extension(".css") -> ++ "text/css"; ++from_extension(".htm") -> ++ "text/html"; ++from_extension(".html") -> ++ "text/html"; ++from_extension(".asc") -> ++ "text/plain"; ++from_extension(".c") -> ++ "text/plain"; ++from_extension(".cc") -> ++ "text/plain"; ++from_extension(".f90") -> ++ "text/plain"; ++from_extension(".f") -> ++ "text/plain"; ++from_extension(".hh") -> ++ "text/plain"; ++from_extension(".m") -> ++ "text/plain"; + from_extension(".txt") -> + "text/plain"; +-from_extension(".doc") -> +- "application/msword"; +-from_extension(".pdf") -> +- "application/pdf"; +-from_extension(".xls") -> +- "application/vnd.ms-excel"; +-from_extension(".rtf") -> +- "application/rtf"; ++from_extension(".rtx") -> ++ "text/richtext"; ++from_extension(".sgm") -> ++ "text/sgml"; ++from_extension(".sgml") -> ++ "text/sgml"; ++from_extension(".tsv") -> ++ "text/tab-separated-values"; ++from_extension(".jad") -> ++ "text/vnd.sun.j2me.app-descriptor"; ++from_extension(".etx") -> ++ "text/x-setext"; ++from_extension(".xml") -> ++ "application/xml"; ++from_extension(".dl") -> ++ "video/dl"; ++from_extension(".fli") -> ++ "video/fli"; ++from_extension(".flv") -> ++ "video/x-flv"; ++from_extension(".gl") -> ++ "video/gl"; ++from_extension(".mp4") -> ++ "video/mp4"; ++from_extension(".mpe") -> ++ "video/mpeg"; ++from_extension(".mpeg") -> ++ "video/mpeg"; ++from_extension(".mpg") -> ++ "video/mpeg"; + from_extension(".mov") -> + "video/quicktime"; +-from_extension(".mp3") -> +- "audio/mpeg"; ++from_extension(".qt") -> ++ "video/quicktime"; ++from_extension(".viv") -> ++ "video/vnd.vivo"; ++from_extension(".vivo") -> ++ "video/vnd.vivo"; ++from_extension(".asf") -> ++ "video/x-ms-asf"; ++from_extension(".asx") -> ++ "video/x-ms-asx"; ++from_extension(".wmv") -> ++ "video/x-ms-wmv"; ++from_extension(".wmx") -> ++ "video/x-ms-wmx"; ++from_extension(".wvx") -> ++ "video/x-ms-wvx"; ++from_extension(".avi") -> ++ "video/x-msvideo"; ++from_extension(".movie") -> ++ "video/x-sgi-movie"; ++from_extension(".mime") -> ++ "www/mime"; ++from_extension(".ice") -> ++ "x-conference/x-cooltalk"; ++from_extension(".vrm") -> ++ "x-world/x-vrml"; ++from_extension(".spx") -> ++ "audio/ogg"; ++from_extension(".xhtml") -> ++ "application/xhtml+xml"; ++from_extension(".bz2") -> ++ "application/x-bzip2"; ++from_extension(".doc") -> ++ "application/msword"; + from_extension(".z") -> + "application/x-compress"; +-from_extension(".wav") -> +- "audio/x-wav"; + from_extension(".ico") -> + "image/x-icon"; + from_extension(".bmp") -> + "image/bmp"; + from_extension(".m4a") -> + "audio/mpeg"; +-from_extension(".m3u") -> +- "audio/x-mpegurl"; +-from_extension(".exe") -> +- "application/octet-stream"; + from_extension(".csv") -> + "text/csv"; ++from_extension(".eot") -> ++ "application/vnd.ms-fontobject"; ++from_extension(".m4v") -> ++ "video/mp4"; ++from_extension(".svg") -> ++ "image/svg+xml"; ++from_extension(".svgz") -> ++ "image/svg+xml"; ++from_extension(".ttc") -> ++ "application/x-font-ttf"; ++from_extension(".ttf") -> ++ "application/x-font-ttf"; ++from_extension(".vcf") -> ++ "text/x-vcard"; ++from_extension(".webm") -> ++ "video/web"; ++from_extension(".webp") -> ++ "image/web"; ++from_extension(".woff") -> ++ "application/x-font-woff"; ++from_extension(".otf") -> ++ "font/opentype"; + from_extension(_) -> + undefined. + + %% + %% Tests + %% +--include_lib("eunit/include/eunit.hrl"). + -ifdef(TEST). ++-include_lib("eunit/include/eunit.hrl"). + + exhaustive_from_extension_test() -> + T = mochiweb_cover:clause_lookup_table(?MODULE, from_extension), +diff -wbBur apache-couchdb-1.2.1/src/mochiweb/mochiweb_multipart.erl apache-couchdb-1.2.1.q/src/mochiweb/mochiweb_multipart.erl +--- apache-couchdb-1.2.1/src/mochiweb/mochiweb_multipart.erl 2012-12-21 01:24:07.000000000 +0400 ++++ apache-couchdb-1.2.1.q/src/mochiweb/mochiweb_multipart.erl 2013-03-22 15:26:58.000000000 +0400 +@@ -128,7 +128,7 @@ + + parse_multipart_request(Req, Callback) -> + %% TODO: Support chunked? +- Length = list_to_integer(Req:get_header_value("content-length")), ++ Length = list_to_integer(Req:get_combined_header_value("content-length")), + Boundary = iolist_to_binary( + get_boundary(Req:get_header_value("content-type"))), + Prefix = <<"\r\n--", Boundary/binary>>, +@@ -240,24 +240,22 @@ + S + end. + +-find_in_binary(B, Data) when size(B) > 0 -> +- case size(Data) - size(B) of ++%% @spec find_in_binary(Pattern::binary(), Data::binary()) -> ++%% {exact, N} | {partial, N, K} | not_found ++%% @doc Searches for the given pattern in the given binary. ++find_in_binary(P, Data) when size(P) > 0 -> ++ PS = size(P), ++ DS = size(Data), ++ case DS - PS of + Last when Last < 0 -> +- partial_find(B, Data, 0, size(Data)); ++ partial_find(P, Data, 0, DS); + Last -> +- find_in_binary(B, size(B), Data, 0, Last) ++ case binary:match(Data, P) of ++ {Pos, _} -> {exact, Pos}; ++ nomatch -> partial_find(P, Data, Last+1, PS-1) ++ end + end. + +-find_in_binary(B, BS, D, N, Last) when N =< Last-> +- case D of +- <<_:N/binary, B:BS/binary, _/binary>> -> +- {exact, N}; +- _ -> +- find_in_binary(B, BS, D, 1 + N, Last) +- end; +-find_in_binary(B, BS, D, N, Last) when N =:= 1 + Last -> +- partial_find(B, D, N, BS - 1). +- + partial_find(_B, _D, _N, 0) -> + not_found; + partial_find(B, D, N, K) -> +@@ -295,8 +293,8 @@ + %% + %% Tests + %% +--include_lib("eunit/include/eunit.hrl"). + -ifdef(TEST). ++-include_lib("eunit/include/eunit.hrl"). + + ssl_cert_opts() -> + EbinDir = filename:dirname(code:which(?MODULE)), +@@ -313,7 +311,7 @@ + ssl -> + ServerOpts0 ++ [{ssl, true}, {ssl_opts, ssl_cert_opts()}] + end, +- {ok, Server} = mochiweb_socket_server:start(ServerOpts), ++ {ok, Server} = mochiweb_socket_server:start_link(ServerOpts), + Port = mochiweb_socket_server:get(Server, port), + ClientOpts = [binary, {active, false}], + {ok, Client} = case Transport of +@@ -821,4 +819,54 @@ + 10))), + ok. + ++%% @todo Move somewhere more appropriate than in the test suite ++ ++multipart_parsing_benchmark_test() -> ++ run_multipart_parsing_benchmark(1). ++ ++run_multipart_parsing_benchmark(0) -> ok; ++run_multipart_parsing_benchmark(N) -> ++ multipart_parsing_benchmark(), ++ run_multipart_parsing_benchmark(N-1). ++ ++multipart_parsing_benchmark() -> ++ ContentType = "multipart/form-data; boundary=----------ei4GI3GI3Ij5Ef1ae0KM7Ij5ei4Ij5", ++ Chunk = binary:copy(<<"This Is_%Some=Quite0Long4String2Used9For7BenchmarKing.5">>, 102400), ++ BinContent = <<"------------ei4GI3GI3Ij5Ef1ae0KM7Ij5ei4Ij5\r\nContent-Disposition: form-data; name=\"Filename\"\r\n\r\nhello.txt\r\n------------ei4GI3GI3Ij5Ef1ae0KM7Ij5ei4Ij5\r\nContent-Disposition: form-data; name=\"success_action_status\"\r\n\r\n201\r\n------------ei4GI3GI3Ij5Ef1ae0KM7Ij5ei4Ij5\r\nContent-Disposition: form-data; name=\"file\"; filename=\"hello.txt\"\r\nContent-Type: application/octet-stream\r\n\r\n", Chunk/binary, "\r\n------------ei4GI3GI3Ij5Ef1ae0KM7Ij5ei4Ij5\r\nContent-Disposition: form-data; name=\"Upload\"\r\n\r\nSubmit Query\r\n------------ei4GI3GI3Ij5Ef1ae0KM7Ij5ei4Ij5--">>, ++ Expect = [{headers, ++ [{"content-disposition", ++ {"form-data", [{"name", "Filename"}]}}]}, ++ {body, <<"hello.txt">>}, ++ body_end, ++ {headers, ++ [{"content-disposition", ++ {"form-data", [{"name", "success_action_status"}]}}]}, ++ {body, <<"201">>}, ++ body_end, ++ {headers, ++ [{"content-disposition", ++ {"form-data", [{"name", "file"}, {"filename", "hello.txt"}]}}, ++ {"content-type", {"application/octet-stream", []}}]}, ++ {body, Chunk}, ++ body_end, ++ {headers, ++ [{"content-disposition", ++ {"form-data", [{"name", "Upload"}]}}]}, ++ {body, <<"Submit Query">>}, ++ body_end, ++ eof], ++ TestCallback = fun (Next) -> test_callback(Next, Expect) end, ++ ServerFun = fun (Socket) -> ++ ok = mochiweb_socket:send(Socket, BinContent), ++ exit(normal) ++ end, ++ ClientFun = fun (Socket) -> ++ Req = fake_request(Socket, ContentType, ++ byte_size(BinContent)), ++ Res = parse_multipart_request(Req, TestCallback), ++ {0, <<>>, ok} = Res, ++ ok ++ end, ++ ok = with_socket_server(plain, ServerFun, ClientFun), ++ ok. + -endif. +diff -wbBur apache-couchdb-1.2.1/src/mochiweb/mochiweb_request.erl apache-couchdb-1.2.1.q/src/mochiweb/mochiweb_request.erl +--- apache-couchdb-1.2.1/src/mochiweb/mochiweb_request.erl 2012-12-21 01:24:07.000000000 +0400 ++++ apache-couchdb-1.2.1.q/src/mochiweb/mochiweb_request.erl 2013-03-22 15:26:58.000000000 +0400 +@@ -3,7 +3,7 @@ + + %% @doc MochiWeb HTTP Request abstraction. + +--module(mochiweb_request, [Socket, Method, RawPath, Version, Headers]). ++-module(mochiweb_request). + -author('bob@mochimedia.com'). + + -include_lib("kernel/include/file.hrl"). +@@ -11,17 +11,18 @@ + + -define(QUIP, "Any of you quaids got a smint?"). + +--export([get_header_value/1, get_primary_header_value/1, get/1, dump/0]). +--export([send/1, recv/1, recv/2, recv_body/0, recv_body/1, stream_body/3]). +--export([start_response/1, start_response_length/1, start_raw_response/1]). +--export([respond/1, ok/1]). +--export([not_found/0, not_found/1]). +--export([parse_post/0, parse_qs/0]). +--export([should_close/0, cleanup/0]). +--export([parse_cookie/0, get_cookie_value/1]). +--export([serve_file/2, serve_file/3]). +--export([accepted_encodings/1]). +--export([accepts_content_type/1]). ++-export([new/5]). ++-export([get_header_value/2, get_primary_header_value/2, get_combined_header_value/2, get/2, dump/1]). ++-export([send/2, recv/2, recv/3, recv_body/1, recv_body/2, stream_body/4]). ++-export([start_response/2, start_response_length/2, start_raw_response/2]). ++-export([respond/2, ok/2]). ++-export([not_found/1, not_found/2]). ++-export([parse_post/1, parse_qs/1]). ++-export([should_close/1, cleanup/1]). ++-export([parse_cookie/1, get_cookie_value/2]). ++-export([serve_file/3, serve_file/4]). ++-export([accepted_encodings/2]). ++-export([accepts_content_type/2, accepted_content_types/2]). + + -define(SAVE_QS, mochiweb_request_qs). + -define(SAVE_PATH, mochiweb_request_path). +@@ -32,11 +33,10 @@ + -define(SAVE_COOKIE, mochiweb_request_cookie). + -define(SAVE_FORCE_CLOSE, mochiweb_request_force_close). + +-%% @type iolist() = [iolist() | binary() | char()]. +-%% @type iodata() = binary() | iolist(). + %% @type key() = atom() | string() | binary() + %% @type value() = atom() | string() | binary() | integer() + %% @type headers(). A mochiweb_headers structure. ++%% @type request(). A mochiweb_request parameterized module instance. + %% @type response(). A mochiweb_response parameterized module instance. + %% @type ioheaders() = headers() | [{key(), value()}]. + +@@ -46,50 +46,58 @@ + % Maximum recv_body() length of 1MB + -define(MAX_RECV_BODY, (1024*1024)). + +-%% @spec get_header_value(K) -> undefined | Value ++%% @spec new(Socket, Method, RawPath, Version, headers()) -> request() ++%% @doc Create a new request instance. ++new(Socket, Method, RawPath, Version, Headers) -> ++ {?MODULE, [Socket, Method, RawPath, Version, Headers]}. ++ ++%% @spec get_header_value(K, request()) -> undefined | Value + %% @doc Get the value of a given request header. +-get_header_value(K) -> ++get_header_value(K, {?MODULE, [_Socket, _Method, _RawPath, _Version, Headers]}) -> + mochiweb_headers:get_value(K, Headers). + +-get_primary_header_value(K) -> ++get_primary_header_value(K, {?MODULE, [_Socket, _Method, _RawPath, _Version, Headers]}) -> + mochiweb_headers:get_primary_value(K, Headers). + ++get_combined_header_value(K, {?MODULE, [_Socket, _Method, _RawPath, _Version, Headers]}) -> ++ mochiweb_headers:get_combined_value(K, Headers). ++ + %% @type field() = socket | scheme | method | raw_path | version | headers | peer | path | body_length | range + +-%% @spec get(field()) -> term() ++%% @spec get(field(), request()) -> term() + %% @doc Return the internal representation of the given field. If + %% socket is requested on a HTTPS connection, then + %% an ssl socket will be returned as {ssl, SslSocket}. + %% You can use SslSocket with the ssl + %% application, eg: ssl:peercert(SslSocket). +-get(socket) -> ++get(socket, {?MODULE, [Socket, _Method, _RawPath, _Version, _Headers]}) -> + Socket; +-get(scheme) -> ++get(scheme, {?MODULE, [Socket, _Method, _RawPath, _Version, _Headers]}) -> + case mochiweb_socket:type(Socket) of + plain -> + http; + ssl -> + https + end; +-get(method) -> ++get(method, {?MODULE, [_Socket, Method, _RawPath, _Version, _Headers]}) -> + Method; +-get(raw_path) -> ++get(raw_path, {?MODULE, [_Socket, _Method, RawPath, _Version, _Headers]}) -> + RawPath; +-get(version) -> ++get(version, {?MODULE, [_Socket, _Method, _RawPath, Version, _Headers]}) -> + Version; +-get(headers) -> ++get(headers, {?MODULE, [_Socket, _Method, _RawPath, _Version, Headers]}) -> + Headers; +-get(peer) -> ++get(peer, {?MODULE, [Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> + case mochiweb_socket:peername(Socket) of + {ok, {Addr={10, _, _, _}, _Port}} -> +- case get_header_value("x-forwarded-for") of ++ case get_header_value("x-forwarded-for", THIS) of + undefined -> + inet_parse:ntoa(Addr); + Hosts -> + string:strip(lists:last(string:tokens(Hosts, ","))) + end; + {ok, {{127, 0, 0, 1}, _Port}} -> +- case get_header_value("x-forwarded-for") of ++ case get_header_value("x-forwarded-for", THIS) of + undefined -> + "127.0.0.1"; + Hosts -> +@@ -100,7 +108,7 @@ + {error, enotconn} -> + exit(normal) + end; +-get(path) -> ++get(path, {?MODULE, [_Socket, _Method, RawPath, _Version, _Headers]}) -> + case erlang:get(?SAVE_PATH) of + undefined -> + {Path0, _, _} = mochiweb_util:urlsplit_path(RawPath), +@@ -110,35 +118,35 @@ + Cached -> + Cached + end; +-get(body_length) -> ++get(body_length, {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> + case erlang:get(?SAVE_BODY_LENGTH) of + undefined -> +- BodyLength = body_length(), ++ BodyLength = body_length(THIS), + put(?SAVE_BODY_LENGTH, {cached, BodyLength}), + BodyLength; + {cached, Cached} -> + Cached + end; +-get(range) -> +- case get_header_value(range) of ++get(range, {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> ++ case get_header_value(range, THIS) of + undefined -> + undefined; + RawRange -> + mochiweb_http:parse_range_request(RawRange) + end. + +-%% @spec dump() -> {mochiweb_request, [{atom(), term()}]} ++%% @spec dump(request()) -> {mochiweb_request, [{atom(), term()}]} + %% @doc Dump the internal representation to a "human readable" set of terms + %% for debugging/inspection purposes. +-dump() -> ++dump({?MODULE, [_Socket, Method, RawPath, Version, Headers]}) -> + {?MODULE, [{method, Method}, + {version, Version}, + {raw_path, RawPath}, + {headers, mochiweb_headers:to_list(Headers)}]}. + +-%% @spec send(iodata()) -> ok ++%% @spec send(iodata(), request()) -> ok + %% @doc Send data over the socket. +-send(Data) -> ++send(Data, {?MODULE, [Socket, _Method, _RawPath, _Version, _Headers]}) -> + case mochiweb_socket:send(Socket, Data) of + ok -> + ok; +@@ -146,16 +154,16 @@ + exit(normal) + end. + +-%% @spec recv(integer()) -> binary() ++%% @spec recv(integer(), request()) -> binary() + %% @doc Receive Length bytes from the client as a binary, with the default + %% idle timeout. +-recv(Length) -> +- recv(Length, ?IDLE_TIMEOUT). ++recv(Length, {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> ++ recv(Length, ?IDLE_TIMEOUT, THIS). + +-%% @spec recv(integer(), integer()) -> binary() ++%% @spec recv(integer(), integer(), request()) -> binary() + %% @doc Receive Length bytes from the client as a binary, with the given + %% Timeout in msec. +-recv(Length, Timeout) -> ++recv(Length, Timeout, {?MODULE, [Socket, _Method, _RawPath, _Version, _Headers]}) -> + case mochiweb_socket:recv(Socket, Length, Timeout) of + {ok, Data} -> + put(?SAVE_RECV, true), +@@ -164,12 +172,12 @@ + exit(normal) + end. + +-%% @spec body_length() -> undefined | chunked | unknown_transfer_encoding | integer() ++%% @spec body_length(request()) -> undefined | chunked | unknown_transfer_encoding | integer() + %% @doc Infer body length from transfer-encoding and content-length headers. +-body_length() -> +- case get_header_value("transfer-encoding") of ++body_length({?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> ++ case get_header_value("transfer-encoding", THIS) of + undefined -> +- case get_header_value("content-length") of ++ case get_combined_header_value("content-length", THIS) of + undefined -> + undefined; + Length -> +@@ -182,16 +190,16 @@ + end. + + +-%% @spec recv_body() -> binary() ++%% @spec recv_body(request()) -> binary() + %% @doc Receive the body of the HTTP request (defined by Content-Length). + %% Will only receive up to the default max-body length of 1MB. +-recv_body() -> +- recv_body(?MAX_RECV_BODY). ++recv_body({?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> ++ recv_body(?MAX_RECV_BODY, THIS). + +-%% @spec recv_body(integer()) -> binary() ++%% @spec recv_body(integer(), request()) -> binary() + %% @doc Receive the body of the HTTP request (defined by Content-Length). + %% Will receive up to MaxBody bytes. +-recv_body(MaxBody) -> ++recv_body(MaxBody, {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> + case erlang:get(?SAVE_BODY) of + undefined -> + % we could use a sane constant for max chunk size +@@ -205,17 +213,18 @@ + true -> + {NewLength, [Bin | BinAcc]} + end +- end, {0, []}, MaxBody), ++ end, {0, []}, MaxBody, THIS), + put(?SAVE_BODY, Body), + Body; + Cached -> Cached + end. + +-stream_body(MaxChunkSize, ChunkFun, FunState) -> +- stream_body(MaxChunkSize, ChunkFun, FunState, undefined). ++stream_body(MaxChunkSize, ChunkFun, FunState, {?MODULE,[_Socket,_Method,_RawPath,_Version,_Headers]}=THIS) -> ++ stream_body(MaxChunkSize, ChunkFun, FunState, undefined, THIS). + +-stream_body(MaxChunkSize, ChunkFun, FunState, MaxBodyLength) -> +- Expect = case get_header_value("expect") of ++stream_body(MaxChunkSize, ChunkFun, FunState, MaxBodyLength, ++ {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> ++ Expect = case get_header_value("expect", THIS) of + undefined -> + undefined; + Value when is_list(Value) -> +@@ -223,11 +232,12 @@ + end, + case Expect of + "100-continue" -> +- start_raw_response({100, gb_trees:empty()}); ++ _ = start_raw_response({100, gb_trees:empty()}, THIS), ++ ok; + _Else -> + ok + end, +- case body_length() of ++ case body_length(THIS) of + undefined -> + undefined; + {unknown_transfer_encoding, Unknown} -> +@@ -236,7 +246,7 @@ + % In this case the MaxBody is actually used to + % determine the maximum allowed size of a single + % chunk. +- stream_chunked_body(MaxChunkSize, ChunkFun, FunState); ++ stream_chunked_body(MaxChunkSize, ChunkFun, FunState, THIS); + 0 -> + <<>>; + Length when is_integer(Length) -> +@@ -244,62 +254,64 @@ + MaxBodyLength when is_integer(MaxBodyLength), MaxBodyLength < Length -> + exit({body_too_large, content_length}); + _ -> +- stream_unchunked_body(Length, ChunkFun, FunState) +- end; +- Length -> +- exit({length_not_integer, Length}) ++ stream_unchunked_body(Length, ChunkFun, FunState, THIS) ++ end + end. + + +-%% @spec start_response({integer(), ioheaders()}) -> response() ++%% @spec start_response({integer(), ioheaders()}, request()) -> response() + %% @doc Start the HTTP response by sending the Code HTTP response and + %% ResponseHeaders. The server will set header defaults such as Server + %% and Date if not present in ResponseHeaders. +-start_response({Code, ResponseHeaders}) -> ++start_response({Code, ResponseHeaders}, {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> + HResponse = mochiweb_headers:make(ResponseHeaders), + HResponse1 = mochiweb_headers:default_from_list(server_headers(), + HResponse), +- start_raw_response({Code, HResponse1}). ++ start_raw_response({Code, HResponse1}, THIS). + +-%% @spec start_raw_response({integer(), headers()}) -> response() ++%% @spec start_raw_response({integer(), headers()}, request()) -> response() + %% @doc Start the HTTP response by sending the Code HTTP response and + %% ResponseHeaders. +-start_raw_response({Code, ResponseHeaders}) -> ++start_raw_response({Code, ResponseHeaders}, {?MODULE, [_Socket, _Method, _RawPath, Version, _Headers]}=THIS) -> + F = fun ({K, V}, Acc) -> + [mochiweb_util:make_io(K), <<": ">>, V, <<"\r\n">> | Acc] + end, + End = lists:foldl(F, [<<"\r\n">>], + mochiweb_headers:to_list(ResponseHeaders)), +- send([make_version(Version), make_code(Code), <<"\r\n">> | End]), ++ send([make_version(Version), make_code(Code), <<"\r\n">> | End], THIS), + mochiweb:new_response({THIS, Code, ResponseHeaders}). + + +-%% @spec start_response_length({integer(), ioheaders(), integer()}) -> response() ++%% @spec start_response_length({integer(), ioheaders(), integer()}, request()) -> response() + %% @doc Start the HTTP response by sending the Code HTTP response and + %% ResponseHeaders including a Content-Length of Length. The server + %% will set header defaults such as Server + %% and Date if not present in ResponseHeaders. +-start_response_length({Code, ResponseHeaders, Length}) -> ++start_response_length({Code, ResponseHeaders, Length}, ++ {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> + HResponse = mochiweb_headers:make(ResponseHeaders), + HResponse1 = mochiweb_headers:enter("Content-Length", Length, HResponse), +- start_response({Code, HResponse1}). ++ start_response({Code, HResponse1}, THIS). + +-%% @spec respond({integer(), ioheaders(), iodata() | chunked | {file, IoDevice}}) -> response() ++%% @spec respond({integer(), ioheaders(), iodata() | chunked | {file, IoDevice}}, request()) -> response() + %% @doc Start the HTTP response with start_response, and send Body to the + %% client (if the get(method) /= 'HEAD'). The Content-Length header + %% will be set by the Body length, and the server will insert header + %% defaults. +-respond({Code, ResponseHeaders, {file, IoDevice}}) -> ++respond({Code, ResponseHeaders, {file, IoDevice}}, ++ {?MODULE, [_Socket, Method, _RawPath, _Version, _Headers]}=THIS) -> + Length = mochiweb_io:iodevice_size(IoDevice), +- Response = start_response_length({Code, ResponseHeaders, Length}), ++ Response = start_response_length({Code, ResponseHeaders, Length}, THIS), + case Method of + 'HEAD' -> + ok; + _ -> +- mochiweb_io:iodevice_stream(fun send/1, IoDevice) ++ mochiweb_io:iodevice_stream( ++ fun (Body) -> send(Body, THIS) end, ++ IoDevice) + end, + Response; +-respond({Code, ResponseHeaders, chunked}) -> ++respond({Code, ResponseHeaders, chunked}, {?MODULE, [_Socket, Method, _RawPath, Version, _Headers]}=THIS) -> + HResponse = mochiweb_headers:make(ResponseHeaders), + HResponse1 = case Method of + 'HEAD' -> +@@ -320,35 +332,35 @@ + put(?SAVE_FORCE_CLOSE, true), + HResponse + end, +- start_response({Code, HResponse1}); +-respond({Code, ResponseHeaders, Body}) -> +- Response = start_response_length({Code, ResponseHeaders, iolist_size(Body)}), ++ start_response({Code, HResponse1}, THIS); ++respond({Code, ResponseHeaders, Body}, {?MODULE, [_Socket, Method, _RawPath, _Version, _Headers]}=THIS) -> ++ Response = start_response_length({Code, ResponseHeaders, iolist_size(Body)}, THIS), + case Method of + 'HEAD' -> + ok; + _ -> +- send(Body) ++ send(Body, THIS) + end, + Response. + +-%% @spec not_found() -> response() ++%% @spec not_found(request()) -> response() + %% @doc Alias for not_found([]). +-not_found() -> +- not_found([]). ++not_found({?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> ++ not_found([], THIS). + +-%% @spec not_found(ExtraHeaders) -> response() ++%% @spec not_found(ExtraHeaders, request()) -> response() + %% @doc Alias for respond({404, [{"Content-Type", "text/plain"} + %% | ExtraHeaders], <<"Not found.">>}). +-not_found(ExtraHeaders) -> ++not_found(ExtraHeaders, {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> + respond({404, [{"Content-Type", "text/plain"} | ExtraHeaders], +- <<"Not found.">>}). ++ <<"Not found.">>}, THIS). + +-%% @spec ok({value(), iodata()} | {value(), ioheaders(), iodata() | {file, IoDevice}}) -> ++%% @spec ok({value(), iodata()} | {value(), ioheaders(), iodata() | {file, IoDevice}}, request()) -> + %% response() + %% @doc respond({200, [{"Content-Type", ContentType} | Headers], Body}). +-ok({ContentType, Body}) -> +- ok({ContentType, [], Body}); +-ok({ContentType, ResponseHeaders, Body}) -> ++ok({ContentType, Body}, {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> ++ ok({ContentType, [], Body}, THIS); ++ok({ContentType, ResponseHeaders, Body}, {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> + HResponse = mochiweb_headers:make(ResponseHeaders), + case THIS:get(range) of + X when (X =:= undefined orelse X =:= fail) orelse Body =:= chunked -> +@@ -357,7 +369,7 @@ + %% full response. + HResponse1 = mochiweb_headers:enter("Content-Type", ContentType, + HResponse), +- respond({200, HResponse1, Body}); ++ respond({200, HResponse1, Body}, THIS); + Ranges -> + {PartList, Size} = range_parts(Body, Ranges), + case PartList of +@@ -366,7 +378,7 @@ + ContentType, + HResponse), + %% could be 416, for now we'll just return 200 +- respond({200, HResponse1, Body}); ++ respond({200, HResponse1, Body}, THIS); + PartList -> + {RangeHeaders, RangeBody} = + mochiweb_multipart:parts_to_body(PartList, ContentType, Size), +@@ -374,46 +386,50 @@ + [{"Accept-Ranges", "bytes"} | + RangeHeaders], + HResponse), +- respond({206, HResponse1, RangeBody}) ++ respond({206, HResponse1, RangeBody}, THIS) + end + end. + +-%% @spec should_close() -> bool() ++%% @spec should_close(request()) -> bool() + %% @doc Return true if the connection must be closed. If false, using + %% Keep-Alive should be safe. +-should_close() -> ++should_close({?MODULE, [_Socket, _Method, _RawPath, Version, _Headers]}=THIS) -> + ForceClose = erlang:get(?SAVE_FORCE_CLOSE) =/= undefined, + DidNotRecv = erlang:get(?SAVE_RECV) =:= undefined, + ForceClose orelse Version < {1, 0} + %% Connection: close +- orelse get_header_value("connection") =:= "close" ++ orelse is_close(get_header_value("connection", THIS)) + %% HTTP 1.0 requires Connection: Keep-Alive + orelse (Version =:= {1, 0} +- andalso get_header_value("connection") =/= "Keep-Alive") ++ andalso get_header_value("connection", THIS) =/= "Keep-Alive") + %% unread data left on the socket, can't safely continue + orelse (DidNotRecv +- andalso get_header_value("content-length") =/= undefined +- andalso list_to_integer(get_header_value("content-length")) > 0) ++ andalso get_combined_header_value("content-length", THIS) =/= undefined ++ andalso list_to_integer(get_combined_header_value("content-length", THIS)) > 0) + orelse (DidNotRecv +- andalso get_header_value("transfer-encoding") =:= "chunked"). ++ andalso get_header_value("transfer-encoding", THIS) =:= "chunked"). ++ ++is_close("close") -> ++ true; ++is_close(S=[_C, _L, _O, _S, _E]) -> ++ string:to_lower(S) =:= "close"; ++is_close(_) -> ++ false. + +-%% @spec cleanup() -> ok ++%% @spec cleanup(request()) -> ok + %% @doc Clean up any junk in the process dictionary, required before continuing + %% a Keep-Alive request. +-cleanup() -> +- [erase(K) || K <- [?SAVE_QS, +- ?SAVE_PATH, +- ?SAVE_RECV, +- ?SAVE_BODY, +- ?SAVE_BODY_LENGTH, +- ?SAVE_POST, +- ?SAVE_COOKIE, +- ?SAVE_FORCE_CLOSE]], ++cleanup({?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}) -> ++ L = [?SAVE_QS, ?SAVE_PATH, ?SAVE_RECV, ?SAVE_BODY, ?SAVE_BODY_LENGTH, ++ ?SAVE_POST, ?SAVE_COOKIE, ?SAVE_FORCE_CLOSE], ++ lists:foreach(fun(K) -> ++ erase(K) ++ end, L), + ok. + +-%% @spec parse_qs() -> [{Key::string(), Value::string()}] ++%% @spec parse_qs(request()) -> [{Key::string(), Value::string()}] + %% @doc Parse the query string of the URL. +-parse_qs() -> ++parse_qs({?MODULE, [_Socket, _Method, RawPath, _Version, _Headers]}) -> + case erlang:get(?SAVE_QS) of + undefined -> + {_, QueryString, _} = mochiweb_util:urlsplit_path(RawPath), +@@ -424,17 +440,17 @@ + Cached + end. + +-%% @spec get_cookie_value(Key::string) -> string() | undefined ++%% @spec get_cookie_value(Key::string, request()) -> string() | undefined + %% @doc Get the value of the given cookie. +-get_cookie_value(Key) -> +- proplists:get_value(Key, parse_cookie()). ++get_cookie_value(Key, {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> ++ proplists:get_value(Key, parse_cookie(THIS)). + +-%% @spec parse_cookie() -> [{Key::string(), Value::string()}] ++%% @spec parse_cookie(request()) -> [{Key::string(), Value::string()}] + %% @doc Parse the cookie header. +-parse_cookie() -> ++parse_cookie({?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> + case erlang:get(?SAVE_COOKIE) of + undefined -> +- Cookies = case get_header_value("cookie") of ++ Cookies = case get_header_value("cookie", THIS) of + undefined -> + []; + Value -> +@@ -446,17 +462,17 @@ + Cached + end. + +-%% @spec parse_post() -> [{Key::string(), Value::string()}] ++%% @spec parse_post(request()) -> [{Key::string(), Value::string()}] + %% @doc Parse an application/x-www-form-urlencoded form POST. This + %% has the side-effect of calling recv_body(). +-parse_post() -> ++parse_post({?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> + case erlang:get(?SAVE_POST) of + undefined -> +- Parsed = case recv_body() of ++ Parsed = case recv_body(THIS) of + undefined -> + []; + Binary -> +- case get_primary_header_value("content-type") of ++ case get_primary_header_value("content-type",THIS) of + "application/x-www-form-urlencoded" ++ _ -> + mochiweb_util:parse_qs(Binary); + _ -> +@@ -469,41 +485,43 @@ + Cached + end. + +-%% @spec stream_chunked_body(integer(), fun(), term()) -> term() ++%% @spec stream_chunked_body(integer(), fun(), term(), request()) -> term() + %% @doc The function is called for each chunk. + %% Used internally by read_chunked_body. +-stream_chunked_body(MaxChunkSize, Fun, FunState) -> +- case read_chunk_length() of ++stream_chunked_body(MaxChunkSize, Fun, FunState, ++ {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> ++ case read_chunk_length(THIS) of + 0 -> +- Fun({0, read_chunk(0)}, FunState); ++ Fun({0, read_chunk(0, THIS)}, FunState); + Length when Length > MaxChunkSize -> +- NewState = read_sub_chunks(Length, MaxChunkSize, Fun, FunState), +- stream_chunked_body(MaxChunkSize, Fun, NewState); ++ NewState = read_sub_chunks(Length, MaxChunkSize, Fun, FunState, THIS), ++ stream_chunked_body(MaxChunkSize, Fun, NewState, THIS); + Length -> +- NewState = Fun({Length, read_chunk(Length)}, FunState), +- stream_chunked_body(MaxChunkSize, Fun, NewState) ++ NewState = Fun({Length, read_chunk(Length, THIS)}, FunState), ++ stream_chunked_body(MaxChunkSize, Fun, NewState, THIS) + end. + +-stream_unchunked_body(0, Fun, FunState) -> ++stream_unchunked_body(0, Fun, FunState, {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}) -> + Fun({0, <<>>}, FunState); +-stream_unchunked_body(Length, Fun, FunState) when Length > 0 -> ++stream_unchunked_body(Length, Fun, FunState, ++ {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) when Length > 0 -> + PktSize = case Length > ?RECBUF_SIZE of + true -> + ?RECBUF_SIZE; + false -> + Length + end, +- Bin = recv(PktSize), ++ Bin = recv(PktSize, THIS), + NewState = Fun({PktSize, Bin}, FunState), +- stream_unchunked_body(Length - PktSize, Fun, NewState). ++ stream_unchunked_body(Length - PktSize, Fun, NewState, THIS). + +-%% @spec read_chunk_length() -> integer() ++%% @spec read_chunk_length(request()) -> integer() + %% @doc Read the length of the next HTTP chunk. +-read_chunk_length() -> +- mochiweb_socket:setopts(Socket, [{packet, line}]), ++read_chunk_length({?MODULE, [Socket, _Method, _RawPath, _Version, _Headers]}) -> ++ ok = mochiweb_socket:setopts(Socket, [{packet, line}]), + case mochiweb_socket:recv(Socket, 0, ?IDLE_TIMEOUT) of + {ok, Header} -> +- mochiweb_socket:setopts(Socket, [{packet, raw}]), ++ ok = mochiweb_socket:setopts(Socket, [{packet, raw}]), + Splitter = fun (C) -> + C =/= $\r andalso C =/= $\n andalso C =/= $ + end, +@@ -513,11 +531,11 @@ + exit(normal) + end. + +-%% @spec read_chunk(integer()) -> Chunk::binary() | [Footer::binary()] ++%% @spec read_chunk(integer(), request()) -> Chunk::binary() | [Footer::binary()] + %% @doc Read in a HTTP chunk of the given length. If Length is 0, then read the + %% HTTP footers (as a list of binaries, since they're nominal). +-read_chunk(0) -> +- mochiweb_socket:setopts(Socket, [{packet, line}]), ++read_chunk(0, {?MODULE, [Socket, _Method, _RawPath, _Version, _Headers]}) -> ++ ok = mochiweb_socket:setopts(Socket, [{packet, line}]), + F = fun (F1, Acc) -> + case mochiweb_socket:recv(Socket, 0, ?IDLE_TIMEOUT) of + {ok, <<"\r\n">>} -> +@@ -529,10 +547,10 @@ + end + end, + Footers = F(F, []), +- mochiweb_socket:setopts(Socket, [{packet, raw}]), ++ ok = mochiweb_socket:setopts(Socket, [{packet, raw}]), + put(?SAVE_RECV, true), + Footers; +-read_chunk(Length) -> ++read_chunk(Length, {?MODULE, [Socket, _Method, _RawPath, _Version, _Headers]}) -> + case mochiweb_socket:recv(Socket, 2 + Length, ?IDLE_TIMEOUT) of + {ok, <>} -> + Chunk; +@@ -540,32 +558,34 @@ + exit(normal) + end. + +-read_sub_chunks(Length, MaxChunkSize, Fun, FunState) when Length > MaxChunkSize -> +- Bin = recv(MaxChunkSize), ++read_sub_chunks(Length, MaxChunkSize, Fun, FunState, ++ {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) when Length > MaxChunkSize -> ++ Bin = recv(MaxChunkSize, THIS), + NewState = Fun({size(Bin), Bin}, FunState), +- read_sub_chunks(Length - MaxChunkSize, MaxChunkSize, Fun, NewState); ++ read_sub_chunks(Length - MaxChunkSize, MaxChunkSize, Fun, NewState, THIS); + +-read_sub_chunks(Length, _MaxChunkSize, Fun, FunState) -> +- Fun({Length, read_chunk(Length)}, FunState). ++read_sub_chunks(Length, _MaxChunkSize, Fun, FunState, ++ {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> ++ Fun({Length, read_chunk(Length, THIS)}, FunState). + +-%% @spec serve_file(Path, DocRoot) -> Response ++%% @spec serve_file(Path, DocRoot, request()) -> Response + %% @doc Serve a file relative to DocRoot. +-serve_file(Path, DocRoot) -> +- serve_file(Path, DocRoot, []). ++serve_file(Path, DocRoot, {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> ++ serve_file(Path, DocRoot, [], THIS). + +-%% @spec serve_file(Path, DocRoot, ExtraHeaders) -> Response ++%% @spec serve_file(Path, DocRoot, ExtraHeaders, request()) -> Response + %% @doc Serve a file relative to DocRoot. +-serve_file(Path, DocRoot, ExtraHeaders) -> ++serve_file(Path, DocRoot, ExtraHeaders, {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> + case mochiweb_util:safe_relative_path(Path) of + undefined -> +- not_found(ExtraHeaders); ++ not_found(ExtraHeaders, THIS); + RelPath -> + FullPath = filename:join([DocRoot, RelPath]), + case filelib:is_dir(FullPath) of + true -> +- maybe_redirect(RelPath, FullPath, ExtraHeaders); ++ maybe_redirect(RelPath, FullPath, ExtraHeaders, THIS); + false -> +- maybe_serve_file(FullPath, ExtraHeaders) ++ maybe_serve_file(FullPath, ExtraHeaders, THIS) + end + end. + +@@ -575,13 +595,14 @@ + directory_index(FullPath) -> + filename:join([FullPath, "index.html"]). + +-maybe_redirect([], FullPath, ExtraHeaders) -> +- maybe_serve_file(directory_index(FullPath), ExtraHeaders); ++maybe_redirect([], FullPath, ExtraHeaders, {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> ++ maybe_serve_file(directory_index(FullPath), ExtraHeaders, THIS); + +-maybe_redirect(RelPath, FullPath, ExtraHeaders) -> ++maybe_redirect(RelPath, FullPath, ExtraHeaders, ++ {?MODULE, [_Socket, _Method, _RawPath, _Version, Headers]}=THIS) -> + case string:right(RelPath, 1) of + "/" -> +- maybe_serve_file(directory_index(FullPath), ExtraHeaders); ++ maybe_serve_file(directory_index(FullPath), ExtraHeaders, THIS); + _ -> + Host = mochiweb_headers:get_value("host", Headers), + Location = "http://" ++ Host ++ "/" ++ RelPath ++ "/", +@@ -596,16 +617,16 @@ + "

The document has moved >, + Bottom = <<">here.

\n">>, + Body = <>, +- respond({301, MoreHeaders, Body}) ++ respond({301, MoreHeaders, Body}, THIS) + end. + +-maybe_serve_file(File, ExtraHeaders) -> ++maybe_serve_file(File, ExtraHeaders, {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> + case file:read_file_info(File) of + {ok, FileInfo} -> + LastModified = httpd_util:rfc1123_date(FileInfo#file_info.mtime), +- case get_header_value("if-modified-since") of ++ case get_header_value("if-modified-since", THIS) of + LastModified -> +- respond({304, ExtraHeaders, ""}); ++ respond({304, ExtraHeaders, ""}, THIS); + _ -> + case file:open(File, [raw, binary]) of + {ok, IoDevice} -> +@@ -613,15 +634,15 @@ + Res = ok({ContentType, + [{"last-modified", LastModified} + | ExtraHeaders], +- {file, IoDevice}}), +- file:close(IoDevice), ++ {file, IoDevice}}, THIS), ++ ok = file:close(IoDevice), + Res; + _ -> +- not_found(ExtraHeaders) ++ not_found(ExtraHeaders, THIS) + end + end; + {error, _} -> +- not_found(ExtraHeaders) ++ not_found(ExtraHeaders, THIS) + end. + + server_headers() -> +@@ -669,7 +690,7 @@ + end, + {lists:foldr(F, [], Ranges), Size}. + +-%% @spec accepted_encodings([encoding()]) -> [encoding()] | bad_accept_encoding_value ++%% @spec accepted_encodings([encoding()], request()) -> [encoding()] | bad_accept_encoding_value + %% @type encoding() = string(). + %% + %% @doc Returns a list of encodings accepted by a request. Encodings that are +@@ -693,8 +714,8 @@ + %% accepted_encodings(["gzip", "deflate", "identity"]) -> + %% ["deflate", "gzip", "identity"] + %% +-accepted_encodings(SupportedEncodings) -> +- AcceptEncodingHeader = case get_header_value("Accept-Encoding") of ++accepted_encodings(SupportedEncodings, {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> ++ AcceptEncodingHeader = case get_header_value("Accept-Encoding", THIS) of + undefined -> + ""; + Value -> +@@ -709,7 +730,7 @@ + ) + end. + +-%% @spec accepts_content_type(string() | binary()) -> boolean() | bad_accept_header ++%% @spec accepts_content_type(string() | binary(), request()) -> boolean() | bad_accept_header + %% + %% @doc Determines whether a request accepts a given media type by analyzing its + %% "Accept" header. +@@ -731,16 +752,9 @@ + %% 5) For an "Accept" header with value "text/*; q=0.0, */*": + %% accepts_content_type("text/plain") -> false + %% +-accepts_content_type(ContentType) when is_binary(ContentType) -> +- accepts_content_type(binary_to_list(ContentType)); +-accepts_content_type(ContentType1) -> ++accepts_content_type(ContentType1, {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> + ContentType = re:replace(ContentType1, "\\s", "", [global, {return, list}]), +- AcceptHeader = case get_header_value("Accept") of +- undefined -> +- "*/*"; +- Value -> +- Value +- end, ++ AcceptHeader = accept_header(THIS), + case mochiweb_util:parse_qvalues(AcceptHeader) of + invalid_qvalue_string -> + bad_accept_header; +@@ -761,9 +775,83 @@ + (not lists:member({SuperType, 0.0}, QList)) + end. + ++%% @spec accepted_content_types([string() | binary()], request()) -> [string()] | bad_accept_header ++%% ++%% @doc Filters which of the given media types this request accepts. This filtering ++%% is performed by analyzing the "Accept" header. The returned list is sorted ++%% according to the preferences specified in the "Accept" header (higher Q values ++%% first). If two or more types have the same preference (Q value), they're order ++%% in the returned list is the same as they're order in the input list. ++%% ++%% Examples ++%% ++%% 1) For a missing "Accept" header: ++%% accepted_content_types(["text/html", "application/json"]) -> ++%% ["text/html", "application/json"] ++%% ++%% 2) For an "Accept" header with value "text/html, application/*": ++%% accepted_content_types(["application/json", "text/html"]) -> ++%% ["application/json", "text/html"] ++%% ++%% 3) For an "Accept" header with value "text/html, */*; q=0.0": ++%% accepted_content_types(["text/html", "application/json"]) -> ++%% ["text/html"] ++%% ++%% 4) For an "Accept" header with value "text/html; q=0.5, */*; q=0.1": ++%% accepts_content_types(["application/json", "text/html"]) -> ++%% ["text/html", "application/json"] ++%% ++accepted_content_types(Types1, {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> ++ Types = lists:map( ++ fun(T) -> re:replace(T, "\\s", "", [global, {return, list}]) end, ++ Types1), ++ AcceptHeader = accept_header(THIS), ++ case mochiweb_util:parse_qvalues(AcceptHeader) of ++ invalid_qvalue_string -> ++ bad_accept_header; ++ QList -> ++ TypesQ = lists:foldr( ++ fun(T, Acc) -> ++ case proplists:get_value(T, QList) of ++ undefined -> ++ [MainType, _SubType] = string:tokens(T, "/"), ++ case proplists:get_value(MainType ++ "/*", QList) of ++ undefined -> ++ case proplists:get_value("*/*", QList) of ++ Q when is_float(Q), Q > 0.0 -> ++ [{Q, T} | Acc]; ++ _ -> ++ Acc ++ end; ++ Q when Q > 0.0 -> ++ [{Q, T} | Acc]; ++ _ -> ++ Acc ++ end; ++ Q when Q > 0.0 -> ++ [{Q, T} | Acc]; ++ _ -> ++ Acc ++ end ++ end, ++ [], Types), ++ % Note: Stable sort. If 2 types have the same Q value we leave them in the ++ % same order as in the input list. ++ SortFun = fun({Q1, _}, {Q2, _}) -> Q1 >= Q2 end, ++ [Type || {_Q, Type} <- lists:sort(SortFun, TypesQ)] ++ end. ++ ++accept_header({?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> ++ case get_header_value("Accept", THIS) of ++ undefined -> ++ "*/*"; ++ Value -> ++ Value ++ end. ++ + %% + %% Tests + %% +--include_lib("eunit/include/eunit.hrl"). + -ifdef(TEST). ++-include_lib("eunit/include/eunit.hrl"). + -endif. +diff -wbBur apache-couchdb-1.2.1/src/mochiweb/mochiweb_request_tests.erl apache-couchdb-1.2.1.q/src/mochiweb/mochiweb_request_tests.erl +--- apache-couchdb-1.2.1/src/mochiweb/mochiweb_request_tests.erl 2012-12-21 01:24:07.000000000 +0400 ++++ apache-couchdb-1.2.1.q/src/mochiweb/mochiweb_request_tests.erl 2013-03-22 15:26:58.000000000 +0400 +@@ -1,12 +1,13 @@ + -module(mochiweb_request_tests). + +--include_lib("eunit/include/eunit.hrl"). + -ifdef(TEST). ++-include_lib("eunit/include/eunit.hrl"). + + accepts_content_type_test() -> + Req1 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1}, + mochiweb_headers:make([{"Accept", "multipart/related"}])), + ?assertEqual(true, Req1:accepts_content_type("multipart/related")), ++ ?assertEqual(true, Req1:accepts_content_type(<<"multipart/related">>)), + + Req2 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1}, + mochiweb_headers:make([{"Accept", "text/html"}])), +@@ -60,4 +61,122 @@ + mochiweb_headers:make([{"Accept", "text/html;level=1;q=0.1, text/html"}])), + ?assertEqual(true, Req14:accepts_content_type("text/html; level=1")). + ++accepted_encodings_test() -> ++ Req1 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1}, ++ mochiweb_headers:make([])), ++ ?assertEqual(["identity"], ++ Req1:accepted_encodings(["gzip", "identity"])), ++ ++ Req2 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1}, ++ mochiweb_headers:make([{"Accept-Encoding", "gzip, deflate"}])), ++ ?assertEqual(["gzip", "identity"], ++ Req2:accepted_encodings(["gzip", "identity"])), ++ ++ Req3 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1}, ++ mochiweb_headers:make([{"Accept-Encoding", "gzip;q=0.5, deflate"}])), ++ ?assertEqual(["deflate", "gzip", "identity"], ++ Req3:accepted_encodings(["gzip", "deflate", "identity"])), ++ ++ Req4 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1}, ++ mochiweb_headers:make([{"Accept-Encoding", "identity, *;q=0"}])), ++ ?assertEqual(["identity"], ++ Req4:accepted_encodings(["gzip", "deflate", "identity"])), ++ ++ Req5 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1}, ++ mochiweb_headers:make([{"Accept-Encoding", "gzip; q=0.1, *;q=0"}])), ++ ?assertEqual(["gzip"], ++ Req5:accepted_encodings(["gzip", "deflate", "identity"])), ++ ++ Req6 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1}, ++ mochiweb_headers:make([{"Accept-Encoding", "gzip; q=, *;q=0"}])), ++ ?assertEqual(bad_accept_encoding_value, ++ Req6:accepted_encodings(["gzip", "deflate", "identity"])), ++ ++ Req7 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1}, ++ mochiweb_headers:make([{"Accept-Encoding", "gzip;q=2.0, *;q=0"}])), ++ ?assertEqual(bad_accept_encoding_value, ++ Req7:accepted_encodings(["gzip", "identity"])), ++ ++ Req8 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1}, ++ mochiweb_headers:make([{"Accept-Encoding", "deflate, *;q=0.0"}])), ++ ?assertEqual([], ++ Req8:accepted_encodings(["gzip", "identity"])). ++ ++accepted_content_types_test() -> ++ Req1 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1}, ++ mochiweb_headers:make([{"Accept", "text/html"}])), ++ ?assertEqual(["text/html"], ++ Req1:accepted_content_types(["text/html", "application/json"])), ++ ++ Req2 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1}, ++ mochiweb_headers:make([{"Accept", "text/html, */*;q=0"}])), ++ ?assertEqual(["text/html"], ++ Req2:accepted_content_types(["text/html", "application/json"])), ++ ++ Req3 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1}, ++ mochiweb_headers:make([{"Accept", "text/*, */*;q=0"}])), ++ ?assertEqual(["text/html"], ++ Req3:accepted_content_types(["text/html", "application/json"])), ++ ++ Req4 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1}, ++ mochiweb_headers:make([{"Accept", "text/*;q=0.8, */*;q=0.5"}])), ++ ?assertEqual(["text/html", "application/json"], ++ Req4:accepted_content_types(["application/json", "text/html"])), ++ ++ Req5 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1}, ++ mochiweb_headers:make([{"Accept", "text/*;q=0.8, */*;q=0.5"}])), ++ ?assertEqual(["text/html", "application/json"], ++ Req5:accepted_content_types(["text/html", "application/json"])), ++ ++ Req6 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1}, ++ mochiweb_headers:make([{"Accept", "text/*;q=0.5, */*;q=0.5"}])), ++ ?assertEqual(["application/json", "text/html"], ++ Req6:accepted_content_types(["application/json", "text/html"])), ++ ++ Req7 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1}, ++ mochiweb_headers:make( ++ [{"Accept", "text/html;q=0.5, application/json;q=0.5"}])), ++ ?assertEqual(["application/json", "text/html"], ++ Req7:accepted_content_types(["application/json", "text/html"])), ++ ++ Req8 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1}, ++ mochiweb_headers:make([{"Accept", "text/html"}])), ++ ?assertEqual([], ++ Req8:accepted_content_types(["application/json"])), ++ ++ Req9 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1}, ++ mochiweb_headers:make([{"Accept", "text/*;q=0.9, text/html;q=0.5, */*;q=0.7"}])), ++ ?assertEqual(["application/json", "text/html"], ++ Req9:accepted_content_types(["text/html", "application/json"])). ++ ++should_close_test() -> ++ F = fun (V, H) -> ++ (mochiweb_request:new( ++ nil, 'GET', "/", V, ++ mochiweb_headers:make(H) ++ )):should_close() ++ end, ++ ?assertEqual( ++ true, ++ F({1, 1}, [{"Connection", "close"}])), ++ ?assertEqual( ++ true, ++ F({1, 0}, [{"Connection", "close"}])), ++ ?assertEqual( ++ true, ++ F({1, 1}, [{"Connection", "ClOSe"}])), ++ ?assertEqual( ++ false, ++ F({1, 1}, [{"Connection", "closer"}])), ++ ?assertEqual( ++ false, ++ F({1, 1}, [])), ++ ?assertEqual( ++ true, ++ F({1, 0}, [])), ++ ?assertEqual( ++ false, ++ F({1, 0}, [{"Connection", "Keep-Alive"}])), ++ ok. ++ + -endif. +diff -wbBur apache-couchdb-1.2.1/src/mochiweb/mochiweb_response.erl apache-couchdb-1.2.1.q/src/mochiweb/mochiweb_response.erl +--- apache-couchdb-1.2.1/src/mochiweb/mochiweb_response.erl 2012-12-21 01:24:07.000000000 +0400 ++++ apache-couchdb-1.2.1.q/src/mochiweb/mochiweb_response.erl 2013-03-22 15:26:58.000000000 +0400 +@@ -3,39 +3,47 @@ + + %% @doc Response abstraction. + +--module(mochiweb_response, [Request, Code, Headers]). ++-module(mochiweb_response). + -author('bob@mochimedia.com'). + + -define(QUIP, "Any of you quaids got a smint?"). + +--export([get_header_value/1, get/1, dump/0]). +--export([send/1, write_chunk/1]). ++-export([new/3, get_header_value/2, get/2, dump/1]). ++-export([send/2, write_chunk/2]). + +-%% @spec get_header_value(string() | atom() | binary()) -> string() | undefined ++%% @type response(). A mochiweb_response parameterized module instance. ++ ++%% @spec new(Request, Code, Headers) -> response() ++%% @doc Create a new mochiweb_response instance. ++new(Request, Code, Headers) -> ++ {?MODULE, [Request, Code, Headers]}. ++ ++%% @spec get_header_value(string() | atom() | binary(), response()) -> ++%% string() | undefined + %% @doc Get the value of the given response header. +-get_header_value(K) -> ++get_header_value(K, {?MODULE, [_Request, _Code, Headers]}) -> + mochiweb_headers:get_value(K, Headers). + +-%% @spec get(request | code | headers) -> term() ++%% @spec get(request | code | headers, response()) -> term() + %% @doc Return the internal representation of the given field. +-get(request) -> ++get(request, {?MODULE, [Request, _Code, _Headers]}) -> + Request; +-get(code) -> ++get(code, {?MODULE, [_Request, Code, _Headers]}) -> + Code; +-get(headers) -> ++get(headers, {?MODULE, [_Request, _Code, Headers]}) -> + Headers. + +-%% @spec dump() -> {mochiweb_request, [{atom(), term()}]} ++%% @spec dump(response()) -> {mochiweb_request, [{atom(), term()}]} + %% @doc Dump the internal representation to a "human readable" set of terms + %% for debugging/inspection purposes. +-dump() -> ++dump({?MODULE, [Request, Code, Headers]}) -> + [{request, Request:dump()}, + {code, Code}, + {headers, mochiweb_headers:to_list(Headers)}]. + +-%% @spec send(iodata()) -> ok ++%% @spec send(iodata(), response()) -> ok + %% @doc Send data over the socket if the method is not HEAD. +-send(Data) -> ++send(Data, {?MODULE, [Request, _Code, _Headers]}) -> + case Request:get(method) of + 'HEAD' -> + ok; +@@ -43,22 +51,22 @@ + Request:send(Data) + end. + +-%% @spec write_chunk(iodata()) -> ok ++%% @spec write_chunk(iodata(), response()) -> ok + %% @doc Write a chunk of a HTTP chunked response. If Data is zero length, + %% then the chunked response will be finished. +-write_chunk(Data) -> ++write_chunk(Data, {?MODULE, [Request, _Code, _Headers]}=THIS) -> + case Request:get(version) of + Version when Version >= {1, 1} -> + Length = iolist_size(Data), +- send([io_lib:format("~.16b\r\n", [Length]), Data, <<"\r\n">>]); ++ send([io_lib:format("~.16b\r\n", [Length]), Data, <<"\r\n">>], THIS); + _ -> +- send(Data) ++ send(Data, THIS) + end. + + + %% + %% Tests + %% +--include_lib("eunit/include/eunit.hrl"). + -ifdef(TEST). ++-include_lib("eunit/include/eunit.hrl"). + -endif. +diff -wbBur apache-couchdb-1.2.1/src/mochiweb/mochiweb_socket_server.erl apache-couchdb-1.2.1.q/src/mochiweb/mochiweb_socket_server.erl +--- apache-couchdb-1.2.1/src/mochiweb/mochiweb_socket_server.erl 2012-12-21 01:24:07.000000000 +0400 ++++ apache-couchdb-1.2.1.q/src/mochiweb/mochiweb_socket_server.erl 2013-03-22 15:26:58.000000000 +0400 +@@ -9,7 +9,7 @@ + + -include("internal.hrl"). + +--export([start/1, stop/1]). ++-export([start/1, start_link/1, stop/1]). + -export([init/1, handle_call/3, handle_cast/2, terminate/2, code_change/3, + handle_info/2]). + -export([get/2, set/3]). +@@ -33,10 +33,22 @@ + + -define(is_old_state(State), not is_record(State, mochiweb_socket_server)). + +-start(State=#mochiweb_socket_server{}) -> +- start_server(State); ++start_link(Options) -> ++ start_server(start_link, parse_options(Options)). ++ + start(Options) -> +- start(parse_options(Options)). ++ case lists:keytake(link, 1, Options) of ++ {value, {_Key, false}, Options1} -> ++ start_server(start, parse_options(Options1)); ++ _ -> ++ %% TODO: https://github.com/mochi/mochiweb/issues/58 ++ %% [X] Phase 1: Add new APIs (Sep 2011) ++ %% [_] Phase 2: Add deprecation warning ++ %% [_] Phase 3: Change default to {link, false} and ignore link ++ %% [_] Phase 4: Add deprecation warning for {link, _} option ++ %% [_] Phase 5: Remove support for {link, _} option ++ start_link(Options) ++ end. + + get(Name, Property) -> + gen_server:call(Name, {get, Property}). +@@ -61,6 +73,8 @@ + + %% Internal API + ++parse_options(State=#mochiweb_socket_server{}) -> ++ State; + parse_options(Options) -> + parse_options(Options, #mochiweb_socket_server{}). + +@@ -116,22 +130,22 @@ + parse_options(Rest, State#mochiweb_socket_server{profile_fun=ProfileFun}). + + +-start_server(State=#mochiweb_socket_server{ssl=Ssl, name=Name}) -> +- case Ssl of +- true -> +- application:start(crypto), +- application:start(public_key), +- application:start(ssl); +- false -> +- void +- end, ++start_server(F, State=#mochiweb_socket_server{ssl=Ssl, name=Name}) -> ++ ok = prep_ssl(Ssl), + case Name of + undefined -> +- gen_server:start_link(?MODULE, State, []); ++ gen_server:F(?MODULE, State, []); + _ -> +- gen_server:start_link(Name, ?MODULE, State, []) ++ gen_server:F(Name, ?MODULE, State, []) + end. + ++prep_ssl(true) -> ++ ok = mochiweb:ensure_started(crypto), ++ ok = mochiweb:ensure_started(public_key), ++ ok = mochiweb:ensure_started(ssl); ++prep_ssl(false) -> ++ ok. ++ + ensure_int(N) when is_integer(N) -> + N; + ensure_int(S) when is_list(S) -> +@@ -165,27 +179,7 @@ + {_, _, _, _, _, _, _, _} -> % IPv6 + [inet6, {ip, Ip} | BaseOpts] + end, +- case listen(Port, Opts, State) of +- {stop, eacces} -> +- case Port < 1024 of +- true -> +- case catch fdsrv:start() of +- {ok, _} -> +- case fdsrv:bind_socket(tcp, Port) of +- {ok, Fd} -> +- listen(Port, [{fd, Fd} | Opts], State); +- _ -> +- {stop, fdsrv_bind_failed} +- end; +- _ -> +- {stop, fdsrv_start_failed} +- end; +- false -> +- {stop, eacces} +- end; +- Other -> +- Other +- end. ++ listen(Port, Opts, State). + + new_acceptor_pool(Listen, + State=#mochiweb_socket_server{acceptor_pool=Pool, +@@ -271,15 +265,8 @@ + + terminate(Reason, State) when ?is_old_state(State) -> + terminate(Reason, upgrade_state(State)); +-terminate(_Reason, #mochiweb_socket_server{listen=Listen, port=Port}) -> +- mochiweb_socket:close(Listen), +- case Port < 1024 of +- true -> +- catch fdsrv:stop(), +- ok; +- false -> +- ok +- end. ++terminate(_Reason, #mochiweb_socket_server{listen=Listen}) -> ++ mochiweb_socket:close(Listen). + + code_change(_OldVsn, State, _Extra) -> + State. +@@ -337,8 +324,8 @@ + %% + %% Tests + %% +--include_lib("eunit/include/eunit.hrl"). + -ifdef(TEST). ++-include_lib("eunit/include/eunit.hrl"). + + upgrade_state_test() -> + OldState = {mochiweb_socket_server, +diff -wbBur apache-couchdb-1.2.1/src/mochiweb/mochiweb_util.erl apache-couchdb-1.2.1.q/src/mochiweb/mochiweb_util.erl +--- apache-couchdb-1.2.1/src/mochiweb/mochiweb_util.erl 2012-12-21 01:24:07.000000000 +0400 ++++ apache-couchdb-1.2.1.q/src/mochiweb/mochiweb_util.erl 2013-03-22 15:26:58.000000000 +0400 +@@ -9,7 +9,7 @@ + -export([path_split/1]). + -export([urlsplit/1, urlsplit_path/1, urlunsplit/1, urlunsplit_path/1]). + -export([guess_mime/1, parse_header/1]). +--export([shell_quote/1, cmd/1, cmd_string/1, cmd_port/2, cmd_status/1]). ++-export([shell_quote/1, cmd/1, cmd_string/1, cmd_port/2, cmd_status/1, cmd_status/2]). + -export([record_to_proplist/2, record_to_proplist/3]). + -export([safe_relative_path/1, partition/2]). + -export([parse_qvalues/1, pick_accepted_encodings/3]). +@@ -124,11 +124,17 @@ + string:join([shell_quote(X) || X <- Argv], " "). + + %% @spec cmd_status([string()]) -> {ExitStatus::integer(), Stdout::binary()} +-%% @doc Accumulate the output and exit status from the given application, will be +-%% spawned with cmd_port/2. ++%% @doc Accumulate the output and exit status from the given application, ++%% will be spawned with cmd_port/2. + cmd_status(Argv) -> ++ cmd_status(Argv, []). ++ ++%% @spec cmd_status([string()], [atom()]) -> {ExitStatus::integer(), Stdout::binary()} ++%% @doc Accumulate the output and exit status from the given application, ++%% will be spawned with cmd_port/2. ++cmd_status(Argv, Options) -> + Port = cmd_port(Argv, [exit_status, stderr_to_stdout, +- use_stdio, binary]), ++ use_stdio, binary | Options]), + try cmd_loop(Port, []) + after catch port_close(Port) + end. +@@ -578,8 +584,8 @@ + %% + %% Tests + %% +--include_lib("eunit/include/eunit.hrl"). + -ifdef(TEST). ++-include_lib("eunit/include/eunit.hrl"). + + make_io_test() -> + ?assertEqual( +diff -wbBur apache-couchdb-1.2.1/src/mochiweb/reloader.erl apache-couchdb-1.2.1.q/src/mochiweb/reloader.erl +--- apache-couchdb-1.2.1/src/mochiweb/reloader.erl 2012-12-21 01:24:07.000000000 +0400 ++++ apache-couchdb-1.2.1.q/src/mochiweb/reloader.erl 2013-03-22 15:26:58.000000000 +0400 +@@ -59,7 +59,7 @@ + %% @doc gen_server callback. + handle_info(doit, State) -> + Now = stamp(), +- doit(State#state.last, Now), ++ _ = doit(State#state.last, Now), + {noreply, State#state{last = Now}}; + handle_info(_Info, State) -> + {noreply, State}. +@@ -156,6 +156,6 @@ + %% + %% Tests + %% +--include_lib("eunit/include/eunit.hrl"). + -ifdef(TEST). ++-include_lib("eunit/include/eunit.hrl"). + -endif. -- cgit v1.2.3-54-g00ecf