couchdb-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cml...@apache.org
Subject svn commit: r747575 - in /couchdb/trunk/src/mochiweb: mochijson.erl mochijson2.erl mochiweb.app mochiweb_headers.erl mochiweb_html.erl mochiweb_http.erl mochiweb_util.erl
Date Tue, 24 Feb 2009 22:10:05 GMT
Author: cmlenz
Date: Tue Feb 24 22:10:04 2009
New Revision: 747575

URL: http://svn.apache.org/viewvc?rev=747575&view=rev
Log:
Update MochiWeb in trunk to r97. Closes COUCHDB-255.

Modified:
    couchdb/trunk/src/mochiweb/mochijson.erl
    couchdb/trunk/src/mochiweb/mochijson2.erl
    couchdb/trunk/src/mochiweb/mochiweb.app
    couchdb/trunk/src/mochiweb/mochiweb_headers.erl
    couchdb/trunk/src/mochiweb/mochiweb_html.erl
    couchdb/trunk/src/mochiweb/mochiweb_http.erl
    couchdb/trunk/src/mochiweb/mochiweb_util.erl

Modified: couchdb/trunk/src/mochiweb/mochijson.erl
URL: http://svn.apache.org/viewvc/couchdb/trunk/src/mochiweb/mochijson.erl?rev=747575&r1=747574&r2=747575&view=diff
==============================================================================
--- couchdb/trunk/src/mochiweb/mochijson.erl (original)
+++ couchdb/trunk/src/mochiweb/mochijson.erl Tue Feb 24 22:10:04 2009
@@ -478,10 +478,6 @@
     true = equiv(E, decode(encode(E))),
     test_one(Rest, 1+N).
 
-e2j_test_vec(unicode) -> 
-    [
-     {"foo" ++ [500] ++ "bar", [$", $f, $o, $o, 500, $b, $a, $r, $"]}
-    ];
 e2j_test_vec(utf8) ->
     [
     {1, "1"},

Modified: couchdb/trunk/src/mochiweb/mochijson2.erl
URL: http://svn.apache.org/viewvc/couchdb/trunk/src/mochiweb/mochijson2.erl?rev=747575&r1=747574&r2=747575&view=diff
==============================================================================
--- couchdb/trunk/src/mochiweb/mochijson2.erl (original)
+++ couchdb/trunk/src/mochiweb/mochijson2.erl Tue Feb 24 22:10:04 2009
@@ -132,13 +132,81 @@
     lists:reverse([$\} | Acc1]).
 
 json_encode_string(A, _State) when is_atom(A) ->
-    json_encode_string_unicode(xmerl_ucs:from_utf8(atom_to_list(A)), [?Q]);
+    L = atom_to_list(A),
+    case json_string_is_safe(L) of
+        true ->
+            [?Q, L, ?Q];
+        false ->
+            json_encode_string_unicode(xmerl_ucs:from_utf8(L), [?Q])
+    end;
 json_encode_string(B, _State) when is_binary(B) ->
-    json_encode_string_unicode(xmerl_ucs:from_utf8(B), [?Q]);
+    case json_bin_is_safe(B) of
+        true ->
+            [?Q, B, ?Q];
+        false ->
+            json_encode_string_unicode(xmerl_ucs:from_utf8(B), [?Q])
+    end;
 json_encode_string(I, _State) when is_integer(I) ->
-    json_encode_string_unicode(integer_to_list(I), [?Q]);
+    [?Q, integer_to_list(I), ?Q];
 json_encode_string(L, _State) when is_list(L) ->
-    json_encode_string_unicode(L, [?Q]).
+    case json_string_is_safe(L) of
+        true ->
+            [?Q, L, ?Q];
+        false ->
+            json_encode_string_unicode(L, [?Q])
+    end.
+
+json_string_is_safe([]) ->
+    true;
+json_string_is_safe([C | Rest]) ->
+    case C of
+        ?Q ->
+            false;
+        $\\ ->
+            false;
+        $\b ->
+            false;
+        $\f ->
+            false;
+        $\n ->
+            false;
+        $\r ->
+            false;
+        $\t ->
+            false;
+        C when C >= 0, C < $\s; C >= 16#7f, C =< 16#10FFFF ->
+            false;
+        C when C < 16#7f ->
+            json_string_is_safe(Rest);
+        _ ->
+            false
+    end.
+
+json_bin_is_safe(<<>>) ->
+    true;
+json_bin_is_safe(<<C, Rest/binary>>) ->
+    case C of
+        ?Q ->
+            false;
+        $\\ ->
+            false;
+        $\b ->
+            false;
+        $\f ->
+            false;
+        $\n ->
+            false;
+        $\r ->
+            false;
+        $\t ->
+            false;
+        C when C >= 0, C < $\s; C >= 16#7f, C =< 16#10FFFF ->
+            false;
+        C when C < 16#7f ->
+            json_bin_is_safe(Rest);
+        _ ->
+            false
+    end.
 
 json_encode_string_unicode([], Acc) ->
     lists:reverse([$\" | Acc]);
@@ -260,8 +328,28 @@
             decode_array(B, S1#decoder{state=any}, Acc)
     end.
 
-tokenize_string(B, S) ->
-    tokenize_string(B, S, []).
+tokenize_string(B, S=#decoder{offset=O}) ->
+    case tokenize_string_fast(B, O) of
+        {escape, O1} ->
+            Length = O1 - O,
+            S1 = ?ADV_COL(S, Length),
+            <<_:O/binary, Head:Length/binary, _/binary>> = B,
+            tokenize_string(B, S1, lists:reverse(binary_to_list(Head)));
+        O1 ->
+            Length = O1 - O,
+            <<_:O/binary, String:Length/binary, ?Q, _/binary>> = B,
+            {{const, String}, ?ADV_COL(S, Length + 1)}
+    end.
+
+tokenize_string_fast(B, O) ->
+    case B of
+        <<_:O/binary, ?Q, _/binary>> ->
+            O;
+        <<_:O/binary, C, _/binary>> when C =/= $\\ ->
+            tokenize_string_fast(B, 1 + O);
+        _ ->
+            {escape, O}
+    end.
 
 tokenize_string(B, S=#decoder{offset=O}, Acc) ->
     case B of

Modified: couchdb/trunk/src/mochiweb/mochiweb.app
URL: http://svn.apache.org/viewvc/couchdb/trunk/src/mochiweb/mochiweb.app?rev=747575&r1=747574&r2=747575&view=diff
==============================================================================
--- couchdb/trunk/src/mochiweb/mochiweb.app (original)
+++ couchdb/trunk/src/mochiweb/mochiweb.app Tue Feb 24 22:10:04 2009
@@ -21,7 +21,10 @@
         mochiweb_socket_server,
         mochiweb_sup,
         mochiweb_util,
-        reloader
+        reloader,
+        mochifmt,
+        mochifmt_std,
+        mochifmt_records
 	    ]},
   {registered, []},
   {mod, {mochiweb_app, []}},

Modified: couchdb/trunk/src/mochiweb/mochiweb_headers.erl
URL: http://svn.apache.org/viewvc/couchdb/trunk/src/mochiweb/mochiweb_headers.erl?rev=747575&r1=747574&r2=747575&view=diff
==============================================================================
--- couchdb/trunk/src/mochiweb/mochiweb_headers.erl (original)
+++ couchdb/trunk/src/mochiweb/mochiweb_headers.erl Tue Feb 24 22:10:04 2009
@@ -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([get_primary_value/2]).
+-export([delete_any/2, get_primary_value/2]).
 -export([default/3, enter_from_list/2, default_from_list/2]).
 -export([to_list/1, make/1]).
 -export([test/0]).
@@ -35,6 +35,8 @@
                         H3),
     "application/x-www-form-urlencoded" = ?MODULE:get_primary_value(
                                              "content-type", H4),
+    H4 = ?MODULE:delete_any("nonexistent-header", H4),
+    H3 = ?MODULE:delete_any("content-type", H4),
     ok.
 
 %% @spec empty() -> headers()
@@ -145,6 +147,12 @@
             gb_trees:update(K1, {K0, V2}, T)
     end.
 
+%% @spec delete_any(key(), headers()) -> headers()
+%% @doc Delete the header corresponding to key if it is present.
+delete_any(K, T) ->
+    K1 = normalize(K),
+    gb_trees:delete_any(K1, T).
+
 %% Internal API
 
 expand({array, L}) ->

Modified: couchdb/trunk/src/mochiweb/mochiweb_html.erl
URL: http://svn.apache.org/viewvc/couchdb/trunk/src/mochiweb/mochiweb_html.erl?rev=747575&r1=747574&r2=747575&view=diff
==============================================================================
--- couchdb/trunk/src/mochiweb/mochiweb_html.erl (original)
+++ couchdb/trunk/src/mochiweb/mochiweb_html.erl Tue Feb 24 22:10:04 2009
@@ -129,7 +129,9 @@
 test() ->
     test_destack(),
     test_tokens(),
+    test_tokens2(),
     test_parse(),
+    test_parse2(),
     test_parse_tokens(),
     test_escape(),
     test_escape_attr(),
@@ -426,6 +428,34 @@
     Expect = parse(D0),
     ok.
 
+test_tokens2() ->
+    D0 = <<"<channel><title>from __future__ import *</title><link>http://bob.pythonmac.org</link><description>Bob's
Rants</description></channel>">>,
+    Expect = [{start_tag,<<"channel">>,[],false},
+              {start_tag,<<"title">>,[],false},
+              {data,<<"from __future__ import *">>,false},
+              {end_tag,<<"title">>},
+              {start_tag,<<"link">>,[],true},
+              {data,<<"http://bob.pythonmac.org">>,false},
+              {end_tag,<<"link">>},
+              {start_tag,<<"description">>,[],false},
+              {data,<<"Bob's Rants">>,false},
+              {end_tag,<<"description">>},
+              {end_tag,<<"channel">>}],
+    Expect = tokens(D0),
+    ok.
+
+test_parse2() ->
+    D0 = <<"<channel><title>from __future__ import *</title><link>http://bob.pythonmac.org<br>foo</link><description>Bob's
Rants</description></channel>">>,
+    Expect = {<<"channel">>,[],
+              [{<<"title">>,[],[<<"from __future__ import *">>]},
+               {<<"link">>,[],[
+                               <<"http://bob.pythonmac.org">>,
+                               {<<"br">>,[],[]},
+                               <<"foo">>]},
+               {<<"description">>,[],[<<"Bob's Rants">>]}]},
+    Expect = parse(D0),
+    ok.
+
 test_parse_tokens() ->
     D0 = [{doctype,[<<"HTML">>,<<"PUBLIC">>,<<"-//W3C//DTD
HTML 4.01 Transitional//EN">>]},
           {data,<<"\n">>,true},
@@ -562,8 +592,23 @@
         end,
     case lists:splitwith(F, Stack) of
         {_, []} ->
-            %% No match, no state change
-            Stack;
+            %% If we're parsing something like XML we might find
+            %% a <link>tag</link> that is normally a singleton
+            %% in HTML but isn't here
+            case {is_singleton(TagName), Stack} of
+                {true, [{T0, A0, Acc0} | Post0]} ->
+                    case lists:splitwith(F, Acc0) of
+                        {_, []} ->
+                            %% Actually was a singleton
+                            Stack;
+                        {Pre, [{T1, A1, []} | Post1]} ->
+                            [{T0, A0, [{T1, A1, lists:reverse(Pre)} | Post1]}
+                             | Post0]
+                    end;
+                _ ->
+                    %% No match, no state change
+                    Stack
+            end;
         {_Pre, [_T]} ->
             %% Unfurl the whole stack, we're done
             destack(Stack);

Modified: couchdb/trunk/src/mochiweb/mochiweb_http.erl
URL: http://svn.apache.org/viewvc/couchdb/trunk/src/mochiweb/mochiweb_http.erl?rev=747575&r1=747574&r2=747575&view=diff
==============================================================================
--- couchdb/trunk/src/mochiweb/mochiweb_http.erl (original)
+++ couchdb/trunk/src/mochiweb/mochiweb_http.erl Tue Feb 24 22:10:04 2009
@@ -10,6 +10,7 @@
 
 -define(IDLE_TIMEOUT, 30000).
 
+-define(MAX_HEADERS, 1000).
 -define(DEFAULTS, [{name, ?MODULE},
                    {port, 8888}]).
 
@@ -37,7 +38,7 @@
 
 stop(Name) ->
     mochiweb_socket_server:stop(Name).
-    
+
 start() ->
     start([{ip, "127.0.0.1"},
            {loop, {?MODULE, default_body}}]).
@@ -80,12 +81,12 @@
                                    {body, Req:recv_body()},
                                    Req:dump()]]),
     Req:ok({"text/html", [], frm(Body)});
-default_body(Req, 'POST', _Path) ->    
+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)});           
+    Req:ok({"text/html", [], frm(Body)});
 default_body(Req, _Method, _Path) ->
     Req:respond({501, [], []}).
 
@@ -99,7 +100,7 @@
 request(Socket, Body) ->
     case gen_tcp:recv(Socket, 0, ?IDLE_TIMEOUT) of
         {ok, {http_request, Method, Path, Version}} ->
-            headers(Socket, {Method, Path, Version}, [], Body);
+            headers(Socket, {Method, Path, Version}, [], Body, 0);
         {error, {http_error, "\r\n"}} ->
             request(Socket, Body);
         {error, {http_error, "\n"}} ->
@@ -109,7 +110,15 @@
             exit(normal)
     end.
 
-headers(Socket, Request, Headers, Body) ->
+headers(Socket, Request, Headers, _Body, ?MAX_HEADERS) ->
+    %% Too many headers sent, bad request.
+    inet:setopts(Socket, [{packet, raw}]),
+    Req = mochiweb:new_request({Socket, Request,
+                                lists:reverse(Headers)}),
+    Req:respond({400, [], []}),
+    gen_tcp:close(Socket),
+    exit(normal);
+headers(Socket, Request, Headers, Body, HeaderCount) ->
     case gen_tcp:recv(Socket, 0, ?IDLE_TIMEOUT) of
         {ok, http_eoh} ->
             inet:setopts(Socket, [{packet, raw}]),
@@ -125,7 +134,8 @@
                     ?MODULE:loop(Socket, Body)
             end;
         {ok, {http_header, _, Name, _, Value}} ->
-            headers(Socket, Request, [{Name, Value} | Headers], Body);
+            headers(Socket, Request, [{Name, Value} | Headers], Body,
+                    1 + HeaderCount);
         _Other ->
             gen_tcp:close(Socket),
             exit(normal)

Modified: couchdb/trunk/src/mochiweb/mochiweb_util.erl
URL: http://svn.apache.org/viewvc/couchdb/trunk/src/mochiweb/mochiweb_util.erl?rev=747575&r1=747574&r2=747575&view=diff
==============================================================================
--- couchdb/trunk/src/mochiweb/mochiweb_util.erl (original)
+++ couchdb/trunk/src/mochiweb/mochiweb_util.erl Tue Feb 24 22:10:04 2009
@@ -134,12 +134,16 @@
 revjoin([S | Rest], Separator, Acc) ->
     revjoin(Rest, Separator, [S, Separator | Acc]).
 
-%% @spec quote_plus(atom() | integer() | string()) -> string()
+%% @spec quote_plus(atom() | integer() | float() | string() | binary()) -> string()
 %% @doc URL safe encoding of the given term.
 quote_plus(Atom) when is_atom(Atom) ->
     quote_plus(atom_to_list(Atom));
 quote_plus(Int) when is_integer(Int) ->
     quote_plus(integer_to_list(Int));
+quote_plus(Binary) when is_binary(Binary) ->
+    quote_plus(binary_to_list(Binary));
+quote_plus(Float) when is_float(Float) ->
+    quote_plus(mochinum:digits(Float));
 quote_plus(String) ->
     quote_plus(String, []).
 
@@ -542,6 +546,7 @@
 test_quote_plus() ->
     "foo" = quote_plus(foo),
     "1" = quote_plus(1),
+    "1.1" = quote_plus(1.1),
     "foo" = quote_plus("foo"),
     "foo+bar" = quote_plus("foo bar"),
     "foo%0A" = quote_plus("foo\n"),



Mime
View raw message