DELETED README.md Index: README.md ================================================================== --- README.md +++ /dev/null @@ -1,20 +0,0 @@ -# Antigone - -Antigone is a simple static site server. All files located in -the `www` directory are matched and served. - -## Installation - -If [available in Hex](https://hex.pm/docs/publish), the package can be installed as: - - 1. Add antigone to your list of dependencies in `mix.exs`: - - def deps do - [{:antigone, "~> 0.0.1"}] - end - - 2. Ensure antigone is started before your application: - - def application do - [applications: [:antigone]] - end DELETED _build/dev/lib/antigone/ebin/Elixir.Antigone.beam Index: _build/dev/lib/antigone/ebin/Elixir.Antigone.beam ================================================================== --- _build/dev/lib/antigone/ebin/Elixir.Antigone.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/antigone/ebin/antigone.app Index: _build/dev/lib/antigone/ebin/antigone.app ================================================================== --- _build/dev/lib/antigone/ebin/antigone.app +++ /dev/null @@ -1,7 +0,0 @@ -{application,antigone, - [{registered,[]}, - {description,"antigone"}, - {applications,[kernel,stdlib,elixir,logger,cowboy,plug]}, - {mod,{'Elixir.Antigone',[]}}, - {vsn,"0.0.1"}, - {modules,['Elixir.Antigone','Elixir.Router']}]}. DELETED _build/dev/lib/cowboy/ebin/cowboy.app Index: _build/dev/lib/cowboy/ebin/cowboy.app ================================================================== --- _build/dev/lib/cowboy/ebin/cowboy.app +++ /dev/null @@ -1,14 +0,0 @@ -{application,cowboy, - [{description,"Small, fast, modular HTTP server."}, - {vsn,"1.0.4"}, - {id,"git"}, - {modules,[cowboy,cowboy_app,cowboy_bstr,cowboy_clock, - cowboy_handler,cowboy_http,cowboy_http_handler, - cowboy_loop_handler,cowboy_middleware,cowboy_protocol, - cowboy_req,cowboy_rest,cowboy_router,cowboy_spdy, - cowboy_static,cowboy_sub_protocol,cowboy_sup, - cowboy_websocket,cowboy_websocket_handler]}, - {registered,[cowboy_clock,cowboy_sup]}, - {applications,[kernel,stdlib,ranch,cowlib,crypto]}, - {mod,{cowboy_app,[]}}, - {env,[]}]}. DELETED _build/dev/lib/cowboy/ebin/cowboy.beam Index: _build/dev/lib/cowboy/ebin/cowboy.beam ================================================================== --- _build/dev/lib/cowboy/ebin/cowboy.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/cowboy/ebin/cowboy_app.beam Index: _build/dev/lib/cowboy/ebin/cowboy_app.beam ================================================================== --- _build/dev/lib/cowboy/ebin/cowboy_app.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/cowboy/ebin/cowboy_bstr.beam Index: _build/dev/lib/cowboy/ebin/cowboy_bstr.beam ================================================================== --- _build/dev/lib/cowboy/ebin/cowboy_bstr.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/cowboy/ebin/cowboy_clock.beam Index: _build/dev/lib/cowboy/ebin/cowboy_clock.beam ================================================================== --- _build/dev/lib/cowboy/ebin/cowboy_clock.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/cowboy/ebin/cowboy_handler.beam Index: _build/dev/lib/cowboy/ebin/cowboy_handler.beam ================================================================== --- _build/dev/lib/cowboy/ebin/cowboy_handler.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/cowboy/ebin/cowboy_http.beam Index: _build/dev/lib/cowboy/ebin/cowboy_http.beam ================================================================== --- _build/dev/lib/cowboy/ebin/cowboy_http.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/cowboy/ebin/cowboy_http_handler.beam Index: _build/dev/lib/cowboy/ebin/cowboy_http_handler.beam ================================================================== --- _build/dev/lib/cowboy/ebin/cowboy_http_handler.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/cowboy/ebin/cowboy_loop_handler.beam Index: _build/dev/lib/cowboy/ebin/cowboy_loop_handler.beam ================================================================== --- _build/dev/lib/cowboy/ebin/cowboy_loop_handler.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/cowboy/ebin/cowboy_middleware.beam Index: _build/dev/lib/cowboy/ebin/cowboy_middleware.beam ================================================================== --- _build/dev/lib/cowboy/ebin/cowboy_middleware.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/cowboy/ebin/cowboy_protocol.beam Index: _build/dev/lib/cowboy/ebin/cowboy_protocol.beam ================================================================== --- _build/dev/lib/cowboy/ebin/cowboy_protocol.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/cowboy/ebin/cowboy_req.beam Index: _build/dev/lib/cowboy/ebin/cowboy_req.beam ================================================================== --- _build/dev/lib/cowboy/ebin/cowboy_req.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/cowboy/ebin/cowboy_rest.beam Index: _build/dev/lib/cowboy/ebin/cowboy_rest.beam ================================================================== --- _build/dev/lib/cowboy/ebin/cowboy_rest.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/cowboy/ebin/cowboy_router.beam Index: _build/dev/lib/cowboy/ebin/cowboy_router.beam ================================================================== --- _build/dev/lib/cowboy/ebin/cowboy_router.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/cowboy/ebin/cowboy_spdy.beam Index: _build/dev/lib/cowboy/ebin/cowboy_spdy.beam ================================================================== --- _build/dev/lib/cowboy/ebin/cowboy_spdy.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/cowboy/ebin/cowboy_static.beam Index: _build/dev/lib/cowboy/ebin/cowboy_static.beam ================================================================== --- _build/dev/lib/cowboy/ebin/cowboy_static.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/cowboy/ebin/cowboy_sub_protocol.beam Index: _build/dev/lib/cowboy/ebin/cowboy_sub_protocol.beam ================================================================== --- _build/dev/lib/cowboy/ebin/cowboy_sub_protocol.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/cowboy/ebin/cowboy_sup.beam Index: _build/dev/lib/cowboy/ebin/cowboy_sup.beam ================================================================== --- _build/dev/lib/cowboy/ebin/cowboy_sup.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/cowboy/ebin/cowboy_websocket.beam Index: _build/dev/lib/cowboy/ebin/cowboy_websocket.beam ================================================================== --- _build/dev/lib/cowboy/ebin/cowboy_websocket.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/cowboy/ebin/cowboy_websocket_handler.beam Index: _build/dev/lib/cowboy/ebin/cowboy_websocket_handler.beam ================================================================== --- _build/dev/lib/cowboy/ebin/cowboy_websocket_handler.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/cowlib/ebin/cow_cookie.beam Index: _build/dev/lib/cowlib/ebin/cow_cookie.beam ================================================================== --- _build/dev/lib/cowlib/ebin/cow_cookie.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/cowlib/ebin/cow_date.beam Index: _build/dev/lib/cowlib/ebin/cow_date.beam ================================================================== --- _build/dev/lib/cowlib/ebin/cow_date.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/cowlib/ebin/cow_http.beam Index: _build/dev/lib/cowlib/ebin/cow_http.beam ================================================================== --- _build/dev/lib/cowlib/ebin/cow_http.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/cowlib/ebin/cow_http_hd.beam Index: _build/dev/lib/cowlib/ebin/cow_http_hd.beam ================================================================== --- _build/dev/lib/cowlib/ebin/cow_http_hd.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/cowlib/ebin/cow_http_te.beam Index: _build/dev/lib/cowlib/ebin/cow_http_te.beam ================================================================== --- _build/dev/lib/cowlib/ebin/cow_http_te.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/cowlib/ebin/cow_mimetypes.beam Index: _build/dev/lib/cowlib/ebin/cow_mimetypes.beam ================================================================== --- _build/dev/lib/cowlib/ebin/cow_mimetypes.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/cowlib/ebin/cow_multipart.beam Index: _build/dev/lib/cowlib/ebin/cow_multipart.beam ================================================================== --- _build/dev/lib/cowlib/ebin/cow_multipart.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/cowlib/ebin/cow_qs.beam Index: _build/dev/lib/cowlib/ebin/cow_qs.beam ================================================================== --- _build/dev/lib/cowlib/ebin/cow_qs.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/cowlib/ebin/cow_spdy.beam Index: _build/dev/lib/cowlib/ebin/cow_spdy.beam ================================================================== --- _build/dev/lib/cowlib/ebin/cow_spdy.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/cowlib/ebin/cowlib.app Index: _build/dev/lib/cowlib/ebin/cowlib.app ================================================================== --- _build/dev/lib/cowlib/ebin/cowlib.app +++ /dev/null @@ -1,8 +0,0 @@ -{application,cowlib, - [{description,"Support library for manipulating Web protocols."}, - {vsn,"1.0.2"}, - {id,"git"}, - {modules,[cow_cookie,cow_date,cow_http,cow_http_hd,cow_http_te, - cow_mimetypes,cow_multipart,cow_qs,cow_spdy]}, - {registered,[]}, - {applications,[kernel,stdlib,crypto]}]}. DELETED _build/dev/lib/cowlib/include/cow_inline.hrl Index: _build/dev/lib/cowlib/include/cow_inline.hrl ================================================================== --- _build/dev/lib/cowlib/include/cow_inline.hrl +++ /dev/null @@ -1,388 +0,0 @@ -%% Copyright (c) 2014, Loïc Hoguin -%% -%% Permission to use, copy, modify, and/or distribute this software for any -%% purpose with or without fee is hereby granted, provided that the above -%% copyright notice and this permission notice appear in all copies. -%% -%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - --ifndef(COW_INLINE_HRL). --define(COW_INLINE_HRL, 1). - -%% INLINE_LOWERCASE(Function, Rest, Acc, ...) -%% -%% To be included at the end of a case block. -%% Defined for up to 10 extra arguments. - --define(INLINE_LOWERCASE(Function, Rest, Acc), - $A -> Function(Rest, << Acc/binary, $a >>); - $B -> Function(Rest, << Acc/binary, $b >>); - $C -> Function(Rest, << Acc/binary, $c >>); - $D -> Function(Rest, << Acc/binary, $d >>); - $E -> Function(Rest, << Acc/binary, $e >>); - $F -> Function(Rest, << Acc/binary, $f >>); - $G -> Function(Rest, << Acc/binary, $g >>); - $H -> Function(Rest, << Acc/binary, $h >>); - $I -> Function(Rest, << Acc/binary, $i >>); - $J -> Function(Rest, << Acc/binary, $j >>); - $K -> Function(Rest, << Acc/binary, $k >>); - $L -> Function(Rest, << Acc/binary, $l >>); - $M -> Function(Rest, << Acc/binary, $m >>); - $N -> Function(Rest, << Acc/binary, $n >>); - $O -> Function(Rest, << Acc/binary, $o >>); - $P -> Function(Rest, << Acc/binary, $p >>); - $Q -> Function(Rest, << Acc/binary, $q >>); - $R -> Function(Rest, << Acc/binary, $r >>); - $S -> Function(Rest, << Acc/binary, $s >>); - $T -> Function(Rest, << Acc/binary, $t >>); - $U -> Function(Rest, << Acc/binary, $u >>); - $V -> Function(Rest, << Acc/binary, $v >>); - $W -> Function(Rest, << Acc/binary, $w >>); - $X -> Function(Rest, << Acc/binary, $x >>); - $Y -> Function(Rest, << Acc/binary, $y >>); - $Z -> Function(Rest, << Acc/binary, $z >>); - C -> Function(Rest, << Acc/binary, C >>) -). - --define(INLINE_LOWERCASE(Function, Rest, A0, Acc), - $A -> Function(Rest, A0, << Acc/binary, $a >>); - $B -> Function(Rest, A0, << Acc/binary, $b >>); - $C -> Function(Rest, A0, << Acc/binary, $c >>); - $D -> Function(Rest, A0, << Acc/binary, $d >>); - $E -> Function(Rest, A0, << Acc/binary, $e >>); - $F -> Function(Rest, A0, << Acc/binary, $f >>); - $G -> Function(Rest, A0, << Acc/binary, $g >>); - $H -> Function(Rest, A0, << Acc/binary, $h >>); - $I -> Function(Rest, A0, << Acc/binary, $i >>); - $J -> Function(Rest, A0, << Acc/binary, $j >>); - $K -> Function(Rest, A0, << Acc/binary, $k >>); - $L -> Function(Rest, A0, << Acc/binary, $l >>); - $M -> Function(Rest, A0, << Acc/binary, $m >>); - $N -> Function(Rest, A0, << Acc/binary, $n >>); - $O -> Function(Rest, A0, << Acc/binary, $o >>); - $P -> Function(Rest, A0, << Acc/binary, $p >>); - $Q -> Function(Rest, A0, << Acc/binary, $q >>); - $R -> Function(Rest, A0, << Acc/binary, $r >>); - $S -> Function(Rest, A0, << Acc/binary, $s >>); - $T -> Function(Rest, A0, << Acc/binary, $t >>); - $U -> Function(Rest, A0, << Acc/binary, $u >>); - $V -> Function(Rest, A0, << Acc/binary, $v >>); - $W -> Function(Rest, A0, << Acc/binary, $w >>); - $X -> Function(Rest, A0, << Acc/binary, $x >>); - $Y -> Function(Rest, A0, << Acc/binary, $y >>); - $Z -> Function(Rest, A0, << Acc/binary, $z >>); - C -> Function(Rest, A0, << Acc/binary, C >>) -). - --define(INLINE_LOWERCASE(Function, Rest, A0, A1, Acc), - $A -> Function(Rest, A0, A1, << Acc/binary, $a >>); - $B -> Function(Rest, A0, A1, << Acc/binary, $b >>); - $C -> Function(Rest, A0, A1, << Acc/binary, $c >>); - $D -> Function(Rest, A0, A1, << Acc/binary, $d >>); - $E -> Function(Rest, A0, A1, << Acc/binary, $e >>); - $F -> Function(Rest, A0, A1, << Acc/binary, $f >>); - $G -> Function(Rest, A0, A1, << Acc/binary, $g >>); - $H -> Function(Rest, A0, A1, << Acc/binary, $h >>); - $I -> Function(Rest, A0, A1, << Acc/binary, $i >>); - $J -> Function(Rest, A0, A1, << Acc/binary, $j >>); - $K -> Function(Rest, A0, A1, << Acc/binary, $k >>); - $L -> Function(Rest, A0, A1, << Acc/binary, $l >>); - $M -> Function(Rest, A0, A1, << Acc/binary, $m >>); - $N -> Function(Rest, A0, A1, << Acc/binary, $n >>); - $O -> Function(Rest, A0, A1, << Acc/binary, $o >>); - $P -> Function(Rest, A0, A1, << Acc/binary, $p >>); - $Q -> Function(Rest, A0, A1, << Acc/binary, $q >>); - $R -> Function(Rest, A0, A1, << Acc/binary, $r >>); - $S -> Function(Rest, A0, A1, << Acc/binary, $s >>); - $T -> Function(Rest, A0, A1, << Acc/binary, $t >>); - $U -> Function(Rest, A0, A1, << Acc/binary, $u >>); - $V -> Function(Rest, A0, A1, << Acc/binary, $v >>); - $W -> Function(Rest, A0, A1, << Acc/binary, $w >>); - $X -> Function(Rest, A0, A1, << Acc/binary, $x >>); - $Y -> Function(Rest, A0, A1, << Acc/binary, $y >>); - $Z -> Function(Rest, A0, A1, << Acc/binary, $z >>); - C -> Function(Rest, A0, A1, << Acc/binary, C >>) -). - --define(INLINE_LOWERCASE(Function, Rest, A0, A1, A2, Acc), - $A -> Function(Rest, A0, A1, A2, << Acc/binary, $a >>); - $B -> Function(Rest, A0, A1, A2, << Acc/binary, $b >>); - $C -> Function(Rest, A0, A1, A2, << Acc/binary, $c >>); - $D -> Function(Rest, A0, A1, A2, << Acc/binary, $d >>); - $E -> Function(Rest, A0, A1, A2, << Acc/binary, $e >>); - $F -> Function(Rest, A0, A1, A2, << Acc/binary, $f >>); - $G -> Function(Rest, A0, A1, A2, << Acc/binary, $g >>); - $H -> Function(Rest, A0, A1, A2, << Acc/binary, $h >>); - $I -> Function(Rest, A0, A1, A2, << Acc/binary, $i >>); - $J -> Function(Rest, A0, A1, A2, << Acc/binary, $j >>); - $K -> Function(Rest, A0, A1, A2, << Acc/binary, $k >>); - $L -> Function(Rest, A0, A1, A2, << Acc/binary, $l >>); - $M -> Function(Rest, A0, A1, A2, << Acc/binary, $m >>); - $N -> Function(Rest, A0, A1, A2, << Acc/binary, $n >>); - $O -> Function(Rest, A0, A1, A2, << Acc/binary, $o >>); - $P -> Function(Rest, A0, A1, A2, << Acc/binary, $p >>); - $Q -> Function(Rest, A0, A1, A2, << Acc/binary, $q >>); - $R -> Function(Rest, A0, A1, A2, << Acc/binary, $r >>); - $S -> Function(Rest, A0, A1, A2, << Acc/binary, $s >>); - $T -> Function(Rest, A0, A1, A2, << Acc/binary, $t >>); - $U -> Function(Rest, A0, A1, A2, << Acc/binary, $u >>); - $V -> Function(Rest, A0, A1, A2, << Acc/binary, $v >>); - $W -> Function(Rest, A0, A1, A2, << Acc/binary, $w >>); - $X -> Function(Rest, A0, A1, A2, << Acc/binary, $x >>); - $Y -> Function(Rest, A0, A1, A2, << Acc/binary, $y >>); - $Z -> Function(Rest, A0, A1, A2, << Acc/binary, $z >>); - C -> Function(Rest, A0, A1, A2, << Acc/binary, C >>) -). - --define(INLINE_LOWERCASE(Function, Rest, A0, A1, A2, A3, Acc), - $A -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $a >>); - $B -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $b >>); - $C -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $c >>); - $D -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $d >>); - $E -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $e >>); - $F -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $f >>); - $G -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $g >>); - $H -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $h >>); - $I -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $i >>); - $J -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $j >>); - $K -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $k >>); - $L -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $l >>); - $M -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $m >>); - $N -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $n >>); - $O -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $o >>); - $P -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $p >>); - $Q -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $q >>); - $R -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $r >>); - $S -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $s >>); - $T -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $t >>); - $U -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $u >>); - $V -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $v >>); - $W -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $w >>); - $X -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $x >>); - $Y -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $y >>); - $Z -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $z >>); - C -> Function(Rest, A0, A1, A2, A3, << Acc/binary, C >>) -). - --define(INLINE_LOWERCASE(Function, Rest, A0, A1, A2, A3, A4, Acc), - $A -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $a >>); - $B -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $b >>); - $C -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $c >>); - $D -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $d >>); - $E -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $e >>); - $F -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $f >>); - $G -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $g >>); - $H -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $h >>); - $I -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $i >>); - $J -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $j >>); - $K -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $k >>); - $L -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $l >>); - $M -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $m >>); - $N -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $n >>); - $O -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $o >>); - $P -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $p >>); - $Q -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $q >>); - $R -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $r >>); - $S -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $s >>); - $T -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $t >>); - $U -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $u >>); - $V -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $v >>); - $W -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $w >>); - $X -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $x >>); - $Y -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $y >>); - $Z -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $z >>); - C -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, C >>) -). - --define(INLINE_LOWERCASE(Function, Rest, A0, A1, A2, A3, A4, A5, Acc), - $A -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $a >>); - $B -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $b >>); - $C -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $c >>); - $D -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $d >>); - $E -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $e >>); - $F -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $f >>); - $G -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $g >>); - $H -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $h >>); - $I -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $i >>); - $J -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $j >>); - $K -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $k >>); - $L -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $l >>); - $M -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $m >>); - $N -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $n >>); - $O -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $o >>); - $P -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $p >>); - $Q -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $q >>); - $R -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $r >>); - $S -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $s >>); - $T -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $t >>); - $U -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $u >>); - $V -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $v >>); - $W -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $w >>); - $X -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $x >>); - $Y -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $y >>); - $Z -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $z >>); - C -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, C >>) -). - --define(INLINE_LOWERCASE(Function, Rest, A0, A1, A2, A3, A4, A5, A6, Acc), - $A -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $a >>); - $B -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $b >>); - $C -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $c >>); - $D -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $d >>); - $E -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $e >>); - $F -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $f >>); - $G -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $g >>); - $H -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $h >>); - $I -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $i >>); - $J -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $j >>); - $K -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $k >>); - $L -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $l >>); - $M -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $m >>); - $N -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $n >>); - $O -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $o >>); - $P -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $p >>); - $Q -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $q >>); - $R -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $r >>); - $S -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $s >>); - $T -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $t >>); - $U -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $u >>); - $V -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $v >>); - $W -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $w >>); - $X -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $x >>); - $Y -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $y >>); - $Z -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $z >>); - C -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, C >>) -). - --define(INLINE_LOWERCASE(Function, Rest, A0, A1, A2, A3, A4, A5, A6, A7, Acc), - $A -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $a >>); - $B -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $b >>); - $C -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $c >>); - $D -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $d >>); - $E -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $e >>); - $F -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $f >>); - $G -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $g >>); - $H -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $h >>); - $I -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $i >>); - $J -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $j >>); - $K -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $k >>); - $L -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $l >>); - $M -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $m >>); - $N -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $n >>); - $O -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $o >>); - $P -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $p >>); - $Q -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $q >>); - $R -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $r >>); - $S -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $s >>); - $T -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $t >>); - $U -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $u >>); - $V -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $v >>); - $W -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $w >>); - $X -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $x >>); - $Y -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $y >>); - $Z -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $z >>); - C -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, C >>) -). - --define(INLINE_LOWERCASE(Function, Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, Acc), - $A -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $a >>); - $B -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $b >>); - $C -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $c >>); - $D -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $d >>); - $E -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $e >>); - $F -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $f >>); - $G -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $g >>); - $H -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $h >>); - $I -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $i >>); - $J -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $j >>); - $K -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $k >>); - $L -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $l >>); - $M -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $m >>); - $N -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $n >>); - $O -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $o >>); - $P -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $p >>); - $Q -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $q >>); - $R -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $r >>); - $S -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $s >>); - $T -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $t >>); - $U -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $u >>); - $V -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $v >>); - $W -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $w >>); - $X -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $x >>); - $Y -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $y >>); - $Z -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $z >>); - C -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, C >>) -). - --define(INLINE_LOWERCASE(Function, Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, Acc), - $A -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $a >>); - $B -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $b >>); - $C -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $c >>); - $D -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $d >>); - $E -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $e >>); - $F -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $f >>); - $G -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $g >>); - $H -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $h >>); - $I -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $i >>); - $J -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $j >>); - $K -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $k >>); - $L -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $l >>); - $M -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $m >>); - $N -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $n >>); - $O -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $o >>); - $P -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $p >>); - $Q -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $q >>); - $R -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $r >>); - $S -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $s >>); - $T -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $t >>); - $U -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $u >>); - $V -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $v >>); - $W -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $w >>); - $X -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $x >>); - $Y -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $y >>); - $Z -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $z >>); - C -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, C >>) -). - -%% INLINE_LOWERCASE_BC(Bin) -%% -%% Lowercase the entire binary string in a binary comprehension. - --define(INLINE_LOWERCASE_BC(Bin), - << << case C of - $A -> $a; - $B -> $b; - $C -> $c; - $D -> $d; - $E -> $e; - $F -> $f; - $G -> $g; - $H -> $h; - $I -> $i; - $J -> $j; - $K -> $k; - $L -> $l; - $M -> $m; - $N -> $n; - $O -> $o; - $P -> $p; - $Q -> $q; - $R -> $r; - $S -> $s; - $T -> $t; - $U -> $u; - $V -> $v; - $W -> $w; - $X -> $x; - $Y -> $y; - $Z -> $z; - C -> C - end >> || << C >> <= Bin >>). - --endif. DELETED _build/dev/lib/plug/ebin/Elixir.Collectable.Plug.Conn.beam Index: _build/dev/lib/plug/ebin/Elixir.Collectable.Plug.Conn.beam ================================================================== --- _build/dev/lib/plug/ebin/Elixir.Collectable.Plug.Conn.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/plug/ebin/Elixir.Inspect.Plug.Conn.beam Index: _build/dev/lib/plug/ebin/Elixir.Inspect.Plug.Conn.beam ================================================================== --- _build/dev/lib/plug/ebin/Elixir.Inspect.Plug.Conn.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/plug/ebin/Elixir.Plug.Adapters.Cowboy.Conn.beam Index: _build/dev/lib/plug/ebin/Elixir.Plug.Adapters.Cowboy.Conn.beam ================================================================== --- _build/dev/lib/plug/ebin/Elixir.Plug.Adapters.Cowboy.Conn.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/plug/ebin/Elixir.Plug.Adapters.Cowboy.Handler.beam Index: _build/dev/lib/plug/ebin/Elixir.Plug.Adapters.Cowboy.Handler.beam ================================================================== --- _build/dev/lib/plug/ebin/Elixir.Plug.Adapters.Cowboy.Handler.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/plug/ebin/Elixir.Plug.Adapters.Cowboy.beam Index: _build/dev/lib/plug/ebin/Elixir.Plug.Adapters.Cowboy.beam ================================================================== --- _build/dev/lib/plug/ebin/Elixir.Plug.Adapters.Cowboy.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/plug/ebin/Elixir.Plug.Adapters.Test.Conn.beam Index: _build/dev/lib/plug/ebin/Elixir.Plug.Adapters.Test.Conn.beam ================================================================== --- _build/dev/lib/plug/ebin/Elixir.Plug.Adapters.Test.Conn.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/plug/ebin/Elixir.Plug.Adapters.Translator.beam Index: _build/dev/lib/plug/ebin/Elixir.Plug.Adapters.Translator.beam ================================================================== --- _build/dev/lib/plug/ebin/Elixir.Plug.Adapters.Translator.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/plug/ebin/Elixir.Plug.Builder.beam Index: _build/dev/lib/plug/ebin/Elixir.Plug.Builder.beam ================================================================== --- _build/dev/lib/plug/ebin/Elixir.Plug.Builder.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/plug/ebin/Elixir.Plug.CSRFProtection.InvalidCSRFTokenError.beam Index: _build/dev/lib/plug/ebin/Elixir.Plug.CSRFProtection.InvalidCSRFTokenError.beam ================================================================== --- _build/dev/lib/plug/ebin/Elixir.Plug.CSRFProtection.InvalidCSRFTokenError.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/plug/ebin/Elixir.Plug.CSRFProtection.InvalidCrossOriginRequestError.beam Index: _build/dev/lib/plug/ebin/Elixir.Plug.CSRFProtection.InvalidCrossOriginRequestError.beam ================================================================== --- _build/dev/lib/plug/ebin/Elixir.Plug.CSRFProtection.InvalidCrossOriginRequestError.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/plug/ebin/Elixir.Plug.CSRFProtection.beam Index: _build/dev/lib/plug/ebin/Elixir.Plug.CSRFProtection.beam ================================================================== --- _build/dev/lib/plug/ebin/Elixir.Plug.CSRFProtection.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/plug/ebin/Elixir.Plug.Conn.Adapter.beam Index: _build/dev/lib/plug/ebin/Elixir.Plug.Conn.Adapter.beam ================================================================== --- _build/dev/lib/plug/ebin/Elixir.Plug.Conn.Adapter.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/plug/ebin/Elixir.Plug.Conn.AlreadySentError.beam Index: _build/dev/lib/plug/ebin/Elixir.Plug.Conn.AlreadySentError.beam ================================================================== --- _build/dev/lib/plug/ebin/Elixir.Plug.Conn.AlreadySentError.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/plug/ebin/Elixir.Plug.Conn.Cookies.beam Index: _build/dev/lib/plug/ebin/Elixir.Plug.Conn.Cookies.beam ================================================================== --- _build/dev/lib/plug/ebin/Elixir.Plug.Conn.Cookies.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/plug/ebin/Elixir.Plug.Conn.InvalidHeaderError.beam Index: _build/dev/lib/plug/ebin/Elixir.Plug.Conn.InvalidHeaderError.beam ================================================================== --- _build/dev/lib/plug/ebin/Elixir.Plug.Conn.InvalidHeaderError.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/plug/ebin/Elixir.Plug.Conn.NotSentError.beam Index: _build/dev/lib/plug/ebin/Elixir.Plug.Conn.NotSentError.beam ================================================================== --- _build/dev/lib/plug/ebin/Elixir.Plug.Conn.NotSentError.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/plug/ebin/Elixir.Plug.Conn.Query.beam Index: _build/dev/lib/plug/ebin/Elixir.Plug.Conn.Query.beam ================================================================== --- _build/dev/lib/plug/ebin/Elixir.Plug.Conn.Query.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/plug/ebin/Elixir.Plug.Conn.Status.beam Index: _build/dev/lib/plug/ebin/Elixir.Plug.Conn.Status.beam ================================================================== --- _build/dev/lib/plug/ebin/Elixir.Plug.Conn.Status.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/plug/ebin/Elixir.Plug.Conn.Unfetched.beam Index: _build/dev/lib/plug/ebin/Elixir.Plug.Conn.Unfetched.beam ================================================================== --- _build/dev/lib/plug/ebin/Elixir.Plug.Conn.Unfetched.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/plug/ebin/Elixir.Plug.Conn.Utils.beam Index: _build/dev/lib/plug/ebin/Elixir.Plug.Conn.Utils.beam ================================================================== --- _build/dev/lib/plug/ebin/Elixir.Plug.Conn.Utils.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/plug/ebin/Elixir.Plug.Conn.WrapperError.beam Index: _build/dev/lib/plug/ebin/Elixir.Plug.Conn.WrapperError.beam ================================================================== --- _build/dev/lib/plug/ebin/Elixir.Plug.Conn.WrapperError.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/plug/ebin/Elixir.Plug.Conn.beam Index: _build/dev/lib/plug/ebin/Elixir.Plug.Conn.beam ================================================================== --- _build/dev/lib/plug/ebin/Elixir.Plug.Conn.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/plug/ebin/Elixir.Plug.Crypto.KeyGenerator.beam Index: _build/dev/lib/plug/ebin/Elixir.Plug.Crypto.KeyGenerator.beam ================================================================== --- _build/dev/lib/plug/ebin/Elixir.Plug.Crypto.KeyGenerator.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/plug/ebin/Elixir.Plug.Crypto.MessageEncryptor.beam Index: _build/dev/lib/plug/ebin/Elixir.Plug.Crypto.MessageEncryptor.beam ================================================================== --- _build/dev/lib/plug/ebin/Elixir.Plug.Crypto.MessageEncryptor.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/plug/ebin/Elixir.Plug.Crypto.MessageVerifier.beam Index: _build/dev/lib/plug/ebin/Elixir.Plug.Crypto.MessageVerifier.beam ================================================================== --- _build/dev/lib/plug/ebin/Elixir.Plug.Crypto.MessageVerifier.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/plug/ebin/Elixir.Plug.Crypto.beam Index: _build/dev/lib/plug/ebin/Elixir.Plug.Crypto.beam ================================================================== --- _build/dev/lib/plug/ebin/Elixir.Plug.Crypto.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/plug/ebin/Elixir.Plug.Debugger.beam Index: _build/dev/lib/plug/ebin/Elixir.Plug.Debugger.beam ================================================================== --- _build/dev/lib/plug/ebin/Elixir.Plug.Debugger.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/plug/ebin/Elixir.Plug.ErrorHandler.beam Index: _build/dev/lib/plug/ebin/Elixir.Plug.ErrorHandler.beam ================================================================== --- _build/dev/lib/plug/ebin/Elixir.Plug.ErrorHandler.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/plug/ebin/Elixir.Plug.Exception.Any.beam Index: _build/dev/lib/plug/ebin/Elixir.Plug.Exception.Any.beam ================================================================== --- _build/dev/lib/plug/ebin/Elixir.Plug.Exception.Any.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/plug/ebin/Elixir.Plug.Exception.beam Index: _build/dev/lib/plug/ebin/Elixir.Plug.Exception.beam ================================================================== --- _build/dev/lib/plug/ebin/Elixir.Plug.Exception.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/plug/ebin/Elixir.Plug.HTML.beam Index: _build/dev/lib/plug/ebin/Elixir.Plug.HTML.beam ================================================================== --- _build/dev/lib/plug/ebin/Elixir.Plug.HTML.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/plug/ebin/Elixir.Plug.Head.beam Index: _build/dev/lib/plug/ebin/Elixir.Plug.Head.beam ================================================================== --- _build/dev/lib/plug/ebin/Elixir.Plug.Head.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/plug/ebin/Elixir.Plug.Logger.beam Index: _build/dev/lib/plug/ebin/Elixir.Plug.Logger.beam ================================================================== --- _build/dev/lib/plug/ebin/Elixir.Plug.Logger.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/plug/ebin/Elixir.Plug.MIME.beam Index: _build/dev/lib/plug/ebin/Elixir.Plug.MIME.beam ================================================================== --- _build/dev/lib/plug/ebin/Elixir.Plug.MIME.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/plug/ebin/Elixir.Plug.MethodOverride.beam Index: _build/dev/lib/plug/ebin/Elixir.Plug.MethodOverride.beam ================================================================== --- _build/dev/lib/plug/ebin/Elixir.Plug.MethodOverride.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/plug/ebin/Elixir.Plug.Parsers.BadEncodingError.beam Index: _build/dev/lib/plug/ebin/Elixir.Plug.Parsers.BadEncodingError.beam ================================================================== --- _build/dev/lib/plug/ebin/Elixir.Plug.Parsers.BadEncodingError.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/plug/ebin/Elixir.Plug.Parsers.JSON.beam Index: _build/dev/lib/plug/ebin/Elixir.Plug.Parsers.JSON.beam ================================================================== --- _build/dev/lib/plug/ebin/Elixir.Plug.Parsers.JSON.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/plug/ebin/Elixir.Plug.Parsers.MULTIPART.beam Index: _build/dev/lib/plug/ebin/Elixir.Plug.Parsers.MULTIPART.beam ================================================================== --- _build/dev/lib/plug/ebin/Elixir.Plug.Parsers.MULTIPART.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/plug/ebin/Elixir.Plug.Parsers.ParseError.beam Index: _build/dev/lib/plug/ebin/Elixir.Plug.Parsers.ParseError.beam ================================================================== --- _build/dev/lib/plug/ebin/Elixir.Plug.Parsers.ParseError.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/plug/ebin/Elixir.Plug.Parsers.RequestTooLargeError.beam Index: _build/dev/lib/plug/ebin/Elixir.Plug.Parsers.RequestTooLargeError.beam ================================================================== --- _build/dev/lib/plug/ebin/Elixir.Plug.Parsers.RequestTooLargeError.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/plug/ebin/Elixir.Plug.Parsers.URLENCODED.beam Index: _build/dev/lib/plug/ebin/Elixir.Plug.Parsers.URLENCODED.beam ================================================================== --- _build/dev/lib/plug/ebin/Elixir.Plug.Parsers.URLENCODED.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/plug/ebin/Elixir.Plug.Parsers.UnsupportedMediaTypeError.beam Index: _build/dev/lib/plug/ebin/Elixir.Plug.Parsers.UnsupportedMediaTypeError.beam ================================================================== --- _build/dev/lib/plug/ebin/Elixir.Plug.Parsers.UnsupportedMediaTypeError.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/plug/ebin/Elixir.Plug.Parsers.beam Index: _build/dev/lib/plug/ebin/Elixir.Plug.Parsers.beam ================================================================== --- _build/dev/lib/plug/ebin/Elixir.Plug.Parsers.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/plug/ebin/Elixir.Plug.RequestId.beam Index: _build/dev/lib/plug/ebin/Elixir.Plug.RequestId.beam ================================================================== --- _build/dev/lib/plug/ebin/Elixir.Plug.RequestId.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/plug/ebin/Elixir.Plug.Router.InvalidSpecError.beam Index: _build/dev/lib/plug/ebin/Elixir.Plug.Router.InvalidSpecError.beam ================================================================== --- _build/dev/lib/plug/ebin/Elixir.Plug.Router.InvalidSpecError.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/plug/ebin/Elixir.Plug.Router.Utils.beam Index: _build/dev/lib/plug/ebin/Elixir.Plug.Router.Utils.beam ================================================================== --- _build/dev/lib/plug/ebin/Elixir.Plug.Router.Utils.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/plug/ebin/Elixir.Plug.Router.beam Index: _build/dev/lib/plug/ebin/Elixir.Plug.Router.beam ================================================================== --- _build/dev/lib/plug/ebin/Elixir.Plug.Router.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/plug/ebin/Elixir.Plug.SSL.beam Index: _build/dev/lib/plug/ebin/Elixir.Plug.SSL.beam ================================================================== --- _build/dev/lib/plug/ebin/Elixir.Plug.SSL.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/plug/ebin/Elixir.Plug.Session.COOKIE.beam Index: _build/dev/lib/plug/ebin/Elixir.Plug.Session.COOKIE.beam ================================================================== --- _build/dev/lib/plug/ebin/Elixir.Plug.Session.COOKIE.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/plug/ebin/Elixir.Plug.Session.ETS.beam Index: _build/dev/lib/plug/ebin/Elixir.Plug.Session.ETS.beam ================================================================== --- _build/dev/lib/plug/ebin/Elixir.Plug.Session.ETS.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/plug/ebin/Elixir.Plug.Session.Store.beam Index: _build/dev/lib/plug/ebin/Elixir.Plug.Session.Store.beam ================================================================== --- _build/dev/lib/plug/ebin/Elixir.Plug.Session.Store.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/plug/ebin/Elixir.Plug.Session.beam Index: _build/dev/lib/plug/ebin/Elixir.Plug.Session.beam ================================================================== --- _build/dev/lib/plug/ebin/Elixir.Plug.Session.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/plug/ebin/Elixir.Plug.Static.InvalidPathError.beam Index: _build/dev/lib/plug/ebin/Elixir.Plug.Static.InvalidPathError.beam ================================================================== --- _build/dev/lib/plug/ebin/Elixir.Plug.Static.InvalidPathError.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/plug/ebin/Elixir.Plug.Static.beam Index: _build/dev/lib/plug/ebin/Elixir.Plug.Static.beam ================================================================== --- _build/dev/lib/plug/ebin/Elixir.Plug.Static.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/plug/ebin/Elixir.Plug.Supervisor.beam Index: _build/dev/lib/plug/ebin/Elixir.Plug.Supervisor.beam ================================================================== --- _build/dev/lib/plug/ebin/Elixir.Plug.Supervisor.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/plug/ebin/Elixir.Plug.Test.beam Index: _build/dev/lib/plug/ebin/Elixir.Plug.Test.beam ================================================================== --- _build/dev/lib/plug/ebin/Elixir.Plug.Test.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/plug/ebin/Elixir.Plug.Upload.beam Index: _build/dev/lib/plug/ebin/Elixir.Plug.Upload.beam ================================================================== --- _build/dev/lib/plug/ebin/Elixir.Plug.Upload.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/plug/ebin/Elixir.Plug.beam Index: _build/dev/lib/plug/ebin/Elixir.Plug.beam ================================================================== --- _build/dev/lib/plug/ebin/Elixir.Plug.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/plug/ebin/plug.app Index: _build/dev/lib/plug/ebin/plug.app ================================================================== --- _build/dev/lib/plug/ebin/plug.app +++ /dev/null @@ -1,48 +0,0 @@ -{application,plug, - [{registered,[]}, - {description,"A specification and conveniences for composable modules between web applications"}, - {applications,[kernel,stdlib,elixir,crypto,logger]}, - {mod,{'Elixir.Plug',[]}}, - {vsn,"1.0.3"}, - {modules,['Elixir.Collectable.Plug.Conn', - 'Elixir.Inspect.Plug.Conn','Elixir.Plug', - 'Elixir.Plug.Adapters.Cowboy', - 'Elixir.Plug.Adapters.Cowboy.Conn', - 'Elixir.Plug.Adapters.Cowboy.Handler', - 'Elixir.Plug.Adapters.Test.Conn', - 'Elixir.Plug.Adapters.Translator', - 'Elixir.Plug.Builder','Elixir.Plug.CSRFProtection', - 'Elixir.Plug.CSRFProtection.InvalidCSRFTokenError', - 'Elixir.Plug.CSRFProtection.InvalidCrossOriginRequestError', - 'Elixir.Plug.Conn','Elixir.Plug.Conn.Adapter', - 'Elixir.Plug.Conn.AlreadySentError', - 'Elixir.Plug.Conn.Cookies', - 'Elixir.Plug.Conn.InvalidHeaderError', - 'Elixir.Plug.Conn.NotSentError', - 'Elixir.Plug.Conn.Query','Elixir.Plug.Conn.Status', - 'Elixir.Plug.Conn.Unfetched','Elixir.Plug.Conn.Utils', - 'Elixir.Plug.Conn.WrapperError','Elixir.Plug.Crypto', - 'Elixir.Plug.Crypto.KeyGenerator', - 'Elixir.Plug.Crypto.MessageEncryptor', - 'Elixir.Plug.Crypto.MessageVerifier', - 'Elixir.Plug.Debugger','Elixir.Plug.ErrorHandler', - 'Elixir.Plug.Exception','Elixir.Plug.Exception.Any', - 'Elixir.Plug.HTML','Elixir.Plug.Head', - 'Elixir.Plug.Logger','Elixir.Plug.MIME', - 'Elixir.Plug.MethodOverride','Elixir.Plug.Parsers', - 'Elixir.Plug.Parsers.BadEncodingError', - 'Elixir.Plug.Parsers.JSON', - 'Elixir.Plug.Parsers.MULTIPART', - 'Elixir.Plug.Parsers.ParseError', - 'Elixir.Plug.Parsers.RequestTooLargeError', - 'Elixir.Plug.Parsers.URLENCODED', - 'Elixir.Plug.Parsers.UnsupportedMediaTypeError', - 'Elixir.Plug.RequestId','Elixir.Plug.Router', - 'Elixir.Plug.Router.InvalidSpecError', - 'Elixir.Plug.Router.Utils','Elixir.Plug.SSL', - 'Elixir.Plug.Session','Elixir.Plug.Session.COOKIE', - 'Elixir.Plug.Session.ETS','Elixir.Plug.Session.Store', - 'Elixir.Plug.Static', - 'Elixir.Plug.Static.InvalidPathError', - 'Elixir.Plug.Supervisor','Elixir.Plug.Test', - 'Elixir.Plug.Upload']}]}. DELETED _build/dev/lib/ranch/ebin/ranch.app Index: _build/dev/lib/ranch/ebin/ranch.app ================================================================== --- _build/dev/lib/ranch/ebin/ranch.app +++ /dev/null @@ -1,12 +0,0 @@ -{application,ranch, - [{description,"Socket acceptor pool for TCP protocols."}, - {vsn,"1.2.0"}, - {id,"git"}, - {modules,[ranch,ranch_acceptor,ranch_acceptors_sup,ranch_app, - ranch_conns_sup,ranch_listener_sup,ranch_protocol, - ranch_server,ranch_ssl,ranch_sup,ranch_tcp, - ranch_transport]}, - {registered,[ranch_sup,ranch_server]}, - {applications,[kernel,stdlib]}, - {mod,{ranch_app,[]}}, - {env,[]}]}. DELETED _build/dev/lib/ranch/ebin/ranch.beam Index: _build/dev/lib/ranch/ebin/ranch.beam ================================================================== --- _build/dev/lib/ranch/ebin/ranch.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/ranch/ebin/ranch_acceptor.beam Index: _build/dev/lib/ranch/ebin/ranch_acceptor.beam ================================================================== --- _build/dev/lib/ranch/ebin/ranch_acceptor.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/ranch/ebin/ranch_acceptors_sup.beam Index: _build/dev/lib/ranch/ebin/ranch_acceptors_sup.beam ================================================================== --- _build/dev/lib/ranch/ebin/ranch_acceptors_sup.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/ranch/ebin/ranch_app.beam Index: _build/dev/lib/ranch/ebin/ranch_app.beam ================================================================== --- _build/dev/lib/ranch/ebin/ranch_app.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/ranch/ebin/ranch_conns_sup.beam Index: _build/dev/lib/ranch/ebin/ranch_conns_sup.beam ================================================================== --- _build/dev/lib/ranch/ebin/ranch_conns_sup.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/ranch/ebin/ranch_listener_sup.beam Index: _build/dev/lib/ranch/ebin/ranch_listener_sup.beam ================================================================== --- _build/dev/lib/ranch/ebin/ranch_listener_sup.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/ranch/ebin/ranch_protocol.beam Index: _build/dev/lib/ranch/ebin/ranch_protocol.beam ================================================================== --- _build/dev/lib/ranch/ebin/ranch_protocol.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/ranch/ebin/ranch_server.beam Index: _build/dev/lib/ranch/ebin/ranch_server.beam ================================================================== --- _build/dev/lib/ranch/ebin/ranch_server.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/ranch/ebin/ranch_ssl.beam Index: _build/dev/lib/ranch/ebin/ranch_ssl.beam ================================================================== --- _build/dev/lib/ranch/ebin/ranch_ssl.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/ranch/ebin/ranch_sup.beam Index: _build/dev/lib/ranch/ebin/ranch_sup.beam ================================================================== --- _build/dev/lib/ranch/ebin/ranch_sup.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/ranch/ebin/ranch_tcp.beam Index: _build/dev/lib/ranch/ebin/ranch_tcp.beam ================================================================== --- _build/dev/lib/ranch/ebin/ranch_tcp.beam +++ /dev/null cannot compute difference between binary files DELETED _build/dev/lib/ranch/ebin/ranch_transport.beam Index: _build/dev/lib/ranch/ebin/ranch_transport.beam ================================================================== --- _build/dev/lib/ranch/ebin/ranch_transport.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/antigone/ebin/Elixir.Antigone.beam Index: _build/test/lib/antigone/ebin/Elixir.Antigone.beam ================================================================== --- _build/test/lib/antigone/ebin/Elixir.Antigone.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/antigone/ebin/Elixir.Router.beam Index: _build/test/lib/antigone/ebin/Elixir.Router.beam ================================================================== --- _build/test/lib/antigone/ebin/Elixir.Router.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/antigone/ebin/antigone.app Index: _build/test/lib/antigone/ebin/antigone.app ================================================================== --- _build/test/lib/antigone/ebin/antigone.app +++ /dev/null @@ -1,7 +0,0 @@ -{application,antigone, - [{registered,[]}, - {description,"antigone"}, - {applications,[kernel,stdlib,elixir,logger,cowboy,plug]}, - {mod,{'Elixir.Antigone',[]}}, - {vsn,"0.0.1"}, - {modules,['Elixir.Antigone','Elixir.Router']}]}. DELETED _build/test/lib/cowboy/ebin/cowboy.app Index: _build/test/lib/cowboy/ebin/cowboy.app ================================================================== --- _build/test/lib/cowboy/ebin/cowboy.app +++ /dev/null @@ -1,14 +0,0 @@ -{application,cowboy, - [{description,"Small, fast, modular HTTP server."}, - {vsn,"1.0.4"}, - {id,"git"}, - {modules,[cowboy,cowboy_app,cowboy_bstr,cowboy_clock, - cowboy_handler,cowboy_http,cowboy_http_handler, - cowboy_loop_handler,cowboy_middleware,cowboy_protocol, - cowboy_req,cowboy_rest,cowboy_router,cowboy_spdy, - cowboy_static,cowboy_sub_protocol,cowboy_sup, - cowboy_websocket,cowboy_websocket_handler]}, - {registered,[cowboy_clock,cowboy_sup]}, - {applications,[kernel,stdlib,ranch,cowlib,crypto]}, - {mod,{cowboy_app,[]}}, - {env,[]}]}. DELETED _build/test/lib/cowboy/ebin/cowboy.beam Index: _build/test/lib/cowboy/ebin/cowboy.beam ================================================================== --- _build/test/lib/cowboy/ebin/cowboy.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/cowboy/ebin/cowboy_app.beam Index: _build/test/lib/cowboy/ebin/cowboy_app.beam ================================================================== --- _build/test/lib/cowboy/ebin/cowboy_app.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/cowboy/ebin/cowboy_bstr.beam Index: _build/test/lib/cowboy/ebin/cowboy_bstr.beam ================================================================== --- _build/test/lib/cowboy/ebin/cowboy_bstr.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/cowboy/ebin/cowboy_clock.beam Index: _build/test/lib/cowboy/ebin/cowboy_clock.beam ================================================================== --- _build/test/lib/cowboy/ebin/cowboy_clock.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/cowboy/ebin/cowboy_handler.beam Index: _build/test/lib/cowboy/ebin/cowboy_handler.beam ================================================================== --- _build/test/lib/cowboy/ebin/cowboy_handler.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/cowboy/ebin/cowboy_http.beam Index: _build/test/lib/cowboy/ebin/cowboy_http.beam ================================================================== --- _build/test/lib/cowboy/ebin/cowboy_http.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/cowboy/ebin/cowboy_http_handler.beam Index: _build/test/lib/cowboy/ebin/cowboy_http_handler.beam ================================================================== --- _build/test/lib/cowboy/ebin/cowboy_http_handler.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/cowboy/ebin/cowboy_loop_handler.beam Index: _build/test/lib/cowboy/ebin/cowboy_loop_handler.beam ================================================================== --- _build/test/lib/cowboy/ebin/cowboy_loop_handler.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/cowboy/ebin/cowboy_middleware.beam Index: _build/test/lib/cowboy/ebin/cowboy_middleware.beam ================================================================== --- _build/test/lib/cowboy/ebin/cowboy_middleware.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/cowboy/ebin/cowboy_protocol.beam Index: _build/test/lib/cowboy/ebin/cowboy_protocol.beam ================================================================== --- _build/test/lib/cowboy/ebin/cowboy_protocol.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/cowboy/ebin/cowboy_req.beam Index: _build/test/lib/cowboy/ebin/cowboy_req.beam ================================================================== --- _build/test/lib/cowboy/ebin/cowboy_req.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/cowboy/ebin/cowboy_rest.beam Index: _build/test/lib/cowboy/ebin/cowboy_rest.beam ================================================================== --- _build/test/lib/cowboy/ebin/cowboy_rest.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/cowboy/ebin/cowboy_router.beam Index: _build/test/lib/cowboy/ebin/cowboy_router.beam ================================================================== --- _build/test/lib/cowboy/ebin/cowboy_router.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/cowboy/ebin/cowboy_spdy.beam Index: _build/test/lib/cowboy/ebin/cowboy_spdy.beam ================================================================== --- _build/test/lib/cowboy/ebin/cowboy_spdy.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/cowboy/ebin/cowboy_static.beam Index: _build/test/lib/cowboy/ebin/cowboy_static.beam ================================================================== --- _build/test/lib/cowboy/ebin/cowboy_static.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/cowboy/ebin/cowboy_sub_protocol.beam Index: _build/test/lib/cowboy/ebin/cowboy_sub_protocol.beam ================================================================== --- _build/test/lib/cowboy/ebin/cowboy_sub_protocol.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/cowboy/ebin/cowboy_sup.beam Index: _build/test/lib/cowboy/ebin/cowboy_sup.beam ================================================================== --- _build/test/lib/cowboy/ebin/cowboy_sup.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/cowboy/ebin/cowboy_websocket.beam Index: _build/test/lib/cowboy/ebin/cowboy_websocket.beam ================================================================== --- _build/test/lib/cowboy/ebin/cowboy_websocket.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/cowboy/ebin/cowboy_websocket_handler.beam Index: _build/test/lib/cowboy/ebin/cowboy_websocket_handler.beam ================================================================== --- _build/test/lib/cowboy/ebin/cowboy_websocket_handler.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/cowlib/ebin/cow_cookie.beam Index: _build/test/lib/cowlib/ebin/cow_cookie.beam ================================================================== --- _build/test/lib/cowlib/ebin/cow_cookie.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/cowlib/ebin/cow_date.beam Index: _build/test/lib/cowlib/ebin/cow_date.beam ================================================================== --- _build/test/lib/cowlib/ebin/cow_date.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/cowlib/ebin/cow_http.beam Index: _build/test/lib/cowlib/ebin/cow_http.beam ================================================================== --- _build/test/lib/cowlib/ebin/cow_http.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/cowlib/ebin/cow_http_hd.beam Index: _build/test/lib/cowlib/ebin/cow_http_hd.beam ================================================================== --- _build/test/lib/cowlib/ebin/cow_http_hd.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/cowlib/ebin/cow_http_te.beam Index: _build/test/lib/cowlib/ebin/cow_http_te.beam ================================================================== --- _build/test/lib/cowlib/ebin/cow_http_te.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/cowlib/ebin/cow_mimetypes.beam Index: _build/test/lib/cowlib/ebin/cow_mimetypes.beam ================================================================== --- _build/test/lib/cowlib/ebin/cow_mimetypes.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/cowlib/ebin/cow_multipart.beam Index: _build/test/lib/cowlib/ebin/cow_multipart.beam ================================================================== --- _build/test/lib/cowlib/ebin/cow_multipart.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/cowlib/ebin/cow_qs.beam Index: _build/test/lib/cowlib/ebin/cow_qs.beam ================================================================== --- _build/test/lib/cowlib/ebin/cow_qs.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/cowlib/ebin/cow_spdy.beam Index: _build/test/lib/cowlib/ebin/cow_spdy.beam ================================================================== --- _build/test/lib/cowlib/ebin/cow_spdy.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/cowlib/ebin/cowlib.app Index: _build/test/lib/cowlib/ebin/cowlib.app ================================================================== --- _build/test/lib/cowlib/ebin/cowlib.app +++ /dev/null @@ -1,8 +0,0 @@ -{application,cowlib, - [{description,"Support library for manipulating Web protocols."}, - {vsn,"1.0.2"}, - {id,"git"}, - {modules,[cow_cookie,cow_date,cow_http,cow_http_hd,cow_http_te, - cow_mimetypes,cow_multipart,cow_qs,cow_spdy]}, - {registered,[]}, - {applications,[kernel,stdlib,crypto]}]}. DELETED _build/test/lib/cowlib/include/cow_inline.hrl Index: _build/test/lib/cowlib/include/cow_inline.hrl ================================================================== --- _build/test/lib/cowlib/include/cow_inline.hrl +++ /dev/null @@ -1,388 +0,0 @@ -%% Copyright (c) 2014, Loïc Hoguin -%% -%% Permission to use, copy, modify, and/or distribute this software for any -%% purpose with or without fee is hereby granted, provided that the above -%% copyright notice and this permission notice appear in all copies. -%% -%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - --ifndef(COW_INLINE_HRL). --define(COW_INLINE_HRL, 1). - -%% INLINE_LOWERCASE(Function, Rest, Acc, ...) -%% -%% To be included at the end of a case block. -%% Defined for up to 10 extra arguments. - --define(INLINE_LOWERCASE(Function, Rest, Acc), - $A -> Function(Rest, << Acc/binary, $a >>); - $B -> Function(Rest, << Acc/binary, $b >>); - $C -> Function(Rest, << Acc/binary, $c >>); - $D -> Function(Rest, << Acc/binary, $d >>); - $E -> Function(Rest, << Acc/binary, $e >>); - $F -> Function(Rest, << Acc/binary, $f >>); - $G -> Function(Rest, << Acc/binary, $g >>); - $H -> Function(Rest, << Acc/binary, $h >>); - $I -> Function(Rest, << Acc/binary, $i >>); - $J -> Function(Rest, << Acc/binary, $j >>); - $K -> Function(Rest, << Acc/binary, $k >>); - $L -> Function(Rest, << Acc/binary, $l >>); - $M -> Function(Rest, << Acc/binary, $m >>); - $N -> Function(Rest, << Acc/binary, $n >>); - $O -> Function(Rest, << Acc/binary, $o >>); - $P -> Function(Rest, << Acc/binary, $p >>); - $Q -> Function(Rest, << Acc/binary, $q >>); - $R -> Function(Rest, << Acc/binary, $r >>); - $S -> Function(Rest, << Acc/binary, $s >>); - $T -> Function(Rest, << Acc/binary, $t >>); - $U -> Function(Rest, << Acc/binary, $u >>); - $V -> Function(Rest, << Acc/binary, $v >>); - $W -> Function(Rest, << Acc/binary, $w >>); - $X -> Function(Rest, << Acc/binary, $x >>); - $Y -> Function(Rest, << Acc/binary, $y >>); - $Z -> Function(Rest, << Acc/binary, $z >>); - C -> Function(Rest, << Acc/binary, C >>) -). - --define(INLINE_LOWERCASE(Function, Rest, A0, Acc), - $A -> Function(Rest, A0, << Acc/binary, $a >>); - $B -> Function(Rest, A0, << Acc/binary, $b >>); - $C -> Function(Rest, A0, << Acc/binary, $c >>); - $D -> Function(Rest, A0, << Acc/binary, $d >>); - $E -> Function(Rest, A0, << Acc/binary, $e >>); - $F -> Function(Rest, A0, << Acc/binary, $f >>); - $G -> Function(Rest, A0, << Acc/binary, $g >>); - $H -> Function(Rest, A0, << Acc/binary, $h >>); - $I -> Function(Rest, A0, << Acc/binary, $i >>); - $J -> Function(Rest, A0, << Acc/binary, $j >>); - $K -> Function(Rest, A0, << Acc/binary, $k >>); - $L -> Function(Rest, A0, << Acc/binary, $l >>); - $M -> Function(Rest, A0, << Acc/binary, $m >>); - $N -> Function(Rest, A0, << Acc/binary, $n >>); - $O -> Function(Rest, A0, << Acc/binary, $o >>); - $P -> Function(Rest, A0, << Acc/binary, $p >>); - $Q -> Function(Rest, A0, << Acc/binary, $q >>); - $R -> Function(Rest, A0, << Acc/binary, $r >>); - $S -> Function(Rest, A0, << Acc/binary, $s >>); - $T -> Function(Rest, A0, << Acc/binary, $t >>); - $U -> Function(Rest, A0, << Acc/binary, $u >>); - $V -> Function(Rest, A0, << Acc/binary, $v >>); - $W -> Function(Rest, A0, << Acc/binary, $w >>); - $X -> Function(Rest, A0, << Acc/binary, $x >>); - $Y -> Function(Rest, A0, << Acc/binary, $y >>); - $Z -> Function(Rest, A0, << Acc/binary, $z >>); - C -> Function(Rest, A0, << Acc/binary, C >>) -). - --define(INLINE_LOWERCASE(Function, Rest, A0, A1, Acc), - $A -> Function(Rest, A0, A1, << Acc/binary, $a >>); - $B -> Function(Rest, A0, A1, << Acc/binary, $b >>); - $C -> Function(Rest, A0, A1, << Acc/binary, $c >>); - $D -> Function(Rest, A0, A1, << Acc/binary, $d >>); - $E -> Function(Rest, A0, A1, << Acc/binary, $e >>); - $F -> Function(Rest, A0, A1, << Acc/binary, $f >>); - $G -> Function(Rest, A0, A1, << Acc/binary, $g >>); - $H -> Function(Rest, A0, A1, << Acc/binary, $h >>); - $I -> Function(Rest, A0, A1, << Acc/binary, $i >>); - $J -> Function(Rest, A0, A1, << Acc/binary, $j >>); - $K -> Function(Rest, A0, A1, << Acc/binary, $k >>); - $L -> Function(Rest, A0, A1, << Acc/binary, $l >>); - $M -> Function(Rest, A0, A1, << Acc/binary, $m >>); - $N -> Function(Rest, A0, A1, << Acc/binary, $n >>); - $O -> Function(Rest, A0, A1, << Acc/binary, $o >>); - $P -> Function(Rest, A0, A1, << Acc/binary, $p >>); - $Q -> Function(Rest, A0, A1, << Acc/binary, $q >>); - $R -> Function(Rest, A0, A1, << Acc/binary, $r >>); - $S -> Function(Rest, A0, A1, << Acc/binary, $s >>); - $T -> Function(Rest, A0, A1, << Acc/binary, $t >>); - $U -> Function(Rest, A0, A1, << Acc/binary, $u >>); - $V -> Function(Rest, A0, A1, << Acc/binary, $v >>); - $W -> Function(Rest, A0, A1, << Acc/binary, $w >>); - $X -> Function(Rest, A0, A1, << Acc/binary, $x >>); - $Y -> Function(Rest, A0, A1, << Acc/binary, $y >>); - $Z -> Function(Rest, A0, A1, << Acc/binary, $z >>); - C -> Function(Rest, A0, A1, << Acc/binary, C >>) -). - --define(INLINE_LOWERCASE(Function, Rest, A0, A1, A2, Acc), - $A -> Function(Rest, A0, A1, A2, << Acc/binary, $a >>); - $B -> Function(Rest, A0, A1, A2, << Acc/binary, $b >>); - $C -> Function(Rest, A0, A1, A2, << Acc/binary, $c >>); - $D -> Function(Rest, A0, A1, A2, << Acc/binary, $d >>); - $E -> Function(Rest, A0, A1, A2, << Acc/binary, $e >>); - $F -> Function(Rest, A0, A1, A2, << Acc/binary, $f >>); - $G -> Function(Rest, A0, A1, A2, << Acc/binary, $g >>); - $H -> Function(Rest, A0, A1, A2, << Acc/binary, $h >>); - $I -> Function(Rest, A0, A1, A2, << Acc/binary, $i >>); - $J -> Function(Rest, A0, A1, A2, << Acc/binary, $j >>); - $K -> Function(Rest, A0, A1, A2, << Acc/binary, $k >>); - $L -> Function(Rest, A0, A1, A2, << Acc/binary, $l >>); - $M -> Function(Rest, A0, A1, A2, << Acc/binary, $m >>); - $N -> Function(Rest, A0, A1, A2, << Acc/binary, $n >>); - $O -> Function(Rest, A0, A1, A2, << Acc/binary, $o >>); - $P -> Function(Rest, A0, A1, A2, << Acc/binary, $p >>); - $Q -> Function(Rest, A0, A1, A2, << Acc/binary, $q >>); - $R -> Function(Rest, A0, A1, A2, << Acc/binary, $r >>); - $S -> Function(Rest, A0, A1, A2, << Acc/binary, $s >>); - $T -> Function(Rest, A0, A1, A2, << Acc/binary, $t >>); - $U -> Function(Rest, A0, A1, A2, << Acc/binary, $u >>); - $V -> Function(Rest, A0, A1, A2, << Acc/binary, $v >>); - $W -> Function(Rest, A0, A1, A2, << Acc/binary, $w >>); - $X -> Function(Rest, A0, A1, A2, << Acc/binary, $x >>); - $Y -> Function(Rest, A0, A1, A2, << Acc/binary, $y >>); - $Z -> Function(Rest, A0, A1, A2, << Acc/binary, $z >>); - C -> Function(Rest, A0, A1, A2, << Acc/binary, C >>) -). - --define(INLINE_LOWERCASE(Function, Rest, A0, A1, A2, A3, Acc), - $A -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $a >>); - $B -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $b >>); - $C -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $c >>); - $D -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $d >>); - $E -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $e >>); - $F -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $f >>); - $G -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $g >>); - $H -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $h >>); - $I -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $i >>); - $J -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $j >>); - $K -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $k >>); - $L -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $l >>); - $M -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $m >>); - $N -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $n >>); - $O -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $o >>); - $P -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $p >>); - $Q -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $q >>); - $R -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $r >>); - $S -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $s >>); - $T -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $t >>); - $U -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $u >>); - $V -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $v >>); - $W -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $w >>); - $X -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $x >>); - $Y -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $y >>); - $Z -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $z >>); - C -> Function(Rest, A0, A1, A2, A3, << Acc/binary, C >>) -). - --define(INLINE_LOWERCASE(Function, Rest, A0, A1, A2, A3, A4, Acc), - $A -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $a >>); - $B -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $b >>); - $C -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $c >>); - $D -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $d >>); - $E -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $e >>); - $F -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $f >>); - $G -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $g >>); - $H -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $h >>); - $I -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $i >>); - $J -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $j >>); - $K -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $k >>); - $L -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $l >>); - $M -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $m >>); - $N -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $n >>); - $O -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $o >>); - $P -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $p >>); - $Q -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $q >>); - $R -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $r >>); - $S -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $s >>); - $T -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $t >>); - $U -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $u >>); - $V -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $v >>); - $W -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $w >>); - $X -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $x >>); - $Y -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $y >>); - $Z -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $z >>); - C -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, C >>) -). - --define(INLINE_LOWERCASE(Function, Rest, A0, A1, A2, A3, A4, A5, Acc), - $A -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $a >>); - $B -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $b >>); - $C -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $c >>); - $D -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $d >>); - $E -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $e >>); - $F -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $f >>); - $G -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $g >>); - $H -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $h >>); - $I -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $i >>); - $J -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $j >>); - $K -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $k >>); - $L -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $l >>); - $M -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $m >>); - $N -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $n >>); - $O -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $o >>); - $P -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $p >>); - $Q -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $q >>); - $R -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $r >>); - $S -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $s >>); - $T -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $t >>); - $U -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $u >>); - $V -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $v >>); - $W -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $w >>); - $X -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $x >>); - $Y -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $y >>); - $Z -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $z >>); - C -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, C >>) -). - --define(INLINE_LOWERCASE(Function, Rest, A0, A1, A2, A3, A4, A5, A6, Acc), - $A -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $a >>); - $B -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $b >>); - $C -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $c >>); - $D -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $d >>); - $E -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $e >>); - $F -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $f >>); - $G -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $g >>); - $H -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $h >>); - $I -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $i >>); - $J -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $j >>); - $K -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $k >>); - $L -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $l >>); - $M -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $m >>); - $N -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $n >>); - $O -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $o >>); - $P -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $p >>); - $Q -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $q >>); - $R -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $r >>); - $S -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $s >>); - $T -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $t >>); - $U -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $u >>); - $V -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $v >>); - $W -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $w >>); - $X -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $x >>); - $Y -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $y >>); - $Z -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $z >>); - C -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, C >>) -). - --define(INLINE_LOWERCASE(Function, Rest, A0, A1, A2, A3, A4, A5, A6, A7, Acc), - $A -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $a >>); - $B -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $b >>); - $C -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $c >>); - $D -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $d >>); - $E -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $e >>); - $F -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $f >>); - $G -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $g >>); - $H -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $h >>); - $I -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $i >>); - $J -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $j >>); - $K -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $k >>); - $L -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $l >>); - $M -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $m >>); - $N -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $n >>); - $O -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $o >>); - $P -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $p >>); - $Q -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $q >>); - $R -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $r >>); - $S -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $s >>); - $T -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $t >>); - $U -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $u >>); - $V -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $v >>); - $W -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $w >>); - $X -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $x >>); - $Y -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $y >>); - $Z -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $z >>); - C -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, C >>) -). - --define(INLINE_LOWERCASE(Function, Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, Acc), - $A -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $a >>); - $B -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $b >>); - $C -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $c >>); - $D -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $d >>); - $E -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $e >>); - $F -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $f >>); - $G -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $g >>); - $H -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $h >>); - $I -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $i >>); - $J -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $j >>); - $K -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $k >>); - $L -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $l >>); - $M -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $m >>); - $N -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $n >>); - $O -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $o >>); - $P -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $p >>); - $Q -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $q >>); - $R -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $r >>); - $S -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $s >>); - $T -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $t >>); - $U -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $u >>); - $V -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $v >>); - $W -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $w >>); - $X -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $x >>); - $Y -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $y >>); - $Z -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $z >>); - C -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, C >>) -). - --define(INLINE_LOWERCASE(Function, Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, Acc), - $A -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $a >>); - $B -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $b >>); - $C -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $c >>); - $D -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $d >>); - $E -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $e >>); - $F -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $f >>); - $G -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $g >>); - $H -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $h >>); - $I -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $i >>); - $J -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $j >>); - $K -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $k >>); - $L -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $l >>); - $M -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $m >>); - $N -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $n >>); - $O -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $o >>); - $P -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $p >>); - $Q -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $q >>); - $R -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $r >>); - $S -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $s >>); - $T -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $t >>); - $U -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $u >>); - $V -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $v >>); - $W -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $w >>); - $X -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $x >>); - $Y -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $y >>); - $Z -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $z >>); - C -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, C >>) -). - -%% INLINE_LOWERCASE_BC(Bin) -%% -%% Lowercase the entire binary string in a binary comprehension. - --define(INLINE_LOWERCASE_BC(Bin), - << << case C of - $A -> $a; - $B -> $b; - $C -> $c; - $D -> $d; - $E -> $e; - $F -> $f; - $G -> $g; - $H -> $h; - $I -> $i; - $J -> $j; - $K -> $k; - $L -> $l; - $M -> $m; - $N -> $n; - $O -> $o; - $P -> $p; - $Q -> $q; - $R -> $r; - $S -> $s; - $T -> $t; - $U -> $u; - $V -> $v; - $W -> $w; - $X -> $x; - $Y -> $y; - $Z -> $z; - C -> C - end >> || << C >> <= Bin >>). - --endif. DELETED _build/test/lib/plug/ebin/Elixir.Collectable.Plug.Conn.beam Index: _build/test/lib/plug/ebin/Elixir.Collectable.Plug.Conn.beam ================================================================== --- _build/test/lib/plug/ebin/Elixir.Collectable.Plug.Conn.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/plug/ebin/Elixir.Inspect.Plug.Conn.beam Index: _build/test/lib/plug/ebin/Elixir.Inspect.Plug.Conn.beam ================================================================== --- _build/test/lib/plug/ebin/Elixir.Inspect.Plug.Conn.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/plug/ebin/Elixir.Plug.Adapters.Cowboy.Conn.beam Index: _build/test/lib/plug/ebin/Elixir.Plug.Adapters.Cowboy.Conn.beam ================================================================== --- _build/test/lib/plug/ebin/Elixir.Plug.Adapters.Cowboy.Conn.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/plug/ebin/Elixir.Plug.Adapters.Cowboy.Handler.beam Index: _build/test/lib/plug/ebin/Elixir.Plug.Adapters.Cowboy.Handler.beam ================================================================== --- _build/test/lib/plug/ebin/Elixir.Plug.Adapters.Cowboy.Handler.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/plug/ebin/Elixir.Plug.Adapters.Cowboy.beam Index: _build/test/lib/plug/ebin/Elixir.Plug.Adapters.Cowboy.beam ================================================================== --- _build/test/lib/plug/ebin/Elixir.Plug.Adapters.Cowboy.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/plug/ebin/Elixir.Plug.Adapters.Test.Conn.beam Index: _build/test/lib/plug/ebin/Elixir.Plug.Adapters.Test.Conn.beam ================================================================== --- _build/test/lib/plug/ebin/Elixir.Plug.Adapters.Test.Conn.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/plug/ebin/Elixir.Plug.Adapters.Translator.beam Index: _build/test/lib/plug/ebin/Elixir.Plug.Adapters.Translator.beam ================================================================== --- _build/test/lib/plug/ebin/Elixir.Plug.Adapters.Translator.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/plug/ebin/Elixir.Plug.Builder.beam Index: _build/test/lib/plug/ebin/Elixir.Plug.Builder.beam ================================================================== --- _build/test/lib/plug/ebin/Elixir.Plug.Builder.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/plug/ebin/Elixir.Plug.CSRFProtection.InvalidCSRFTokenError.beam Index: _build/test/lib/plug/ebin/Elixir.Plug.CSRFProtection.InvalidCSRFTokenError.beam ================================================================== --- _build/test/lib/plug/ebin/Elixir.Plug.CSRFProtection.InvalidCSRFTokenError.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/plug/ebin/Elixir.Plug.CSRFProtection.InvalidCrossOriginRequestError.beam Index: _build/test/lib/plug/ebin/Elixir.Plug.CSRFProtection.InvalidCrossOriginRequestError.beam ================================================================== --- _build/test/lib/plug/ebin/Elixir.Plug.CSRFProtection.InvalidCrossOriginRequestError.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/plug/ebin/Elixir.Plug.CSRFProtection.beam Index: _build/test/lib/plug/ebin/Elixir.Plug.CSRFProtection.beam ================================================================== --- _build/test/lib/plug/ebin/Elixir.Plug.CSRFProtection.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/plug/ebin/Elixir.Plug.Conn.Adapter.beam Index: _build/test/lib/plug/ebin/Elixir.Plug.Conn.Adapter.beam ================================================================== --- _build/test/lib/plug/ebin/Elixir.Plug.Conn.Adapter.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/plug/ebin/Elixir.Plug.Conn.AlreadySentError.beam Index: _build/test/lib/plug/ebin/Elixir.Plug.Conn.AlreadySentError.beam ================================================================== --- _build/test/lib/plug/ebin/Elixir.Plug.Conn.AlreadySentError.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/plug/ebin/Elixir.Plug.Conn.Cookies.beam Index: _build/test/lib/plug/ebin/Elixir.Plug.Conn.Cookies.beam ================================================================== --- _build/test/lib/plug/ebin/Elixir.Plug.Conn.Cookies.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/plug/ebin/Elixir.Plug.Conn.InvalidHeaderError.beam Index: _build/test/lib/plug/ebin/Elixir.Plug.Conn.InvalidHeaderError.beam ================================================================== --- _build/test/lib/plug/ebin/Elixir.Plug.Conn.InvalidHeaderError.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/plug/ebin/Elixir.Plug.Conn.NotSentError.beam Index: _build/test/lib/plug/ebin/Elixir.Plug.Conn.NotSentError.beam ================================================================== --- _build/test/lib/plug/ebin/Elixir.Plug.Conn.NotSentError.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/plug/ebin/Elixir.Plug.Conn.Query.beam Index: _build/test/lib/plug/ebin/Elixir.Plug.Conn.Query.beam ================================================================== --- _build/test/lib/plug/ebin/Elixir.Plug.Conn.Query.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/plug/ebin/Elixir.Plug.Conn.Status.beam Index: _build/test/lib/plug/ebin/Elixir.Plug.Conn.Status.beam ================================================================== --- _build/test/lib/plug/ebin/Elixir.Plug.Conn.Status.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/plug/ebin/Elixir.Plug.Conn.Unfetched.beam Index: _build/test/lib/plug/ebin/Elixir.Plug.Conn.Unfetched.beam ================================================================== --- _build/test/lib/plug/ebin/Elixir.Plug.Conn.Unfetched.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/plug/ebin/Elixir.Plug.Conn.Utils.beam Index: _build/test/lib/plug/ebin/Elixir.Plug.Conn.Utils.beam ================================================================== --- _build/test/lib/plug/ebin/Elixir.Plug.Conn.Utils.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/plug/ebin/Elixir.Plug.Conn.WrapperError.beam Index: _build/test/lib/plug/ebin/Elixir.Plug.Conn.WrapperError.beam ================================================================== --- _build/test/lib/plug/ebin/Elixir.Plug.Conn.WrapperError.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/plug/ebin/Elixir.Plug.Conn.beam Index: _build/test/lib/plug/ebin/Elixir.Plug.Conn.beam ================================================================== --- _build/test/lib/plug/ebin/Elixir.Plug.Conn.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/plug/ebin/Elixir.Plug.Crypto.KeyGenerator.beam Index: _build/test/lib/plug/ebin/Elixir.Plug.Crypto.KeyGenerator.beam ================================================================== --- _build/test/lib/plug/ebin/Elixir.Plug.Crypto.KeyGenerator.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/plug/ebin/Elixir.Plug.Crypto.MessageEncryptor.beam Index: _build/test/lib/plug/ebin/Elixir.Plug.Crypto.MessageEncryptor.beam ================================================================== --- _build/test/lib/plug/ebin/Elixir.Plug.Crypto.MessageEncryptor.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/plug/ebin/Elixir.Plug.Crypto.MessageVerifier.beam Index: _build/test/lib/plug/ebin/Elixir.Plug.Crypto.MessageVerifier.beam ================================================================== --- _build/test/lib/plug/ebin/Elixir.Plug.Crypto.MessageVerifier.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/plug/ebin/Elixir.Plug.Crypto.beam Index: _build/test/lib/plug/ebin/Elixir.Plug.Crypto.beam ================================================================== --- _build/test/lib/plug/ebin/Elixir.Plug.Crypto.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/plug/ebin/Elixir.Plug.Debugger.beam Index: _build/test/lib/plug/ebin/Elixir.Plug.Debugger.beam ================================================================== --- _build/test/lib/plug/ebin/Elixir.Plug.Debugger.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/plug/ebin/Elixir.Plug.ErrorHandler.beam Index: _build/test/lib/plug/ebin/Elixir.Plug.ErrorHandler.beam ================================================================== --- _build/test/lib/plug/ebin/Elixir.Plug.ErrorHandler.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/plug/ebin/Elixir.Plug.Exception.Any.beam Index: _build/test/lib/plug/ebin/Elixir.Plug.Exception.Any.beam ================================================================== --- _build/test/lib/plug/ebin/Elixir.Plug.Exception.Any.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/plug/ebin/Elixir.Plug.Exception.beam Index: _build/test/lib/plug/ebin/Elixir.Plug.Exception.beam ================================================================== --- _build/test/lib/plug/ebin/Elixir.Plug.Exception.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/plug/ebin/Elixir.Plug.HTML.beam Index: _build/test/lib/plug/ebin/Elixir.Plug.HTML.beam ================================================================== --- _build/test/lib/plug/ebin/Elixir.Plug.HTML.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/plug/ebin/Elixir.Plug.Head.beam Index: _build/test/lib/plug/ebin/Elixir.Plug.Head.beam ================================================================== --- _build/test/lib/plug/ebin/Elixir.Plug.Head.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/plug/ebin/Elixir.Plug.Logger.beam Index: _build/test/lib/plug/ebin/Elixir.Plug.Logger.beam ================================================================== --- _build/test/lib/plug/ebin/Elixir.Plug.Logger.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/plug/ebin/Elixir.Plug.MIME.beam Index: _build/test/lib/plug/ebin/Elixir.Plug.MIME.beam ================================================================== --- _build/test/lib/plug/ebin/Elixir.Plug.MIME.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/plug/ebin/Elixir.Plug.MethodOverride.beam Index: _build/test/lib/plug/ebin/Elixir.Plug.MethodOverride.beam ================================================================== --- _build/test/lib/plug/ebin/Elixir.Plug.MethodOverride.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/plug/ebin/Elixir.Plug.Parsers.BadEncodingError.beam Index: _build/test/lib/plug/ebin/Elixir.Plug.Parsers.BadEncodingError.beam ================================================================== --- _build/test/lib/plug/ebin/Elixir.Plug.Parsers.BadEncodingError.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/plug/ebin/Elixir.Plug.Parsers.JSON.beam Index: _build/test/lib/plug/ebin/Elixir.Plug.Parsers.JSON.beam ================================================================== --- _build/test/lib/plug/ebin/Elixir.Plug.Parsers.JSON.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/plug/ebin/Elixir.Plug.Parsers.MULTIPART.beam Index: _build/test/lib/plug/ebin/Elixir.Plug.Parsers.MULTIPART.beam ================================================================== --- _build/test/lib/plug/ebin/Elixir.Plug.Parsers.MULTIPART.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/plug/ebin/Elixir.Plug.Parsers.ParseError.beam Index: _build/test/lib/plug/ebin/Elixir.Plug.Parsers.ParseError.beam ================================================================== --- _build/test/lib/plug/ebin/Elixir.Plug.Parsers.ParseError.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/plug/ebin/Elixir.Plug.Parsers.RequestTooLargeError.beam Index: _build/test/lib/plug/ebin/Elixir.Plug.Parsers.RequestTooLargeError.beam ================================================================== --- _build/test/lib/plug/ebin/Elixir.Plug.Parsers.RequestTooLargeError.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/plug/ebin/Elixir.Plug.Parsers.URLENCODED.beam Index: _build/test/lib/plug/ebin/Elixir.Plug.Parsers.URLENCODED.beam ================================================================== --- _build/test/lib/plug/ebin/Elixir.Plug.Parsers.URLENCODED.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/plug/ebin/Elixir.Plug.Parsers.UnsupportedMediaTypeError.beam Index: _build/test/lib/plug/ebin/Elixir.Plug.Parsers.UnsupportedMediaTypeError.beam ================================================================== --- _build/test/lib/plug/ebin/Elixir.Plug.Parsers.UnsupportedMediaTypeError.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/plug/ebin/Elixir.Plug.Parsers.beam Index: _build/test/lib/plug/ebin/Elixir.Plug.Parsers.beam ================================================================== --- _build/test/lib/plug/ebin/Elixir.Plug.Parsers.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/plug/ebin/Elixir.Plug.RequestId.beam Index: _build/test/lib/plug/ebin/Elixir.Plug.RequestId.beam ================================================================== --- _build/test/lib/plug/ebin/Elixir.Plug.RequestId.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/plug/ebin/Elixir.Plug.Router.InvalidSpecError.beam Index: _build/test/lib/plug/ebin/Elixir.Plug.Router.InvalidSpecError.beam ================================================================== --- _build/test/lib/plug/ebin/Elixir.Plug.Router.InvalidSpecError.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/plug/ebin/Elixir.Plug.Router.Utils.beam Index: _build/test/lib/plug/ebin/Elixir.Plug.Router.Utils.beam ================================================================== --- _build/test/lib/plug/ebin/Elixir.Plug.Router.Utils.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/plug/ebin/Elixir.Plug.Router.beam Index: _build/test/lib/plug/ebin/Elixir.Plug.Router.beam ================================================================== --- _build/test/lib/plug/ebin/Elixir.Plug.Router.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/plug/ebin/Elixir.Plug.SSL.beam Index: _build/test/lib/plug/ebin/Elixir.Plug.SSL.beam ================================================================== --- _build/test/lib/plug/ebin/Elixir.Plug.SSL.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/plug/ebin/Elixir.Plug.Session.COOKIE.beam Index: _build/test/lib/plug/ebin/Elixir.Plug.Session.COOKIE.beam ================================================================== --- _build/test/lib/plug/ebin/Elixir.Plug.Session.COOKIE.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/plug/ebin/Elixir.Plug.Session.ETS.beam Index: _build/test/lib/plug/ebin/Elixir.Plug.Session.ETS.beam ================================================================== --- _build/test/lib/plug/ebin/Elixir.Plug.Session.ETS.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/plug/ebin/Elixir.Plug.Session.Store.beam Index: _build/test/lib/plug/ebin/Elixir.Plug.Session.Store.beam ================================================================== --- _build/test/lib/plug/ebin/Elixir.Plug.Session.Store.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/plug/ebin/Elixir.Plug.Session.beam Index: _build/test/lib/plug/ebin/Elixir.Plug.Session.beam ================================================================== --- _build/test/lib/plug/ebin/Elixir.Plug.Session.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/plug/ebin/Elixir.Plug.Static.InvalidPathError.beam Index: _build/test/lib/plug/ebin/Elixir.Plug.Static.InvalidPathError.beam ================================================================== --- _build/test/lib/plug/ebin/Elixir.Plug.Static.InvalidPathError.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/plug/ebin/Elixir.Plug.Static.beam Index: _build/test/lib/plug/ebin/Elixir.Plug.Static.beam ================================================================== --- _build/test/lib/plug/ebin/Elixir.Plug.Static.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/plug/ebin/Elixir.Plug.Supervisor.beam Index: _build/test/lib/plug/ebin/Elixir.Plug.Supervisor.beam ================================================================== --- _build/test/lib/plug/ebin/Elixir.Plug.Supervisor.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/plug/ebin/Elixir.Plug.Test.beam Index: _build/test/lib/plug/ebin/Elixir.Plug.Test.beam ================================================================== --- _build/test/lib/plug/ebin/Elixir.Plug.Test.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/plug/ebin/Elixir.Plug.Upload.beam Index: _build/test/lib/plug/ebin/Elixir.Plug.Upload.beam ================================================================== --- _build/test/lib/plug/ebin/Elixir.Plug.Upload.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/plug/ebin/Elixir.Plug.beam Index: _build/test/lib/plug/ebin/Elixir.Plug.beam ================================================================== --- _build/test/lib/plug/ebin/Elixir.Plug.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/plug/ebin/plug.app Index: _build/test/lib/plug/ebin/plug.app ================================================================== --- _build/test/lib/plug/ebin/plug.app +++ /dev/null @@ -1,48 +0,0 @@ -{application,plug, - [{registered,[]}, - {description,"A specification and conveniences for composable modules between web applications"}, - {applications,[kernel,stdlib,elixir,crypto,logger]}, - {mod,{'Elixir.Plug',[]}}, - {vsn,"1.0.3"}, - {modules,['Elixir.Collectable.Plug.Conn', - 'Elixir.Inspect.Plug.Conn','Elixir.Plug', - 'Elixir.Plug.Adapters.Cowboy', - 'Elixir.Plug.Adapters.Cowboy.Conn', - 'Elixir.Plug.Adapters.Cowboy.Handler', - 'Elixir.Plug.Adapters.Test.Conn', - 'Elixir.Plug.Adapters.Translator', - 'Elixir.Plug.Builder','Elixir.Plug.CSRFProtection', - 'Elixir.Plug.CSRFProtection.InvalidCSRFTokenError', - 'Elixir.Plug.CSRFProtection.InvalidCrossOriginRequestError', - 'Elixir.Plug.Conn','Elixir.Plug.Conn.Adapter', - 'Elixir.Plug.Conn.AlreadySentError', - 'Elixir.Plug.Conn.Cookies', - 'Elixir.Plug.Conn.InvalidHeaderError', - 'Elixir.Plug.Conn.NotSentError', - 'Elixir.Plug.Conn.Query','Elixir.Plug.Conn.Status', - 'Elixir.Plug.Conn.Unfetched','Elixir.Plug.Conn.Utils', - 'Elixir.Plug.Conn.WrapperError','Elixir.Plug.Crypto', - 'Elixir.Plug.Crypto.KeyGenerator', - 'Elixir.Plug.Crypto.MessageEncryptor', - 'Elixir.Plug.Crypto.MessageVerifier', - 'Elixir.Plug.Debugger','Elixir.Plug.ErrorHandler', - 'Elixir.Plug.Exception','Elixir.Plug.Exception.Any', - 'Elixir.Plug.HTML','Elixir.Plug.Head', - 'Elixir.Plug.Logger','Elixir.Plug.MIME', - 'Elixir.Plug.MethodOverride','Elixir.Plug.Parsers', - 'Elixir.Plug.Parsers.BadEncodingError', - 'Elixir.Plug.Parsers.JSON', - 'Elixir.Plug.Parsers.MULTIPART', - 'Elixir.Plug.Parsers.ParseError', - 'Elixir.Plug.Parsers.RequestTooLargeError', - 'Elixir.Plug.Parsers.URLENCODED', - 'Elixir.Plug.Parsers.UnsupportedMediaTypeError', - 'Elixir.Plug.RequestId','Elixir.Plug.Router', - 'Elixir.Plug.Router.InvalidSpecError', - 'Elixir.Plug.Router.Utils','Elixir.Plug.SSL', - 'Elixir.Plug.Session','Elixir.Plug.Session.COOKIE', - 'Elixir.Plug.Session.ETS','Elixir.Plug.Session.Store', - 'Elixir.Plug.Static', - 'Elixir.Plug.Static.InvalidPathError', - 'Elixir.Plug.Supervisor','Elixir.Plug.Test', - 'Elixir.Plug.Upload']}]}. DELETED _build/test/lib/ranch/ebin/ranch.app Index: _build/test/lib/ranch/ebin/ranch.app ================================================================== --- _build/test/lib/ranch/ebin/ranch.app +++ /dev/null @@ -1,12 +0,0 @@ -{application,ranch, - [{description,"Socket acceptor pool for TCP protocols."}, - {vsn,"1.2.0"}, - {id,"git"}, - {modules,[ranch,ranch_acceptor,ranch_acceptors_sup,ranch_app, - ranch_conns_sup,ranch_listener_sup,ranch_protocol, - ranch_server,ranch_ssl,ranch_sup,ranch_tcp, - ranch_transport]}, - {registered,[ranch_sup,ranch_server]}, - {applications,[kernel,stdlib]}, - {mod,{ranch_app,[]}}, - {env,[]}]}. DELETED _build/test/lib/ranch/ebin/ranch.beam Index: _build/test/lib/ranch/ebin/ranch.beam ================================================================== --- _build/test/lib/ranch/ebin/ranch.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/ranch/ebin/ranch_acceptor.beam Index: _build/test/lib/ranch/ebin/ranch_acceptor.beam ================================================================== --- _build/test/lib/ranch/ebin/ranch_acceptor.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/ranch/ebin/ranch_acceptors_sup.beam Index: _build/test/lib/ranch/ebin/ranch_acceptors_sup.beam ================================================================== --- _build/test/lib/ranch/ebin/ranch_acceptors_sup.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/ranch/ebin/ranch_app.beam Index: _build/test/lib/ranch/ebin/ranch_app.beam ================================================================== --- _build/test/lib/ranch/ebin/ranch_app.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/ranch/ebin/ranch_conns_sup.beam Index: _build/test/lib/ranch/ebin/ranch_conns_sup.beam ================================================================== --- _build/test/lib/ranch/ebin/ranch_conns_sup.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/ranch/ebin/ranch_listener_sup.beam Index: _build/test/lib/ranch/ebin/ranch_listener_sup.beam ================================================================== --- _build/test/lib/ranch/ebin/ranch_listener_sup.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/ranch/ebin/ranch_protocol.beam Index: _build/test/lib/ranch/ebin/ranch_protocol.beam ================================================================== --- _build/test/lib/ranch/ebin/ranch_protocol.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/ranch/ebin/ranch_server.beam Index: _build/test/lib/ranch/ebin/ranch_server.beam ================================================================== --- _build/test/lib/ranch/ebin/ranch_server.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/ranch/ebin/ranch_ssl.beam Index: _build/test/lib/ranch/ebin/ranch_ssl.beam ================================================================== --- _build/test/lib/ranch/ebin/ranch_ssl.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/ranch/ebin/ranch_sup.beam Index: _build/test/lib/ranch/ebin/ranch_sup.beam ================================================================== --- _build/test/lib/ranch/ebin/ranch_sup.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/ranch/ebin/ranch_tcp.beam Index: _build/test/lib/ranch/ebin/ranch_tcp.beam ================================================================== --- _build/test/lib/ranch/ebin/ranch_tcp.beam +++ /dev/null cannot compute difference between binary files DELETED _build/test/lib/ranch/ebin/ranch_transport.beam Index: _build/test/lib/ranch/ebin/ranch_transport.beam ================================================================== --- _build/test/lib/ranch/ebin/ranch_transport.beam +++ /dev/null cannot compute difference between binary files DELETED config/config.exs Index: config/config.exs ================================================================== --- config/config.exs +++ /dev/null @@ -1,30 +0,0 @@ -# This file is responsible for configuring your application -# and its dependencies with the aid of the Mix.Config module. -use Mix.Config - -# This configuration is loaded before any dependency and is restricted -# to this project. If another project depends on this project, this -# file won't be loaded nor affect the parent project. For this reason, -# if you want to provide default values for your application for -# 3rd-party users, it should be done in your "mix.exs" file. - -# You can configure for your application as: -# -# config :antigone, key: :value -# -# And access this configuration in your application as: -# -# Application.get_env(:antigone, :key) -# -# Or configure a 3rd-party app: -# -# config :logger, level: :info -# - -# It is also possible to import configuration files, relative to this -# directory. For example, you can emulate configuration per environment -# by uncommenting the line below and defining dev.exs, test.exs and such. -# Configuration from the imported file will override the ones defined -# here (which is why it is important to import them last). -# -# import_config "#{Mix.env}.exs" DELETED deps/cowboy/AUTHORS Index: deps/cowboy/AUTHORS ================================================================== --- deps/cowboy/AUTHORS +++ /dev/null @@ -1,91 +0,0 @@ -Cowboy is available thanks to the work of: - -Loïc Hoguin -Magnus Klaar -Ali Sabil -Anthony Ramine -Adam Cammack -Tom Burdick -James Fish -Paul Oliver -Slava Yurin -Vladimir Dronnikov -YAMAMOTO Takashi -Yurii Rashkovskii -Andrew Majorov -Eduardo Gurgel -Egobrain -Josh Toft -Steven Gravell -Alex Kovalev -Andrew Thompson -Hunter Morris -Ivan Lisenkov -Martin Rehfeld -Matthias Endler -Seletskiy Stanislav -Sina Samavati -Tristan Sloughter -0x00F6 -0xAX -Adam Cammmack -Adrian Roe -Alexander Færøy -Alexei Sholik -Alexey Lebedeff -Andre Graf -Andrzej Sliwa -Blake Gentry -Bob Ippolito -Boris Faure -Cameron Bytheway -Cristian Hancila -Daniel White -Danielle Sucher -Dave Peticolas -David Kelly -David N. Welton -DeadZen -Dmitry Groshev -Drew -Drew Varner -Eiichi Tsukata -Fred Hebert -Hans Ulrich Niedermann -Ivan Blinkov -Jeremy Ong -Jesper Louis Andersen -Josh Allmann -Josh Marchán -José Valim -Julian Squires -Klaus Trainer -Kuk-Hyun Lee -Mathieu Lecarme -Max Lapshin -Michael Truog -Michiel Hakvoort -Nakai Ryosuke -Ori Bar -Pablo Vieytes -Paulo Oliveira -Peter Ericson -RJ -Radosław Szymczyszyn -Richard Ramsden -Roberto Ostinelli -Sergey Prokhorov -Sergey Rublev -Sergey Urbanovich -Seven Du -Thomas Nordström -Tim Dysinger -Tomas Morstein -Unix1 -alisdair sullivan -dbmercer -derdesign -mocchira -pmyarchon -rambocoder -serge DELETED deps/cowboy/LICENSE Index: deps/cowboy/LICENSE ================================================================== --- deps/cowboy/LICENSE +++ /dev/null @@ -1,13 +0,0 @@ -Copyright (c) 2011-2014, Loïc Hoguin - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. DELETED deps/cowboy/Makefile Index: deps/cowboy/Makefile ================================================================== --- deps/cowboy/Makefile +++ /dev/null @@ -1,75 +0,0 @@ -# See LICENSE for licensing information. - -PROJECT = cowboy - -# Options. - -ERLC_OPTS ?= -Werror +debug_info +warn_export_all +warn_export_vars \ - +warn_shadow_vars +warn_obsolete_guard +warn_missing_spec -COMPILE_FIRST = cowboy_middleware cowboy_sub_protocol -CT_OPTS += -pa test -ct_hooks cowboy_ct_hook [] -PLT_APPS = crypto public_key ssl -CI_OTP = OTP_R16B01 OTP_R16B02 OTP_R16B03-1 OTP-17.0.2 OTP-17.1.2 OTP-17.2.2 OTP-17.3.4 OTP-17.4.1 OTP-17.5.6.2 OTP-18.0.2 - -# Dependencies. - -DEPS = cowlib ranch -TEST_DEPS = ct_helper gun -dep_ct_helper = git https://github.com/extend/ct_helper.git master -dep_gun = git https://github.com/ninenines/gun b85c1f726ca49ac0e3abdcf717317cb95b06207d - -# Standard targets. - -include erlang.mk - -# Documentation. - -dep_ezdoc = git https://github.com/ninenines/ezdoc master -$(eval $(call dep_target,ezdoc)) - -build-doc-deps: $(DEPS_DIR)/ezdoc - $(MAKE) -C $(DEPS_DIR)/ezdoc - -define ezdoc_script -io:format("Building manual~n"), -[begin - AST = ezdoc:parse_file(F), - BF = filename:rootname(filename:basename(F)), - io:format(" ~s~n", [BF]), - file:write_file("doc/markdown/manual/" ++ BF ++ ".md", ezdoc_markdown:export(AST)), - case BF of - "cowboy" ++ _ when BF =/= "cowboy_app" -> - file:write_file("doc/man3/" ++ BF ++ ".3", ezdoc_man:export(3, AST)); - _ when BF =/= "index" -> - file:write_file("doc/man7/" ++ BF ++ ".7", ezdoc_man:export(7, AST)); - _ -> - ok - end -end || F <- filelib:wildcard("doc/src/manual/*.ezdoc")], -io:format("Building guide~n"), -[begin - AST = ezdoc:parse_file(F), - BF = filename:rootname(filename:basename(F)), - io:format(" ~s~n", [BF]), - file:write_file("doc/markdown/guide/" ++ BF ++ ".md", ezdoc_markdown:export(AST)) -end || F <- filelib:wildcard("doc/src/guide/*.ezdoc")], -io:format("Done.~n"), -init:stop(). -endef -export ezdoc_script - -docs:: clean-docs build-doc-deps - @mkdir -p doc/man3 doc/man7 doc/markdown/guide doc/markdown/manual - $(gen_verbose) erl -noinput -pa ebin deps/ezdoc/ebin -eval "$$ezdoc_script" - @gzip doc/man3/*.3 doc/man7/*.7 - @cp doc/src/guide/*.png doc/markdown/guide - -clean-docs: - $(gen_verbose) rm -rf doc/man3 doc/man7 doc/markdown - -MAN_INSTALL_PATH ?= /usr/local/share/man - -install-docs: - mkdir -p $(MAN_INSTALL_PATH)/man3/ $(MAN_INSTALL_PATH)/man7/ - install -g 0 -o 0 -m 0644 doc/man3/*.gz $(MAN_INSTALL_PATH)/man3/ - install -g 0 -o 0 -m 0644 doc/man7/*.gz $(MAN_INSTALL_PATH)/man7/ DELETED deps/cowboy/README.md Index: deps/cowboy/README.md ================================================================== --- deps/cowboy/README.md +++ /dev/null @@ -1,50 +0,0 @@ -Cowboy -====== - -Cowboy is a small, fast and modular HTTP server written in Erlang. - -Goals ------ - -Cowboy aims to provide a **complete** HTTP stack in a **small** code base. -It is optimized for **low latency** and **low memory usage**, in part -because it uses **binary strings**. - -Cowboy provides **routing** capabilities, selectively dispatching requests -to handlers written in Erlang. - -Because it uses Ranch for managing connections, Cowboy can easily be -**embedded** in any other application. - -No parameterized module. No process dictionary. **Clean** Erlang code. - -Sponsors --------- - -The SPDY implementation was sponsored by -[LeoFS Cloud Storage](http://www.leofs.org). - -The project is currently sponsored by -[Kato.im](https://kato.im). - -Online documentation --------------------- - - * [User guide](http://ninenines.eu/docs/en/cowboy/HEAD/guide) - * [Function reference](http://ninenines.eu/docs/en/cowboy/HEAD/manual) - -Offline documentation ---------------------- - - * While still online, run `make docs` - * Function reference man pages available in `doc/man3/` and `doc/man7/` - * Run `make install-docs` to install man pages on your system - * Full documentation in Markdown available in `doc/markdown/` - * Examples available in `examples/` - -Getting help ------------- - - * Official IRC Channel: #ninenines on irc.freenode.net - * [Mailing Lists](http://lists.ninenines.eu) - * [Commercial Support](http://ninenines.eu/support) DELETED deps/cowboy/ebin/cowboy.app Index: deps/cowboy/ebin/cowboy.app ================================================================== --- deps/cowboy/ebin/cowboy.app +++ /dev/null @@ -1,14 +0,0 @@ -{application,cowboy, - [{description,"Small, fast, modular HTTP server."}, - {vsn,"1.0.4"}, - {id,"git"}, - {modules,[cowboy,cowboy_app,cowboy_bstr,cowboy_clock, - cowboy_handler,cowboy_http,cowboy_http_handler, - cowboy_loop_handler,cowboy_middleware,cowboy_protocol, - cowboy_req,cowboy_rest,cowboy_router,cowboy_spdy, - cowboy_static,cowboy_sub_protocol,cowboy_sup, - cowboy_websocket,cowboy_websocket_handler]}, - {registered,[cowboy_clock,cowboy_sup]}, - {applications,[kernel,stdlib,ranch,cowlib,crypto]}, - {mod,{cowboy_app,[]}}, - {env,[]}]}. DELETED deps/cowboy/ebin/cowboy.beam Index: deps/cowboy/ebin/cowboy.beam ================================================================== --- deps/cowboy/ebin/cowboy.beam +++ /dev/null cannot compute difference between binary files DELETED deps/cowboy/ebin/cowboy_app.beam Index: deps/cowboy/ebin/cowboy_app.beam ================================================================== --- deps/cowboy/ebin/cowboy_app.beam +++ /dev/null cannot compute difference between binary files DELETED deps/cowboy/ebin/cowboy_bstr.beam Index: deps/cowboy/ebin/cowboy_bstr.beam ================================================================== --- deps/cowboy/ebin/cowboy_bstr.beam +++ /dev/null cannot compute difference between binary files DELETED deps/cowboy/ebin/cowboy_clock.beam Index: deps/cowboy/ebin/cowboy_clock.beam ================================================================== --- deps/cowboy/ebin/cowboy_clock.beam +++ /dev/null cannot compute difference between binary files DELETED deps/cowboy/ebin/cowboy_handler.beam Index: deps/cowboy/ebin/cowboy_handler.beam ================================================================== --- deps/cowboy/ebin/cowboy_handler.beam +++ /dev/null cannot compute difference between binary files DELETED deps/cowboy/ebin/cowboy_http.beam Index: deps/cowboy/ebin/cowboy_http.beam ================================================================== --- deps/cowboy/ebin/cowboy_http.beam +++ /dev/null cannot compute difference between binary files DELETED deps/cowboy/ebin/cowboy_http_handler.beam Index: deps/cowboy/ebin/cowboy_http_handler.beam ================================================================== --- deps/cowboy/ebin/cowboy_http_handler.beam +++ /dev/null cannot compute difference between binary files DELETED deps/cowboy/ebin/cowboy_loop_handler.beam Index: deps/cowboy/ebin/cowboy_loop_handler.beam ================================================================== --- deps/cowboy/ebin/cowboy_loop_handler.beam +++ /dev/null cannot compute difference between binary files DELETED deps/cowboy/ebin/cowboy_middleware.beam Index: deps/cowboy/ebin/cowboy_middleware.beam ================================================================== --- deps/cowboy/ebin/cowboy_middleware.beam +++ /dev/null cannot compute difference between binary files DELETED deps/cowboy/ebin/cowboy_protocol.beam Index: deps/cowboy/ebin/cowboy_protocol.beam ================================================================== --- deps/cowboy/ebin/cowboy_protocol.beam +++ /dev/null cannot compute difference between binary files DELETED deps/cowboy/ebin/cowboy_req.beam Index: deps/cowboy/ebin/cowboy_req.beam ================================================================== --- deps/cowboy/ebin/cowboy_req.beam +++ /dev/null cannot compute difference between binary files DELETED deps/cowboy/ebin/cowboy_rest.beam Index: deps/cowboy/ebin/cowboy_rest.beam ================================================================== --- deps/cowboy/ebin/cowboy_rest.beam +++ /dev/null cannot compute difference between binary files DELETED deps/cowboy/ebin/cowboy_router.beam Index: deps/cowboy/ebin/cowboy_router.beam ================================================================== --- deps/cowboy/ebin/cowboy_router.beam +++ /dev/null cannot compute difference between binary files DELETED deps/cowboy/ebin/cowboy_spdy.beam Index: deps/cowboy/ebin/cowboy_spdy.beam ================================================================== --- deps/cowboy/ebin/cowboy_spdy.beam +++ /dev/null cannot compute difference between binary files DELETED deps/cowboy/ebin/cowboy_static.beam Index: deps/cowboy/ebin/cowboy_static.beam ================================================================== --- deps/cowboy/ebin/cowboy_static.beam +++ /dev/null cannot compute difference between binary files DELETED deps/cowboy/ebin/cowboy_sub_protocol.beam Index: deps/cowboy/ebin/cowboy_sub_protocol.beam ================================================================== --- deps/cowboy/ebin/cowboy_sub_protocol.beam +++ /dev/null cannot compute difference between binary files DELETED deps/cowboy/ebin/cowboy_sup.beam Index: deps/cowboy/ebin/cowboy_sup.beam ================================================================== --- deps/cowboy/ebin/cowboy_sup.beam +++ /dev/null cannot compute difference between binary files DELETED deps/cowboy/ebin/cowboy_websocket.beam Index: deps/cowboy/ebin/cowboy_websocket.beam ================================================================== --- deps/cowboy/ebin/cowboy_websocket.beam +++ /dev/null cannot compute difference between binary files DELETED deps/cowboy/ebin/cowboy_websocket_handler.beam Index: deps/cowboy/ebin/cowboy_websocket_handler.beam ================================================================== --- deps/cowboy/ebin/cowboy_websocket_handler.beam +++ /dev/null cannot compute difference between binary files DELETED deps/cowboy/erlang.mk Index: deps/cowboy/erlang.mk ================================================================== --- deps/cowboy/erlang.mk +++ /dev/null @@ -1,6029 +0,0 @@ -# Copyright (c) 2013-2015, Loïc Hoguin -# -# Permission to use, copy, modify, and/or distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -.PHONY: all app deps search rel docs install-docs check tests clean distclean help erlang-mk - -ERLANG_MK_FILENAME := $(realpath $(lastword $(MAKEFILE_LIST))) - -ERLANG_MK_VERSION = 1.2.0-632-g26ea355-dirty - -# Core configuration. - -PROJECT ?= $(notdir $(CURDIR)) -PROJECT := $(strip $(PROJECT)) - -PROJECT_VERSION ?= rolling - -# Verbosity. - -V ?= 0 - -verbose_0 = @ -verbose = $(verbose_$(V)) - -gen_verbose_0 = @echo " GEN " $@; -gen_verbose = $(gen_verbose_$(V)) - -# Temporary files directory. - -ERLANG_MK_TMP ?= $(CURDIR)/.erlang.mk -export ERLANG_MK_TMP - -# "erl" command. - -ERL = erl +A0 -noinput -boot start_clean - -# Platform detection. -# @todo Add Windows/Cygwin detection eventually. - -ifeq ($(PLATFORM),) -UNAME_S := $(shell uname -s) - -ifeq ($(UNAME_S),Linux) -PLATFORM = linux -else ifeq ($(UNAME_S),Darwin) -PLATFORM = darwin -else ifeq ($(UNAME_S),SunOS) -PLATFORM = solaris -else ifeq ($(UNAME_S),GNU) -PLATFORM = gnu -else ifeq ($(UNAME_S),FreeBSD) -PLATFORM = freebsd -else ifeq ($(UNAME_S),NetBSD) -PLATFORM = netbsd -else ifeq ($(UNAME_S),OpenBSD) -PLATFORM = openbsd -else -$(error Unable to detect platform. Please open a ticket with the output of uname -a.) -endif - -export PLATFORM -endif - -# Core targets. - -ifneq ($(words $(MAKECMDGOALS)),1) -.NOTPARALLEL: -endif - -all:: deps - $(verbose) $(MAKE) --no-print-directory app - $(verbose) $(MAKE) --no-print-directory rel - -# Noop to avoid a Make warning when there's nothing to do. -rel:: - $(verbose) echo -n - -check:: clean app tests - -clean:: clean-crashdump - -clean-crashdump: -ifneq ($(wildcard erl_crash.dump),) - $(gen_verbose) rm -f erl_crash.dump -endif - -distclean:: clean - -help:: - $(verbose) printf "%s\n" \ - "erlang.mk (version $(ERLANG_MK_VERSION)) is distributed under the terms of the ISC License." \ - "Copyright (c) 2013-2015 Loïc Hoguin " \ - "" \ - "Usage: [V=1] $(MAKE) [-jNUM] [target]..." \ - "" \ - "Core targets:" \ - " all Run deps, app and rel targets in that order" \ - " app Compile the project" \ - " deps Fetch dependencies (if needed) and compile them" \ - " search q=... Search for a package in the built-in index" \ - " rel Build a release for this project, if applicable" \ - " docs Build the documentation for this project" \ - " install-docs Install the man pages for this project" \ - " check Compile and run all tests and analysis for this project" \ - " tests Run the tests for this project" \ - " clean Delete temporary and output files from most targets" \ - " distclean Delete all temporary and output files" \ - " help Display this help and exit" \ - " erlang-mk Update erlang.mk to the latest version" - -# Core functions. - -empty := -space := $(empty) $(empty) -tab := $(empty) $(empty) -comma := , - -define newline - - -endef - -define comma_list -$(subst $(space),$(comma),$(strip $(1))) -endef - -# Adding erlang.mk to make Erlang scripts who call init:get_plain_arguments() happy. -define erlang -$(ERL) -pz $(ERLANG_MK_TMP)/rebar/ebin -eval "$(subst $(newline),,$(subst ",\",$(1)))" -- erlang.mk -endef - -ifeq ($(shell which wget 2>/dev/null | wc -l), 1) -define core_http_get - wget --no-check-certificate -O $(1) $(2)|| rm $(1) -endef -else -define core_http_get.erl - ssl:start(), - inets:start(), - case httpc:request(get, {"$(2)", []}, [{autoredirect, true}], []) of - {ok, {{_, 200, _}, _, Body}} -> - case file:write_file("$(1)", Body) of - ok -> ok; - {error, R1} -> halt(R1) - end; - {error, R2} -> - halt(R2) - end, - halt(0). -endef - -define core_http_get - $(call erlang,$(call core_http_get.erl,$(1),$(2))) -endef -endif - -core_eq = $(and $(findstring $(1),$(2)),$(findstring $(2),$(1))) - -core_find = $(foreach d,$(call core_ls,$1*),$(call core_find,$d/,$2) $(filter $(subst *,%,$2),$d)) - -core_lc = $(subst A,a,$(subst B,b,$(subst C,c,$(subst D,d,$(subst E,e,$(subst F,f,$(subst G,g,$(subst H,h,$(subst I,i,$(subst J,j,$(subst K,k,$(subst L,l,$(subst M,m,$(subst N,n,$(subst O,o,$(subst P,p,$(subst Q,q,$(subst R,r,$(subst S,s,$(subst T,t,$(subst U,u,$(subst V,v,$(subst W,w,$(subst X,x,$(subst Y,y,$(subst Z,z,$(1))))))))))))))))))))))))))) - -# @todo On Windows: $(shell dir /B $(1)); make sure to handle when no file exists. -core_ls = $(filter-out $(1),$(shell echo $(1))) - -# Automated update. - -ERLANG_MK_BUILD_CONFIG ?= build.config -ERLANG_MK_BUILD_DIR ?= .erlang.mk.build - -erlang-mk: - git clone https://github.com/ninenines/erlang.mk $(ERLANG_MK_BUILD_DIR) - if [ -f $(ERLANG_MK_BUILD_CONFIG) ]; then cp $(ERLANG_MK_BUILD_CONFIG) $(ERLANG_MK_BUILD_DIR); fi - cd $(ERLANG_MK_BUILD_DIR) && $(MAKE) - cp $(ERLANG_MK_BUILD_DIR)/erlang.mk ./erlang.mk - rm -rf $(ERLANG_MK_BUILD_DIR) - -# The erlang.mk package index is bundled in the default erlang.mk build. -# Search for the string "copyright" to skip to the rest of the code. - -PACKAGES += aberth -pkg_aberth_name = aberth -pkg_aberth_description = Generic BERT-RPC server in Erlang -pkg_aberth_homepage = https://github.com/a13x/aberth -pkg_aberth_fetch = git -pkg_aberth_repo = https://github.com/a13x/aberth -pkg_aberth_commit = master - -PACKAGES += active -pkg_active_name = active -pkg_active_description = Active development for Erlang: rebuild and reload source/binary files while the VM is running -pkg_active_homepage = https://github.com/proger/active -pkg_active_fetch = git -pkg_active_repo = https://github.com/proger/active -pkg_active_commit = master - -PACKAGES += actordb_core -pkg_actordb_core_name = actordb_core -pkg_actordb_core_description = ActorDB main source -pkg_actordb_core_homepage = http://www.actordb.com/ -pkg_actordb_core_fetch = git -pkg_actordb_core_repo = https://github.com/biokoda/actordb_core -pkg_actordb_core_commit = master - -PACKAGES += actordb_thrift -pkg_actordb_thrift_name = actordb_thrift -pkg_actordb_thrift_description = Thrift API for ActorDB -pkg_actordb_thrift_homepage = http://www.actordb.com/ -pkg_actordb_thrift_fetch = git -pkg_actordb_thrift_repo = https://github.com/biokoda/actordb_thrift -pkg_actordb_thrift_commit = master - -PACKAGES += aleppo -pkg_aleppo_name = aleppo -pkg_aleppo_description = Alternative Erlang Pre-Processor -pkg_aleppo_homepage = https://github.com/ErlyORM/aleppo -pkg_aleppo_fetch = git -pkg_aleppo_repo = https://github.com/ErlyORM/aleppo -pkg_aleppo_commit = master - -PACKAGES += alog -pkg_alog_name = alog -pkg_alog_description = Simply the best logging framework for Erlang -pkg_alog_homepage = https://github.com/siberian-fast-food/alogger -pkg_alog_fetch = git -pkg_alog_repo = https://github.com/siberian-fast-food/alogger -pkg_alog_commit = master - -PACKAGES += amqp_client -pkg_amqp_client_name = amqp_client -pkg_amqp_client_description = RabbitMQ Erlang AMQP client -pkg_amqp_client_homepage = https://www.rabbitmq.com/erlang-client-user-guide.html -pkg_amqp_client_fetch = git -pkg_amqp_client_repo = https://github.com/rabbitmq/rabbitmq-erlang-client.git -pkg_amqp_client_commit = master - -PACKAGES += annotations -pkg_annotations_name = annotations -pkg_annotations_description = Simple code instrumentation utilities -pkg_annotations_homepage = https://github.com/hyperthunk/annotations -pkg_annotations_fetch = git -pkg_annotations_repo = https://github.com/hyperthunk/annotations -pkg_annotations_commit = master - -PACKAGES += antidote -pkg_antidote_name = antidote -pkg_antidote_description = Large-scale computation without synchronisation -pkg_antidote_homepage = https://syncfree.lip6.fr/ -pkg_antidote_fetch = git -pkg_antidote_repo = https://github.com/SyncFree/antidote -pkg_antidote_commit = master - -PACKAGES += apns -pkg_apns_name = apns -pkg_apns_description = Apple Push Notification Server for Erlang -pkg_apns_homepage = http://inaka.github.com/apns4erl -pkg_apns_fetch = git -pkg_apns_repo = https://github.com/inaka/apns4erl -pkg_apns_commit = 1.0.4 - -PACKAGES += azdht -pkg_azdht_name = azdht -pkg_azdht_description = Azureus Distributed Hash Table (DHT) in Erlang -pkg_azdht_homepage = https://github.com/arcusfelis/azdht -pkg_azdht_fetch = git -pkg_azdht_repo = https://github.com/arcusfelis/azdht -pkg_azdht_commit = master - -PACKAGES += backoff -pkg_backoff_name = backoff -pkg_backoff_description = Simple exponential backoffs in Erlang -pkg_backoff_homepage = https://github.com/ferd/backoff -pkg_backoff_fetch = git -pkg_backoff_repo = https://github.com/ferd/backoff -pkg_backoff_commit = master - -PACKAGES += barrel_tcp -pkg_barrel_tcp_name = barrel_tcp -pkg_barrel_tcp_description = barrel is a generic TCP acceptor pool with low latency in Erlang. -pkg_barrel_tcp_homepage = https://github.com/benoitc-attic/barrel_tcp -pkg_barrel_tcp_fetch = git -pkg_barrel_tcp_repo = https://github.com/benoitc-attic/barrel_tcp -pkg_barrel_tcp_commit = master - -PACKAGES += basho_bench -pkg_basho_bench_name = basho_bench -pkg_basho_bench_description = A load-generation and testing tool for basically whatever you can write a returning Erlang function for. -pkg_basho_bench_homepage = https://github.com/basho/basho_bench -pkg_basho_bench_fetch = git -pkg_basho_bench_repo = https://github.com/basho/basho_bench -pkg_basho_bench_commit = master - -PACKAGES += bcrypt -pkg_bcrypt_name = bcrypt -pkg_bcrypt_description = Bcrypt Erlang / C library -pkg_bcrypt_homepage = https://github.com/riverrun/branglecrypt -pkg_bcrypt_fetch = git -pkg_bcrypt_repo = https://github.com/riverrun/branglecrypt -pkg_bcrypt_commit = master - -PACKAGES += beam -pkg_beam_name = beam -pkg_beam_description = BEAM emulator written in Erlang -pkg_beam_homepage = https://github.com/tonyrog/beam -pkg_beam_fetch = git -pkg_beam_repo = https://github.com/tonyrog/beam -pkg_beam_commit = master - -PACKAGES += beanstalk -pkg_beanstalk_name = beanstalk -pkg_beanstalk_description = An Erlang client for beanstalkd -pkg_beanstalk_homepage = https://github.com/tim/erlang-beanstalk -pkg_beanstalk_fetch = git -pkg_beanstalk_repo = https://github.com/tim/erlang-beanstalk -pkg_beanstalk_commit = master - -PACKAGES += bear -pkg_bear_name = bear -pkg_bear_description = a set of statistics functions for erlang -pkg_bear_homepage = https://github.com/boundary/bear -pkg_bear_fetch = git -pkg_bear_repo = https://github.com/boundary/bear -pkg_bear_commit = master - -PACKAGES += bertconf -pkg_bertconf_name = bertconf -pkg_bertconf_description = Make ETS tables out of statc BERT files that are auto-reloaded -pkg_bertconf_homepage = https://github.com/ferd/bertconf -pkg_bertconf_fetch = git -pkg_bertconf_repo = https://github.com/ferd/bertconf -pkg_bertconf_commit = master - -PACKAGES += bifrost -pkg_bifrost_name = bifrost -pkg_bifrost_description = Erlang FTP Server Framework -pkg_bifrost_homepage = https://github.com/thorstadt/bifrost -pkg_bifrost_fetch = git -pkg_bifrost_repo = https://github.com/thorstadt/bifrost -pkg_bifrost_commit = master - -PACKAGES += binpp -pkg_binpp_name = binpp -pkg_binpp_description = Erlang Binary Pretty Printer -pkg_binpp_homepage = https://github.com/jtendo/binpp -pkg_binpp_fetch = git -pkg_binpp_repo = https://github.com/jtendo/binpp -pkg_binpp_commit = master - -PACKAGES += bisect -pkg_bisect_name = bisect -pkg_bisect_description = Ordered fixed-size binary dictionary in Erlang -pkg_bisect_homepage = https://github.com/knutin/bisect -pkg_bisect_fetch = git -pkg_bisect_repo = https://github.com/knutin/bisect -pkg_bisect_commit = master - -PACKAGES += bitcask -pkg_bitcask_name = bitcask -pkg_bitcask_description = because you need another a key/value storage engine -pkg_bitcask_homepage = https://github.com/basho/bitcask -pkg_bitcask_fetch = git -pkg_bitcask_repo = https://github.com/basho/bitcask -pkg_bitcask_commit = master - -PACKAGES += bitstore -pkg_bitstore_name = bitstore -pkg_bitstore_description = A document based ontology development environment -pkg_bitstore_homepage = https://github.com/bdionne/bitstore -pkg_bitstore_fetch = git -pkg_bitstore_repo = https://github.com/bdionne/bitstore -pkg_bitstore_commit = master - -PACKAGES += bootstrap -pkg_bootstrap_name = bootstrap -pkg_bootstrap_description = A simple, yet powerful Erlang cluster bootstrapping application. -pkg_bootstrap_homepage = https://github.com/schlagert/bootstrap -pkg_bootstrap_fetch = git -pkg_bootstrap_repo = https://github.com/schlagert/bootstrap -pkg_bootstrap_commit = master - -PACKAGES += boss_db -pkg_boss_db_name = boss_db -pkg_boss_db_description = BossDB: a sharded, caching, pooling, evented ORM for Erlang -pkg_boss_db_homepage = https://github.com/ErlyORM/boss_db -pkg_boss_db_fetch = git -pkg_boss_db_repo = https://github.com/ErlyORM/boss_db -pkg_boss_db_commit = master - -PACKAGES += boss -pkg_boss_name = boss -pkg_boss_description = Erlang web MVC, now featuring Comet -pkg_boss_homepage = https://github.com/ChicagoBoss/ChicagoBoss -pkg_boss_fetch = git -pkg_boss_repo = https://github.com/ChicagoBoss/ChicagoBoss -pkg_boss_commit = master - -PACKAGES += bson -pkg_bson_name = bson -pkg_bson_description = BSON documents in Erlang, see bsonspec.org -pkg_bson_homepage = https://github.com/comtihon/bson-erlang -pkg_bson_fetch = git -pkg_bson_repo = https://github.com/comtihon/bson-erlang -pkg_bson_commit = master - -PACKAGES += bullet -pkg_bullet_name = bullet -pkg_bullet_description = Simple, reliable, efficient streaming for Cowboy. -pkg_bullet_homepage = http://ninenines.eu -pkg_bullet_fetch = git -pkg_bullet_repo = https://github.com/extend/bullet -pkg_bullet_commit = master - -PACKAGES += cache -pkg_cache_name = cache -pkg_cache_description = Erlang in-memory cache -pkg_cache_homepage = https://github.com/fogfish/cache -pkg_cache_fetch = git -pkg_cache_repo = https://github.com/fogfish/cache -pkg_cache_commit = master - -PACKAGES += cake -pkg_cake_name = cake -pkg_cake_description = Really simple terminal colorization -pkg_cake_homepage = https://github.com/darach/cake-erl -pkg_cake_fetch = git -pkg_cake_repo = https://github.com/darach/cake-erl -pkg_cake_commit = v0.1.2 - -PACKAGES += carotene -pkg_carotene_name = carotene -pkg_carotene_description = Real-time server -pkg_carotene_homepage = https://github.com/carotene/carotene -pkg_carotene_fetch = git -pkg_carotene_repo = https://github.com/carotene/carotene -pkg_carotene_commit = master - -PACKAGES += cberl -pkg_cberl_name = cberl -pkg_cberl_description = NIF based Erlang bindings for Couchbase -pkg_cberl_homepage = https://github.com/chitika/cberl -pkg_cberl_fetch = git -pkg_cberl_repo = https://github.com/chitika/cberl -pkg_cberl_commit = master - -PACKAGES += cecho -pkg_cecho_name = cecho -pkg_cecho_description = An ncurses library for Erlang -pkg_cecho_homepage = https://github.com/mazenharake/cecho -pkg_cecho_fetch = git -pkg_cecho_repo = https://github.com/mazenharake/cecho -pkg_cecho_commit = master - -PACKAGES += cferl -pkg_cferl_name = cferl -pkg_cferl_description = Rackspace / Open Stack Cloud Files Erlang Client -pkg_cferl_homepage = https://github.com/ddossot/cferl -pkg_cferl_fetch = git -pkg_cferl_repo = https://github.com/ddossot/cferl -pkg_cferl_commit = master - -PACKAGES += chaos_monkey -pkg_chaos_monkey_name = chaos_monkey -pkg_chaos_monkey_description = This is The CHAOS MONKEY. It will kill your processes. -pkg_chaos_monkey_homepage = https://github.com/dLuna/chaos_monkey -pkg_chaos_monkey_fetch = git -pkg_chaos_monkey_repo = https://github.com/dLuna/chaos_monkey -pkg_chaos_monkey_commit = master - -PACKAGES += check_node -pkg_check_node_name = check_node -pkg_check_node_description = Nagios Scripts for monitoring Riak -pkg_check_node_homepage = https://github.com/basho-labs/riak_nagios -pkg_check_node_fetch = git -pkg_check_node_repo = https://github.com/basho-labs/riak_nagios -pkg_check_node_commit = master - -PACKAGES += chronos -pkg_chronos_name = chronos -pkg_chronos_description = Timer module for Erlang that makes it easy to abstact time out of the tests. -pkg_chronos_homepage = https://github.com/lehoff/chronos -pkg_chronos_fetch = git -pkg_chronos_repo = https://github.com/lehoff/chronos -pkg_chronos_commit = master - -PACKAGES += classifier -pkg_classifier_name = classifier -pkg_classifier_description = An Erlang Bayesian Filter and Text Classifier -pkg_classifier_homepage = https://github.com/inaka/classifier -pkg_classifier_fetch = git -pkg_classifier_repo = https://github.com/inaka/classifier -pkg_classifier_commit = master - -PACKAGES += clique -pkg_clique_name = clique -pkg_clique_description = CLI Framework for Erlang -pkg_clique_homepage = https://github.com/basho/clique -pkg_clique_fetch = git -pkg_clique_repo = https://github.com/basho/clique -pkg_clique_commit = develop - -PACKAGES += cl -pkg_cl_name = cl -pkg_cl_description = OpenCL binding for Erlang -pkg_cl_homepage = https://github.com/tonyrog/cl -pkg_cl_fetch = git -pkg_cl_repo = https://github.com/tonyrog/cl -pkg_cl_commit = master - -PACKAGES += cloudi_core -pkg_cloudi_core_name = cloudi_core -pkg_cloudi_core_description = CloudI internal service runtime -pkg_cloudi_core_homepage = http://cloudi.org/ -pkg_cloudi_core_fetch = git -pkg_cloudi_core_repo = https://github.com/CloudI/cloudi_core -pkg_cloudi_core_commit = master - -PACKAGES += cloudi_service_api_requests -pkg_cloudi_service_api_requests_name = cloudi_service_api_requests -pkg_cloudi_service_api_requests_description = CloudI Service API requests (JSON-RPC/Erlang-term support) -pkg_cloudi_service_api_requests_homepage = http://cloudi.org/ -pkg_cloudi_service_api_requests_fetch = git -pkg_cloudi_service_api_requests_repo = https://github.com/CloudI/cloudi_service_api_requests -pkg_cloudi_service_api_requests_commit = master - -PACKAGES += cloudi_service_db_cassandra_cql -pkg_cloudi_service_db_cassandra_cql_name = cloudi_service_db_cassandra_cql -pkg_cloudi_service_db_cassandra_cql_description = Cassandra CQL CloudI Service -pkg_cloudi_service_db_cassandra_cql_homepage = http://cloudi.org/ -pkg_cloudi_service_db_cassandra_cql_fetch = git -pkg_cloudi_service_db_cassandra_cql_repo = https://github.com/CloudI/cloudi_service_db_cassandra_cql -pkg_cloudi_service_db_cassandra_cql_commit = master - -PACKAGES += cloudi_service_db_cassandra -pkg_cloudi_service_db_cassandra_name = cloudi_service_db_cassandra -pkg_cloudi_service_db_cassandra_description = Cassandra CloudI Service -pkg_cloudi_service_db_cassandra_homepage = http://cloudi.org/ -pkg_cloudi_service_db_cassandra_fetch = git -pkg_cloudi_service_db_cassandra_repo = https://github.com/CloudI/cloudi_service_db_cassandra -pkg_cloudi_service_db_cassandra_commit = master - -PACKAGES += cloudi_service_db_couchdb -pkg_cloudi_service_db_couchdb_name = cloudi_service_db_couchdb -pkg_cloudi_service_db_couchdb_description = CouchDB CloudI Service -pkg_cloudi_service_db_couchdb_homepage = http://cloudi.org/ -pkg_cloudi_service_db_couchdb_fetch = git -pkg_cloudi_service_db_couchdb_repo = https://github.com/CloudI/cloudi_service_db_couchdb -pkg_cloudi_service_db_couchdb_commit = master - -PACKAGES += cloudi_service_db_elasticsearch -pkg_cloudi_service_db_elasticsearch_name = cloudi_service_db_elasticsearch -pkg_cloudi_service_db_elasticsearch_description = elasticsearch CloudI Service -pkg_cloudi_service_db_elasticsearch_homepage = http://cloudi.org/ -pkg_cloudi_service_db_elasticsearch_fetch = git -pkg_cloudi_service_db_elasticsearch_repo = https://github.com/CloudI/cloudi_service_db_elasticsearch -pkg_cloudi_service_db_elasticsearch_commit = master - -PACKAGES += cloudi_service_db_memcached -pkg_cloudi_service_db_memcached_name = cloudi_service_db_memcached -pkg_cloudi_service_db_memcached_description = memcached CloudI Service -pkg_cloudi_service_db_memcached_homepage = http://cloudi.org/ -pkg_cloudi_service_db_memcached_fetch = git -pkg_cloudi_service_db_memcached_repo = https://github.com/CloudI/cloudi_service_db_memcached -pkg_cloudi_service_db_memcached_commit = master - -PACKAGES += cloudi_service_db -pkg_cloudi_service_db_name = cloudi_service_db -pkg_cloudi_service_db_description = CloudI Database (in-memory/testing/generic) -pkg_cloudi_service_db_homepage = http://cloudi.org/ -pkg_cloudi_service_db_fetch = git -pkg_cloudi_service_db_repo = https://github.com/CloudI/cloudi_service_db -pkg_cloudi_service_db_commit = master - -PACKAGES += cloudi_service_db_mysql -pkg_cloudi_service_db_mysql_name = cloudi_service_db_mysql -pkg_cloudi_service_db_mysql_description = MySQL CloudI Service -pkg_cloudi_service_db_mysql_homepage = http://cloudi.org/ -pkg_cloudi_service_db_mysql_fetch = git -pkg_cloudi_service_db_mysql_repo = https://github.com/CloudI/cloudi_service_db_mysql -pkg_cloudi_service_db_mysql_commit = master - -PACKAGES += cloudi_service_db_pgsql -pkg_cloudi_service_db_pgsql_name = cloudi_service_db_pgsql -pkg_cloudi_service_db_pgsql_description = PostgreSQL CloudI Service -pkg_cloudi_service_db_pgsql_homepage = http://cloudi.org/ -pkg_cloudi_service_db_pgsql_fetch = git -pkg_cloudi_service_db_pgsql_repo = https://github.com/CloudI/cloudi_service_db_pgsql -pkg_cloudi_service_db_pgsql_commit = master - -PACKAGES += cloudi_service_db_riak -pkg_cloudi_service_db_riak_name = cloudi_service_db_riak -pkg_cloudi_service_db_riak_description = Riak CloudI Service -pkg_cloudi_service_db_riak_homepage = http://cloudi.org/ -pkg_cloudi_service_db_riak_fetch = git -pkg_cloudi_service_db_riak_repo = https://github.com/CloudI/cloudi_service_db_riak -pkg_cloudi_service_db_riak_commit = master - -PACKAGES += cloudi_service_db_tokyotyrant -pkg_cloudi_service_db_tokyotyrant_name = cloudi_service_db_tokyotyrant -pkg_cloudi_service_db_tokyotyrant_description = Tokyo Tyrant CloudI Service -pkg_cloudi_service_db_tokyotyrant_homepage = http://cloudi.org/ -pkg_cloudi_service_db_tokyotyrant_fetch = git -pkg_cloudi_service_db_tokyotyrant_repo = https://github.com/CloudI/cloudi_service_db_tokyotyrant -pkg_cloudi_service_db_tokyotyrant_commit = master - -PACKAGES += cloudi_service_filesystem -pkg_cloudi_service_filesystem_name = cloudi_service_filesystem -pkg_cloudi_service_filesystem_description = Filesystem CloudI Service -pkg_cloudi_service_filesystem_homepage = http://cloudi.org/ -pkg_cloudi_service_filesystem_fetch = git -pkg_cloudi_service_filesystem_repo = https://github.com/CloudI/cloudi_service_filesystem -pkg_cloudi_service_filesystem_commit = master - -PACKAGES += cloudi_service_http_client -pkg_cloudi_service_http_client_name = cloudi_service_http_client -pkg_cloudi_service_http_client_description = HTTP client CloudI Service -pkg_cloudi_service_http_client_homepage = http://cloudi.org/ -pkg_cloudi_service_http_client_fetch = git -pkg_cloudi_service_http_client_repo = https://github.com/CloudI/cloudi_service_http_client -pkg_cloudi_service_http_client_commit = master - -PACKAGES += cloudi_service_http_cowboy -pkg_cloudi_service_http_cowboy_name = cloudi_service_http_cowboy -pkg_cloudi_service_http_cowboy_description = cowboy HTTP/HTTPS CloudI Service -pkg_cloudi_service_http_cowboy_homepage = http://cloudi.org/ -pkg_cloudi_service_http_cowboy_fetch = git -pkg_cloudi_service_http_cowboy_repo = https://github.com/CloudI/cloudi_service_http_cowboy -pkg_cloudi_service_http_cowboy_commit = master - -PACKAGES += cloudi_service_http_elli -pkg_cloudi_service_http_elli_name = cloudi_service_http_elli -pkg_cloudi_service_http_elli_description = elli HTTP CloudI Service -pkg_cloudi_service_http_elli_homepage = http://cloudi.org/ -pkg_cloudi_service_http_elli_fetch = git -pkg_cloudi_service_http_elli_repo = https://github.com/CloudI/cloudi_service_http_elli -pkg_cloudi_service_http_elli_commit = master - -PACKAGES += cloudi_service_map_reduce -pkg_cloudi_service_map_reduce_name = cloudi_service_map_reduce -pkg_cloudi_service_map_reduce_description = Map/Reduce CloudI Service -pkg_cloudi_service_map_reduce_homepage = http://cloudi.org/ -pkg_cloudi_service_map_reduce_fetch = git -pkg_cloudi_service_map_reduce_repo = https://github.com/CloudI/cloudi_service_map_reduce -pkg_cloudi_service_map_reduce_commit = master - -PACKAGES += cloudi_service_oauth1 -pkg_cloudi_service_oauth1_name = cloudi_service_oauth1 -pkg_cloudi_service_oauth1_description = OAuth v1.0 CloudI Service -pkg_cloudi_service_oauth1_homepage = http://cloudi.org/ -pkg_cloudi_service_oauth1_fetch = git -pkg_cloudi_service_oauth1_repo = https://github.com/CloudI/cloudi_service_oauth1 -pkg_cloudi_service_oauth1_commit = master - -PACKAGES += cloudi_service_queue -pkg_cloudi_service_queue_name = cloudi_service_queue -pkg_cloudi_service_queue_description = Persistent Queue Service -pkg_cloudi_service_queue_homepage = http://cloudi.org/ -pkg_cloudi_service_queue_fetch = git -pkg_cloudi_service_queue_repo = https://github.com/CloudI/cloudi_service_queue -pkg_cloudi_service_queue_commit = master - -PACKAGES += cloudi_service_quorum -pkg_cloudi_service_quorum_name = cloudi_service_quorum -pkg_cloudi_service_quorum_description = CloudI Quorum Service -pkg_cloudi_service_quorum_homepage = http://cloudi.org/ -pkg_cloudi_service_quorum_fetch = git -pkg_cloudi_service_quorum_repo = https://github.com/CloudI/cloudi_service_quorum -pkg_cloudi_service_quorum_commit = master - -PACKAGES += cloudi_service_router -pkg_cloudi_service_router_name = cloudi_service_router -pkg_cloudi_service_router_description = CloudI Router Service -pkg_cloudi_service_router_homepage = http://cloudi.org/ -pkg_cloudi_service_router_fetch = git -pkg_cloudi_service_router_repo = https://github.com/CloudI/cloudi_service_router -pkg_cloudi_service_router_commit = master - -PACKAGES += cloudi_service_tcp -pkg_cloudi_service_tcp_name = cloudi_service_tcp -pkg_cloudi_service_tcp_description = TCP CloudI Service -pkg_cloudi_service_tcp_homepage = http://cloudi.org/ -pkg_cloudi_service_tcp_fetch = git -pkg_cloudi_service_tcp_repo = https://github.com/CloudI/cloudi_service_tcp -pkg_cloudi_service_tcp_commit = master - -PACKAGES += cloudi_service_timers -pkg_cloudi_service_timers_name = cloudi_service_timers -pkg_cloudi_service_timers_description = Timers CloudI Service -pkg_cloudi_service_timers_homepage = http://cloudi.org/ -pkg_cloudi_service_timers_fetch = git -pkg_cloudi_service_timers_repo = https://github.com/CloudI/cloudi_service_timers -pkg_cloudi_service_timers_commit = master - -PACKAGES += cloudi_service_udp -pkg_cloudi_service_udp_name = cloudi_service_udp -pkg_cloudi_service_udp_description = UDP CloudI Service -pkg_cloudi_service_udp_homepage = http://cloudi.org/ -pkg_cloudi_service_udp_fetch = git -pkg_cloudi_service_udp_repo = https://github.com/CloudI/cloudi_service_udp -pkg_cloudi_service_udp_commit = master - -PACKAGES += cloudi_service_validate -pkg_cloudi_service_validate_name = cloudi_service_validate -pkg_cloudi_service_validate_description = CloudI Validate Service -pkg_cloudi_service_validate_homepage = http://cloudi.org/ -pkg_cloudi_service_validate_fetch = git -pkg_cloudi_service_validate_repo = https://github.com/CloudI/cloudi_service_validate -pkg_cloudi_service_validate_commit = master - -PACKAGES += cloudi_service_zeromq -pkg_cloudi_service_zeromq_name = cloudi_service_zeromq -pkg_cloudi_service_zeromq_description = ZeroMQ CloudI Service -pkg_cloudi_service_zeromq_homepage = http://cloudi.org/ -pkg_cloudi_service_zeromq_fetch = git -pkg_cloudi_service_zeromq_repo = https://github.com/CloudI/cloudi_service_zeromq -pkg_cloudi_service_zeromq_commit = master - -PACKAGES += cluster_info -pkg_cluster_info_name = cluster_info -pkg_cluster_info_description = Fork of Hibari's nifty cluster_info OTP app -pkg_cluster_info_homepage = https://github.com/basho/cluster_info -pkg_cluster_info_fetch = git -pkg_cluster_info_repo = https://github.com/basho/cluster_info -pkg_cluster_info_commit = master - -PACKAGES += color -pkg_color_name = color -pkg_color_description = ANSI colors for your Erlang -pkg_color_homepage = https://github.com/julianduque/erlang-color -pkg_color_fetch = git -pkg_color_repo = https://github.com/julianduque/erlang-color -pkg_color_commit = master - -PACKAGES += confetti -pkg_confetti_name = confetti -pkg_confetti_description = Erlang configuration provider / application:get_env/2 on steroids -pkg_confetti_homepage = https://github.com/jtendo/confetti -pkg_confetti_fetch = git -pkg_confetti_repo = https://github.com/jtendo/confetti -pkg_confetti_commit = master - -PACKAGES += couchbeam -pkg_couchbeam_name = couchbeam -pkg_couchbeam_description = Apache CouchDB client in Erlang -pkg_couchbeam_homepage = https://github.com/benoitc/couchbeam -pkg_couchbeam_fetch = git -pkg_couchbeam_repo = https://github.com/benoitc/couchbeam -pkg_couchbeam_commit = master - -PACKAGES += couch -pkg_couch_name = couch -pkg_couch_description = A embeddable document oriented database compatible with Apache CouchDB -pkg_couch_homepage = https://github.com/benoitc/opencouch -pkg_couch_fetch = git -pkg_couch_repo = https://github.com/benoitc/opencouch -pkg_couch_commit = master - -PACKAGES += covertool -pkg_covertool_name = covertool -pkg_covertool_description = Tool to convert Erlang cover data files into Cobertura XML reports -pkg_covertool_homepage = https://github.com/idubrov/covertool -pkg_covertool_fetch = git -pkg_covertool_repo = https://github.com/idubrov/covertool -pkg_covertool_commit = master - -PACKAGES += cowboy -pkg_cowboy_name = cowboy -pkg_cowboy_description = Small, fast and modular HTTP server. -pkg_cowboy_homepage = http://ninenines.eu -pkg_cowboy_fetch = git -pkg_cowboy_repo = https://github.com/ninenines/cowboy -pkg_cowboy_commit = 1.0.1 - -PACKAGES += cowdb -pkg_cowdb_name = cowdb -pkg_cowdb_description = Pure Key/Value database library for Erlang Applications -pkg_cowdb_homepage = https://github.com/refuge/cowdb -pkg_cowdb_fetch = git -pkg_cowdb_repo = https://github.com/refuge/cowdb -pkg_cowdb_commit = master - -PACKAGES += cowlib -pkg_cowlib_name = cowlib -pkg_cowlib_description = Support library for manipulating Web protocols. -pkg_cowlib_homepage = http://ninenines.eu -pkg_cowlib_fetch = git -pkg_cowlib_repo = https://github.com/ninenines/cowlib -pkg_cowlib_commit = 1.0.1 - -PACKAGES += cpg -pkg_cpg_name = cpg -pkg_cpg_description = CloudI Process Groups -pkg_cpg_homepage = https://github.com/okeuday/cpg -pkg_cpg_fetch = git -pkg_cpg_repo = https://github.com/okeuday/cpg -pkg_cpg_commit = master - -PACKAGES += cqerl -pkg_cqerl_name = cqerl -pkg_cqerl_description = Native Erlang CQL client for Cassandra -pkg_cqerl_homepage = https://matehat.github.io/cqerl/ -pkg_cqerl_fetch = git -pkg_cqerl_repo = https://github.com/matehat/cqerl -pkg_cqerl_commit = master - -PACKAGES += cr -pkg_cr_name = cr -pkg_cr_description = Chain Replication -pkg_cr_homepage = https://synrc.com/apps/cr/doc/cr.htm -pkg_cr_fetch = git -pkg_cr_repo = https://github.com/spawnproc/cr -pkg_cr_commit = master - -PACKAGES += cuttlefish -pkg_cuttlefish_name = cuttlefish -pkg_cuttlefish_description = never lose your childlike sense of wonder baby cuttlefish, promise me? -pkg_cuttlefish_homepage = https://github.com/basho/cuttlefish -pkg_cuttlefish_fetch = git -pkg_cuttlefish_repo = https://github.com/basho/cuttlefish -pkg_cuttlefish_commit = master - -PACKAGES += damocles -pkg_damocles_name = damocles -pkg_damocles_description = Erlang library for generating adversarial network conditions for QAing distributed applications/systems on a single Linux box. -pkg_damocles_homepage = https://github.com/lostcolony/damocles -pkg_damocles_fetch = git -pkg_damocles_repo = https://github.com/lostcolony/damocles -pkg_damocles_commit = master - -PACKAGES += debbie -pkg_debbie_name = debbie -pkg_debbie_description = .DEB Built In Erlang -pkg_debbie_homepage = https://github.com/crownedgrouse/debbie -pkg_debbie_fetch = git -pkg_debbie_repo = https://github.com/crownedgrouse/debbie -pkg_debbie_commit = master - -PACKAGES += decimal -pkg_decimal_name = decimal -pkg_decimal_description = An Erlang decimal arithmetic library -pkg_decimal_homepage = https://github.com/tim/erlang-decimal -pkg_decimal_fetch = git -pkg_decimal_repo = https://github.com/tim/erlang-decimal -pkg_decimal_commit = master - -PACKAGES += detergent -pkg_detergent_name = detergent -pkg_detergent_description = An emulsifying Erlang SOAP library -pkg_detergent_homepage = https://github.com/devinus/detergent -pkg_detergent_fetch = git -pkg_detergent_repo = https://github.com/devinus/detergent -pkg_detergent_commit = master - -PACKAGES += detest -pkg_detest_name = detest -pkg_detest_description = Tool for running tests on a cluster of erlang nodes -pkg_detest_homepage = https://github.com/biokoda/detest -pkg_detest_fetch = git -pkg_detest_repo = https://github.com/biokoda/detest -pkg_detest_commit = master - -PACKAGES += dh_date -pkg_dh_date_name = dh_date -pkg_dh_date_description = Date formatting / parsing library for erlang -pkg_dh_date_homepage = https://github.com/daleharvey/dh_date -pkg_dh_date_fetch = git -pkg_dh_date_repo = https://github.com/daleharvey/dh_date -pkg_dh_date_commit = master - -PACKAGES += dhtcrawler -pkg_dhtcrawler_name = dhtcrawler -pkg_dhtcrawler_description = dhtcrawler is a DHT crawler written in erlang. It can join a DHT network and crawl many P2P torrents. -pkg_dhtcrawler_homepage = https://github.com/kevinlynx/dhtcrawler -pkg_dhtcrawler_fetch = git -pkg_dhtcrawler_repo = https://github.com/kevinlynx/dhtcrawler -pkg_dhtcrawler_commit = master - -PACKAGES += dirbusterl -pkg_dirbusterl_name = dirbusterl -pkg_dirbusterl_description = DirBuster successor in Erlang -pkg_dirbusterl_homepage = https://github.com/silentsignal/DirBustErl -pkg_dirbusterl_fetch = git -pkg_dirbusterl_repo = https://github.com/silentsignal/DirBustErl -pkg_dirbusterl_commit = master - -PACKAGES += dispcount -pkg_dispcount_name = dispcount -pkg_dispcount_description = Erlang task dispatcher based on ETS counters. -pkg_dispcount_homepage = https://github.com/ferd/dispcount -pkg_dispcount_fetch = git -pkg_dispcount_repo = https://github.com/ferd/dispcount -pkg_dispcount_commit = master - -PACKAGES += dlhttpc -pkg_dlhttpc_name = dlhttpc -pkg_dlhttpc_description = dispcount-based lhttpc fork for massive amounts of requests to limited endpoints -pkg_dlhttpc_homepage = https://github.com/ferd/dlhttpc -pkg_dlhttpc_fetch = git -pkg_dlhttpc_repo = https://github.com/ferd/dlhttpc -pkg_dlhttpc_commit = master - -PACKAGES += dns -pkg_dns_name = dns -pkg_dns_description = Erlang DNS library -pkg_dns_homepage = https://github.com/aetrion/dns_erlang -pkg_dns_fetch = git -pkg_dns_repo = https://github.com/aetrion/dns_erlang -pkg_dns_commit = master - -PACKAGES += dnssd -pkg_dnssd_name = dnssd -pkg_dnssd_description = Erlang interface to Apple's Bonjour D NS Service Discovery implementation -pkg_dnssd_homepage = https://github.com/benoitc/dnssd_erlang -pkg_dnssd_fetch = git -pkg_dnssd_repo = https://github.com/benoitc/dnssd_erlang -pkg_dnssd_commit = master - -PACKAGES += dtl -pkg_dtl_name = dtl -pkg_dtl_description = Django Template Language: A full-featured port of the Django template engine to Erlang. -pkg_dtl_homepage = https://github.com/oinksoft/dtl -pkg_dtl_fetch = git -pkg_dtl_repo = https://github.com/oinksoft/dtl -pkg_dtl_commit = master - -PACKAGES += dynamic_compile -pkg_dynamic_compile_name = dynamic_compile -pkg_dynamic_compile_description = compile and load erlang modules from string input -pkg_dynamic_compile_homepage = https://github.com/jkvor/dynamic_compile -pkg_dynamic_compile_fetch = git -pkg_dynamic_compile_repo = https://github.com/jkvor/dynamic_compile -pkg_dynamic_compile_commit = master - -PACKAGES += e2 -pkg_e2_name = e2 -pkg_e2_description = Library to simply writing correct OTP applications. -pkg_e2_homepage = http://e2project.org -pkg_e2_fetch = git -pkg_e2_repo = https://github.com/gar1t/e2 -pkg_e2_commit = master - -PACKAGES += eamf -pkg_eamf_name = eamf -pkg_eamf_description = eAMF provides Action Message Format (AMF) support for Erlang -pkg_eamf_homepage = https://github.com/mrinalwadhwa/eamf -pkg_eamf_fetch = git -pkg_eamf_repo = https://github.com/mrinalwadhwa/eamf -pkg_eamf_commit = master - -PACKAGES += eavro -pkg_eavro_name = eavro -pkg_eavro_description = Apache Avro encoder/decoder -pkg_eavro_homepage = https://github.com/SIfoxDevTeam/eavro -pkg_eavro_fetch = git -pkg_eavro_repo = https://github.com/SIfoxDevTeam/eavro -pkg_eavro_commit = master - -PACKAGES += ecapnp -pkg_ecapnp_name = ecapnp -pkg_ecapnp_description = Cap'n Proto library for Erlang -pkg_ecapnp_homepage = https://github.com/kaos/ecapnp -pkg_ecapnp_fetch = git -pkg_ecapnp_repo = https://github.com/kaos/ecapnp -pkg_ecapnp_commit = master - -PACKAGES += econfig -pkg_econfig_name = econfig -pkg_econfig_description = simple Erlang config handler using INI files -pkg_econfig_homepage = https://github.com/benoitc/econfig -pkg_econfig_fetch = git -pkg_econfig_repo = https://github.com/benoitc/econfig -pkg_econfig_commit = master - -PACKAGES += edate -pkg_edate_name = edate -pkg_edate_description = date manipulation library for erlang -pkg_edate_homepage = https://github.com/dweldon/edate -pkg_edate_fetch = git -pkg_edate_repo = https://github.com/dweldon/edate -pkg_edate_commit = master - -PACKAGES += edgar -pkg_edgar_name = edgar -pkg_edgar_description = Erlang Does GNU AR -pkg_edgar_homepage = https://github.com/crownedgrouse/edgar -pkg_edgar_fetch = git -pkg_edgar_repo = https://github.com/crownedgrouse/edgar -pkg_edgar_commit = master - -PACKAGES += edis -pkg_edis_name = edis -pkg_edis_description = An Erlang implementation of Redis KV Store -pkg_edis_homepage = http://inaka.github.com/edis/ -pkg_edis_fetch = git -pkg_edis_repo = https://github.com/inaka/edis -pkg_edis_commit = master - -PACKAGES += edns -pkg_edns_name = edns -pkg_edns_description = Erlang/OTP DNS server -pkg_edns_homepage = https://github.com/hcvst/erlang-dns -pkg_edns_fetch = git -pkg_edns_repo = https://github.com/hcvst/erlang-dns -pkg_edns_commit = master - -PACKAGES += edown -pkg_edown_name = edown -pkg_edown_description = EDoc extension for generating Github-flavored Markdown -pkg_edown_homepage = https://github.com/uwiger/edown -pkg_edown_fetch = git -pkg_edown_repo = https://github.com/uwiger/edown -pkg_edown_commit = master - -PACKAGES += eep_app -pkg_eep_app_name = eep_app -pkg_eep_app_description = Embedded Event Processing -pkg_eep_app_homepage = https://github.com/darach/eep-erl -pkg_eep_app_fetch = git -pkg_eep_app_repo = https://github.com/darach/eep-erl -pkg_eep_app_commit = master - -PACKAGES += eep -pkg_eep_name = eep -pkg_eep_description = Erlang Easy Profiling (eep) application provides a way to analyze application performance and call hierarchy -pkg_eep_homepage = https://github.com/virtan/eep -pkg_eep_fetch = git -pkg_eep_repo = https://github.com/virtan/eep -pkg_eep_commit = master - -PACKAGES += efene -pkg_efene_name = efene -pkg_efene_description = Alternative syntax for the Erlang Programming Language focusing on simplicity, ease of use and programmer UX -pkg_efene_homepage = https://github.com/efene/efene -pkg_efene_fetch = git -pkg_efene_repo = https://github.com/efene/efene -pkg_efene_commit = master - -PACKAGES += eganglia -pkg_eganglia_name = eganglia -pkg_eganglia_description = Erlang library to interact with Ganglia -pkg_eganglia_homepage = https://github.com/inaka/eganglia -pkg_eganglia_fetch = git -pkg_eganglia_repo = https://github.com/inaka/eganglia -pkg_eganglia_commit = v0.9.1 - -PACKAGES += egeoip -pkg_egeoip_name = egeoip -pkg_egeoip_description = Erlang IP Geolocation module, currently supporting the MaxMind GeoLite City Database. -pkg_egeoip_homepage = https://github.com/mochi/egeoip -pkg_egeoip_fetch = git -pkg_egeoip_repo = https://github.com/mochi/egeoip -pkg_egeoip_commit = master - -PACKAGES += ehsa -pkg_ehsa_name = ehsa -pkg_ehsa_description = Erlang HTTP server basic and digest authentication modules -pkg_ehsa_homepage = https://bitbucket.org/a12n/ehsa -pkg_ehsa_fetch = hg -pkg_ehsa_repo = https://bitbucket.org/a12n/ehsa -pkg_ehsa_commit = 2.0.4 - -PACKAGES += ejabberd -pkg_ejabberd_name = ejabberd -pkg_ejabberd_description = Robust, ubiquitous and massively scalable Jabber / XMPP Instant Messaging platform -pkg_ejabberd_homepage = https://github.com/processone/ejabberd -pkg_ejabberd_fetch = git -pkg_ejabberd_repo = https://github.com/processone/ejabberd -pkg_ejabberd_commit = master - -PACKAGES += ej -pkg_ej_name = ej -pkg_ej_description = Helper module for working with Erlang terms representing JSON -pkg_ej_homepage = https://github.com/seth/ej -pkg_ej_fetch = git -pkg_ej_repo = https://github.com/seth/ej -pkg_ej_commit = master - -PACKAGES += ejwt -pkg_ejwt_name = ejwt -pkg_ejwt_description = erlang library for JSON Web Token -pkg_ejwt_homepage = https://github.com/artefactop/ejwt -pkg_ejwt_fetch = git -pkg_ejwt_repo = https://github.com/artefactop/ejwt -pkg_ejwt_commit = master - -PACKAGES += ekaf -pkg_ekaf_name = ekaf -pkg_ekaf_description = A minimal, high-performance Kafka client in Erlang. -pkg_ekaf_homepage = https://github.com/helpshift/ekaf -pkg_ekaf_fetch = git -pkg_ekaf_repo = https://github.com/helpshift/ekaf -pkg_ekaf_commit = master - -PACKAGES += elarm -pkg_elarm_name = elarm -pkg_elarm_description = Alarm Manager for Erlang. -pkg_elarm_homepage = https://github.com/esl/elarm -pkg_elarm_fetch = git -pkg_elarm_repo = https://github.com/esl/elarm -pkg_elarm_commit = master - -PACKAGES += eleveldb -pkg_eleveldb_name = eleveldb -pkg_eleveldb_description = Erlang LevelDB API -pkg_eleveldb_homepage = https://github.com/basho/eleveldb -pkg_eleveldb_fetch = git -pkg_eleveldb_repo = https://github.com/basho/eleveldb -pkg_eleveldb_commit = master - -PACKAGES += elli -pkg_elli_name = elli -pkg_elli_description = Simple, robust and performant Erlang web server -pkg_elli_homepage = https://github.com/knutin/elli -pkg_elli_fetch = git -pkg_elli_repo = https://github.com/knutin/elli -pkg_elli_commit = master - -PACKAGES += elvis -pkg_elvis_name = elvis -pkg_elvis_description = Erlang Style Reviewer -pkg_elvis_homepage = https://github.com/inaka/elvis -pkg_elvis_fetch = git -pkg_elvis_repo = https://github.com/inaka/elvis -pkg_elvis_commit = 0.2.4 - -PACKAGES += emagick -pkg_emagick_name = emagick -pkg_emagick_description = Wrapper for Graphics/ImageMagick command line tool. -pkg_emagick_homepage = https://github.com/kivra/emagick -pkg_emagick_fetch = git -pkg_emagick_repo = https://github.com/kivra/emagick -pkg_emagick_commit = master - -PACKAGES += emysql -pkg_emysql_name = emysql -pkg_emysql_description = Stable, pure Erlang MySQL driver. -pkg_emysql_homepage = https://github.com/Eonblast/Emysql -pkg_emysql_fetch = git -pkg_emysql_repo = https://github.com/Eonblast/Emysql -pkg_emysql_commit = master - -PACKAGES += enm -pkg_enm_name = enm -pkg_enm_description = Erlang driver for nanomsg -pkg_enm_homepage = https://github.com/basho/enm -pkg_enm_fetch = git -pkg_enm_repo = https://github.com/basho/enm -pkg_enm_commit = master - -PACKAGES += entop -pkg_entop_name = entop -pkg_entop_description = A top-like tool for monitoring an Erlang node -pkg_entop_homepage = https://github.com/mazenharake/entop -pkg_entop_fetch = git -pkg_entop_repo = https://github.com/mazenharake/entop -pkg_entop_commit = master - -PACKAGES += epcap -pkg_epcap_name = epcap -pkg_epcap_description = Erlang packet capture interface using pcap -pkg_epcap_homepage = https://github.com/msantos/epcap -pkg_epcap_fetch = git -pkg_epcap_repo = https://github.com/msantos/epcap -pkg_epcap_commit = master - -PACKAGES += eper -pkg_eper_name = eper -pkg_eper_description = Erlang performance and debugging tools. -pkg_eper_homepage = https://github.com/massemanet/eper -pkg_eper_fetch = git -pkg_eper_repo = https://github.com/massemanet/eper -pkg_eper_commit = master - -PACKAGES += epgsql -pkg_epgsql_name = epgsql -pkg_epgsql_description = Erlang PostgreSQL client library. -pkg_epgsql_homepage = https://github.com/epgsql/epgsql -pkg_epgsql_fetch = git -pkg_epgsql_repo = https://github.com/epgsql/epgsql -pkg_epgsql_commit = master - -PACKAGES += episcina -pkg_episcina_name = episcina -pkg_episcina_description = A simple non intrusive resource pool for connections -pkg_episcina_homepage = https://github.com/erlware/episcina -pkg_episcina_fetch = git -pkg_episcina_repo = https://github.com/erlware/episcina -pkg_episcina_commit = master - -PACKAGES += eplot -pkg_eplot_name = eplot -pkg_eplot_description = A plot engine written in erlang. -pkg_eplot_homepage = https://github.com/psyeugenic/eplot -pkg_eplot_fetch = git -pkg_eplot_repo = https://github.com/psyeugenic/eplot -pkg_eplot_commit = master - -PACKAGES += epocxy -pkg_epocxy_name = epocxy -pkg_epocxy_description = Erlang Patterns of Concurrency -pkg_epocxy_homepage = https://github.com/duomark/epocxy -pkg_epocxy_fetch = git -pkg_epocxy_repo = https://github.com/duomark/epocxy -pkg_epocxy_commit = master - -PACKAGES += epubnub -pkg_epubnub_name = epubnub -pkg_epubnub_description = Erlang PubNub API -pkg_epubnub_homepage = https://github.com/tsloughter/epubnub -pkg_epubnub_fetch = git -pkg_epubnub_repo = https://github.com/tsloughter/epubnub -pkg_epubnub_commit = master - -PACKAGES += eqm -pkg_eqm_name = eqm -pkg_eqm_description = Erlang pub sub with supply-demand channels -pkg_eqm_homepage = https://github.com/loucash/eqm -pkg_eqm_fetch = git -pkg_eqm_repo = https://github.com/loucash/eqm -pkg_eqm_commit = master - -PACKAGES += eredis -pkg_eredis_name = eredis -pkg_eredis_description = Erlang Redis client -pkg_eredis_homepage = https://github.com/wooga/eredis -pkg_eredis_fetch = git -pkg_eredis_repo = https://github.com/wooga/eredis -pkg_eredis_commit = master - -PACKAGES += eredis_pool -pkg_eredis_pool_name = eredis_pool -pkg_eredis_pool_description = eredis_pool is Pool of Redis clients, using eredis and poolboy. -pkg_eredis_pool_homepage = https://github.com/hiroeorz/eredis_pool -pkg_eredis_pool_fetch = git -pkg_eredis_pool_repo = https://github.com/hiroeorz/eredis_pool -pkg_eredis_pool_commit = master - -PACKAGES += erlang_cep -pkg_erlang_cep_name = erlang_cep -pkg_erlang_cep_description = A basic CEP package written in erlang -pkg_erlang_cep_homepage = https://github.com/danmacklin/erlang_cep -pkg_erlang_cep_fetch = git -pkg_erlang_cep_repo = https://github.com/danmacklin/erlang_cep -pkg_erlang_cep_commit = master - -PACKAGES += erlang_js -pkg_erlang_js_name = erlang_js -pkg_erlang_js_description = A linked-in driver for Erlang to Mozilla's Spidermonkey Javascript runtime. -pkg_erlang_js_homepage = https://github.com/basho/erlang_js -pkg_erlang_js_fetch = git -pkg_erlang_js_repo = https://github.com/basho/erlang_js -pkg_erlang_js_commit = master - -PACKAGES += erlang_localtime -pkg_erlang_localtime_name = erlang_localtime -pkg_erlang_localtime_description = Erlang library for conversion from one local time to another -pkg_erlang_localtime_homepage = https://github.com/dmitryme/erlang_localtime -pkg_erlang_localtime_fetch = git -pkg_erlang_localtime_repo = https://github.com/dmitryme/erlang_localtime -pkg_erlang_localtime_commit = master - -PACKAGES += erlang_smtp -pkg_erlang_smtp_name = erlang_smtp -pkg_erlang_smtp_description = Erlang SMTP and POP3 server code. -pkg_erlang_smtp_homepage = https://github.com/tonyg/erlang-smtp -pkg_erlang_smtp_fetch = git -pkg_erlang_smtp_repo = https://github.com/tonyg/erlang-smtp -pkg_erlang_smtp_commit = master - -PACKAGES += erlang_term -pkg_erlang_term_name = erlang_term -pkg_erlang_term_description = Erlang Term Info -pkg_erlang_term_homepage = https://github.com/okeuday/erlang_term -pkg_erlang_term_fetch = git -pkg_erlang_term_repo = https://github.com/okeuday/erlang_term -pkg_erlang_term_commit = master - -PACKAGES += erlastic_search -pkg_erlastic_search_name = erlastic_search -pkg_erlastic_search_description = An Erlang app for communicating with Elastic Search's rest interface. -pkg_erlastic_search_homepage = https://github.com/tsloughter/erlastic_search -pkg_erlastic_search_fetch = git -pkg_erlastic_search_repo = https://github.com/tsloughter/erlastic_search -pkg_erlastic_search_commit = master - -PACKAGES += erlasticsearch -pkg_erlasticsearch_name = erlasticsearch -pkg_erlasticsearch_description = Erlang thrift interface to elastic_search -pkg_erlasticsearch_homepage = https://github.com/dieswaytoofast/erlasticsearch -pkg_erlasticsearch_fetch = git -pkg_erlasticsearch_repo = https://github.com/dieswaytoofast/erlasticsearch -pkg_erlasticsearch_commit = master - -PACKAGES += erlbrake -pkg_erlbrake_name = erlbrake -pkg_erlbrake_description = Erlang Airbrake notification client -pkg_erlbrake_homepage = https://github.com/kenpratt/erlbrake -pkg_erlbrake_fetch = git -pkg_erlbrake_repo = https://github.com/kenpratt/erlbrake -pkg_erlbrake_commit = master - -PACKAGES += erlcloud -pkg_erlcloud_name = erlcloud -pkg_erlcloud_description = Cloud Computing library for erlang (Amazon EC2, S3, SQS, SimpleDB, Mechanical Turk, ELB) -pkg_erlcloud_homepage = https://github.com/gleber/erlcloud -pkg_erlcloud_fetch = git -pkg_erlcloud_repo = https://github.com/gleber/erlcloud -pkg_erlcloud_commit = master - -PACKAGES += erlcron -pkg_erlcron_name = erlcron -pkg_erlcron_description = Erlang cronish system -pkg_erlcron_homepage = https://github.com/erlware/erlcron -pkg_erlcron_fetch = git -pkg_erlcron_repo = https://github.com/erlware/erlcron -pkg_erlcron_commit = master - -PACKAGES += erldb -pkg_erldb_name = erldb -pkg_erldb_description = ORM (Object-relational mapping) application implemented in Erlang -pkg_erldb_homepage = http://erldb.org -pkg_erldb_fetch = git -pkg_erldb_repo = https://github.com/erldb/erldb -pkg_erldb_commit = master - -PACKAGES += erldis -pkg_erldis_name = erldis -pkg_erldis_description = redis erlang client library -pkg_erldis_homepage = https://github.com/cstar/erldis -pkg_erldis_fetch = git -pkg_erldis_repo = https://github.com/cstar/erldis -pkg_erldis_commit = master - -PACKAGES += erldns -pkg_erldns_name = erldns -pkg_erldns_description = DNS server, in erlang. -pkg_erldns_homepage = https://github.com/aetrion/erl-dns -pkg_erldns_fetch = git -pkg_erldns_repo = https://github.com/aetrion/erl-dns -pkg_erldns_commit = master - -PACKAGES += erldocker -pkg_erldocker_name = erldocker -pkg_erldocker_description = Docker Remote API client for Erlang -pkg_erldocker_homepage = https://github.com/proger/erldocker -pkg_erldocker_fetch = git -pkg_erldocker_repo = https://github.com/proger/erldocker -pkg_erldocker_commit = master - -PACKAGES += erlfsmon -pkg_erlfsmon_name = erlfsmon -pkg_erlfsmon_description = Erlang filesystem event watcher for Linux and OSX -pkg_erlfsmon_homepage = https://github.com/proger/erlfsmon -pkg_erlfsmon_fetch = git -pkg_erlfsmon_repo = https://github.com/proger/erlfsmon -pkg_erlfsmon_commit = master - -PACKAGES += erlgit -pkg_erlgit_name = erlgit -pkg_erlgit_description = Erlang convenience wrapper around git executable -pkg_erlgit_homepage = https://github.com/gleber/erlgit -pkg_erlgit_fetch = git -pkg_erlgit_repo = https://github.com/gleber/erlgit -pkg_erlgit_commit = master - -PACKAGES += erlguten -pkg_erlguten_name = erlguten -pkg_erlguten_description = ErlGuten is a system for high-quality typesetting, written purely in Erlang. -pkg_erlguten_homepage = https://github.com/richcarl/erlguten -pkg_erlguten_fetch = git -pkg_erlguten_repo = https://github.com/richcarl/erlguten -pkg_erlguten_commit = master - -PACKAGES += erlmc -pkg_erlmc_name = erlmc -pkg_erlmc_description = Erlang memcached binary protocol client -pkg_erlmc_homepage = https://github.com/jkvor/erlmc -pkg_erlmc_fetch = git -pkg_erlmc_repo = https://github.com/jkvor/erlmc -pkg_erlmc_commit = master - -PACKAGES += erlmongo -pkg_erlmongo_name = erlmongo -pkg_erlmongo_description = Record based Erlang driver for MongoDB with gridfs support -pkg_erlmongo_homepage = https://github.com/SergejJurecko/erlmongo -pkg_erlmongo_fetch = git -pkg_erlmongo_repo = https://github.com/SergejJurecko/erlmongo -pkg_erlmongo_commit = master - -PACKAGES += erlog -pkg_erlog_name = erlog -pkg_erlog_description = Prolog interpreter in and for Erlang -pkg_erlog_homepage = https://github.com/rvirding/erlog -pkg_erlog_fetch = git -pkg_erlog_repo = https://github.com/rvirding/erlog -pkg_erlog_commit = master - -PACKAGES += erlpass -pkg_erlpass_name = erlpass -pkg_erlpass_description = A library to handle password hashing and changing in a safe manner, independent from any kind of storage whatsoever. -pkg_erlpass_homepage = https://github.com/ferd/erlpass -pkg_erlpass_fetch = git -pkg_erlpass_repo = https://github.com/ferd/erlpass -pkg_erlpass_commit = master - -PACKAGES += erlport -pkg_erlport_name = erlport -pkg_erlport_description = ErlPort - connect Erlang to other languages -pkg_erlport_homepage = https://github.com/hdima/erlport -pkg_erlport_fetch = git -pkg_erlport_repo = https://github.com/hdima/erlport -pkg_erlport_commit = master - -PACKAGES += erlsha2 -pkg_erlsha2_name = erlsha2 -pkg_erlsha2_description = SHA-224, SHA-256, SHA-384, SHA-512 implemented in Erlang NIFs. -pkg_erlsha2_homepage = https://github.com/vinoski/erlsha2 -pkg_erlsha2_fetch = git -pkg_erlsha2_repo = https://github.com/vinoski/erlsha2 -pkg_erlsha2_commit = master - -PACKAGES += erlsh -pkg_erlsh_name = erlsh -pkg_erlsh_description = Erlang shell tools -pkg_erlsh_homepage = https://github.com/proger/erlsh -pkg_erlsh_fetch = git -pkg_erlsh_repo = https://github.com/proger/erlsh -pkg_erlsh_commit = master - -PACKAGES += erlsom -pkg_erlsom_name = erlsom -pkg_erlsom_description = XML parser for Erlang -pkg_erlsom_homepage = https://github.com/willemdj/erlsom -pkg_erlsom_fetch = git -pkg_erlsom_repo = https://github.com/willemdj/erlsom -pkg_erlsom_commit = master - -PACKAGES += erl_streams -pkg_erl_streams_name = erl_streams -pkg_erl_streams_description = Streams in Erlang -pkg_erl_streams_homepage = https://github.com/epappas/erl_streams -pkg_erl_streams_fetch = git -pkg_erl_streams_repo = https://github.com/epappas/erl_streams -pkg_erl_streams_commit = master - -PACKAGES += erlubi -pkg_erlubi_name = erlubi -pkg_erlubi_description = Ubigraph Erlang Client (and Process Visualizer) -pkg_erlubi_homepage = https://github.com/krestenkrab/erlubi -pkg_erlubi_fetch = git -pkg_erlubi_repo = https://github.com/krestenkrab/erlubi -pkg_erlubi_commit = master - -PACKAGES += erlvolt -pkg_erlvolt_name = erlvolt -pkg_erlvolt_description = VoltDB Erlang Client Driver -pkg_erlvolt_homepage = https://github.com/VoltDB/voltdb-client-erlang -pkg_erlvolt_fetch = git -pkg_erlvolt_repo = https://github.com/VoltDB/voltdb-client-erlang -pkg_erlvolt_commit = master - -PACKAGES += erlware_commons -pkg_erlware_commons_name = erlware_commons -pkg_erlware_commons_description = Erlware Commons is an Erlware project focused on all aspects of reusable Erlang components. -pkg_erlware_commons_homepage = https://github.com/erlware/erlware_commons -pkg_erlware_commons_fetch = git -pkg_erlware_commons_repo = https://github.com/erlware/erlware_commons -pkg_erlware_commons_commit = master - -PACKAGES += erlydtl -pkg_erlydtl_name = erlydtl -pkg_erlydtl_description = Django Template Language for Erlang. -pkg_erlydtl_homepage = https://github.com/erlydtl/erlydtl -pkg_erlydtl_fetch = git -pkg_erlydtl_repo = https://github.com/erlydtl/erlydtl -pkg_erlydtl_commit = master - -PACKAGES += errd -pkg_errd_name = errd -pkg_errd_description = Erlang RRDTool library -pkg_errd_homepage = https://github.com/archaelus/errd -pkg_errd_fetch = git -pkg_errd_repo = https://github.com/archaelus/errd -pkg_errd_commit = master - -PACKAGES += erserve -pkg_erserve_name = erserve -pkg_erserve_description = Erlang/Rserve communication interface -pkg_erserve_homepage = https://github.com/del/erserve -pkg_erserve_fetch = git -pkg_erserve_repo = https://github.com/del/erserve -pkg_erserve_commit = master - -PACKAGES += erwa -pkg_erwa_name = erwa -pkg_erwa_description = A WAMP router and client written in Erlang. -pkg_erwa_homepage = https://github.com/bwegh/erwa -pkg_erwa_fetch = git -pkg_erwa_repo = https://github.com/bwegh/erwa -pkg_erwa_commit = 0.1.1 - -PACKAGES += espec -pkg_espec_name = espec -pkg_espec_description = ESpec: Behaviour driven development framework for Erlang -pkg_espec_homepage = https://github.com/lucaspiller/espec -pkg_espec_fetch = git -pkg_espec_repo = https://github.com/lucaspiller/espec -pkg_espec_commit = master - -PACKAGES += estatsd -pkg_estatsd_name = estatsd -pkg_estatsd_description = Erlang stats aggregation app that periodically flushes data to graphite -pkg_estatsd_homepage = https://github.com/RJ/estatsd -pkg_estatsd_fetch = git -pkg_estatsd_repo = https://github.com/RJ/estatsd -pkg_estatsd_commit = master - -PACKAGES += etap -pkg_etap_name = etap -pkg_etap_description = etap is a simple erlang testing library that provides TAP compliant output. -pkg_etap_homepage = https://github.com/ngerakines/etap -pkg_etap_fetch = git -pkg_etap_repo = https://github.com/ngerakines/etap -pkg_etap_commit = master - -PACKAGES += etest_http -pkg_etest_http_name = etest_http -pkg_etest_http_description = etest Assertions around HTTP (client-side) -pkg_etest_http_homepage = https://github.com/wooga/etest_http -pkg_etest_http_fetch = git -pkg_etest_http_repo = https://github.com/wooga/etest_http -pkg_etest_http_commit = master - -PACKAGES += etest -pkg_etest_name = etest -pkg_etest_description = A lightweight, convention over configuration test framework for Erlang -pkg_etest_homepage = https://github.com/wooga/etest -pkg_etest_fetch = git -pkg_etest_repo = https://github.com/wooga/etest -pkg_etest_commit = master - -PACKAGES += etoml -pkg_etoml_name = etoml -pkg_etoml_description = TOML language erlang parser -pkg_etoml_homepage = https://github.com/kalta/etoml -pkg_etoml_fetch = git -pkg_etoml_repo = https://github.com/kalta/etoml -pkg_etoml_commit = master - -PACKAGES += eunit_formatters -pkg_eunit_formatters_name = eunit_formatters -pkg_eunit_formatters_description = Because eunit's output sucks. Let's make it better. -pkg_eunit_formatters_homepage = https://github.com/seancribbs/eunit_formatters -pkg_eunit_formatters_fetch = git -pkg_eunit_formatters_repo = https://github.com/seancribbs/eunit_formatters -pkg_eunit_formatters_commit = master - -PACKAGES += eunit -pkg_eunit_name = eunit -pkg_eunit_description = The EUnit lightweight unit testing framework for Erlang - this is the canonical development repository. -pkg_eunit_homepage = https://github.com/richcarl/eunit -pkg_eunit_fetch = git -pkg_eunit_repo = https://github.com/richcarl/eunit -pkg_eunit_commit = master - -PACKAGES += euthanasia -pkg_euthanasia_name = euthanasia -pkg_euthanasia_description = Merciful killer for your Erlang processes -pkg_euthanasia_homepage = https://github.com/doubleyou/euthanasia -pkg_euthanasia_fetch = git -pkg_euthanasia_repo = https://github.com/doubleyou/euthanasia -pkg_euthanasia_commit = master - -PACKAGES += evum -pkg_evum_name = evum -pkg_evum_description = Spawn Linux VMs as Erlang processes in the Erlang VM -pkg_evum_homepage = https://github.com/msantos/evum -pkg_evum_fetch = git -pkg_evum_repo = https://github.com/msantos/evum -pkg_evum_commit = master - -PACKAGES += exec -pkg_exec_name = exec -pkg_exec_description = Execute and control OS processes from Erlang/OTP. -pkg_exec_homepage = http://saleyn.github.com/erlexec -pkg_exec_fetch = git -pkg_exec_repo = https://github.com/saleyn/erlexec -pkg_exec_commit = master - -PACKAGES += exml -pkg_exml_name = exml -pkg_exml_description = XML parsing library in Erlang -pkg_exml_homepage = https://github.com/paulgray/exml -pkg_exml_fetch = git -pkg_exml_repo = https://github.com/paulgray/exml -pkg_exml_commit = master - -PACKAGES += exometer -pkg_exometer_name = exometer -pkg_exometer_description = Basic measurement objects and probe behavior -pkg_exometer_homepage = https://github.com/Feuerlabs/exometer -pkg_exometer_fetch = git -pkg_exometer_repo = https://github.com/Feuerlabs/exometer -pkg_exometer_commit = 1.2 - -PACKAGES += exs1024 -pkg_exs1024_name = exs1024 -pkg_exs1024_description = Xorshift1024star pseudo random number generator for Erlang. -pkg_exs1024_homepage = https://github.com/jj1bdx/exs1024 -pkg_exs1024_fetch = git -pkg_exs1024_repo = https://github.com/jj1bdx/exs1024 -pkg_exs1024_commit = master - -PACKAGES += exs64 -pkg_exs64_name = exs64 -pkg_exs64_description = Xorshift64star pseudo random number generator for Erlang. -pkg_exs64_homepage = https://github.com/jj1bdx/exs64 -pkg_exs64_fetch = git -pkg_exs64_repo = https://github.com/jj1bdx/exs64 -pkg_exs64_commit = master - -PACKAGES += exsplus116 -pkg_exsplus116_name = exsplus116 -pkg_exsplus116_description = Xorshift116plus for Erlang -pkg_exsplus116_homepage = https://github.com/jj1bdx/exsplus116 -pkg_exsplus116_fetch = git -pkg_exsplus116_repo = https://github.com/jj1bdx/exsplus116 -pkg_exsplus116_commit = master - -PACKAGES += exsplus128 -pkg_exsplus128_name = exsplus128 -pkg_exsplus128_description = Xorshift128plus pseudo random number generator for Erlang. -pkg_exsplus128_homepage = https://github.com/jj1bdx/exsplus128 -pkg_exsplus128_fetch = git -pkg_exsplus128_repo = https://github.com/jj1bdx/exsplus128 -pkg_exsplus128_commit = master - -PACKAGES += ezmq -pkg_ezmq_name = ezmq -pkg_ezmq_description = zMQ implemented in Erlang -pkg_ezmq_homepage = https://github.com/RoadRunnr/ezmq -pkg_ezmq_fetch = git -pkg_ezmq_repo = https://github.com/RoadRunnr/ezmq -pkg_ezmq_commit = master - -PACKAGES += ezmtp -pkg_ezmtp_name = ezmtp -pkg_ezmtp_description = ZMTP protocol in pure Erlang. -pkg_ezmtp_homepage = https://github.com/a13x/ezmtp -pkg_ezmtp_fetch = git -pkg_ezmtp_repo = https://github.com/a13x/ezmtp -pkg_ezmtp_commit = master - -PACKAGES += fast_disk_log -pkg_fast_disk_log_name = fast_disk_log -pkg_fast_disk_log_description = Pool-based asynchronous Erlang disk logger -pkg_fast_disk_log_homepage = https://github.com/lpgauth/fast_disk_log -pkg_fast_disk_log_fetch = git -pkg_fast_disk_log_repo = https://github.com/lpgauth/fast_disk_log -pkg_fast_disk_log_commit = master - -PACKAGES += feeder -pkg_feeder_name = feeder -pkg_feeder_description = Stream parse RSS and Atom formatted XML feeds. -pkg_feeder_homepage = https://github.com/michaelnisi/feeder -pkg_feeder_fetch = git -pkg_feeder_repo = https://github.com/michaelnisi/feeder -pkg_feeder_commit = v1.4.6 - -PACKAGES += fix -pkg_fix_name = fix -pkg_fix_description = http://fixprotocol.org/ implementation. -pkg_fix_homepage = https://github.com/maxlapshin/fix -pkg_fix_fetch = git -pkg_fix_repo = https://github.com/maxlapshin/fix -pkg_fix_commit = master - -PACKAGES += flower -pkg_flower_name = flower -pkg_flower_description = FlowER - a Erlang OpenFlow development platform -pkg_flower_homepage = https://github.com/travelping/flower -pkg_flower_fetch = git -pkg_flower_repo = https://github.com/travelping/flower -pkg_flower_commit = master - -PACKAGES += fn -pkg_fn_name = fn -pkg_fn_description = Function utilities for Erlang -pkg_fn_homepage = https://github.com/reiddraper/fn -pkg_fn_fetch = git -pkg_fn_repo = https://github.com/reiddraper/fn -pkg_fn_commit = master - -PACKAGES += folsom_cowboy -pkg_folsom_cowboy_name = folsom_cowboy -pkg_folsom_cowboy_description = A Cowboy based Folsom HTTP Wrapper. -pkg_folsom_cowboy_homepage = https://github.com/boundary/folsom_cowboy -pkg_folsom_cowboy_fetch = git -pkg_folsom_cowboy_repo = https://github.com/boundary/folsom_cowboy -pkg_folsom_cowboy_commit = master - -PACKAGES += folsomite -pkg_folsomite_name = folsomite -pkg_folsomite_description = blow up your graphite / riemann server with folsom metrics -pkg_folsomite_homepage = https://github.com/campanja/folsomite -pkg_folsomite_fetch = git -pkg_folsomite_repo = https://github.com/campanja/folsomite -pkg_folsomite_commit = master - -PACKAGES += folsom -pkg_folsom_name = folsom -pkg_folsom_description = Expose Erlang Events and Metrics -pkg_folsom_homepage = https://github.com/boundary/folsom -pkg_folsom_fetch = git -pkg_folsom_repo = https://github.com/boundary/folsom -pkg_folsom_commit = master - -PACKAGES += fs -pkg_fs_name = fs -pkg_fs_description = Erlang FileSystem Listener -pkg_fs_homepage = https://github.com/synrc/fs -pkg_fs_fetch = git -pkg_fs_repo = https://github.com/synrc/fs -pkg_fs_commit = master - -PACKAGES += fuse -pkg_fuse_name = fuse -pkg_fuse_description = A Circuit Breaker for Erlang -pkg_fuse_homepage = https://github.com/jlouis/fuse -pkg_fuse_fetch = git -pkg_fuse_repo = https://github.com/jlouis/fuse -pkg_fuse_commit = master - -PACKAGES += gcm -pkg_gcm_name = gcm -pkg_gcm_description = An Erlang application for Google Cloud Messaging -pkg_gcm_homepage = https://github.com/pdincau/gcm-erlang -pkg_gcm_fetch = git -pkg_gcm_repo = https://github.com/pdincau/gcm-erlang -pkg_gcm_commit = master - -PACKAGES += gcprof -pkg_gcprof_name = gcprof -pkg_gcprof_description = Garbage Collection profiler for Erlang -pkg_gcprof_homepage = https://github.com/knutin/gcprof -pkg_gcprof_fetch = git -pkg_gcprof_repo = https://github.com/knutin/gcprof -pkg_gcprof_commit = master - -PACKAGES += geas -pkg_geas_name = geas -pkg_geas_description = Guess Erlang Application Scattering -pkg_geas_homepage = https://github.com/crownedgrouse/geas -pkg_geas_fetch = git -pkg_geas_repo = https://github.com/crownedgrouse/geas -pkg_geas_commit = master - -PACKAGES += geef -pkg_geef_name = geef -pkg_geef_description = Git NEEEEF (Erlang NIF) -pkg_geef_homepage = https://github.com/carlosmn/geef -pkg_geef_fetch = git -pkg_geef_repo = https://github.com/carlosmn/geef -pkg_geef_commit = master - -PACKAGES += gen_cycle -pkg_gen_cycle_name = gen_cycle -pkg_gen_cycle_description = Simple, generic OTP behaviour for recurring tasks -pkg_gen_cycle_homepage = https://github.com/aerosol/gen_cycle -pkg_gen_cycle_fetch = git -pkg_gen_cycle_repo = https://github.com/aerosol/gen_cycle -pkg_gen_cycle_commit = develop - -PACKAGES += gen_icmp -pkg_gen_icmp_name = gen_icmp -pkg_gen_icmp_description = Erlang interface to ICMP sockets -pkg_gen_icmp_homepage = https://github.com/msantos/gen_icmp -pkg_gen_icmp_fetch = git -pkg_gen_icmp_repo = https://github.com/msantos/gen_icmp -pkg_gen_icmp_commit = master - -PACKAGES += gen_nb_server -pkg_gen_nb_server_name = gen_nb_server -pkg_gen_nb_server_description = OTP behavior for writing non-blocking servers -pkg_gen_nb_server_homepage = https://github.com/kevsmith/gen_nb_server -pkg_gen_nb_server_fetch = git -pkg_gen_nb_server_repo = https://github.com/kevsmith/gen_nb_server -pkg_gen_nb_server_commit = master - -PACKAGES += gen_paxos -pkg_gen_paxos_name = gen_paxos -pkg_gen_paxos_description = An Erlang/OTP-style implementation of the PAXOS distributed consensus protocol -pkg_gen_paxos_homepage = https://github.com/gburd/gen_paxos -pkg_gen_paxos_fetch = git -pkg_gen_paxos_repo = https://github.com/gburd/gen_paxos -pkg_gen_paxos_commit = master - -PACKAGES += gen_smtp -pkg_gen_smtp_name = gen_smtp -pkg_gen_smtp_description = A generic Erlang SMTP server and client that can be extended via callback modules -pkg_gen_smtp_homepage = https://github.com/Vagabond/gen_smtp -pkg_gen_smtp_fetch = git -pkg_gen_smtp_repo = https://github.com/Vagabond/gen_smtp -pkg_gen_smtp_commit = master - -PACKAGES += gen_tracker -pkg_gen_tracker_name = gen_tracker -pkg_gen_tracker_description = supervisor with ets handling of children and their metadata -pkg_gen_tracker_homepage = https://github.com/erlyvideo/gen_tracker -pkg_gen_tracker_fetch = git -pkg_gen_tracker_repo = https://github.com/erlyvideo/gen_tracker -pkg_gen_tracker_commit = master - -PACKAGES += gen_unix -pkg_gen_unix_name = gen_unix -pkg_gen_unix_description = Erlang Unix socket interface -pkg_gen_unix_homepage = https://github.com/msantos/gen_unix -pkg_gen_unix_fetch = git -pkg_gen_unix_repo = https://github.com/msantos/gen_unix -pkg_gen_unix_commit = master - -PACKAGES += getopt -pkg_getopt_name = getopt -pkg_getopt_description = Module to parse command line arguments using the GNU getopt syntax -pkg_getopt_homepage = https://github.com/jcomellas/getopt -pkg_getopt_fetch = git -pkg_getopt_repo = https://github.com/jcomellas/getopt -pkg_getopt_commit = master - -PACKAGES += gettext -pkg_gettext_name = gettext -pkg_gettext_description = Erlang internationalization library. -pkg_gettext_homepage = https://github.com/etnt/gettext -pkg_gettext_fetch = git -pkg_gettext_repo = https://github.com/etnt/gettext -pkg_gettext_commit = master - -PACKAGES += giallo -pkg_giallo_name = giallo -pkg_giallo_description = Small and flexible web framework on top of Cowboy -pkg_giallo_homepage = https://github.com/kivra/giallo -pkg_giallo_fetch = git -pkg_giallo_repo = https://github.com/kivra/giallo -pkg_giallo_commit = master - -PACKAGES += gin -pkg_gin_name = gin -pkg_gin_description = The guards and for Erlang parse_transform -pkg_gin_homepage = https://github.com/mad-cocktail/gin -pkg_gin_fetch = git -pkg_gin_repo = https://github.com/mad-cocktail/gin -pkg_gin_commit = master - -PACKAGES += gitty -pkg_gitty_name = gitty -pkg_gitty_description = Git access in erlang -pkg_gitty_homepage = https://github.com/maxlapshin/gitty -pkg_gitty_fetch = git -pkg_gitty_repo = https://github.com/maxlapshin/gitty -pkg_gitty_commit = master - -PACKAGES += gold_fever -pkg_gold_fever_name = gold_fever -pkg_gold_fever_description = A Treasure Hunt for Erlangers -pkg_gold_fever_homepage = https://github.com/inaka/gold_fever -pkg_gold_fever_fetch = git -pkg_gold_fever_repo = https://github.com/inaka/gold_fever -pkg_gold_fever_commit = master - -PACKAGES += gossiperl -pkg_gossiperl_name = gossiperl -pkg_gossiperl_description = Gossip middleware in Erlang -pkg_gossiperl_homepage = http://gossiperl.com/ -pkg_gossiperl_fetch = git -pkg_gossiperl_repo = https://github.com/gossiperl/gossiperl -pkg_gossiperl_commit = master - -PACKAGES += gpb -pkg_gpb_name = gpb -pkg_gpb_description = A Google Protobuf implementation for Erlang -pkg_gpb_homepage = https://github.com/tomas-abrahamsson/gpb -pkg_gpb_fetch = git -pkg_gpb_repo = https://github.com/tomas-abrahamsson/gpb -pkg_gpb_commit = master - -PACKAGES += gproc -pkg_gproc_name = gproc -pkg_gproc_description = Extended process registry for Erlang -pkg_gproc_homepage = https://github.com/uwiger/gproc -pkg_gproc_fetch = git -pkg_gproc_repo = https://github.com/uwiger/gproc -pkg_gproc_commit = master - -PACKAGES += grapherl -pkg_grapherl_name = grapherl -pkg_grapherl_description = Create graphs of Erlang systems and programs -pkg_grapherl_homepage = https://github.com/eproxus/grapherl -pkg_grapherl_fetch = git -pkg_grapherl_repo = https://github.com/eproxus/grapherl -pkg_grapherl_commit = master - -PACKAGES += gun -pkg_gun_name = gun -pkg_gun_description = Asynchronous SPDY, HTTP and Websocket client written in Erlang. -pkg_gun_homepage = http//ninenines.eu -pkg_gun_fetch = git -pkg_gun_repo = https://github.com/ninenines/gun -pkg_gun_commit = master - -PACKAGES += gut -pkg_gut_name = gut -pkg_gut_description = gut is a template printing, aka scaffolding, tool for Erlang. Like rails generate or yeoman -pkg_gut_homepage = https://github.com/unbalancedparentheses/gut -pkg_gut_fetch = git -pkg_gut_repo = https://github.com/unbalancedparentheses/gut -pkg_gut_commit = master - -PACKAGES += hackney -pkg_hackney_name = hackney -pkg_hackney_description = simple HTTP client in Erlang -pkg_hackney_homepage = https://github.com/benoitc/hackney -pkg_hackney_fetch = git -pkg_hackney_repo = https://github.com/benoitc/hackney -pkg_hackney_commit = master - -PACKAGES += hamcrest -pkg_hamcrest_name = hamcrest -pkg_hamcrest_description = Erlang port of Hamcrest -pkg_hamcrest_homepage = https://github.com/hyperthunk/hamcrest-erlang -pkg_hamcrest_fetch = git -pkg_hamcrest_repo = https://github.com/hyperthunk/hamcrest-erlang -pkg_hamcrest_commit = master - -PACKAGES += hanoidb -pkg_hanoidb_name = hanoidb -pkg_hanoidb_description = Erlang LSM BTree Storage -pkg_hanoidb_homepage = https://github.com/krestenkrab/hanoidb -pkg_hanoidb_fetch = git -pkg_hanoidb_repo = https://github.com/krestenkrab/hanoidb -pkg_hanoidb_commit = master - -PACKAGES += hottub -pkg_hottub_name = hottub -pkg_hottub_description = Permanent Erlang Worker Pool -pkg_hottub_homepage = https://github.com/bfrog/hottub -pkg_hottub_fetch = git -pkg_hottub_repo = https://github.com/bfrog/hottub -pkg_hottub_commit = master - -PACKAGES += hpack -pkg_hpack_name = hpack -pkg_hpack_description = HPACK Implementation for Erlang -pkg_hpack_homepage = https://github.com/joedevivo/hpack -pkg_hpack_fetch = git -pkg_hpack_repo = https://github.com/joedevivo/hpack -pkg_hpack_commit = master - -PACKAGES += hyper -pkg_hyper_name = hyper -pkg_hyper_description = Erlang implementation of HyperLogLog -pkg_hyper_homepage = https://github.com/GameAnalytics/hyper -pkg_hyper_fetch = git -pkg_hyper_repo = https://github.com/GameAnalytics/hyper -pkg_hyper_commit = master - -PACKAGES += ibrowse -pkg_ibrowse_name = ibrowse -pkg_ibrowse_description = Erlang HTTP client -pkg_ibrowse_homepage = https://github.com/cmullaparthi/ibrowse -pkg_ibrowse_fetch = git -pkg_ibrowse_repo = https://github.com/cmullaparthi/ibrowse -pkg_ibrowse_commit = v4.1.1 - -PACKAGES += ierlang -pkg_ierlang_name = ierlang -pkg_ierlang_description = An Erlang language kernel for IPython. -pkg_ierlang_homepage = https://github.com/robbielynch/ierlang -pkg_ierlang_fetch = git -pkg_ierlang_repo = https://github.com/robbielynch/ierlang -pkg_ierlang_commit = master - -PACKAGES += iota -pkg_iota_name = iota -pkg_iota_description = iota (Inter-dependency Objective Testing Apparatus) - a tool to enforce clean separation of responsibilities in Erlang code -pkg_iota_homepage = https://github.com/jpgneves/iota -pkg_iota_fetch = git -pkg_iota_repo = https://github.com/jpgneves/iota -pkg_iota_commit = master - -PACKAGES += ircd -pkg_ircd_name = ircd -pkg_ircd_description = A pluggable IRC daemon application/library for Erlang. -pkg_ircd_homepage = https://github.com/tonyg/erlang-ircd -pkg_ircd_fetch = git -pkg_ircd_repo = https://github.com/tonyg/erlang-ircd -pkg_ircd_commit = master - -PACKAGES += irc_lib -pkg_irc_lib_name = irc_lib -pkg_irc_lib_description = Erlang irc client library -pkg_irc_lib_homepage = https://github.com/OtpChatBot/irc_lib -pkg_irc_lib_fetch = git -pkg_irc_lib_repo = https://github.com/OtpChatBot/irc_lib -pkg_irc_lib_commit = master - -PACKAGES += iris -pkg_iris_name = iris -pkg_iris_description = Iris Erlang binding -pkg_iris_homepage = https://github.com/project-iris/iris-erl -pkg_iris_fetch = git -pkg_iris_repo = https://github.com/project-iris/iris-erl -pkg_iris_commit = master - -PACKAGES += iso8601 -pkg_iso8601_name = iso8601 -pkg_iso8601_description = Erlang ISO 8601 date formatter/parser -pkg_iso8601_homepage = https://github.com/seansawyer/erlang_iso8601 -pkg_iso8601_fetch = git -pkg_iso8601_repo = https://github.com/seansawyer/erlang_iso8601 -pkg_iso8601_commit = master - -PACKAGES += itweet -pkg_itweet_name = itweet -pkg_itweet_description = Twitter Stream API on ibrowse -pkg_itweet_homepage = http://inaka.github.com/itweet/ -pkg_itweet_fetch = git -pkg_itweet_repo = https://github.com/inaka/itweet -pkg_itweet_commit = v2.0 - -PACKAGES += jerg -pkg_jerg_name = jerg -pkg_jerg_description = JSON Schema to Erlang Records Generator -pkg_jerg_homepage = https://github.com/ddossot/jerg -pkg_jerg_fetch = git -pkg_jerg_repo = https://github.com/ddossot/jerg -pkg_jerg_commit = master - -PACKAGES += jesse -pkg_jesse_name = jesse -pkg_jesse_description = jesse (JSon Schema Erlang) is an implementation of a json schema validator for Erlang. -pkg_jesse_homepage = https://github.com/klarna/jesse -pkg_jesse_fetch = git -pkg_jesse_repo = https://github.com/klarna/jesse -pkg_jesse_commit = master - -PACKAGES += jiffy -pkg_jiffy_name = jiffy -pkg_jiffy_description = JSON NIFs for Erlang. -pkg_jiffy_homepage = https://github.com/davisp/jiffy -pkg_jiffy_fetch = git -pkg_jiffy_repo = https://github.com/davisp/jiffy -pkg_jiffy_commit = master - -PACKAGES += jiffy_v -pkg_jiffy_v_name = jiffy_v -pkg_jiffy_v_description = JSON validation utility -pkg_jiffy_v_homepage = https://github.com/shizzard/jiffy-v -pkg_jiffy_v_fetch = git -pkg_jiffy_v_repo = https://github.com/shizzard/jiffy-v -pkg_jiffy_v_commit = 0.3.3 - -PACKAGES += jobs -pkg_jobs_name = jobs -pkg_jobs_description = a Job scheduler for load regulation -pkg_jobs_homepage = https://github.com/esl/jobs -pkg_jobs_fetch = git -pkg_jobs_repo = https://github.com/esl/jobs -pkg_jobs_commit = 0.3 - -PACKAGES += joxa -pkg_joxa_name = joxa -pkg_joxa_description = A Modern Lisp for the Erlang VM -pkg_joxa_homepage = https://github.com/joxa/joxa -pkg_joxa_fetch = git -pkg_joxa_repo = https://github.com/joxa/joxa -pkg_joxa_commit = master - -PACKAGES += jsonerl -pkg_jsonerl_name = jsonerl -pkg_jsonerl_description = yet another but slightly different erlang <-> json encoder/decoder -pkg_jsonerl_homepage = https://github.com/lambder/jsonerl -pkg_jsonerl_fetch = git -pkg_jsonerl_repo = https://github.com/lambder/jsonerl -pkg_jsonerl_commit = master - -PACKAGES += json -pkg_json_name = json -pkg_json_description = a high level json library for erlang (17.0+) -pkg_json_homepage = https://github.com/talentdeficit/json -pkg_json_fetch = git -pkg_json_repo = https://github.com/talentdeficit/json -pkg_json_commit = master - -PACKAGES += jsonpath -pkg_jsonpath_name = jsonpath -pkg_jsonpath_description = Fast Erlang JSON data retrieval and updates via javascript-like notation -pkg_jsonpath_homepage = https://github.com/GeneStevens/jsonpath -pkg_jsonpath_fetch = git -pkg_jsonpath_repo = https://github.com/GeneStevens/jsonpath -pkg_jsonpath_commit = master - -PACKAGES += json_rec -pkg_json_rec_name = json_rec -pkg_json_rec_description = JSON to erlang record -pkg_json_rec_homepage = https://github.com/justinkirby/json_rec -pkg_json_rec_fetch = git -pkg_json_rec_repo = https://github.com/justinkirby/json_rec -pkg_json_rec_commit = master - -PACKAGES += jsonx -pkg_jsonx_name = jsonx -pkg_jsonx_description = JSONX is an Erlang library for efficient decode and encode JSON, written in C. -pkg_jsonx_homepage = https://github.com/iskra/jsonx -pkg_jsonx_fetch = git -pkg_jsonx_repo = https://github.com/iskra/jsonx -pkg_jsonx_commit = master - -PACKAGES += jsx -pkg_jsx_name = jsx -pkg_jsx_description = An Erlang application for consuming, producing and manipulating JSON. -pkg_jsx_homepage = https://github.com/talentdeficit/jsx -pkg_jsx_fetch = git -pkg_jsx_repo = https://github.com/talentdeficit/jsx -pkg_jsx_commit = master - -PACKAGES += kafka -pkg_kafka_name = kafka -pkg_kafka_description = Kafka consumer and producer in Erlang -pkg_kafka_homepage = https://github.com/wooga/kafka-erlang -pkg_kafka_fetch = git -pkg_kafka_repo = https://github.com/wooga/kafka-erlang -pkg_kafka_commit = master - -PACKAGES += kai -pkg_kai_name = kai -pkg_kai_description = DHT storage by Takeshi Inoue -pkg_kai_homepage = https://github.com/synrc/kai -pkg_kai_fetch = git -pkg_kai_repo = https://github.com/synrc/kai -pkg_kai_commit = master - -PACKAGES += katja -pkg_katja_name = katja -pkg_katja_description = A simple Riemann client written in Erlang. -pkg_katja_homepage = https://github.com/nifoc/katja -pkg_katja_fetch = git -pkg_katja_repo = https://github.com/nifoc/katja -pkg_katja_commit = master - -PACKAGES += kdht -pkg_kdht_name = kdht -pkg_kdht_description = kdht is an erlang DHT implementation -pkg_kdht_homepage = https://github.com/kevinlynx/kdht -pkg_kdht_fetch = git -pkg_kdht_repo = https://github.com/kevinlynx/kdht -pkg_kdht_commit = master - -PACKAGES += key2value -pkg_key2value_name = key2value -pkg_key2value_description = Erlang 2-way map -pkg_key2value_homepage = https://github.com/okeuday/key2value -pkg_key2value_fetch = git -pkg_key2value_repo = https://github.com/okeuday/key2value -pkg_key2value_commit = master - -PACKAGES += keys1value -pkg_keys1value_name = keys1value -pkg_keys1value_description = Erlang set associative map for key lists -pkg_keys1value_homepage = https://github.com/okeuday/keys1value -pkg_keys1value_fetch = git -pkg_keys1value_repo = https://github.com/okeuday/keys1value -pkg_keys1value_commit = master - -PACKAGES += kinetic -pkg_kinetic_name = kinetic -pkg_kinetic_description = Erlang Kinesis Client -pkg_kinetic_homepage = https://github.com/AdRoll/kinetic -pkg_kinetic_fetch = git -pkg_kinetic_repo = https://github.com/AdRoll/kinetic -pkg_kinetic_commit = master - -PACKAGES += kjell -pkg_kjell_name = kjell -pkg_kjell_description = Erlang Shell -pkg_kjell_homepage = https://github.com/karlll/kjell -pkg_kjell_fetch = git -pkg_kjell_repo = https://github.com/karlll/kjell -pkg_kjell_commit = master - -PACKAGES += kraken -pkg_kraken_name = kraken -pkg_kraken_description = Distributed Pubsub Server for Realtime Apps -pkg_kraken_homepage = https://github.com/Asana/kraken -pkg_kraken_fetch = git -pkg_kraken_repo = https://github.com/Asana/kraken -pkg_kraken_commit = master - -PACKAGES += kucumberl -pkg_kucumberl_name = kucumberl -pkg_kucumberl_description = A pure-erlang, open-source, implementation of Cucumber -pkg_kucumberl_homepage = https://github.com/openshine/kucumberl -pkg_kucumberl_fetch = git -pkg_kucumberl_repo = https://github.com/openshine/kucumberl -pkg_kucumberl_commit = master - -PACKAGES += kvc -pkg_kvc_name = kvc -pkg_kvc_description = KVC - Key Value Coding for Erlang data structures -pkg_kvc_homepage = https://github.com/etrepum/kvc -pkg_kvc_fetch = git -pkg_kvc_repo = https://github.com/etrepum/kvc -pkg_kvc_commit = master - -PACKAGES += kvlists -pkg_kvlists_name = kvlists -pkg_kvlists_description = Lists of key-value pairs (decoded JSON) in Erlang -pkg_kvlists_homepage = https://github.com/jcomellas/kvlists -pkg_kvlists_fetch = git -pkg_kvlists_repo = https://github.com/jcomellas/kvlists -pkg_kvlists_commit = master - -PACKAGES += kvs -pkg_kvs_name = kvs -pkg_kvs_description = Container and Iterator -pkg_kvs_homepage = https://github.com/synrc/kvs -pkg_kvs_fetch = git -pkg_kvs_repo = https://github.com/synrc/kvs -pkg_kvs_commit = master - -PACKAGES += lager_amqp_backend -pkg_lager_amqp_backend_name = lager_amqp_backend -pkg_lager_amqp_backend_description = AMQP RabbitMQ Lager backend -pkg_lager_amqp_backend_homepage = https://github.com/jbrisbin/lager_amqp_backend -pkg_lager_amqp_backend_fetch = git -pkg_lager_amqp_backend_repo = https://github.com/jbrisbin/lager_amqp_backend -pkg_lager_amqp_backend_commit = master - -PACKAGES += lager -pkg_lager_name = lager -pkg_lager_description = A logging framework for Erlang/OTP. -pkg_lager_homepage = https://github.com/basho/lager -pkg_lager_fetch = git -pkg_lager_repo = https://github.com/basho/lager -pkg_lager_commit = master - -PACKAGES += lager_syslog -pkg_lager_syslog_name = lager_syslog -pkg_lager_syslog_description = Syslog backend for lager -pkg_lager_syslog_homepage = https://github.com/basho/lager_syslog -pkg_lager_syslog_fetch = git -pkg_lager_syslog_repo = https://github.com/basho/lager_syslog -pkg_lager_syslog_commit = master - -PACKAGES += lambdapad -pkg_lambdapad_name = lambdapad -pkg_lambdapad_description = Static site generator using Erlang. Yes, Erlang. -pkg_lambdapad_homepage = https://github.com/gar1t/lambdapad -pkg_lambdapad_fetch = git -pkg_lambdapad_repo = https://github.com/gar1t/lambdapad -pkg_lambdapad_commit = master - -PACKAGES += lasp -pkg_lasp_name = lasp -pkg_lasp_description = A Language for Distributed, Eventually Consistent Computations -pkg_lasp_homepage = http://lasp-lang.org/ -pkg_lasp_fetch = git -pkg_lasp_repo = https://github.com/lasp-lang/lasp -pkg_lasp_commit = master - -PACKAGES += lasse -pkg_lasse_name = lasse -pkg_lasse_description = SSE handler for Cowboy -pkg_lasse_homepage = https://github.com/inaka/lasse -pkg_lasse_fetch = git -pkg_lasse_repo = https://github.com/inaka/lasse -pkg_lasse_commit = 0.1.0 - -PACKAGES += ldap -pkg_ldap_name = ldap -pkg_ldap_description = LDAP server written in Erlang -pkg_ldap_homepage = https://github.com/spawnproc/ldap -pkg_ldap_fetch = git -pkg_ldap_repo = https://github.com/spawnproc/ldap -pkg_ldap_commit = master - -PACKAGES += lethink -pkg_lethink_name = lethink -pkg_lethink_description = erlang driver for rethinkdb -pkg_lethink_homepage = https://github.com/taybin/lethink -pkg_lethink_fetch = git -pkg_lethink_repo = https://github.com/taybin/lethink -pkg_lethink_commit = master - -PACKAGES += lfe -pkg_lfe_name = lfe -pkg_lfe_description = Lisp Flavoured Erlang (LFE) -pkg_lfe_homepage = https://github.com/rvirding/lfe -pkg_lfe_fetch = git -pkg_lfe_repo = https://github.com/rvirding/lfe -pkg_lfe_commit = master - -PACKAGES += ling -pkg_ling_name = ling -pkg_ling_description = Erlang on Xen -pkg_ling_homepage = https://github.com/cloudozer/ling -pkg_ling_fetch = git -pkg_ling_repo = https://github.com/cloudozer/ling -pkg_ling_commit = master - -PACKAGES += live -pkg_live_name = live -pkg_live_description = Automated module and configuration reloader. -pkg_live_homepage = http://ninenines.eu -pkg_live_fetch = git -pkg_live_repo = https://github.com/ninenines/live -pkg_live_commit = master - -PACKAGES += lmq -pkg_lmq_name = lmq -pkg_lmq_description = Lightweight Message Queue -pkg_lmq_homepage = https://github.com/iij/lmq -pkg_lmq_fetch = git -pkg_lmq_repo = https://github.com/iij/lmq -pkg_lmq_commit = master - -PACKAGES += locker -pkg_locker_name = locker -pkg_locker_description = Atomic distributed 'check and set' for short-lived keys -pkg_locker_homepage = https://github.com/wooga/locker -pkg_locker_fetch = git -pkg_locker_repo = https://github.com/wooga/locker -pkg_locker_commit = master - -PACKAGES += locks -pkg_locks_name = locks -pkg_locks_description = A scalable, deadlock-resolving resource locker -pkg_locks_homepage = https://github.com/uwiger/locks -pkg_locks_fetch = git -pkg_locks_repo = https://github.com/uwiger/locks -pkg_locks_commit = master - -PACKAGES += log4erl -pkg_log4erl_name = log4erl -pkg_log4erl_description = A logger for erlang in the spirit of Log4J. -pkg_log4erl_homepage = https://github.com/ahmednawras/log4erl -pkg_log4erl_fetch = git -pkg_log4erl_repo = https://github.com/ahmednawras/log4erl -pkg_log4erl_commit = master - -PACKAGES += lol -pkg_lol_name = lol -pkg_lol_description = Lisp on erLang, and programming is fun again -pkg_lol_homepage = https://github.com/b0oh/lol -pkg_lol_fetch = git -pkg_lol_repo = https://github.com/b0oh/lol -pkg_lol_commit = master - -PACKAGES += lucid -pkg_lucid_name = lucid -pkg_lucid_description = HTTP/2 server written in Erlang -pkg_lucid_homepage = https://github.com/tatsuhiro-t/lucid -pkg_lucid_fetch = git -pkg_lucid_repo = https://github.com/tatsuhiro-t/lucid -pkg_lucid_commit = master - -PACKAGES += luerl -pkg_luerl_name = luerl -pkg_luerl_description = Lua in Erlang -pkg_luerl_homepage = https://github.com/rvirding/luerl -pkg_luerl_fetch = git -pkg_luerl_repo = https://github.com/rvirding/luerl -pkg_luerl_commit = develop - -PACKAGES += luwak -pkg_luwak_name = luwak -pkg_luwak_description = Large-object storage interface for Riak -pkg_luwak_homepage = https://github.com/basho/luwak -pkg_luwak_fetch = git -pkg_luwak_repo = https://github.com/basho/luwak -pkg_luwak_commit = master - -PACKAGES += lux -pkg_lux_name = lux -pkg_lux_description = Lux (LUcid eXpect scripting) simplifies test automation and provides an Expect-style execution of commands -pkg_lux_homepage = https://github.com/hawk/lux -pkg_lux_fetch = git -pkg_lux_repo = https://github.com/hawk/lux -pkg_lux_commit = master - -PACKAGES += machi -pkg_machi_name = machi -pkg_machi_description = Machi file store -pkg_machi_homepage = https://github.com/basho/machi -pkg_machi_fetch = git -pkg_machi_repo = https://github.com/basho/machi -pkg_machi_commit = master - -PACKAGES += mad -pkg_mad_name = mad -pkg_mad_description = Small and Fast Rebar Replacement -pkg_mad_homepage = https://github.com/synrc/mad -pkg_mad_fetch = git -pkg_mad_repo = https://github.com/synrc/mad -pkg_mad_commit = master - -PACKAGES += marina -pkg_marina_name = marina -pkg_marina_description = Non-blocking Erlang Cassandra CQL3 client -pkg_marina_homepage = https://github.com/lpgauth/marina -pkg_marina_fetch = git -pkg_marina_repo = https://github.com/lpgauth/marina -pkg_marina_commit = master - -PACKAGES += mavg -pkg_mavg_name = mavg -pkg_mavg_description = Erlang :: Exponential moving average library -pkg_mavg_homepage = https://github.com/EchoTeam/mavg -pkg_mavg_fetch = git -pkg_mavg_repo = https://github.com/EchoTeam/mavg -pkg_mavg_commit = master - -PACKAGES += mcd -pkg_mcd_name = mcd -pkg_mcd_description = Fast memcached protocol client in pure Erlang -pkg_mcd_homepage = https://github.com/EchoTeam/mcd -pkg_mcd_fetch = git -pkg_mcd_repo = https://github.com/EchoTeam/mcd -pkg_mcd_commit = master - -PACKAGES += mcerlang -pkg_mcerlang_name = mcerlang -pkg_mcerlang_description = The McErlang model checker for Erlang -pkg_mcerlang_homepage = https://github.com/fredlund/McErlang -pkg_mcerlang_fetch = git -pkg_mcerlang_repo = https://github.com/fredlund/McErlang -pkg_mcerlang_commit = master - -PACKAGES += mc_erl -pkg_mc_erl_name = mc_erl -pkg_mc_erl_description = mc-erl is a server for Minecraft 1.4.7 written in Erlang. -pkg_mc_erl_homepage = https://github.com/clonejo/mc-erl -pkg_mc_erl_fetch = git -pkg_mc_erl_repo = https://github.com/clonejo/mc-erl -pkg_mc_erl_commit = master - -PACKAGES += meck -pkg_meck_name = meck -pkg_meck_description = A mocking library for Erlang -pkg_meck_homepage = https://github.com/eproxus/meck -pkg_meck_fetch = git -pkg_meck_repo = https://github.com/eproxus/meck -pkg_meck_commit = master - -PACKAGES += mekao -pkg_mekao_name = mekao -pkg_mekao_description = SQL constructor -pkg_mekao_homepage = https://github.com/ddosia/mekao -pkg_mekao_fetch = git -pkg_mekao_repo = https://github.com/ddosia/mekao -pkg_mekao_commit = master - -PACKAGES += memo -pkg_memo_name = memo -pkg_memo_description = Erlang memoization server -pkg_memo_homepage = https://github.com/tuncer/memo -pkg_memo_fetch = git -pkg_memo_repo = https://github.com/tuncer/memo -pkg_memo_commit = master - -PACKAGES += merge_index -pkg_merge_index_name = merge_index -pkg_merge_index_description = MergeIndex is an Erlang library for storing ordered sets on disk. It is very similar to an SSTable (in Google's Bigtable) or an HFile (in Hadoop). -pkg_merge_index_homepage = https://github.com/basho/merge_index -pkg_merge_index_fetch = git -pkg_merge_index_repo = https://github.com/basho/merge_index -pkg_merge_index_commit = master - -PACKAGES += merl -pkg_merl_name = merl -pkg_merl_description = Metaprogramming in Erlang -pkg_merl_homepage = https://github.com/richcarl/merl -pkg_merl_fetch = git -pkg_merl_repo = https://github.com/richcarl/merl -pkg_merl_commit = master - -PACKAGES += mimetypes -pkg_mimetypes_name = mimetypes -pkg_mimetypes_description = Erlang MIME types library -pkg_mimetypes_homepage = https://github.com/spawngrid/mimetypes -pkg_mimetypes_fetch = git -pkg_mimetypes_repo = https://github.com/spawngrid/mimetypes -pkg_mimetypes_commit = master - -PACKAGES += mixer -pkg_mixer_name = mixer -pkg_mixer_description = Mix in functions from other modules -pkg_mixer_homepage = https://github.com/chef/mixer -pkg_mixer_fetch = git -pkg_mixer_repo = https://github.com/chef/mixer -pkg_mixer_commit = master - -PACKAGES += mochiweb -pkg_mochiweb_name = mochiweb -pkg_mochiweb_description = MochiWeb is an Erlang library for building lightweight HTTP servers. -pkg_mochiweb_homepage = https://github.com/mochi/mochiweb -pkg_mochiweb_fetch = git -pkg_mochiweb_repo = https://github.com/mochi/mochiweb -pkg_mochiweb_commit = master - -PACKAGES += mochiweb_xpath -pkg_mochiweb_xpath_name = mochiweb_xpath -pkg_mochiweb_xpath_description = XPath support for mochiweb's html parser -pkg_mochiweb_xpath_homepage = https://github.com/retnuh/mochiweb_xpath -pkg_mochiweb_xpath_fetch = git -pkg_mochiweb_xpath_repo = https://github.com/retnuh/mochiweb_xpath -pkg_mochiweb_xpath_commit = master - -PACKAGES += mockgyver -pkg_mockgyver_name = mockgyver -pkg_mockgyver_description = A mocking library for Erlang -pkg_mockgyver_homepage = https://github.com/klajo/mockgyver -pkg_mockgyver_fetch = git -pkg_mockgyver_repo = https://github.com/klajo/mockgyver -pkg_mockgyver_commit = master - -PACKAGES += modlib -pkg_modlib_name = modlib -pkg_modlib_description = Web framework based on Erlang's inets httpd -pkg_modlib_homepage = https://github.com/gar1t/modlib -pkg_modlib_fetch = git -pkg_modlib_repo = https://github.com/gar1t/modlib -pkg_modlib_commit = master - -PACKAGES += mongodb -pkg_mongodb_name = mongodb -pkg_mongodb_description = MongoDB driver for Erlang -pkg_mongodb_homepage = https://github.com/comtihon/mongodb-erlang -pkg_mongodb_fetch = git -pkg_mongodb_repo = https://github.com/comtihon/mongodb-erlang -pkg_mongodb_commit = master - -PACKAGES += mongooseim -pkg_mongooseim_name = mongooseim -pkg_mongooseim_description = Jabber / XMPP server with focus on performance and scalability, by Erlang Solutions -pkg_mongooseim_homepage = https://www.erlang-solutions.com/products/mongooseim-massively-scalable-ejabberd-platform -pkg_mongooseim_fetch = git -pkg_mongooseim_repo = https://github.com/esl/MongooseIM -pkg_mongooseim_commit = master - -PACKAGES += moyo -pkg_moyo_name = moyo -pkg_moyo_description = Erlang utility functions library -pkg_moyo_homepage = https://github.com/dwango/moyo -pkg_moyo_fetch = git -pkg_moyo_repo = https://github.com/dwango/moyo -pkg_moyo_commit = master - -PACKAGES += msgpack -pkg_msgpack_name = msgpack -pkg_msgpack_description = MessagePack (de)serializer implementation for Erlang -pkg_msgpack_homepage = https://github.com/msgpack/msgpack-erlang -pkg_msgpack_fetch = git -pkg_msgpack_repo = https://github.com/msgpack/msgpack-erlang -pkg_msgpack_commit = master - -PACKAGES += mu2 -pkg_mu2_name = mu2 -pkg_mu2_description = Erlang mutation testing tool -pkg_mu2_homepage = https://github.com/ramsay-t/mu2 -pkg_mu2_fetch = git -pkg_mu2_repo = https://github.com/ramsay-t/mu2 -pkg_mu2_commit = master - -PACKAGES += mustache -pkg_mustache_name = mustache -pkg_mustache_description = Mustache template engine for Erlang. -pkg_mustache_homepage = https://github.com/mojombo/mustache.erl -pkg_mustache_fetch = git -pkg_mustache_repo = https://github.com/mojombo/mustache.erl -pkg_mustache_commit = master - -PACKAGES += myproto -pkg_myproto_name = myproto -pkg_myproto_description = MySQL Server Protocol in Erlang -pkg_myproto_homepage = https://github.com/altenwald/myproto -pkg_myproto_fetch = git -pkg_myproto_repo = https://github.com/altenwald/myproto -pkg_myproto_commit = master - -PACKAGES += mysql -pkg_mysql_name = mysql -pkg_mysql_description = Erlang MySQL Driver (from code.google.com) -pkg_mysql_homepage = https://github.com/dizzyd/erlang-mysql-driver -pkg_mysql_fetch = git -pkg_mysql_repo = https://github.com/dizzyd/erlang-mysql-driver -pkg_mysql_commit = master - -PACKAGES += n2o -pkg_n2o_name = n2o -pkg_n2o_description = WebSocket Application Server -pkg_n2o_homepage = https://github.com/5HT/n2o -pkg_n2o_fetch = git -pkg_n2o_repo = https://github.com/5HT/n2o -pkg_n2o_commit = master - -PACKAGES += nat_upnp -pkg_nat_upnp_name = nat_upnp -pkg_nat_upnp_description = Erlang library to map your internal port to an external using UNP IGD -pkg_nat_upnp_homepage = https://github.com/benoitc/nat_upnp -pkg_nat_upnp_fetch = git -pkg_nat_upnp_repo = https://github.com/benoitc/nat_upnp -pkg_nat_upnp_commit = master - -PACKAGES += neo4j -pkg_neo4j_name = neo4j -pkg_neo4j_description = Erlang client library for Neo4J. -pkg_neo4j_homepage = https://github.com/dmitriid/neo4j-erlang -pkg_neo4j_fetch = git -pkg_neo4j_repo = https://github.com/dmitriid/neo4j-erlang -pkg_neo4j_commit = master - -PACKAGES += neotoma -pkg_neotoma_name = neotoma -pkg_neotoma_description = Erlang library and packrat parser-generator for parsing expression grammars. -pkg_neotoma_homepage = https://github.com/seancribbs/neotoma -pkg_neotoma_fetch = git -pkg_neotoma_repo = https://github.com/seancribbs/neotoma -pkg_neotoma_commit = master - -PACKAGES += newrelic -pkg_newrelic_name = newrelic -pkg_newrelic_description = Erlang library for sending metrics to New Relic -pkg_newrelic_homepage = https://github.com/wooga/newrelic-erlang -pkg_newrelic_fetch = git -pkg_newrelic_repo = https://github.com/wooga/newrelic-erlang -pkg_newrelic_commit = master - -PACKAGES += nifty -pkg_nifty_name = nifty -pkg_nifty_description = Erlang NIF wrapper generator -pkg_nifty_homepage = https://github.com/parapluu/nifty -pkg_nifty_fetch = git -pkg_nifty_repo = https://github.com/parapluu/nifty -pkg_nifty_commit = master - -PACKAGES += nitrogen_core -pkg_nitrogen_core_name = nitrogen_core -pkg_nitrogen_core_description = The core Nitrogen library. -pkg_nitrogen_core_homepage = http://nitrogenproject.com/ -pkg_nitrogen_core_fetch = git -pkg_nitrogen_core_repo = https://github.com/nitrogen/nitrogen_core -pkg_nitrogen_core_commit = master - -PACKAGES += nkbase -pkg_nkbase_name = nkbase -pkg_nkbase_description = NkBASE distributed database -pkg_nkbase_homepage = https://github.com/Nekso/nkbase -pkg_nkbase_fetch = git -pkg_nkbase_repo = https://github.com/Nekso/nkbase -pkg_nkbase_commit = develop - -PACKAGES += nkdocker -pkg_nkdocker_name = nkdocker -pkg_nkdocker_description = Erlang Docker client -pkg_nkdocker_homepage = https://github.com/Nekso/nkdocker -pkg_nkdocker_fetch = git -pkg_nkdocker_repo = https://github.com/Nekso/nkdocker -pkg_nkdocker_commit = master - -PACKAGES += nkpacket -pkg_nkpacket_name = nkpacket -pkg_nkpacket_description = Generic Erlang transport layer -pkg_nkpacket_homepage = https://github.com/Nekso/nkpacket -pkg_nkpacket_fetch = git -pkg_nkpacket_repo = https://github.com/Nekso/nkpacket -pkg_nkpacket_commit = master - -PACKAGES += nodefinder -pkg_nodefinder_name = nodefinder -pkg_nodefinder_description = automatic node discovery via UDP multicast -pkg_nodefinder_homepage = https://github.com/erlanger/nodefinder -pkg_nodefinder_fetch = git -pkg_nodefinder_repo = https://github.com/okeuday/nodefinder -pkg_nodefinder_commit = master - -PACKAGES += nprocreg -pkg_nprocreg_name = nprocreg -pkg_nprocreg_description = Minimal Distributed Erlang Process Registry -pkg_nprocreg_homepage = http://nitrogenproject.com/ -pkg_nprocreg_fetch = git -pkg_nprocreg_repo = https://github.com/nitrogen/nprocreg -pkg_nprocreg_commit = master - -PACKAGES += oauth2c -pkg_oauth2c_name = oauth2c -pkg_oauth2c_description = Erlang OAuth2 Client -pkg_oauth2c_homepage = https://github.com/kivra/oauth2_client -pkg_oauth2c_fetch = git -pkg_oauth2c_repo = https://github.com/kivra/oauth2_client -pkg_oauth2c_commit = master - -PACKAGES += oauth2 -pkg_oauth2_name = oauth2 -pkg_oauth2_description = Erlang Oauth2 implementation -pkg_oauth2_homepage = https://github.com/kivra/oauth2 -pkg_oauth2_fetch = git -pkg_oauth2_repo = https://github.com/kivra/oauth2 -pkg_oauth2_commit = master - -PACKAGES += oauth -pkg_oauth_name = oauth -pkg_oauth_description = An Erlang OAuth 1.0 implementation -pkg_oauth_homepage = https://github.com/tim/erlang-oauth -pkg_oauth_fetch = git -pkg_oauth_repo = https://github.com/tim/erlang-oauth -pkg_oauth_commit = master - -PACKAGES += of_protocol -pkg_of_protocol_name = of_protocol -pkg_of_protocol_description = OpenFlow Protocol Library for Erlang -pkg_of_protocol_homepage = https://github.com/FlowForwarding/of_protocol -pkg_of_protocol_fetch = git -pkg_of_protocol_repo = https://github.com/FlowForwarding/of_protocol -pkg_of_protocol_commit = master - -PACKAGES += openflow -pkg_openflow_name = openflow -pkg_openflow_description = An OpenFlow controller written in pure erlang -pkg_openflow_homepage = https://github.com/renatoaguiar/erlang-openflow -pkg_openflow_fetch = git -pkg_openflow_repo = https://github.com/renatoaguiar/erlang-openflow -pkg_openflow_commit = master - -PACKAGES += openid -pkg_openid_name = openid -pkg_openid_description = Erlang OpenID -pkg_openid_homepage = https://github.com/brendonh/erl_openid -pkg_openid_fetch = git -pkg_openid_repo = https://github.com/brendonh/erl_openid -pkg_openid_commit = master - -PACKAGES += openpoker -pkg_openpoker_name = openpoker -pkg_openpoker_description = Genesis Texas hold'em Game Server -pkg_openpoker_homepage = https://github.com/hpyhacking/openpoker -pkg_openpoker_fetch = git -pkg_openpoker_repo = https://github.com/hpyhacking/openpoker -pkg_openpoker_commit = master - -PACKAGES += pal -pkg_pal_name = pal -pkg_pal_description = Pragmatic Authentication Library -pkg_pal_homepage = https://github.com/manifest/pal -pkg_pal_fetch = git -pkg_pal_repo = https://github.com/manifest/pal -pkg_pal_commit = master - -PACKAGES += parse_trans -pkg_parse_trans_name = parse_trans -pkg_parse_trans_description = Parse transform utilities for Erlang -pkg_parse_trans_homepage = https://github.com/uwiger/parse_trans -pkg_parse_trans_fetch = git -pkg_parse_trans_repo = https://github.com/uwiger/parse_trans -pkg_parse_trans_commit = master - -PACKAGES += parsexml -pkg_parsexml_name = parsexml -pkg_parsexml_description = Simple DOM XML parser with convenient and very simple API -pkg_parsexml_homepage = https://github.com/maxlapshin/parsexml -pkg_parsexml_fetch = git -pkg_parsexml_repo = https://github.com/maxlapshin/parsexml -pkg_parsexml_commit = master - -PACKAGES += pegjs -pkg_pegjs_name = pegjs -pkg_pegjs_description = An implementation of PEG.js grammar for Erlang. -pkg_pegjs_homepage = https://github.com/dmitriid/pegjs -pkg_pegjs_fetch = git -pkg_pegjs_repo = https://github.com/dmitriid/pegjs -pkg_pegjs_commit = 0.3 - -PACKAGES += percept2 -pkg_percept2_name = percept2 -pkg_percept2_description = Concurrent profiling tool for Erlang -pkg_percept2_homepage = https://github.com/huiqing/percept2 -pkg_percept2_fetch = git -pkg_percept2_repo = https://github.com/huiqing/percept2 -pkg_percept2_commit = master - -PACKAGES += pgsql -pkg_pgsql_name = pgsql -pkg_pgsql_description = Erlang PostgreSQL driver -pkg_pgsql_homepage = https://github.com/semiocast/pgsql -pkg_pgsql_fetch = git -pkg_pgsql_repo = https://github.com/semiocast/pgsql -pkg_pgsql_commit = master - -PACKAGES += pkgx -pkg_pkgx_name = pkgx -pkg_pkgx_description = Build .deb packages from Erlang releases -pkg_pkgx_homepage = https://github.com/arjan/pkgx -pkg_pkgx_fetch = git -pkg_pkgx_repo = https://github.com/arjan/pkgx -pkg_pkgx_commit = master - -PACKAGES += pkt -pkg_pkt_name = pkt -pkg_pkt_description = Erlang network protocol library -pkg_pkt_homepage = https://github.com/msantos/pkt -pkg_pkt_fetch = git -pkg_pkt_repo = https://github.com/msantos/pkt -pkg_pkt_commit = master - -PACKAGES += plain_fsm -pkg_plain_fsm_name = plain_fsm -pkg_plain_fsm_description = A behaviour/support library for writing plain Erlang FSMs. -pkg_plain_fsm_homepage = https://github.com/uwiger/plain_fsm -pkg_plain_fsm_fetch = git -pkg_plain_fsm_repo = https://github.com/uwiger/plain_fsm -pkg_plain_fsm_commit = master - -PACKAGES += plumtree -pkg_plumtree_name = plumtree -pkg_plumtree_description = Epidemic Broadcast Trees -pkg_plumtree_homepage = https://github.com/helium/plumtree -pkg_plumtree_fetch = git -pkg_plumtree_repo = https://github.com/helium/plumtree -pkg_plumtree_commit = master - -PACKAGES += pmod_transform -pkg_pmod_transform_name = pmod_transform -pkg_pmod_transform_description = Parse transform for parameterized modules -pkg_pmod_transform_homepage = https://github.com/erlang/pmod_transform -pkg_pmod_transform_fetch = git -pkg_pmod_transform_repo = https://github.com/erlang/pmod_transform -pkg_pmod_transform_commit = master - -PACKAGES += pobox -pkg_pobox_name = pobox -pkg_pobox_description = External buffer processes to protect against mailbox overflow in Erlang -pkg_pobox_homepage = https://github.com/ferd/pobox -pkg_pobox_fetch = git -pkg_pobox_repo = https://github.com/ferd/pobox -pkg_pobox_commit = master - -PACKAGES += ponos -pkg_ponos_name = ponos -pkg_ponos_description = ponos is a simple yet powerful load generator written in erlang -pkg_ponos_homepage = https://github.com/klarna/ponos -pkg_ponos_fetch = git -pkg_ponos_repo = https://github.com/klarna/ponos -pkg_ponos_commit = master - -PACKAGES += poolboy -pkg_poolboy_name = poolboy -pkg_poolboy_description = A hunky Erlang worker pool factory -pkg_poolboy_homepage = https://github.com/devinus/poolboy -pkg_poolboy_fetch = git -pkg_poolboy_repo = https://github.com/devinus/poolboy -pkg_poolboy_commit = master - -PACKAGES += pooler -pkg_pooler_name = pooler -pkg_pooler_description = An OTP Process Pool Application -pkg_pooler_homepage = https://github.com/seth/pooler -pkg_pooler_fetch = git -pkg_pooler_repo = https://github.com/seth/pooler -pkg_pooler_commit = master - -PACKAGES += pqueue -pkg_pqueue_name = pqueue -pkg_pqueue_description = Erlang Priority Queues -pkg_pqueue_homepage = https://github.com/okeuday/pqueue -pkg_pqueue_fetch = git -pkg_pqueue_repo = https://github.com/okeuday/pqueue -pkg_pqueue_commit = master - -PACKAGES += procket -pkg_procket_name = procket -pkg_procket_description = Erlang interface to low level socket operations -pkg_procket_homepage = http://blog.listincomprehension.com/search/label/procket -pkg_procket_fetch = git -pkg_procket_repo = https://github.com/msantos/procket -pkg_procket_commit = master - -PACKAGES += proper -pkg_proper_name = proper -pkg_proper_description = PropEr: a QuickCheck-inspired property-based testing tool for Erlang. -pkg_proper_homepage = http://proper.softlab.ntua.gr -pkg_proper_fetch = git -pkg_proper_repo = https://github.com/manopapad/proper -pkg_proper_commit = master - -PACKAGES += prop -pkg_prop_name = prop -pkg_prop_description = An Erlang code scaffolding and generator system. -pkg_prop_homepage = https://github.com/nuex/prop -pkg_prop_fetch = git -pkg_prop_repo = https://github.com/nuex/prop -pkg_prop_commit = master - -PACKAGES += props -pkg_props_name = props -pkg_props_description = Property structure library -pkg_props_homepage = https://github.com/greyarea/props -pkg_props_fetch = git -pkg_props_repo = https://github.com/greyarea/props -pkg_props_commit = master - -PACKAGES += protobuffs -pkg_protobuffs_name = protobuffs -pkg_protobuffs_description = An implementation of Google's Protocol Buffers for Erlang, based on ngerakines/erlang_protobuffs. -pkg_protobuffs_homepage = https://github.com/basho/erlang_protobuffs -pkg_protobuffs_fetch = git -pkg_protobuffs_repo = https://github.com/basho/erlang_protobuffs -pkg_protobuffs_commit = master - -PACKAGES += psycho -pkg_psycho_name = psycho -pkg_psycho_description = HTTP server that provides a WSGI-like interface for applications and middleware. -pkg_psycho_homepage = https://github.com/gar1t/psycho -pkg_psycho_fetch = git -pkg_psycho_repo = https://github.com/gar1t/psycho -pkg_psycho_commit = master - -PACKAGES += ptrackerl -pkg_ptrackerl_name = ptrackerl -pkg_ptrackerl_description = Pivotal Tracker API Client written in Erlang -pkg_ptrackerl_homepage = https://github.com/inaka/ptrackerl -pkg_ptrackerl_fetch = git -pkg_ptrackerl_repo = https://github.com/inaka/ptrackerl -pkg_ptrackerl_commit = master - -PACKAGES += purity -pkg_purity_name = purity -pkg_purity_description = A side-effect analyzer for Erlang -pkg_purity_homepage = https://github.com/mpitid/purity -pkg_purity_fetch = git -pkg_purity_repo = https://github.com/mpitid/purity -pkg_purity_commit = master - -PACKAGES += push_service -pkg_push_service_name = push_service -pkg_push_service_description = Push service -pkg_push_service_homepage = https://github.com/hairyhum/push_service -pkg_push_service_fetch = git -pkg_push_service_repo = https://github.com/hairyhum/push_service -pkg_push_service_commit = master - -PACKAGES += qdate -pkg_qdate_name = qdate -pkg_qdate_description = Date, time, and timezone parsing, formatting, and conversion for Erlang. -pkg_qdate_homepage = https://github.com/choptastic/qdate -pkg_qdate_fetch = git -pkg_qdate_repo = https://github.com/choptastic/qdate -pkg_qdate_commit = 0.4.0 - -PACKAGES += qrcode -pkg_qrcode_name = qrcode -pkg_qrcode_description = QR Code encoder in Erlang -pkg_qrcode_homepage = https://github.com/komone/qrcode -pkg_qrcode_fetch = git -pkg_qrcode_repo = https://github.com/komone/qrcode -pkg_qrcode_commit = master - -PACKAGES += quest -pkg_quest_name = quest -pkg_quest_description = Learn Erlang through this set of challenges. An interactive system for getting to know Erlang. -pkg_quest_homepage = https://github.com/eriksoe/ErlangQuest -pkg_quest_fetch = git -pkg_quest_repo = https://github.com/eriksoe/ErlangQuest -pkg_quest_commit = master - -PACKAGES += quickrand -pkg_quickrand_name = quickrand -pkg_quickrand_description = Quick Erlang Random Number Generation -pkg_quickrand_homepage = https://github.com/okeuday/quickrand -pkg_quickrand_fetch = git -pkg_quickrand_repo = https://github.com/okeuday/quickrand -pkg_quickrand_commit = master - -PACKAGES += rabbit_exchange_type_riak -pkg_rabbit_exchange_type_riak_name = rabbit_exchange_type_riak -pkg_rabbit_exchange_type_riak_description = Custom RabbitMQ exchange type for sticking messages in Riak -pkg_rabbit_exchange_type_riak_homepage = https://github.com/jbrisbin/riak-exchange -pkg_rabbit_exchange_type_riak_fetch = git -pkg_rabbit_exchange_type_riak_repo = https://github.com/jbrisbin/riak-exchange -pkg_rabbit_exchange_type_riak_commit = master - -PACKAGES += rabbit -pkg_rabbit_name = rabbit -pkg_rabbit_description = RabbitMQ Server -pkg_rabbit_homepage = https://www.rabbitmq.com/ -pkg_rabbit_fetch = git -pkg_rabbit_repo = https://github.com/rabbitmq/rabbitmq-server.git -pkg_rabbit_commit = master - -PACKAGES += rack -pkg_rack_name = rack -pkg_rack_description = Rack handler for erlang -pkg_rack_homepage = https://github.com/erlyvideo/rack -pkg_rack_fetch = git -pkg_rack_repo = https://github.com/erlyvideo/rack -pkg_rack_commit = master - -PACKAGES += radierl -pkg_radierl_name = radierl -pkg_radierl_description = RADIUS protocol stack implemented in Erlang. -pkg_radierl_homepage = https://github.com/vances/radierl -pkg_radierl_fetch = git -pkg_radierl_repo = https://github.com/vances/radierl -pkg_radierl_commit = master - -PACKAGES += rafter -pkg_rafter_name = rafter -pkg_rafter_description = An Erlang library application which implements the Raft consensus protocol -pkg_rafter_homepage = https://github.com/andrewjstone/rafter -pkg_rafter_fetch = git -pkg_rafter_repo = https://github.com/andrewjstone/rafter -pkg_rafter_commit = master - -PACKAGES += ranch -pkg_ranch_name = ranch -pkg_ranch_description = Socket acceptor pool for TCP protocols. -pkg_ranch_homepage = http://ninenines.eu -pkg_ranch_fetch = git -pkg_ranch_repo = https://github.com/ninenines/ranch -pkg_ranch_commit = 1.1.0 - -PACKAGES += rbeacon -pkg_rbeacon_name = rbeacon -pkg_rbeacon_description = LAN discovery and presence in Erlang. -pkg_rbeacon_homepage = https://github.com/refuge/rbeacon -pkg_rbeacon_fetch = git -pkg_rbeacon_repo = https://github.com/refuge/rbeacon -pkg_rbeacon_commit = master - -PACKAGES += rebar -pkg_rebar_name = rebar -pkg_rebar_description = Erlang build tool that makes it easy to compile and test Erlang applications, port drivers and releases. -pkg_rebar_homepage = http://www.rebar3.org -pkg_rebar_fetch = git -pkg_rebar_repo = https://github.com/rebar/rebar3 -pkg_rebar_commit = master - -PACKAGES += rebus -pkg_rebus_name = rebus -pkg_rebus_description = A stupid simple, internal, pub/sub event bus written in- and for Erlang. -pkg_rebus_homepage = https://github.com/olle/rebus -pkg_rebus_fetch = git -pkg_rebus_repo = https://github.com/olle/rebus -pkg_rebus_commit = master - -PACKAGES += rec2json -pkg_rec2json_name = rec2json -pkg_rec2json_description = Compile erlang record definitions into modules to convert them to/from json easily. -pkg_rec2json_homepage = https://github.com/lordnull/rec2json -pkg_rec2json_fetch = git -pkg_rec2json_repo = https://github.com/lordnull/rec2json -pkg_rec2json_commit = master - -PACKAGES += recon -pkg_recon_name = recon -pkg_recon_description = Collection of functions and scripts to debug Erlang in production. -pkg_recon_homepage = https://github.com/ferd/recon -pkg_recon_fetch = git -pkg_recon_repo = https://github.com/ferd/recon -pkg_recon_commit = 2.2.1 - -PACKAGES += record_info -pkg_record_info_name = record_info -pkg_record_info_description = Convert between record and proplist -pkg_record_info_homepage = https://github.com/bipthelin/erlang-record_info -pkg_record_info_fetch = git -pkg_record_info_repo = https://github.com/bipthelin/erlang-record_info -pkg_record_info_commit = master - -PACKAGES += redgrid -pkg_redgrid_name = redgrid -pkg_redgrid_description = automatic Erlang node discovery via redis -pkg_redgrid_homepage = https://github.com/jkvor/redgrid -pkg_redgrid_fetch = git -pkg_redgrid_repo = https://github.com/jkvor/redgrid -pkg_redgrid_commit = master - -PACKAGES += redo -pkg_redo_name = redo -pkg_redo_description = pipelined erlang redis client -pkg_redo_homepage = https://github.com/jkvor/redo -pkg_redo_fetch = git -pkg_redo_repo = https://github.com/jkvor/redo -pkg_redo_commit = master - -PACKAGES += reltool_util -pkg_reltool_util_name = reltool_util -pkg_reltool_util_description = Erlang reltool utility functionality application -pkg_reltool_util_homepage = https://github.com/okeuday/reltool_util -pkg_reltool_util_fetch = git -pkg_reltool_util_repo = https://github.com/okeuday/reltool_util -pkg_reltool_util_commit = master - -PACKAGES += relx -pkg_relx_name = relx -pkg_relx_description = Sane, simple release creation for Erlang -pkg_relx_homepage = https://github.com/erlware/relx -pkg_relx_fetch = git -pkg_relx_repo = https://github.com/erlware/relx -pkg_relx_commit = master - -PACKAGES += resource_discovery -pkg_resource_discovery_name = resource_discovery -pkg_resource_discovery_description = An application used to dynamically discover resources present in an Erlang node cluster. -pkg_resource_discovery_homepage = http://erlware.org/ -pkg_resource_discovery_fetch = git -pkg_resource_discovery_repo = https://github.com/erlware/resource_discovery -pkg_resource_discovery_commit = master - -PACKAGES += restc -pkg_restc_name = restc -pkg_restc_description = Erlang Rest Client -pkg_restc_homepage = https://github.com/kivra/restclient -pkg_restc_fetch = git -pkg_restc_repo = https://github.com/kivra/restclient -pkg_restc_commit = master - -PACKAGES += rfc4627_jsonrpc -pkg_rfc4627_jsonrpc_name = rfc4627_jsonrpc -pkg_rfc4627_jsonrpc_description = Erlang RFC4627 (JSON) codec and JSON-RPC server implementation. -pkg_rfc4627_jsonrpc_homepage = https://github.com/tonyg/erlang-rfc4627 -pkg_rfc4627_jsonrpc_fetch = git -pkg_rfc4627_jsonrpc_repo = https://github.com/tonyg/erlang-rfc4627 -pkg_rfc4627_jsonrpc_commit = master - -PACKAGES += riakc -pkg_riakc_name = riakc -pkg_riakc_description = Erlang clients for Riak. -pkg_riakc_homepage = https://github.com/basho/riak-erlang-client -pkg_riakc_fetch = git -pkg_riakc_repo = https://github.com/basho/riak-erlang-client -pkg_riakc_commit = master - -PACKAGES += riak_core -pkg_riak_core_name = riak_core -pkg_riak_core_description = Distributed systems infrastructure used by Riak. -pkg_riak_core_homepage = https://github.com/basho/riak_core -pkg_riak_core_fetch = git -pkg_riak_core_repo = https://github.com/basho/riak_core -pkg_riak_core_commit = master - -PACKAGES += riak_dt -pkg_riak_dt_name = riak_dt -pkg_riak_dt_description = Convergent replicated datatypes in Erlang -pkg_riak_dt_homepage = https://github.com/basho/riak_dt -pkg_riak_dt_fetch = git -pkg_riak_dt_repo = https://github.com/basho/riak_dt -pkg_riak_dt_commit = master - -PACKAGES += riak_ensemble -pkg_riak_ensemble_name = riak_ensemble -pkg_riak_ensemble_description = Multi-Paxos framework in Erlang -pkg_riak_ensemble_homepage = https://github.com/basho/riak_ensemble -pkg_riak_ensemble_fetch = git -pkg_riak_ensemble_repo = https://github.com/basho/riak_ensemble -pkg_riak_ensemble_commit = master - -PACKAGES += riakhttpc -pkg_riakhttpc_name = riakhttpc -pkg_riakhttpc_description = Riak Erlang client using the HTTP interface -pkg_riakhttpc_homepage = https://github.com/basho/riak-erlang-http-client -pkg_riakhttpc_fetch = git -pkg_riakhttpc_repo = https://github.com/basho/riak-erlang-http-client -pkg_riakhttpc_commit = master - -PACKAGES += riak_kv -pkg_riak_kv_name = riak_kv -pkg_riak_kv_description = Riak Key/Value Store -pkg_riak_kv_homepage = https://github.com/basho/riak_kv -pkg_riak_kv_fetch = git -pkg_riak_kv_repo = https://github.com/basho/riak_kv -pkg_riak_kv_commit = master - -PACKAGES += riaknostic -pkg_riaknostic_name = riaknostic -pkg_riaknostic_description = A diagnostic tool for Riak installations, to find common errors asap -pkg_riaknostic_homepage = https://github.com/basho/riaknostic -pkg_riaknostic_fetch = git -pkg_riaknostic_repo = https://github.com/basho/riaknostic -pkg_riaknostic_commit = master - -PACKAGES += riak_pg -pkg_riak_pg_name = riak_pg -pkg_riak_pg_description = Distributed process groups with riak_core. -pkg_riak_pg_homepage = https://github.com/cmeiklejohn/riak_pg -pkg_riak_pg_fetch = git -pkg_riak_pg_repo = https://github.com/cmeiklejohn/riak_pg -pkg_riak_pg_commit = master - -PACKAGES += riak_pipe -pkg_riak_pipe_name = riak_pipe -pkg_riak_pipe_description = Riak Pipelines -pkg_riak_pipe_homepage = https://github.com/basho/riak_pipe -pkg_riak_pipe_fetch = git -pkg_riak_pipe_repo = https://github.com/basho/riak_pipe -pkg_riak_pipe_commit = master - -PACKAGES += riakpool -pkg_riakpool_name = riakpool -pkg_riakpool_description = erlang riak client pool -pkg_riakpool_homepage = https://github.com/dweldon/riakpool -pkg_riakpool_fetch = git -pkg_riakpool_repo = https://github.com/dweldon/riakpool -pkg_riakpool_commit = master - -PACKAGES += riak_sysmon -pkg_riak_sysmon_name = riak_sysmon -pkg_riak_sysmon_description = Simple OTP app for managing Erlang VM system_monitor event messages -pkg_riak_sysmon_homepage = https://github.com/basho/riak_sysmon -pkg_riak_sysmon_fetch = git -pkg_riak_sysmon_repo = https://github.com/basho/riak_sysmon -pkg_riak_sysmon_commit = master - -PACKAGES += riak_test -pkg_riak_test_name = riak_test -pkg_riak_test_description = I'm in your cluster, testing your riaks -pkg_riak_test_homepage = https://github.com/basho/riak_test -pkg_riak_test_fetch = git -pkg_riak_test_repo = https://github.com/basho/riak_test -pkg_riak_test_commit = master - -PACKAGES += rivus_cep -pkg_rivus_cep_name = rivus_cep -pkg_rivus_cep_description = Complex event processing in Erlang -pkg_rivus_cep_homepage = https://github.com/vascokk/rivus_cep -pkg_rivus_cep_fetch = git -pkg_rivus_cep_repo = https://github.com/vascokk/rivus_cep -pkg_rivus_cep_commit = master - -PACKAGES += rlimit -pkg_rlimit_name = rlimit -pkg_rlimit_description = Magnus Klaar's rate limiter code from etorrent -pkg_rlimit_homepage = https://github.com/jlouis/rlimit -pkg_rlimit_fetch = git -pkg_rlimit_repo = https://github.com/jlouis/rlimit -pkg_rlimit_commit = master - -PACKAGES += safetyvalve -pkg_safetyvalve_name = safetyvalve -pkg_safetyvalve_description = A safety valve for your erlang node -pkg_safetyvalve_homepage = https://github.com/jlouis/safetyvalve -pkg_safetyvalve_fetch = git -pkg_safetyvalve_repo = https://github.com/jlouis/safetyvalve -pkg_safetyvalve_commit = master - -PACKAGES += seestar -pkg_seestar_name = seestar -pkg_seestar_description = The Erlang client for Cassandra 1.2+ binary protocol -pkg_seestar_homepage = https://github.com/iamaleksey/seestar -pkg_seestar_fetch = git -pkg_seestar_repo = https://github.com/iamaleksey/seestar -pkg_seestar_commit = master - -PACKAGES += service -pkg_service_name = service -pkg_service_description = A minimal Erlang behavior for creating CloudI internal services -pkg_service_homepage = http://cloudi.org/ -pkg_service_fetch = git -pkg_service_repo = https://github.com/CloudI/service -pkg_service_commit = master - -PACKAGES += setup -pkg_setup_name = setup -pkg_setup_description = Generic setup utility for Erlang-based systems -pkg_setup_homepage = https://github.com/uwiger/setup -pkg_setup_fetch = git -pkg_setup_repo = https://github.com/uwiger/setup -pkg_setup_commit = master - -PACKAGES += sext -pkg_sext_name = sext -pkg_sext_description = Sortable Erlang Term Serialization -pkg_sext_homepage = https://github.com/uwiger/sext -pkg_sext_fetch = git -pkg_sext_repo = https://github.com/uwiger/sext -pkg_sext_commit = master - -PACKAGES += sfmt -pkg_sfmt_name = sfmt -pkg_sfmt_description = SFMT pseudo random number generator for Erlang. -pkg_sfmt_homepage = https://github.com/jj1bdx/sfmt-erlang -pkg_sfmt_fetch = git -pkg_sfmt_repo = https://github.com/jj1bdx/sfmt-erlang -pkg_sfmt_commit = master - -PACKAGES += sgte -pkg_sgte_name = sgte -pkg_sgte_description = A simple Erlang Template Engine -pkg_sgte_homepage = https://github.com/filippo/sgte -pkg_sgte_fetch = git -pkg_sgte_repo = https://github.com/filippo/sgte -pkg_sgte_commit = master - -PACKAGES += sheriff -pkg_sheriff_name = sheriff -pkg_sheriff_description = Parse transform for type based validation. -pkg_sheriff_homepage = http://ninenines.eu -pkg_sheriff_fetch = git -pkg_sheriff_repo = https://github.com/extend/sheriff -pkg_sheriff_commit = master - -PACKAGES += shotgun -pkg_shotgun_name = shotgun -pkg_shotgun_description = better than just a gun -pkg_shotgun_homepage = https://github.com/inaka/shotgun -pkg_shotgun_fetch = git -pkg_shotgun_repo = https://github.com/inaka/shotgun -pkg_shotgun_commit = 0.1.0 - -PACKAGES += sidejob -pkg_sidejob_name = sidejob -pkg_sidejob_description = Parallel worker and capacity limiting library for Erlang -pkg_sidejob_homepage = https://github.com/basho/sidejob -pkg_sidejob_fetch = git -pkg_sidejob_repo = https://github.com/basho/sidejob -pkg_sidejob_commit = master - -PACKAGES += sieve -pkg_sieve_name = sieve -pkg_sieve_description = sieve is a simple TCP routing proxy (layer 7) in erlang -pkg_sieve_homepage = https://github.com/benoitc/sieve -pkg_sieve_fetch = git -pkg_sieve_repo = https://github.com/benoitc/sieve -pkg_sieve_commit = master - -PACKAGES += sighandler -pkg_sighandler_name = sighandler -pkg_sighandler_description = Handle UNIX signals in Er lang -pkg_sighandler_homepage = https://github.com/jkingsbery/sighandler -pkg_sighandler_fetch = git -pkg_sighandler_repo = https://github.com/jkingsbery/sighandler -pkg_sighandler_commit = master - -PACKAGES += simhash -pkg_simhash_name = simhash -pkg_simhash_description = Simhashing for Erlang -- hashing algorithm to find near-duplicates in binary data. -pkg_simhash_homepage = https://github.com/ferd/simhash -pkg_simhash_fetch = git -pkg_simhash_repo = https://github.com/ferd/simhash -pkg_simhash_commit = master - -PACKAGES += simple_bridge -pkg_simple_bridge_name = simple_bridge -pkg_simple_bridge_description = A simple, standardized interface library to Erlang HTTP Servers. -pkg_simple_bridge_homepage = https://github.com/nitrogen/simple_bridge -pkg_simple_bridge_fetch = git -pkg_simple_bridge_repo = https://github.com/nitrogen/simple_bridge -pkg_simple_bridge_commit = master - -PACKAGES += simple_oauth2 -pkg_simple_oauth2_name = simple_oauth2 -pkg_simple_oauth2_description = Simple erlang OAuth2 client module for any http server framework (Google, Facebook, Yandex, Vkontakte are preconfigured) -pkg_simple_oauth2_homepage = https://github.com/virtan/simple_oauth2 -pkg_simple_oauth2_fetch = git -pkg_simple_oauth2_repo = https://github.com/virtan/simple_oauth2 -pkg_simple_oauth2_commit = master - -PACKAGES += skel -pkg_skel_name = skel -pkg_skel_description = A Streaming Process-based Skeleton Library for Erlang -pkg_skel_homepage = https://github.com/ParaPhrase/skel -pkg_skel_fetch = git -pkg_skel_repo = https://github.com/ParaPhrase/skel -pkg_skel_commit = master - -PACKAGES += smother -pkg_smother_name = smother -pkg_smother_description = Extended code coverage metrics for Erlang. -pkg_smother_homepage = https://ramsay-t.github.io/Smother/ -pkg_smother_fetch = git -pkg_smother_repo = https://github.com/ramsay-t/Smother -pkg_smother_commit = master - -PACKAGES += social -pkg_social_name = social -pkg_social_description = Cowboy handler for social login via OAuth2 providers -pkg_social_homepage = https://github.com/dvv/social -pkg_social_fetch = git -pkg_social_repo = https://github.com/dvv/social -pkg_social_commit = master - -PACKAGES += spapi_router -pkg_spapi_router_name = spapi_router -pkg_spapi_router_description = Partially-connected Erlang clustering -pkg_spapi_router_homepage = https://github.com/spilgames/spapi-router -pkg_spapi_router_fetch = git -pkg_spapi_router_repo = https://github.com/spilgames/spapi-router -pkg_spapi_router_commit = master - -PACKAGES += sqerl -pkg_sqerl_name = sqerl -pkg_sqerl_description = An Erlang-flavoured SQL DSL -pkg_sqerl_homepage = https://github.com/hairyhum/sqerl -pkg_sqerl_fetch = git -pkg_sqerl_repo = https://github.com/hairyhum/sqerl -pkg_sqerl_commit = master - -PACKAGES += srly -pkg_srly_name = srly -pkg_srly_description = Native Erlang Unix serial interface -pkg_srly_homepage = https://github.com/msantos/srly -pkg_srly_fetch = git -pkg_srly_repo = https://github.com/msantos/srly -pkg_srly_commit = master - -PACKAGES += sshrpc -pkg_sshrpc_name = sshrpc -pkg_sshrpc_description = Erlang SSH RPC module (experimental) -pkg_sshrpc_homepage = https://github.com/jj1bdx/sshrpc -pkg_sshrpc_fetch = git -pkg_sshrpc_repo = https://github.com/jj1bdx/sshrpc -pkg_sshrpc_commit = master - -PACKAGES += stable -pkg_stable_name = stable -pkg_stable_description = Library of assorted helpers for Cowboy web server. -pkg_stable_homepage = https://github.com/dvv/stable -pkg_stable_fetch = git -pkg_stable_repo = https://github.com/dvv/stable -pkg_stable_commit = master - -PACKAGES += statebox -pkg_statebox_name = statebox -pkg_statebox_description = Erlang state monad with merge/conflict-resolution capabilities. Useful for Riak. -pkg_statebox_homepage = https://github.com/mochi/statebox -pkg_statebox_fetch = git -pkg_statebox_repo = https://github.com/mochi/statebox -pkg_statebox_commit = master - -PACKAGES += statebox_riak -pkg_statebox_riak_name = statebox_riak -pkg_statebox_riak_description = Convenience library that makes it easier to use statebox with riak, extracted from best practices in our production code at Mochi Media. -pkg_statebox_riak_homepage = https://github.com/mochi/statebox_riak -pkg_statebox_riak_fetch = git -pkg_statebox_riak_repo = https://github.com/mochi/statebox_riak -pkg_statebox_riak_commit = master - -PACKAGES += statman -pkg_statman_name = statman -pkg_statman_description = Efficiently collect massive volumes of metrics inside the Erlang VM -pkg_statman_homepage = https://github.com/knutin/statman -pkg_statman_fetch = git -pkg_statman_repo = https://github.com/knutin/statman -pkg_statman_commit = master - -PACKAGES += statsderl -pkg_statsderl_name = statsderl -pkg_statsderl_description = StatsD client (erlang) -pkg_statsderl_homepage = https://github.com/lpgauth/statsderl -pkg_statsderl_fetch = git -pkg_statsderl_repo = https://github.com/lpgauth/statsderl -pkg_statsderl_commit = master - -PACKAGES += stdinout_pool -pkg_stdinout_pool_name = stdinout_pool -pkg_stdinout_pool_description = stdinout_pool : stuff goes in, stuff goes out. there's never any miscommunication. -pkg_stdinout_pool_homepage = https://github.com/mattsta/erlang-stdinout-pool -pkg_stdinout_pool_fetch = git -pkg_stdinout_pool_repo = https://github.com/mattsta/erlang-stdinout-pool -pkg_stdinout_pool_commit = master - -PACKAGES += stockdb -pkg_stockdb_name = stockdb -pkg_stockdb_description = Database for storing Stock Exchange quotes in erlang -pkg_stockdb_homepage = https://github.com/maxlapshin/stockdb -pkg_stockdb_fetch = git -pkg_stockdb_repo = https://github.com/maxlapshin/stockdb -pkg_stockdb_commit = master - -PACKAGES += stripe -pkg_stripe_name = stripe -pkg_stripe_description = Erlang interface to the stripe.com API -pkg_stripe_homepage = https://github.com/mattsta/stripe-erlang -pkg_stripe_fetch = git -pkg_stripe_repo = https://github.com/mattsta/stripe-erlang -pkg_stripe_commit = v1 - -PACKAGES += surrogate -pkg_surrogate_name = surrogate -pkg_surrogate_description = Proxy server written in erlang. Supports reverse proxy load balancing and forward proxy with http (including CONNECT), socks4, socks5, and transparent proxy modes. -pkg_surrogate_homepage = https://github.com/skruger/Surrogate -pkg_surrogate_fetch = git -pkg_surrogate_repo = https://github.com/skruger/Surrogate -pkg_surrogate_commit = master - -PACKAGES += swab -pkg_swab_name = swab -pkg_swab_description = General purpose buffer handling module -pkg_swab_homepage = https://github.com/crownedgrouse/swab -pkg_swab_fetch = git -pkg_swab_repo = https://github.com/crownedgrouse/swab -pkg_swab_commit = master - -PACKAGES += swarm -pkg_swarm_name = swarm -pkg_swarm_description = Fast and simple acceptor pool for Erlang -pkg_swarm_homepage = https://github.com/jeremey/swarm -pkg_swarm_fetch = git -pkg_swarm_repo = https://github.com/jeremey/swarm -pkg_swarm_commit = master - -PACKAGES += switchboard -pkg_switchboard_name = switchboard -pkg_switchboard_description = A framework for processing email using worker plugins. -pkg_switchboard_homepage = https://github.com/thusfresh/switchboard -pkg_switchboard_fetch = git -pkg_switchboard_repo = https://github.com/thusfresh/switchboard -pkg_switchboard_commit = master - -PACKAGES += sync -pkg_sync_name = sync -pkg_sync_description = On-the-fly recompiling and reloading in Erlang. -pkg_sync_homepage = https://github.com/rustyio/sync -pkg_sync_fetch = git -pkg_sync_repo = https://github.com/rustyio/sync -pkg_sync_commit = master - -PACKAGES += syn -pkg_syn_name = syn -pkg_syn_description = A global process registry for Erlang. -pkg_syn_homepage = https://github.com/ostinelli/syn -pkg_syn_fetch = git -pkg_syn_repo = https://github.com/ostinelli/syn -pkg_syn_commit = master - -PACKAGES += syntaxerl -pkg_syntaxerl_name = syntaxerl -pkg_syntaxerl_description = Syntax checker for Erlang -pkg_syntaxerl_homepage = https://github.com/ten0s/syntaxerl -pkg_syntaxerl_fetch = git -pkg_syntaxerl_repo = https://github.com/ten0s/syntaxerl -pkg_syntaxerl_commit = master - -PACKAGES += syslog -pkg_syslog_name = syslog -pkg_syslog_description = Erlang port driver for interacting with syslog via syslog(3) -pkg_syslog_homepage = https://github.com/Vagabond/erlang-syslog -pkg_syslog_fetch = git -pkg_syslog_repo = https://github.com/Vagabond/erlang-syslog -pkg_syslog_commit = master - -PACKAGES += taskforce -pkg_taskforce_name = taskforce -pkg_taskforce_description = Erlang worker pools for controlled parallelisation of arbitrary tasks. -pkg_taskforce_homepage = https://github.com/g-andrade/taskforce -pkg_taskforce_fetch = git -pkg_taskforce_repo = https://github.com/g-andrade/taskforce -pkg_taskforce_commit = master - -PACKAGES += tddreloader -pkg_tddreloader_name = tddreloader -pkg_tddreloader_description = Shell utility for recompiling, reloading, and testing code as it changes -pkg_tddreloader_homepage = https://github.com/version2beta/tddreloader -pkg_tddreloader_fetch = git -pkg_tddreloader_repo = https://github.com/version2beta/tddreloader -pkg_tddreloader_commit = master - -PACKAGES += tempo -pkg_tempo_name = tempo -pkg_tempo_description = NIF-based date and time parsing and formatting for Erlang. -pkg_tempo_homepage = https://github.com/selectel/tempo -pkg_tempo_fetch = git -pkg_tempo_repo = https://github.com/selectel/tempo -pkg_tempo_commit = master - -PACKAGES += ticktick -pkg_ticktick_name = ticktick -pkg_ticktick_description = Ticktick is an id generator for message service. -pkg_ticktick_homepage = https://github.com/ericliang/ticktick -pkg_ticktick_fetch = git -pkg_ticktick_repo = https://github.com/ericliang/ticktick -pkg_ticktick_commit = master - -PACKAGES += tinymq -pkg_tinymq_name = tinymq -pkg_tinymq_description = TinyMQ - a diminutive, in-memory message queue -pkg_tinymq_homepage = https://github.com/ChicagoBoss/tinymq -pkg_tinymq_fetch = git -pkg_tinymq_repo = https://github.com/ChicagoBoss/tinymq -pkg_tinymq_commit = master - -PACKAGES += tinymt -pkg_tinymt_name = tinymt -pkg_tinymt_description = TinyMT pseudo random number generator for Erlang. -pkg_tinymt_homepage = https://github.com/jj1bdx/tinymt-erlang -pkg_tinymt_fetch = git -pkg_tinymt_repo = https://github.com/jj1bdx/tinymt-erlang -pkg_tinymt_commit = master - -PACKAGES += tirerl -pkg_tirerl_name = tirerl -pkg_tirerl_description = Erlang interface to Elastic Search -pkg_tirerl_homepage = https://github.com/inaka/tirerl -pkg_tirerl_fetch = git -pkg_tirerl_repo = https://github.com/inaka/tirerl -pkg_tirerl_commit = master - -PACKAGES += traffic_tools -pkg_traffic_tools_name = traffic_tools -pkg_traffic_tools_description = Simple traffic limiting library -pkg_traffic_tools_homepage = https://github.com/systra/traffic_tools -pkg_traffic_tools_fetch = git -pkg_traffic_tools_repo = https://github.com/systra/traffic_tools -pkg_traffic_tools_commit = master - -PACKAGES += trails -pkg_trails_name = trails -pkg_trails_description = A couple of improvements over Cowboy Routes -pkg_trails_homepage = http://inaka.github.io/cowboy-trails/ -pkg_trails_fetch = git -pkg_trails_repo = https://github.com/inaka/cowboy-trails -pkg_trails_commit = master - -PACKAGES += trane -pkg_trane_name = trane -pkg_trane_description = SAX style broken HTML parser in Erlang -pkg_trane_homepage = https://github.com/massemanet/trane -pkg_trane_fetch = git -pkg_trane_repo = https://github.com/massemanet/trane -pkg_trane_commit = master - -PACKAGES += transit -pkg_transit_name = transit -pkg_transit_description = transit format for erlang -pkg_transit_homepage = https://github.com/isaiah/transit-erlang -pkg_transit_fetch = git -pkg_transit_repo = https://github.com/isaiah/transit-erlang -pkg_transit_commit = master - -PACKAGES += trie -pkg_trie_name = trie -pkg_trie_description = Erlang Trie Implementation -pkg_trie_homepage = https://github.com/okeuday/trie -pkg_trie_fetch = git -pkg_trie_repo = https://github.com/okeuday/trie -pkg_trie_commit = master - -PACKAGES += triq -pkg_triq_name = triq -pkg_triq_description = Trifork QuickCheck -pkg_triq_homepage = https://github.com/krestenkrab/triq -pkg_triq_fetch = git -pkg_triq_repo = https://github.com/krestenkrab/triq -pkg_triq_commit = master - -PACKAGES += tunctl -pkg_tunctl_name = tunctl -pkg_tunctl_description = Erlang TUN/TAP interface -pkg_tunctl_homepage = https://github.com/msantos/tunctl -pkg_tunctl_fetch = git -pkg_tunctl_repo = https://github.com/msantos/tunctl -pkg_tunctl_commit = master - -PACKAGES += twerl -pkg_twerl_name = twerl -pkg_twerl_description = Erlang client for the Twitter Streaming API -pkg_twerl_homepage = https://github.com/lucaspiller/twerl -pkg_twerl_fetch = git -pkg_twerl_repo = https://github.com/lucaspiller/twerl -pkg_twerl_commit = oauth - -PACKAGES += twitter_erlang -pkg_twitter_erlang_name = twitter_erlang -pkg_twitter_erlang_description = An Erlang twitter client -pkg_twitter_erlang_homepage = https://github.com/ngerakines/erlang_twitter -pkg_twitter_erlang_fetch = git -pkg_twitter_erlang_repo = https://github.com/ngerakines/erlang_twitter -pkg_twitter_erlang_commit = master - -PACKAGES += ucol_nif -pkg_ucol_nif_name = ucol_nif -pkg_ucol_nif_description = ICU based collation Erlang module -pkg_ucol_nif_homepage = https://github.com/refuge/ucol_nif -pkg_ucol_nif_fetch = git -pkg_ucol_nif_repo = https://github.com/refuge/ucol_nif -pkg_ucol_nif_commit = master - -PACKAGES += unicorn -pkg_unicorn_name = unicorn -pkg_unicorn_description = Generic configuration server -pkg_unicorn_homepage = https://github.com/shizzard/unicorn -pkg_unicorn_fetch = git -pkg_unicorn_repo = https://github.com/shizzard/unicorn -pkg_unicorn_commit = 0.3.0 - -PACKAGES += unsplit -pkg_unsplit_name = unsplit -pkg_unsplit_description = Resolves conflicts in Mnesia after network splits -pkg_unsplit_homepage = https://github.com/uwiger/unsplit -pkg_unsplit_fetch = git -pkg_unsplit_repo = https://github.com/uwiger/unsplit -pkg_unsplit_commit = master - -PACKAGES += uuid -pkg_uuid_name = uuid -pkg_uuid_description = Erlang UUID Implementation -pkg_uuid_homepage = https://github.com/okeuday/uuid -pkg_uuid_fetch = git -pkg_uuid_repo = https://github.com/okeuday/uuid -pkg_uuid_commit = v1.4.0 - -PACKAGES += ux -pkg_ux_name = ux -pkg_ux_description = Unicode eXtention for Erlang (Strings, Collation) -pkg_ux_homepage = https://github.com/erlang-unicode/ux -pkg_ux_fetch = git -pkg_ux_repo = https://github.com/erlang-unicode/ux -pkg_ux_commit = master - -PACKAGES += vert -pkg_vert_name = vert -pkg_vert_description = Erlang binding to libvirt virtualization API -pkg_vert_homepage = https://github.com/msantos/erlang-libvirt -pkg_vert_fetch = git -pkg_vert_repo = https://github.com/msantos/erlang-libvirt -pkg_vert_commit = master - -PACKAGES += verx -pkg_verx_name = verx -pkg_verx_description = Erlang implementation of the libvirtd remote protocol -pkg_verx_homepage = https://github.com/msantos/verx -pkg_verx_fetch = git -pkg_verx_repo = https://github.com/msantos/verx -pkg_verx_commit = master - -PACKAGES += vmq_acl -pkg_vmq_acl_name = vmq_acl -pkg_vmq_acl_description = Component of VerneMQ: A distributed MQTT message broker -pkg_vmq_acl_homepage = https://verne.mq/ -pkg_vmq_acl_fetch = git -pkg_vmq_acl_repo = https://github.com/erlio/vmq_acl -pkg_vmq_acl_commit = master - -PACKAGES += vmq_bridge -pkg_vmq_bridge_name = vmq_bridge -pkg_vmq_bridge_description = Component of VerneMQ: A distributed MQTT message broker -pkg_vmq_bridge_homepage = https://verne.mq/ -pkg_vmq_bridge_fetch = git -pkg_vmq_bridge_repo = https://github.com/erlio/vmq_bridge -pkg_vmq_bridge_commit = master - -PACKAGES += vmq_graphite -pkg_vmq_graphite_name = vmq_graphite -pkg_vmq_graphite_description = Component of VerneMQ: A distributed MQTT message broker -pkg_vmq_graphite_homepage = https://verne.mq/ -pkg_vmq_graphite_fetch = git -pkg_vmq_graphite_repo = https://github.com/erlio/vmq_graphite -pkg_vmq_graphite_commit = master - -PACKAGES += vmq_passwd -pkg_vmq_passwd_name = vmq_passwd -pkg_vmq_passwd_description = Component of VerneMQ: A distributed MQTT message broker -pkg_vmq_passwd_homepage = https://verne.mq/ -pkg_vmq_passwd_fetch = git -pkg_vmq_passwd_repo = https://github.com/erlio/vmq_passwd -pkg_vmq_passwd_commit = master - -PACKAGES += vmq_server -pkg_vmq_server_name = vmq_server -pkg_vmq_server_description = Component of VerneMQ: A distributed MQTT message broker -pkg_vmq_server_homepage = https://verne.mq/ -pkg_vmq_server_fetch = git -pkg_vmq_server_repo = https://github.com/erlio/vmq_server -pkg_vmq_server_commit = master - -PACKAGES += vmq_snmp -pkg_vmq_snmp_name = vmq_snmp -pkg_vmq_snmp_description = Component of VerneMQ: A distributed MQTT message broker -pkg_vmq_snmp_homepage = https://verne.mq/ -pkg_vmq_snmp_fetch = git -pkg_vmq_snmp_repo = https://github.com/erlio/vmq_snmp -pkg_vmq_snmp_commit = master - -PACKAGES += vmq_systree -pkg_vmq_systree_name = vmq_systree -pkg_vmq_systree_description = Component of VerneMQ: A distributed MQTT message broker -pkg_vmq_systree_homepage = https://verne.mq/ -pkg_vmq_systree_fetch = git -pkg_vmq_systree_repo = https://github.com/erlio/vmq_systree -pkg_vmq_systree_commit = master - -PACKAGES += vmstats -pkg_vmstats_name = vmstats -pkg_vmstats_description = tiny Erlang app that works in conjunction with statsderl in order to generate information on the Erlang VM for graphite logs. -pkg_vmstats_homepage = https://github.com/ferd/vmstats -pkg_vmstats_fetch = git -pkg_vmstats_repo = https://github.com/ferd/vmstats -pkg_vmstats_commit = master - -PACKAGES += walrus -pkg_walrus_name = walrus -pkg_walrus_description = Walrus - Mustache-like Templating -pkg_walrus_homepage = https://github.com/devinus/walrus -pkg_walrus_fetch = git -pkg_walrus_repo = https://github.com/devinus/walrus -pkg_walrus_commit = master - -PACKAGES += webmachine -pkg_webmachine_name = webmachine -pkg_webmachine_description = A REST-based system for building web applications. -pkg_webmachine_homepage = https://github.com/basho/webmachine -pkg_webmachine_fetch = git -pkg_webmachine_repo = https://github.com/basho/webmachine -pkg_webmachine_commit = master - -PACKAGES += websocket_client -pkg_websocket_client_name = websocket_client -pkg_websocket_client_description = Erlang websocket client (ws and wss supported) -pkg_websocket_client_homepage = https://github.com/jeremyong/websocket_client -pkg_websocket_client_fetch = git -pkg_websocket_client_repo = https://github.com/jeremyong/websocket_client -pkg_websocket_client_commit = master - -PACKAGES += worker_pool -pkg_worker_pool_name = worker_pool -pkg_worker_pool_description = a simple erlang worker pool -pkg_worker_pool_homepage = https://github.com/inaka/worker_pool -pkg_worker_pool_fetch = git -pkg_worker_pool_repo = https://github.com/inaka/worker_pool -pkg_worker_pool_commit = 1.0.2 - -PACKAGES += wrangler -pkg_wrangler_name = wrangler -pkg_wrangler_description = Import of the Wrangler svn repository. -pkg_wrangler_homepage = http://www.cs.kent.ac.uk/projects/wrangler/Home.html -pkg_wrangler_fetch = git -pkg_wrangler_repo = https://github.com/RefactoringTools/wrangler -pkg_wrangler_commit = master - -PACKAGES += wsock -pkg_wsock_name = wsock -pkg_wsock_description = Erlang library to build WebSocket clients and servers -pkg_wsock_homepage = https://github.com/madtrick/wsock -pkg_wsock_fetch = git -pkg_wsock_repo = https://github.com/madtrick/wsock -pkg_wsock_commit = master - -PACKAGES += xhttpc -pkg_xhttpc_name = xhttpc -pkg_xhttpc_description = Extensible HTTP Client for Erlang -pkg_xhttpc_homepage = https://github.com/seriyps/xhttpc -pkg_xhttpc_fetch = git -pkg_xhttpc_repo = https://github.com/seriyps/xhttpc -pkg_xhttpc_commit = master - -PACKAGES += xref_runner -pkg_xref_runner_name = xref_runner -pkg_xref_runner_description = Erlang Xref Runner (inspired in rebar xref) -pkg_xref_runner_homepage = https://github.com/inaka/xref_runner -pkg_xref_runner_fetch = git -pkg_xref_runner_repo = https://github.com/inaka/xref_runner -pkg_xref_runner_commit = 0.2.0 - -PACKAGES += yamerl -pkg_yamerl_name = yamerl -pkg_yamerl_description = YAML 1.2 parser in pure Erlang -pkg_yamerl_homepage = https://github.com/yakaz/yamerl -pkg_yamerl_fetch = git -pkg_yamerl_repo = https://github.com/yakaz/yamerl -pkg_yamerl_commit = master - -PACKAGES += yamler -pkg_yamler_name = yamler -pkg_yamler_description = libyaml-based yaml loader for Erlang -pkg_yamler_homepage = https://github.com/goertzenator/yamler -pkg_yamler_fetch = git -pkg_yamler_repo = https://github.com/goertzenator/yamler -pkg_yamler_commit = master - -PACKAGES += yaws -pkg_yaws_name = yaws -pkg_yaws_description = Yaws webserver -pkg_yaws_homepage = http://yaws.hyber.org -pkg_yaws_fetch = git -pkg_yaws_repo = https://github.com/klacke/yaws -pkg_yaws_commit = master - -PACKAGES += zab_engine -pkg_zab_engine_name = zab_engine -pkg_zab_engine_description = zab propotocol implement by erlang -pkg_zab_engine_homepage = https://github.com/xinmingyao/zab_engine -pkg_zab_engine_fetch = git -pkg_zab_engine_repo = https://github.com/xinmingyao/zab_engine -pkg_zab_engine_commit = master - -PACKAGES += zeta -pkg_zeta_name = zeta -pkg_zeta_description = HTTP access log parser in Erlang -pkg_zeta_homepage = https://github.com/s1n4/zeta -pkg_zeta_fetch = git -pkg_zeta_repo = https://github.com/s1n4/zeta -pkg_zeta_commit = - -PACKAGES += zippers -pkg_zippers_name = zippers -pkg_zippers_description = A library for functional zipper data structures in Erlang. Read more on zippers -pkg_zippers_homepage = https://github.com/ferd/zippers -pkg_zippers_fetch = git -pkg_zippers_repo = https://github.com/ferd/zippers -pkg_zippers_commit = master - -PACKAGES += zlists -pkg_zlists_name = zlists -pkg_zlists_description = Erlang lazy lists library. -pkg_zlists_homepage = https://github.com/vjache/erlang-zlists -pkg_zlists_fetch = git -pkg_zlists_repo = https://github.com/vjache/erlang-zlists -pkg_zlists_commit = master - -PACKAGES += zraft_lib -pkg_zraft_lib_name = zraft_lib -pkg_zraft_lib_description = Erlang raft consensus protocol implementation -pkg_zraft_lib_homepage = https://github.com/dreyk/zraft_lib -pkg_zraft_lib_fetch = git -pkg_zraft_lib_repo = https://github.com/dreyk/zraft_lib -pkg_zraft_lib_commit = master - -PACKAGES += zucchini -pkg_zucchini_name = zucchini -pkg_zucchini_description = An Erlang INI parser -pkg_zucchini_homepage = https://github.com/devinus/zucchini -pkg_zucchini_fetch = git -pkg_zucchini_repo = https://github.com/devinus/zucchini -pkg_zucchini_commit = master - -# Copyright (c) 2015, Loïc Hoguin -# This file is part of erlang.mk and subject to the terms of the ISC License. - -.PHONY: search - -define pkg_print - $(verbose) printf "%s\n" \ - $(if $(call core_eq,$(1),$(pkg_$(1)_name)),,"Pkg name: $(1)") \ - "App name: $(pkg_$(1)_name)" \ - "Description: $(pkg_$(1)_description)" \ - "Home page: $(pkg_$(1)_homepage)" \ - "Fetch with: $(pkg_$(1)_fetch)" \ - "Repository: $(pkg_$(1)_repo)" \ - "Commit: $(pkg_$(1)_commit)" \ - "" - -endef - -search: -ifdef q - $(foreach p,$(PACKAGES), \ - $(if $(findstring $(call core_lc,$(q)),$(call core_lc,$(pkg_$(p)_name) $(pkg_$(p)_description))), \ - $(call pkg_print,$(p)))) -else - $(foreach p,$(PACKAGES),$(call pkg_print,$(p))) -endif - -# Copyright (c) 2013-2015, Loïc Hoguin -# This file is part of erlang.mk and subject to the terms of the ISC License. - -.PHONY: distclean-deps distclean-pkg - -# Configuration. - -IGNORE_DEPS ?= - -DEPS_DIR ?= $(CURDIR)/deps -export DEPS_DIR - -REBAR_DEPS_DIR = $(DEPS_DIR) -export REBAR_DEPS_DIR - -ALL_DEPS_DIRS = $(addprefix $(DEPS_DIR)/,$(filter-out $(IGNORE_DEPS),$(DEPS))) - -ifeq ($(filter $(DEPS_DIR),$(subst :, ,$(ERL_LIBS))),) -ifeq ($(ERL_LIBS),) - ERL_LIBS = $(DEPS_DIR) -else - ERL_LIBS := $(ERL_LIBS):$(DEPS_DIR) -endif -endif -export ERL_LIBS - -# Verbosity. - -dep_verbose_0 = @echo " DEP " $(1); -dep_verbose = $(dep_verbose_$(V)) - -# Core targets. - -ifneq ($(SKIP_DEPS),) -deps:: -else -deps:: $(ALL_DEPS_DIRS) -ifneq ($(IS_DEP),1) - $(verbose) rm -f $(ERLANG_MK_TMP)/deps.log -endif - $(verbose) mkdir -p $(ERLANG_MK_TMP) - $(verbose) for dep in $(ALL_DEPS_DIRS) ; do \ - if grep -qs ^$$dep$$ $(ERLANG_MK_TMP)/deps.log; then \ - echo -n; \ - else \ - echo $$dep >> $(ERLANG_MK_TMP)/deps.log; \ - if [ -f $$dep/GNUmakefile ] || [ -f $$dep/makefile ] || [ -f $$dep/Makefile ]; then \ - $(MAKE) -C $$dep IS_DEP=1 || exit $$?; \ - else \ - echo "ERROR: No Makefile to build dependency $$dep."; \ - exit 1; \ - fi \ - fi \ - done -endif - -distclean:: distclean-deps distclean-pkg - -# Deps related targets. - -# @todo rename GNUmakefile and makefile into Makefile first, if they exist -# While Makefile file could be GNUmakefile or makefile, -# in practice only Makefile is needed so far. -define dep_autopatch - if [ -f $(DEPS_DIR)/$(1)/Makefile ]; then \ - if [ 0 != `grep -c "include ../\w*\.mk" $(DEPS_DIR)/$(1)/Makefile` ]; then \ - $(call dep_autopatch2,$(1)); \ - elif [ 0 != `grep -ci rebar $(DEPS_DIR)/$(1)/Makefile` ]; then \ - $(call dep_autopatch2,$(1)); \ - elif [ -n "`find $(DEPS_DIR)/$(1)/ -type f -name \*.mk -not -name erlang.mk | xargs -r grep -i rebar`" ]; then \ - $(call dep_autopatch2,$(1)); \ - else \ - if [ -f $(DEPS_DIR)/$(1)/erlang.mk ]; then \ - $(call erlang,$(call dep_autopatch_appsrc.erl,$(1))); \ - $(call dep_autopatch_erlang_mk,$(1)); \ - else \ - $(call erlang,$(call dep_autopatch_app.erl,$(1))); \ - fi \ - fi \ - else \ - if [ ! -d $(DEPS_DIR)/$(1)/src/ ]; then \ - $(call dep_autopatch_noop,$(1)); \ - else \ - $(call dep_autopatch2,$(1)); \ - fi \ - fi -endef - -define dep_autopatch2 - $(call erlang,$(call dep_autopatch_appsrc.erl,$(1))); \ - if [ -f $(DEPS_DIR)/$(1)/rebar.config -o -f $(DEPS_DIR)/$(1)/rebar.config.script ]; then \ - $(call dep_autopatch_fetch_rebar); \ - $(call dep_autopatch_rebar,$(1)); \ - else \ - $(call dep_autopatch_gen,$(1)); \ - fi -endef - -define dep_autopatch_noop - printf "noop:\n" > $(DEPS_DIR)/$(1)/Makefile -endef - -# Overwrite erlang.mk with the current file by default. -ifeq ($(NO_AUTOPATCH_ERLANG_MK),) -define dep_autopatch_erlang_mk - echo "include $(ERLANG_MK_FILENAME)" > $(DEPS_DIR)/$(1)/erlang.mk -endef -else -define dep_autopatch_erlang_mk - echo -n -endef -endif - -define dep_autopatch_gen - printf "%s\n" \ - "ERLC_OPTS = +debug_info" \ - "include ../../erlang.mk" > $(DEPS_DIR)/$(1)/Makefile -endef - -define dep_autopatch_fetch_rebar - mkdir -p $(ERLANG_MK_TMP); \ - if [ ! -d $(ERLANG_MK_TMP)/rebar ]; then \ - git clone -q -n -- https://github.com/rebar/rebar $(ERLANG_MK_TMP)/rebar; \ - cd $(ERLANG_MK_TMP)/rebar; \ - git checkout -q 791db716b5a3a7671e0b351f95ddf24b848ee173; \ - $(MAKE); \ - cd -; \ - fi -endef - -define dep_autopatch_rebar - if [ -f $(DEPS_DIR)/$(1)/Makefile ]; then \ - mv $(DEPS_DIR)/$(1)/Makefile $(DEPS_DIR)/$(1)/Makefile.orig.mk; \ - fi; \ - $(call erlang,$(call dep_autopatch_rebar.erl,$(1))); \ - rm -f $(DEPS_DIR)/$(1)/ebin/$(1).app -endef - -define dep_autopatch_rebar.erl - application:set_env(rebar, log_level, debug), - Conf1 = case file:consult("$(DEPS_DIR)/$(1)/rebar.config") of - {ok, Conf0} -> Conf0; - _ -> [] - end, - {Conf, OsEnv} = fun() -> - case filelib:is_file("$(DEPS_DIR)/$(1)/rebar.config.script") of - false -> {Conf1, []}; - true -> - Bindings0 = erl_eval:new_bindings(), - Bindings1 = erl_eval:add_binding('CONFIG', Conf1, Bindings0), - Bindings = erl_eval:add_binding('SCRIPT', "$(DEPS_DIR)/$(1)/rebar.config.script", Bindings1), - Before = os:getenv(), - {ok, Conf2} = file:script("$(DEPS_DIR)/$(1)/rebar.config.script", Bindings), - {Conf2, lists:foldl(fun(E, Acc) -> lists:delete(E, Acc) end, os:getenv(), Before)} - end - end(), - Write = fun (Text) -> - file:write_file("$(DEPS_DIR)/$(1)/Makefile", Text, [append]) - end, - Escape = fun (Text) -> - re:replace(Text, "\\\\$$$$", "\$$$$$$$$", [global, {return, list}]) - end, - Write("IGNORE_DEPS = edown eper eunit_formatters meck node_package " - "rebar_lock_deps_plugin rebar_vsn_plugin reltool_util\n"), - Write("C_SRC_DIR = /path/do/not/exist\n"), - Write("DRV_CFLAGS = -fPIC\nexport DRV_CFLAGS\n"), - Write(["ERLANG_ARCH = ", rebar_utils:wordsize(), "\nexport ERLANG_ARCH\n"]), - fun() -> - Write("ERLC_OPTS = +debug_info\nexport ERLC_OPTS\n"), - case lists:keyfind(erl_opts, 1, Conf) of - false -> ok; - {_, ErlOpts} -> - lists:foreach(fun - ({d, D}) -> - Write("ERLC_OPTS += -D" ++ atom_to_list(D) ++ "=1\n"); - ({i, I}) -> - Write(["ERLC_OPTS += -I ", I, "\n"]); - ({platform_define, Regex, D}) -> - case rebar_utils:is_arch(Regex) of - true -> Write("ERLC_OPTS += -D" ++ atom_to_list(D) ++ "=1\n"); - false -> ok - end; - ({parse_transform, PT}) -> - Write("ERLC_OPTS += +'{parse_transform, " ++ atom_to_list(PT) ++ "}'\n"); - (_) -> ok - end, ErlOpts) - end, - Write("\n") - end(), - fun() -> - File = case lists:keyfind(deps, 1, Conf) of - false -> []; - {_, Deps} -> - [begin case case Dep of - {N, S} when is_atom(N), is_list(S) -> {N, {hex, S}}; - {N, S} when is_tuple(S) -> {N, S}; - {N, _, S} -> {N, S}; - {N, _, S, _} -> {N, S}; - _ -> false - end of - false -> ok; - {Name, Source} -> - {Method, Repo, Commit} = case Source of - {hex, V} -> {hex, undefined, V}; - {git, R} -> {git, R, master}; - {M, R, {branch, C}} -> {M, R, C}; - {M, R, {ref, C}} -> {M, R, C}; - {M, R, {tag, C}} -> {M, R, C}; - {M, R, C} -> {M, R, C} - end, - Write(io_lib:format("DEPS += ~s\ndep_~s = ~s ~s ~s~n", [Name, Name, Method, Repo, Commit])) - end end || Dep <- Deps] - end - end(), - fun() -> - case lists:keyfind(erl_first_files, 1, Conf) of - false -> ok; - {_, Files} -> - Names = [[" ", case lists:reverse(F) of - "lre." ++ Elif -> lists:reverse(Elif); - Elif -> lists:reverse(Elif) - end] || "src/" ++ F <- Files], - Write(io_lib:format("COMPILE_FIRST +=~s\n", [Names])) - end - end(), - FindFirst = fun(F, Fd) -> - case io:parse_erl_form(Fd, undefined) of - {ok, {attribute, _, compile, {parse_transform, PT}}, _} -> - [PT, F(F, Fd)]; - {ok, {attribute, _, compile, CompileOpts}, _} when is_list(CompileOpts) -> - case proplists:get_value(parse_transform, CompileOpts) of - undefined -> [F(F, Fd)]; - PT -> [PT, F(F, Fd)] - end; - {ok, {attribute, _, include, Hrl}, _} -> - case file:open("$(DEPS_DIR)/$(1)/include/" ++ Hrl, [read]) of - {ok, HrlFd} -> [F(F, HrlFd), F(F, Fd)]; - _ -> - case file:open("$(DEPS_DIR)/$(1)/src/" ++ Hrl, [read]) of - {ok, HrlFd} -> [F(F, HrlFd), F(F, Fd)]; - _ -> [F(F, Fd)] - end - end; - {ok, {attribute, _, include_lib, "$(1)/include/" ++ Hrl}, _} -> - {ok, HrlFd} = file:open("$(DEPS_DIR)/$(1)/include/" ++ Hrl, [read]), - [F(F, HrlFd), F(F, Fd)]; - {ok, {attribute, _, include_lib, Hrl}, _} -> - case file:open("$(DEPS_DIR)/$(1)/include/" ++ Hrl, [read]) of - {ok, HrlFd} -> [F(F, HrlFd), F(F, Fd)]; - _ -> [F(F, Fd)] - end; - {ok, {attribute, _, import, {Imp, _}}, _} -> - case file:open("$(DEPS_DIR)/$(1)/src/" ++ atom_to_list(Imp) ++ ".erl", [read]) of - {ok, ImpFd} -> [Imp, F(F, ImpFd), F(F, Fd)]; - _ -> [F(F, Fd)] - end; - {eof, _} -> - file:close(Fd), - []; - _ -> - F(F, Fd) - end - end, - fun() -> - ErlFiles = filelib:wildcard("$(DEPS_DIR)/$(1)/src/*.erl"), - First0 = lists:usort(lists:flatten([begin - {ok, Fd} = file:open(F, [read]), - FindFirst(FindFirst, Fd) - end || F <- ErlFiles])), - First = lists:flatten([begin - {ok, Fd} = file:open("$(DEPS_DIR)/$(1)/src/" ++ atom_to_list(M) ++ ".erl", [read]), - FindFirst(FindFirst, Fd) - end || M <- First0, lists:member("$(DEPS_DIR)/$(1)/src/" ++ atom_to_list(M) ++ ".erl", ErlFiles)]) ++ First0, - Write(["COMPILE_FIRST +=", [[" ", atom_to_list(M)] || M <- First, - lists:member("$(DEPS_DIR)/$(1)/src/" ++ atom_to_list(M) ++ ".erl", ErlFiles)], "\n"]) - end(), - Write("\n\nrebar_dep: preprocess pre-deps deps pre-app app\n"), - Write("\npreprocess::\n"), - Write("\npre-deps::\n"), - Write("\npre-app::\n"), - PatchHook = fun(Cmd) -> - case Cmd of - "make -C" ++ Cmd1 -> "$$$$\(MAKE) -C" ++ Escape(Cmd1); - "gmake -C" ++ Cmd1 -> "$$$$\(MAKE) -C" ++ Escape(Cmd1); - "make " ++ Cmd1 -> "$$$$\(MAKE) -f Makefile.orig.mk " ++ Escape(Cmd1); - "gmake " ++ Cmd1 -> "$$$$\(MAKE) -f Makefile.orig.mk " ++ Escape(Cmd1); - _ -> Escape(Cmd) - end - end, - fun() -> - case lists:keyfind(pre_hooks, 1, Conf) of - false -> ok; - {_, Hooks} -> - [case H of - {'get-deps', Cmd} -> - Write("\npre-deps::\n\t" ++ PatchHook(Cmd) ++ "\n"); - {compile, Cmd} -> - Write("\npre-app::\n\tCC=$$$$\(CC) " ++ PatchHook(Cmd) ++ "\n"); - {Regex, compile, Cmd} -> - case rebar_utils:is_arch(Regex) of - true -> Write("\npre-app::\n\tCC=$$$$\(CC) " ++ PatchHook(Cmd) ++ "\n"); - false -> ok - end; - _ -> ok - end || H <- Hooks] - end - end(), - ShellToMk = fun(V) -> - re:replace(re:replace(V, "(\\\\$$$$)(\\\\w*)", "\\\\1(\\\\2)", [global]), - "-Werror\\\\b", "", [{return, list}, global]) - end, - PortSpecs = fun() -> - case lists:keyfind(port_specs, 1, Conf) of - false -> - case filelib:is_dir("$(DEPS_DIR)/$(1)/c_src") of - false -> []; - true -> - [{"priv/" ++ proplists:get_value(so_name, Conf, "$(1)_drv.so"), - proplists:get_value(port_sources, Conf, ["c_src/*.c"]), []}] - end; - {_, Specs} -> - lists:flatten([case S of - {Output, Input} -> {ShellToMk(Output), Input, []}; - {Regex, Output, Input} -> - case rebar_utils:is_arch(Regex) of - true -> {ShellToMk(Output), Input, []}; - false -> [] - end; - {Regex, Output, Input, [{env, Env}]} -> - case rebar_utils:is_arch(Regex) of - true -> {ShellToMk(Output), Input, Env}; - false -> [] - end - end || S <- Specs]) - end - end(), - PortSpecWrite = fun (Text) -> - file:write_file("$(DEPS_DIR)/$(1)/c_src/Makefile.erlang.mk", Text, [append]) - end, - case PortSpecs of - [] -> ok; - _ -> - Write("\npre-app::\n\t$$$$\(MAKE) -f c_src/Makefile.erlang.mk\n"), - PortSpecWrite(io_lib:format("ERL_CFLAGS = -finline-functions -Wall -fPIC -I ~s/erts-~s/include -I ~s\n", - [code:root_dir(), erlang:system_info(version), code:lib_dir(erl_interface, include)])), - PortSpecWrite(io_lib:format("ERL_LDFLAGS = -L ~s -lerl_interface -lei\n", - [code:lib_dir(erl_interface, lib)])), - [PortSpecWrite(["\n", E, "\n"]) || E <- OsEnv], - FilterEnv = fun(Env) -> - lists:flatten([case E of - {_, _} -> E; - {Regex, K, V} -> - case rebar_utils:is_arch(Regex) of - true -> {K, V}; - false -> [] - end - end || E <- Env]) - end, - MergeEnv = fun(Env) -> - lists:foldl(fun ({K, V}, Acc) -> - case lists:keyfind(K, 1, Acc) of - false -> [{K, rebar_utils:expand_env_variable(V, K, "")}|Acc]; - {_, V0} -> [{K, rebar_utils:expand_env_variable(V, K, V0)}|Acc] - end - end, [], Env) - end, - PortEnv = case lists:keyfind(port_env, 1, Conf) of - false -> []; - {_, PortEnv0} -> FilterEnv(PortEnv0) - end, - PortSpec = fun ({Output, Input0, Env}) -> - filelib:ensure_dir("$(DEPS_DIR)/$(1)/" ++ Output), - Input = [[" ", I] || I <- Input0], - PortSpecWrite([ - [["\n", K, " = ", ShellToMk(V)] || {K, V} <- lists:reverse(MergeEnv(PortEnv))], - case $(PLATFORM) of - darwin -> "\n\nLDFLAGS += -flat_namespace -undefined suppress"; - _ -> "" - end, - "\n\nall:: ", Output, "\n\n", - "%.o: %.c\n\t$$$$\(CC) -c -o $$$$\@ $$$$\< $$$$\(CFLAGS) $$$$\(ERL_CFLAGS) $$$$\(DRV_CFLAGS) $$$$\(EXE_CFLAGS)\n\n", - "%.o: %.C\n\t$$$$\(CXX) -c -o $$$$\@ $$$$\< $$$$\(CXXFLAGS) $$$$\(ERL_CFLAGS) $$$$\(DRV_CFLAGS) $$$$\(EXE_CFLAGS)\n\n", - "%.o: %.cc\n\t$$$$\(CXX) -c -o $$$$\@ $$$$\< $$$$\(CXXFLAGS) $$$$\(ERL_CFLAGS) $$$$\(DRV_CFLAGS) $$$$\(EXE_CFLAGS)\n\n", - "%.o: %.cpp\n\t$$$$\(CXX) -c -o $$$$\@ $$$$\< $$$$\(CXXFLAGS) $$$$\(ERL_CFLAGS) $$$$\(DRV_CFLAGS) $$$$\(EXE_CFLAGS)\n\n", - [[Output, ": ", K, " = ", ShellToMk(V), "\n"] || {K, V} <- lists:reverse(MergeEnv(FilterEnv(Env)))], - Output, ": $$$$\(foreach ext,.c .C .cc .cpp,", - "$$$$\(patsubst %$$$$\(ext),%.o,$$$$\(filter %$$$$\(ext),$$$$\(wildcard", Input, "))))\n", - "\t$$$$\(CC) -o $$$$\@ $$$$\? $$$$\(LDFLAGS) $$$$\(ERL_LDFLAGS) $$$$\(DRV_LDFLAGS) $$$$\(EXE_LDFLAGS)", - case filename:extension(Output) of - [] -> "\n"; - _ -> " -shared\n" - end]) - end, - [PortSpec(S) || S <- PortSpecs] - end, - Write("\ninclude $(ERLANG_MK_FILENAME)"), - RunPlugin = fun(Plugin, Step) -> - case erlang:function_exported(Plugin, Step, 2) of - false -> ok; - true -> - c:cd("$(DEPS_DIR)/$(1)/"), - Ret = Plugin:Step({config, "", Conf, dict:new(), dict:new(), dict:new(), - dict:store(base_dir, "", dict:new())}, undefined), - io:format("rebar plugin ~p step ~p ret ~p~n", [Plugin, Step, Ret]) - end - end, - fun() -> - case lists:keyfind(plugins, 1, Conf) of - false -> ok; - {_, Plugins} -> - [begin - case lists:keyfind(deps, 1, Conf) of - false -> ok; - {_, Deps} -> - case lists:keyfind(P, 1, Deps) of - false -> ok; - _ -> - Path = "$(DEPS_DIR)/" ++ atom_to_list(P), - io:format("~s", [os:cmd("$(MAKE) -C $(DEPS_DIR)/$(1) " ++ Path)]), - io:format("~s", [os:cmd("$(MAKE) -C " ++ Path ++ " IS_DEP=1")]), - code:add_patha(Path ++ "/ebin") - end - end - end || P <- Plugins], - [case code:load_file(P) of - {module, P} -> ok; - _ -> - case lists:keyfind(plugin_dir, 1, Conf) of - false -> ok; - {_, PluginsDir} -> - ErlFile = "$(DEPS_DIR)/$(1)/" ++ PluginsDir ++ "/" ++ atom_to_list(P) ++ ".erl", - {ok, P, Bin} = compile:file(ErlFile, [binary]), - {module, P} = code:load_binary(P, ErlFile, Bin) - end - end || P <- Plugins], - [RunPlugin(P, preprocess) || P <- Plugins], - [RunPlugin(P, pre_compile) || P <- Plugins] - end - end(), - halt() -endef - -define dep_autopatch_app.erl - UpdateModules = fun(App) -> - case filelib:is_regular(App) of - false -> ok; - true -> - {ok, [{application, $(1), L0}]} = file:consult(App), - Mods = filelib:fold_files("$(DEPS_DIR)/$(1)/src", "\\\\.erl$$$$", true, - fun (F, Acc) -> [list_to_atom(filename:rootname(filename:basename(F)))|Acc] end, []), - L = lists:keystore(modules, 1, L0, {modules, Mods}), - ok = file:write_file(App, io_lib:format("~p.~n", [{application, $(1), L}])) - end - end, - UpdateModules("$(DEPS_DIR)/$(1)/ebin/$(1).app"), - halt() -endef - -define dep_autopatch_appsrc.erl - AppSrcOut = "$(DEPS_DIR)/$(1)/src/$(1).app.src", - AppSrcIn = case filelib:is_regular(AppSrcOut) of false -> "$(DEPS_DIR)/$(1)/ebin/$(1).app"; true -> AppSrcOut end, - case filelib:is_regular(AppSrcIn) of - false -> ok; - true -> - {ok, [{application, $(1), L0}]} = file:consult(AppSrcIn), - L1 = lists:keystore(modules, 1, L0, {modules, []}), - L2 = case lists:keyfind(vsn, 1, L1) of {_, git} -> lists:keyreplace(vsn, 1, L1, {vsn, "git"}); _ -> L1 end, - L3 = case lists:keyfind(registered, 1, L2) of false -> [{registered, []}|L2]; _ -> L2 end, - ok = file:write_file(AppSrcOut, io_lib:format("~p.~n", [{application, $(1), L3}])), - case AppSrcOut of AppSrcIn -> ok; _ -> ok = file:delete(AppSrcIn) end - end, - halt() -endef - -define hex_fetch.erl - ssl:start(), - inets:start(), - {ok, {{_, 200, _}, _, Body}} = httpc:request(get, - {"https://s3.amazonaws.com/s3.hex.pm/tarballs/$(1)-$(2).tar", []}, - [], [{body_format, binary}]), - {ok, Files} = erl_tar:extract({binary, Body}, [memory]), - {_, Source} = lists:keyfind("contents.tar.gz", 1, Files), - ok = erl_tar:extract({binary, Source}, [{cwd, "$(DEPS_DIR)/$(1)"}, compressed]), - halt() -endef - -define dep_fetch - if [ "$(2)" = "git" ]; then \ - git clone -q -n -- $(3) $(DEPS_DIR)/$(1); \ - cd $(DEPS_DIR)/$(1) && git checkout -q $(4); \ - elif [ "$(2)" = "hg" ]; then \ - hg clone -q -U $(3) $(DEPS_DIR)/$(1); \ - cd $(DEPS_DIR)/$(1) && hg update -q $(4); \ - elif [ "$(2)" = "svn" ]; then \ - svn checkout -q $(3) $(DEPS_DIR)/$(1); \ - elif [ "$(2)" = "cp" ]; then \ - cp -R $(3) $(DEPS_DIR)/$(1); \ - elif [ "$(2)" = "hex" ]; then \ - $(call erlang,$(call hex_fetch.erl,$(1),$(strip $(4)))); \ - else \ - echo "Unknown or invalid dependency: $(1). Please consult the erlang.mk README for instructions." >&2; \ - exit 78; \ - fi -endef - -define dep_target -$(DEPS_DIR)/$(1): - $(verbose) mkdir -p $(DEPS_DIR) -ifeq (,$(dep_$(1))) - $(dep_verbose) $(call dep_fetch,$(pkg_$(1)_name),$(pkg_$(1)_fetch), \ - $(patsubst git://github.com/%,https://github.com/%,$(pkg_$(1)_repo)), \ - $(pkg_$(1)_commit)) -else -ifeq (1,$(words $(dep_$(1)))) - $(dep_verbose) $(call dep_fetch,$(1),git, \ - $(patsubst git://github.com/%,https://github.com/%,$(dep_$(1))), \ - master) -else -ifeq (2,$(words $(dep_$(1)))) - $(dep_verbose) $(call dep_fetch,$(1),git, \ - $(patsubst git://github.com/%,https://github.com/%,$(word 1,$(dep_$(1)))), \ - $(word 2,$(dep_$(1)))) -else - $(dep_verbose) $(call dep_fetch,$(1),$(word 1,$(dep_$(1))), \ - $(patsubst git://github.com/%,https://github.com/%,$(word 2,$(dep_$(1)))), \ - $(word 3,$(dep_$(1)))) -endif -endif -endif - $(verbose) if [ -f $(DEPS_DIR)/$(1)/configure.ac -o -f $(DEPS_DIR)/$(1)/configure.in ]; then \ - echo " AUTO " $(1); \ - cd $(DEPS_DIR)/$(1) && autoreconf -Wall -vif -I m4; \ - fi - - $(verbose) if [ -f $(DEPS_DIR)/$(1)/configure ]; then \ - echo " CONF " $(1); \ - cd $(DEPS_DIR)/$(1) && ./configure; \ - fi -ifeq ($(filter $(1),$(NO_AUTOPATCH)),) - $(verbose) if [ "$(1)" = "amqp_client" -a "$(RABBITMQ_CLIENT_PATCH)" ]; then \ - if [ ! -d $(DEPS_DIR)/rabbitmq-codegen ]; then \ - echo " PATCH Downloading rabbitmq-codegen"; \ - git clone https://github.com/rabbitmq/rabbitmq-codegen.git $(DEPS_DIR)/rabbitmq-codegen; \ - fi; \ - if [ ! -d $(DEPS_DIR)/rabbitmq-server ]; then \ - echo " PATCH Downloading rabbitmq-server"; \ - git clone https://github.com/rabbitmq/rabbitmq-server.git $(DEPS_DIR)/rabbitmq-server; \ - fi; \ - ln -s $(DEPS_DIR)/amqp_client/deps/rabbit_common-0.0.0 $(DEPS_DIR)/rabbit_common; \ - elif [ "$(1)" = "rabbit" -a "$(RABBITMQ_SERVER_PATCH)" ]; then \ - if [ ! -d $(DEPS_DIR)/rabbitmq-codegen ]; then \ - echo " PATCH Downloading rabbitmq-codegen"; \ - git clone https://github.com/rabbitmq/rabbitmq-codegen.git $(DEPS_DIR)/rabbitmq-codegen; \ - fi \ - else \ - $(call dep_autopatch,$(1)) \ - fi -endif -endef - -$(foreach dep,$(DEPS),$(eval $(call dep_target,$(dep)))) - -distclean-deps: - $(gen_verbose) rm -rf $(DEPS_DIR) - -# Copyright (c) 2015, Loïc Hoguin -# This file is part of erlang.mk and subject to the terms of the ISC License. - -# Verbosity. - -proto_verbose_0 = @echo " PROTO " $(filter %.proto,$(?F)); -proto_verbose = $(proto_verbose_$(V)) - -# Core targets. - -define compile_proto - $(verbose) mkdir -p ebin/ include/ - $(proto_verbose) $(call erlang,$(call compile_proto.erl,$(1))) - $(proto_verbose) erlc +debug_info -o ebin/ ebin/*.erl - $(verbose) rm ebin/*.erl -endef - -define compile_proto.erl - [begin - Dir = filename:dirname(filename:dirname(F)), - protobuffs_compile:generate_source(F, - [{output_include_dir, Dir ++ "/include"}, - {output_src_dir, Dir ++ "/ebin"}]) - end || F <- string:tokens("$(1)", " ")], - halt(). -endef - -ifneq ($(wildcard src/),) -ebin/$(PROJECT).app:: $(sort $(call core_find,src/,*.proto)) - $(if $(strip $?),$(call compile_proto,$?)) -endif - -# Copyright (c) 2013-2015, Loïc Hoguin -# This file is part of erlang.mk and subject to the terms of the ISC License. - -.PHONY: clean-app - -# Configuration. - -ERLC_OPTS ?= -Werror +debug_info +warn_export_vars +warn_shadow_vars \ - +warn_obsolete_guard # +bin_opt_info +warn_export_all +warn_missing_spec -COMPILE_FIRST ?= -COMPILE_FIRST_PATHS = $(addprefix src/,$(addsuffix .erl,$(COMPILE_FIRST))) -ERLC_EXCLUDE ?= -ERLC_EXCLUDE_PATHS = $(addprefix src/,$(addsuffix .erl,$(ERLC_EXCLUDE))) - -ERLC_MIB_OPTS ?= -COMPILE_MIB_FIRST ?= -COMPILE_MIB_FIRST_PATHS = $(addprefix mibs/,$(addsuffix .mib,$(COMPILE_MIB_FIRST))) - -# Verbosity. - -app_verbose_0 = @echo " APP " $(PROJECT); -app_verbose = $(app_verbose_$(V)) - -appsrc_verbose_0 = @echo " APP " $(PROJECT).app.src; -appsrc_verbose = $(appsrc_verbose_$(V)) - -erlc_verbose_0 = @echo " ERLC " $(filter-out $(patsubst %,%.erl,$(ERLC_EXCLUDE)),\ - $(filter %.erl %.core,$(?F))); -erlc_verbose = $(erlc_verbose_$(V)) - -xyrl_verbose_0 = @echo " XYRL " $(filter %.xrl %.yrl,$(?F)); -xyrl_verbose = $(xyrl_verbose_$(V)) - -asn1_verbose_0 = @echo " ASN1 " $(filter %.asn1,$(?F)); -asn1_verbose = $(asn1_verbose_$(V)) - -mib_verbose_0 = @echo " MIB " $(filter %.bin %.mib,$(?F)); -mib_verbose = $(mib_verbose_$(V)) - -# Targets. - -ifeq ($(wildcard ebin/test),) -app:: app-build -else -app:: clean app-build -endif - -ifeq ($(wildcard src/$(PROJECT)_app.erl),) -define app_file -{application, $(PROJECT), [ - {description, "$(PROJECT_DESCRIPTION)"}, - {vsn, "$(PROJECT_VERSION)"}, - {id, "$(1)"}, - {modules, [$(call comma_list,$(2))]}, - {registered, []}, - {applications, [$(call comma_list,kernel stdlib $(OTP_DEPS) $(DEPS))]} -]}. -endef -else -define app_file -{application, $(PROJECT), [ - {description, "$(PROJECT_DESCRIPTION)"}, - {vsn, "$(PROJECT_VERSION)"}, - {id, "$(1)"}, - {modules, [$(call comma_list,$(2))]}, - {registered, [$(call comma_list,$(PROJECT)_sup $(PROJECT_REGISTERED))]}, - {applications, [$(call comma_list,kernel stdlib $(OTP_DEPS) $(DEPS))]}, - {mod, {$(PROJECT)_app, []}} -]}. -endef -endif - -app-build: erlc-include ebin/$(PROJECT).app - $(eval GITDESCRIBE := $(shell git describe --dirty --abbrev=7 --tags --always --first-parent 2>/dev/null || true)) - $(eval MODULES := $(patsubst %,'%',$(sort $(notdir $(basename $(wildcard ebin/*.beam)))))) -ifeq ($(wildcard src/$(PROJECT).app.src),) - $(app_verbose) echo $(subst $(newline),,$(subst ",\",$(call app_file,$(GITDESCRIBE),$(MODULES)))) \ - > ebin/$(PROJECT).app -else - $(verbose) if [ -z "$$(grep -E '^[^%]*{\s*modules\s*,' src/$(PROJECT).app.src)" ]; then \ - echo "Empty modules entry not found in $(PROJECT).app.src. Please consult the erlang.mk README for instructions." >&2; \ - exit 1; \ - fi - $(appsrc_verbose) cat src/$(PROJECT).app.src \ - | sed "s/{[[:space:]]*modules[[:space:]]*,[[:space:]]*\[\]}/{modules, \[$(call comma_list,$(MODULES))\]}/" \ - | sed "s/{id,[[:space:]]*\"git\"}/{id, \"$(GITDESCRIBE)\"}/" \ - > ebin/$(PROJECT).app -endif - -erlc-include: - - $(verbose) if [ -d ebin/ ]; then \ - find include/ src/ -type f -name \*.hrl -newer ebin -exec touch $(shell find src/ -type f -name "*.erl") \; 2>/dev/null || printf ''; \ - fi - -define compile_erl - $(erlc_verbose) erlc -v $(if $(IS_DEP),$(filter-out -Werror,$(ERLC_OPTS)),$(ERLC_OPTS)) -o ebin/ \ - -pa ebin/ -I include/ $(filter-out $(ERLC_EXCLUDE_PATHS),\ - $(COMPILE_FIRST_PATHS) $(1)) -endef - -define compile_xyrl - $(xyrl_verbose) erlc -v -o ebin/ $(1) - $(xyrl_verbose) erlc $(ERLC_OPTS) -o ebin/ ebin/*.erl - $(verbose) rm ebin/*.erl -endef - -define compile_asn1 - $(asn1_verbose) erlc -v -I include/ -o ebin/ $(1) - $(verbose) mv ebin/*.hrl include/ - $(verbose) mv ebin/*.asn1db include/ - $(verbose) rm ebin/*.erl -endef - -define compile_mib - $(mib_verbose) erlc -v $(ERLC_MIB_OPTS) -o priv/mibs/ \ - -I priv/mibs/ $(COMPILE_MIB_FIRST_PATHS) $(1) - $(mib_verbose) erlc -o include/ -- priv/mibs/*.bin -endef - -ifneq ($(wildcard src/),) -ebin/$(PROJECT).app:: - $(verbose) mkdir -p ebin/ - -ifneq ($(wildcard asn1/),) -ebin/$(PROJECT).app:: $(sort $(call core_find,asn1/,*.asn1)) - $(verbose) mkdir -p include - $(if $(strip $?),$(call compile_asn1,$?)) -endif - -ifneq ($(wildcard mibs/),) -ebin/$(PROJECT).app:: $(sort $(call core_find,mibs/,*.mib)) - $(verbose) mkdir -p priv/mibs/ include - $(if $(strip $?),$(call compile_mib,$?)) -endif - -ebin/$(PROJECT).app:: $(sort $(call core_find,src/,*.erl *.core)) - $(if $(strip $?),$(call compile_erl,$?)) - -ebin/$(PROJECT).app:: $(sort $(call core_find,src/,*.xrl *.yrl)) - $(if $(strip $?),$(call compile_xyrl,$?)) -endif - -clean:: clean-app - -clean-app: - $(gen_verbose) rm -rf ebin/ priv/mibs/ \ - $(addprefix include/,$(addsuffix .hrl,$(notdir $(basename $(call core_find,mibs/,*.mib))))) - -# Copyright (c) 2015, Viktor Söderqvist -# This file is part of erlang.mk and subject to the terms of the ISC License. - -.PHONY: docs-deps - -# Configuration. - -ALL_DOC_DEPS_DIRS = $(addprefix $(DEPS_DIR)/,$(DOC_DEPS)) - -# Targets. - -$(foreach dep,$(DOC_DEPS),$(eval $(call dep_target,$(dep)))) - -ifneq ($(SKIP_DEPS),) -doc-deps: -else -doc-deps: $(ALL_DOC_DEPS_DIRS) - $(verbose) for dep in $(ALL_DOC_DEPS_DIRS) ; do $(MAKE) -C $$dep; done -endif - -# Copyright (c) 2015, Loïc Hoguin -# This file is part of erlang.mk and subject to the terms of the ISC License. - -.PHONY: test-deps test-dir test-build clean-test-dir - -# Configuration. - -TEST_DIR ?= $(CURDIR)/test - -ALL_TEST_DEPS_DIRS = $(addprefix $(DEPS_DIR)/,$(TEST_DEPS)) - -TEST_ERLC_OPTS ?= +debug_info +warn_export_vars +warn_shadow_vars +warn_obsolete_guard -TEST_ERLC_OPTS += -DTEST=1 - -# Targets. - -$(foreach dep,$(TEST_DEPS),$(eval $(call dep_target,$(dep)))) - -ifneq ($(SKIP_DEPS),) -test-deps: -else -test-deps: $(ALL_TEST_DEPS_DIRS) - $(verbose) for dep in $(ALL_TEST_DEPS_DIRS) ; do $(MAKE) -C $$dep IS_DEP=1; done -endif - -ifneq ($(wildcard $(TEST_DIR)),) -test-dir: - $(gen_verbose) erlc -v $(TEST_ERLC_OPTS) -I include/ -o $(TEST_DIR) \ - $(call core_find,$(TEST_DIR)/,*.erl) -pa ebin/ -endif - -ifeq ($(wildcard ebin/test),) -test-build:: ERLC_OPTS=$(TEST_ERLC_OPTS) -test-build:: clean deps test-deps - $(verbose) $(MAKE) --no-print-directory app-build test-dir ERLC_OPTS="$(TEST_ERLC_OPTS)" - $(gen_verbose) touch ebin/test -else -test-build:: ERLC_OPTS=$(TEST_ERLC_OPTS) -test-build:: deps test-deps - $(verbose) $(MAKE) --no-print-directory app-build test-dir ERLC_OPTS="$(TEST_ERLC_OPTS)" -endif - -clean:: clean-test-dir - -clean-test-dir: -ifneq ($(wildcard $(TEST_DIR)/*.beam),) - $(gen_verbose) rm -f $(TEST_DIR)/*.beam -endif - -# Copyright (c) 2015, Loïc Hoguin -# This file is part of erlang.mk and subject to the terms of the ISC License. - -.PHONY: asciidoc asciidoc-guide asciidoc-manual install-asciidoc distclean-asciidoc - -MAN_INSTALL_PATH ?= /usr/local/share/man -MAN_SECTIONS ?= 3 7 - -docs:: asciidoc - -asciidoc: distclean-asciidoc doc-deps asciidoc-guide asciidoc-manual - -ifeq ($(wildcard doc/src/guide/book.asciidoc),) -asciidoc-guide: -else -asciidoc-guide: - a2x -v -f pdf doc/src/guide/book.asciidoc && mv doc/src/guide/book.pdf doc/guide.pdf - a2x -v -f chunked doc/src/guide/book.asciidoc && mv doc/src/guide/book.chunked/ doc/html/ -endif - -ifeq ($(wildcard doc/src/manual/*.asciidoc),) -asciidoc-manual: -else -asciidoc-manual: - for f in doc/src/manual/*.asciidoc ; do \ - a2x -v -f manpage $$f ; \ - done - for s in $(MAN_SECTIONS); do \ - mkdir -p doc/man$$s/ ; \ - mv doc/src/manual/*.$$s doc/man$$s/ ; \ - gzip doc/man$$s/*.$$s ; \ - done - -install-docs:: install-asciidoc - -install-asciidoc: asciidoc-manual - for s in $(MAN_SECTIONS); do \ - mkdir -p $(MAN_INSTALL_PATH)/man$$s/ ; \ - install -g 0 -o 0 -m 0644 doc/man$$s/*.gz $(MAN_INSTALL_PATH)/man$$s/ ; \ - done -endif - -distclean:: distclean-asciidoc - -distclean-asciidoc: - $(gen_verbose) rm -rf doc/html/ doc/guide.pdf doc/man3/ doc/man7/ - -# Copyright (c) 2014-2015, Loïc Hoguin -# This file is part of erlang.mk and subject to the terms of the ISC License. - -.PHONY: bootstrap bootstrap-lib bootstrap-rel new list-templates - -# Core targets. - -help:: - $(verbose) printf "%s\n" "" \ - "Bootstrap targets:" \ - " bootstrap Generate a skeleton of an OTP application" \ - " bootstrap-lib Generate a skeleton of an OTP library" \ - " bootstrap-rel Generate the files needed to build a release" \ - " new t=TPL n=NAME Generate a module NAME based on the template TPL" \ - " list-templates List available templates" - -# Bootstrap templates. - -define bs_appsrc -{application, $(PROJECT), [ - {description, ""}, - {vsn, "0.1.0"}, - {id, "git"}, - {modules, []}, - {registered, []}, - {applications, [ - kernel, - stdlib - ]}, - {mod, {$(PROJECT)_app, []}}, - {env, []} -]}. -endef - -define bs_appsrc_lib -{application, $(PROJECT), [ - {description, ""}, - {vsn, "0.1.0"}, - {id, "git"}, - {modules, []}, - {registered, []}, - {applications, [ - kernel, - stdlib - ]} -]}. -endef - -ifdef SP -define bs_Makefile -PROJECT = $(PROJECT) - -# Whitespace to be used when creating files from templates. -SP = $(SP) - -include erlang.mk -endef -else -define bs_Makefile -PROJECT = $(PROJECT) -include erlang.mk -endef -endif - -define bs_app --module($(PROJECT)_app). --behaviour(application). - --export([start/2]). --export([stop/1]). - -start(_Type, _Args) -> - $(PROJECT)_sup:start_link(). - -stop(_State) -> - ok. -endef - -define bs_relx_config -{release, {$(PROJECT)_release, "1"}, [$(PROJECT)]}. -{extended_start_script, true}. -{sys_config, "rel/sys.config"}. -{vm_args, "rel/vm.args"}. -endef - -define bs_sys_config -[ -]. -endef - -define bs_vm_args --name $(PROJECT)@127.0.0.1 --setcookie $(PROJECT) --heart -endef - -# Normal templates. - -define tpl_supervisor --module($(n)). --behaviour(supervisor). - --export([start_link/0]). --export([init/1]). - -start_link() -> - supervisor:start_link({local, ?MODULE}, ?MODULE, []). - -init([]) -> - Procs = [], - {ok, {{one_for_one, 1, 5}, Procs}}. -endef - -define tpl_gen_server --module($(n)). --behaviour(gen_server). - -%% API. --export([start_link/0]). - -%% gen_server. --export([init/1]). --export([handle_call/3]). --export([handle_cast/2]). --export([handle_info/2]). --export([terminate/2]). --export([code_change/3]). - --record(state, { -}). - -%% API. - --spec start_link() -> {ok, pid()}. -start_link() -> - gen_server:start_link(?MODULE, [], []). - -%% gen_server. - -init([]) -> - {ok, #state{}}. - -handle_call(_Request, _From, State) -> - {reply, ignored, State}. - -handle_cast(_Msg, State) -> - {noreply, State}. - -handle_info(_Info, State) -> - {noreply, State}. - -terminate(_Reason, _State) -> - ok. - -code_change(_OldVsn, State, _Extra) -> - {ok, State}. -endef - -define tpl_cowboy_http --module($(n)). --behaviour(cowboy_http_handler). - --export([init/3]). --export([handle/2]). --export([terminate/3]). - --record(state, { -}). - -init(_, Req, _Opts) -> - {ok, Req, #state{}}. - -handle(Req, State=#state{}) -> - {ok, Req2} = cowboy_req:reply(200, Req), - {ok, Req2, State}. - -terminate(_Reason, _Req, _State) -> - ok. -endef - -define tpl_gen_fsm --module($(n)). --behaviour(gen_fsm). - -%% API. --export([start_link/0]). - -%% gen_fsm. --export([init/1]). --export([state_name/2]). --export([handle_event/3]). --export([state_name/3]). --export([handle_sync_event/4]). --export([handle_info/3]). --export([terminate/3]). --export([code_change/4]). - --record(state, { -}). - -%% API. - --spec start_link() -> {ok, pid()}. -start_link() -> - gen_fsm:start_link(?MODULE, [], []). - -%% gen_fsm. - -init([]) -> - {ok, state_name, #state{}}. - -state_name(_Event, StateData) -> - {next_state, state_name, StateData}. - -handle_event(_Event, StateName, StateData) -> - {next_state, StateName, StateData}. - -state_name(_Event, _From, StateData) -> - {reply, ignored, state_name, StateData}. - -handle_sync_event(_Event, _From, StateName, StateData) -> - {reply, ignored, StateName, StateData}. - -handle_info(_Info, StateName, StateData) -> - {next_state, StateName, StateData}. - -terminate(_Reason, _StateName, _StateData) -> - ok. - -code_change(_OldVsn, StateName, StateData, _Extra) -> - {ok, StateName, StateData}. -endef - -define tpl_cowboy_loop --module($(n)). --behaviour(cowboy_loop_handler). - --export([init/3]). --export([info/3]). --export([terminate/3]). - --record(state, { -}). - -init(_, Req, _Opts) -> - {loop, Req, #state{}, 5000, hibernate}. - -info(_Info, Req, State) -> - {loop, Req, State, hibernate}. - -terminate(_Reason, _Req, _State) -> - ok. -endef - -define tpl_cowboy_rest --module($(n)). - --export([init/3]). --export([content_types_provided/2]). --export([get_html/2]). - -init(_, _Req, _Opts) -> - {upgrade, protocol, cowboy_rest}. - -content_types_provided(Req, State) -> - {[{{<<"text">>, <<"html">>, '*'}, get_html}], Req, State}. - -get_html(Req, State) -> - {<<"This is REST!">>, Req, State}. -endef - -define tpl_cowboy_ws --module($(n)). --behaviour(cowboy_websocket_handler). - --export([init/3]). --export([websocket_init/3]). --export([websocket_handle/3]). --export([websocket_info/3]). --export([websocket_terminate/3]). - --record(state, { -}). - -init(_, _, _) -> - {upgrade, protocol, cowboy_websocket}. - -websocket_init(_, Req, _Opts) -> - Req2 = cowboy_req:compact(Req), - {ok, Req2, #state{}}. - -websocket_handle({text, Data}, Req, State) -> - {reply, {text, Data}, Req, State}; -websocket_handle({binary, Data}, Req, State) -> - {reply, {binary, Data}, Req, State}; -websocket_handle(_Frame, Req, State) -> - {ok, Req, State}. - -websocket_info(_Info, Req, State) -> - {ok, Req, State}. - -websocket_terminate(_Reason, _Req, _State) -> - ok. -endef - -define tpl_ranch_protocol --module($(n)). --behaviour(ranch_protocol). - --export([start_link/4]). --export([init/4]). - --type opts() :: []. --export_type([opts/0]). - --record(state, { - socket :: inet:socket(), - transport :: module() -}). - -start_link(Ref, Socket, Transport, Opts) -> - Pid = spawn_link(?MODULE, init, [Ref, Socket, Transport, Opts]), - {ok, Pid}. - --spec init(ranch:ref(), inet:socket(), module(), opts()) -> ok. -init(Ref, Socket, Transport, _Opts) -> - ok = ranch:accept_ack(Ref), - loop(#state{socket=Socket, transport=Transport}). - -loop(State) -> - loop(State). -endef - -# Plugin-specific targets. - -define render_template - $(verbose) echo "$${_$(1)}" > $(2) -endef - -ifndef WS -ifdef SP -WS = $(subst a,,a $(wordlist 1,$(SP),a a a a a a a a a a a a a a a a a a a a)) -else -WS = $(tab) -endif -endif - -$(foreach template,$(filter bs_% tpl_%,$(.VARIABLES)), \ - $(eval _$(template) = $$(subst $$(tab),$$(WS),$$($(template)))) \ - $(eval export _$(template))) - -bootstrap: -ifneq ($(wildcard src/),) - $(error Error: src/ directory already exists) -endif - $(call render_template,bs_Makefile,Makefile) - $(verbose) mkdir src/ - $(call render_template,bs_appsrc,src/$(PROJECT).app.src) - $(call render_template,bs_app,src/$(PROJECT)_app.erl) - $(eval n := $(PROJECT)_sup) - $(call render_template,tpl_supervisor,src/$(PROJECT)_sup.erl) - -bootstrap-lib: -ifneq ($(wildcard src/),) - $(error Error: src/ directory already exists) -endif - $(call render_template,bs_Makefile,Makefile) - $(verbose) mkdir src/ - $(call render_template,bs_appsrc_lib,src/$(PROJECT).app.src) - -bootstrap-rel: -ifneq ($(wildcard relx.config),) - $(error Error: relx.config already exists) -endif -ifneq ($(wildcard rel/),) - $(error Error: rel/ directory already exists) -endif - $(call render_template,bs_relx_config,relx.config) - $(verbose) mkdir rel/ - $(call render_template,bs_sys_config,rel/sys.config) - $(call render_template,bs_vm_args,rel/vm.args) - -new: -ifeq ($(wildcard src/),) - $(error Error: src/ directory does not exist) -endif -ifndef t - $(error Usage: $(MAKE) new t=TEMPLATE n=NAME) -endif -ifndef tpl_$(t) - $(error Unknown template) -endif -ifndef n - $(error Usage: $(MAKE) new t=TEMPLATE n=NAME) -endif - $(call render_template,tpl_$(t),src/$(n).erl) - -list-templates: - $(verbose) echo Available templates: $(sort $(patsubst tpl_%,%,$(filter tpl_%,$(.VARIABLES)))) - -# Copyright (c) 2014-2015, Loïc Hoguin -# This file is part of erlang.mk and subject to the terms of the ISC License. - -.PHONY: clean-c_src distclean-c_src-env - -# Configuration. - -C_SRC_DIR ?= $(CURDIR)/c_src -C_SRC_ENV ?= $(C_SRC_DIR)/env.mk -C_SRC_OUTPUT ?= $(CURDIR)/priv/$(PROJECT).so -C_SRC_TYPE ?= shared - -# System type and C compiler/flags. - -ifeq ($(PLATFORM),darwin) - CC ?= cc - CFLAGS ?= -O3 -std=c99 -arch x86_64 -finline-functions -Wall -Wmissing-prototypes - CXXFLAGS ?= -O3 -arch x86_64 -finline-functions -Wall - LDFLAGS ?= -arch x86_64 -flat_namespace -undefined suppress -else ifeq ($(PLATFORM),freebsd) - CC ?= cc - CFLAGS ?= -O3 -std=c99 -finline-functions -Wall -Wmissing-prototypes - CXXFLAGS ?= -O3 -finline-functions -Wall -else ifeq ($(PLATFORM),linux) - CC ?= gcc - CFLAGS ?= -O3 -std=c99 -finline-functions -Wall -Wmissing-prototypes - CXXFLAGS ?= -O3 -finline-functions -Wall -endif - -CFLAGS += -fPIC -I $(ERTS_INCLUDE_DIR) -I $(ERL_INTERFACE_INCLUDE_DIR) -CXXFLAGS += -fPIC -I $(ERTS_INCLUDE_DIR) -I $(ERL_INTERFACE_INCLUDE_DIR) - -LDLIBS += -L $(ERL_INTERFACE_LIB_DIR) -lerl_interface -lei - -ifeq ($(C_SRC_TYPE),shared) -LDFLAGS += -shared -endif - -# Verbosity. - -c_verbose_0 = @echo " C " $(?F); -c_verbose = $(c_verbose_$(V)) - -cpp_verbose_0 = @echo " CPP " $(?F); -cpp_verbose = $(cpp_verbose_$(V)) - -link_verbose_0 = @echo " LD " $(@F); -link_verbose = $(link_verbose_$(V)) - -# Targets. - -ifeq ($(wildcard $(C_SRC_DIR)),) -else ifneq ($(wildcard $(C_SRC_DIR)/Makefile),) -app:: app-c_src - -test-build:: app-c_src - -app-c_src: - $(MAKE) -C $(C_SRC_DIR) - -clean:: - $(MAKE) -C $(C_SRC_DIR) clean - -else - -ifeq ($(SOURCES),) -SOURCES := $(sort $(call core_find,$(C_SRC_DIR)/,*.c *.C *.cc *.cpp)) -endif -OBJECTS = $(addsuffix .o, $(basename $(SOURCES))) - -COMPILE_C = $(c_verbose) $(CC) $(CFLAGS) $(CPPFLAGS) -c -COMPILE_CPP = $(cpp_verbose) $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c - -app:: $(C_SRC_ENV) $(C_SRC_OUTPUT) - -test-build:: $(C_SRC_ENV) $(C_SRC_OUTPUT) - -$(C_SRC_OUTPUT): $(OBJECTS) - $(verbose) mkdir -p priv/ - $(link_verbose) $(CC) $(OBJECTS) $(LDFLAGS) $(LDLIBS) -o $(C_SRC_OUTPUT) - -%.o: %.c - $(COMPILE_C) $(OUTPUT_OPTION) $< - -%.o: %.cc - $(COMPILE_CPP) $(OUTPUT_OPTION) $< - -%.o: %.C - $(COMPILE_CPP) $(OUTPUT_OPTION) $< - -%.o: %.cpp - $(COMPILE_CPP) $(OUTPUT_OPTION) $< - -clean:: clean-c_src - -clean-c_src: - $(gen_verbose) rm -f $(C_SRC_OUTPUT) $(OBJECTS) - -endif - -ifneq ($(wildcard $(C_SRC_DIR)),) -$(C_SRC_ENV): - $(verbose) $(ERL) -eval "file:write_file(\"$(C_SRC_ENV)\", \ - io_lib:format( \ - \"ERTS_INCLUDE_DIR ?= ~s/erts-~s/include/~n\" \ - \"ERL_INTERFACE_INCLUDE_DIR ?= ~s~n\" \ - \"ERL_INTERFACE_LIB_DIR ?= ~s~n\", \ - [code:root_dir(), erlang:system_info(version), \ - code:lib_dir(erl_interface, include), \ - code:lib_dir(erl_interface, lib)])), \ - halt()." - -distclean:: distclean-c_src-env - -distclean-c_src-env: - $(gen_verbose) rm -f $(C_SRC_ENV) - --include $(C_SRC_ENV) -endif - -# Copyright (c) 2015, Loïc Hoguin -# This file is part of erlang.mk and subject to the terms of the ISC License. - -.PHONY: ci ci-setup distclean-kerl - -KERL ?= $(CURDIR)/kerl -export KERL - -KERL_URL ?= https://raw.githubusercontent.com/yrashk/kerl/master/kerl - -OTP_GIT ?= https://github.com/erlang/otp - -CI_INSTALL_DIR ?= $(HOME)/erlang -CI_OTP ?= - -ifeq ($(strip $(CI_OTP)),) -ci:: -else -ci:: $(addprefix ci-,$(CI_OTP)) - -ci-prepare: $(addprefix $(CI_INSTALL_DIR)/,$(CI_OTP)) - -ci-setup:: - -ci_verbose_0 = @echo " CI " $(1); -ci_verbose = $(ci_verbose_$(V)) - -define ci_target -ci-$(1): $(CI_INSTALL_DIR)/$(1) - $(ci_verbose) \ - PATH="$(CI_INSTALL_DIR)/$(1)/bin:$(PATH)" \ - CI_OTP_RELEASE="$(1)" \ - CT_OPTS="-label $(1)" \ - $(MAKE) clean ci-setup tests -endef - -$(foreach otp,$(CI_OTP),$(eval $(call ci_target,$(otp)))) - -define ci_otp_target -ifeq ($(wildcard $(CI_INSTALL_DIR)/$(1)),) -$(CI_INSTALL_DIR)/$(1): $(KERL) - $(KERL) build git $(OTP_GIT) $(1) $(1) - $(KERL) install $(1) $(CI_INSTALL_DIR)/$(1) -endif -endef - -$(foreach otp,$(CI_OTP),$(eval $(call ci_otp_target,$(otp)))) - -$(KERL): - $(gen_verbose) $(call core_http_get,$(KERL),$(KERL_URL)) - $(verbose) chmod +x $(KERL) - -help:: - $(verbose) printf "%s\n" "" \ - "Continuous Integration targets:" \ - " ci Run '$(MAKE) tests' on all configured Erlang versions." \ - "" \ - "The CI_OTP variable must be defined with the Erlang versions" \ - "that must be tested. For example: CI_OTP = OTP-17.3.4 OTP-17.5.3" - -distclean:: distclean-kerl - -distclean-kerl: - $(gen_verbose) rm -rf $(KERL) -endif - -# Copyright (c) 2013-2015, Loïc Hoguin -# This file is part of erlang.mk and subject to the terms of the ISC License. - -.PHONY: ct distclean-ct - -# Configuration. - -CT_OPTS ?= -ifneq ($(wildcard $(TEST_DIR)),) - CT_SUITES ?= $(sort $(subst _SUITE.erl,,$(notdir $(call core_find,$(TEST_DIR)/,*_SUITE.erl)))) -else - CT_SUITES ?= -endif - -# Core targets. - -tests:: ct - -distclean:: distclean-ct - -help:: - $(verbose) printf "%s\n" "" \ - "Common_test targets:" \ - " ct Run all the common_test suites for this project" \ - "" \ - "All your common_test suites have their associated targets." \ - "A suite named http_SUITE can be ran using the ct-http target." - -# Plugin-specific targets. - -CT_RUN = ct_run \ - -no_auto_compile \ - -noinput \ - -pa $(CURDIR)/ebin $(DEPS_DIR)/*/ebin $(TEST_DIR) \ - -dir $(TEST_DIR) \ - -logdir $(CURDIR)/logs - -ifeq ($(CT_SUITES),) -ct: -else -ct: test-build - $(verbose) mkdir -p $(CURDIR)/logs/ - $(gen_verbose) $(CT_RUN) -suite $(addsuffix _SUITE,$(CT_SUITES)) $(CT_OPTS) -endif - -define ct_suite_target -ct-$(1): test-build - $(verbose) mkdir -p $(CURDIR)/logs/ - $(gen_verbose) $(CT_RUN) -suite $(addsuffix _SUITE,$(1)) $(CT_OPTS) -endef - -$(foreach test,$(CT_SUITES),$(eval $(call ct_suite_target,$(test)))) - -distclean-ct: - $(gen_verbose) rm -rf $(CURDIR)/logs/ - -# Copyright (c) 2013-2015, Loïc Hoguin -# This file is part of erlang.mk and subject to the terms of the ISC License. - -.PHONY: plt distclean-plt dialyze - -# Configuration. - -DIALYZER_PLT ?= $(CURDIR)/.$(PROJECT).plt -export DIALYZER_PLT - -PLT_APPS ?= -DIALYZER_DIRS ?= --src -r src -DIALYZER_OPTS ?= -Werror_handling -Wrace_conditions \ - -Wunmatched_returns # -Wunderspecs - -# Core targets. - -check:: dialyze - -distclean:: distclean-plt - -help:: - $(verbose) printf "%s\n" "" \ - "Dialyzer targets:" \ - " plt Build a PLT file for this project" \ - " dialyze Analyze the project using Dialyzer" - -# Plugin-specific targets. - -$(DIALYZER_PLT): deps app - $(verbose) dialyzer --build_plt --apps erts kernel stdlib $(PLT_APPS) $(OTP_DEPS) $(ALL_DEPS_DIRS) - -plt: $(DIALYZER_PLT) - -distclean-plt: - $(gen_verbose) rm -f $(DIALYZER_PLT) - -ifneq ($(wildcard $(DIALYZER_PLT)),) -dialyze: -else -dialyze: $(DIALYZER_PLT) -endif - $(verbose) dialyzer --no_native $(DIALYZER_DIRS) $(DIALYZER_OPTS) - -# Copyright (c) 2013-2015, Loïc Hoguin -# This file is part of erlang.mk and subject to the terms of the ISC License. - -.PHONY: distclean-edoc edoc - -# Configuration. - -EDOC_OPTS ?= - -# Core targets. - -docs:: distclean-edoc edoc - -distclean:: distclean-edoc - -# Plugin-specific targets. - -edoc: doc-deps - $(gen_verbose) $(ERL) -eval 'edoc:application($(PROJECT), ".", [$(EDOC_OPTS)]), halt().' - -distclean-edoc: - $(gen_verbose) rm -f doc/*.css doc/*.html doc/*.png doc/edoc-info - -# Copyright (c) 2015, Erlang Solutions Ltd. -# This file is part of erlang.mk and subject to the terms of the ISC License. - -.PHONY: elvis distclean-elvis - -# Configuration. - -ELVIS_CONFIG ?= $(CURDIR)/elvis.config - -ELVIS ?= $(CURDIR)/elvis -export ELVIS - -ELVIS_URL ?= https://github.com/inaka/elvis/releases/download/0.2.5-beta2/elvis -ELVIS_CONFIG_URL ?= https://github.com/inaka/elvis/releases/download/0.2.5-beta2/elvis.config -ELVIS_OPTS ?= - -# Core targets. - -help:: - $(verbose) printf "%s\n" "" \ - "Elvis targets:" \ - " elvis Run Elvis using the local elvis.config or download the default otherwise" - -distclean:: distclean-elvis - -# Plugin-specific targets. - -$(ELVIS): - $(gen_verbose) $(call core_http_get,$(ELVIS),$(ELVIS_URL)) - $(verbose) chmod +x $(ELVIS) - -$(ELVIS_CONFIG): - $(verbose) $(call core_http_get,$(ELVIS_CONFIG),$(ELVIS_CONFIG_URL)) - -elvis: $(ELVIS) $(ELVIS_CONFIG) - $(verbose) $(ELVIS) rock -c $(ELVIS_CONFIG) $(ELVIS_OPTS) - -distclean-elvis: - $(gen_verbose) rm -rf $(ELVIS) - -# Copyright (c) 2013-2015, Loïc Hoguin -# This file is part of erlang.mk and subject to the terms of the ISC License. - -# Configuration. - -DTL_FULL_PATH ?= 0 - -# Verbosity. - -dtl_verbose_0 = @echo " DTL " $(filter %.dtl,$(?F)); -dtl_verbose = $(dtl_verbose_$(V)) - -# Core targets. - -define compile_erlydtl - $(dtl_verbose) $(ERL) -pa ebin/ $(DEPS_DIR)/erlydtl/ebin/ -eval ' \ - Compile = fun(F) -> \ - S = fun (1) -> re:replace(filename:rootname(string:sub_string(F, 11), ".dtl"), "/", "_", [{return, list}, global]); \ - (0) -> filename:basename(F, ".dtl") \ - end, \ - Module = list_to_atom(string:to_lower(S($(DTL_FULL_PATH))) ++ "_dtl"), \ - {ok, _} = erlydtl:compile(F, Module, [{out_dir, "ebin/"}, return_errors, {doc_root, "templates"}]) \ - end, \ - _ = [Compile(F) || F <- string:tokens("$(1)", " ")], \ - halt().' -endef - -ifneq ($(wildcard src/),) -ebin/$(PROJECT).app:: $(sort $(call core_find,templates/,*.dtl)) - $(if $(strip $?),$(call compile_erlydtl,$?)) -endif - -# Copyright (c) 2014 Dave Cottlehuber -# This file is part of erlang.mk and subject to the terms of the ISC License. - -.PHONY: distclean-escript escript - -# Configuration. - -ESCRIPT_NAME ?= $(PROJECT) -ESCRIPT_COMMENT ?= This is an -*- erlang -*- file - -ESCRIPT_BEAMS ?= "ebin/*", "deps/*/ebin/*" -ESCRIPT_SYS_CONFIG ?= "rel/sys.config" -ESCRIPT_EMU_ARGS ?= -pa . \ - -sasl errlog_type error \ - -escript main $(ESCRIPT_NAME) -ESCRIPT_SHEBANG ?= /usr/bin/env escript -ESCRIPT_STATIC ?= "deps/*/priv/**", "priv/**" - -# Core targets. - -distclean:: distclean-escript - -help:: - $(verbose) printf "%s\n" "" \ - "Escript targets:" \ - " escript Build an executable escript archive" \ - -# Plugin-specific targets. - -# Based on https://github.com/synrc/mad/blob/master/src/mad_bundle.erl -# Copyright (c) 2013 Maxim Sokhatsky, Synrc Research Center -# Modified MIT License, https://github.com/synrc/mad/blob/master/LICENSE : -# Software may only be used for the great good and the true happiness of all -# sentient beings. - -define ESCRIPT_RAW -'Read = fun(F) -> {ok, B} = file:read_file(filename:absname(F)), B end,'\ -'Files = fun(L) -> A = lists:concat([filelib:wildcard(X)||X<- L ]),'\ -' [F || F <- A, not filelib:is_dir(F) ] end,'\ -'Squash = fun(L) -> [{filename:basename(F), Read(F) } || F <- L ] end,'\ -'Zip = fun(A, L) -> {ok,{_,Z}} = zip:create(A, L, [{compress,all},memory]), Z end,'\ -'Ez = fun(Escript) ->'\ -' Static = Files([$(ESCRIPT_STATIC)]),'\ -' Beams = Squash(Files([$(ESCRIPT_BEAMS), $(ESCRIPT_SYS_CONFIG)])),'\ -' Archive = Beams ++ [{ "static.gz", Zip("static.gz", Static)}],'\ -' escript:create(Escript, [ $(ESCRIPT_OPTIONS)'\ -' {archive, Archive, [memory]},'\ -' {shebang, "$(ESCRIPT_SHEBANG)"},'\ -' {comment, "$(ESCRIPT_COMMENT)"},'\ -' {emu_args, " $(ESCRIPT_EMU_ARGS)"}'\ -' ]),'\ -' file:change_mode(Escript, 8#755)'\ -'end,'\ -'Ez("$(ESCRIPT_NAME)"),'\ -'halt().' -endef - -ESCRIPT_COMMAND = $(subst ' ',,$(ESCRIPT_RAW)) - -escript:: distclean-escript deps app - $(gen_verbose) $(ERL) -eval $(ESCRIPT_COMMAND) - -distclean-escript: - $(gen_verbose) rm -f $(ESCRIPT_NAME) - -# Copyright (c) 2014, Enrique Fernandez -# Copyright (c) 2015, Loïc Hoguin -# This file is contributed to erlang.mk and subject to the terms of the ISC License. - -.PHONY: eunit - -# Configuration - -EUNIT_OPTS ?= - -# Core targets. - -tests:: eunit - -help:: - $(verbose) printf "%s\n" "" \ - "EUnit targets:" \ - " eunit Run all the EUnit tests for this project" - -# Plugin-specific targets. - -define eunit.erl - case "$(COVER)" of - "" -> ok; - _ -> - case cover:compile_beam_directory("ebin") of - {error, _} -> halt(1); - _ -> ok - end - end, - case eunit:test([$(call comma_list,$(1))], [$(EUNIT_OPTS)]) of - ok -> ok; - error -> halt(2) - end, - case "$(COVER)" of - "" -> ok; - _ -> - cover:export("eunit.coverdata") - end, - halt() -endef - -EUNIT_EBIN_MODS = $(notdir $(basename $(call core_find,ebin/,*.beam))) -EUNIT_TEST_MODS = $(notdir $(basename $(call core_find,$(TEST_DIR)/,*.beam))) -EUNIT_MODS = $(foreach mod,$(EUNIT_EBIN_MODS) $(filter-out \ - $(patsubst %,%_tests,$(EUNIT_EBIN_MODS)),$(EUNIT_TEST_MODS)),{module,'$(mod)'}) - -eunit: test-build - $(gen_verbose) $(ERL) -pa $(TEST_DIR) $(DEPS_DIR)/*/ebin ebin \ - -eval "$(subst $(newline),,$(subst ",\",$(call eunit.erl,$(EUNIT_MODS))))" - -# Copyright (c) 2013-2015, Loïc Hoguin -# This file is part of erlang.mk and subject to the terms of the ISC License. - -.PHONY: relx-rel distclean-relx-rel distclean-relx run - -# Configuration. - -RELX_CONFIG ?= $(CURDIR)/relx.config - -RELX ?= $(CURDIR)/relx -export RELX - -RELX_URL ?= https://github.com/erlware/relx/releases/download/v2.0.0/relx -RELX_OPTS ?= -RELX_OUTPUT_DIR ?= _rel - -ifeq ($(firstword $(RELX_OPTS)),-o) - RELX_OUTPUT_DIR = $(word 2,$(RELX_OPTS)) -else - RELX_OPTS += -o $(RELX_OUTPUT_DIR) -endif - -# Core targets. - -ifeq ($(IS_DEP),) -ifneq ($(wildcard $(RELX_CONFIG)),) -rel:: distclean-relx-rel relx-rel -endif -endif - -distclean:: distclean-relx-rel distclean-relx - -# Plugin-specific targets. - -$(RELX): - $(gen_verbose) $(call core_http_get,$(RELX),$(RELX_URL)) - $(verbose) chmod +x $(RELX) - -relx-rel: $(RELX) - $(verbose) $(RELX) -c $(RELX_CONFIG) $(RELX_OPTS) - -distclean-relx-rel: - $(gen_verbose) rm -rf $(RELX_OUTPUT_DIR) - -distclean-relx: - $(gen_verbose) rm -rf $(RELX) - -# Run target. - -ifeq ($(wildcard $(RELX_CONFIG)),) -run: -else - -define get_relx_release.erl - {ok, Config} = file:consult("$(RELX_CONFIG)"), - {release, {Name, _}, _} = lists:keyfind(release, 1, Config), - io:format("~s", [Name]), - halt(0). -endef - -RELX_RELEASE = `$(call erlang,$(get_relx_release.erl))` - -run: all - $(verbose) $(RELX_OUTPUT_DIR)/$(RELX_RELEASE)/bin/$(RELX_RELEASE) console - -help:: - $(verbose) printf "%s\n" "" \ - "Relx targets:" \ - " run Compile the project, build the release and run it" - -endif - -# Copyright (c) 2014, M Robert Martin -# This file is contributed to erlang.mk and subject to the terms of the ISC License. - -.PHONY: shell - -# Configuration. - -SHELL_PATH ?= -pa $(CURDIR)/ebin $(DEPS_DIR)/*/ebin -SHELL_OPTS ?= - -ALL_SHELL_DEPS_DIRS = $(addprefix $(DEPS_DIR)/,$(SHELL_DEPS)) - -# Core targets - -help:: - $(verbose) printf "%s\n" "" \ - "Shell targets:" \ - " shell Run an erlang shell with SHELL_OPTS or reasonable default" - -# Plugin-specific targets. - -$(foreach dep,$(SHELL_DEPS),$(eval $(call dep_target,$(dep)))) - -build-shell-deps: $(ALL_SHELL_DEPS_DIRS) - $(verbose) for dep in $(ALL_SHELL_DEPS_DIRS) ; do $(MAKE) -C $$dep ; done - -shell: build-shell-deps - $(gen_verbose) erl $(SHELL_PATH) $(SHELL_OPTS) - -# Copyright (c) 2015, Loïc Hoguin -# This file is part of erlang.mk and subject to the terms of the ISC License. - -ifneq ($(wildcard $(DEPS_DIR)/triq),) -.PHONY: triq - -# Targets. - -tests:: triq - -define triq_check.erl - code:add_pathsa(["$(CURDIR)/ebin", "$(DEPS_DIR)/*/ebin"]), - try - case $(1) of - all -> [true] =:= lists:usort([triq:check(M) || M <- [$(call comma_list,$(3))]]); - module -> triq:check($(2)); - function -> triq:check($(2)) - end - of - true -> halt(0); - _ -> halt(1) - catch error:undef -> - io:format("Undefined property or module~n"), - halt(0) - end. -endef - -ifdef t -ifeq (,$(findstring :,$(t))) -triq: test-build - $(verbose) $(call erlang,$(call triq_check.erl,module,$(t))) -else -triq: test-build - $(verbose) echo Testing $(t)/0 - $(verbose) $(call erlang,$(call triq_check.erl,function,$(t)())) -endif -else -triq: test-build - $(eval MODULES := $(patsubst %,'%',$(sort $(notdir $(basename $(wildcard ebin/*.beam)))))) - $(gen_verbose) $(call erlang,$(call triq_check.erl,all,undefined,$(MODULES))) -endif -endif - -# Copyright (c) 2015, Erlang Solutions Ltd. -# This file is part of erlang.mk and subject to the terms of the ISC License. - -.PHONY: xref distclean-xref - -# Configuration. - -ifeq ($(XREF_CONFIG),) - XREF_ARGS := -else - XREF_ARGS := -c $(XREF_CONFIG) -endif - -XREFR ?= $(CURDIR)/xrefr -export XREFR - -XREFR_URL ?= https://github.com/inaka/xref_runner/releases/download/0.2.2/xrefr - -# Core targets. - -help:: - $(verbose) printf "%s\n" "" \ - "Xref targets:" \ - " xref Run Xrefr using $XREF_CONFIG as config file if defined" - -distclean:: distclean-xref - -# Plugin-specific targets. - -$(XREFR): - $(gen_verbose) $(call core_http_get,$(XREFR),$(XREFR_URL)) - $(verbose) chmod +x $(XREFR) - -xref: deps app $(XREFR) - $(gen_verbose) $(XREFR) $(XREFR_ARGS) - -distclean-xref: - $(gen_verbose) rm -rf $(XREFR) - -# Copyright 2015, Viktor Söderqvist -# This file is part of erlang.mk and subject to the terms of the ISC License. - -COVER_REPORT_DIR = cover - -# Hook in coverage to ct - -ifdef COVER -ifdef CT_RUN -# All modules in 'ebin' -COVER_MODS = $(notdir $(basename $(call core_ls,ebin/*.beam))) - -test-build:: $(TEST_DIR)/ct.cover.spec - -$(TEST_DIR)/ct.cover.spec: - $(verbose) echo Cover mods: $(COVER_MODS) - $(gen_verbose) printf "%s\n" \ - '{incl_mods,[$(subst $(space),$(comma),$(COVER_MODS))]}.' \ - '{export,"$(CURDIR)/ct.coverdata"}.' > $@ - -CT_RUN += -cover $(TEST_DIR)/ct.cover.spec -endif -endif - -# Core targets - -ifdef COVER -ifneq ($(COVER_REPORT_DIR),) -tests:: - $(verbose) $(MAKE) --no-print-directory cover-report -endif -endif - -clean:: coverdata-clean - -ifneq ($(COVER_REPORT_DIR),) -distclean:: cover-report-clean -endif - -help:: - $(verbose) printf "%s\n" "" \ - "Cover targets:" \ - " cover-report Generate a HTML coverage report from previously collected" \ - " cover data." \ - " all.coverdata Merge {eunit,ct}.coverdata into one coverdata file." \ - "" \ - "If COVER=1 is set, coverage data is generated by the targets eunit and ct. The" \ - "target tests additionally generates a HTML coverage report from the combined" \ - "coverdata files from each of these testing tools. HTML reports can be disabled" \ - "by setting COVER_REPORT_DIR to empty." - -# Plugin specific targets - -COVERDATA = $(filter-out all.coverdata,$(wildcard *.coverdata)) - -.PHONY: coverdata-clean -coverdata-clean: - $(gen_verbose) rm -f *.coverdata ct.cover.spec - -# Merge all coverdata files into one. -all.coverdata: $(COVERDATA) - $(gen_verbose) $(ERL) -eval ' \ - $(foreach f,$(COVERDATA),cover:import("$(f)") == ok orelse halt(1),) \ - cover:export("$@"), halt(0).' - -# These are only defined if COVER_REPORT_DIR is non-empty. Set COVER_REPORT_DIR to -# empty if you want the coverdata files but not the HTML report. -ifneq ($(COVER_REPORT_DIR),) - -.PHONY: cover-report-clean cover-report - -cover-report-clean: - $(gen_verbose) rm -rf $(COVER_REPORT_DIR) - -ifeq ($(COVERDATA),) -cover-report: -else - -# Modules which include eunit.hrl always contain one line without coverage -# because eunit defines test/0 which is never called. We compensate for this. -EUNIT_HRL_MODS = $(subst $(space),$(comma),$(shell \ - grep -e '^\s*-include.*include/eunit\.hrl"' src/*.erl \ - | sed "s/^src\/\(.*\)\.erl:.*/'\1'/" | uniq)) - -define cover_report.erl - $(foreach f,$(COVERDATA),cover:import("$(f)") == ok orelse halt(1),) - Ms = cover:imported_modules(), - [cover:analyse_to_file(M, "$(COVER_REPORT_DIR)/" ++ atom_to_list(M) - ++ ".COVER.html", [html]) || M <- Ms], - Report = [begin {ok, R} = cover:analyse(M, module), R end || M <- Ms], - EunitHrlMods = [$(EUNIT_HRL_MODS)], - Report1 = [{M, {Y, case lists:member(M, EunitHrlMods) of - true -> N - 1; false -> N end}} || {M, {Y, N}} <- Report], - TotalY = lists:sum([Y || {_, {Y, _}} <- Report1]), - TotalN = lists:sum([N || {_, {_, N}} <- Report1]), - TotalPerc = round(100 * TotalY / (TotalY + TotalN)), - {ok, F} = file:open("$(COVER_REPORT_DIR)/index.html", [write]), - io:format(F, "~n" - "~n" - "Coverage report~n" - "~n", []), - io:format(F, "

Coverage

~n

Total: ~p%

~n", [TotalPerc]), - io:format(F, "~n", []), - [io:format(F, "" - "~n", - [M, M, round(100 * Y / (Y + N))]) || {M, {Y, N}} <- Report1], - How = "$(subst $(space),$(comma)$(space),$(basename $(COVERDATA)))", - Date = "$(shell date -u "+%Y-%m-%dT%H:%M:%SZ")", - io:format(F, "
ModuleCoverage
~p~p%
~n" - "

Generated using ~s and erlang.mk on ~s.

~n" - "", [How, Date]), - halt(). -endef - -cover-report: - $(gen_verbose) mkdir -p $(COVER_REPORT_DIR) - $(gen_verbose) $(call erlang,$(cover_report.erl)) - -endif -endif # ifneq ($(COVER_REPORT_DIR),) DELETED deps/cowboy/rebar.config Index: deps/cowboy/rebar.config ================================================================== --- deps/cowboy/rebar.config +++ /dev/null @@ -1,4 +0,0 @@ -{deps, [ - {cowlib, ".*", {git, "https://github.com/ninenines/cowlib.git", "1.0.0"}}, - {ranch, ".*", {git, "https://github.com/ninenines/ranch.git", "1.0.0"}} -]}. DELETED deps/cowboy/src/cowboy.app.src Index: deps/cowboy/src/cowboy.app.src ================================================================== --- deps/cowboy/src/cowboy.app.src +++ /dev/null @@ -1,30 +0,0 @@ -%% Copyright (c) 2011-2014, Loïc Hoguin -%% -%% Permission to use, copy, modify, and/or distribute this software for any -%% purpose with or without fee is hereby granted, provided that the above -%% copyright notice and this permission notice appear in all copies. -%% -%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -{application, cowboy, [ - {description, "Small, fast, modular HTTP server."}, - {vsn, "1.0.4"}, - {id, "git"}, - {modules, []}, - {registered, [cowboy_clock, cowboy_sup]}, - {applications, [ - kernel, - stdlib, - ranch, - cowlib, - crypto - ]}, - {mod, {cowboy_app, []}}, - {env, []} -]}. DELETED deps/cowboy/src/cowboy.erl Index: deps/cowboy/src/cowboy.erl ================================================================== --- deps/cowboy/src/cowboy.erl +++ /dev/null @@ -1,75 +0,0 @@ -%% Copyright (c) 2011-2014, Loïc Hoguin -%% -%% Permission to use, copy, modify, and/or distribute this software for any -%% purpose with or without fee is hereby granted, provided that the above -%% copyright notice and this permission notice appear in all copies. -%% -%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - --module(cowboy). - --export([start_http/4]). --export([start_https/4]). --export([start_spdy/4]). --export([stop_listener/1]). --export([set_env/3]). - --type http_headers() :: [{binary(), iodata()}]. --export_type([http_headers/0]). - --type http_status() :: non_neg_integer() | binary(). --export_type([http_status/0]). - --type http_version() :: 'HTTP/1.1' | 'HTTP/1.0'. --export_type([http_version/0]). - --type onrequest_fun() :: fun((Req) -> Req). --export_type([onrequest_fun/0]). - --type onresponse_fun() :: - fun((http_status(), http_headers(), iodata(), Req) -> Req). --export_type([onresponse_fun/0]). - --spec start_http(ranch:ref(), non_neg_integer(), ranch_tcp:opts(), - cowboy_protocol:opts()) -> {ok, pid()} | {error, any()}. -start_http(Ref, NbAcceptors, TransOpts, ProtoOpts) - when is_integer(NbAcceptors), NbAcceptors > 0 -> - ranch:start_listener(Ref, NbAcceptors, - ranch_tcp, TransOpts, cowboy_protocol, ProtoOpts). - --spec start_https(ranch:ref(), non_neg_integer(), ranch_ssl:opts(), - cowboy_protocol:opts()) -> {ok, pid()} | {error, any()}. -start_https(Ref, NbAcceptors, TransOpts, ProtoOpts) - when is_integer(NbAcceptors), NbAcceptors > 0 -> - ranch:start_listener(Ref, NbAcceptors, - ranch_ssl, TransOpts, cowboy_protocol, ProtoOpts). - --spec start_spdy(ranch:ref(), non_neg_integer(), ranch_ssl:opts(), - cowboy_spdy:opts()) -> {ok, pid()} | {error, any()}. -start_spdy(Ref, NbAcceptors, TransOpts, ProtoOpts) - when is_integer(NbAcceptors), NbAcceptors > 0 -> - TransOpts2 = [ - {connection_type, supervisor}, - {next_protocols_advertised, - [<<"spdy/3">>, <<"http/1.1">>, <<"http/1.0">>]} - |TransOpts], - ranch:start_listener(Ref, NbAcceptors, - ranch_ssl, TransOpts2, cowboy_spdy, ProtoOpts). - --spec stop_listener(ranch:ref()) -> ok | {error, not_found}. -stop_listener(Ref) -> - ranch:stop_listener(Ref). - --spec set_env(ranch:ref(), atom(), any()) -> ok. -set_env(Ref, Name, Value) -> - Opts = ranch:get_protocol_options(Ref), - {_, Env} = lists:keyfind(env, 1, Opts), - Opts2 = lists:keyreplace(env, 1, Opts, - {env, lists:keystore(Name, 1, Env, {Name, Value})}), - ok = ranch:set_protocol_options(Ref, Opts2). DELETED deps/cowboy/src/cowboy_app.erl Index: deps/cowboy/src/cowboy_app.erl ================================================================== --- deps/cowboy/src/cowboy_app.erl +++ /dev/null @@ -1,27 +0,0 @@ -%% Copyright (c) 2011-2014, Loïc Hoguin -%% -%% Permission to use, copy, modify, and/or distribute this software for any -%% purpose with or without fee is hereby granted, provided that the above -%% copyright notice and this permission notice appear in all copies. -%% -%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - --module(cowboy_app). --behaviour(application). - --export([start/2]). --export([stop/1]). - --spec start(_, _) -> {ok, pid()}. -start(_, _) -> - cowboy_sup:start_link(). - --spec stop(_) -> ok. -stop(_) -> - ok. DELETED deps/cowboy/src/cowboy_bstr.erl Index: deps/cowboy/src/cowboy_bstr.erl ================================================================== --- deps/cowboy/src/cowboy_bstr.erl +++ /dev/null @@ -1,123 +0,0 @@ -%% Copyright (c) 2011-2014, Loïc Hoguin -%% -%% Permission to use, copy, modify, and/or distribute this software for any -%% purpose with or without fee is hereby granted, provided that the above -%% copyright notice and this permission notice appear in all copies. -%% -%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - --module(cowboy_bstr). - -%% Binary strings. --export([capitalize_token/1]). --export([to_lower/1]). --export([to_upper/1]). - -%% Characters. --export([char_to_lower/1]). --export([char_to_upper/1]). - -%% The first letter and all letters after a dash are capitalized. -%% This is the form seen for header names in the HTTP/1.1 RFC and -%% others. Note that using this form isn't required, as header names -%% are case insensitive, and it is only provided for use with eventual -%% badly implemented clients. --spec capitalize_token(B) -> B when B::binary(). -capitalize_token(B) -> - capitalize_token(B, true, <<>>). -capitalize_token(<<>>, _, Acc) -> - Acc; -capitalize_token(<< $-, Rest/bits >>, _, Acc) -> - capitalize_token(Rest, true, << Acc/binary, $- >>); -capitalize_token(<< C, Rest/bits >>, true, Acc) -> - capitalize_token(Rest, false, << Acc/binary, (char_to_upper(C)) >>); -capitalize_token(<< C, Rest/bits >>, false, Acc) -> - capitalize_token(Rest, false, << Acc/binary, (char_to_lower(C)) >>). - --spec to_lower(B) -> B when B::binary(). -to_lower(B) -> - << << (char_to_lower(C)) >> || << C >> <= B >>. - --spec to_upper(B) -> B when B::binary(). -to_upper(B) -> - << << (char_to_upper(C)) >> || << C >> <= B >>. - --spec char_to_lower(char()) -> char(). -char_to_lower($A) -> $a; -char_to_lower($B) -> $b; -char_to_lower($C) -> $c; -char_to_lower($D) -> $d; -char_to_lower($E) -> $e; -char_to_lower($F) -> $f; -char_to_lower($G) -> $g; -char_to_lower($H) -> $h; -char_to_lower($I) -> $i; -char_to_lower($J) -> $j; -char_to_lower($K) -> $k; -char_to_lower($L) -> $l; -char_to_lower($M) -> $m; -char_to_lower($N) -> $n; -char_to_lower($O) -> $o; -char_to_lower($P) -> $p; -char_to_lower($Q) -> $q; -char_to_lower($R) -> $r; -char_to_lower($S) -> $s; -char_to_lower($T) -> $t; -char_to_lower($U) -> $u; -char_to_lower($V) -> $v; -char_to_lower($W) -> $w; -char_to_lower($X) -> $x; -char_to_lower($Y) -> $y; -char_to_lower($Z) -> $z; -char_to_lower(Ch) -> Ch. - --spec char_to_upper(char()) -> char(). -char_to_upper($a) -> $A; -char_to_upper($b) -> $B; -char_to_upper($c) -> $C; -char_to_upper($d) -> $D; -char_to_upper($e) -> $E; -char_to_upper($f) -> $F; -char_to_upper($g) -> $G; -char_to_upper($h) -> $H; -char_to_upper($i) -> $I; -char_to_upper($j) -> $J; -char_to_upper($k) -> $K; -char_to_upper($l) -> $L; -char_to_upper($m) -> $M; -char_to_upper($n) -> $N; -char_to_upper($o) -> $O; -char_to_upper($p) -> $P; -char_to_upper($q) -> $Q; -char_to_upper($r) -> $R; -char_to_upper($s) -> $S; -char_to_upper($t) -> $T; -char_to_upper($u) -> $U; -char_to_upper($v) -> $V; -char_to_upper($w) -> $W; -char_to_upper($x) -> $X; -char_to_upper($y) -> $Y; -char_to_upper($z) -> $Z; -char_to_upper(Ch) -> Ch. - -%% Tests. - --ifdef(TEST). -capitalize_token_test_() -> - Tests = [ - {<<"heLLo-woRld">>, <<"Hello-World">>}, - {<<"Sec-Websocket-Version">>, <<"Sec-Websocket-Version">>}, - {<<"Sec-WebSocket-Version">>, <<"Sec-Websocket-Version">>}, - {<<"sec-websocket-version">>, <<"Sec-Websocket-Version">>}, - {<<"SEC-WEBSOCKET-VERSION">>, <<"Sec-Websocket-Version">>}, - {<<"Sec-WebSocket--Version">>, <<"Sec-Websocket--Version">>}, - {<<"Sec-WebSocket---Version">>, <<"Sec-Websocket---Version">>} - ], - [{H, fun() -> R = capitalize_token(H) end} || {H, R} <- Tests]. --endif. DELETED deps/cowboy/src/cowboy_clock.erl Index: deps/cowboy/src/cowboy_clock.erl ================================================================== --- deps/cowboy/src/cowboy_clock.erl +++ /dev/null @@ -1,213 +0,0 @@ -%% Copyright (c) 2011-2014, Loïc Hoguin -%% -%% Permission to use, copy, modify, and/or distribute this software for any -%% purpose with or without fee is hereby granted, provided that the above -%% copyright notice and this permission notice appear in all copies. -%% -%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -%% While a gen_server process runs in the background to update -%% the cache of formatted dates every second, all API calls are -%% local and directly read from the ETS cache table, providing -%% fast time and date computations. --module(cowboy_clock). --behaviour(gen_server). - -%% API. --export([start_link/0]). --export([stop/0]). --export([rfc1123/0]). --export([rfc1123/1]). - -%% gen_server. --export([init/1]). --export([handle_call/3]). --export([handle_cast/2]). --export([handle_info/2]). --export([terminate/2]). --export([code_change/3]). - --record(state, { - universaltime = undefined :: undefined | calendar:datetime(), - rfc1123 = <<>> :: binary(), - tref = undefined :: undefined | reference() -}). - -%% API. - --spec start_link() -> {ok, pid()}. -start_link() -> - gen_server:start_link({local, ?MODULE}, ?MODULE, [], []). - --spec stop() -> stopped. -stop() -> - gen_server:call(?MODULE, stop). - --spec rfc1123() -> binary(). -rfc1123() -> - ets:lookup_element(?MODULE, rfc1123, 2). - --spec rfc1123(calendar:datetime()) -> binary(). -rfc1123(DateTime) -> - update_rfc1123(<<>>, undefined, DateTime). - -%% gen_server. - --spec init([]) -> {ok, #state{}}. -init([]) -> - ?MODULE = ets:new(?MODULE, [set, protected, - named_table, {read_concurrency, true}]), - T = erlang:universaltime(), - B = update_rfc1123(<<>>, undefined, T), - TRef = erlang:send_after(1000, self(), update), - ets:insert(?MODULE, {rfc1123, B}), - {ok, #state{universaltime=T, rfc1123=B, tref=TRef}}. - --type from() :: {pid(), term()}. --spec handle_call - (stop, from(), State) -> {stop, normal, stopped, State} - when State::#state{}. -handle_call(stop, _From, State) -> - {stop, normal, stopped, State}; -handle_call(_Request, _From, State) -> - {reply, ignored, State}. - --spec handle_cast(_, State) -> {noreply, State} when State::#state{}. -handle_cast(_Msg, State) -> - {noreply, State}. - --spec handle_info(any(), State) -> {noreply, State} when State::#state{}. -handle_info(update, #state{universaltime=Prev, rfc1123=B1, tref=TRef0}) -> - %% Cancel the timer in case an external process sent an update message. - _ = erlang:cancel_timer(TRef0), - T = erlang:universaltime(), - B2 = update_rfc1123(B1, Prev, T), - ets:insert(?MODULE, {rfc1123, B2}), - TRef = erlang:send_after(1000, self(), update), - {noreply, #state{universaltime=T, rfc1123=B2, tref=TRef}}; -handle_info(_Info, State) -> - {noreply, State}. - --spec terminate(_, _) -> ok. -terminate(_Reason, _State) -> - ok. - --spec code_change(_, State, _) -> {ok, State} when State::#state{}. -code_change(_OldVsn, State, _Extra) -> - {ok, State}. - -%% Internal. - --spec update_rfc1123(binary(), undefined | calendar:datetime(), - calendar:datetime()) -> binary(). -update_rfc1123(Bin, Now, Now) -> - Bin; -update_rfc1123(<< Keep:23/binary, _/bits >>, - {Date, {H, M, _}}, {Date, {H, M, S}}) -> - << Keep/binary, (pad_int(S))/binary, " GMT" >>; -update_rfc1123(<< Keep:20/binary, _/bits >>, - {Date, {H, _, _}}, {Date, {H, M, S}}) -> - << Keep/binary, (pad_int(M))/binary, $:, (pad_int(S))/binary, " GMT" >>; -update_rfc1123(<< Keep:17/binary, _/bits >>, {Date, _}, {Date, {H, M, S}}) -> - << Keep/binary, (pad_int(H))/binary, $:, (pad_int(M))/binary, - $:, (pad_int(S))/binary, " GMT" >>; -update_rfc1123(<< _:7/binary, Keep:10/binary, _/bits >>, - {{Y, Mo, _}, _}, {Date = {Y, Mo, D}, {H, M, S}}) -> - Wday = calendar:day_of_the_week(Date), - << (weekday(Wday))/binary, ", ", (pad_int(D))/binary, Keep/binary, - (pad_int(H))/binary, $:, (pad_int(M))/binary, - $:, (pad_int(S))/binary, " GMT" >>; -update_rfc1123(<< _:11/binary, Keep:6/binary, _/bits >>, - {{Y, _, _}, _}, {Date = {Y, Mo, D}, {H, M, S}}) -> - Wday = calendar:day_of_the_week(Date), - << (weekday(Wday))/binary, ", ", (pad_int(D))/binary, " ", - (month(Mo))/binary, Keep/binary, - (pad_int(H))/binary, $:, (pad_int(M))/binary, - $:, (pad_int(S))/binary, " GMT" >>; -update_rfc1123(_, _, {Date = {Y, Mo, D}, {H, M, S}}) -> - Wday = calendar:day_of_the_week(Date), - << (weekday(Wday))/binary, ", ", (pad_int(D))/binary, " ", - (month(Mo))/binary, " ", (integer_to_binary(Y))/binary, - " ", (pad_int(H))/binary, $:, (pad_int(M))/binary, - $:, (pad_int(S))/binary, " GMT" >>. - -%% Following suggestion by MononcQc on #erlounge. --spec pad_int(0..59) -> binary(). -pad_int(X) when X < 10 -> - << $0, ($0 + X) >>; -pad_int(X) -> - integer_to_binary(X). - --spec weekday(1..7) -> <<_:24>>. -weekday(1) -> <<"Mon">>; -weekday(2) -> <<"Tue">>; -weekday(3) -> <<"Wed">>; -weekday(4) -> <<"Thu">>; -weekday(5) -> <<"Fri">>; -weekday(6) -> <<"Sat">>; -weekday(7) -> <<"Sun">>. - --spec month(1..12) -> <<_:24>>. -month( 1) -> <<"Jan">>; -month( 2) -> <<"Feb">>; -month( 3) -> <<"Mar">>; -month( 4) -> <<"Apr">>; -month( 5) -> <<"May">>; -month( 6) -> <<"Jun">>; -month( 7) -> <<"Jul">>; -month( 8) -> <<"Aug">>; -month( 9) -> <<"Sep">>; -month(10) -> <<"Oct">>; -month(11) -> <<"Nov">>; -month(12) -> <<"Dec">>. - -%% Tests. - --ifdef(TEST). -update_rfc1123_test_() -> - Tests = [ - {<<"Sat, 14 May 2011 14:25:33 GMT">>, undefined, - {{2011, 5, 14}, {14, 25, 33}}, <<>>}, - {<<"Sat, 14 May 2011 14:25:33 GMT">>, {{2011, 5, 14}, {14, 25, 33}}, - {{2011, 5, 14}, {14, 25, 33}}, <<"Sat, 14 May 2011 14:25:33 GMT">>}, - {<<"Sat, 14 May 2011 14:25:34 GMT">>, {{2011, 5, 14}, {14, 25, 33}}, - {{2011, 5, 14}, {14, 25, 34}}, <<"Sat, 14 May 2011 14:25:33 GMT">>}, - {<<"Sat, 14 May 2011 14:26:00 GMT">>, {{2011, 5, 14}, {14, 25, 59}}, - {{2011, 5, 14}, {14, 26, 0}}, <<"Sat, 14 May 2011 14:25:59 GMT">>}, - {<<"Sat, 14 May 2011 15:00:00 GMT">>, {{2011, 5, 14}, {14, 59, 59}}, - {{2011, 5, 14}, {15, 0, 0}}, <<"Sat, 14 May 2011 14:59:59 GMT">>}, - {<<"Sun, 15 May 2011 00:00:00 GMT">>, {{2011, 5, 14}, {23, 59, 59}}, - {{2011, 5, 15}, { 0, 0, 0}}, <<"Sat, 14 May 2011 23:59:59 GMT">>}, - {<<"Wed, 01 Jun 2011 00:00:00 GMT">>, {{2011, 5, 31}, {23, 59, 59}}, - {{2011, 6, 1}, { 0, 0, 0}}, <<"Tue, 31 May 2011 23:59:59 GMT">>}, - {<<"Sun, 01 Jan 2012 00:00:00 GMT">>, {{2011, 5, 31}, {23, 59, 59}}, - {{2012, 1, 1}, { 0, 0, 0}}, <<"Sat, 31 Dec 2011 23:59:59 GMT">>} - ], - [{R, fun() -> R = update_rfc1123(B, P, N) end} || {R, P, N, B} <- Tests]. - -pad_int_test_() -> - Tests = [ - { 0, <<"00">>}, { 1, <<"01">>}, { 2, <<"02">>}, { 3, <<"03">>}, - { 4, <<"04">>}, { 5, <<"05">>}, { 6, <<"06">>}, { 7, <<"07">>}, - { 8, <<"08">>}, { 9, <<"09">>}, {10, <<"10">>}, {11, <<"11">>}, - {12, <<"12">>}, {13, <<"13">>}, {14, <<"14">>}, {15, <<"15">>}, - {16, <<"16">>}, {17, <<"17">>}, {18, <<"18">>}, {19, <<"19">>}, - {20, <<"20">>}, {21, <<"21">>}, {22, <<"22">>}, {23, <<"23">>}, - {24, <<"24">>}, {25, <<"25">>}, {26, <<"26">>}, {27, <<"27">>}, - {28, <<"28">>}, {29, <<"29">>}, {30, <<"30">>}, {31, <<"31">>}, - {32, <<"32">>}, {33, <<"33">>}, {34, <<"34">>}, {35, <<"35">>}, - {36, <<"36">>}, {37, <<"37">>}, {38, <<"38">>}, {39, <<"39">>}, - {40, <<"40">>}, {41, <<"41">>}, {42, <<"42">>}, {43, <<"43">>}, - {44, <<"44">>}, {45, <<"45">>}, {46, <<"46">>}, {47, <<"47">>}, - {48, <<"48">>}, {49, <<"49">>}, {50, <<"50">>}, {51, <<"51">>}, - {52, <<"52">>}, {53, <<"53">>}, {54, <<"54">>}, {55, <<"55">>}, - {56, <<"56">>}, {57, <<"57">>}, {58, <<"58">>}, {59, <<"59">>} - ], - [{I, fun() -> O = pad_int(I) end} || {I, O} <- Tests]. --endif. DELETED deps/cowboy/src/cowboy_handler.erl Index: deps/cowboy/src/cowboy_handler.erl ================================================================== --- deps/cowboy/src/cowboy_handler.erl +++ /dev/null @@ -1,304 +0,0 @@ -%% Copyright (c) 2011-2014, Loïc Hoguin -%% -%% Permission to use, copy, modify, and/or distribute this software for any -%% purpose with or without fee is hereby granted, provided that the above -%% copyright notice and this permission notice appear in all copies. -%% -%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -%% Handler middleware. -%% -%% Execute the handler given by the handler and handler_opts -%% environment values. The result of this execution is added to the -%% environment under the result value. -%% -%% When using loop handlers, we are receiving data from the socket because we -%% want to know when the socket gets closed. This is generally not an issue -%% because these kinds of requests are generally not pipelined, and don't have -%% a body. If they do have a body, this body is often read in the -%% init/3 callback and this is no problem. Otherwise, this data -%% accumulates in a buffer until we reach a certain threshold of 5000 bytes -%% by default. This can be configured through the loop_max_buffer -%% environment value. The request will be terminated with an -%% {error, overflow} reason if this threshold is reached. --module(cowboy_handler). --behaviour(cowboy_middleware). - --export([execute/2]). --export([handler_loop/4]). - --record(state, { - env :: cowboy_middleware:env(), - hibernate = false :: boolean(), - loop_buffer_size = 0 :: non_neg_integer(), - loop_max_buffer = 5000 :: non_neg_integer() | infinity, - loop_timeout = infinity :: timeout(), - loop_timeout_ref = undefined :: undefined | reference(), - resp_sent = false :: boolean() -}). - --spec execute(Req, Env) - -> {ok, Req, Env} | {suspend, ?MODULE, handler_loop, [any()]} - when Req::cowboy_req:req(), Env::cowboy_middleware:env(). -execute(Req, Env) -> - {_, Handler} = lists:keyfind(handler, 1, Env), - {_, HandlerOpts} = lists:keyfind(handler_opts, 1, Env), - MaxBuffer = case lists:keyfind(loop_max_buffer, 1, Env) of - false -> 5000; - {_, MaxBuffer0} -> MaxBuffer0 - end, - handler_init(Req, #state{env=Env, loop_max_buffer=MaxBuffer}, - Handler, HandlerOpts). - --spec handler_init(Req, #state{}, module(), any()) - -> {ok, Req, cowboy_middleware:env()} | {suspend, module(), atom(), [any()]} - when Req::cowboy_req:req(). -handler_init(Req, State, Handler, HandlerOpts) -> - Transport = cowboy_req:get(transport, Req), - try Handler:init({Transport:name(), http}, Req, HandlerOpts) of - {ok, Req2, HandlerState} -> - handler_handle(Req2, State, Handler, HandlerState); - {loop, Req2, HandlerState} -> - handler_after_callback(Req2, State, Handler, HandlerState); - {loop, Req2, HandlerState, hibernate} -> - handler_after_callback(Req2, State#state{hibernate=true}, - Handler, HandlerState); - {loop, Req2, HandlerState, Timeout} -> - State2 = handler_loop_timeout(State#state{loop_timeout=Timeout}), - handler_after_callback(Req2, State2, Handler, HandlerState); - {loop, Req2, HandlerState, Timeout, hibernate} -> - State2 = handler_loop_timeout(State#state{ - hibernate=true, loop_timeout=Timeout}), - handler_after_callback(Req2, State2, Handler, HandlerState); - {shutdown, Req2, HandlerState} -> - terminate_request(Req2, State, Handler, HandlerState, - {normal, shutdown}); - {upgrade, protocol, Module} -> - upgrade_protocol(Req, State, Handler, HandlerOpts, Module); - {upgrade, protocol, Module, Req2, HandlerOpts2} -> - upgrade_protocol(Req2, State, Handler, HandlerOpts2, Module) - catch Class:Reason -> - Stacktrace = erlang:get_stacktrace(), - cowboy_req:maybe_reply(Stacktrace, Req), - erlang:Class([ - {reason, Reason}, - {mfa, {Handler, init, 3}}, - {stacktrace, Stacktrace}, - {req, cowboy_req:to_list(Req)}, - {opts, HandlerOpts} - ]) - end. - --spec upgrade_protocol(Req, #state{}, module(), any(), module()) - -> {ok, Req, Env} - | {suspend, module(), atom(), any()} - | {halt, Req} - | {error, cowboy:http_status(), Req} - when Req::cowboy_req:req(), Env::cowboy_middleware:env(). -upgrade_protocol(Req, #state{env=Env}, - Handler, HandlerOpts, Module) -> - Module:upgrade(Req, Env, Handler, HandlerOpts). - --spec handler_handle(Req, #state{}, module(), any()) - -> {ok, Req, cowboy_middleware:env()} when Req::cowboy_req:req(). -handler_handle(Req, State, Handler, HandlerState) -> - try Handler:handle(Req, HandlerState) of - {ok, Req2, HandlerState2} -> - terminate_request(Req2, State, Handler, HandlerState2, - {normal, shutdown}) - catch Class:Reason -> - Stacktrace = erlang:get_stacktrace(), - cowboy_req:maybe_reply(Stacktrace, Req), - handler_terminate(Req, Handler, HandlerState, Reason), - erlang:Class([ - {reason, Reason}, - {mfa, {Handler, handle, 2}}, - {stacktrace, Stacktrace}, - {req, cowboy_req:to_list(Req)}, - {state, HandlerState} - ]) - end. - -%% Update the state if the response was sent in the callback. --spec handler_after_callback(Req, #state{}, module(), any()) - -> {ok, Req, cowboy_middleware:env()} | {suspend, module(), atom(), [any()]} - when Req::cowboy_req:req(). -handler_after_callback(Req, State=#state{resp_sent=false}, Handler, - HandlerState) -> - receive - {cowboy_req, resp_sent} -> - handler_before_loop(Req, State#state{resp_sent=true}, Handler, - HandlerState) - after 0 -> - handler_before_loop(Req, State, Handler, HandlerState) - end; -handler_after_callback(Req, State, Handler, HandlerState) -> - handler_before_loop(Req, State, Handler, HandlerState). - --spec handler_before_loop(Req, #state{}, module(), any()) - -> {ok, Req, cowboy_middleware:env()} | {suspend, module(), atom(), [any()]} - when Req::cowboy_req:req(). -handler_before_loop(Req, State=#state{hibernate=true}, Handler, HandlerState) -> - [Socket, Transport] = cowboy_req:get([socket, transport], Req), - Transport:setopts(Socket, [{active, once}]), - {suspend, ?MODULE, handler_loop, - [Req, State#state{hibernate=false}, Handler, HandlerState]}; -handler_before_loop(Req, State, Handler, HandlerState) -> - [Socket, Transport] = cowboy_req:get([socket, transport], Req), - Transport:setopts(Socket, [{active, once}]), - handler_loop(Req, State, Handler, HandlerState). - -%% Almost the same code can be found in cowboy_websocket. --spec handler_loop_timeout(#state{}) -> #state{}. -handler_loop_timeout(State=#state{loop_timeout=infinity}) -> - State#state{loop_timeout_ref=undefined}; -handler_loop_timeout(State=#state{loop_timeout=Timeout, - loop_timeout_ref=PrevRef}) -> - _ = case PrevRef of - undefined -> ignore; - PrevRef -> erlang:cancel_timer(PrevRef) - end, - TRef = erlang:start_timer(Timeout, self(), ?MODULE), - State#state{loop_timeout_ref=TRef}. - --spec handler_loop(Req, #state{}, module(), any()) - -> {ok, Req, cowboy_middleware:env()} | {suspend, module(), atom(), [any()]} - when Req::cowboy_req:req(). -handler_loop(Req, State=#state{loop_buffer_size=NbBytes, - loop_max_buffer=Threshold, loop_timeout_ref=TRef, - resp_sent=RespSent}, Handler, HandlerState) -> - [Socket, Transport] = cowboy_req:get([socket, transport], Req), - {OK, Closed, Error} = Transport:messages(), - receive - {OK, Socket, Data} -> - NbBytes2 = NbBytes + byte_size(Data), - if NbBytes2 > Threshold -> - _ = handler_terminate(Req, Handler, HandlerState, - {error, overflow}), - _ = if RespSent -> ok; true -> - cowboy_req:reply(500, Req) - end, - exit(normal); - true -> - Req2 = cowboy_req:append_buffer(Data, Req), - State2 = handler_loop_timeout(State#state{ - loop_buffer_size=NbBytes2}), - handler_before_loop(Req2, State2, Handler, HandlerState) - end; - {Closed, Socket} -> - terminate_request(Req, State, Handler, HandlerState, - {error, closed}); - {Error, Socket, Reason} -> - terminate_request(Req, State, Handler, HandlerState, - {error, Reason}); - {timeout, TRef, ?MODULE} -> - handler_after_loop(Req, State, Handler, HandlerState, - {normal, timeout}); - {timeout, OlderTRef, ?MODULE} when is_reference(OlderTRef) -> - handler_loop(Req, State, Handler, HandlerState); - Message -> - %% We set the socket back to {active, false} mode in case - %% the handler is going to call recv. We also flush any - %% data received after that and put it into the buffer. - %% We do not check the size here, if data keeps coming - %% we'll error out on the next packet received. - Transport:setopts(Socket, [{active, false}]), - Req2 = receive {OK, Socket, Data} -> - cowboy_req:append_buffer(Data, Req) - after 0 -> - Req - end, - handler_call(Req2, State, Handler, HandlerState, Message) - end. - --spec handler_call(Req, #state{}, module(), any(), any()) - -> {ok, Req, cowboy_middleware:env()} | {suspend, module(), atom(), [any()]} - when Req::cowboy_req:req(). -handler_call(Req, State=#state{resp_sent=RespSent}, - Handler, HandlerState, Message) -> - try Handler:info(Message, Req, HandlerState) of - {ok, Req2, HandlerState2} -> - handler_after_loop(Req2, State, Handler, HandlerState2, - {normal, shutdown}); - {loop, Req2, HandlerState2} -> - handler_after_callback(Req2, State, Handler, HandlerState2); - {loop, Req2, HandlerState2, hibernate} -> - handler_after_callback(Req2, State#state{hibernate=true}, - Handler, HandlerState2) - catch Class:Reason -> - Stacktrace = erlang:get_stacktrace(), - if RespSent -> ok; true -> - cowboy_req:maybe_reply(Stacktrace, Req) - end, - handler_terminate(Req, Handler, HandlerState, Reason), - erlang:Class([ - {reason, Reason}, - {mfa, {Handler, info, 3}}, - {stacktrace, Stacktrace}, - {req, cowboy_req:to_list(Req)}, - {state, HandlerState} - ]) - end. - -%% It is sometimes important to make a socket passive as it was initially -%% and as it is expected to be by cowboy_protocol, right after we're done -%% with loop handling. The browser may freely pipeline a bunch of requests -%% if previous one was, say, a JSONP long-polling request. --spec handler_after_loop(Req, #state{}, module(), any(), - {normal, timeout | shutdown} | {error, atom()}) -> - {ok, Req, cowboy_middleware:env()} when Req::cowboy_req:req(). -handler_after_loop(Req, State, Handler, HandlerState, Reason) -> - [Socket, Transport] = cowboy_req:get([socket, transport], Req), - Transport:setopts(Socket, [{active, false}]), - {OK, _Closed, _Error} = Transport:messages(), - Req2 = receive - {OK, Socket, Data} -> - cowboy_req:append_buffer(Data, Req) - after 0 -> - Req - end, - terminate_request(Req2, State, Handler, HandlerState, Reason). - --spec terminate_request(Req, #state{}, module(), any(), - {normal, timeout | shutdown} | {error, atom()}) -> - {ok, Req, cowboy_middleware:env()} when Req::cowboy_req:req(). -terminate_request(Req, #state{env=Env, loop_timeout_ref=TRef}, - Handler, HandlerState, Reason) -> - HandlerRes = handler_terminate(Req, Handler, HandlerState, Reason), - _ = case TRef of - undefined -> ignore; - TRef -> erlang:cancel_timer(TRef) - end, - flush_timeouts(), - {ok, Req, [{result, HandlerRes}|Env]}. - --spec handler_terminate(cowboy_req:req(), module(), any(), - {normal, timeout | shutdown} | {error, atom()}) -> ok. -handler_terminate(Req, Handler, HandlerState, Reason) -> - try - Handler:terminate(Reason, cowboy_req:lock(Req), HandlerState) - catch Class:Reason2 -> - erlang:Class([ - {reason, Reason2}, - {mfa, {Handler, terminate, 3}}, - {stacktrace, erlang:get_stacktrace()}, - {req, cowboy_req:to_list(Req)}, - {state, HandlerState}, - {terminate_reason, Reason} - ]) - end. - --spec flush_timeouts() -> ok. -flush_timeouts() -> - receive - {timeout, TRef, ?MODULE} when is_reference(TRef) -> - flush_timeouts() - after 0 -> - ok - end. DELETED deps/cowboy/src/cowboy_http.erl Index: deps/cowboy/src/cowboy_http.erl ================================================================== --- deps/cowboy/src/cowboy_http.erl +++ /dev/null @@ -1,1068 +0,0 @@ -%% Copyright (c) 2011-2014, Loïc Hoguin -%% Copyright (c) 2011, Anthony Ramine -%% -%% Permission to use, copy, modify, and/or distribute this software for any -%% purpose with or without fee is hereby granted, provided that the above -%% copyright notice and this permission notice appear in all copies. -%% -%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -%% Deprecated HTTP parsing API. --module(cowboy_http). - -%% Parsing. --export([list/2]). --export([nonempty_list/2]). --export([content_type/1]). --export([media_range/2]). --export([conneg/2]). --export([language_range/2]). --export([entity_tag_match/1]). --export([expectation/2]). --export([params/2]). --export([http_date/1]). --export([rfc1123_date/1]). --export([rfc850_date/1]). --export([asctime_date/1]). --export([whitespace/2]). --export([digits/1]). --export([token/2]). --export([token_ci/2]). --export([quoted_string/2]). --export([authorization/2]). --export([range/1]). --export([parameterized_tokens/1]). - -%% Decoding. --export([ce_identity/1]). - -%% Parsing. - --spec nonempty_list(binary(), fun()) -> [any(), ...] | {error, badarg}. -nonempty_list(Data, Fun) -> - case list(Data, Fun, []) of - {error, badarg} -> {error, badarg}; - [] -> {error, badarg}; - L -> lists:reverse(L) - end. - --spec list(binary(), fun()) -> list() | {error, badarg}. -list(Data, Fun) -> - case list(Data, Fun, []) of - {error, badarg} -> {error, badarg}; - L -> lists:reverse(L) - end. - --spec list(binary(), fun(), [binary()]) -> [any()] | {error, badarg}. -%% From the RFC: -%%
Wherever this construct is used, null elements are allowed, -%% but do not contribute to the count of elements present. -%% That is, "(element), , (element) " is permitted, but counts -%% as only two elements. Therefore, where at least one element is required, -%% at least one non-null element MUST be present.
-list(Data, Fun, Acc) -> - whitespace(Data, - fun (<<>>) -> Acc; - (<< $,, Rest/binary >>) -> list(Rest, Fun, Acc); - (Rest) -> Fun(Rest, - fun (D, I) -> whitespace(D, - fun (<<>>) -> [I|Acc]; - (<< $,, R/binary >>) -> list(R, Fun, [I|Acc]); - (_Any) -> {error, badarg} - end) - end) - end). - -%% We lowercase the charset header as we know it's case insensitive. --spec content_type(binary()) -> any(). -content_type(Data) -> - media_type(Data, - fun (Rest, Type, SubType) -> - params(Rest, - fun (<<>>, Params) -> - case lists:keyfind(<<"charset">>, 1, Params) of - false -> - {Type, SubType, Params}; - {_, Charset} -> - Charset2 = cowboy_bstr:to_lower(Charset), - Params2 = lists:keyreplace(<<"charset">>, - 1, Params, {<<"charset">>, Charset2}), - {Type, SubType, Params2} - end; - (_Rest2, _) -> - {error, badarg} - end) - end). - --spec media_range(binary(), fun()) -> any(). -media_range(Data, Fun) -> - media_type(Data, - fun (Rest, Type, SubType) -> - media_range_params(Rest, Fun, Type, SubType, []) - end). - --spec media_range_params(binary(), fun(), binary(), binary(), - [{binary(), binary()}]) -> any(). -media_range_params(Data, Fun, Type, SubType, Acc) -> - whitespace(Data, - fun (<< $;, Rest/binary >>) -> - whitespace(Rest, - fun (Rest2) -> - media_range_param_attr(Rest2, Fun, Type, SubType, Acc) - end); - (Rest) -> Fun(Rest, {{Type, SubType, lists:reverse(Acc)}, 1000, []}) - end). - --spec media_range_param_attr(binary(), fun(), binary(), binary(), - [{binary(), binary()}]) -> any(). -media_range_param_attr(Data, Fun, Type, SubType, Acc) -> - token_ci(Data, - fun (_Rest, <<>>) -> {error, badarg}; - (<< $=, Rest/binary >>, Attr) -> - media_range_param_value(Rest, Fun, Type, SubType, Acc, Attr) - end). - --spec media_range_param_value(binary(), fun(), binary(), binary(), - [{binary(), binary()}], binary()) -> any(). -media_range_param_value(Data, Fun, Type, SubType, Acc, <<"q">>) -> - qvalue(Data, - fun (Rest, Quality) -> - accept_ext(Rest, Fun, Type, SubType, Acc, Quality, []) - end); -media_range_param_value(Data, Fun, Type, SubType, Acc, Attr) -> - word(Data, - fun (Rest, Value) -> - media_range_params(Rest, Fun, - Type, SubType, [{Attr, Value}|Acc]) - end). - --spec media_type(binary(), fun()) -> any(). -media_type(Data, Fun) -> - token_ci(Data, - fun (_Rest, <<>>) -> {error, badarg}; - (<< $/, Rest/binary >>, Type) -> - token_ci(Rest, - fun (_Rest2, <<>>) -> {error, badarg}; - (Rest2, SubType) -> Fun(Rest2, Type, SubType) - end); - %% This is a non-strict parsing clause required by some user agents - %% that use * instead of */* in the list of media types. - (Rest, <<"*">> = Type) -> - token_ci(<<"*", Rest/binary>>, - fun (_Rest2, <<>>) -> {error, badarg}; - (Rest2, SubType) -> Fun(Rest2, Type, SubType) - end); - (_Rest, _Type) -> {error, badarg} - end). - --spec accept_ext(binary(), fun(), binary(), binary(), - [{binary(), binary()}], 0..1000, - [{binary(), binary()} | binary()]) -> any(). -accept_ext(Data, Fun, Type, SubType, Params, Quality, Acc) -> - whitespace(Data, - fun (<< $;, Rest/binary >>) -> - whitespace(Rest, - fun (Rest2) -> - accept_ext_attr(Rest2, Fun, - Type, SubType, Params, Quality, Acc) - end); - (Rest) -> - Fun(Rest, {{Type, SubType, lists:reverse(Params)}, - Quality, lists:reverse(Acc)}) - end). - --spec accept_ext_attr(binary(), fun(), binary(), binary(), - [{binary(), binary()}], 0..1000, - [{binary(), binary()} | binary()]) -> any(). -accept_ext_attr(Data, Fun, Type, SubType, Params, Quality, Acc) -> - token_ci(Data, - fun (_Rest, <<>>) -> {error, badarg}; - (<< $=, Rest/binary >>, Attr) -> - accept_ext_value(Rest, Fun, Type, SubType, Params, - Quality, Acc, Attr); - (Rest, Attr) -> - accept_ext(Rest, Fun, Type, SubType, Params, - Quality, [Attr|Acc]) - end). - --spec accept_ext_value(binary(), fun(), binary(), binary(), - [{binary(), binary()}], 0..1000, - [{binary(), binary()} | binary()], binary()) -> any(). -accept_ext_value(Data, Fun, Type, SubType, Params, Quality, Acc, Attr) -> - word(Data, - fun (Rest, Value) -> - accept_ext(Rest, Fun, - Type, SubType, Params, Quality, [{Attr, Value}|Acc]) - end). - --spec conneg(binary(), fun()) -> any(). -conneg(Data, Fun) -> - token_ci(Data, - fun (_Rest, <<>>) -> {error, badarg}; - (Rest, Conneg) -> - maybe_qparam(Rest, - fun (Rest2, Quality) -> - Fun(Rest2, {Conneg, Quality}) - end) - end). - --spec language_range(binary(), fun()) -> any(). -language_range(<< $*, Rest/binary >>, Fun) -> - language_range_ret(Rest, Fun, '*'); -language_range(Data, Fun) -> - language_tag(Data, - fun (Rest, LanguageTag) -> - language_range_ret(Rest, Fun, LanguageTag) - end). - --spec language_range_ret(binary(), fun(), '*' | {binary(), [binary()]}) -> any(). -language_range_ret(Data, Fun, LanguageTag) -> - maybe_qparam(Data, - fun (Rest, Quality) -> - Fun(Rest, {LanguageTag, Quality}) - end). - --spec language_tag(binary(), fun()) -> any(). -language_tag(Data, Fun) -> - alpha(Data, - fun (_Rest, Tag) when byte_size(Tag) =:= 0; byte_size(Tag) > 8 -> - {error, badarg}; - (<< $-, Rest/binary >>, Tag) -> - language_subtag(Rest, Fun, Tag, []); - (Rest, Tag) -> - Fun(Rest, Tag) - end). - --spec language_subtag(binary(), fun(), binary(), [binary()]) -> any(). -language_subtag(Data, Fun, Tag, Acc) -> - alphanumeric(Data, - fun (_Rest, SubTag) when byte_size(SubTag) =:= 0; - byte_size(SubTag) > 8 -> {error, badarg}; - (<< $-, Rest/binary >>, SubTag) -> - language_subtag(Rest, Fun, Tag, [SubTag|Acc]); - (Rest, SubTag) -> - %% Rebuild the full tag now that we know it's correct - Sub = << << $-, S/binary >> || S <- lists:reverse([SubTag|Acc]) >>, - Fun(Rest, << Tag/binary, Sub/binary >>) - end). - --spec maybe_qparam(binary(), fun()) -> any(). -maybe_qparam(Data, Fun) -> - whitespace(Data, - fun (<< $;, Rest/binary >>) -> - whitespace(Rest, - fun (Rest2) -> - %% This is a non-strict parsing clause required by some user agents - %% that use the wrong delimiter putting a charset where a qparam is - %% expected. - try qparam(Rest2, Fun) of - Result -> Result - catch - error:function_clause -> - Fun(<<",", Rest2/binary>>, 1000) - end - end); - (Rest) -> - Fun(Rest, 1000) - end). - --spec qparam(binary(), fun()) -> any(). -qparam(<< Q, $=, Data/binary >>, Fun) when Q =:= $q; Q =:= $Q -> - qvalue(Data, Fun). - --spec entity_tag_match(binary()) -> any(). -entity_tag_match(<< $*, Rest/binary >>) -> - whitespace(Rest, - fun (<<>>) -> '*'; - (_Any) -> {error, badarg} - end); -entity_tag_match(Data) -> - nonempty_list(Data, fun entity_tag/2). - --spec entity_tag(binary(), fun()) -> any(). -entity_tag(<< "W/", Rest/binary >>, Fun) -> - opaque_tag(Rest, Fun, weak); -entity_tag(Data, Fun) -> - opaque_tag(Data, Fun, strong). - --spec opaque_tag(binary(), fun(), weak | strong) -> any(). -opaque_tag(Data, Fun, Strength) -> - quoted_string(Data, - fun (_Rest, <<>>) -> {error, badarg}; - (Rest, OpaqueTag) -> Fun(Rest, {Strength, OpaqueTag}) - end). - --spec expectation(binary(), fun()) -> any(). -expectation(Data, Fun) -> - token_ci(Data, - fun (_Rest, <<>>) -> {error, badarg}; - (<< $=, Rest/binary >>, Expectation) -> - word(Rest, - fun (Rest2, ExtValue) -> - params(Rest2, fun (Rest3, ExtParams) -> - Fun(Rest3, {Expectation, ExtValue, ExtParams}) - end) - end); - (Rest, Expectation) -> - Fun(Rest, Expectation) - end). - --spec params(binary(), fun()) -> any(). -params(Data, Fun) -> - params(Data, Fun, []). - --spec params(binary(), fun(), [{binary(), binary()}]) -> any(). -params(Data, Fun, Acc) -> - whitespace(Data, - fun (<< $;, Rest/binary >>) -> - param(Rest, - fun (Rest2, Attr, Value) -> - params(Rest2, Fun, [{Attr, Value}|Acc]) - end); - (Rest) -> - Fun(Rest, lists:reverse(Acc)) - end). - --spec param(binary(), fun()) -> any(). -param(Data, Fun) -> - whitespace(Data, - fun (Rest) -> - token_ci(Rest, - fun (_Rest2, <<>>) -> {error, badarg}; - (<< $=, Rest2/binary >>, Attr) -> - word(Rest2, - fun (Rest3, Value) -> - Fun(Rest3, Attr, Value) - end); - (_Rest2, _Attr) -> {error, badarg} - end) - end). - -%% While this may not be the most efficient date parsing we can do, -%% it should work fine for our purposes because all HTTP dates should -%% be sent as RFC1123 dates in HTTP/1.1. --spec http_date(binary()) -> any(). -http_date(Data) -> - case rfc1123_date(Data) of - {error, badarg} -> - case rfc850_date(Data) of - {error, badarg} -> - case asctime_date(Data) of - {error, badarg} -> - {error, badarg}; - HTTPDate -> - HTTPDate - end; - HTTPDate -> - HTTPDate - end; - HTTPDate -> - HTTPDate - end. - --spec rfc1123_date(binary()) -> any(). -rfc1123_date(Data) -> - wkday(Data, - fun (<< ", ", Rest/binary >>, _WkDay) -> - date1(Rest, - fun (<< " ", Rest2/binary >>, Date) -> - time(Rest2, - fun (<< " GMT", Rest3/binary >>, Time) -> - http_date_ret(Rest3, {Date, Time}); - (_Any, _Time) -> - {error, badarg} - end); - (_Any, _Date) -> - {error, badarg} - end); - (_Any, _WkDay) -> - {error, badarg} - end). - --spec rfc850_date(binary()) -> any(). -%% From the RFC: -%% HTTP/1.1 clients and caches SHOULD assume that an RFC-850 date -%% which appears to be more than 50 years in the future is in fact -%% in the past (this helps solve the "year 2000" problem). -rfc850_date(Data) -> - weekday(Data, - fun (<< ", ", Rest/binary >>, _WeekDay) -> - date2(Rest, - fun (<< " ", Rest2/binary >>, Date) -> - time(Rest2, - fun (<< " GMT", Rest3/binary >>, Time) -> - http_date_ret(Rest3, {Date, Time}); - (_Any, _Time) -> - {error, badarg} - end); - (_Any, _Date) -> - {error, badarg} - end); - (_Any, _WeekDay) -> - {error, badarg} - end). - --spec asctime_date(binary()) -> any(). -asctime_date(Data) -> - wkday(Data, - fun (<< " ", Rest/binary >>, _WkDay) -> - date3(Rest, - fun (<< " ", Rest2/binary >>, PartialDate) -> - time(Rest2, - fun (<< " ", Rest3/binary >>, Time) -> - asctime_year(Rest3, - PartialDate, Time); - (_Any, _Time) -> - {error, badarg} - end); - (_Any, _PartialDate) -> - {error, badarg} - end); - (_Any, _WkDay) -> - {error, badarg} - end). - --spec asctime_year(binary(), tuple(), tuple()) -> any(). -asctime_year(<< Y1, Y2, Y3, Y4, Rest/binary >>, {Month, Day}, Time) - when Y1 >= $0, Y1 =< $9, Y2 >= $0, Y2 =< $9, - Y3 >= $0, Y3 =< $9, Y4 >= $0, Y4 =< $9 -> - Year = (Y1 - $0) * 1000 + (Y2 - $0) * 100 + (Y3 - $0) * 10 + (Y4 - $0), - http_date_ret(Rest, {{Year, Month, Day}, Time}). - --spec http_date_ret(binary(), tuple()) -> any(). -http_date_ret(Data, DateTime = {Date, _Time}) -> - whitespace(Data, - fun (<<>>) -> - case calendar:valid_date(Date) of - true -> DateTime; - false -> {error, badarg} - end; - (_Any) -> - {error, badarg} - end). - -%% We never use it, pretty much just checks the wkday is right. --spec wkday(binary(), fun()) -> any(). -wkday(<< WkDay:3/binary, Rest/binary >>, Fun) - when WkDay =:= <<"Mon">>; WkDay =:= <<"Tue">>; WkDay =:= <<"Wed">>; - WkDay =:= <<"Thu">>; WkDay =:= <<"Fri">>; WkDay =:= <<"Sat">>; - WkDay =:= <<"Sun">> -> - Fun(Rest, WkDay); -wkday(_Any, _Fun) -> - {error, badarg}. - -%% We never use it, pretty much just checks the weekday is right. --spec weekday(binary(), fun()) -> any(). -weekday(<< "Monday", Rest/binary >>, Fun) -> - Fun(Rest, <<"Monday">>); -weekday(<< "Tuesday", Rest/binary >>, Fun) -> - Fun(Rest, <<"Tuesday">>); -weekday(<< "Wednesday", Rest/binary >>, Fun) -> - Fun(Rest, <<"Wednesday">>); -weekday(<< "Thursday", Rest/binary >>, Fun) -> - Fun(Rest, <<"Thursday">>); -weekday(<< "Friday", Rest/binary >>, Fun) -> - Fun(Rest, <<"Friday">>); -weekday(<< "Saturday", Rest/binary >>, Fun) -> - Fun(Rest, <<"Saturday">>); -weekday(<< "Sunday", Rest/binary >>, Fun) -> - Fun(Rest, <<"Sunday">>); -weekday(_Any, _Fun) -> - {error, badarg}. - --spec date1(binary(), fun()) -> any(). -date1(<< D1, D2, " ", M:3/binary, " ", Y1, Y2, Y3, Y4, Rest/binary >>, Fun) - when D1 >= $0, D1 =< $9, D2 >= $0, D2 =< $9, - Y1 >= $0, Y1 =< $9, Y2 >= $0, Y2 =< $9, - Y3 >= $0, Y3 =< $9, Y4 >= $0, Y4 =< $9 -> - case month(M) of - {error, badarg} -> - {error, badarg}; - Month -> - Fun(Rest, { - (Y1 - $0) * 1000 + (Y2 - $0) * 100 + (Y3 - $0) * 10 + (Y4 - $0), - Month, - (D1 - $0) * 10 + (D2 - $0) - }) - end; -date1(_Data, _Fun) -> - {error, badarg}. - --spec date2(binary(), fun()) -> any(). -date2(<< D1, D2, "-", M:3/binary, "-", Y1, Y2, Rest/binary >>, Fun) - when D1 >= $0, D1 =< $9, D2 >= $0, D2 =< $9, - Y1 >= $0, Y1 =< $9, Y2 >= $0, Y2 =< $9 -> - case month(M) of - {error, badarg} -> - {error, badarg}; - Month -> - Year = (Y1 - $0) * 10 + (Y2 - $0), - Year2 = case Year > 50 of - true -> Year + 1900; - false -> Year + 2000 - end, - Fun(Rest, { - Year2, - Month, - (D1 - $0) * 10 + (D2 - $0) - }) - end; -date2(_Data, _Fun) -> - {error, badarg}. - --spec date3(binary(), fun()) -> any(). -date3(<< M:3/binary, " ", D1, D2, Rest/binary >>, Fun) - when (D1 >= $0 andalso D1 =< $3) orelse D1 =:= $\s, - D2 >= $0, D2 =< $9 -> - case month(M) of - {error, badarg} -> - {error, badarg}; - Month -> - Day = case D1 of - $\s -> D2 - $0; - D1 -> (D1 - $0) * 10 + (D2 - $0) - end, - Fun(Rest, {Month, Day}) - end; -date3(_Data, _Fun) -> - {error, badarg}. - --spec month(<< _:24 >>) -> 1..12 | {error, badarg}. -month(<<"Jan">>) -> 1; -month(<<"Feb">>) -> 2; -month(<<"Mar">>) -> 3; -month(<<"Apr">>) -> 4; -month(<<"May">>) -> 5; -month(<<"Jun">>) -> 6; -month(<<"Jul">>) -> 7; -month(<<"Aug">>) -> 8; -month(<<"Sep">>) -> 9; -month(<<"Oct">>) -> 10; -month(<<"Nov">>) -> 11; -month(<<"Dec">>) -> 12; -month(_Any) -> {error, badarg}. - --spec time(binary(), fun()) -> any(). -time(<< H1, H2, ":", M1, M2, ":", S1, S2, Rest/binary >>, Fun) - when H1 >= $0, H1 =< $2, H2 >= $0, H2 =< $9, - M1 >= $0, M1 =< $5, M2 >= $0, M2 =< $9, - S1 >= $0, S1 =< $5, S2 >= $0, S2 =< $9 -> - Hour = (H1 - $0) * 10 + (H2 - $0), - case Hour < 24 of - true -> - Time = { - Hour, - (M1 - $0) * 10 + (M2 - $0), - (S1 - $0) * 10 + (S2 - $0) - }, - Fun(Rest, Time); - false -> - {error, badarg} - end. - --spec whitespace(binary(), fun()) -> any(). -whitespace(<< C, Rest/binary >>, Fun) - when C =:= $\s; C =:= $\t -> - whitespace(Rest, Fun); -whitespace(Data, Fun) -> - Fun(Data). - --spec digits(binary()) -> non_neg_integer() | {error, badarg}. -digits(Data) -> - digits(Data, - fun (Rest, I) -> - whitespace(Rest, - fun (<<>>) -> - I; - (_Rest2) -> - {error, badarg} - end) - end). - --spec digits(binary(), fun()) -> any(). -digits(<< C, Rest/binary >>, Fun) - when C >= $0, C =< $9 -> - digits(Rest, Fun, C - $0); -digits(_Data, _Fun) -> - {error, badarg}. - --spec digits(binary(), fun(), non_neg_integer()) -> any(). -digits(<< C, Rest/binary >>, Fun, Acc) - when C >= $0, C =< $9 -> - digits(Rest, Fun, Acc * 10 + (C - $0)); -digits(Data, Fun, Acc) -> - Fun(Data, Acc). - -%% Changes all characters to lowercase. --spec alpha(binary(), fun()) -> any(). -alpha(Data, Fun) -> - alpha(Data, Fun, <<>>). - --spec alpha(binary(), fun(), binary()) -> any(). -alpha(<<>>, Fun, Acc) -> - Fun(<<>>, Acc); -alpha(<< C, Rest/binary >>, Fun, Acc) - when C >= $a andalso C =< $z; - C >= $A andalso C =< $Z -> - C2 = cowboy_bstr:char_to_lower(C), - alpha(Rest, Fun, << Acc/binary, C2 >>); -alpha(Data, Fun, Acc) -> - Fun(Data, Acc). - --spec alphanumeric(binary(), fun()) -> any(). -alphanumeric(Data, Fun) -> - alphanumeric(Data, Fun, <<>>). - --spec alphanumeric(binary(), fun(), binary()) -> any(). -alphanumeric(<<>>, Fun, Acc) -> - Fun(<<>>, Acc); -alphanumeric(<< C, Rest/binary >>, Fun, Acc) - when C >= $a andalso C =< $z; - C >= $A andalso C =< $Z; - C >= $0 andalso C =< $9 -> - C2 = cowboy_bstr:char_to_lower(C), - alphanumeric(Rest, Fun, << Acc/binary, C2 >>); -alphanumeric(Data, Fun, Acc) -> - Fun(Data, Acc). - -%% @doc Parse either a token or a quoted string. --spec word(binary(), fun()) -> any(). -word(Data = << $", _/binary >>, Fun) -> - quoted_string(Data, Fun); -word(Data, Fun) -> - token(Data, - fun (_Rest, <<>>) -> {error, badarg}; - (Rest, Token) -> Fun(Rest, Token) - end). - -%% Changes all characters to lowercase. --spec token_ci(binary(), fun()) -> any(). -token_ci(Data, Fun) -> - token(Data, Fun, ci, <<>>). - --spec token(binary(), fun()) -> any(). -token(Data, Fun) -> - token(Data, Fun, cs, <<>>). - --spec token(binary(), fun(), ci | cs, binary()) -> any(). -token(<<>>, Fun, _Case, Acc) -> - Fun(<<>>, Acc); -token(Data = << C, _Rest/binary >>, Fun, _Case, Acc) - when C =:= $(; C =:= $); C =:= $<; C =:= $>; C =:= $@; - C =:= $,; C =:= $;; C =:= $:; C =:= $\\; C =:= $"; - C =:= $/; C =:= $[; C =:= $]; C =:= $?; C =:= $=; - C =:= ${; C =:= $}; C =:= $\s; C =:= $\t; - C < 32; C =:= 127 -> - Fun(Data, Acc); -token(<< C, Rest/binary >>, Fun, Case = ci, Acc) -> - C2 = cowboy_bstr:char_to_lower(C), - token(Rest, Fun, Case, << Acc/binary, C2 >>); -token(<< C, Rest/binary >>, Fun, Case, Acc) -> - token(Rest, Fun, Case, << Acc/binary, C >>). - --spec quoted_string(binary(), fun()) -> any(). -quoted_string(<< $", Rest/binary >>, Fun) -> - quoted_string(Rest, Fun, <<>>); -quoted_string(_, _Fun) -> - {error, badarg}. - --spec quoted_string(binary(), fun(), binary()) -> any(). -quoted_string(<<>>, _Fun, _Acc) -> - {error, badarg}; -quoted_string(<< $", Rest/binary >>, Fun, Acc) -> - Fun(Rest, Acc); -quoted_string(<< $\\, C, Rest/binary >>, Fun, Acc) -> - quoted_string(Rest, Fun, << Acc/binary, C >>); -quoted_string(<< C, Rest/binary >>, Fun, Acc) -> - quoted_string(Rest, Fun, << Acc/binary, C >>). - --spec qvalue(binary(), fun()) -> any(). -qvalue(<< $0, $., Rest/binary >>, Fun) -> - qvalue(Rest, Fun, 0, 100); -%% Some user agents use q=.x instead of q=0.x -qvalue(<< $., Rest/binary >>, Fun) -> - qvalue(Rest, Fun, 0, 100); -qvalue(<< $0, Rest/binary >>, Fun) -> - Fun(Rest, 0); -qvalue(<< $1, $., $0, $0, $0, Rest/binary >>, Fun) -> - Fun(Rest, 1000); -qvalue(<< $1, $., $0, $0, Rest/binary >>, Fun) -> - Fun(Rest, 1000); -qvalue(<< $1, $., $0, Rest/binary >>, Fun) -> - Fun(Rest, 1000); -qvalue(<< $1, Rest/binary >>, Fun) -> - Fun(Rest, 1000); -qvalue(_Data, _Fun) -> - {error, badarg}. - --spec qvalue(binary(), fun(), integer(), 1 | 10 | 100) -> any(). -qvalue(Data, Fun, Q, 0) -> - Fun(Data, Q); -qvalue(<< C, Rest/binary >>, Fun, Q, M) - when C >= $0, C =< $9 -> - qvalue(Rest, Fun, Q + (C - $0) * M, M div 10); -qvalue(Data, Fun, Q, _M) -> - Fun(Data, Q). - -%% Only RFC2617 Basic authorization is supported so far. --spec authorization(binary(), binary()) -> {binary(), any()} | {error, badarg}. -authorization(UserPass, Type = <<"basic">>) -> - whitespace(UserPass, - fun(D) -> - authorization_basic_userid(base64:mime_decode(D), - fun(Rest, Userid) -> - authorization_basic_password(Rest, - fun(Password) -> - {Type, {Userid, Password}} - end) - end) - end); -authorization(String, Type) -> - whitespace(String, fun(Rest) -> {Type, Rest} end). - --spec authorization_basic_userid(binary(), fun()) -> any(). -authorization_basic_userid(Data, Fun) -> - authorization_basic_userid(Data, Fun, <<>>). - -authorization_basic_userid(<<>>, _Fun, _Acc) -> - {error, badarg}; -authorization_basic_userid(<>, _Fun, Acc) - when C < 32; C =:= 127; (C =:=$: andalso Acc =:= <<>>) -> - {error, badarg}; -authorization_basic_userid(<<$:, Rest/binary>>, Fun, Acc) -> - Fun(Rest, Acc); -authorization_basic_userid(<>, Fun, Acc) -> - authorization_basic_userid(Rest, Fun, <>). - --spec authorization_basic_password(binary(), fun()) -> any(). -authorization_basic_password(Data, Fun) -> - authorization_basic_password(Data, Fun, <<>>). - -authorization_basic_password(<>, _Fun, _Acc) - when C < 32; C=:= 127 -> - {error, badarg}; -authorization_basic_password(<<>>, Fun, Acc) -> - Fun(Acc); -authorization_basic_password(<>, Fun, Acc) -> - authorization_basic_password(Rest, Fun, <>). - --spec range(binary()) -> {Unit, [Range]} | {error, badarg} when - Unit :: binary(), - Range :: {non_neg_integer(), non_neg_integer() | infinity} | neg_integer(). -range(Data) -> - token_ci(Data, fun range/2). - -range(Data, Token) -> - whitespace(Data, - fun(<<"=", Rest/binary>>) -> - case list(Rest, fun range_beginning/2) of - {error, badarg} -> - {error, badarg}; - Ranges -> - {Token, Ranges} - end; - (_) -> - {error, badarg} - end). - -range_beginning(Data, Fun) -> - range_digits(Data, suffix, - fun(D, RangeBeginning) -> - range_ending(D, Fun, RangeBeginning) - end). - -range_ending(Data, Fun, RangeBeginning) -> - whitespace(Data, - fun(<<"-", R/binary>>) -> - case RangeBeginning of - suffix -> - range_digits(R, fun(D, RangeEnding) -> Fun(D, -RangeEnding) end); - _ -> - range_digits(R, infinity, - fun(D, RangeEnding) -> - Fun(D, {RangeBeginning, RangeEnding}) - end) - end; - (_) -> - {error, badarg} - end). - --spec range_digits(binary(), fun()) -> any(). -range_digits(Data, Fun) -> - whitespace(Data, - fun(D) -> - digits(D, Fun) - end). - --spec range_digits(binary(), any(), fun()) -> any(). -range_digits(Data, Default, Fun) -> - whitespace(Data, - fun(<< C, Rest/binary >>) when C >= $0, C =< $9 -> - digits(Rest, Fun, C - $0); - (_) -> - Fun(Data, Default) - end). - --spec parameterized_tokens(binary()) -> any(). -parameterized_tokens(Data) -> - nonempty_list(Data, - fun (D, Fun) -> - token(D, - fun (_Rest, <<>>) -> {error, badarg}; - (Rest, Token) -> - parameterized_tokens_params(Rest, - fun (Rest2, Params) -> - Fun(Rest2, {Token, Params}) - end, []) - end) - end). - --spec parameterized_tokens_params(binary(), fun(), [binary() | {binary(), binary()}]) -> any(). -parameterized_tokens_params(Data, Fun, Acc) -> - whitespace(Data, - fun (<< $;, Rest/binary >>) -> - parameterized_tokens_param(Rest, - fun (Rest2, Param) -> - parameterized_tokens_params(Rest2, Fun, [Param|Acc]) - end); - (Rest) -> - Fun(Rest, lists:reverse(Acc)) - end). - --spec parameterized_tokens_param(binary(), fun()) -> any(). -parameterized_tokens_param(Data, Fun) -> - whitespace(Data, - fun (Rest) -> - token(Rest, - fun (_Rest2, <<>>) -> {error, badarg}; - (<< $=, Rest2/binary >>, Attr) -> - word(Rest2, - fun (Rest3, Value) -> - Fun(Rest3, {Attr, Value}) - end); - (Rest2, Attr) -> - Fun(Rest2, Attr) - end) - end). - -%% Decoding. - -%% @todo Move this to cowlib too I suppose. :-) --spec ce_identity(binary()) -> {ok, binary()}. -ce_identity(Data) -> - {ok, Data}. - -%% Tests. - --ifdef(TEST). -nonempty_charset_list_test_() -> - Tests = [ - {<<>>, {error, badarg}}, - {<<"iso-8859-5, unicode-1-1;q=0.8">>, [ - {<<"iso-8859-5">>, 1000}, - {<<"unicode-1-1">>, 800} - ]}, - %% Some user agents send this invalid value for the Accept-Charset header - {<<"ISO-8859-1;utf-8;q=0.7,*;q=0.7">>, [ - {<<"iso-8859-1">>, 1000}, - {<<"utf-8">>, 700}, - {<<"*">>, 700} - ]} - ], - [{V, fun() -> R = nonempty_list(V, fun conneg/2) end} || {V, R} <- Tests]. - -nonempty_language_range_list_test_() -> - Tests = [ - {<<"da, en-gb;q=0.8, en;q=0.7">>, [ - {<<"da">>, 1000}, - {<<"en-gb">>, 800}, - {<<"en">>, 700} - ]}, - {<<"en, en-US, en-cockney, i-cherokee, x-pig-latin, es-419">>, [ - {<<"en">>, 1000}, - {<<"en-us">>, 1000}, - {<<"en-cockney">>, 1000}, - {<<"i-cherokee">>, 1000}, - {<<"x-pig-latin">>, 1000}, - {<<"es-419">>, 1000} - ]} - ], - [{V, fun() -> R = nonempty_list(V, fun language_range/2) end} - || {V, R} <- Tests]. - -nonempty_token_list_test_() -> - Tests = [ - {<<>>, {error, badarg}}, - {<<" ">>, {error, badarg}}, - {<<" , ">>, {error, badarg}}, - {<<",,,">>, {error, badarg}}, - {<<"a b">>, {error, badarg}}, - {<<"a , , , ">>, [<<"a">>]}, - {<<" , , , a">>, [<<"a">>]}, - {<<"a, , b">>, [<<"a">>, <<"b">>]}, - {<<"close">>, [<<"close">>]}, - {<<"keep-alive, upgrade">>, [<<"keep-alive">>, <<"upgrade">>]} - ], - [{V, fun() -> R = nonempty_list(V, fun token/2) end} || {V, R} <- Tests]. - -media_range_list_test_() -> - Tests = [ - {<<"audio/*; q=0.2, audio/basic">>, [ - {{<<"audio">>, <<"*">>, []}, 200, []}, - {{<<"audio">>, <<"basic">>, []}, 1000, []} - ]}, - {<<"text/plain; q=0.5, text/html, " - "text/x-dvi; q=0.8, text/x-c">>, [ - {{<<"text">>, <<"plain">>, []}, 500, []}, - {{<<"text">>, <<"html">>, []}, 1000, []}, - {{<<"text">>, <<"x-dvi">>, []}, 800, []}, - {{<<"text">>, <<"x-c">>, []}, 1000, []} - ]}, - {<<"text/*, text/html, text/html;level=1, */*">>, [ - {{<<"text">>, <<"*">>, []}, 1000, []}, - {{<<"text">>, <<"html">>, []}, 1000, []}, - {{<<"text">>, <<"html">>, [{<<"level">>, <<"1">>}]}, 1000, []}, - {{<<"*">>, <<"*">>, []}, 1000, []} - ]}, - {<<"text/*;q=0.3, text/html;q=0.7, text/html;level=1, " - "text/html;level=2;q=0.4, */*;q=0.5">>, [ - {{<<"text">>, <<"*">>, []}, 300, []}, - {{<<"text">>, <<"html">>, []}, 700, []}, - {{<<"text">>, <<"html">>, [{<<"level">>, <<"1">>}]}, 1000, []}, - {{<<"text">>, <<"html">>, [{<<"level">>, <<"2">>}]}, 400, []}, - {{<<"*">>, <<"*">>, []}, 500, []} - ]}, - {<<"text/html;level=1;quoted=\"hi hi hi\";" - "q=0.123;standalone;complex=gits, text/plain">>, [ - {{<<"text">>, <<"html">>, - [{<<"level">>, <<"1">>}, {<<"quoted">>, <<"hi hi hi">>}]}, 123, - [<<"standalone">>, {<<"complex">>, <<"gits">>}]}, - {{<<"text">>, <<"plain">>, []}, 1000, []} - ]}, - {<<"text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2">>, [ - {{<<"text">>, <<"html">>, []}, 1000, []}, - {{<<"image">>, <<"gif">>, []}, 1000, []}, - {{<<"image">>, <<"jpeg">>, []}, 1000, []}, - {{<<"*">>, <<"*">>, []}, 200, []}, - {{<<"*">>, <<"*">>, []}, 200, []} - ]} - ], - [{V, fun() -> R = list(V, fun media_range/2) end} || {V, R} <- Tests]. - -entity_tag_match_test_() -> - Tests = [ - {<<"\"xyzzy\"">>, [{strong, <<"xyzzy">>}]}, - {<<"\"xyzzy\", W/\"r2d2xxxx\", \"c3piozzzz\"">>, - [{strong, <<"xyzzy">>}, - {weak, <<"r2d2xxxx">>}, - {strong, <<"c3piozzzz">>}]}, - {<<"*">>, '*'} - ], - [{V, fun() -> R = entity_tag_match(V) end} || {V, R} <- Tests]. - -http_date_test_() -> - Tests = [ - {<<"Sun, 06 Nov 1994 08:49:37 GMT">>, {{1994, 11, 6}, {8, 49, 37}}}, - {<<"Sunday, 06-Nov-94 08:49:37 GMT">>, {{1994, 11, 6}, {8, 49, 37}}}, - {<<"Sun Nov 6 08:49:37 1994">>, {{1994, 11, 6}, {8, 49, 37}}} - ], - [{V, fun() -> R = http_date(V) end} || {V, R} <- Tests]. - -rfc1123_date_test_() -> - Tests = [ - {<<"Sun, 06 Nov 1994 08:49:37 GMT">>, {{1994, 11, 6}, {8, 49, 37}}} - ], - [{V, fun() -> R = rfc1123_date(V) end} || {V, R} <- Tests]. - -rfc850_date_test_() -> - Tests = [ - {<<"Sunday, 06-Nov-94 08:49:37 GMT">>, {{1994, 11, 6}, {8, 49, 37}}} - ], - [{V, fun() -> R = rfc850_date(V) end} || {V, R} <- Tests]. - -asctime_date_test_() -> - Tests = [ - {<<"Sun Nov 6 08:49:37 1994">>, {{1994, 11, 6}, {8, 49, 37}}} - ], - [{V, fun() -> R = asctime_date(V) end} || {V, R} <- Tests]. - -content_type_test_() -> - Tests = [ - {<<"text/plain; charset=iso-8859-4">>, - {<<"text">>, <<"plain">>, [{<<"charset">>, <<"iso-8859-4">>}]}}, - {<<"multipart/form-data \t;Boundary=\"MultipartIsUgly\"">>, - {<<"multipart">>, <<"form-data">>, [ - {<<"boundary">>, <<"MultipartIsUgly">>} - ]}}, - {<<"foo/bar; one=FirstParam; two=SecondParam">>, - {<<"foo">>, <<"bar">>, [ - {<<"one">>, <<"FirstParam">>}, - {<<"two">>, <<"SecondParam">>} - ]}} - ], - [{V, fun () -> R = content_type(V) end} || {V, R} <- Tests]. - -parameterized_tokens_test_() -> - Tests = [ - {<<"foo">>, [{<<"foo">>, []}]}, - {<<"bar; baz=2">>, [{<<"bar">>, [{<<"baz">>, <<"2">>}]}]}, - {<<"bar; baz=2;bat">>, [{<<"bar">>, [{<<"baz">>, <<"2">>}, <<"bat">>]}]}, - {<<"bar; baz=2;bat=\"z=1,2;3\"">>, [{<<"bar">>, [{<<"baz">>, <<"2">>}, {<<"bat">>, <<"z=1,2;3">>}]}]}, - {<<"foo, bar; baz=2">>, [{<<"foo">>, []}, {<<"bar">>, [{<<"baz">>, <<"2">>}]}]} - ], - [{V, fun () -> R = parameterized_tokens(V) end} || {V, R} <- Tests]. - -digits_test_() -> - Tests = [ - {<<"42 ">>, 42}, - {<<"69\t">>, 69}, - {<<"1337">>, 1337} - ], - [{V, fun() -> R = digits(V) end} || {V, R} <- Tests]. - -http_authorization_test_() -> - Tests = [ - {<<"basic">>, <<"QWxsYWRpbjpvcGVuIHNlc2FtZQ==">>, - {<<"basic">>, {<<"Alladin">>, <<"open sesame">>}}}, - {<<"basic">>, <<"dXNlcm5hbWU6">>, - {<<"basic">>, {<<"username">>, <<>>}}}, - {<<"basic">>, <<"dXNlcm5hbWUK">>, - {error, badarg}}, - {<<"basic">>, <<"_[]@#$%^&*()-AA==">>, - {error, badarg}}, - {<<"basic">>, <<"dXNlcjpwYXNzCA==">>, - {error, badarg}}, - {<<"bearer">>, <<" some_secret_key">>, - {<<"bearer">>,<<"some_secret_key">>}} - ], - [{V, fun() -> R = authorization(V,T) end} || {T, V, R} <- Tests]. - -http_range_test_() -> - Tests = [ - {<<"bytes=1-20">>, - {<<"bytes">>, [{1, 20}]}}, - {<<"bytes=-100">>, - {<<"bytes">>, [-100]}}, - {<<"bytes=1-">>, - {<<"bytes">>, [{1, infinity}]}}, - {<<"bytes=1-20,30-40,50-">>, - {<<"bytes">>, [{1, 20}, {30, 40}, {50, infinity}]}}, - {<<"bytes = 1 - 20 , 50 - , - 300 ">>, - {<<"bytes">>, [{1, 20}, {50, infinity}, -300]}}, - {<<"bytes=1-20,-500,30-40">>, - {<<"bytes">>, [{1, 20}, -500, {30, 40}]}}, - {<<"test=1-20,-500,30-40">>, - {<<"test">>, [{1, 20}, -500, {30, 40}]}}, - {<<"bytes=-">>, - {error, badarg}}, - {<<"bytes=-30,-">>, - {error, badarg}} - ], - [fun() -> R = range(V) end ||{V, R} <- Tests]. --endif. DELETED deps/cowboy/src/cowboy_http_handler.erl Index: deps/cowboy/src/cowboy_http_handler.erl ================================================================== --- deps/cowboy/src/cowboy_http_handler.erl +++ /dev/null @@ -1,37 +0,0 @@ -%% Copyright (c) 2011-2014, Loïc Hoguin -%% -%% Permission to use, copy, modify, and/or distribute this software for any -%% purpose with or without fee is hereby granted, provided that the above -%% copyright notice and this permission notice appear in all copies. -%% -%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - --module(cowboy_http_handler). - --type opts() :: any(). --type state() :: any(). --type terminate_reason() :: {normal, shutdown} - | {normal, timeout} %% Only occurs in loop handlers. - | {error, closed} %% Only occurs in loop handlers. - | {error, overflow} %% Only occurs in loop handlers. - | {error, atom()}. - --callback init({atom(), http}, Req, opts()) - -> {ok, Req, state()} - | {loop, Req, state()} - | {loop, Req, state(), hibernate} - | {loop, Req, state(), timeout()} - | {loop, Req, state(), timeout(), hibernate} - | {shutdown, Req, state()} - | {upgrade, protocol, module()} - | {upgrade, protocol, module(), Req, opts()} - when Req::cowboy_req:req(). --callback handle(Req, State) -> {ok, Req, State} - when Req::cowboy_req:req(), State::state(). --callback terminate(terminate_reason(), cowboy_req:req(), state()) -> ok. DELETED deps/cowboy/src/cowboy_loop_handler.erl Index: deps/cowboy/src/cowboy_loop_handler.erl ================================================================== --- deps/cowboy/src/cowboy_loop_handler.erl +++ /dev/null @@ -1,40 +0,0 @@ -%% Copyright (c) 2011-2014, Loïc Hoguin -%% -%% Permission to use, copy, modify, and/or distribute this software for any -%% purpose with or without fee is hereby granted, provided that the above -%% copyright notice and this permission notice appear in all copies. -%% -%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - --module(cowboy_loop_handler). - --type opts() :: any(). --type state() :: any(). --type terminate_reason() :: {normal, shutdown} - | {normal, timeout} - | {error, closed} - | {error, overflow} - | {error, atom()}. - --callback init({atom(), http}, Req, opts()) - -> {ok, Req, state()} - | {loop, Req, state()} - | {loop, Req, state(), hibernate} - | {loop, Req, state(), timeout()} - | {loop, Req, state(), timeout(), hibernate} - | {shutdown, Req, state()} - | {upgrade, protocol, module()} - | {upgrade, protocol, module(), Req, opts()} - when Req::cowboy_req:req(). --callback info(any(), Req, State) - -> {ok, Req, State} - | {loop, Req, State} - | {loop, Req, State, hibernate} - when Req::cowboy_req:req(), State::state(). --callback terminate(terminate_reason(), cowboy_req:req(), state()) -> ok. DELETED deps/cowboy/src/cowboy_middleware.erl Index: deps/cowboy/src/cowboy_middleware.erl ================================================================== --- deps/cowboy/src/cowboy_middleware.erl +++ /dev/null @@ -1,25 +0,0 @@ -%% Copyright (c) 2013-2014, Loïc Hoguin -%% -%% Permission to use, copy, modify, and/or distribute this software for any -%% purpose with or without fee is hereby granted, provided that the above -%% copyright notice and this permission notice appear in all copies. -%% -%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - --module(cowboy_middleware). - --type env() :: [{atom(), any()}]. --export_type([env/0]). - --callback execute(Req, Env) - -> {ok, Req, Env} - | {suspend, module(), atom(), [any()]} - | {halt, Req} - | {error, cowboy:http_status(), Req} - when Req::cowboy_req:req(), Env::env(). DELETED deps/cowboy/src/cowboy_protocol.erl Index: deps/cowboy/src/cowboy_protocol.erl ================================================================== --- deps/cowboy/src/cowboy_protocol.erl +++ /dev/null @@ -1,510 +0,0 @@ -%% Copyright (c) 2011-2014, Loïc Hoguin -%% Copyright (c) 2011, Anthony Ramine -%% -%% Permission to use, copy, modify, and/or distribute this software for any -%% purpose with or without fee is hereby granted, provided that the above -%% copyright notice and this permission notice appear in all copies. -%% -%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - --module(cowboy_protocol). - -%% API. --export([start_link/4]). - -%% Internal. --export([init/4]). --export([parse_request/3]). --export([resume/6]). - --type opts() :: [{compress, boolean()} - | {env, cowboy_middleware:env()} - | {max_empty_lines, non_neg_integer()} - | {max_header_name_length, non_neg_integer()} - | {max_header_value_length, non_neg_integer()} - | {max_headers, non_neg_integer()} - | {max_keepalive, non_neg_integer()} - | {max_request_line_length, non_neg_integer()} - | {middlewares, [module()]} - | {onrequest, cowboy:onrequest_fun()} - | {onresponse, cowboy:onresponse_fun()} - | {timeout, timeout()}]. --export_type([opts/0]). - --record(state, { - socket :: inet:socket(), - transport :: module(), - middlewares :: [module()], - compress :: boolean(), - env :: cowboy_middleware:env(), - onrequest :: undefined | cowboy:onrequest_fun(), - onresponse = undefined :: undefined | cowboy:onresponse_fun(), - max_empty_lines :: non_neg_integer(), - req_keepalive = 1 :: non_neg_integer(), - max_keepalive :: non_neg_integer(), - max_request_line_length :: non_neg_integer(), - max_header_name_length :: non_neg_integer(), - max_header_value_length :: non_neg_integer(), - max_headers :: non_neg_integer(), - timeout :: timeout(), - until :: non_neg_integer() | infinity -}). - --include_lib("cowlib/include/cow_inline.hrl"). - -%% API. - --spec start_link(ranch:ref(), inet:socket(), module(), opts()) -> {ok, pid()}. -start_link(Ref, Socket, Transport, Opts) -> - Pid = spawn_link(?MODULE, init, [Ref, Socket, Transport, Opts]), - {ok, Pid}. - -%% Internal. - -%% Faster alternative to proplists:get_value/3. -get_value(Key, Opts, Default) -> - case lists:keyfind(Key, 1, Opts) of - {_, Value} -> Value; - _ -> Default - end. - --spec init(ranch:ref(), inet:socket(), module(), opts()) -> ok. -init(Ref, Socket, Transport, Opts) -> - Compress = get_value(compress, Opts, false), - MaxEmptyLines = get_value(max_empty_lines, Opts, 5), - MaxHeaderNameLength = get_value(max_header_name_length, Opts, 64), - MaxHeaderValueLength = get_value(max_header_value_length, Opts, 4096), - MaxHeaders = get_value(max_headers, Opts, 100), - MaxKeepalive = get_value(max_keepalive, Opts, 100), - MaxRequestLineLength = get_value(max_request_line_length, Opts, 4096), - Middlewares = get_value(middlewares, Opts, [cowboy_router, cowboy_handler]), - Env = [{listener, Ref}|get_value(env, Opts, [])], - OnRequest = get_value(onrequest, Opts, undefined), - OnResponse = get_value(onresponse, Opts, undefined), - Timeout = get_value(timeout, Opts, 5000), - ok = ranch:accept_ack(Ref), - wait_request(<<>>, #state{socket=Socket, transport=Transport, - middlewares=Middlewares, compress=Compress, env=Env, - max_empty_lines=MaxEmptyLines, max_keepalive=MaxKeepalive, - max_request_line_length=MaxRequestLineLength, - max_header_name_length=MaxHeaderNameLength, - max_header_value_length=MaxHeaderValueLength, max_headers=MaxHeaders, - onrequest=OnRequest, onresponse=OnResponse, - timeout=Timeout, until=until(Timeout)}, 0). - --spec until(timeout()) -> non_neg_integer() | infinity. -until(infinity) -> - infinity; -until(Timeout) -> - {Me, S, Mi} = os:timestamp(), - Me * 1000000000 + S * 1000 + Mi div 1000 + Timeout. - -%% Request parsing. -%% -%% The next set of functions is the request parsing code. All of it -%% runs using a single binary match context. This optimization ends -%% right after the header parsing is finished and the code becomes -%% more interesting past that point. - --spec recv(inet:socket(), module(), non_neg_integer() | infinity) - -> {ok, binary()} | {error, closed | timeout | atom()}. -recv(Socket, Transport, infinity) -> - Transport:recv(Socket, 0, infinity); -recv(Socket, Transport, Until) -> - {Me, S, Mi} = os:timestamp(), - Now = Me * 1000000000 + S * 1000 + Mi div 1000, - Timeout = Until - Now, - if Timeout < 0 -> - {error, timeout}; - true -> - Transport:recv(Socket, 0, Timeout) - end. - --spec wait_request(binary(), #state{}, non_neg_integer()) -> ok. -wait_request(Buffer, State=#state{socket=Socket, transport=Transport, - until=Until}, ReqEmpty) -> - case recv(Socket, Transport, Until) of - {ok, Data} -> - parse_request(<< Buffer/binary, Data/binary >>, State, ReqEmpty); - {error, _} -> - terminate(State) - end. - --spec parse_request(binary(), #state{}, non_neg_integer()) -> ok. -%% Empty lines must be using \r\n. -parse_request(<< $\n, _/binary >>, State, _) -> - error_terminate(400, State); -%% We limit the length of the Request-line to MaxLength to avoid endlessly -%% reading from the socket and eventually crashing. -parse_request(Buffer, State=#state{max_request_line_length=MaxLength, - max_empty_lines=MaxEmpty}, ReqEmpty) -> - case match_eol(Buffer, 0) of - nomatch when byte_size(Buffer) > MaxLength -> - error_terminate(414, State); - nomatch -> - wait_request(Buffer, State, ReqEmpty); - 1 when ReqEmpty =:= MaxEmpty -> - error_terminate(400, State); - 1 -> - << _:16, Rest/binary >> = Buffer, - parse_request(Rest, State, ReqEmpty + 1); - _ -> - parse_method(Buffer, State, <<>>) - end. - -match_eol(<< $\n, _/bits >>, N) -> - N; -match_eol(<< _, Rest/bits >>, N) -> - match_eol(Rest, N + 1); -match_eol(_, _) -> - nomatch. - -parse_method(<< C, Rest/bits >>, State, SoFar) -> - case C of - $\r -> error_terminate(400, State); - $\s -> parse_uri(Rest, State, SoFar); - _ -> parse_method(Rest, State, << SoFar/binary, C >>) - end. - -parse_uri(<< $\r, _/bits >>, State, _) -> - error_terminate(400, State); -parse_uri(<< "* ", Rest/bits >>, State, Method) -> - parse_version(Rest, State, Method, <<"*">>, <<>>); -parse_uri(<< "http://", Rest/bits >>, State, Method) -> - parse_uri_skip_host(Rest, State, Method); -parse_uri(<< "https://", Rest/bits >>, State, Method) -> - parse_uri_skip_host(Rest, State, Method); -parse_uri(<< "HTTP://", Rest/bits >>, State, Method) -> - parse_uri_skip_host(Rest, State, Method); -parse_uri(<< "HTTPS://", Rest/bits >>, State, Method) -> - parse_uri_skip_host(Rest, State, Method); -parse_uri(Buffer, State, Method) -> - parse_uri_path(Buffer, State, Method, <<>>). - -parse_uri_skip_host(<< C, Rest/bits >>, State, Method) -> - case C of - $\r -> error_terminate(400, State); - $/ -> parse_uri_path(Rest, State, Method, <<"/">>); - $\s -> parse_version(Rest, State, Method, <<"/">>, <<>>); - $? -> parse_uri_query(Rest, State, Method, <<"/">>, <<>>); - $# -> skip_uri_fragment(Rest, State, Method, <<"/">>, <<>>); - _ -> parse_uri_skip_host(Rest, State, Method) - end. - -parse_uri_path(<< C, Rest/bits >>, State, Method, SoFar) -> - case C of - $\r -> error_terminate(400, State); - $\s -> parse_version(Rest, State, Method, SoFar, <<>>); - $? -> parse_uri_query(Rest, State, Method, SoFar, <<>>); - $# -> skip_uri_fragment(Rest, State, Method, SoFar, <<>>); - _ -> parse_uri_path(Rest, State, Method, << SoFar/binary, C >>) - end. - -parse_uri_query(<< C, Rest/bits >>, S, M, P, SoFar) -> - case C of - $\r -> error_terminate(400, S); - $\s -> parse_version(Rest, S, M, P, SoFar); - $# -> skip_uri_fragment(Rest, S, M, P, SoFar); - _ -> parse_uri_query(Rest, S, M, P, << SoFar/binary, C >>) - end. - -skip_uri_fragment(<< C, Rest/bits >>, S, M, P, Q) -> - case C of - $\r -> error_terminate(400, S); - $\s -> parse_version(Rest, S, M, P, Q); - _ -> skip_uri_fragment(Rest, S, M, P, Q) - end. - -parse_version(<< "HTTP/1.1\r\n", Rest/bits >>, S, M, P, Q) -> - parse_header(Rest, S, M, P, Q, 'HTTP/1.1', []); -parse_version(<< "HTTP/1.0\r\n", Rest/bits >>, S, M, P, Q) -> - parse_header(Rest, S, M, P, Q, 'HTTP/1.0', []); -parse_version(_, State, _, _, _) -> - error_terminate(505, State). - -%% Stop receiving data if we have more than allowed number of headers. -wait_header(_, State=#state{max_headers=MaxHeaders}, _, _, _, _, Headers) - when length(Headers) >= MaxHeaders -> - error_terminate(400, State); -wait_header(Buffer, State=#state{socket=Socket, transport=Transport, - until=Until}, M, P, Q, V, H) -> - case recv(Socket, Transport, Until) of - {ok, Data} -> - parse_header(<< Buffer/binary, Data/binary >>, - State, M, P, Q, V, H); - {error, timeout} -> - error_terminate(408, State); - {error, _} -> - terminate(State) - end. - -parse_header(<< $\r, $\n, Rest/bits >>, S, M, P, Q, V, Headers) -> - request(Rest, S, M, P, Q, V, lists:reverse(Headers)); -parse_header(Buffer, State=#state{max_header_name_length=MaxLength}, - M, P, Q, V, H) -> - case match_colon(Buffer, 0) of - nomatch when byte_size(Buffer) > MaxLength -> - error_terminate(400, State); - nomatch -> - wait_header(Buffer, State, M, P, Q, V, H); - _ -> - parse_hd_name(Buffer, State, M, P, Q, V, H, <<>>) - end. - -match_colon(<< $:, _/bits >>, N) -> - N; -match_colon(<< _, Rest/bits >>, N) -> - match_colon(Rest, N + 1); -match_colon(_, _) -> - nomatch. - -parse_hd_name(<< C, Rest/bits >>, S, M, P, Q, V, H, SoFar) -> - case C of - $: -> parse_hd_before_value(Rest, S, M, P, Q, V, H, SoFar); - $\s -> parse_hd_name_ws(Rest, S, M, P, Q, V, H, SoFar); - $\t -> parse_hd_name_ws(Rest, S, M, P, Q, V, H, SoFar); - ?INLINE_LOWERCASE(parse_hd_name, Rest, S, M, P, Q, V, H, SoFar) - end. - -parse_hd_name_ws(<< C, Rest/bits >>, S, M, P, Q, V, H, Name) -> - case C of - $\s -> parse_hd_name_ws(Rest, S, M, P, Q, V, H, Name); - $\t -> parse_hd_name_ws(Rest, S, M, P, Q, V, H, Name); - $: -> parse_hd_before_value(Rest, S, M, P, Q, V, H, Name) - end. - -wait_hd_before_value(Buffer, State=#state{ - socket=Socket, transport=Transport, until=Until}, - M, P, Q, V, H, N) -> - case recv(Socket, Transport, Until) of - {ok, Data} -> - parse_hd_before_value(<< Buffer/binary, Data/binary >>, - State, M, P, Q, V, H, N); - {error, timeout} -> - error_terminate(408, State); - {error, _} -> - terminate(State) - end. - -parse_hd_before_value(<< $\s, Rest/bits >>, S, M, P, Q, V, H, N) -> - parse_hd_before_value(Rest, S, M, P, Q, V, H, N); -parse_hd_before_value(<< $\t, Rest/bits >>, S, M, P, Q, V, H, N) -> - parse_hd_before_value(Rest, S, M, P, Q, V, H, N); -parse_hd_before_value(Buffer, State=#state{ - max_header_value_length=MaxLength}, M, P, Q, V, H, N) -> - case match_eol(Buffer, 0) of - nomatch when byte_size(Buffer) > MaxLength -> - error_terminate(400, State); - nomatch -> - wait_hd_before_value(Buffer, State, M, P, Q, V, H, N); - _ -> - parse_hd_value(Buffer, State, M, P, Q, V, H, N, <<>>) - end. - -%% We completely ignore the first argument which is always -%% the empty binary. We keep it there because we don't want -%% to change the other arguments' position and trigger costy -%% operations for no reasons. -wait_hd_value(_, State=#state{ - socket=Socket, transport=Transport, until=Until}, - M, P, Q, V, H, N, SoFar) -> - case recv(Socket, Transport, Until) of - {ok, Data} -> - parse_hd_value(Data, State, M, P, Q, V, H, N, SoFar); - {error, timeout} -> - error_terminate(408, State); - {error, _} -> - terminate(State) - end. - -%% Pushing back as much as we could the retrieval of new data -%% to check for multilines allows us to avoid a few tests in -%% the critical path, but forces us to have a special function. -wait_hd_value_nl(_, State=#state{ - socket=Socket, transport=Transport, until=Until}, - M, P, Q, V, Headers, Name, SoFar) -> - case recv(Socket, Transport, Until) of - {ok, << C, Data/bits >>} when C =:= $\s; C =:= $\t -> - parse_hd_value(Data, State, M, P, Q, V, Headers, Name, SoFar); - {ok, Data} -> - parse_header(Data, State, M, P, Q, V, [{Name, SoFar}|Headers]); - {error, timeout} -> - error_terminate(408, State); - {error, _} -> - terminate(State) - end. - -parse_hd_value(<< $\r, Rest/bits >>, S, M, P, Q, V, Headers, Name, SoFar) -> - case Rest of - << $\n >> -> - wait_hd_value_nl(<<>>, S, M, P, Q, V, Headers, Name, SoFar); - << $\n, C, Rest2/bits >> when C =:= $\s; C =:= $\t -> - parse_hd_value(Rest2, S, M, P, Q, V, Headers, Name, - << SoFar/binary, C >>); - << $\n, Rest2/bits >> -> - parse_header(Rest2, S, M, P, Q, V, [{Name, SoFar}|Headers]) - end; -parse_hd_value(<< C, Rest/bits >>, S, M, P, Q, V, H, N, SoFar) -> - parse_hd_value(Rest, S, M, P, Q, V, H, N, << SoFar/binary, C >>); -parse_hd_value(<<>>, State=#state{max_header_value_length=MaxLength}, - _, _, _, _, _, _, SoFar) when byte_size(SoFar) > MaxLength -> - error_terminate(400, State); -parse_hd_value(<<>>, S, M, P, Q, V, H, N, SoFar) -> - wait_hd_value(<<>>, S, M, P, Q, V, H, N, SoFar). - -request(B, State=#state{transport=Transport}, M, P, Q, Version, Headers) -> - case lists:keyfind(<<"host">>, 1, Headers) of - false when Version =:= 'HTTP/1.1' -> - error_terminate(400, State); - false -> - request(B, State, M, P, Q, Version, Headers, - <<>>, default_port(Transport:name())); - {_, RawHost} -> - try parse_host(RawHost, false, <<>>) of - {Host, undefined} -> - request(B, State, M, P, Q, Version, Headers, - Host, default_port(Transport:name())); - {Host, Port} -> - request(B, State, M, P, Q, Version, Headers, - Host, Port) - catch _:_ -> - error_terminate(400, State) - end - end. - --spec default_port(atom()) -> 80 | 443. -default_port(ssl) -> 443; -default_port(_) -> 80. - -%% Same code as cow_http:parse_fullhost/1, but inline because we -%% really want this to go fast. -parse_host(<< $[, Rest/bits >>, false, <<>>) -> - parse_host(Rest, true, << $[ >>); -parse_host(<<>>, false, Acc) -> - {Acc, undefined}; -parse_host(<< $:, Rest/bits >>, false, Acc) -> - {Acc, list_to_integer(binary_to_list(Rest))}; -parse_host(<< $], Rest/bits >>, true, Acc) -> - parse_host(Rest, false, << Acc/binary, $] >>); -parse_host(<< C, Rest/bits >>, E, Acc) -> - case C of - ?INLINE_LOWERCASE(parse_host, Rest, E, Acc) - end. - -%% End of request parsing. -%% -%% We create the Req object and start handling the request. - -request(Buffer, State=#state{socket=Socket, transport=Transport, - req_keepalive=ReqKeepalive, max_keepalive=MaxKeepalive, - compress=Compress, onresponse=OnResponse}, - Method, Path, Query, Version, Headers, Host, Port) -> - case Transport:peername(Socket) of - {ok, Peer} -> - Req = cowboy_req:new(Socket, Transport, Peer, Method, Path, - Query, Version, Headers, Host, Port, Buffer, - ReqKeepalive < MaxKeepalive, Compress, OnResponse), - onrequest(Req, State); - {error, _} -> - %% Couldn't read the peer address; connection is gone. - terminate(State) - end. - -%% Call the global onrequest callback. The callback can send a reply, -%% in which case we consider the request handled and move on to the next -%% one. Note that since we haven't dispatched yet, we don't know the -%% handler, host_info, path_info or bindings yet. --spec onrequest(cowboy_req:req(), #state{}) -> ok. -onrequest(Req, State=#state{onrequest=undefined}) -> - execute(Req, State); -onrequest(Req, State=#state{onrequest=OnRequest}) -> - Req2 = OnRequest(Req), - case cowboy_req:get(resp_state, Req2) of - waiting -> execute(Req2, State); - _ -> next_request(Req2, State, ok) - end. - --spec execute(cowboy_req:req(), #state{}) -> ok. -execute(Req, State=#state{middlewares=Middlewares, env=Env}) -> - execute(Req, State, Env, Middlewares). - --spec execute(cowboy_req:req(), #state{}, cowboy_middleware:env(), [module()]) - -> ok. -execute(Req, State, Env, []) -> - next_request(Req, State, get_value(result, Env, ok)); -execute(Req, State, Env, [Middleware|Tail]) -> - case Middleware:execute(Req, Env) of - {ok, Req2, Env2} -> - execute(Req2, State, Env2, Tail); - {suspend, Module, Function, Args} -> - erlang:hibernate(?MODULE, resume, - [State, Env, Tail, Module, Function, Args]); - {halt, Req2} -> - next_request(Req2, State, ok); - {error, Code, Req2} -> - error_terminate(Code, Req2, State) - end. - --spec resume(#state{}, cowboy_middleware:env(), [module()], - module(), module(), [any()]) -> ok. -resume(State, Env, Tail, Module, Function, Args) -> - case apply(Module, Function, Args) of - {ok, Req2, Env2} -> - execute(Req2, State, Env2, Tail); - {suspend, Module2, Function2, Args2} -> - erlang:hibernate(?MODULE, resume, - [State, Env, Tail, Module2, Function2, Args2]); - {halt, Req2} -> - next_request(Req2, State, ok); - {error, Code, Req2} -> - error_terminate(Code, Req2, State) - end. - --spec next_request(cowboy_req:req(), #state{}, any()) -> ok. -next_request(Req, State=#state{req_keepalive=Keepalive, timeout=Timeout}, - HandlerRes) -> - cowboy_req:ensure_response(Req, 204), - %% If we are going to close the connection, - %% we do not want to attempt to skip the body. - case cowboy_req:get(connection, Req) of - close -> - terminate(State); - _ -> - %% Skip the body if it is reasonably sized. Close otherwise. - Buffer = case cowboy_req:body(Req) of - {ok, _, Req2} -> cowboy_req:get(buffer, Req2); - _ -> close - end, - %% Flush the resp_sent message before moving on. - if HandlerRes =:= ok, Buffer =/= close -> - receive {cowboy_req, resp_sent} -> ok after 0 -> ok end, - ?MODULE:parse_request(Buffer, - State#state{req_keepalive=Keepalive + 1, - until=until(Timeout)}, 0); - true -> - terminate(State) - end - end. - --spec error_terminate(cowboy:http_status(), #state{}) -> ok. -error_terminate(Status, State=#state{socket=Socket, transport=Transport, - compress=Compress, onresponse=OnResponse}) -> - error_terminate(Status, cowboy_req:new(Socket, Transport, - undefined, <<"GET">>, <<>>, <<>>, 'HTTP/1.1', [], <<>>, - undefined, <<>>, false, Compress, OnResponse), State). - --spec error_terminate(cowboy:http_status(), cowboy_req:req(), #state{}) -> ok. -error_terminate(Status, Req, State) -> - _ = cowboy_req:reply(Status, Req), - terminate(State). - --spec terminate(#state{}) -> ok. -terminate(#state{socket=Socket, transport=Transport}) -> - Transport:close(Socket), - ok. DELETED deps/cowboy/src/cowboy_req.erl Index: deps/cowboy/src/cowboy_req.erl ================================================================== --- deps/cowboy/src/cowboy_req.erl +++ /dev/null @@ -1,1385 +0,0 @@ -%% Copyright (c) 2011-2014, Loïc Hoguin -%% Copyright (c) 2011, Anthony Ramine -%% -%% Permission to use, copy, modify, and/or distribute this software for any -%% purpose with or without fee is hereby granted, provided that the above -%% copyright notice and this permission notice appear in all copies. -%% -%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - --module(cowboy_req). - -%% Request API. --export([new/14]). --export([method/1]). --export([version/1]). --export([peer/1]). --export([host/1]). --export([host_info/1]). --export([port/1]). --export([path/1]). --export([path_info/1]). --export([qs/1]). --export([qs_val/2]). --export([qs_val/3]). --export([qs_vals/1]). --export([host_url/1]). --export([url/1]). --export([binding/2]). --export([binding/3]). --export([bindings/1]). --export([header/2]). --export([header/3]). --export([headers/1]). --export([parse_header/2]). --export([parse_header/3]). --export([cookie/2]). --export([cookie/3]). --export([cookies/1]). --export([meta/2]). --export([meta/3]). --export([set_meta/3]). - -%% Request body API. --export([has_body/1]). --export([body_length/1]). --export([body/1]). --export([body/2]). --export([body_qs/1]). --export([body_qs/2]). - -%% Multipart API. --export([part/1]). --export([part/2]). --export([part_body/1]). --export([part_body/2]). - -%% Response API. --export([set_resp_cookie/4]). --export([set_resp_header/3]). --export([set_resp_body/2]). --export([set_resp_body_fun/2]). --export([set_resp_body_fun/3]). --export([has_resp_header/2]). --export([has_resp_body/1]). --export([delete_resp_header/2]). --export([reply/2]). --export([reply/3]). --export([reply/4]). --export([chunked_reply/2]). --export([chunked_reply/3]). --export([chunk/2]). --export([upgrade_reply/3]). --export([continue/1]). --export([maybe_reply/2]). --export([ensure_response/2]). - -%% Private setter/getter API. --export([append_buffer/2]). --export([get/2]). --export([set/2]). --export([set_bindings/4]). - -%% Misc API. --export([compact/1]). --export([lock/1]). --export([to_list/1]). - --type cookie_opts() :: cow_cookie:cookie_opts(). --export_type([cookie_opts/0]). - --type content_decode_fun() :: fun((binary()) - -> {ok, binary()} - | {error, atom()}). --type transfer_decode_fun() :: fun((binary(), any()) - -> cow_http_te:decode_ret()). - --type body_opts() :: [{continue, boolean()} - | {length, non_neg_integer()} - | {read_length, non_neg_integer()} - | {read_timeout, timeout()} - | {transfer_decode, transfer_decode_fun(), any()} - | {content_decode, content_decode_fun()}]. --export_type([body_opts/0]). - --type resp_body_fun() :: fun((any(), module()) -> ok). --type send_chunk_fun() :: fun((iodata()) -> ok | {error, atom()}). --type resp_chunked_fun() :: fun((send_chunk_fun()) -> ok). - --record(http_req, { - %% Transport. - socket = undefined :: any(), - transport = undefined :: undefined | module(), - connection = keepalive :: keepalive | close, - - %% Request. - pid = undefined :: pid(), - method = <<"GET">> :: binary(), - version = 'HTTP/1.1' :: cowboy:http_version(), - peer = undefined :: undefined | {inet:ip_address(), inet:port_number()}, - host = undefined :: undefined | binary(), - host_info = undefined :: undefined | cowboy_router:tokens(), - port = undefined :: undefined | inet:port_number(), - path = undefined :: binary(), - path_info = undefined :: undefined | cowboy_router:tokens(), - qs = undefined :: binary(), - qs_vals = undefined :: undefined | list({binary(), binary() | true}), - bindings = undefined :: undefined | cowboy_router:bindings(), - headers = [] :: cowboy:http_headers(), - p_headers = [] :: [any()], - cookies = undefined :: undefined | [{binary(), binary()}], - meta = [] :: [{atom(), any()}], - - %% Request body. - body_state = waiting :: waiting | done | {stream, non_neg_integer(), - transfer_decode_fun(), any(), content_decode_fun()}, - buffer = <<>> :: binary(), - multipart = undefined :: undefined | {binary(), binary()}, - - %% Response. - resp_compress = false :: boolean(), - resp_state = waiting :: locked | waiting | waiting_stream - | chunks | stream | done, - resp_headers = [] :: cowboy:http_headers(), - resp_body = <<>> :: iodata() | resp_body_fun() - | {non_neg_integer(), resp_body_fun()} - | {chunked, resp_chunked_fun()}, - - %% Functions. - onresponse = undefined :: undefined | already_called - | cowboy:onresponse_fun() -}). - --opaque req() :: #http_req{}. --export_type([req/0]). - -%% Request API. - --spec new(any(), module(), - undefined | {inet:ip_address(), inet:port_number()}, - binary(), binary(), binary(), - cowboy:http_version(), cowboy:http_headers(), binary(), - inet:port_number() | undefined, binary(), boolean(), boolean(), - undefined | cowboy:onresponse_fun()) - -> req(). -new(Socket, Transport, Peer, Method, Path, Query, - Version, Headers, Host, Port, Buffer, CanKeepalive, - Compress, OnResponse) -> - Req = #http_req{socket=Socket, transport=Transport, pid=self(), peer=Peer, - method=Method, path=Path, qs=Query, version=Version, - headers=Headers, host=Host, port=Port, buffer=Buffer, - resp_compress=Compress, onresponse=OnResponse}, - case CanKeepalive of - false -> - Req#http_req{connection=close}; - true -> - case lists:keyfind(<<"connection">>, 1, Headers) of - false -> - case Version of - 'HTTP/1.1' -> Req; %% keepalive - 'HTTP/1.0' -> Req#http_req{connection=close} - end; - {_, ConnectionHeader} -> - Tokens = cow_http_hd:parse_connection(ConnectionHeader), - Connection = connection_to_atom(Tokens), - Req#http_req{connection=Connection, - p_headers=[{<<"connection">>, Tokens}]} - end - end. - --spec method(Req) -> {binary(), Req} when Req::req(). -method(Req) -> - {Req#http_req.method, Req}. - --spec version(Req) -> {cowboy:http_version(), Req} when Req::req(). -version(Req) -> - {Req#http_req.version, Req}. - --spec peer(Req) - -> {{inet:ip_address(), inet:port_number()}, Req} - when Req::req(). -peer(Req) -> - {Req#http_req.peer, Req}. - --spec host(Req) -> {binary(), Req} when Req::req(). -host(Req) -> - {Req#http_req.host, Req}. - --spec host_info(Req) - -> {cowboy_router:tokens() | undefined, Req} when Req::req(). -host_info(Req) -> - {Req#http_req.host_info, Req}. - --spec port(Req) -> {inet:port_number(), Req} when Req::req(). -port(Req) -> - {Req#http_req.port, Req}. - --spec path(Req) -> {binary(), Req} when Req::req(). -path(Req) -> - {Req#http_req.path, Req}. - --spec path_info(Req) - -> {cowboy_router:tokens() | undefined, Req} when Req::req(). -path_info(Req) -> - {Req#http_req.path_info, Req}. - --spec qs(Req) -> {binary(), Req} when Req::req(). -qs(Req) -> - {Req#http_req.qs, Req}. - --spec qs_val(binary(), Req) - -> {binary() | true | undefined, Req} when Req::req(). -qs_val(Name, Req) when is_binary(Name) -> - qs_val(Name, Req, undefined). - --spec qs_val(binary(), Req, Default) - -> {binary() | true | Default, Req} when Req::req(), Default::any(). -qs_val(Name, Req=#http_req{qs=RawQs, qs_vals=undefined}, Default) - when is_binary(Name) -> - QsVals = cow_qs:parse_qs(RawQs), - qs_val(Name, Req#http_req{qs_vals=QsVals}, Default); -qs_val(Name, Req, Default) -> - case lists:keyfind(Name, 1, Req#http_req.qs_vals) of - {Name, Value} -> {Value, Req}; - false -> {Default, Req} - end. - --spec qs_vals(Req) -> {list({binary(), binary() | true}), Req} when Req::req(). -qs_vals(Req=#http_req{qs=RawQs, qs_vals=undefined}) -> - QsVals = cow_qs:parse_qs(RawQs), - qs_vals(Req#http_req{qs_vals=QsVals}); -qs_vals(Req=#http_req{qs_vals=QsVals}) -> - {QsVals, Req}. - -%% The URL includes the scheme, host and port only. --spec host_url(Req) -> {undefined | binary(), Req} when Req::req(). -host_url(Req=#http_req{port=undefined}) -> - {undefined, Req}; -host_url(Req=#http_req{transport=Transport, host=Host, port=Port}) -> - TransportName = Transport:name(), - Secure = case TransportName of - ssl -> <<"s">>; - _ -> <<>> - end, - PortBin = case {TransportName, Port} of - {ssl, 443} -> <<>>; - {tcp, 80} -> <<>>; - _ -> << ":", (integer_to_binary(Port))/binary >> - end, - {<< "http", Secure/binary, "://", Host/binary, PortBin/binary >>, Req}. - -%% The URL includes the scheme, host, port, path and query string. --spec url(Req) -> {undefined | binary(), Req} when Req::req(). -url(Req=#http_req{}) -> - {HostURL, Req2} = host_url(Req), - url(HostURL, Req2). - -url(undefined, Req=#http_req{}) -> - {undefined, Req}; -url(HostURL, Req=#http_req{path=Path, qs=QS}) -> - QS2 = case QS of - <<>> -> <<>>; - _ -> << "?", QS/binary >> - end, - {<< HostURL/binary, Path/binary, QS2/binary >>, Req}. - --spec binding(atom(), Req) -> {any() | undefined, Req} when Req::req(). -binding(Name, Req) when is_atom(Name) -> - binding(Name, Req, undefined). - --spec binding(atom(), Req, Default) - -> {any() | Default, Req} when Req::req(), Default::any(). -binding(Name, Req, Default) when is_atom(Name) -> - case lists:keyfind(Name, 1, Req#http_req.bindings) of - {Name, Value} -> {Value, Req}; - false -> {Default, Req} - end. - --spec bindings(Req) -> {[{atom(), any()}], Req} when Req::req(). -bindings(Req) -> - {Req#http_req.bindings, Req}. - --spec header(binary(), Req) - -> {binary() | undefined, Req} when Req::req(). -header(Name, Req) -> - header(Name, Req, undefined). - --spec header(binary(), Req, Default) - -> {binary() | Default, Req} when Req::req(), Default::any(). -header(Name, Req, Default) -> - case lists:keyfind(Name, 1, Req#http_req.headers) of - {Name, Value} -> {Value, Req}; - false -> {Default, Req} - end. - --spec headers(Req) -> {cowboy:http_headers(), Req} when Req::req(). -headers(Req) -> - {Req#http_req.headers, Req}. - --spec parse_header(binary(), Req) - -> {ok, any(), Req} | {undefined, binary(), Req} - | {error, badarg} when Req::req(). -parse_header(Name, Req=#http_req{p_headers=PHeaders}) -> - case lists:keyfind(Name, 1, PHeaders) of - false -> parse_header(Name, Req, parse_header_default(Name)); - {Name, Value} -> {ok, Value, Req} - end. - --spec parse_header_default(binary()) -> any(). -parse_header_default(<<"transfer-encoding">>) -> [<<"identity">>]; -parse_header_default(_Name) -> undefined. - --spec parse_header(binary(), Req, any()) - -> {ok, any(), Req} | {undefined, binary(), Req} - | {error, badarg} when Req::req(). -parse_header(Name = <<"accept">>, Req, Default) -> - parse_header(Name, Req, Default, - fun (Value) -> - cowboy_http:list(Value, fun cowboy_http:media_range/2) - end); -parse_header(Name = <<"accept-charset">>, Req, Default) -> - parse_header(Name, Req, Default, - fun (Value) -> - cowboy_http:nonempty_list(Value, fun cowboy_http:conneg/2) - end); -parse_header(Name = <<"accept-encoding">>, Req, Default) -> - parse_header(Name, Req, Default, - fun (Value) -> - cowboy_http:list(Value, fun cowboy_http:conneg/2) - end); -parse_header(Name = <<"accept-language">>, Req, Default) -> - parse_header(Name, Req, Default, - fun (Value) -> - cowboy_http:nonempty_list(Value, fun cowboy_http:language_range/2) - end); -parse_header(Name = <<"authorization">>, Req, Default) -> - parse_header(Name, Req, Default, - fun (Value) -> - cowboy_http:token_ci(Value, fun cowboy_http:authorization/2) - end); -parse_header(Name = <<"content-length">>, Req, Default) -> - parse_header(Name, Req, Default, fun cow_http_hd:parse_content_length/1); -parse_header(Name = <<"content-type">>, Req, Default) -> - parse_header(Name, Req, Default, fun cowboy_http:content_type/1); -parse_header(Name = <<"cookie">>, Req, Default) -> - parse_header(Name, Req, Default, fun cow_cookie:parse_cookie/1); -parse_header(Name = <<"expect">>, Req, Default) -> - parse_header(Name, Req, Default, - fun (Value) -> - cowboy_http:nonempty_list(Value, fun cowboy_http:expectation/2) - end); -parse_header(Name, Req, Default) - when Name =:= <<"if-match">>; - Name =:= <<"if-none-match">> -> - parse_header(Name, Req, Default, fun cowboy_http:entity_tag_match/1); -parse_header(Name, Req, Default) - when Name =:= <<"if-modified-since">>; - Name =:= <<"if-unmodified-since">> -> - parse_header(Name, Req, Default, fun cowboy_http:http_date/1); -parse_header(Name = <<"range">>, Req, Default) -> - parse_header(Name, Req, Default, fun cowboy_http:range/1); -parse_header(Name, Req, Default) - when Name =:= <<"sec-websocket-protocol">>; - Name =:= <<"x-forwarded-for">> -> - parse_header(Name, Req, Default, - fun (Value) -> - cowboy_http:nonempty_list(Value, fun cowboy_http:token/2) - end); -parse_header(Name = <<"transfer-encoding">>, Req, Default) -> - parse_header(Name, Req, Default, fun cow_http_hd:parse_transfer_encoding/1); -%% @todo Product version. -parse_header(Name = <<"upgrade">>, Req, Default) -> - parse_header(Name, Req, Default, - fun (Value) -> - cowboy_http:nonempty_list(Value, fun cowboy_http:token_ci/2) - end); -parse_header(Name = <<"sec-websocket-extensions">>, Req, Default) -> - parse_header(Name, Req, Default, fun cowboy_http:parameterized_tokens/1); -parse_header(Name, Req, Default) -> - {Value, Req2} = header(Name, Req, Default), - {undefined, Value, Req2}. - -parse_header(Name, Req=#http_req{p_headers=PHeaders}, Default, Fun) -> - case header(Name, Req) of - {undefined, Req2} -> - {ok, Default, Req2#http_req{p_headers=[{Name, Default}|PHeaders]}}; - {Value, Req2} -> - case Fun(Value) of - {error, badarg} -> - {error, badarg}; - P -> - {ok, P, Req2#http_req{p_headers=[{Name, P}|PHeaders]}} - end - end. - --spec cookie(binary(), Req) - -> {binary() | undefined, Req} when Req::req(). -cookie(Name, Req) when is_binary(Name) -> - cookie(Name, Req, undefined). - --spec cookie(binary(), Req, Default) - -> {binary() | Default, Req} when Req::req(), Default::any(). -cookie(Name, Req=#http_req{cookies=undefined}, Default) when is_binary(Name) -> - case parse_header(<<"cookie">>, Req) of - {ok, undefined, Req2} -> - {Default, Req2#http_req{cookies=[]}}; - {ok, Cookies, Req2} -> - cookie(Name, Req2#http_req{cookies=Cookies}, Default) - end; -cookie(Name, Req, Default) -> - case lists:keyfind(Name, 1, Req#http_req.cookies) of - {Name, Value} -> {Value, Req}; - false -> {Default, Req} - end. - --spec cookies(Req) -> {list({binary(), binary()}), Req} when Req::req(). -cookies(Req=#http_req{cookies=undefined}) -> - case parse_header(<<"cookie">>, Req) of - {ok, undefined, Req2} -> - {[], Req2#http_req{cookies=[]}}; - {ok, Cookies, Req2} -> - cookies(Req2#http_req{cookies=Cookies}); - %% Flash player incorrectly sends an empty Cookie header. - {error, badarg} -> - {[], Req#http_req{cookies=[]}} - end; -cookies(Req=#http_req{cookies=Cookies}) -> - {Cookies, Req}. - --spec meta(atom(), Req) -> {any() | undefined, Req} when Req::req(). -meta(Name, Req) -> - meta(Name, Req, undefined). - --spec meta(atom(), Req, any()) -> {any(), Req} when Req::req(). -meta(Name, Req, Default) -> - case lists:keyfind(Name, 1, Req#http_req.meta) of - {Name, Value} -> {Value, Req}; - false -> {Default, Req} - end. - --spec set_meta(atom(), any(), Req) -> Req when Req::req(). -set_meta(Name, Value, Req=#http_req{meta=Meta}) -> - Req#http_req{meta=lists:keystore(Name, 1, Meta, {Name, Value})}. - -%% Request Body API. - --spec has_body(req()) -> boolean(). -has_body(Req) -> - case lists:keyfind(<<"content-length">>, 1, Req#http_req.headers) of - {_, <<"0">>} -> - false; - {_, _} -> - true; - _ -> - lists:keymember(<<"transfer-encoding">>, 1, Req#http_req.headers) - end. - -%% The length may not be known if Transfer-Encoding is not identity, -%% and the body hasn't been read at the time of the call. --spec body_length(Req) -> {undefined | non_neg_integer(), Req} when Req::req(). -body_length(Req) -> - case parse_header(<<"transfer-encoding">>, Req) of - {ok, [<<"identity">>], Req2} -> - {ok, Length, Req3} = parse_header(<<"content-length">>, Req2, 0), - {Length, Req3}; - {ok, _, Req2} -> - {undefined, Req2} - end. - --spec body(Req) - -> {ok, binary(), Req} | {more, binary(), Req} - | {error, atom()} when Req::req(). -body(Req) -> - body(Req, []). - --spec body(Req, body_opts()) - -> {ok, binary(), Req} | {more, binary(), Req} - | {error, atom()} when Req::req(). -body(Req=#http_req{body_state=waiting}, Opts) -> - %% Send a 100 continue if needed (enabled by default). - Req1 = case lists:keyfind(continue, 1, Opts) of - {_, false} -> - Req; - _ -> - {ok, ExpectHeader, Req0} = parse_header(<<"expect">>, Req), - ok = case ExpectHeader of - [<<"100-continue">>] -> continue(Req0); - _ -> ok - end, - Req0 - end, - %% Initialize body streaming state. - CFun = case lists:keyfind(content_decode, 1, Opts) of - false -> - fun cowboy_http:ce_identity/1; - {_, CFun0} -> - CFun0 - end, - case lists:keyfind(transfer_decode, 1, Opts) of - false -> - case parse_header(<<"transfer-encoding">>, Req1) of - {ok, [<<"chunked">>], Req2} -> - body(Req2#http_req{body_state={stream, 0, - fun cow_http_te:stream_chunked/2, {0, 0}, CFun}}, Opts); - {ok, [<<"identity">>], Req2} -> - {Len, Req3} = body_length(Req2), - case Len of - 0 -> - {ok, <<>>, Req3#http_req{body_state=done}}; - _ -> - body(Req3#http_req{body_state={stream, Len, - fun cow_http_te:stream_identity/2, {0, Len}, - CFun}}, Opts) - end - end; - {_, TFun, TState} -> - body(Req1#http_req{body_state={stream, 0, - TFun, TState, CFun}}, Opts) - end; -body(Req=#http_req{body_state=done}, _) -> - {ok, <<>>, Req}; -body(Req, Opts) -> - ChunkLen = case lists:keyfind(length, 1, Opts) of - false -> 8000000; - {_, ChunkLen0} -> ChunkLen0 - end, - ReadLen = case lists:keyfind(read_length, 1, Opts) of - false -> 1000000; - {_, ReadLen0} -> ReadLen0 - end, - ReadTimeout = case lists:keyfind(read_timeout, 1, Opts) of - false -> 15000; - {_, ReadTimeout0} -> ReadTimeout0 - end, - body_loop(Req, ReadTimeout, ReadLen, ChunkLen, <<>>). - -body_loop(Req=#http_req{buffer=Buffer, body_state={stream, Length, _, _, _}}, - ReadTimeout, ReadLength, ChunkLength, Acc) -> - {Tag, Res, Req2} = case Buffer of - <<>> -> - body_recv(Req, ReadTimeout, min(Length, ReadLength)); - _ -> - body_decode(Req, ReadTimeout) - end, - case {Tag, Res} of - {ok, {ok, Data}} -> - {ok, << Acc/binary, Data/binary >>, Req2}; - {more, {ok, Data}} -> - Acc2 = << Acc/binary, Data/binary >>, - case byte_size(Acc2) >= ChunkLength of - true -> {more, Acc2, Req2}; - false -> body_loop(Req2, ReadTimeout, ReadLength, ChunkLength, Acc2) - end; - _ -> %% Error. - Res - end. - -body_recv(Req=#http_req{transport=Transport, socket=Socket, buffer=Buffer}, - ReadTimeout, ReadLength) -> - case Transport:recv(Socket, ReadLength, ReadTimeout) of - {ok, Data} -> - body_decode(Req#http_req{buffer= << Buffer/binary, Data/binary >>}, - ReadTimeout); - Error = {error, _} -> - {error, Error, Req} - end. - -%% Two decodings happen. First a decoding function is applied to the -%% transferred data, and then another is applied to the actual content. -%% -%% Transfer encoding is generally used for chunked bodies. The decoding -%% function uses a state to keep track of how much it has read, which is -%% also initialized through this function. -%% -%% Content encoding is generally used for compression. -%% -%% @todo Handle chunked after-the-facts headers. -%% @todo Depending on the length returned we might want to 0 or +5 it. -body_decode(Req=#http_req{buffer=Data, body_state={stream, _, - TDecode, TState, CDecode}}, ReadTimeout) -> - case TDecode(Data, TState) of - more -> - body_recv(Req#http_req{body_state={stream, 0, - TDecode, TState, CDecode}}, ReadTimeout, 0); - {more, Data2, TState2} -> - {more, CDecode(Data2), Req#http_req{body_state={stream, 0, - TDecode, TState2, CDecode}, buffer= <<>>}}; - {more, Data2, Length, TState2} when is_integer(Length) -> - {more, CDecode(Data2), Req#http_req{body_state={stream, Length, - TDecode, TState2, CDecode}, buffer= <<>>}}; - {more, Data2, Rest, TState2} -> - {more, CDecode(Data2), Req#http_req{body_state={stream, 0, - TDecode, TState2, CDecode}, buffer=Rest}}; - {done, TotalLength, Rest} -> - {ok, {ok, <<>>}, body_decode_end(Req, TotalLength, Rest)}; - {done, Data2, TotalLength, Rest} -> - {ok, CDecode(Data2), body_decode_end(Req, TotalLength, Rest)} - end. - -body_decode_end(Req=#http_req{headers=Headers, p_headers=PHeaders}, - TotalLength, Rest) -> - Headers2 = lists:keystore(<<"content-length">>, 1, Headers, - {<<"content-length">>, integer_to_binary(TotalLength)}), - %% At this point we just assume TEs were all decoded. - Headers3 = lists:keydelete(<<"transfer-encoding">>, 1, Headers2), - PHeaders2 = lists:keystore(<<"content-length">>, 1, PHeaders, - {<<"content-length">>, TotalLength}), - PHeaders3 = lists:keydelete(<<"transfer-encoding">>, 1, PHeaders2), - Req#http_req{buffer=Rest, body_state=done, - headers=Headers3, p_headers=PHeaders3}. - --spec body_qs(Req) - -> {ok, [{binary(), binary() | true}], Req} | {error, atom()} - when Req::req(). -body_qs(Req) -> - body_qs(Req, [ - {length, 64000}, - {read_length, 64000}, - {read_timeout, 5000}]). - --spec body_qs(Req, body_opts()) -> {ok, [{binary(), binary() | true}], Req} - | {badlength, Req} | {error, atom()} when Req::req(). -body_qs(Req, Opts) -> - case body(Req, Opts) of - {ok, Body, Req2} -> - {ok, cow_qs:parse_qs(Body), Req2}; - {more, _, Req2} -> - {badlength, Req2}; - {error, Reason} -> - {error, Reason} - end. - -%% Multipart API. - --spec part(Req) - -> {ok, cow_multipart:headers(), Req} | {done, Req} - when Req::req(). -part(Req) -> - part(Req, [ - {length, 64000}, - {read_length, 64000}, - {read_timeout, 5000}]). - --spec part(Req, body_opts()) - -> {ok, cow_multipart:headers(), Req} | {done, Req} - when Req::req(). -part(Req=#http_req{multipart=undefined}, Opts) -> - part(init_multipart(Req), Opts); -part(Req, Opts) -> - {Data, Req2} = stream_multipart(Req, Opts), - part(Data, Opts, Req2). - -part(Buffer, Opts, Req=#http_req{multipart={Boundary, _}}) -> - case cow_multipart:parse_headers(Buffer, Boundary) of - more -> - {Data, Req2} = stream_multipart(Req, Opts), - part(<< Buffer/binary, Data/binary >>, Opts, Req2); - {more, Buffer2} -> - {Data, Req2} = stream_multipart(Req, Opts), - part(<< Buffer2/binary, Data/binary >>, Opts, Req2); - {ok, Headers, Rest} -> - {ok, Headers, Req#http_req{multipart={Boundary, Rest}}}; - %% Ignore epilogue. - {done, _} -> - {done, Req#http_req{multipart=undefined}} - end. - --spec part_body(Req) - -> {ok, binary(), Req} | {more, binary(), Req} - when Req::req(). -part_body(Req) -> - part_body(Req, []). - --spec part_body(Req, body_opts()) - -> {ok, binary(), Req} | {more, binary(), Req} - when Req::req(). -part_body(Req=#http_req{multipart=undefined}, Opts) -> - part_body(init_multipart(Req), Opts); -part_body(Req, Opts) -> - part_body(<<>>, Opts, Req, <<>>). - -part_body(Buffer, Opts, Req=#http_req{multipart={Boundary, _}}, Acc) -> - ChunkLen = case lists:keyfind(length, 1, Opts) of - false -> 8000000; - {_, ChunkLen0} -> ChunkLen0 - end, - case byte_size(Acc) > ChunkLen of - true -> - {more, Acc, Req#http_req{multipart={Boundary, Buffer}}}; - false -> - {Data, Req2} = stream_multipart(Req, Opts), - case cow_multipart:parse_body(<< Buffer/binary, Data/binary >>, Boundary) of - {ok, Body} -> - part_body(<<>>, Opts, Req2, << Acc/binary, Body/binary >>); - {ok, Body, Rest} -> - part_body(Rest, Opts, Req2, << Acc/binary, Body/binary >>); - done -> - {ok, Acc, Req2}; - {done, Body} -> - {ok, << Acc/binary, Body/binary >>, Req2}; - {done, Body, Rest} -> - {ok, << Acc/binary, Body/binary >>, - Req2#http_req{multipart={Boundary, Rest}}} - end - end. - -init_multipart(Req) -> - {ok, {<<"multipart">>, _, Params}, Req2} - = parse_header(<<"content-type">>, Req), - {_, Boundary} = lists:keyfind(<<"boundary">>, 1, Params), - Req2#http_req{multipart={Boundary, <<>>}}. - -stream_multipart(Req=#http_req{body_state=BodyState, multipart={_, <<>>}}, Opts) -> - true = BodyState =/= done, - {_, Data, Req2} = body(Req, Opts), - {Data, Req2}; -stream_multipart(Req=#http_req{multipart={Boundary, Buffer}}, _) -> - {Buffer, Req#http_req{multipart={Boundary, <<>>}}}. - -%% Response API. - -%% The cookie name cannot contain any of the following characters: -%% =,;\s\t\r\n\013\014 -%% -%% The cookie value cannot contain any of the following characters: -%% ,; \t\r\n\013\014 --spec set_resp_cookie(iodata(), iodata(), cookie_opts(), Req) - -> Req when Req::req(). -set_resp_cookie(Name, Value, Opts, Req) -> - Cookie = cow_cookie:setcookie(Name, Value, Opts), - set_resp_header(<<"set-cookie">>, Cookie, Req). - --spec set_resp_header(binary(), iodata(), Req) - -> Req when Req::req(). -set_resp_header(Name, Value, Req=#http_req{resp_headers=RespHeaders}) -> - Req#http_req{resp_headers=[{Name, Value}|RespHeaders]}. - --spec set_resp_body(iodata(), Req) -> Req when Req::req(). -set_resp_body(Body, Req) -> - Req#http_req{resp_body=Body}. - --spec set_resp_body_fun(resp_body_fun(), Req) -> Req when Req::req(). -set_resp_body_fun(StreamFun, Req) when is_function(StreamFun) -> - Req#http_req{resp_body=StreamFun}. - -%% If the body function crashes while writing the response body or writes -%% fewer bytes than declared the behaviour is undefined. --spec set_resp_body_fun(non_neg_integer(), resp_body_fun(), Req) - -> Req when Req::req(); - (chunked, resp_chunked_fun(), Req) - -> Req when Req::req(). -set_resp_body_fun(StreamLen, StreamFun, Req) - when is_integer(StreamLen), is_function(StreamFun) -> - Req#http_req{resp_body={StreamLen, StreamFun}}; -set_resp_body_fun(chunked, StreamFun, Req) - when is_function(StreamFun) -> - Req#http_req{resp_body={chunked, StreamFun}}. - --spec has_resp_header(binary(), req()) -> boolean(). -has_resp_header(Name, #http_req{resp_headers=RespHeaders}) -> - lists:keymember(Name, 1, RespHeaders). - --spec has_resp_body(req()) -> boolean(). -has_resp_body(#http_req{resp_body=RespBody}) when is_function(RespBody) -> - true; -has_resp_body(#http_req{resp_body={chunked, _}}) -> - true; -has_resp_body(#http_req{resp_body={Length, _}}) -> - Length > 0; -has_resp_body(#http_req{resp_body=RespBody}) -> - iolist_size(RespBody) > 0. - --spec delete_resp_header(binary(), Req) - -> Req when Req::req(). -delete_resp_header(Name, Req=#http_req{resp_headers=RespHeaders}) -> - RespHeaders2 = lists:keydelete(Name, 1, RespHeaders), - Req#http_req{resp_headers=RespHeaders2}. - --spec reply(cowboy:http_status(), Req) -> {ok, Req} when Req::req(). -reply(Status, Req=#http_req{resp_body=Body}) -> - reply(Status, [], Body, Req). - --spec reply(cowboy:http_status(), cowboy:http_headers(), Req) - -> {ok, Req} when Req::req(). -reply(Status, Headers, Req=#http_req{resp_body=Body}) -> - reply(Status, Headers, Body, Req). - --spec reply(cowboy:http_status(), cowboy:http_headers(), - iodata() | {non_neg_integer() | resp_body_fun()}, Req) - -> {ok, Req} when Req::req(). -reply(Status, Headers, Body, Req=#http_req{ - socket=Socket, transport=Transport, - version=Version, connection=Connection, - method=Method, resp_compress=Compress, - resp_state=RespState, resp_headers=RespHeaders}) - when RespState =:= waiting; RespState =:= waiting_stream -> - HTTP11Headers = if - Transport =/= cowboy_spdy, Version =:= 'HTTP/1.0', Connection =:= keepalive -> - [{<<"connection">>, atom_to_connection(Connection)}]; - Transport =/= cowboy_spdy, Version =:= 'HTTP/1.1', Connection =:= close -> - [{<<"connection">>, atom_to_connection(Connection)}]; - true -> - [] - end, - Req3 = case Body of - BodyFun when is_function(BodyFun) -> - %% We stream the response body until we close the connection. - RespConn = close, - {RespType, Req2} = if - Transport =:= cowboy_spdy -> - response(Status, Headers, RespHeaders, [ - {<<"date">>, cowboy_clock:rfc1123()}, - {<<"server">>, <<"Cowboy">>} - ], stream, Req); - true -> - response(Status, Headers, RespHeaders, [ - {<<"connection">>, <<"close">>}, - {<<"date">>, cowboy_clock:rfc1123()}, - {<<"server">>, <<"Cowboy">>}, - {<<"transfer-encoding">>, <<"identity">>} - ], <<>>, Req) - end, - if RespType =/= hook, Method =/= <<"HEAD">> -> - BodyFun(Socket, Transport); - true -> ok - end, - Req2#http_req{connection=RespConn}; - {chunked, BodyFun} -> - %% We stream the response body in chunks. - {RespType, Req2} = chunked_response(Status, Headers, Req), - if RespType =/= hook, Method =/= <<"HEAD">> -> - ChunkFun = fun(IoData) -> chunk(IoData, Req2) end, - BodyFun(ChunkFun), - %% Send the last chunk if chunked encoding was used. - if - Version =:= 'HTTP/1.0'; RespState =:= waiting_stream -> - Req2; - true -> - last_chunk(Req2) - end; - true -> Req2 - end; - {ContentLength, BodyFun} -> - %% We stream the response body for ContentLength bytes. - RespConn = response_connection(Headers, Connection), - {RespType, Req2} = response(Status, Headers, RespHeaders, [ - {<<"content-length">>, integer_to_list(ContentLength)}, - {<<"date">>, cowboy_clock:rfc1123()}, - {<<"server">>, <<"Cowboy">>} - |HTTP11Headers], stream, Req), - if RespType =/= hook, Method =/= <<"HEAD">> -> - BodyFun(Socket, Transport); - true -> ok - end, - Req2#http_req{connection=RespConn}; - _ when Compress -> - RespConn = response_connection(Headers, Connection), - Req2 = reply_may_compress(Status, Headers, Body, Req, - RespHeaders, HTTP11Headers, Method), - Req2#http_req{connection=RespConn}; - _ -> - RespConn = response_connection(Headers, Connection), - Req2 = reply_no_compress(Status, Headers, Body, Req, - RespHeaders, HTTP11Headers, Method, iolist_size(Body)), - Req2#http_req{connection=RespConn} - end, - {ok, Req3#http_req{resp_state=done, resp_headers=[], resp_body= <<>>}}. - -reply_may_compress(Status, Headers, Body, Req, - RespHeaders, HTTP11Headers, Method) -> - BodySize = iolist_size(Body), - case parse_header(<<"accept-encoding">>, Req) of - {ok, Encodings, Req2} -> - CanGzip = (BodySize > 300) - andalso (false =:= lists:keyfind(<<"content-encoding">>, - 1, Headers)) - andalso (false =:= lists:keyfind(<<"content-encoding">>, - 1, RespHeaders)) - andalso (false =:= lists:keyfind(<<"transfer-encoding">>, - 1, Headers)) - andalso (false =:= lists:keyfind(<<"transfer-encoding">>, - 1, RespHeaders)) - andalso (Encodings =/= undefined) - andalso (false =/= lists:keyfind(<<"gzip">>, 1, Encodings)), - case CanGzip of - true -> - GzBody = zlib:gzip(Body), - {_, Req3} = response(Status, Headers, RespHeaders, [ - {<<"content-length">>, integer_to_list(byte_size(GzBody))}, - {<<"content-encoding">>, <<"gzip">>}, - {<<"date">>, cowboy_clock:rfc1123()}, - {<<"server">>, <<"Cowboy">>} - |HTTP11Headers], - case Method of <<"HEAD">> -> <<>>; _ -> GzBody end, - Req2), - Req3; - false -> - reply_no_compress(Status, Headers, Body, Req, - RespHeaders, HTTP11Headers, Method, BodySize) - end; - {error, badarg} -> - reply_no_compress(Status, Headers, Body, Req, - RespHeaders, HTTP11Headers, Method, BodySize) - end. - -reply_no_compress(Status, Headers, Body, Req, - RespHeaders, HTTP11Headers, Method, BodySize) -> - {_, Req2} = response(Status, Headers, RespHeaders, [ - {<<"content-length">>, integer_to_list(BodySize)}, - {<<"date">>, cowboy_clock:rfc1123()}, - {<<"server">>, <<"Cowboy">>} - |HTTP11Headers], - case Method of <<"HEAD">> -> <<>>; _ -> Body end, - Req), - Req2. - --spec chunked_reply(cowboy:http_status(), Req) -> {ok, Req} when Req::req(). -chunked_reply(Status, Req) -> - chunked_reply(Status, [], Req). - --spec chunked_reply(cowboy:http_status(), cowboy:http_headers(), Req) - -> {ok, Req} when Req::req(). -chunked_reply(Status, Headers, Req) -> - {_, Req2} = chunked_response(Status, Headers, Req), - {ok, Req2}. - --spec chunk(iodata(), req()) -> ok | {error, atom()}. -chunk(_Data, #http_req{method= <<"HEAD">>}) -> - ok; -chunk(Data, #http_req{socket=Socket, transport=cowboy_spdy, - resp_state=chunks}) -> - cowboy_spdy:stream_data(Socket, Data); -chunk(Data, #http_req{socket=Socket, transport=Transport, - resp_state=stream}) -> - Transport:send(Socket, Data); -chunk(Data, #http_req{socket=Socket, transport=Transport, - resp_state=chunks}) -> - Transport:send(Socket, [integer_to_list(iolist_size(Data), 16), - <<"\r\n">>, Data, <<"\r\n">>]). - -%% If ever made public, need to send nothing if HEAD. --spec last_chunk(Req) -> Req when Req::req(). -last_chunk(Req=#http_req{socket=Socket, transport=cowboy_spdy}) -> - _ = cowboy_spdy:stream_close(Socket), - Req#http_req{resp_state=done}; -last_chunk(Req=#http_req{socket=Socket, transport=Transport}) -> - _ = Transport:send(Socket, <<"0\r\n\r\n">>), - Req#http_req{resp_state=done}. - --spec upgrade_reply(cowboy:http_status(), cowboy:http_headers(), Req) - -> {ok, Req} when Req::req(). -upgrade_reply(Status, Headers, Req=#http_req{transport=Transport, - resp_state=waiting, resp_headers=RespHeaders}) - when Transport =/= cowboy_spdy -> - {_, Req2} = response(Status, Headers, RespHeaders, [ - {<<"connection">>, <<"Upgrade">>} - ], <<>>, Req), - {ok, Req2#http_req{resp_state=done, resp_headers=[], resp_body= <<>>}}. - --spec continue(req()) -> ok | {error, atom()}. -continue(#http_req{socket=Socket, transport=Transport, - version=Version}) -> - HTTPVer = atom_to_binary(Version, latin1), - Transport:send(Socket, - << HTTPVer/binary, " ", (status(100))/binary, "\r\n\r\n" >>). - -%% Meant to be used internally for sending errors after crashes. --spec maybe_reply([{module(), atom(), arity() | [term()], _}], req()) -> ok. -maybe_reply(Stacktrace, Req) -> - receive - {cowboy_req, resp_sent} -> ok - after 0 -> - _ = do_maybe_reply(Stacktrace, Req), - ok - end. - -do_maybe_reply([ - {cow_http_hd, _, _, _}, - {cowboy_req, parse_header, _, _}|_], Req) -> - cowboy_req:reply(400, Req); -do_maybe_reply(_, Req) -> - cowboy_req:reply(500, Req). - --spec ensure_response(req(), cowboy:http_status()) -> ok. -%% The response has already been fully sent to the client. -ensure_response(#http_req{resp_state=done}, _) -> - ok; -%% No response has been sent but everything apparently went fine. -%% Reply with the status code found in the second argument. -ensure_response(Req=#http_req{resp_state=RespState}, Status) - when RespState =:= waiting; RespState =:= waiting_stream -> - _ = reply(Status, [], [], Req), - ok; -%% Terminate the chunked body for HTTP/1.1 only. -ensure_response(#http_req{method= <<"HEAD">>}, _) -> - ok; -ensure_response(Req=#http_req{resp_state=chunks}, _) -> - _ = last_chunk(Req), - ok; -ensure_response(#http_req{}, _) -> - ok. - -%% Private setter/getter API. - --spec append_buffer(binary(), Req) -> Req when Req::req(). -append_buffer(Suffix, Req=#http_req{buffer=Buffer}) -> - Req#http_req{buffer= << Buffer/binary, Suffix/binary >>}. - --spec get(atom(), req()) -> any(); ([atom()], req()) -> any(). -get(List, Req) when is_list(List) -> - [g(Atom, Req) || Atom <- List]; -get(Atom, Req) when is_atom(Atom) -> - g(Atom, Req). - -g(bindings, #http_req{bindings=Ret}) -> Ret; -g(body_state, #http_req{body_state=Ret}) -> Ret; -g(buffer, #http_req{buffer=Ret}) -> Ret; -g(connection, #http_req{connection=Ret}) -> Ret; -g(cookies, #http_req{cookies=Ret}) -> Ret; -g(headers, #http_req{headers=Ret}) -> Ret; -g(host, #http_req{host=Ret}) -> Ret; -g(host_info, #http_req{host_info=Ret}) -> Ret; -g(meta, #http_req{meta=Ret}) -> Ret; -g(method, #http_req{method=Ret}) -> Ret; -g(multipart, #http_req{multipart=Ret}) -> Ret; -g(onresponse, #http_req{onresponse=Ret}) -> Ret; -g(p_headers, #http_req{p_headers=Ret}) -> Ret; -g(path, #http_req{path=Ret}) -> Ret; -g(path_info, #http_req{path_info=Ret}) -> Ret; -g(peer, #http_req{peer=Ret}) -> Ret; -g(pid, #http_req{pid=Ret}) -> Ret; -g(port, #http_req{port=Ret}) -> Ret; -g(qs, #http_req{qs=Ret}) -> Ret; -g(qs_vals, #http_req{qs_vals=Ret}) -> Ret; -g(resp_body, #http_req{resp_body=Ret}) -> Ret; -g(resp_compress, #http_req{resp_compress=Ret}) -> Ret; -g(resp_headers, #http_req{resp_headers=Ret}) -> Ret; -g(resp_state, #http_req{resp_state=Ret}) -> Ret; -g(socket, #http_req{socket=Ret}) -> Ret; -g(transport, #http_req{transport=Ret}) -> Ret; -g(version, #http_req{version=Ret}) -> Ret. - --spec set([{atom(), any()}], Req) -> Req when Req::req(). -set([], Req) -> Req; -set([{bindings, Val}|Tail], Req) -> set(Tail, Req#http_req{bindings=Val}); -set([{body_state, Val}|Tail], Req) -> set(Tail, Req#http_req{body_state=Val}); -set([{buffer, Val}|Tail], Req) -> set(Tail, Req#http_req{buffer=Val}); -set([{connection, Val}|Tail], Req) -> set(Tail, Req#http_req{connection=Val}); -set([{cookies, Val}|Tail], Req) -> set(Tail, Req#http_req{cookies=Val}); -set([{headers, Val}|Tail], Req) -> set(Tail, Req#http_req{headers=Val}); -set([{host, Val}|Tail], Req) -> set(Tail, Req#http_req{host=Val}); -set([{host_info, Val}|Tail], Req) -> set(Tail, Req#http_req{host_info=Val}); -set([{meta, Val}|Tail], Req) -> set(Tail, Req#http_req{meta=Val}); -set([{method, Val}|Tail], Req) -> set(Tail, Req#http_req{method=Val}); -set([{multipart, Val}|Tail], Req) -> set(Tail, Req#http_req{multipart=Val}); -set([{onresponse, Val}|Tail], Req) -> set(Tail, Req#http_req{onresponse=Val}); -set([{p_headers, Val}|Tail], Req) -> set(Tail, Req#http_req{p_headers=Val}); -set([{path, Val}|Tail], Req) -> set(Tail, Req#http_req{path=Val}); -set([{path_info, Val}|Tail], Req) -> set(Tail, Req#http_req{path_info=Val}); -set([{peer, Val}|Tail], Req) -> set(Tail, Req#http_req{peer=Val}); -set([{pid, Val}|Tail], Req) -> set(Tail, Req#http_req{pid=Val}); -set([{port, Val}|Tail], Req) -> set(Tail, Req#http_req{port=Val}); -set([{qs, Val}|Tail], Req) -> set(Tail, Req#http_req{qs=Val}); -set([{qs_vals, Val}|Tail], Req) -> set(Tail, Req#http_req{qs_vals=Val}); -set([{resp_body, Val}|Tail], Req) -> set(Tail, Req#http_req{resp_body=Val}); -set([{resp_headers, Val}|Tail], Req) -> set(Tail, Req#http_req{resp_headers=Val}); -set([{resp_state, Val}|Tail], Req) -> set(Tail, Req#http_req{resp_state=Val}); -set([{socket, Val}|Tail], Req) -> set(Tail, Req#http_req{socket=Val}); -set([{transport, Val}|Tail], Req) -> set(Tail, Req#http_req{transport=Val}); -set([{version, Val}|Tail], Req) -> set(Tail, Req#http_req{version=Val}). - --spec set_bindings(cowboy_router:tokens(), cowboy_router:tokens(), - cowboy_router:bindings(), Req) -> Req when Req::req(). -set_bindings(HostInfo, PathInfo, Bindings, Req) -> - Req#http_req{host_info=HostInfo, path_info=PathInfo, - bindings=Bindings}. - -%% Misc API. - --spec compact(Req) -> Req when Req::req(). -compact(Req) -> - Req#http_req{host_info=undefined, - path_info=undefined, qs_vals=undefined, - bindings=undefined, headers=[], - p_headers=[], cookies=[]}. - --spec lock(Req) -> Req when Req::req(). -lock(Req) -> - Req#http_req{resp_state=locked}. - --spec to_list(req()) -> [{atom(), any()}]. -to_list(Req) -> - lists:zip(record_info(fields, http_req), tl(tuple_to_list(Req))). - -%% Internal. - --spec chunked_response(cowboy:http_status(), cowboy:http_headers(), Req) -> - {normal | hook, Req} when Req::req(). -chunked_response(Status, Headers, Req=#http_req{ - transport=cowboy_spdy, resp_state=waiting, - resp_headers=RespHeaders}) -> - {RespType, Req2} = response(Status, Headers, RespHeaders, [ - {<<"date">>, cowboy_clock:rfc1123()}, - {<<"server">>, <<"Cowboy">>} - ], stream, Req), - {RespType, Req2#http_req{resp_state=chunks, - resp_headers=[], resp_body= <<>>}}; -chunked_response(Status, Headers, Req=#http_req{ - version=Version, connection=Connection, - resp_state=RespState, resp_headers=RespHeaders}) - when RespState =:= waiting; RespState =:= waiting_stream -> - RespConn = response_connection(Headers, Connection), - HTTP11Headers = if - Version =:= 'HTTP/1.0', Connection =:= keepalive -> - [{<<"connection">>, atom_to_connection(Connection)}]; - Version =:= 'HTTP/1.0' -> []; - true -> - MaybeTE = if - RespState =:= waiting_stream -> []; - true -> [{<<"transfer-encoding">>, <<"chunked">>}] - end, - if - Connection =:= close -> - [{<<"connection">>, atom_to_connection(Connection)}|MaybeTE]; - true -> - MaybeTE - end - end, - RespState2 = if - Version =:= 'HTTP/1.1', RespState =:= 'waiting' -> chunks; - true -> stream - end, - {RespType, Req2} = response(Status, Headers, RespHeaders, [ - {<<"date">>, cowboy_clock:rfc1123()}, - {<<"server">>, <<"Cowboy">>} - |HTTP11Headers], <<>>, Req), - {RespType, Req2#http_req{connection=RespConn, resp_state=RespState2, - resp_headers=[], resp_body= <<>>}}. - --spec response(cowboy:http_status(), cowboy:http_headers(), - cowboy:http_headers(), cowboy:http_headers(), stream | iodata(), Req) - -> {normal | hook, Req} when Req::req(). -response(Status, Headers, RespHeaders, DefaultHeaders, Body, Req=#http_req{ - socket=Socket, transport=Transport, version=Version, - pid=ReqPid, onresponse=OnResponse}) -> - FullHeaders = case OnResponse of - already_called -> Headers; - _ -> response_merge_headers(Headers, RespHeaders, DefaultHeaders) - end, - Body2 = case Body of stream -> <<>>; _ -> Body end, - {Status2, FullHeaders2, Req2} = case OnResponse of - already_called -> {Status, FullHeaders, Req}; - undefined -> {Status, FullHeaders, Req}; - OnResponse -> - case OnResponse(Status, FullHeaders, Body2, - %% Don't call 'onresponse' from the hook itself. - Req#http_req{resp_headers=[], resp_body= <<>>, - onresponse=already_called}) of - StHdReq = {_, _, _} -> - StHdReq; - Req1 -> - {Status, FullHeaders, Req1} - end - end, - ReplyType = case Req2#http_req.resp_state of - waiting when Transport =:= cowboy_spdy, Body =:= stream -> - cowboy_spdy:stream_reply(Socket, status(Status2), FullHeaders2), - ReqPid ! {?MODULE, resp_sent}, - normal; - waiting when Transport =:= cowboy_spdy -> - cowboy_spdy:reply(Socket, status(Status2), FullHeaders2, Body), - ReqPid ! {?MODULE, resp_sent}, - normal; - RespState when RespState =:= waiting; RespState =:= waiting_stream -> - HTTPVer = atom_to_binary(Version, latin1), - StatusLine = << HTTPVer/binary, " ", - (status(Status2))/binary, "\r\n" >>, - HeaderLines = [[Key, <<": ">>, Value, <<"\r\n">>] - || {Key, Value} <- FullHeaders2], - Transport:send(Socket, [StatusLine, HeaderLines, <<"\r\n">>, Body2]), - ReqPid ! {?MODULE, resp_sent}, - normal; - _ -> - hook - end, - {ReplyType, Req2}. - --spec response_connection(cowboy:http_headers(), keepalive | close) - -> keepalive | close. -response_connection([], Connection) -> - Connection; -response_connection([{Name, Value}|Tail], Connection) -> - case Name of - <<"connection">> -> - Tokens = cow_http_hd:parse_connection(Value), - connection_to_atom(Tokens); - _ -> - response_connection(Tail, Connection) - end. - --spec response_merge_headers(cowboy:http_headers(), cowboy:http_headers(), - cowboy:http_headers()) -> cowboy:http_headers(). -response_merge_headers(Headers, RespHeaders, DefaultHeaders) -> - Headers2 = [{Key, Value} || {Key, Value} <- Headers], - merge_headers( - merge_headers(Headers2, RespHeaders), - DefaultHeaders). - --spec merge_headers(cowboy:http_headers(), cowboy:http_headers()) - -> cowboy:http_headers(). - -%% Merge headers by prepending the tuples in the second list to the -%% first list. It also handles Set-Cookie properly, which supports -%% duplicated entries. Notice that, while the RFC2109 does allow more -%% than one cookie to be set per Set-Cookie header, we are following -%% the implementation of common web servers and applications which -%% return many distinct headers per each Set-Cookie entry to avoid -%% issues with clients/browser which may not support it. -merge_headers(Headers, []) -> - Headers; -merge_headers(Headers, [{<<"set-cookie">>, Value}|Tail]) -> - merge_headers([{<<"set-cookie">>, Value}|Headers], Tail); -merge_headers(Headers, [{Name, Value}|Tail]) -> - Headers2 = case lists:keymember(Name, 1, Headers) of - true -> Headers; - false -> [{Name, Value}|Headers] - end, - merge_headers(Headers2, Tail). - --spec atom_to_connection(keepalive) -> <<_:80>>; - (close) -> <<_:40>>. -atom_to_connection(keepalive) -> - <<"keep-alive">>; -atom_to_connection(close) -> - <<"close">>. - -%% We don't match on "keep-alive" since it is the default value. --spec connection_to_atom([binary()]) -> keepalive | close. -connection_to_atom([]) -> - keepalive; -connection_to_atom([<<"close">>|_]) -> - close; -connection_to_atom([_|Tail]) -> - connection_to_atom(Tail). - --spec status(cowboy:http_status()) -> binary(). -status(100) -> <<"100 Continue">>; -status(101) -> <<"101 Switching Protocols">>; -status(102) -> <<"102 Processing">>; -status(200) -> <<"200 OK">>; -status(201) -> <<"201 Created">>; -status(202) -> <<"202 Accepted">>; -status(203) -> <<"203 Non-Authoritative Information">>; -status(204) -> <<"204 No Content">>; -status(205) -> <<"205 Reset Content">>; -status(206) -> <<"206 Partial Content">>; -status(207) -> <<"207 Multi-Status">>; -status(226) -> <<"226 IM Used">>; -status(300) -> <<"300 Multiple Choices">>; -status(301) -> <<"301 Moved Permanently">>; -status(302) -> <<"302 Found">>; -status(303) -> <<"303 See Other">>; -status(304) -> <<"304 Not Modified">>; -status(305) -> <<"305 Use Proxy">>; -status(306) -> <<"306 Switch Proxy">>; -status(307) -> <<"307 Temporary Redirect">>; -status(400) -> <<"400 Bad Request">>; -status(401) -> <<"401 Unauthorized">>; -status(402) -> <<"402 Payment Required">>; -status(403) -> <<"403 Forbidden">>; -status(404) -> <<"404 Not Found">>; -status(405) -> <<"405 Method Not Allowed">>; -status(406) -> <<"406 Not Acceptable">>; -status(407) -> <<"407 Proxy Authentication Required">>; -status(408) -> <<"408 Request Timeout">>; -status(409) -> <<"409 Conflict">>; -status(410) -> <<"410 Gone">>; -status(411) -> <<"411 Length Required">>; -status(412) -> <<"412 Precondition Failed">>; -status(413) -> <<"413 Request Entity Too Large">>; -status(414) -> <<"414 Request-URI Too Long">>; -status(415) -> <<"415 Unsupported Media Type">>; -status(416) -> <<"416 Requested Range Not Satisfiable">>; -status(417) -> <<"417 Expectation Failed">>; -status(418) -> <<"418 I'm a teapot">>; -status(422) -> <<"422 Unprocessable Entity">>; -status(423) -> <<"423 Locked">>; -status(424) -> <<"424 Failed Dependency">>; -status(425) -> <<"425 Unordered Collection">>; -status(426) -> <<"426 Upgrade Required">>; -status(428) -> <<"428 Precondition Required">>; -status(429) -> <<"429 Too Many Requests">>; -status(431) -> <<"431 Request Header Fields Too Large">>; -status(500) -> <<"500 Internal Server Error">>; -status(501) -> <<"501 Not Implemented">>; -status(502) -> <<"502 Bad Gateway">>; -status(503) -> <<"503 Service Unavailable">>; -status(504) -> <<"504 Gateway Timeout">>; -status(505) -> <<"505 HTTP Version Not Supported">>; -status(506) -> <<"506 Variant Also Negotiates">>; -status(507) -> <<"507 Insufficient Storage">>; -status(510) -> <<"510 Not Extended">>; -status(511) -> <<"511 Network Authentication Required">>; -status(B) when is_binary(B) -> B. - -%% Tests. - --ifdef(TEST). -url_test() -> - {undefined, _} = - url(#http_req{transport=ranch_tcp, host= <<>>, port= undefined, - path= <<>>, qs= <<>>, pid=self()}), - {<<"http://localhost/path">>, _ } = - url(#http_req{transport=ranch_tcp, host= <<"localhost">>, port=80, - path= <<"/path">>, qs= <<>>, pid=self()}), - {<<"http://localhost:443/path">>, _} = - url(#http_req{transport=ranch_tcp, host= <<"localhost">>, port=443, - path= <<"/path">>, qs= <<>>, pid=self()}), - {<<"http://localhost:8080/path">>, _} = - url(#http_req{transport=ranch_tcp, host= <<"localhost">>, port=8080, - path= <<"/path">>, qs= <<>>, pid=self()}), - {<<"http://localhost:8080/path?dummy=2785">>, _} = - url(#http_req{transport=ranch_tcp, host= <<"localhost">>, port=8080, - path= <<"/path">>, qs= <<"dummy=2785">>, pid=self()}), - {<<"https://localhost/path">>, _} = - url(#http_req{transport=ranch_ssl, host= <<"localhost">>, port=443, - path= <<"/path">>, qs= <<>>, pid=self()}), - {<<"https://localhost:8443/path">>, _} = - url(#http_req{transport=ranch_ssl, host= <<"localhost">>, port=8443, - path= <<"/path">>, qs= <<>>, pid=self()}), - {<<"https://localhost:8443/path?dummy=2785">>, _} = - url(#http_req{transport=ranch_ssl, host= <<"localhost">>, port=8443, - path= <<"/path">>, qs= <<"dummy=2785">>, pid=self()}), - ok. - -connection_to_atom_test_() -> - Tests = [ - {[<<"close">>], close}, - {[<<"keep-alive">>], keepalive}, - {[<<"keep-alive">>, <<"upgrade">>], keepalive} - ], - [{lists:flatten(io_lib:format("~p", [T])), - fun() -> R = connection_to_atom(T) end} || {T, R} <- Tests]. - -merge_headers_test_() -> - Tests = [ - {[{<<"content-length">>,<<"13">>},{<<"server">>,<<"Cowboy">>}], - [{<<"set-cookie">>,<<"foo=bar">>},{<<"content-length">>,<<"11">>}], - [{<<"set-cookie">>,<<"foo=bar">>}, - {<<"content-length">>,<<"13">>}, - {<<"server">>,<<"Cowboy">>}]}, - {[{<<"content-length">>,<<"13">>},{<<"server">>,<<"Cowboy">>}], - [{<<"set-cookie">>,<<"foo=bar">>},{<<"set-cookie">>,<<"bar=baz">>}], - [{<<"set-cookie">>,<<"bar=baz">>}, - {<<"set-cookie">>,<<"foo=bar">>}, - {<<"content-length">>,<<"13">>}, - {<<"server">>,<<"Cowboy">>}]} - ], - [fun() -> Res = merge_headers(L,R) end || {L, R, Res} <- Tests]. --endif. DELETED deps/cowboy/src/cowboy_rest.erl Index: deps/cowboy/src/cowboy_rest.erl ================================================================== --- deps/cowboy/src/cowboy_rest.erl +++ /dev/null @@ -1,1022 +0,0 @@ -%% Copyright (c) 2011-2014, Loïc Hoguin -%% -%% Permission to use, copy, modify, and/or distribute this software for any -%% purpose with or without fee is hereby granted, provided that the above -%% copyright notice and this permission notice appear in all copies. -%% -%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -%% Originally based on the Webmachine Diagram from Alan Dean and -%% Justin Sheehy. --module(cowboy_rest). --behaviour(cowboy_sub_protocol). - --export([upgrade/4]). - --record(state, { - env :: cowboy_middleware:env(), - method = undefined :: binary(), - - %% Handler. - handler :: atom(), - handler_state :: any(), - - %% Allowed methods. Only used for OPTIONS requests. - allowed_methods :: [binary()], - - %% Media type. - content_types_p = [] :: - [{binary() | {binary(), binary(), [{binary(), binary()}] | '*'}, - atom()}], - content_type_a :: undefined - | {binary() | {binary(), binary(), [{binary(), binary()}] | '*'}, - atom()}, - - %% Language. - languages_p = [] :: [binary()], - language_a :: undefined | binary(), - - %% Charset. - charsets_p = [] :: [binary()], - charset_a :: undefined | binary(), - - %% Whether the resource exists. - exists = false :: boolean(), - - %% Cached resource calls. - etag :: undefined | no_call | {strong | weak, binary()}, - last_modified :: undefined | no_call | calendar:datetime(), - expires :: undefined | no_call | calendar:datetime() | binary() -}). - --spec upgrade(Req, Env, module(), any()) - -> {ok, Req, Env} when Req::cowboy_req:req(), Env::cowboy_middleware:env(). -upgrade(Req, Env, Handler, HandlerOpts) -> - Method = cowboy_req:get(method, Req), - case erlang:function_exported(Handler, rest_init, 2) of - true -> - try Handler:rest_init(Req, HandlerOpts) of - {ok, Req2, HandlerState} -> - service_available(Req2, #state{env=Env, method=Method, - handler=Handler, handler_state=HandlerState}) - catch Class:Reason -> - Stacktrace = erlang:get_stacktrace(), - cowboy_req:maybe_reply(Stacktrace, Req), - erlang:Class([ - {reason, Reason}, - {mfa, {Handler, rest_init, 2}}, - {stacktrace, Stacktrace}, - {req, cowboy_req:to_list(Req)}, - {opts, HandlerOpts} - ]) - end; - false -> - service_available(Req, #state{env=Env, method=Method, - handler=Handler}) - end. - -service_available(Req, State) -> - expect(Req, State, service_available, true, fun known_methods/2, 503). - -%% known_methods/2 should return a list of binary methods. -known_methods(Req, State=#state{method=Method}) -> - case call(Req, State, known_methods) of - no_call when Method =:= <<"HEAD">>; Method =:= <<"GET">>; - Method =:= <<"POST">>; Method =:= <<"PUT">>; - Method =:= <<"PATCH">>; Method =:= <<"DELETE">>; - Method =:= <<"OPTIONS">> -> - next(Req, State, fun uri_too_long/2); - no_call -> - next(Req, State, 501); - {halt, Req2, HandlerState} -> - terminate(Req2, State#state{handler_state=HandlerState}); - {List, Req2, HandlerState} -> - State2 = State#state{handler_state=HandlerState}, - case lists:member(Method, List) of - true -> next(Req2, State2, fun uri_too_long/2); - false -> next(Req2, State2, 501) - end - end. - -uri_too_long(Req, State) -> - expect(Req, State, uri_too_long, false, fun allowed_methods/2, 414). - -%% allowed_methods/2 should return a list of binary methods. -allowed_methods(Req, State=#state{method=Method}) -> - case call(Req, State, allowed_methods) of - no_call when Method =:= <<"HEAD">>; Method =:= <<"GET">> -> - next(Req, State, fun malformed_request/2); - no_call when Method =:= <<"OPTIONS">> -> - next(Req, State#state{allowed_methods= - [<<"HEAD">>, <<"GET">>, <<"OPTIONS">>]}, - fun malformed_request/2); - no_call -> - method_not_allowed(Req, State, - [<<"HEAD">>, <<"GET">>, <<"OPTIONS">>]); - {halt, Req2, HandlerState} -> - terminate(Req2, State#state{handler_state=HandlerState}); - {List, Req2, HandlerState} -> - State2 = State#state{handler_state=HandlerState}, - case lists:member(Method, List) of - true when Method =:= <<"OPTIONS">> -> - next(Req2, State2#state{allowed_methods=List}, - fun malformed_request/2); - true -> - next(Req2, State2, fun malformed_request/2); - false -> - method_not_allowed(Req2, State2, List) - end - end. - -method_not_allowed(Req, State, []) -> - Req2 = cowboy_req:set_resp_header(<<"allow">>, <<>>, Req), - respond(Req2, State, 405); -method_not_allowed(Req, State, Methods) -> - << ", ", Allow/binary >> = << << ", ", M/binary >> || M <- Methods >>, - Req2 = cowboy_req:set_resp_header(<<"allow">>, Allow, Req), - respond(Req2, State, 405). - -malformed_request(Req, State) -> - expect(Req, State, malformed_request, false, fun is_authorized/2, 400). - -%% is_authorized/2 should return true or {false, WwwAuthenticateHeader}. -is_authorized(Req, State) -> - case call(Req, State, is_authorized) of - no_call -> - forbidden(Req, State); - {halt, Req2, HandlerState} -> - terminate(Req2, State#state{handler_state=HandlerState}); - {true, Req2, HandlerState} -> - forbidden(Req2, State#state{handler_state=HandlerState}); - {{false, AuthHead}, Req2, HandlerState} -> - Req3 = cowboy_req:set_resp_header( - <<"www-authenticate">>, AuthHead, Req2), - respond(Req3, State#state{handler_state=HandlerState}, 401) - end. - -forbidden(Req, State) -> - expect(Req, State, forbidden, false, fun valid_content_headers/2, 403). - -valid_content_headers(Req, State) -> - expect(Req, State, valid_content_headers, true, - fun known_content_type/2, 501). - -known_content_type(Req, State) -> - expect(Req, State, known_content_type, true, - fun valid_entity_length/2, 415). - -valid_entity_length(Req, State) -> - expect(Req, State, valid_entity_length, true, fun options/2, 413). - -%% If you need to add additional headers to the response at this point, -%% you should do it directly in the options/2 call using set_resp_headers. -options(Req, State=#state{allowed_methods=Methods, method= <<"OPTIONS">>}) -> - case call(Req, State, options) of - no_call when Methods =:= [] -> - Req2 = cowboy_req:set_resp_header(<<"allow">>, <<>>, Req), - respond(Req2, State, 200); - no_call -> - << ", ", Allow/binary >> - = << << ", ", M/binary >> || M <- Methods >>, - Req2 = cowboy_req:set_resp_header(<<"allow">>, Allow, Req), - respond(Req2, State, 200); - {halt, Req2, HandlerState} -> - terminate(Req2, State#state{handler_state=HandlerState}); - {ok, Req2, HandlerState} -> - respond(Req2, State#state{handler_state=HandlerState}, 200) - end; -options(Req, State) -> - content_types_provided(Req, State). - -%% content_types_provided/2 should return a list of content types and their -%% associated callback function as a tuple: {{Type, SubType, Params}, Fun}. -%% Type and SubType are the media type as binary. Params is a list of -%% Key/Value tuple, with Key and Value a binary. Fun is the name of the -%% callback that will be used to return the content of the response. It is -%% given as an atom. -%% -%% An example of such return value would be: -%% {{<<"text">>, <<"html">>, []}, to_html} -%% -%% Note that it is also possible to return a binary content type that will -%% then be parsed by Cowboy. However note that while this may make your -%% resources a little more readable, this is a lot less efficient. -%% -%% An example of such return value would be: -%% {<<"text/html">>, to_html} -content_types_provided(Req, State) -> - case call(Req, State, content_types_provided) of - no_call -> - State2 = State#state{ - content_types_p=[{{<<"text">>, <<"html">>, '*'}, to_html}]}, - case cowboy_req:parse_header(<<"accept">>, Req) of - {error, badarg} -> - respond(Req, State2, 400); - {ok, undefined, Req2} -> - languages_provided( - cowboy_req:set_meta(media_type, {<<"text">>, <<"html">>, []}, Req2), - State2#state{content_type_a={{<<"text">>, <<"html">>, []}, to_html}}); - {ok, Accept, Req2} -> - Accept2 = prioritize_accept(Accept), - choose_media_type(Req2, State2, Accept2) - end; - {halt, Req2, HandlerState} -> - terminate(Req2, State#state{handler_state=HandlerState}); - {[], Req2, HandlerState} -> - not_acceptable(Req2, State#state{handler_state=HandlerState}); - {CTP, Req2, HandlerState} -> - CTP2 = [normalize_content_types(P) || P <- CTP], - State2 = State#state{ - handler_state=HandlerState, content_types_p=CTP2}, - case cowboy_req:parse_header(<<"accept">>, Req2) of - {error, badarg} -> - respond(Req2, State2, 400); - {ok, undefined, Req3} -> - {PMT, _Fun} = HeadCTP = hd(CTP2), - languages_provided( - cowboy_req:set_meta(media_type, PMT, Req3), - State2#state{content_type_a=HeadCTP}); - {ok, Accept, Req3} -> - Accept2 = prioritize_accept(Accept), - choose_media_type(Req3, State2, Accept2) - end - end. - -normalize_content_types({ContentType, Callback}) - when is_binary(ContentType) -> - {cowboy_http:content_type(ContentType), Callback}; -normalize_content_types(Normalized) -> - Normalized. - -prioritize_accept(Accept) -> - lists:sort( - fun ({MediaTypeA, Quality, _AcceptParamsA}, - {MediaTypeB, Quality, _AcceptParamsB}) -> - %% Same quality, check precedence in more details. - prioritize_mediatype(MediaTypeA, MediaTypeB); - ({_MediaTypeA, QualityA, _AcceptParamsA}, - {_MediaTypeB, QualityB, _AcceptParamsB}) -> - %% Just compare the quality. - QualityA > QualityB - end, Accept). - -%% Media ranges can be overridden by more specific media ranges or -%% specific media types. If more than one media range applies to a given -%% type, the most specific reference has precedence. -%% -%% We always choose B over A when we can't decide between the two. -prioritize_mediatype({TypeA, SubTypeA, ParamsA}, {TypeB, SubTypeB, ParamsB}) -> - case TypeB of - TypeA -> - case SubTypeB of - SubTypeA -> length(ParamsA) > length(ParamsB); - <<"*">> -> true; - _Any -> false - end; - <<"*">> -> true; - _Any -> false - end. - -%% Ignoring the rare AcceptParams. Not sure what should be done about them. -choose_media_type(Req, State, []) -> - not_acceptable(Req, State); -choose_media_type(Req, State=#state{content_types_p=CTP}, - [MediaType|Tail]) -> - match_media_type(Req, State, Tail, CTP, MediaType). - -match_media_type(Req, State, Accept, [], _MediaType) -> - choose_media_type(Req, State, Accept); -match_media_type(Req, State, Accept, CTP, - MediaType = {{<<"*">>, <<"*">>, _Params_A}, _QA, _APA}) -> - match_media_type_params(Req, State, Accept, CTP, MediaType); -match_media_type(Req, State, Accept, - CTP = [{{Type, SubType_P, _PP}, _Fun}|_Tail], - MediaType = {{Type, SubType_A, _PA}, _QA, _APA}) - when SubType_P =:= SubType_A; SubType_A =:= <<"*">> -> - match_media_type_params(Req, State, Accept, CTP, MediaType); -match_media_type(Req, State, Accept, [_Any|Tail], MediaType) -> - match_media_type(Req, State, Accept, Tail, MediaType). - -match_media_type_params(Req, State, _Accept, - [Provided = {{TP, STP, '*'}, _Fun}|_Tail], - {{_TA, _STA, Params_A}, _QA, _APA}) -> - PMT = {TP, STP, Params_A}, - languages_provided(cowboy_req:set_meta(media_type, PMT, Req), - State#state{content_type_a=Provided}); -match_media_type_params(Req, State, Accept, - [Provided = {PMT = {_TP, _STP, Params_P}, _Fun}|Tail], - MediaType = {{_TA, _STA, Params_A}, _QA, _APA}) -> - case lists:sort(Params_P) =:= lists:sort(Params_A) of - true -> - languages_provided(cowboy_req:set_meta(media_type, PMT, Req), - State#state{content_type_a=Provided}); - false -> - match_media_type(Req, State, Accept, Tail, MediaType) - end. - -%% languages_provided should return a list of binary values indicating -%% which languages are accepted by the resource. -%% -%% @todo I suppose we should also ask the resource if it wants to -%% set a language itself or if it wants it to be automatically chosen. -languages_provided(Req, State) -> - case call(Req, State, languages_provided) of - no_call -> - charsets_provided(Req, State); - {halt, Req2, HandlerState} -> - terminate(Req2, State#state{handler_state=HandlerState}); - {[], Req2, HandlerState} -> - not_acceptable(Req2, State#state{handler_state=HandlerState}); - {LP, Req2, HandlerState} -> - State2 = State#state{handler_state=HandlerState, languages_p=LP}, - {ok, AcceptLanguage, Req3} = - cowboy_req:parse_header(<<"accept-language">>, Req2), - case AcceptLanguage of - undefined -> - set_language(Req3, State2#state{language_a=hd(LP)}); - AcceptLanguage -> - AcceptLanguage2 = prioritize_languages(AcceptLanguage), - choose_language(Req3, State2, AcceptLanguage2) - end - end. - -%% A language-range matches a language-tag if it exactly equals the tag, -%% or if it exactly equals a prefix of the tag such that the first tag -%% character following the prefix is "-". The special range "*", if -%% present in the Accept-Language field, matches every tag not matched -%% by any other range present in the Accept-Language field. -%% -%% @todo The last sentence probably means we should always put '*' -%% at the end of the list. -prioritize_languages(AcceptLanguages) -> - lists:sort( - fun ({_TagA, QualityA}, {_TagB, QualityB}) -> - QualityA > QualityB - end, AcceptLanguages). - -choose_language(Req, State, []) -> - not_acceptable(Req, State); -choose_language(Req, State=#state{languages_p=LP}, [Language|Tail]) -> - match_language(Req, State, Tail, LP, Language). - -match_language(Req, State, Accept, [], _Language) -> - choose_language(Req, State, Accept); -match_language(Req, State, _Accept, [Provided|_Tail], {'*', _Quality}) -> - set_language(Req, State#state{language_a=Provided}); -match_language(Req, State, _Accept, [Provided|_Tail], {Provided, _Quality}) -> - set_language(Req, State#state{language_a=Provided}); -match_language(Req, State, Accept, [Provided|Tail], - Language = {Tag, _Quality}) -> - Length = byte_size(Tag), - case Provided of - << Tag:Length/binary, $-, _Any/bits >> -> - set_language(Req, State#state{language_a=Provided}); - _Any -> - match_language(Req, State, Accept, Tail, Language) - end. - -set_language(Req, State=#state{language_a=Language}) -> - Req2 = cowboy_req:set_resp_header(<<"content-language">>, Language, Req), - charsets_provided(cowboy_req:set_meta(language, Language, Req2), State). - -%% charsets_provided should return a list of binary values indicating -%% which charsets are accepted by the resource. -charsets_provided(Req, State) -> - case call(Req, State, charsets_provided) of - no_call -> - set_content_type(Req, State); - {halt, Req2, HandlerState} -> - terminate(Req2, State#state{handler_state=HandlerState}); - {[], Req2, HandlerState} -> - not_acceptable(Req2, State#state{handler_state=HandlerState}); - {CP, Req2, HandlerState} -> - State2 = State#state{handler_state=HandlerState, charsets_p=CP}, - {ok, AcceptCharset, Req3} = - cowboy_req:parse_header(<<"accept-charset">>, Req2), - case AcceptCharset of - undefined -> - set_content_type(Req3, State2#state{charset_a=hd(CP)}); - AcceptCharset -> - AcceptCharset2 = prioritize_charsets(AcceptCharset), - choose_charset(Req3, State2, AcceptCharset2) - end - end. - -%% The special value "*", if present in the Accept-Charset field, -%% matches every character set (including ISO-8859-1) which is not -%% mentioned elsewhere in the Accept-Charset field. If no "*" is present -%% in an Accept-Charset field, then all character sets not explicitly -%% mentioned get a quality value of 0, except for ISO-8859-1, which gets -%% a quality value of 1 if not explicitly mentioned. -prioritize_charsets(AcceptCharsets) -> - AcceptCharsets2 = lists:sort( - fun ({_CharsetA, QualityA}, {_CharsetB, QualityB}) -> - QualityA > QualityB - end, AcceptCharsets), - case lists:keymember(<<"*">>, 1, AcceptCharsets2) of - true -> AcceptCharsets2; - false -> - case lists:keymember(<<"iso-8859-1">>, 1, AcceptCharsets2) of - true -> AcceptCharsets2; - false -> [{<<"iso-8859-1">>, 1000}|AcceptCharsets2] - end - end. - -choose_charset(Req, State, []) -> - not_acceptable(Req, State); -choose_charset(Req, State=#state{charsets_p=CP}, [Charset|Tail]) -> - match_charset(Req, State, Tail, CP, Charset). - -match_charset(Req, State, Accept, [], _Charset) -> - choose_charset(Req, State, Accept); -match_charset(Req, State, _Accept, [Provided|_], {Provided, _}) -> - set_content_type(Req, State#state{charset_a=Provided}); -match_charset(Req, State, Accept, [_|Tail], Charset) -> - match_charset(Req, State, Accept, Tail, Charset). - -set_content_type(Req, State=#state{ - content_type_a={{Type, SubType, Params}, _Fun}, - charset_a=Charset}) -> - ParamsBin = set_content_type_build_params(Params, []), - ContentType = [Type, <<"/">>, SubType, ParamsBin], - ContentType2 = case Charset of - undefined -> ContentType; - Charset -> [ContentType, <<"; charset=">>, Charset] - end, - Req2 = cowboy_req:set_resp_header(<<"content-type">>, ContentType2, Req), - encodings_provided(cowboy_req:set_meta(charset, Charset, Req2), State). - -set_content_type_build_params('*', []) -> - <<>>; -set_content_type_build_params([], []) -> - <<>>; -set_content_type_build_params([], Acc) -> - lists:reverse(Acc); -set_content_type_build_params([{Attr, Value}|Tail], Acc) -> - set_content_type_build_params(Tail, [[Attr, <<"=">>, Value], <<";">>|Acc]). - -%% @todo Match for identity as we provide nothing else for now. -%% @todo Don't forget to set the Content-Encoding header when we reply a body -%% and the found encoding is something other than identity. -encodings_provided(Req, State) -> - variances(Req, State). - -not_acceptable(Req, State) -> - respond(Req, State, 406). - -%% variances/2 should return a list of headers that will be added -%% to the Vary response header. The Accept, Accept-Language, -%% Accept-Charset and Accept-Encoding headers do not need to be -%% specified. -%% -%% @todo Do Accept-Encoding too when we handle it. -%% @todo Does the order matter? -variances(Req, State=#state{content_types_p=CTP, - languages_p=LP, charsets_p=CP}) -> - Variances = case CTP of - [] -> []; - [_] -> []; - [_|_] -> [<<"accept">>] - end, - Variances2 = case LP of - [] -> Variances; - [_] -> Variances; - [_|_] -> [<<"accept-language">>|Variances] - end, - Variances3 = case CP of - [] -> Variances2; - [_] -> Variances2; - [_|_] -> [<<"accept-charset">>|Variances2] - end, - try variances(Req, State, Variances3) of - {Variances4, Req2, State2} -> - case [[<<", ">>, V] || V <- Variances4] of - [] -> - resource_exists(Req2, State2); - [[<<", ">>, H]|Variances5] -> - Req3 = cowboy_req:set_resp_header( - <<"vary">>, [H|Variances5], Req2), - resource_exists(Req3, State2) - end - catch Class:Reason -> - error_terminate(Req, State, Class, Reason, variances) - end. - -variances(Req, State, Variances) -> - case unsafe_call(Req, State, variances) of - no_call -> - {Variances, Req, State}; - {HandlerVariances, Req2, HandlerState} -> - {Variances ++ HandlerVariances, Req2, - State#state{handler_state=HandlerState}} - end. - -resource_exists(Req, State) -> - expect(Req, State, resource_exists, true, - fun if_match_exists/2, fun if_match_must_not_exist/2). - -if_match_exists(Req, State) -> - State2 = State#state{exists=true}, - case cowboy_req:parse_header(<<"if-match">>, Req) of - {ok, undefined, Req2} -> - if_unmodified_since_exists(Req2, State2); - {ok, '*', Req2} -> - if_unmodified_since_exists(Req2, State2); - {ok, ETagsList, Req2} -> - if_match(Req2, State2, ETagsList); - {error, badarg} -> - respond(Req, State2, 400) - end. - -if_match(Req, State, EtagsList) -> - try generate_etag(Req, State) of - {Etag, Req2, State2} -> - case lists:member(Etag, EtagsList) of - true -> if_unmodified_since_exists(Req2, State2); - %% Etag may be `undefined' which cannot be a member. - false -> precondition_failed(Req2, State2) - end - catch Class:Reason -> - error_terminate(Req, State, Class, Reason, generate_etag) - end. - -if_match_must_not_exist(Req, State) -> - case cowboy_req:header(<<"if-match">>, Req) of - {undefined, Req2} -> is_put_to_missing_resource(Req2, State); - {_Any, Req2} -> precondition_failed(Req2, State) - end. - -if_unmodified_since_exists(Req, State) -> - case cowboy_req:parse_header(<<"if-unmodified-since">>, Req) of - {ok, undefined, Req2} -> - if_none_match_exists(Req2, State); - {ok, IfUnmodifiedSince, Req2} -> - if_unmodified_since(Req2, State, IfUnmodifiedSince); - {error, badarg} -> - if_none_match_exists(Req, State) - end. - -%% If LastModified is the atom 'no_call', we continue. -if_unmodified_since(Req, State, IfUnmodifiedSince) -> - try last_modified(Req, State) of - {LastModified, Req2, State2} -> - case LastModified > IfUnmodifiedSince of - true -> precondition_failed(Req2, State2); - false -> if_none_match_exists(Req2, State2) - end - catch Class:Reason -> - error_terminate(Req, State, Class, Reason, last_modified) - end. - -if_none_match_exists(Req, State) -> - case cowboy_req:parse_header(<<"if-none-match">>, Req) of - {ok, undefined, Req2} -> - if_modified_since_exists(Req2, State); - {ok, '*', Req2} -> - precondition_is_head_get(Req2, State); - {ok, EtagsList, Req2} -> - if_none_match(Req2, State, EtagsList); - {error, badarg} -> - respond(Req, State, 400) - end. - -if_none_match(Req, State, EtagsList) -> - try generate_etag(Req, State) of - {Etag, Req2, State2} -> - case Etag of - undefined -> - precondition_failed(Req2, State2); - Etag -> - case lists:member(Etag, EtagsList) of - true -> precondition_is_head_get(Req2, State2); - false -> if_modified_since_exists(Req2, State2) - end - end - catch Class:Reason -> - error_terminate(Req, State, Class, Reason, generate_etag) - end. - -precondition_is_head_get(Req, State=#state{method=Method}) - when Method =:= <<"HEAD">>; Method =:= <<"GET">> -> - not_modified(Req, State); -precondition_is_head_get(Req, State) -> - precondition_failed(Req, State). - -if_modified_since_exists(Req, State) -> - case cowboy_req:parse_header(<<"if-modified-since">>, Req) of - {ok, undefined, Req2} -> - method(Req2, State); - {ok, IfModifiedSince, Req2} -> - if_modified_since_now(Req2, State, IfModifiedSince); - {error, badarg} -> - method(Req, State) - end. - -if_modified_since_now(Req, State, IfModifiedSince) -> - case IfModifiedSince > erlang:universaltime() of - true -> method(Req, State); - false -> if_modified_since(Req, State, IfModifiedSince) - end. - -if_modified_since(Req, State, IfModifiedSince) -> - try last_modified(Req, State) of - {no_call, Req2, State2} -> - method(Req2, State2); - {LastModified, Req2, State2} -> - case LastModified > IfModifiedSince of - true -> method(Req2, State2); - false -> not_modified(Req2, State2) - end - catch Class:Reason -> - error_terminate(Req, State, Class, Reason, last_modified) - end. - -not_modified(Req, State) -> - Req2 = cowboy_req:delete_resp_header(<<"content-type">>, Req), - try set_resp_etag(Req2, State) of - {Req3, State2} -> - try set_resp_expires(Req3, State2) of - {Req4, State3} -> - respond(Req4, State3, 304) - catch Class:Reason -> - error_terminate(Req, State, Class, Reason, expires) - end - catch Class:Reason -> - error_terminate(Req, State, Class, Reason, generate_etag) - end. - -precondition_failed(Req, State) -> - respond(Req, State, 412). - -is_put_to_missing_resource(Req, State=#state{method= <<"PUT">>}) -> - moved_permanently(Req, State, fun is_conflict/2); -is_put_to_missing_resource(Req, State) -> - previously_existed(Req, State). - -%% moved_permanently/2 should return either false or {true, Location} -%% with Location the full new URI of the resource. -moved_permanently(Req, State, OnFalse) -> - case call(Req, State, moved_permanently) of - {{true, Location}, Req2, HandlerState} -> - Req3 = cowboy_req:set_resp_header( - <<"location">>, Location, Req2), - respond(Req3, State#state{handler_state=HandlerState}, 301); - {false, Req2, HandlerState} -> - OnFalse(Req2, State#state{handler_state=HandlerState}); - {halt, Req2, HandlerState} -> - terminate(Req2, State#state{handler_state=HandlerState}); - no_call -> - OnFalse(Req, State) - end. - -previously_existed(Req, State) -> - expect(Req, State, previously_existed, false, - fun (R, S) -> is_post_to_missing_resource(R, S, 404) end, - fun (R, S) -> moved_permanently(R, S, fun moved_temporarily/2) end). - -%% moved_temporarily/2 should return either false or {true, Location} -%% with Location the full new URI of the resource. -moved_temporarily(Req, State) -> - case call(Req, State, moved_temporarily) of - {{true, Location}, Req2, HandlerState} -> - Req3 = cowboy_req:set_resp_header( - <<"location">>, Location, Req2), - respond(Req3, State#state{handler_state=HandlerState}, 307); - {false, Req2, HandlerState} -> - is_post_to_missing_resource(Req2, State#state{handler_state=HandlerState}, 410); - {halt, Req2, HandlerState} -> - terminate(Req2, State#state{handler_state=HandlerState}); - no_call -> - is_post_to_missing_resource(Req, State, 410) - end. - -is_post_to_missing_resource(Req, State=#state{method= <<"POST">>}, OnFalse) -> - allow_missing_post(Req, State, OnFalse); -is_post_to_missing_resource(Req, State, OnFalse) -> - respond(Req, State, OnFalse). - -allow_missing_post(Req, State, OnFalse) -> - expect(Req, State, allow_missing_post, true, fun accept_resource/2, OnFalse). - -method(Req, State=#state{method= <<"DELETE">>}) -> - delete_resource(Req, State); -method(Req, State=#state{method= <<"PUT">>}) -> - is_conflict(Req, State); -method(Req, State=#state{method=Method}) - when Method =:= <<"POST">>; Method =:= <<"PATCH">> -> - accept_resource(Req, State); -method(Req, State=#state{method=Method}) - when Method =:= <<"GET">>; Method =:= <<"HEAD">> -> - set_resp_body_etag(Req, State); -method(Req, State) -> - multiple_choices(Req, State). - -%% delete_resource/2 should start deleting the resource and return. -delete_resource(Req, State) -> - expect(Req, State, delete_resource, false, 500, fun delete_completed/2). - -%% delete_completed/2 indicates whether the resource has been deleted yet. -delete_completed(Req, State) -> - expect(Req, State, delete_completed, true, fun has_resp_body/2, 202). - -is_conflict(Req, State) -> - expect(Req, State, is_conflict, false, fun accept_resource/2, 409). - -%% content_types_accepted should return a list of media types and their -%% associated callback functions in the same format as content_types_provided. -%% -%% The callback will then be called and is expected to process the content -%% pushed to the resource in the request body. -%% -%% content_types_accepted SHOULD return a different list -%% for each HTTP method. -accept_resource(Req, State) -> - case call(Req, State, content_types_accepted) of - no_call -> - respond(Req, State, 415); - {halt, Req2, HandlerState} -> - terminate(Req2, State#state{handler_state=HandlerState}); - {CTA, Req2, HandlerState} -> - CTA2 = [normalize_content_types(P) || P <- CTA], - State2 = State#state{handler_state=HandlerState}, - case cowboy_req:parse_header(<<"content-type">>, Req2) of - {ok, ContentType, Req3} -> - choose_content_type(Req3, State2, ContentType, CTA2); - {error, badarg} -> - respond(Req2, State2, 415) - end - end. - -%% The special content type '*' will always match. It can be used as a -%% catch-all content type for accepting any kind of request content. -%% Note that because it will always match, it should be the last of the -%% list of content types, otherwise it'll shadow the ones following. -choose_content_type(Req, State, _ContentType, []) -> - respond(Req, State, 415); -choose_content_type(Req, State, ContentType, [{Accepted, Fun}|_Tail]) - when Accepted =:= '*'; Accepted =:= ContentType -> - process_content_type(Req, State, Fun); -%% The special parameter '*' will always match any kind of content type -%% parameters. -%% Note that because it will always match, it should be the last of the -%% list for specific content type, otherwise it'll shadow the ones following. -choose_content_type(Req, State, {Type, SubType, Param}, - [{{Type, SubType, AcceptedParam}, Fun}|_Tail]) - when AcceptedParam =:= '*'; AcceptedParam =:= Param -> - process_content_type(Req, State, Fun); -choose_content_type(Req, State, ContentType, [_Any|Tail]) -> - choose_content_type(Req, State, ContentType, Tail). - -process_content_type(Req, State=#state{method=Method, exists=Exists}, Fun) -> - try case call(Req, State, Fun) of - {halt, Req2, HandlerState2} -> - terminate(Req2, State#state{handler_state=HandlerState2}); - {true, Req2, HandlerState2} when Exists -> - State2 = State#state{handler_state=HandlerState2}, - next(Req2, State2, fun has_resp_body/2); - {true, Req2, HandlerState2} -> - State2 = State#state{handler_state=HandlerState2}, - next(Req2, State2, fun maybe_created/2); - {false, Req2, HandlerState2} -> - State2 = State#state{handler_state=HandlerState2}, - respond(Req2, State2, 400); - {{true, ResURL}, Req2, HandlerState2} when Method =:= <<"POST">> -> - State2 = State#state{handler_state=HandlerState2}, - Req3 = cowboy_req:set_resp_header( - <<"location">>, ResURL, Req2), - if - Exists -> respond(Req3, State2, 303); - true -> respond(Req3, State2, 201) - end - end catch Class:Reason = {case_clause, no_call} -> - error_terminate(Req, State, Class, Reason, Fun) - end. - -%% If PUT was used then the resource has been created at the current URL. -%% Otherwise, if a location header has been set then the resource has been -%% created at a new URL. If not, send a 200 or 204 as expected from a -%% POST or PATCH request. -maybe_created(Req, State=#state{method= <<"PUT">>}) -> - respond(Req, State, 201); -maybe_created(Req, State) -> - case cowboy_req:has_resp_header(<<"location">>, Req) of - true -> respond(Req, State, 201); - false -> has_resp_body(Req, State) - end. - -has_resp_body(Req, State) -> - case cowboy_req:has_resp_body(Req) of - true -> multiple_choices(Req, State); - false -> respond(Req, State, 204) - end. - -%% Set the Etag header if any for the response provided. -set_resp_body_etag(Req, State) -> - try set_resp_etag(Req, State) of - {Req2, State2} -> - set_resp_body_last_modified(Req2, State2) - catch Class:Reason -> - error_terminate(Req, State, Class, Reason, generate_etag) - end. - -%% Set the Last-Modified header if any for the response provided. -set_resp_body_last_modified(Req, State) -> - try last_modified(Req, State) of - {LastModified, Req2, State2} -> - case LastModified of - LastModified when is_atom(LastModified) -> - set_resp_body_expires(Req2, State2); - LastModified -> - LastModifiedBin = cowboy_clock:rfc1123(LastModified), - Req3 = cowboy_req:set_resp_header( - <<"last-modified">>, LastModifiedBin, Req2), - set_resp_body_expires(Req3, State2) - end - catch Class:Reason -> - error_terminate(Req, State, Class, Reason, last_modified) - end. - -%% Set the Expires header if any for the response provided. -set_resp_body_expires(Req, State) -> - try set_resp_expires(Req, State) of - {Req2, State2} -> - set_resp_body(Req2, State2) - catch Class:Reason -> - error_terminate(Req, State, Class, Reason, expires) - end. - -%% Set the response headers and call the callback found using -%% content_types_provided/2 to obtain the request body and add -%% it to the response. -set_resp_body(Req, State=#state{content_type_a={_, Callback}}) -> - try case call(Req, State, Callback) of - {halt, Req2, HandlerState2} -> - terminate(Req2, State#state{handler_state=HandlerState2}); - {Body, Req2, HandlerState2} -> - State2 = State#state{handler_state=HandlerState2}, - Req3 = case Body of - {stream, StreamFun} -> - cowboy_req:set_resp_body_fun(StreamFun, Req2); - {stream, Len, StreamFun} -> - cowboy_req:set_resp_body_fun(Len, StreamFun, Req2); - {chunked, StreamFun} -> - cowboy_req:set_resp_body_fun(chunked, StreamFun, Req2); - _Contents -> - cowboy_req:set_resp_body(Body, Req2) - end, - multiple_choices(Req3, State2) - end catch Class:Reason = {case_clause, no_call} -> - error_terminate(Req, State, Class, Reason, Callback) - end. - -multiple_choices(Req, State) -> - expect(Req, State, multiple_choices, false, 200, 300). - -%% Response utility functions. - -set_resp_etag(Req, State) -> - {Etag, Req2, State2} = generate_etag(Req, State), - case Etag of - undefined -> - {Req2, State2}; - Etag -> - Req3 = cowboy_req:set_resp_header( - <<"etag">>, encode_etag(Etag), Req2), - {Req3, State2} - end. - --spec encode_etag({strong | weak, binary()}) -> iolist(). -encode_etag({strong, Etag}) -> [$",Etag,$"]; -encode_etag({weak, Etag}) -> ["W/\"",Etag,$"]. - -set_resp_expires(Req, State) -> - {Expires, Req2, State2} = expires(Req, State), - case Expires of - Expires when is_atom(Expires) -> - {Req2, State2}; - Expires when is_binary(Expires) -> - Req3 = cowboy_req:set_resp_header( - <<"expires">>, Expires, Req2), - {Req3, State2}; - Expires -> - ExpiresBin = cowboy_clock:rfc1123(Expires), - Req3 = cowboy_req:set_resp_header( - <<"expires">>, ExpiresBin, Req2), - {Req3, State2} - end. - -%% Info retrieval. No logic. - -generate_etag(Req, State=#state{etag=no_call}) -> - {undefined, Req, State}; -generate_etag(Req, State=#state{etag=undefined}) -> - case unsafe_call(Req, State, generate_etag) of - no_call -> - {undefined, Req, State#state{etag=no_call}}; - {Etag, Req2, HandlerState} when is_binary(Etag) -> - [Etag2] = cowboy_http:entity_tag_match(Etag), - {Etag2, Req2, State#state{handler_state=HandlerState, etag=Etag2}}; - {Etag, Req2, HandlerState} -> - {Etag, Req2, State#state{handler_state=HandlerState, etag=Etag}} - end; -generate_etag(Req, State=#state{etag=Etag}) -> - {Etag, Req, State}. - -last_modified(Req, State=#state{last_modified=no_call}) -> - {undefined, Req, State}; -last_modified(Req, State=#state{last_modified=undefined}) -> - case unsafe_call(Req, State, last_modified) of - no_call -> - {undefined, Req, State#state{last_modified=no_call}}; - {LastModified, Req2, HandlerState} -> - {LastModified, Req2, State#state{handler_state=HandlerState, - last_modified=LastModified}} - end; -last_modified(Req, State=#state{last_modified=LastModified}) -> - {LastModified, Req, State}. - -expires(Req, State=#state{expires=no_call}) -> - {undefined, Req, State}; -expires(Req, State=#state{expires=undefined}) -> - case unsafe_call(Req, State, expires) of - no_call -> - {undefined, Req, State#state{expires=no_call}}; - {Expires, Req2, HandlerState} -> - {Expires, Req2, State#state{handler_state=HandlerState, - expires=Expires}} - end; -expires(Req, State=#state{expires=Expires}) -> - {Expires, Req, State}. - -%% REST primitives. - -expect(Req, State, Callback, Expected, OnTrue, OnFalse) -> - case call(Req, State, Callback) of - no_call -> - next(Req, State, OnTrue); - {halt, Req2, HandlerState} -> - terminate(Req2, State#state{handler_state=HandlerState}); - {Expected, Req2, HandlerState} -> - next(Req2, State#state{handler_state=HandlerState}, OnTrue); - {_Unexpected, Req2, HandlerState} -> - next(Req2, State#state{handler_state=HandlerState}, OnFalse) - end. - -call(Req, State=#state{handler=Handler, handler_state=HandlerState}, - Callback) -> - case erlang:function_exported(Handler, Callback, 2) of - true -> - try - Handler:Callback(Req, HandlerState) - catch Class:Reason -> - error_terminate(Req, State, Class, Reason, Callback) - end; - false -> - no_call - end. - -unsafe_call(Req, #state{handler=Handler, handler_state=HandlerState}, - Callback) -> - case erlang:function_exported(Handler, Callback, 2) of - true -> Handler:Callback(Req, HandlerState); - false -> no_call - end. - -next(Req, State, Next) when is_function(Next) -> - Next(Req, State); -next(Req, State, StatusCode) when is_integer(StatusCode) -> - respond(Req, State, StatusCode). - -respond(Req, State, StatusCode) -> - {ok, Req2} = cowboy_req:reply(StatusCode, Req), - terminate(Req2, State). - -terminate(Req, State=#state{env=Env}) -> - rest_terminate(Req, State), - {ok, Req, [{result, ok}|Env]}. - -error_terminate(Req, State=#state{handler=Handler, handler_state=HandlerState}, - Class, Reason, Callback) -> - Stacktrace = erlang:get_stacktrace(), - rest_terminate(Req, State), - cowboy_req:maybe_reply(Stacktrace, Req), - erlang:Class([ - {reason, Reason}, - {mfa, {Handler, Callback, 2}}, - {stacktrace, Stacktrace}, - {req, cowboy_req:to_list(Req)}, - {state, HandlerState} - ]). - -rest_terminate(Req, #state{handler=Handler, handler_state=HandlerState}) -> - case erlang:function_exported(Handler, rest_terminate, 2) of - true -> ok = Handler:rest_terminate( - cowboy_req:lock(Req), HandlerState); - false -> ok - end. DELETED deps/cowboy/src/cowboy_router.erl Index: deps/cowboy/src/cowboy_router.erl ================================================================== --- deps/cowboy/src/cowboy_router.erl +++ /dev/null @@ -1,572 +0,0 @@ -%% Copyright (c) 2011-2014, Loïc Hoguin -%% -%% Permission to use, copy, modify, and/or distribute this software for any -%% purpose with or without fee is hereby granted, provided that the above -%% copyright notice and this permission notice appear in all copies. -%% -%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -%% Routing middleware. -%% -%% Resolve the handler to be used for the request based on the -%% routing information found in the dispatch environment value. -%% When found, the handler module and associated data are added to -%% the environment as the handler and handler_opts values -%% respectively. -%% -%% If the route cannot be found, processing stops with either -%% a 400 or a 404 reply. --module(cowboy_router). --behaviour(cowboy_middleware). - --export([compile/1]). --export([execute/2]). - --type bindings() :: [{atom(), binary()}]. --type tokens() :: [binary()]. --export_type([bindings/0]). --export_type([tokens/0]). - --type constraints() :: [{atom(), int} - | {atom(), function, fun ((binary()) -> true | {true, any()} | false)}]. --export_type([constraints/0]). - --type route_match() :: '_' | iodata(). --type route_path() :: {Path::route_match(), Handler::module(), Opts::any()} - | {Path::route_match(), constraints(), Handler::module(), Opts::any()}. --type route_rule() :: {Host::route_match(), Paths::[route_path()]} - | {Host::route_match(), constraints(), Paths::[route_path()]}. --type routes() :: [route_rule()]. --export_type([routes/0]). - --type dispatch_match() :: '_' | <<_:8>> | [binary() | '_' | '...' | atom()]. --type dispatch_path() :: {dispatch_match(), module(), any()}. --type dispatch_rule() :: {Host::dispatch_match(), Paths::[dispatch_path()]}. --opaque dispatch_rules() :: [dispatch_rule()]. --export_type([dispatch_rules/0]). - --spec compile(routes()) -> dispatch_rules(). -compile(Routes) -> - compile(Routes, []). - -compile([], Acc) -> - lists:reverse(Acc); -compile([{Host, Paths}|Tail], Acc) -> - compile([{Host, [], Paths}|Tail], Acc); -compile([{HostMatch, Constraints, Paths}|Tail], Acc) -> - HostRules = case HostMatch of - '_' -> '_'; - _ -> compile_host(HostMatch) - end, - PathRules = compile_paths(Paths, []), - Hosts = case HostRules of - '_' -> [{'_', Constraints, PathRules}]; - _ -> [{R, Constraints, PathRules} || R <- HostRules] - end, - compile(Tail, Hosts ++ Acc). - -compile_host(HostMatch) when is_list(HostMatch) -> - compile_host(list_to_binary(HostMatch)); -compile_host(HostMatch) when is_binary(HostMatch) -> - compile_rules(HostMatch, $., [], [], <<>>). - -compile_paths([], Acc) -> - lists:reverse(Acc); -compile_paths([{PathMatch, Handler, Opts}|Tail], Acc) -> - compile_paths([{PathMatch, [], Handler, Opts}|Tail], Acc); -compile_paths([{PathMatch, Constraints, Handler, Opts}|Tail], Acc) - when is_list(PathMatch) -> - compile_paths([{iolist_to_binary(PathMatch), - Constraints, Handler, Opts}|Tail], Acc); -compile_paths([{'_', Constraints, Handler, Opts}|Tail], Acc) -> - compile_paths(Tail, [{'_', Constraints, Handler, Opts}] ++ Acc); -compile_paths([{<< $/, PathMatch/binary >>, Constraints, Handler, Opts}|Tail], - Acc) -> - PathRules = compile_rules(PathMatch, $/, [], [], <<>>), - Paths = [{lists:reverse(R), Constraints, Handler, Opts} || R <- PathRules], - compile_paths(Tail, Paths ++ Acc); -compile_paths([{PathMatch, _, _, _}|_], _) -> - error({badarg, "The following route MUST begin with a slash: " - ++ binary_to_list(PathMatch)}). - -compile_rules(<<>>, _, Segments, Rules, <<>>) -> - [Segments|Rules]; -compile_rules(<<>>, _, Segments, Rules, Acc) -> - [[Acc|Segments]|Rules]; -compile_rules(<< S, Rest/binary >>, S, Segments, Rules, <<>>) -> - compile_rules(Rest, S, Segments, Rules, <<>>); -compile_rules(<< S, Rest/binary >>, S, Segments, Rules, Acc) -> - compile_rules(Rest, S, [Acc|Segments], Rules, <<>>); -compile_rules(<< $:, Rest/binary >>, S, Segments, Rules, <<>>) -> - {NameBin, Rest2} = compile_binding(Rest, S, <<>>), - Name = binary_to_atom(NameBin, utf8), - compile_rules(Rest2, S, Segments, Rules, Name); -compile_rules(<< $:, _/binary >>, _, _, _, _) -> - erlang:error(badarg); -compile_rules(<< $[, $., $., $., $], Rest/binary >>, S, Segments, Rules, Acc) - when Acc =:= <<>> -> - compile_rules(Rest, S, ['...'|Segments], Rules, Acc); -compile_rules(<< $[, $., $., $., $], Rest/binary >>, S, Segments, Rules, Acc) -> - compile_rules(Rest, S, ['...', Acc|Segments], Rules, Acc); -compile_rules(<< $[, S, Rest/binary >>, S, Segments, Rules, Acc) -> - compile_brackets(Rest, S, [Acc|Segments], Rules); -compile_rules(<< $[, Rest/binary >>, S, Segments, Rules, <<>>) -> - compile_brackets(Rest, S, Segments, Rules); -%% Open bracket in the middle of a segment. -compile_rules(<< $[, _/binary >>, _, _, _, _) -> - erlang:error(badarg); -%% Missing an open bracket. -compile_rules(<< $], _/binary >>, _, _, _, _) -> - erlang:error(badarg); -compile_rules(<< C, Rest/binary >>, S, Segments, Rules, Acc) -> - compile_rules(Rest, S, Segments, Rules, << Acc/binary, C >>). - -%% Everything past $: until the segment separator ($. for hosts, -%% $/ for paths) or $[ or $] or end of binary is the binding name. -compile_binding(<<>>, _, <<>>) -> - erlang:error(badarg); -compile_binding(Rest = <<>>, _, Acc) -> - {Acc, Rest}; -compile_binding(Rest = << C, _/binary >>, S, Acc) - when C =:= S; C =:= $[; C =:= $] -> - {Acc, Rest}; -compile_binding(<< C, Rest/binary >>, S, Acc) -> - compile_binding(Rest, S, << Acc/binary, C >>). - -compile_brackets(Rest, S, Segments, Rules) -> - {Bracket, Rest2} = compile_brackets_split(Rest, <<>>, 0), - Rules1 = compile_rules(Rest2, S, Segments, [], <<>>), - Rules2 = compile_rules(<< Bracket/binary, Rest2/binary >>, - S, Segments, [], <<>>), - Rules ++ Rules2 ++ Rules1. - -%% Missing a close bracket. -compile_brackets_split(<<>>, _, _) -> - erlang:error(badarg); -%% Make sure we don't confuse the closing bracket we're looking for. -compile_brackets_split(<< C, Rest/binary >>, Acc, N) when C =:= $[ -> - compile_brackets_split(Rest, << Acc/binary, C >>, N + 1); -compile_brackets_split(<< C, Rest/binary >>, Acc, N) when C =:= $], N > 0 -> - compile_brackets_split(Rest, << Acc/binary, C >>, N - 1); -%% That's the right one. -compile_brackets_split(<< $], Rest/binary >>, Acc, 0) -> - {Acc, Rest}; -compile_brackets_split(<< C, Rest/binary >>, Acc, N) -> - compile_brackets_split(Rest, << Acc/binary, C >>, N). - --spec execute(Req, Env) - -> {ok, Req, Env} | {error, 400 | 404, Req} - when Req::cowboy_req:req(), Env::cowboy_middleware:env(). -execute(Req, Env) -> - {_, Dispatch} = lists:keyfind(dispatch, 1, Env), - [Host, Path] = cowboy_req:get([host, path], Req), - case match(Dispatch, Host, Path) of - {ok, Handler, HandlerOpts, Bindings, HostInfo, PathInfo} -> - Req2 = cowboy_req:set_bindings(HostInfo, PathInfo, Bindings, Req), - {ok, Req2, [{handler, Handler}, {handler_opts, HandlerOpts}|Env]}; - {error, notfound, host} -> - {error, 400, Req}; - {error, badrequest, path} -> - {error, 400, Req}; - {error, notfound, path} -> - {error, 404, Req} - end. - -%% Internal. - -%% Match hostname tokens and path tokens against dispatch rules. -%% -%% It is typically used for matching tokens for the hostname and path of -%% the request against a global dispatch rule for your listener. -%% -%% Dispatch rules are a list of {Hostname, PathRules} tuples, with -%% PathRules being a list of {Path, HandlerMod, HandlerOpts}. -%% -%% Hostname and Path are match rules and can be either the -%% atom '_', which matches everything, `<<"*">>', which match the -%% wildcard path, or a list of tokens. -%% -%% Each token can be either a binary, the atom '_', -%% the atom '...' or a named atom. A binary token must match exactly, -%% '_' matches everything for a single token, '...' matches -%% everything for the rest of the tokens and a named atom will bind the -%% corresponding token value and return it. -%% -%% The list of hostname tokens is reversed before matching. For example, if -%% we were to match "www.ninenines.eu", we would first match "eu", then -%% "ninenines", then "www". This means that in the context of hostnames, -%% the '...' atom matches properly the lower levels of the domain -%% as would be expected. -%% -%% When a result is found, this function will return the handler module and -%% options found in the dispatch list, a key-value list of bindings and -%% the tokens that were matched by the '...' atom for both the -%% hostname and path. --spec match(dispatch_rules(), Host::binary() | tokens(), Path::binary()) - -> {ok, module(), any(), bindings(), - HostInfo::undefined | tokens(), - PathInfo::undefined | tokens()} - | {error, notfound, host} | {error, notfound, path} - | {error, badrequest, path}. -match([], _, _) -> - {error, notfound, host}; -%% If the host is '_' then there can be no constraints. -match([{'_', [], PathMatchs}|_Tail], _, Path) -> - match_path(PathMatchs, undefined, Path, []); -match([{HostMatch, Constraints, PathMatchs}|Tail], Tokens, Path) - when is_list(Tokens) -> - case list_match(Tokens, HostMatch, []) of - false -> - match(Tail, Tokens, Path); - {true, Bindings, HostInfo} -> - HostInfo2 = case HostInfo of - undefined -> undefined; - _ -> lists:reverse(HostInfo) - end, - case check_constraints(Constraints, Bindings) of - {ok, Bindings2} -> - match_path(PathMatchs, HostInfo2, Path, Bindings2); - nomatch -> - match(Tail, Tokens, Path) - end - end; -match(Dispatch, Host, Path) -> - match(Dispatch, split_host(Host), Path). - --spec match_path([dispatch_path()], - HostInfo::undefined | tokens(), binary() | tokens(), bindings()) - -> {ok, module(), any(), bindings(), - HostInfo::undefined | tokens(), - PathInfo::undefined | tokens()} - | {error, notfound, path} | {error, badrequest, path}. -match_path([], _, _, _) -> - {error, notfound, path}; -%% If the path is '_' then there can be no constraints. -match_path([{'_', [], Handler, Opts}|_Tail], HostInfo, _, Bindings) -> - {ok, Handler, Opts, Bindings, HostInfo, undefined}; -match_path([{<<"*">>, _Constraints, Handler, Opts}|_Tail], HostInfo, <<"*">>, Bindings) -> - {ok, Handler, Opts, Bindings, HostInfo, undefined}; -match_path([{PathMatch, Constraints, Handler, Opts}|Tail], HostInfo, Tokens, - Bindings) when is_list(Tokens) -> - case list_match(Tokens, PathMatch, Bindings) of - false -> - match_path(Tail, HostInfo, Tokens, Bindings); - {true, PathBinds, PathInfo} -> - case check_constraints(Constraints, PathBinds) of - {ok, PathBinds2} -> - {ok, Handler, Opts, PathBinds2, HostInfo, PathInfo}; - nomatch -> - match_path(Tail, HostInfo, Tokens, Bindings) - end - end; -match_path(_Dispatch, _HostInfo, badrequest, _Bindings) -> - {error, badrequest, path}; -match_path(Dispatch, HostInfo, Path, Bindings) -> - match_path(Dispatch, HostInfo, split_path(Path), Bindings). - -check_constraints([], Bindings) -> - {ok, Bindings}; -check_constraints([Constraint|Tail], Bindings) -> - Name = element(1, Constraint), - case lists:keyfind(Name, 1, Bindings) of - false -> - check_constraints(Tail, Bindings); - {_, Value} -> - case check_constraint(Constraint, Value) of - true -> - check_constraints(Tail, Bindings); - {true, Value2} -> - Bindings2 = lists:keyreplace(Name, 1, Bindings, - {Name, Value2}), - check_constraints(Tail, Bindings2); - false -> - nomatch - end - end. - -check_constraint({_, int}, Value) -> - try {true, list_to_integer(binary_to_list(Value))} - catch _:_ -> false - end; -check_constraint({_, function, Fun}, Value) -> - Fun(Value). - --spec split_host(binary()) -> tokens(). -split_host(Host) -> - split_host(Host, []). - -split_host(Host, Acc) -> - case binary:match(Host, <<".">>) of - nomatch when Host =:= <<>> -> - Acc; - nomatch -> - [Host|Acc]; - {Pos, _} -> - << Segment:Pos/binary, _:8, Rest/bits >> = Host, - false = byte_size(Segment) == 0, - split_host(Rest, [Segment|Acc]) - end. - -%% Following RFC2396, this function may return path segments containing any -%% character, including / if, and only if, a / was escaped -%% and part of a path segment. --spec split_path(binary()) -> tokens(). -split_path(<< $/, Path/bits >>) -> - split_path(Path, []); -split_path(_) -> - badrequest. - -split_path(Path, Acc) -> - try - case binary:match(Path, <<"/">>) of - nomatch when Path =:= <<>> -> - lists:reverse([cow_qs:urldecode(S) || S <- Acc]); - nomatch -> - lists:reverse([cow_qs:urldecode(S) || S <- [Path|Acc]]); - {Pos, _} -> - << Segment:Pos/binary, _:8, Rest/bits >> = Path, - split_path(Rest, [Segment|Acc]) - end - catch - error:badarg -> - badrequest - end. - --spec list_match(tokens(), dispatch_match(), bindings()) - -> {true, bindings(), undefined | tokens()} | false. -%% Atom '...' matches any trailing path, stop right now. -list_match(List, ['...'], Binds) -> - {true, Binds, List}; -%% Atom '_' matches anything, continue. -list_match([_E|Tail], ['_'|TailMatch], Binds) -> - list_match(Tail, TailMatch, Binds); -%% Both values match, continue. -list_match([E|Tail], [E|TailMatch], Binds) -> - list_match(Tail, TailMatch, Binds); -%% Bind E to the variable name V and continue, -%% unless V was already defined and E isn't identical to the previous value. -list_match([E|Tail], [V|TailMatch], Binds) when is_atom(V) -> - case lists:keyfind(V, 1, Binds) of - {_, E} -> - list_match(Tail, TailMatch, Binds); - {_, _} -> - false; - false -> - list_match(Tail, TailMatch, [{V, E}|Binds]) - end; -%% Match complete. -list_match([], [], Binds) -> - {true, Binds, undefined}; -%% Values don't match, stop. -list_match(_List, _Match, _Binds) -> - false. - -%% Tests. - --ifdef(TEST). -compile_test_() -> - Tests = [ - %% Match any host and path. - {[{'_', [{'_', h, o}]}], - [{'_', [], [{'_', [], h, o}]}]}, - {[{"cowboy.example.org", - [{"/", ha, oa}, {"/path/to/resource", hb, ob}]}], - [{[<<"org">>, <<"example">>, <<"cowboy">>], [], [ - {[], [], ha, oa}, - {[<<"path">>, <<"to">>, <<"resource">>], [], hb, ob}]}]}, - {[{'_', [{"/path/to/resource/", h, o}]}], - [{'_', [], [{[<<"path">>, <<"to">>, <<"resource">>], [], h, o}]}]}, - % Cyrillic from a latin1 encoded file. - {[{'_', [{[47,208,191,209,131,209,130,209,140,47,208,186,47,209,128, - 208,181,209,129,209,131,209,128,209,129,209,131,47], h, o}]}], - [{'_', [], [{[<<208,191,209,131,209,130,209,140>>, <<208,186>>, - <<209,128,208,181,209,129,209,131,209,128,209,129,209,131>>], - [], h, o}]}]}, - {[{"cowboy.example.org.", [{'_', h, o}]}], - [{[<<"org">>, <<"example">>, <<"cowboy">>], [], [{'_', [], h, o}]}]}, - {[{".cowboy.example.org", [{'_', h, o}]}], - [{[<<"org">>, <<"example">>, <<"cowboy">>], [], [{'_', [], h, o}]}]}, - % Cyrillic from a latin1 encoded file. - {[{[208,189,208,181,208,186,208,184,208,185,46,209,129,208,176, - 208,185,209,130,46,209,128,209,132,46], [{'_', h, o}]}], - [{[<<209,128,209,132>>, <<209,129,208,176,208,185,209,130>>, - <<208,189,208,181,208,186,208,184,208,185>>], - [], [{'_', [], h, o}]}]}, - {[{":subdomain.example.org", [{"/hats/:name/prices", h, o}]}], - [{[<<"org">>, <<"example">>, subdomain], [], [ - {[<<"hats">>, name, <<"prices">>], [], h, o}]}]}, - {[{"ninenines.:_", [{"/hats/:_", h, o}]}], - [{['_', <<"ninenines">>], [], [{[<<"hats">>, '_'], [], h, o}]}]}, - {[{"[www.]ninenines.eu", - [{"/horses", h, o}, {"/hats/[page/:number]", h, o}]}], [ - {[<<"eu">>, <<"ninenines">>], [], [ - {[<<"horses">>], [], h, o}, - {[<<"hats">>], [], h, o}, - {[<<"hats">>, <<"page">>, number], [], h, o}]}, - {[<<"eu">>, <<"ninenines">>, <<"www">>], [], [ - {[<<"horses">>], [], h, o}, - {[<<"hats">>], [], h, o}, - {[<<"hats">>, <<"page">>, number], [], h, o}]}]}, - {[{'_', [{"/hats/[page/[:number]]", h, o}]}], [{'_', [], [ - {[<<"hats">>], [], h, o}, - {[<<"hats">>, <<"page">>], [], h, o}, - {[<<"hats">>, <<"page">>, number], [], h, o}]}]}, - {[{"[...]ninenines.eu", [{"/hats/[...]", h, o}]}], - [{[<<"eu">>, <<"ninenines">>, '...'], [], [ - {[<<"hats">>, '...'], [], h, o}]}]} - ], - [{lists:flatten(io_lib:format("~p", [Rt])), - fun() -> Rs = compile(Rt) end} || {Rt, Rs} <- Tests]. - -split_host_test_() -> - Tests = [ - {<<"">>, []}, - {<<"*">>, [<<"*">>]}, - {<<"cowboy.ninenines.eu">>, - [<<"eu">>, <<"ninenines">>, <<"cowboy">>]}, - {<<"ninenines.eu">>, - [<<"eu">>, <<"ninenines">>]}, - {<<"a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z">>, - [<<"z">>, <<"y">>, <<"x">>, <<"w">>, <<"v">>, <<"u">>, <<"t">>, - <<"s">>, <<"r">>, <<"q">>, <<"p">>, <<"o">>, <<"n">>, <<"m">>, - <<"l">>, <<"k">>, <<"j">>, <<"i">>, <<"h">>, <<"g">>, <<"f">>, - <<"e">>, <<"d">>, <<"c">>, <<"b">>, <<"a">>]} - ], - [{H, fun() -> R = split_host(H) end} || {H, R} <- Tests]. - -split_path_test_() -> - Tests = [ - {<<"/">>, []}, - {<<"/extend//cowboy">>, [<<"extend">>, <<>>, <<"cowboy">>]}, - {<<"/users">>, [<<"users">>]}, - {<<"/users/42/friends">>, [<<"users">>, <<"42">>, <<"friends">>]}, - {<<"/users/a+b/c%21d">>, [<<"users">>, <<"a b">>, <<"c!d">>]} - ], - [{P, fun() -> R = split_path(P) end} || {P, R} <- Tests]. - -match_test_() -> - Dispatch = [ - {[<<"eu">>, <<"ninenines">>, '_', <<"www">>], [], [ - {[<<"users">>, '_', <<"mails">>], [], match_any_subdomain_users, []} - ]}, - {[<<"eu">>, <<"ninenines">>], [], [ - {[<<"users">>, id, <<"friends">>], [], match_extend_users_friends, []}, - {'_', [], match_extend, []} - ]}, - {[var, <<"ninenines">>], [], [ - {[<<"threads">>, var], [], match_duplicate_vars, - [we, {expect, two}, var, here]} - ]}, - {[ext, <<"erlang">>], [], [ - {'_', [], match_erlang_ext, []} - ]}, - {'_', [], [ - {[<<"users">>, id, <<"friends">>], [], match_users_friends, []}, - {'_', [], match_any, []} - ]} - ], - Tests = [ - {<<"any">>, <<"/">>, {ok, match_any, [], []}}, - {<<"www.any.ninenines.eu">>, <<"/users/42/mails">>, - {ok, match_any_subdomain_users, [], []}}, - {<<"www.ninenines.eu">>, <<"/users/42/mails">>, - {ok, match_any, [], []}}, - {<<"www.ninenines.eu">>, <<"/">>, - {ok, match_any, [], []}}, - {<<"www.any.ninenines.eu">>, <<"/not_users/42/mails">>, - {error, notfound, path}}, - {<<"ninenines.eu">>, <<"/">>, - {ok, match_extend, [], []}}, - {<<"ninenines.eu">>, <<"/users/42/friends">>, - {ok, match_extend_users_friends, [], [{id, <<"42">>}]}}, - {<<"erlang.fr">>, '_', - {ok, match_erlang_ext, [], [{ext, <<"fr">>}]}}, - {<<"any">>, <<"/users/444/friends">>, - {ok, match_users_friends, [], [{id, <<"444">>}]}} - ], - [{lists:flatten(io_lib:format("~p, ~p", [H, P])), fun() -> - {ok, Handler, Opts, Binds, undefined, undefined} - = match(Dispatch, H, P) - end} || {H, P, {ok, Handler, Opts, Binds}} <- Tests]. - -match_info_test_() -> - Dispatch = [ - {[<<"eu">>, <<"ninenines">>, <<"www">>], [], [ - {[<<"pathinfo">>, <<"is">>, <<"next">>, '...'], [], match_path, []} - ]}, - {[<<"eu">>, <<"ninenines">>, '...'], [], [ - {'_', [], match_any, []} - ]}, - % Cyrillic from a latin1 encoded file. - {[<<209,128,209,132>>, <<209,129,208,176,208,185,209,130>>], [], [ - {[<<208,191,209,131,209,130,209,140>>, '...'], [], match_path, []} - ]} - ], - Tests = [ - {<<"ninenines.eu">>, <<"/">>, - {ok, match_any, [], [], [], undefined}}, - {<<"bugs.ninenines.eu">>, <<"/">>, - {ok, match_any, [], [], [<<"bugs">>], undefined}}, - {<<"cowboy.bugs.ninenines.eu">>, <<"/">>, - {ok, match_any, [], [], [<<"cowboy">>, <<"bugs">>], undefined}}, - {<<"www.ninenines.eu">>, <<"/pathinfo/is/next">>, - {ok, match_path, [], [], undefined, []}}, - {<<"www.ninenines.eu">>, <<"/pathinfo/is/next/path_info">>, - {ok, match_path, [], [], undefined, [<<"path_info">>]}}, - {<<"www.ninenines.eu">>, <<"/pathinfo/is/next/foo/bar">>, - {ok, match_path, [], [], undefined, [<<"foo">>, <<"bar">>]}}, - % Cyrillic from a latin1 encoded file. - {<<209,129,208,176,208,185,209,130,46,209,128,209,132>>, - <<47,208,191,209,131,209,130,209,140,47,208,180,208,190,208,188,208,190,208,185>>, - {ok, match_path, [], [], undefined, [<<208,180,208,190,208,188,208,190,208,185>>]}} - ], - [{lists:flatten(io_lib:format("~p, ~p", [H, P])), fun() -> - R = match(Dispatch, H, P) - end} || {H, P, R} <- Tests]. - -match_constraints_test() -> - Dispatch = [{'_', [], - [{[<<"path">>, value], [{value, int}], match, []}]}], - {ok, _, [], [{value, 123}], _, _} = match(Dispatch, - <<"ninenines.eu">>, <<"/path/123">>), - {ok, _, [], [{value, 123}], _, _} = match(Dispatch, - <<"ninenines.eu">>, <<"/path/123/">>), - {error, notfound, path} = match(Dispatch, - <<"ninenines.eu">>, <<"/path/NaN/">>), - Dispatch2 = [{'_', [], - [{[<<"path">>, username], [{username, function, - fun(Value) -> Value =:= cowboy_bstr:to_lower(Value) end}], - match, []}]}], - {ok, _, [], [{username, <<"essen">>}], _, _} = match(Dispatch2, - <<"ninenines.eu">>, <<"/path/essen">>), - {error, notfound, path} = match(Dispatch2, - <<"ninenines.eu">>, <<"/path/ESSEN">>), - ok. - -match_same_bindings_test() -> - Dispatch = [{[same, same], [], [{'_', [], match, []}]}], - {ok, _, [], [{same, <<"eu">>}], _, _} = match(Dispatch, - <<"eu.eu">>, <<"/">>), - {error, notfound, host} = match(Dispatch, - <<"ninenines.eu">>, <<"/">>), - Dispatch2 = [{[<<"eu">>, <<"ninenines">>, user], [], - [{[<<"path">>, user], [], match, []}]}], - {ok, _, [], [{user, <<"essen">>}], _, _} = match(Dispatch2, - <<"essen.ninenines.eu">>, <<"/path/essen">>), - {ok, _, [], [{user, <<"essen">>}], _, _} = match(Dispatch2, - <<"essen.ninenines.eu">>, <<"/path/essen/">>), - {error, notfound, path} = match(Dispatch2, - <<"essen.ninenines.eu">>, <<"/path/notessen">>), - Dispatch3 = [{'_', [], [{[same, same], [], match, []}]}], - {ok, _, [], [{same, <<"path">>}], _, _} = match(Dispatch3, - <<"ninenines.eu">>, <<"/path/path">>), - {error, notfound, path} = match(Dispatch3, - <<"ninenines.eu">>, <<"/path/to">>), - ok. --endif. DELETED deps/cowboy/src/cowboy_spdy.erl Index: deps/cowboy/src/cowboy_spdy.erl ================================================================== --- deps/cowboy/src/cowboy_spdy.erl +++ /dev/null @@ -1,505 +0,0 @@ -%% Copyright (c) 2013-2014, Loïc Hoguin -%% -%% Permission to use, copy, modify, and/or distribute this software for any -%% purpose with or without fee is hereby granted, provided that the above -%% copyright notice and this permission notice appear in all copies. -%% -%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - --module(cowboy_spdy). - -%% API. --export([start_link/4]). - -%% Internal. --export([init/5]). --export([system_continue/3]). --export([system_terminate/4]). --export([system_code_change/4]). - -%% Internal request process. --export([request_init/11]). --export([resume/5]). --export([reply/4]). --export([stream_reply/3]). --export([stream_data/2]). --export([stream_close/1]). - -%% Internal transport functions. --export([name/0]). --export([messages/0]). --export([recv/3]). --export([send/2]). --export([sendfile/2]). --export([setopts/2]). - --type streamid() :: non_neg_integer(). --type socket() :: {pid(), streamid()}. - --record(child, { - streamid :: streamid(), - pid :: pid(), - input = nofin :: fin | nofin, - in_buffer = <<>> :: binary(), - is_recv = false :: false | {active, socket(), pid()} - | {passive, socket(), pid(), non_neg_integer(), reference()}, - output = nofin :: fin | nofin -}). - --record(state, { - parent = undefined :: pid(), - socket, - transport, - buffer = <<>> :: binary(), - middlewares, - env, - onrequest, - onresponse, - peer, - zdef, - zinf, - last_streamid = 0 :: streamid(), - children = [] :: [#child{}] -}). - --type opts() :: [{env, cowboy_middleware:env()} - | {middlewares, [module()]} - | {onrequest, cowboy:onrequest_fun()} - | {onresponse, cowboy:onresponse_fun()}]. --export_type([opts/0]). - -%% API. - --spec start_link(any(), inet:socket(), module(), any()) -> {ok, pid()}. -start_link(Ref, Socket, Transport, Opts) -> - proc_lib:start_link(?MODULE, init, - [self(), Ref, Socket, Transport, Opts]). - -%% Internal. - -%% Faster alternative to proplists:get_value/3. -get_value(Key, Opts, Default) -> - case lists:keyfind(Key, 1, Opts) of - {_, Value} -> Value; - _ -> Default - end. - --spec init(pid(), ranch:ref(), inet:socket(), module(), opts()) -> ok. -init(Parent, Ref, Socket, Transport, Opts) -> - process_flag(trap_exit, true), - ok = proc_lib:init_ack(Parent, {ok, self()}), - {ok, Peer} = Transport:peername(Socket), - Middlewares = get_value(middlewares, Opts, [cowboy_router, cowboy_handler]), - Env = [{listener, Ref}|get_value(env, Opts, [])], - OnRequest = get_value(onrequest, Opts, undefined), - OnResponse = get_value(onresponse, Opts, undefined), - Zdef = cow_spdy:deflate_init(), - Zinf = cow_spdy:inflate_init(), - ok = ranch:accept_ack(Ref), - loop(#state{parent=Parent, socket=Socket, transport=Transport, - middlewares=Middlewares, env=Env, onrequest=OnRequest, - onresponse=OnResponse, peer=Peer, zdef=Zdef, zinf=Zinf}). - -loop(State=#state{parent=Parent, socket=Socket, transport=Transport, - buffer=Buffer, children=Children}) -> - {OK, Closed, Error} = Transport:messages(), - Transport:setopts(Socket, [{active, once}]), - receive - {OK, Socket, Data} -> - parse_frame(State, << Buffer/binary, Data/binary >>); - {Closed, Socket} -> - terminate(State); - {Error, Socket, _Reason} -> - terminate(State); - {recv, FromSocket = {Pid, StreamID}, FromPid, Length, Timeout} - when Pid =:= self() -> - Child = #child{in_buffer=InBuffer, is_recv=false} - = get_child(StreamID, State), - if - Length =:= 0, InBuffer =/= <<>> -> - FromPid ! {recv, FromSocket, {ok, InBuffer}}, - loop(replace_child(Child#child{in_buffer= <<>>}, State)); - byte_size(InBuffer) >= Length -> - << Data:Length/binary, Rest/binary >> = InBuffer, - FromPid ! {recv, FromSocket, {ok, Data}}, - loop(replace_child(Child#child{in_buffer=Rest}, State)); - true -> - TRef = erlang:send_after(Timeout, self(), - {recv_timeout, FromSocket}), - loop(replace_child(Child#child{ - is_recv={passive, FromSocket, FromPid, Length, TRef}}, - State)) - end; - {recv_timeout, {Pid, StreamID}} - when Pid =:= self() -> - Child = #child{is_recv={passive, FromSocket, FromPid, _, _}} - = get_child(StreamID, State), - FromPid ! {recv, FromSocket, {error, timeout}}, - loop(replace_child(Child, State)); - {reply, {Pid, StreamID}, Status, Headers} - when Pid =:= self() -> - Child = #child{output=nofin} = get_child(StreamID, State), - syn_reply(State, StreamID, true, Status, Headers), - loop(replace_child(Child#child{output=fin}, State)); - {reply, {Pid, StreamID}, Status, Headers, Body} - when Pid =:= self() -> - Child = #child{output=nofin} = get_child(StreamID, State), - syn_reply(State, StreamID, false, Status, Headers), - data(State, StreamID, true, Body), - loop(replace_child(Child#child{output=fin}, State)); - {stream_reply, {Pid, StreamID}, Status, Headers} - when Pid =:= self() -> - #child{output=nofin} = get_child(StreamID, State), - syn_reply(State, StreamID, false, Status, Headers), - loop(State); - {stream_data, {Pid, StreamID}, Data} - when Pid =:= self() -> - #child{output=nofin} = get_child(StreamID, State), - data(State, StreamID, false, Data), - loop(State); - {stream_close, {Pid, StreamID}} - when Pid =:= self() -> - Child = #child{output=nofin} = get_child(StreamID, State), - data(State, StreamID, true, <<>>), - loop(replace_child(Child#child{output=fin}, State)); - {sendfile, {Pid, StreamID}, Filepath} - when Pid =:= self() -> - Child = #child{output=nofin} = get_child(StreamID, State), - data_from_file(State, StreamID, Filepath), - loop(replace_child(Child#child{output=fin}, State)); - {active, FromSocket = {Pid, StreamID}, FromPid} when Pid =:= self() -> - Child = #child{in_buffer=InBuffer, is_recv=false} - = get_child(StreamID, State), - case InBuffer of - <<>> -> - loop(replace_child(Child#child{ - is_recv={active, FromSocket, FromPid}}, State)); - _ -> - FromPid ! {spdy, FromSocket, InBuffer}, - loop(replace_child(Child#child{in_buffer= <<>>}, State)) - end; - {passive, FromSocket = {Pid, StreamID}, FromPid} when Pid =:= self() -> - Child = #child{is_recv=IsRecv} = get_child(StreamID, State), - %% Make sure we aren't in the middle of a recv call. - case IsRecv of false -> ok; {active, FromSocket, FromPid} -> ok end, - loop(replace_child(Child#child{is_recv=false}, State)); - {'EXIT', Parent, Reason} -> - exit(Reason); - {'EXIT', Pid, _} -> - %% @todo Report the error if any. - loop(delete_child(Pid, State)); - {system, From, Request} -> - sys:handle_system_msg(Request, From, Parent, ?MODULE, [], State); - %% Calls from the supervisor module. - {'$gen_call', {To, Tag}, which_children} -> - Workers = [{?MODULE, Pid, worker, [?MODULE]} - || #child{pid=Pid} <- Children], - To ! {Tag, Workers}, - loop(State); - {'$gen_call', {To, Tag}, count_children} -> - NbChildren = length(Children), - Counts = [{specs, 1}, {active, NbChildren}, - {supervisors, 0}, {workers, NbChildren}], - To ! {Tag, Counts}, - loop(State); - {'$gen_call', {To, Tag}, _} -> - To ! {Tag, {error, ?MODULE}}, - loop(State) - after 60000 -> - goaway(State, ok), - terminate(State) - end. - --spec system_continue(_, _, #state{}) -> ok. -system_continue(_, _, State) -> - loop(State). - --spec system_terminate(any(), _, _, _) -> no_return(). -system_terminate(Reason, _, _, _) -> - exit(Reason). - --spec system_code_change(Misc, _, _, _) -> {ok, Misc} when Misc::#state{}. -system_code_change(Misc, _, _, _) -> - {ok, Misc}. - -parse_frame(State=#state{zinf=Zinf}, Data) -> - case cow_spdy:split(Data) of - {true, Frame, Rest} -> - P = cow_spdy:parse(Frame, Zinf), - case handle_frame(State#state{buffer = Rest}, P) of - error -> - terminate(State); - State2 -> - parse_frame(State2, Rest) - end; - false -> - loop(State#state{buffer=Data}) - end. - -%% FLAG_UNIDIRECTIONAL can only be set by the server. -handle_frame(State, {syn_stream, StreamID, _, _, true, - _, _, _, _, _, _, _}) -> - rst_stream(State, StreamID, protocol_error), - State; -%% We do not support Associated-To-Stream-ID. -handle_frame(State, {syn_stream, StreamID, AssocToStreamID, - _, _, _, _, _, _, _, _, _}) when AssocToStreamID =/= 0 -> - rst_stream(State, StreamID, internal_error), - State; -%% SYN_STREAM. -%% -%% Erlang does not allow us to control the priority of processes -%% so we ignore that value entirely. -handle_frame(State=#state{middlewares=Middlewares, env=Env, - onrequest=OnRequest, onresponse=OnResponse, peer=Peer}, - {syn_stream, StreamID, _, IsFin, _, _, - Method, _, Host, Path, Version, Headers}) -> - Pid = spawn_link(?MODULE, request_init, [ - {self(), StreamID}, Peer, OnRequest, OnResponse, - Env, Middlewares, Method, Host, Path, Version, Headers - ]), - new_child(State, StreamID, Pid, IsFin); -%% RST_STREAM. -handle_frame(State, {rst_stream, StreamID, Status}) -> - error_logger:error_msg("Received RST_STREAM frame ~p ~p", - [StreamID, Status]), - %% @todo Stop StreamID. - State; -%% PING initiated by the server; ignore, we don't send any. -handle_frame(State, {ping, PingID}) when PingID rem 2 =:= 0 -> - error_logger:error_msg("Ignored PING control frame: ~p~n", [PingID]), - State; -%% PING initiated by the client; send it back. -handle_frame(State=#state{socket=Socket, transport=Transport}, - {ping, PingID}) -> - Transport:send(Socket, cow_spdy:ping(PingID)), - State; -%% Data received for a stream. -handle_frame(State, {data, StreamID, IsFin, Data}) -> - Child = #child{input=nofin, in_buffer=Buffer, is_recv=IsRecv} - = get_child(StreamID, State), - Data2 = << Buffer/binary, Data/binary >>, - IsFin2 = if IsFin -> fin; true -> nofin end, - Child2 = case IsRecv of - {active, FromSocket, FromPid} -> - FromPid ! {spdy, FromSocket, Data}, - Child#child{input=IsFin2, is_recv=false}; - {passive, FromSocket, FromPid, 0, TRef} -> - FromPid ! {recv, FromSocket, {ok, Data2}}, - cancel_recv_timeout(StreamID, TRef), - Child#child{input=IsFin2, in_buffer= <<>>, is_recv=false}; - {passive, FromSocket, FromPid, Length, TRef} - when byte_size(Data2) >= Length -> - << Data3:Length/binary, Rest/binary >> = Data2, - FromPid ! {recv, FromSocket, {ok, Data3}}, - cancel_recv_timeout(StreamID, TRef), - Child#child{input=IsFin2, in_buffer=Rest, is_recv=false}; - _ -> - Child#child{input=IsFin2, in_buffer=Data2} - end, - replace_child(Child2, State); -%% General error, can't recover. -handle_frame(State, {error, badprotocol}) -> - goaway(State, protocol_error), - error; -%% Ignore all other frames for now. -handle_frame(State, Frame) -> - error_logger:error_msg("Ignored frame ~p", [Frame]), - State. - -cancel_recv_timeout(StreamID, TRef) -> - _ = erlang:cancel_timer(TRef), - receive - {recv_timeout, {Pid, StreamID}} - when Pid =:= self() -> - ok - after 0 -> - ok - end. - -%% @todo We must wait for the children to finish here, -%% but only up to N milliseconds. Then we shutdown. -terminate(_State) -> - ok. - -syn_reply(#state{socket=Socket, transport=Transport, zdef=Zdef}, - StreamID, IsFin, Status, Headers) -> - Transport:send(Socket, cow_spdy:syn_reply(Zdef, StreamID, IsFin, - Status, <<"HTTP/1.1">>, Headers)). - -rst_stream(#state{socket=Socket, transport=Transport}, StreamID, Status) -> - Transport:send(Socket, cow_spdy:rst_stream(StreamID, Status)). - -goaway(#state{socket=Socket, transport=Transport, last_streamid=LastStreamID}, - Status) -> - Transport:send(Socket, cow_spdy:goaway(LastStreamID, Status)). - -data(#state{socket=Socket, transport=Transport}, StreamID, IsFin, Data) -> - Transport:send(Socket, cow_spdy:data(StreamID, IsFin, Data)). - -data_from_file(#state{socket=Socket, transport=Transport}, - StreamID, Filepath) -> - {ok, IoDevice} = file:open(Filepath, [read, binary, raw]), - data_from_file(Socket, Transport, StreamID, IoDevice). - -data_from_file(Socket, Transport, StreamID, IoDevice) -> - case file:read(IoDevice, 16#1fff) of - eof -> - _ = Transport:send(Socket, cow_spdy:data(StreamID, true, <<>>)), - ok; - {ok, Data} -> - case Transport:send(Socket, cow_spdy:data(StreamID, false, Data)) of - ok -> - data_from_file(Socket, Transport, StreamID, IoDevice); - {error, _} -> - ok - end - end. - -%% Children. - -new_child(State=#state{children=Children}, StreamID, Pid, IsFin) -> - IsFin2 = if IsFin -> fin; true -> nofin end, - State#state{last_streamid=StreamID, - children=[#child{streamid=StreamID, - pid=Pid, input=IsFin2}|Children]}. - -get_child(StreamID, #state{children=Children}) -> - lists:keyfind(StreamID, #child.streamid, Children). - -replace_child(Child=#child{streamid=StreamID}, - State=#state{children=Children}) -> - Children2 = lists:keyreplace(StreamID, #child.streamid, Children, Child), - State#state{children=Children2}. - -delete_child(Pid, State=#state{children=Children}) -> - Children2 = lists:keydelete(Pid, #child.pid, Children), - State#state{children=Children2}. - -%% Request process. - --spec request_init(socket(), {inet:ip_address(), inet:port_number()}, - cowboy:onrequest_fun(), cowboy:onresponse_fun(), - cowboy_middleware:env(), [module()], - binary(), binary(), binary(), binary(), [{binary(), binary()}]) - -> ok. -request_init(FakeSocket, Peer, OnRequest, OnResponse, - Env, Middlewares, Method, Host, Path, Version, Headers) -> - {Host2, Port} = cow_http:parse_fullhost(Host), - {Path2, Qs} = cow_http:parse_fullpath(Path), - Version2 = cow_http:parse_version(Version), - Req = cowboy_req:new(FakeSocket, ?MODULE, Peer, - Method, Path2, Qs, Version2, Headers, - Host2, Port, <<>>, true, false, OnResponse), - case OnRequest of - undefined -> - execute(Req, Env, Middlewares); - _ -> - Req2 = OnRequest(Req), - case cowboy_req:get(resp_state, Req2) of - waiting -> execute(Req2, Env, Middlewares); - _ -> ok - end - end. - --spec execute(cowboy_req:req(), cowboy_middleware:env(), [module()]) - -> ok. -execute(Req, _, []) -> - cowboy_req:ensure_response(Req, 204); -execute(Req, Env, [Middleware|Tail]) -> - case Middleware:execute(Req, Env) of - {ok, Req2, Env2} -> - execute(Req2, Env2, Tail); - {suspend, Module, Function, Args} -> - erlang:hibernate(?MODULE, resume, - [Env, Tail, Module, Function, Args]); - {halt, Req2} -> - cowboy_req:ensure_response(Req2, 204); - {error, Status, Req2} -> - cowboy_req:reply(Status, Req2) - end. - --spec resume(cowboy_middleware:env(), [module()], - module(), module(), [any()]) -> ok. -resume(Env, Tail, Module, Function, Args) -> - case apply(Module, Function, Args) of - {ok, Req2, Env2} -> - execute(Req2, Env2, Tail); - {suspend, Module2, Function2, Args2} -> - erlang:hibernate(?MODULE, resume, - [Env, Tail, Module2, Function2, Args2]); - {halt, Req2} -> - cowboy_req:ensure_response(Req2, 204); - {error, Status, Req2} -> - cowboy_req:reply(Status, Req2) - end. - -%% Reply functions used by cowboy_req. - --spec reply(socket(), binary(), cowboy:http_headers(), iodata()) -> ok. -reply(Socket = {Pid, _}, Status, Headers, Body) -> - _ = case iolist_size(Body) of - 0 -> Pid ! {reply, Socket, Status, Headers}; - _ -> Pid ! {reply, Socket, Status, Headers, Body} - end, - ok. - --spec stream_reply(socket(), binary(), cowboy:http_headers()) -> ok. -stream_reply(Socket = {Pid, _}, Status, Headers) -> - _ = Pid ! {stream_reply, Socket, Status, Headers}, - ok. - --spec stream_data(socket(), iodata()) -> ok. -stream_data(Socket = {Pid, _}, Data) -> - _ = Pid ! {stream_data, Socket, Data}, - ok. - --spec stream_close(socket()) -> ok. -stream_close(Socket = {Pid, _}) -> - _ = Pid ! {stream_close, Socket}, - ok. - -%% Internal transport functions. - --spec name() -> spdy. -name() -> - spdy. - --spec messages() -> {spdy, spdy_closed, spdy_error}. -messages() -> - {spdy, spdy_closed, spdy_error}. - --spec recv(socket(), non_neg_integer(), timeout()) - -> {ok, binary()} | {error, timeout}. -recv(Socket = {Pid, _}, Length, Timeout) -> - _ = Pid ! {recv, Socket, self(), Length, Timeout}, - receive - {recv, Socket, Ret} -> - Ret - end. - --spec send(socket(), iodata()) -> ok. -send(Socket, Data) -> - stream_data(Socket, Data). - -%% We don't wait for the result of the actual sendfile call, -%% therefore we can't know how much was actually sent. -%% This isn't a problem as we don't use this value in Cowboy. --spec sendfile(socket(), file:name_all()) -> {ok, undefined}. -sendfile(Socket = {Pid, _}, Filepath) -> - _ = Pid ! {sendfile, Socket, Filepath}, - {ok, undefined}. - --spec setopts({pid(), _}, list()) -> ok. -setopts(Socket = {Pid, _}, [{active, once}]) -> - _ = Pid ! {active, Socket, self()}, - ok; -setopts(Socket = {Pid, _}, [{active, false}]) -> - _ = Pid ! {passive, Socket, self()}, - ok. DELETED deps/cowboy/src/cowboy_static.erl Index: deps/cowboy/src/cowboy_static.erl ================================================================== --- deps/cowboy/src/cowboy_static.erl +++ /dev/null @@ -1,291 +0,0 @@ -%% Copyright (c) 2011, Magnus Klaar -%% Copyright (c) 2013-2014, Loïc Hoguin -%% -%% Permission to use, copy, modify, and/or distribute this software for any -%% purpose with or without fee is hereby granted, provided that the above -%% copyright notice and this permission notice appear in all copies. -%% -%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - --module(cowboy_static). - --export([init/3]). --export([rest_init/2]). --export([malformed_request/2]). --export([forbidden/2]). --export([content_types_provided/2]). --export([resource_exists/2]). --export([last_modified/2]). --export([generate_etag/2]). --export([get_file/2]). - --type extra_etag() :: {etag, module(), function()} | {etag, false}. --type extra_mimetypes() :: {mimetypes, module(), function()} - | {mimetypes, binary() | {binary(), binary(), [{binary(), binary()}]}}. --type extra() :: [extra_etag() | extra_mimetypes()]. --type opts() :: {file | dir, string() | binary()} - | {file | dir, string() | binary(), extra()} - | {priv_file | priv_dir, atom(), string() | binary()} - | {priv_file | priv_dir, atom(), string() | binary(), extra()}. --export_type([opts/0]). - --include_lib("kernel/include/file.hrl"). - --type state() :: {binary(), {ok, #file_info{}} | {error, atom()}, extra()}. - --spec init(_, _, _) -> {upgrade, protocol, cowboy_rest}. -init(_, _, _) -> - {upgrade, protocol, cowboy_rest}. - -%% Resolve the file that will be sent and get its file information. -%% If the handler is configured to manage a directory, check that the -%% requested file is inside the configured directory. - --spec rest_init(Req, opts()) - -> {ok, Req, error | state()} - when Req::cowboy_req:req(). -rest_init(Req, {Name, Path}) -> - rest_init_opts(Req, {Name, Path, []}); -rest_init(Req, {Name, App, Path}) - when Name =:= priv_file; Name =:= priv_dir -> - rest_init_opts(Req, {Name, App, Path, []}); -rest_init(Req, Opts) -> - rest_init_opts(Req, Opts). - -rest_init_opts(Req, {priv_file, App, Path, Extra}) -> - rest_init_info(Req, absname(priv_path(App, Path)), Extra); -rest_init_opts(Req, {file, Path, Extra}) -> - rest_init_info(Req, absname(Path), Extra); -rest_init_opts(Req, {priv_dir, App, Path, Extra}) -> - rest_init_dir(Req, priv_path(App, Path), Extra); -rest_init_opts(Req, {dir, Path, Extra}) -> - rest_init_dir(Req, Path, Extra). - -priv_path(App, Path) -> - case code:priv_dir(App) of - {error, bad_name} -> - error({badarg, "Can't resolve the priv_dir of application " - ++ atom_to_list(App)}); - PrivDir when is_list(Path) -> - PrivDir ++ "/" ++ Path; - PrivDir when is_binary(Path) -> - << (list_to_binary(PrivDir))/binary, $/, Path/binary >> - end. - -absname(Path) when is_list(Path) -> - filename:absname(list_to_binary(Path)); -absname(Path) when is_binary(Path) -> - filename:absname(Path). - -rest_init_dir(Req, Path, Extra) when is_list(Path) -> - rest_init_dir(Req, list_to_binary(Path), Extra); -rest_init_dir(Req, Path, Extra) -> - Dir = fullpath(filename:absname(Path)), - {PathInfo, Req2} = cowboy_req:path_info(Req), - Filepath = filename:join([Dir|PathInfo]), - Len = byte_size(Dir), - case fullpath(Filepath) of - << Dir:Len/binary, $/, _/binary >> -> - rest_init_info(Req2, Filepath, Extra); - _ -> - {ok, Req2, error} - end. - -fullpath(Path) -> - fullpath(filename:split(Path), []). -fullpath([], Acc) -> - filename:join(lists:reverse(Acc)); -fullpath([<<".">>|Tail], Acc) -> - fullpath(Tail, Acc); -fullpath([<<"..">>|Tail], Acc=[_]) -> - fullpath(Tail, Acc); -fullpath([<<"..">>|Tail], [_|Acc]) -> - fullpath(Tail, Acc); -fullpath([Segment|Tail], Acc) -> - fullpath(Tail, [Segment|Acc]). - -rest_init_info(Req, Path, Extra) -> - Info = file:read_file_info(Path, [{time, universal}]), - {ok, Req, {Path, Info, Extra}}. - --ifdef(TEST). -fullpath_test_() -> - Tests = [ - {<<"/home/cowboy">>, <<"/home/cowboy">>}, - {<<"/home/cowboy">>, <<"/home/cowboy/">>}, - {<<"/home/cowboy">>, <<"/home/cowboy/./">>}, - {<<"/home/cowboy">>, <<"/home/cowboy/./././././.">>}, - {<<"/home/cowboy">>, <<"/home/cowboy/abc/..">>}, - {<<"/home/cowboy">>, <<"/home/cowboy/abc/../">>}, - {<<"/home/cowboy">>, <<"/home/cowboy/abc/./../.">>}, - {<<"/">>, <<"/home/cowboy/../../../../../..">>}, - {<<"/etc/passwd">>, <<"/home/cowboy/../../etc/passwd">>} - ], - [{P, fun() -> R = fullpath(P) end} || {R, P} <- Tests]. - -good_path_check_test_() -> - Tests = [ - <<"/home/cowboy/file">>, - <<"/home/cowboy/file/">>, - <<"/home/cowboy/./file">>, - <<"/home/cowboy/././././././file">>, - <<"/home/cowboy/abc/../file">>, - <<"/home/cowboy/abc/../file">>, - <<"/home/cowboy/abc/./.././file">> - ], - [{P, fun() -> - case fullpath(P) of - << "/home/cowboy/", _/binary >> -> ok - end - end} || P <- Tests]. - -bad_path_check_test_() -> - Tests = [ - <<"/home/cowboy/../../../../../../file">>, - <<"/home/cowboy/../../etc/passwd">> - ], - [{P, fun() -> - error = case fullpath(P) of - << "/home/cowboy/", _/binary >> -> ok; - _ -> error - end - end} || P <- Tests]. - -good_path_win32_check_test_() -> - Tests = case os:type() of - {unix, _} -> - []; - {win32, _} -> - [ - <<"c:/home/cowboy/file">>, - <<"c:/home/cowboy/file/">>, - <<"c:/home/cowboy/./file">>, - <<"c:/home/cowboy/././././././file">>, - <<"c:/home/cowboy/abc/../file">>, - <<"c:/home/cowboy/abc/../file">>, - <<"c:/home/cowboy/abc/./.././file">> - ] - end, - [{P, fun() -> - case fullpath(P) of - << "c:/home/cowboy/", _/binary >> -> ok - end - end} || P <- Tests]. - -bad_path_win32_check_test_() -> - Tests = case os:type() of - {unix, _} -> - []; - {win32, _} -> - [ - <<"c:/home/cowboy/../../secretfile.bat">>, - <<"c:/home/cowboy/c:/secretfile.bat">>, - <<"c:/home/cowboy/..\\..\\secretfile.bat">>, - <<"c:/home/cowboy/c:\\secretfile.bat">> - ] - end, - [{P, fun() -> - error = case fullpath(P) of - << "c:/home/cowboy/", _/binary >> -> ok; - _ -> error - end - end} || P <- Tests]. --endif. - -%% Reject requests that tried to access a file outside -%% the target directory. - --spec malformed_request(Req, State) - -> {boolean(), Req, State}. -malformed_request(Req, State) -> - {State =:= error, Req, State}. - -%% Directories, files that can't be accessed at all and -%% files with no read flag are forbidden. - --spec forbidden(Req, State) - -> {boolean(), Req, State} - when State::state(). -forbidden(Req, State={_, {ok, #file_info{type=directory}}, _}) -> - {true, Req, State}; -forbidden(Req, State={_, {error, eacces}, _}) -> - {true, Req, State}; -forbidden(Req, State={_, {ok, #file_info{access=Access}}, _}) - when Access =:= write; Access =:= none -> - {true, Req, State}; -forbidden(Req, State) -> - {false, Req, State}. - -%% Detect the mimetype of the file. - --spec content_types_provided(Req, State) - -> {[{binary(), get_file}], Req, State} - when State::state(). -content_types_provided(Req, State={Path, _, Extra}) -> - case lists:keyfind(mimetypes, 1, Extra) of - false -> - {[{cow_mimetypes:web(Path), get_file}], Req, State}; - {mimetypes, Module, Function} -> - {[{Module:Function(Path), get_file}], Req, State}; - {mimetypes, Type} -> - {[{Type, get_file}], Req, State} - end. - -%% Assume the resource doesn't exist if it's not a regular file. - --spec resource_exists(Req, State) - -> {boolean(), Req, State} - when State::state(). -resource_exists(Req, State={_, {ok, #file_info{type=regular}}, _}) -> - {true, Req, State}; -resource_exists(Req, State) -> - {false, Req, State}. - -%% Generate an etag for the file. - --spec generate_etag(Req, State) - -> {{strong | weak, binary()}, Req, State} - when State::state(). -generate_etag(Req, State={Path, {ok, #file_info{size=Size, mtime=Mtime}}, - Extra}) -> - case lists:keyfind(etag, 1, Extra) of - false -> - {generate_default_etag(Size, Mtime), Req, State}; - {etag, Module, Function} -> - {Module:Function(Path, Size, Mtime), Req, State}; - {etag, false} -> - {undefined, Req, State} - end. - -generate_default_etag(Size, Mtime) -> - {strong, integer_to_binary(erlang:phash2({Size, Mtime}, 16#ffffffff))}. - -%% Return the time of last modification of the file. - --spec last_modified(Req, State) - -> {calendar:datetime(), Req, State} - when State::state(). -last_modified(Req, State={_, {ok, #file_info{mtime=Modified}}, _}) -> - {Modified, Req, State}. - -%% Stream the file. -%% @todo Export cowboy_req:resp_body_fun()? - --spec get_file(Req, State) - -> {{stream, non_neg_integer(), fun()}, Req, State} - when State::state(). -get_file(Req, State={Path, {ok, #file_info{size=Size}}, _}) -> - Sendfile = fun (Socket, Transport) -> - case Transport:sendfile(Socket, Path) of - {ok, _} -> ok; - {error, closed} -> ok; - {error, etimedout} -> ok - end - end, - {{stream, Size, Sendfile}, Req, State}. DELETED deps/cowboy/src/cowboy_sub_protocol.erl Index: deps/cowboy/src/cowboy_sub_protocol.erl ================================================================== --- deps/cowboy/src/cowboy_sub_protocol.erl +++ /dev/null @@ -1,23 +0,0 @@ -%% Copyright (c) 2013, James Fish -%% Copyright (c) 2013-2014, Loïc Hoguin -%% -%% Permission to use, copy, modify, and/or distribute this software for any -%% purpose with or without fee is hereby granted, provided that the above -%% copyright notice and this permission notice appear in all copies. -%% -%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - --module(cowboy_sub_protocol). - --callback upgrade(Req, Env, module(), any()) - -> {ok, Req, Env} - | {suspend, module(), atom(), [any()]} - | {halt, Req} - | {error, cowboy:http_status(), Req} - when Req::cowboy_req:req(), Env::cowboy_middleware:env(). DELETED deps/cowboy/src/cowboy_sup.erl Index: deps/cowboy/src/cowboy_sup.erl ================================================================== --- deps/cowboy/src/cowboy_sup.erl +++ /dev/null @@ -1,30 +0,0 @@ -%% Copyright (c) 2011-2014, Loïc Hoguin -%% -%% Permission to use, copy, modify, and/or distribute this software for any -%% purpose with or without fee is hereby granted, provided that the above -%% copyright notice and this permission notice appear in all copies. -%% -%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - --module(cowboy_sup). --behaviour(supervisor). - --export([start_link/0]). --export([init/1]). - --spec start_link() -> {ok, pid()}. -start_link() -> - supervisor:start_link({local, ?MODULE}, ?MODULE, []). - --spec init([]) - -> {ok, {{supervisor:strategy(), 10, 10}, [supervisor:child_spec()]}}. -init([]) -> - Procs = [{cowboy_clock, {cowboy_clock, start_link, []}, - permanent, 5000, worker, [cowboy_clock]}], - {ok, {{one_for_one, 10, 10}, Procs}}. DELETED deps/cowboy/src/cowboy_websocket.erl Index: deps/cowboy/src/cowboy_websocket.erl ================================================================== --- deps/cowboy/src/cowboy_websocket.erl +++ /dev/null @@ -1,770 +0,0 @@ -%% Copyright (c) 2011-2014, Loïc Hoguin -%% -%% Permission to use, copy, modify, and/or distribute this software for any -%% purpose with or without fee is hereby granted, provided that the above -%% copyright notice and this permission notice appear in all copies. -%% -%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -%% Cowboy supports versions 7 through 17 of the Websocket drafts. -%% It also supports RFC6455, the proposed standard for Websocket. --module(cowboy_websocket). --behaviour(cowboy_sub_protocol). - --export([upgrade/4]). --export([handler_loop/4]). - --type close_code() :: 1000..4999. --export_type([close_code/0]). - --type frame() :: close | ping | pong - | {text | binary | close | ping | pong, iodata()} - | {close, close_code(), iodata()}. --export_type([frame/0]). - --type opcode() :: 0 | 1 | 2 | 8 | 9 | 10. --type mask_key() :: 0..16#ffffffff. --type frag_state() :: undefined - | {nofin, opcode(), binary()} | {fin, opcode(), binary()}. --type rsv() :: << _:3 >>. --type terminate_reason() :: {normal | error | remote, atom()} - | {remote, close_code(), binary()}. - --record(state, { - env :: cowboy_middleware:env(), - socket = undefined :: inet:socket(), - transport = undefined :: module(), - handler :: module(), - key = undefined :: undefined | binary(), - timeout = infinity :: timeout(), - timeout_ref = undefined :: undefined | reference(), - messages = undefined :: undefined | {atom(), atom(), atom()}, - hibernate = false :: boolean(), - frag_state = undefined :: frag_state(), - utf8_state = <<>> :: binary(), - deflate_frame = false :: boolean(), - inflate_state :: undefined | port(), - deflate_state :: undefined | port() -}). - --spec upgrade(Req, Env, module(), any()) - -> {ok, Req, Env} - | {suspend, module(), atom(), [any()]} - when Req::cowboy_req:req(), Env::cowboy_middleware:env(). -upgrade(Req, Env, Handler, HandlerOpts) -> - {_, Ref} = lists:keyfind(listener, 1, Env), - ranch:remove_connection(Ref), - [Socket, Transport] = cowboy_req:get([socket, transport], Req), - State = #state{env=Env, socket=Socket, transport=Transport, - handler=Handler}, - try websocket_upgrade(State, Req) of - {ok, State2, Req2} -> - handler_init(State2, Req2, HandlerOpts) - catch _:_ -> - receive - {cowboy_req, resp_sent} -> ok - after 0 -> - _ = cowboy_req:reply(400, Req), - exit(normal) - end - end. - --spec websocket_upgrade(#state{}, Req) - -> {ok, #state{}, Req} when Req::cowboy_req:req(). -websocket_upgrade(State, Req) -> - {ok, ConnTokens, Req2} - = cowboy_req:parse_header(<<"connection">>, Req), - true = lists:member(<<"upgrade">>, ConnTokens), - %% @todo Should probably send a 426 if the Upgrade header is missing. - {ok, [<<"websocket">>], Req3} - = cowboy_req:parse_header(<<"upgrade">>, Req2), - {Version, Req4} = cowboy_req:header(<<"sec-websocket-version">>, Req3), - IntVersion = list_to_integer(binary_to_list(Version)), - true = (IntVersion =:= 7) orelse (IntVersion =:= 8) - orelse (IntVersion =:= 13), - {Key, Req5} = cowboy_req:header(<<"sec-websocket-key">>, Req4), - false = Key =:= undefined, - websocket_extensions(State#state{key=Key}, - cowboy_req:set_meta(websocket_version, IntVersion, Req5)). - --spec websocket_extensions(#state{}, Req) - -> {ok, #state{}, Req} when Req::cowboy_req:req(). -websocket_extensions(State, Req) -> - case cowboy_req:parse_header(<<"sec-websocket-extensions">>, Req) of - {ok, Extensions, Req2} when Extensions =/= undefined -> - [Compress] = cowboy_req:get([resp_compress], Req), - case lists:keyfind(<<"x-webkit-deflate-frame">>, 1, Extensions) of - {<<"x-webkit-deflate-frame">>, []} when Compress =:= true -> - Inflate = zlib:open(), - Deflate = zlib:open(), - % Since we are negotiating an unconstrained deflate-frame - % then we must be willing to accept frames using the - % maximum window size which is 2^15. The negative value - % indicates that zlib headers are not used. - ok = zlib:inflateInit(Inflate, -15), - % Initialize the deflater with a window size of 2^15 bits and disable - % the zlib headers. - ok = zlib:deflateInit(Deflate, best_compression, deflated, -15, 8, default), - {ok, State#state{ - deflate_frame = true, - inflate_state = Inflate, - deflate_state = Deflate - }, cowboy_req:set_meta(websocket_compress, true, Req2)}; - _ -> - {ok, State, cowboy_req:set_meta(websocket_compress, false, Req2)} - end; - _ -> - {ok, State, cowboy_req:set_meta(websocket_compress, false, Req)} - end. - --spec handler_init(#state{}, Req, any()) - -> {ok, Req, cowboy_middleware:env()} | {suspend, module(), atom(), [any()]} - when Req::cowboy_req:req(). -handler_init(State=#state{env=Env, transport=Transport, - handler=Handler}, Req, HandlerOpts) -> - try Handler:websocket_init(Transport:name(), Req, HandlerOpts) of - {ok, Req2, HandlerState} -> - websocket_handshake(State, Req2, HandlerState); - {ok, Req2, HandlerState, hibernate} -> - websocket_handshake(State#state{hibernate=true}, - Req2, HandlerState); - {ok, Req2, HandlerState, Timeout} -> - websocket_handshake(State#state{timeout=Timeout}, - Req2, HandlerState); - {ok, Req2, HandlerState, Timeout, hibernate} -> - websocket_handshake(State#state{timeout=Timeout, - hibernate=true}, Req2, HandlerState); - {shutdown, Req2} -> - cowboy_req:ensure_response(Req2, 400), - {ok, Req2, [{result, closed}|Env]} - catch Class:Reason -> - Stacktrace = erlang:get_stacktrace(), - cowboy_req:maybe_reply(Stacktrace, Req), - erlang:Class([ - {reason, Reason}, - {mfa, {Handler, websocket_init, 3}}, - {stacktrace, Stacktrace}, - {req, cowboy_req:to_list(Req)}, - {opts, HandlerOpts} - ]) - end. - --spec websocket_handshake(#state{}, Req, any()) - -> {ok, Req, cowboy_middleware:env()} - | {suspend, module(), atom(), [any()]} - when Req::cowboy_req:req(). -websocket_handshake(State=#state{ - transport=Transport, key=Key, deflate_frame=DeflateFrame}, - Req, HandlerState) -> - Challenge = base64:encode(crypto:hash(sha, - << Key/binary, "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" >>)), - Extensions = case DeflateFrame of - false -> []; - true -> [{<<"sec-websocket-extensions">>, <<"x-webkit-deflate-frame">>}] - end, - {ok, Req2} = cowboy_req:upgrade_reply( - 101, - [{<<"upgrade">>, <<"websocket">>}, - {<<"sec-websocket-accept">>, Challenge}| - Extensions], - Req), - %% Flush the resp_sent message before moving on. - receive {cowboy_req, resp_sent} -> ok after 0 -> ok end, - State2 = handler_loop_timeout(State), - handler_before_loop(State2#state{key=undefined, - messages=Transport:messages()}, Req2, HandlerState, <<>>). - --spec handler_before_loop(#state{}, Req, any(), binary()) - -> {ok, Req, cowboy_middleware:env()} - | {suspend, module(), atom(), [any()]} - when Req::cowboy_req:req(). -handler_before_loop(State=#state{ - socket=Socket, transport=Transport, hibernate=true}, - Req, HandlerState, SoFar) -> - Transport:setopts(Socket, [{active, once}]), - {suspend, ?MODULE, handler_loop, - [State#state{hibernate=false}, Req, HandlerState, SoFar]}; -handler_before_loop(State=#state{socket=Socket, transport=Transport}, - Req, HandlerState, SoFar) -> - Transport:setopts(Socket, [{active, once}]), - handler_loop(State, Req, HandlerState, SoFar). - --spec handler_loop_timeout(#state{}) -> #state{}. -handler_loop_timeout(State=#state{timeout=infinity}) -> - State#state{timeout_ref=undefined}; -handler_loop_timeout(State=#state{timeout=Timeout, timeout_ref=PrevRef}) -> - _ = case PrevRef of undefined -> ignore; PrevRef -> - erlang:cancel_timer(PrevRef) end, - TRef = erlang:start_timer(Timeout, self(), ?MODULE), - State#state{timeout_ref=TRef}. - --spec handler_loop(#state{}, Req, any(), binary()) - -> {ok, Req, cowboy_middleware:env()} - | {suspend, module(), atom(), [any()]} - when Req::cowboy_req:req(). -handler_loop(State=#state{socket=Socket, messages={OK, Closed, Error}, - timeout_ref=TRef}, Req, HandlerState, SoFar) -> - receive - {OK, Socket, Data} -> - State2 = handler_loop_timeout(State), - websocket_data(State2, Req, HandlerState, - << SoFar/binary, Data/binary >>); - {Closed, Socket} -> - handler_terminate(State, Req, HandlerState, {error, closed}); - {Error, Socket, Reason} -> - handler_terminate(State, Req, HandlerState, {error, Reason}); - {timeout, TRef, ?MODULE} -> - websocket_close(State, Req, HandlerState, {normal, timeout}); - {timeout, OlderTRef, ?MODULE} when is_reference(OlderTRef) -> - handler_loop(State, Req, HandlerState, SoFar); - Message -> - handler_call(State, Req, HandlerState, - SoFar, websocket_info, Message, fun handler_before_loop/4) - end. - -%% All frames passing through this function are considered valid, -%% with the only exception of text and close frames with a payload -%% which may still contain errors. --spec websocket_data(#state{}, Req, any(), binary()) - -> {ok, Req, cowboy_middleware:env()} - | {suspend, module(), atom(), [any()]} - when Req::cowboy_req:req(). -%% RSV bits MUST be 0 unless an extension is negotiated -%% that defines meanings for non-zero values. -websocket_data(State, Req, HandlerState, << _:1, Rsv:3, _/bits >>) - when Rsv =/= 0, State#state.deflate_frame =:= false -> - websocket_close(State, Req, HandlerState, {error, badframe}); -%% Invalid opcode. Note that these opcodes may be used by extensions. -websocket_data(State, Req, HandlerState, << _:4, Opcode:4, _/bits >>) - when Opcode > 2, Opcode =/= 8, Opcode =/= 9, Opcode =/= 10 -> - websocket_close(State, Req, HandlerState, {error, badframe}); -%% Control frames MUST NOT be fragmented. -websocket_data(State, Req, HandlerState, << 0:1, _:3, Opcode:4, _/bits >>) - when Opcode >= 8 -> - websocket_close(State, Req, HandlerState, {error, badframe}); -%% A frame MUST NOT use the zero opcode unless fragmentation was initiated. -websocket_data(State=#state{frag_state=undefined}, Req, HandlerState, - << _:4, 0:4, _/bits >>) -> - websocket_close(State, Req, HandlerState, {error, badframe}); -%% Non-control opcode when expecting control message or next fragment. -websocket_data(State=#state{frag_state={nofin, _, _}}, Req, HandlerState, - << _:4, Opcode:4, _/bits >>) - when Opcode =/= 0, Opcode < 8 -> - websocket_close(State, Req, HandlerState, {error, badframe}); -%% Close control frame length MUST be 0 or >= 2. -websocket_data(State, Req, HandlerState, << _:4, 8:4, _:1, 1:7, _/bits >>) -> - websocket_close(State, Req, HandlerState, {error, badframe}); -%% Close control frame with incomplete close code. Need more data. -websocket_data(State, Req, HandlerState, - Data = << _:4, 8:4, 1:1, Len:7, _/bits >>) - when Len > 1, byte_size(Data) < 8 -> - handler_before_loop(State, Req, HandlerState, Data); -%% 7 bits payload length. -websocket_data(State, Req, HandlerState, << Fin:1, Rsv:3/bits, Opcode:4, 1:1, - Len:7, MaskKey:32, Rest/bits >>) - when Len < 126 -> - websocket_data(State, Req, HandlerState, - Opcode, Len, MaskKey, Rest, Rsv, Fin); -%% 16 bits payload length. -websocket_data(State, Req, HandlerState, << Fin:1, Rsv:3/bits, Opcode:4, 1:1, - 126:7, Len:16, MaskKey:32, Rest/bits >>) - when Len > 125, Opcode < 8 -> - websocket_data(State, Req, HandlerState, - Opcode, Len, MaskKey, Rest, Rsv, Fin); -%% 63 bits payload length. -websocket_data(State, Req, HandlerState, << Fin:1, Rsv:3/bits, Opcode:4, 1:1, - 127:7, 0:1, Len:63, MaskKey:32, Rest/bits >>) - when Len > 16#ffff, Opcode < 8 -> - websocket_data(State, Req, HandlerState, - Opcode, Len, MaskKey, Rest, Rsv, Fin); -%% When payload length is over 63 bits, the most significant bit MUST be 0. -websocket_data(State, Req, HandlerState, << _:8, 1:1, 127:7, 1:1, _:7, _/binary >>) -> - websocket_close(State, Req, HandlerState, {error, badframe}); -%% All frames sent from the client to the server are masked. -websocket_data(State, Req, HandlerState, << _:8, 0:1, _/bits >>) -> - websocket_close(State, Req, HandlerState, {error, badframe}); -%% For the next two clauses, it can be one of the following: -%% -%% * The minimal number of bytes MUST be used to encode the length -%% * All control frames MUST have a payload length of 125 bytes or less -websocket_data(State, Req, HandlerState, << _:9, 126:7, _:48, _/bits >>) -> - websocket_close(State, Req, HandlerState, {error, badframe}); -websocket_data(State, Req, HandlerState, << _:9, 127:7, _:96, _/bits >>) -> - websocket_close(State, Req, HandlerState, {error, badframe}); -%% Need more data. -websocket_data(State, Req, HandlerState, Data) -> - handler_before_loop(State, Req, HandlerState, Data). - -%% Initialize or update fragmentation state. --spec websocket_data(#state{}, Req, any(), - opcode(), non_neg_integer(), mask_key(), binary(), rsv(), 0 | 1) - -> {ok, Req, cowboy_middleware:env()} - | {suspend, module(), atom(), [any()]} - when Req::cowboy_req:req(). -%% The opcode is only included in the first frame fragment. -websocket_data(State=#state{frag_state=undefined}, Req, HandlerState, - Opcode, Len, MaskKey, Data, Rsv, 0) -> - websocket_payload(State#state{frag_state={nofin, Opcode, <<>>}}, - Req, HandlerState, 0, Len, MaskKey, <<>>, 0, Data, Rsv); -%% Subsequent frame fragments. -websocket_data(State=#state{frag_state={nofin, _, _}}, Req, HandlerState, - 0, Len, MaskKey, Data, Rsv, 0) -> - websocket_payload(State, Req, HandlerState, - 0, Len, MaskKey, <<>>, 0, Data, Rsv); -%% Final frame fragment. -websocket_data(State=#state{frag_state={nofin, Opcode, SoFar}}, - Req, HandlerState, 0, Len, MaskKey, Data, Rsv, 1) -> - websocket_payload(State#state{frag_state={fin, Opcode, SoFar}}, - Req, HandlerState, 0, Len, MaskKey, <<>>, 0, Data, Rsv); -%% Unfragmented frame. -websocket_data(State, Req, HandlerState, Opcode, Len, MaskKey, Data, Rsv, 1) -> - websocket_payload(State, Req, HandlerState, - Opcode, Len, MaskKey, <<>>, 0, Data, Rsv). - --spec websocket_payload(#state{}, Req, any(), - opcode(), non_neg_integer(), mask_key(), binary(), non_neg_integer(), - binary(), rsv()) - -> {ok, Req, cowboy_middleware:env()} - | {suspend, module(), atom(), [any()]} - when Req::cowboy_req:req(). -%% Close control frames with a payload MUST contain a valid close code. -websocket_payload(State, Req, HandlerState, - Opcode=8, Len, MaskKey, <<>>, 0, - << MaskedCode:2/binary, Rest/bits >>, Rsv) -> - Unmasked = << Code:16 >> = websocket_unmask(MaskedCode, MaskKey, <<>>), - if Code < 1000; Code =:= 1004; Code =:= 1005; Code =:= 1006; - (Code > 1011) and (Code < 3000); Code > 4999 -> - websocket_close(State, Req, HandlerState, {error, badframe}); - true -> - websocket_payload(State, Req, HandlerState, - Opcode, Len - 2, MaskKey, Unmasked, byte_size(MaskedCode), - Rest, Rsv) - end; -%% Text frames and close control frames MUST have a payload that is valid UTF-8. -websocket_payload(State=#state{utf8_state=Incomplete}, - Req, HandlerState, Opcode, Len, MaskKey, Unmasked, UnmaskedLen, - Data, Rsv) - when (byte_size(Data) < Len) andalso ((Opcode =:= 1) orelse - ((Opcode =:= 8) andalso (Unmasked =/= <<>>))) -> - Unmasked2 = websocket_unmask(Data, - rotate_mask_key(MaskKey, UnmaskedLen), <<>>), - {Unmasked3, State2} = websocket_inflate_frame(Unmasked2, Rsv, false, State), - case is_utf8(<< Incomplete/binary, Unmasked3/binary >>) of - false -> - websocket_close(State2, Req, HandlerState, {error, badencoding}); - Utf8State -> - websocket_payload_loop(State2#state{utf8_state=Utf8State}, - Req, HandlerState, Opcode, Len - byte_size(Data), MaskKey, - << Unmasked/binary, Unmasked3/binary >>, - UnmaskedLen + byte_size(Data), Rsv) - end; -websocket_payload(State=#state{utf8_state=Incomplete}, - Req, HandlerState, Opcode, Len, MaskKey, Unmasked, UnmaskedLen, - Data, Rsv) - when Opcode =:= 1; (Opcode =:= 8) and (Unmasked =/= <<>>) -> - << End:Len/binary, Rest/bits >> = Data, - Unmasked2 = websocket_unmask(End, - rotate_mask_key(MaskKey, UnmaskedLen), <<>>), - {Unmasked3, State2} = websocket_inflate_frame(Unmasked2, Rsv, true, State), - case is_utf8(<< Incomplete/binary, Unmasked3/binary >>) of - <<>> -> - websocket_dispatch(State2#state{utf8_state= <<>>}, - Req, HandlerState, Rest, Opcode, - << Unmasked/binary, Unmasked3/binary >>); - _ -> - websocket_close(State2, Req, HandlerState, {error, badencoding}) - end; -%% Fragmented text frames may cut payload in the middle of UTF-8 codepoints. -websocket_payload(State=#state{frag_state={_, 1, _}, utf8_state=Incomplete}, - Req, HandlerState, Opcode=0, Len, MaskKey, Unmasked, UnmaskedLen, - Data, Rsv) - when byte_size(Data) < Len -> - Unmasked2 = websocket_unmask(Data, - rotate_mask_key(MaskKey, UnmaskedLen), <<>>), - {Unmasked3, State2} = websocket_inflate_frame(Unmasked2, Rsv, false, State), - case is_utf8(<< Incomplete/binary, Unmasked3/binary >>) of - false -> - websocket_close(State2, Req, HandlerState, {error, badencoding}); - Utf8State -> - websocket_payload_loop(State2#state{utf8_state=Utf8State}, - Req, HandlerState, Opcode, Len - byte_size(Data), MaskKey, - << Unmasked/binary, Unmasked3/binary >>, - UnmaskedLen + byte_size(Data), Rsv) - end; -websocket_payload(State=#state{frag_state={Fin, 1, _}, utf8_state=Incomplete}, - Req, HandlerState, Opcode=0, Len, MaskKey, Unmasked, UnmaskedLen, - Data, Rsv) -> - << End:Len/binary, Rest/bits >> = Data, - Unmasked2 = websocket_unmask(End, - rotate_mask_key(MaskKey, UnmaskedLen), <<>>), - {Unmasked3, State2} = websocket_inflate_frame(Unmasked2, Rsv, Fin =:= fin, State), - case is_utf8(<< Incomplete/binary, Unmasked3/binary >>) of - <<>> -> - websocket_dispatch(State2#state{utf8_state= <<>>}, - Req, HandlerState, Rest, Opcode, - << Unmasked/binary, Unmasked3/binary >>); - Utf8State when is_binary(Utf8State), Fin =:= nofin -> - websocket_dispatch(State2#state{utf8_state=Utf8State}, - Req, HandlerState, Rest, Opcode, - << Unmasked/binary, Unmasked3/binary >>); - _ -> - websocket_close(State, Req, HandlerState, {error, badencoding}) - end; -%% Other frames have a binary payload. -websocket_payload(State, Req, HandlerState, - Opcode, Len, MaskKey, Unmasked, UnmaskedLen, Data, Rsv) - when byte_size(Data) < Len -> - Unmasked2 = websocket_unmask(Data, - rotate_mask_key(MaskKey, UnmaskedLen), <<>>), - {Unmasked3, State2} = websocket_inflate_frame(Unmasked2, Rsv, false, State), - websocket_payload_loop(State2, Req, HandlerState, - Opcode, Len - byte_size(Data), MaskKey, - << Unmasked/binary, Unmasked3/binary >>, UnmaskedLen + byte_size(Data), - Rsv); -websocket_payload(State, Req, HandlerState, - Opcode, Len, MaskKey, Unmasked, UnmaskedLen, Data, Rsv) -> - << End:Len/binary, Rest/bits >> = Data, - Unmasked2 = websocket_unmask(End, - rotate_mask_key(MaskKey, UnmaskedLen), <<>>), - {Unmasked3, State2} = websocket_inflate_frame(Unmasked2, Rsv, true, State), - websocket_dispatch(State2, Req, HandlerState, Rest, Opcode, - << Unmasked/binary, Unmasked3/binary >>). - --spec websocket_inflate_frame(binary(), rsv(), boolean(), #state{}) -> - {binary(), #state{}}. -websocket_inflate_frame(Data, << Rsv1:1, _:2 >>, _, - #state{deflate_frame = DeflateFrame} = State) - when DeflateFrame =:= false orelse Rsv1 =:= 0 -> - {Data, State}; -websocket_inflate_frame(Data, << 1:1, _:2 >>, false, State) -> - Result = zlib:inflate(State#state.inflate_state, Data), - {iolist_to_binary(Result), State}; -websocket_inflate_frame(Data, << 1:1, _:2 >>, true, State) -> - Result = zlib:inflate(State#state.inflate_state, - << Data/binary, 0:8, 0:8, 255:8, 255:8 >>), - {iolist_to_binary(Result), State}. - --spec websocket_unmask(B, mask_key(), B) -> B when B::binary(). -websocket_unmask(<<>>, _, Unmasked) -> - Unmasked; -websocket_unmask(<< O:32, Rest/bits >>, MaskKey, Acc) -> - T = O bxor MaskKey, - websocket_unmask(Rest, MaskKey, << Acc/binary, T:32 >>); -websocket_unmask(<< O:24 >>, MaskKey, Acc) -> - << MaskKey2:24, _:8 >> = << MaskKey:32 >>, - T = O bxor MaskKey2, - << Acc/binary, T:24 >>; -websocket_unmask(<< O:16 >>, MaskKey, Acc) -> - << MaskKey2:16, _:16 >> = << MaskKey:32 >>, - T = O bxor MaskKey2, - << Acc/binary, T:16 >>; -websocket_unmask(<< O:8 >>, MaskKey, Acc) -> - << MaskKey2:8, _:24 >> = << MaskKey:32 >>, - T = O bxor MaskKey2, - << Acc/binary, T:8 >>. - -%% Because we unmask on the fly we need to continue from the right mask byte. --spec rotate_mask_key(mask_key(), non_neg_integer()) -> mask_key(). -rotate_mask_key(MaskKey, UnmaskedLen) -> - Left = UnmaskedLen rem 4, - Right = 4 - Left, - (MaskKey bsl (Left * 8)) + (MaskKey bsr (Right * 8)). - -%% Returns <<>> if the argument is valid UTF-8, false if not, -%% or the incomplete part of the argument if we need more data. --spec is_utf8(binary()) -> false | binary(). -is_utf8(Valid = <<>>) -> - Valid; -is_utf8(<< _/utf8, Rest/binary >>) -> - is_utf8(Rest); -%% 2 bytes. Codepages C0 and C1 are invalid; fail early. -is_utf8(<< 2#1100000:7, _/bits >>) -> - false; -is_utf8(Incomplete = << 2#110:3, _:5 >>) -> - Incomplete; -%% 3 bytes. -is_utf8(Incomplete = << 2#1110:4, _:4 >>) -> - Incomplete; -is_utf8(Incomplete = << 2#1110:4, _:4, 2#10:2, _:6 >>) -> - Incomplete; -%% 4 bytes. Codepage F4 may have invalid values greater than 0x10FFFF. -is_utf8(<< 2#11110100:8, 2#10:2, High:6, _/bits >>) when High >= 2#10000 -> - false; -is_utf8(Incomplete = << 2#11110:5, _:3 >>) -> - Incomplete; -is_utf8(Incomplete = << 2#11110:5, _:3, 2#10:2, _:6 >>) -> - Incomplete; -is_utf8(Incomplete = << 2#11110:5, _:3, 2#10:2, _:6, 2#10:2, _:6 >>) -> - Incomplete; -%% Invalid. -is_utf8(_) -> - false. - --spec websocket_payload_loop(#state{}, Req, any(), - opcode(), non_neg_integer(), mask_key(), binary(), - non_neg_integer(), rsv()) - -> {ok, Req, cowboy_middleware:env()} - | {suspend, module(), atom(), [any()]} - when Req::cowboy_req:req(). -websocket_payload_loop(State=#state{socket=Socket, transport=Transport, - messages={OK, Closed, Error}, timeout_ref=TRef}, - Req, HandlerState, Opcode, Len, MaskKey, Unmasked, UnmaskedLen, Rsv) -> - Transport:setopts(Socket, [{active, once}]), - receive - {OK, Socket, Data} -> - State2 = handler_loop_timeout(State), - websocket_payload(State2, Req, HandlerState, - Opcode, Len, MaskKey, Unmasked, UnmaskedLen, Data, Rsv); - {Closed, Socket} -> - handler_terminate(State, Req, HandlerState, {error, closed}); - {Error, Socket, Reason} -> - handler_terminate(State, Req, HandlerState, {error, Reason}); - {timeout, TRef, ?MODULE} -> - websocket_close(State, Req, HandlerState, {normal, timeout}); - {timeout, OlderTRef, ?MODULE} when is_reference(OlderTRef) -> - websocket_payload_loop(State, Req, HandlerState, - Opcode, Len, MaskKey, Unmasked, UnmaskedLen, Rsv); - Message -> - handler_call(State, Req, HandlerState, - <<>>, websocket_info, Message, - fun (State2, Req2, HandlerState2, _) -> - websocket_payload_loop(State2, Req2, HandlerState2, - Opcode, Len, MaskKey, Unmasked, UnmaskedLen, Rsv) - end) - end. - --spec websocket_dispatch(#state{}, Req, any(), binary(), opcode(), binary()) - -> {ok, Req, cowboy_middleware:env()} - | {suspend, module(), atom(), [any()]} - when Req::cowboy_req:req(). -%% Continuation frame. -websocket_dispatch(State=#state{frag_state={nofin, Opcode, SoFar}}, - Req, HandlerState, RemainingData, 0, Payload) -> - websocket_data(State#state{frag_state={nofin, Opcode, - << SoFar/binary, Payload/binary >>}}, Req, HandlerState, RemainingData); -%% Last continuation frame. -websocket_dispatch(State=#state{frag_state={fin, Opcode, SoFar}}, - Req, HandlerState, RemainingData, 0, Payload) -> - websocket_dispatch(State#state{frag_state=undefined}, Req, HandlerState, - RemainingData, Opcode, << SoFar/binary, Payload/binary >>); -%% Text frame. -websocket_dispatch(State, Req, HandlerState, RemainingData, 1, Payload) -> - handler_call(State, Req, HandlerState, RemainingData, - websocket_handle, {text, Payload}, fun websocket_data/4); -%% Binary frame. -websocket_dispatch(State, Req, HandlerState, RemainingData, 2, Payload) -> - handler_call(State, Req, HandlerState, RemainingData, - websocket_handle, {binary, Payload}, fun websocket_data/4); -%% Close control frame. -websocket_dispatch(State, Req, HandlerState, _RemainingData, 8, <<>>) -> - websocket_close(State, Req, HandlerState, {remote, closed}); -websocket_dispatch(State, Req, HandlerState, _RemainingData, 8, - << Code:16, Payload/bits >>) -> - websocket_close(State, Req, HandlerState, {remote, Code, Payload}); -%% Ping control frame. Send a pong back and forward the ping to the handler. -websocket_dispatch(State=#state{socket=Socket, transport=Transport}, - Req, HandlerState, RemainingData, 9, Payload) -> - Len = payload_length_to_binary(iolist_size(Payload)), - Transport:send(Socket, << 1:1, 0:3, 10:4, 0:1, Len/bits, Payload/binary >>), - handler_call(State, Req, HandlerState, RemainingData, - websocket_handle, {ping, Payload}, fun websocket_data/4); -%% Pong control frame. -websocket_dispatch(State, Req, HandlerState, RemainingData, 10, Payload) -> - handler_call(State, Req, HandlerState, RemainingData, - websocket_handle, {pong, Payload}, fun websocket_data/4). - --spec handler_call(#state{}, Req, any(), binary(), atom(), any(), fun()) - -> {ok, Req, cowboy_middleware:env()} - | {suspend, module(), atom(), [any()]} - when Req::cowboy_req:req(). -handler_call(State=#state{handler=Handler}, Req, HandlerState, - RemainingData, Callback, Message, NextState) -> - try Handler:Callback(Message, Req, HandlerState) of - {ok, Req2, HandlerState2} -> - NextState(State, Req2, HandlerState2, RemainingData); - {ok, Req2, HandlerState2, hibernate} -> - NextState(State#state{hibernate=true}, - Req2, HandlerState2, RemainingData); - {reply, Payload, Req2, HandlerState2} - when is_list(Payload) -> - case websocket_send_many(Payload, State) of - {ok, State2} -> - NextState(State2, Req2, HandlerState2, RemainingData); - {shutdown, State2} -> - handler_terminate(State2, Req2, HandlerState2, - {normal, shutdown}); - {{error, _} = Error, State2} -> - handler_terminate(State2, Req2, HandlerState2, Error) - end; - {reply, Payload, Req2, HandlerState2, hibernate} - when is_list(Payload) -> - case websocket_send_many(Payload, State) of - {ok, State2} -> - NextState(State2#state{hibernate=true}, - Req2, HandlerState2, RemainingData); - {shutdown, State2} -> - handler_terminate(State2, Req2, HandlerState2, - {normal, shutdown}); - {{error, _} = Error, State2} -> - handler_terminate(State2, Req2, HandlerState2, Error) - end; - {reply, Payload, Req2, HandlerState2} -> - case websocket_send(Payload, State) of - {ok, State2} -> - NextState(State2, Req2, HandlerState2, RemainingData); - {shutdown, State2} -> - handler_terminate(State2, Req2, HandlerState2, - {normal, shutdown}); - {{error, _} = Error, State2} -> - handler_terminate(State2, Req2, HandlerState2, Error) - end; - {reply, Payload, Req2, HandlerState2, hibernate} -> - case websocket_send(Payload, State) of - {ok, State2} -> - NextState(State2#state{hibernate=true}, - Req2, HandlerState2, RemainingData); - {shutdown, State2} -> - handler_terminate(State2, Req2, HandlerState2, - {normal, shutdown}); - {{error, _} = Error, State2} -> - handler_terminate(State2, Req2, HandlerState2, Error) - end; - {shutdown, Req2, HandlerState2} -> - websocket_close(State, Req2, HandlerState2, {normal, shutdown}) - catch Class:Reason -> - _ = websocket_close(State, Req, HandlerState, {error, handler}), - erlang:Class([ - {reason, Reason}, - {mfa, {Handler, Callback, 3}}, - {stacktrace, erlang:get_stacktrace()}, - {msg, Message}, - {req, cowboy_req:to_list(Req)}, - {state, HandlerState} - ]) - end. - -websocket_opcode(text) -> 1; -websocket_opcode(binary) -> 2; -websocket_opcode(close) -> 8; -websocket_opcode(ping) -> 9; -websocket_opcode(pong) -> 10. - --spec websocket_deflate_frame(opcode(), binary(), #state{}) -> - {binary(), rsv(), #state{}}. -websocket_deflate_frame(Opcode, Payload, - State=#state{deflate_frame = DeflateFrame}) - when DeflateFrame =:= false orelse Opcode >= 8 -> - {Payload, << 0:3 >>, State}; -websocket_deflate_frame(_, Payload, State=#state{deflate_state = Deflate}) -> - Deflated = iolist_to_binary(zlib:deflate(Deflate, Payload, sync)), - DeflatedBodyLength = erlang:size(Deflated) - 4, - Deflated1 = case Deflated of - << Body:DeflatedBodyLength/binary, 0:8, 0:8, 255:8, 255:8 >> -> Body; - _ -> Deflated - end, - {Deflated1, << 1:1, 0:2 >>, State}. - --spec websocket_send(frame(), #state{}) --> {ok, #state{}} | {shutdown, #state{}} | {{error, atom()}, #state{}}. -websocket_send(Type, State=#state{socket=Socket, transport=Transport}) - when Type =:= close -> - Opcode = websocket_opcode(Type), - case Transport:send(Socket, << 1:1, 0:3, Opcode:4, 0:8 >>) of - ok -> {shutdown, State}; - Error -> {Error, State} - end; -websocket_send(Type, State=#state{socket=Socket, transport=Transport}) - when Type =:= ping; Type =:= pong -> - Opcode = websocket_opcode(Type), - {Transport:send(Socket, << 1:1, 0:3, Opcode:4, 0:8 >>), State}; -websocket_send({close, Payload}, State) -> - websocket_send({close, 1000, Payload}, State); -websocket_send({Type = close, StatusCode, Payload}, State=#state{ - socket=Socket, transport=Transport}) -> - Opcode = websocket_opcode(Type), - Len = 2 + iolist_size(Payload), - %% Control packets must not be > 125 in length. - true = Len =< 125, - BinLen = payload_length_to_binary(Len), - Transport:send(Socket, - [<< 1:1, 0:3, Opcode:4, 0:1, BinLen/bits, StatusCode:16 >>, Payload]), - {shutdown, State}; -websocket_send({Type, Payload0}, State=#state{socket=Socket, transport=Transport}) -> - Opcode = websocket_opcode(Type), - {Payload, Rsv, State2} = websocket_deflate_frame(Opcode, iolist_to_binary(Payload0), State), - Len = iolist_size(Payload), - %% Control packets must not be > 125 in length. - true = if Type =:= ping; Type =:= pong -> - Len =< 125; - true -> - true - end, - BinLen = payload_length_to_binary(Len), - {Transport:send(Socket, - [<< 1:1, Rsv/bits, Opcode:4, 0:1, BinLen/bits >>, Payload]), State2}. - --spec websocket_send_many([frame()], #state{}) - -> {ok, #state{}} | {shutdown, #state{}} | {{error, atom()}, #state{}}. -websocket_send_many([], State) -> - {ok, State}; -websocket_send_many([Frame|Tail], State) -> - case websocket_send(Frame, State) of - {ok, State2} -> websocket_send_many(Tail, State2); - {shutdown, State2} -> {shutdown, State2}; - {Error, State2} -> {Error, State2} - end. - --spec websocket_close(#state{}, Req, any(), terminate_reason()) - -> {ok, Req, cowboy_middleware:env()} - when Req::cowboy_req:req(). -websocket_close(State=#state{socket=Socket, transport=Transport}, - Req, HandlerState, Reason) -> - case Reason of - {normal, _} -> - Transport:send(Socket, << 1:1, 0:3, 8:4, 0:1, 2:7, 1000:16 >>); - {error, badframe} -> - Transport:send(Socket, << 1:1, 0:3, 8:4, 0:1, 2:7, 1002:16 >>); - {error, badencoding} -> - Transport:send(Socket, << 1:1, 0:3, 8:4, 0:1, 2:7, 1007:16 >>); - {error, handler} -> - Transport:send(Socket, << 1:1, 0:3, 8:4, 0:1, 2:7, 1011:16 >>); - {remote, closed} -> - Transport:send(Socket, << 1:1, 0:3, 8:4, 0:8 >>); - {remote, Code, _} -> - Transport:send(Socket, << 1:1, 0:3, 8:4, 0:1, 2:7, Code:16 >>) - end, - handler_terminate(State, Req, HandlerState, Reason). - --spec handler_terminate(#state{}, Req, any(), terminate_reason()) - -> {ok, Req, cowboy_middleware:env()} - when Req::cowboy_req:req(). -handler_terminate(#state{env=Env, handler=Handler}, - Req, HandlerState, TerminateReason) -> - try - Handler:websocket_terminate(TerminateReason, Req, HandlerState) - catch Class:Reason -> - erlang:Class([ - {reason, Reason}, - {mfa, {Handler, websocket_terminate, 3}}, - {stacktrace, erlang:get_stacktrace()}, - {req, cowboy_req:to_list(Req)}, - {state, HandlerState}, - {terminate_reason, TerminateReason} - ]) - end, - {ok, Req, [{result, closed}|Env]}. - --spec payload_length_to_binary(0..16#7fffffffffffffff) - -> << _:7 >> | << _:23 >> | << _:71 >>. -payload_length_to_binary(N) -> - case N of - N when N =< 125 -> << N:7 >>; - N when N =< 16#ffff -> << 126:7, N:16 >>; - N when N =< 16#7fffffffffffffff -> << 127:7, N:64 >> - end. DELETED deps/cowboy/src/cowboy_websocket_handler.erl Index: deps/cowboy/src/cowboy_websocket_handler.erl ================================================================== --- deps/cowboy/src/cowboy_websocket_handler.erl +++ /dev/null @@ -1,50 +0,0 @@ -%% Copyright (c) 2011-2014, Loïc Hoguin -%% -%% Permission to use, copy, modify, and/or distribute this software for any -%% purpose with or without fee is hereby granted, provided that the above -%% copyright notice and this permission notice appear in all copies. -%% -%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - --module(cowboy_websocket_handler). - --type opts() :: any(). --type state() :: any(). --type terminate_reason() :: {normal, shutdown} - | {normal, timeout} - | {error, closed} - | {remote, closed} - | {remote, cowboy_websocket:close_code(), binary()} - | {error, badencoding} - | {error, badframe} - | {error, atom()}. - --callback websocket_init(atom(), Req, opts()) - -> {ok, Req, state()} - | {ok, Req, state(), hibernate} - | {ok, Req, state(), timeout()} - | {ok, Req, state(), timeout(), hibernate} - | {shutdown, Req} - when Req::cowboy_req:req(). --callback websocket_handle({text | binary | ping | pong, binary()}, Req, State) - -> {ok, Req, State} - | {ok, Req, State, hibernate} - | {reply, cowboy_websocket:frame() | [cowboy_websocket:frame()], Req, State} - | {reply, cowboy_websocket:frame() | [cowboy_websocket:frame()], Req, State, hibernate} - | {shutdown, Req, State} - when Req::cowboy_req:req(), State::state(). --callback websocket_info(any(), Req, State) - -> {ok, Req, State} - | {ok, Req, State, hibernate} - | {reply, cowboy_websocket:frame() | [cowboy_websocket:frame()], Req, State} - | {reply, cowboy_websocket:frame() | [cowboy_websocket:frame()], Req, State, hibernate} - | {shutdown, Req, State} - when Req::cowboy_req:req(), State::state(). --callback websocket_terminate(terminate_reason(), cowboy_req:req(), state()) - -> ok. DELETED deps/cowlib/LICENSE Index: deps/cowlib/LICENSE ================================================================== --- deps/cowlib/LICENSE +++ /dev/null @@ -1,13 +0,0 @@ -Copyright (c) 2013-2014, Loïc Hoguin - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. DELETED deps/cowlib/Makefile Index: deps/cowlib/Makefile ================================================================== --- deps/cowlib/Makefile +++ /dev/null @@ -1,46 +0,0 @@ -# See LICENSE for licensing information. - -PROJECT = cowlib -PLT_APPS = crypto -CI_OTP = OTP_R15B OTP_R15B01 OTP_R15B02 OTP_R15B03-1 OTP_R16B OTP_R16B01 OTP_R16B02 OTP_R16B03-1 OTP-17.0.2 OTP-17.1.2 OTP-17.2.2 OTP-17.3.4 OTP-17.4.1 OTP-17.5.6.3 OTP-18.0.3 - -include erlang.mk - -TEST_ERLC_OPTS += +'{parse_transform, eunit_autoexport}' -DEXTRA=1 - -.PHONY: gen perfs - -# Mimetypes module generator. - -GEN_URL = http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types -GEN_SRC = src/cow_mimetypes.erl.src -GEN_OUT = src/cow_mimetypes.erl - -gen: - $(gen_verbose) cat $(GEN_SRC) \ - | head -n `grep -n "%% GENERATED" $(GEN_SRC) | cut -d : -f 1` \ - > $(GEN_OUT) - $(gen_verbose) wget -qO - $(GEN_URL) \ - | grep -v ^# \ - | awk '{for (i=2; i<=NF; i++) if ($$i != "") { \ - split($$1, a, "/"); \ - print "all_ext(<<\"" $$i "\">>) -> {<<\"" \ - a[1] "\">>, <<\"" a[2] "\">>, []};"}}' \ - | sort \ - | uniq -w 25 \ - >> $(GEN_OUT) - $(gen_verbose) cat $(GEN_SRC) \ - | tail -n +`grep -n "%% GENERATED" $(GEN_SRC) | cut -d : -f 1` \ - >> $(GEN_OUT) - -# Performance testing. - -deps/horse: - git clone -n -- https://github.com/extend/horse $(DEPS_DIR)/horse - cd $(DEPS_DIR)/horse ; git checkout -q master - $(MAKE) -C $(DEPS_DIR)/horse - -perfs: ERLC_OPTS += -DPERF=1 +'{parse_transform, horse_autoexport}' -DEXTRA=1 -perfs: clean deps deps/horse app - $(gen_verbose) erl -noshell -pa ebin deps/horse/ebin \ - -eval 'horse:app_perf($(PROJECT)), init:stop().' DELETED deps/cowlib/README.md Index: deps/cowlib/README.md ================================================================== --- deps/cowlib/README.md +++ /dev/null @@ -1,20 +0,0 @@ -Cowlib -====== - -Cowlib is a support library for manipulating Web protocols. - -Goals ------ - -Cowlib provides libraries for parsing and building messages -for various Web protocols, including SPDY, HTTP and Websocket. - -It is optimized for completeness rather than speed. No value -is ignored, they are all returned. - -Support -------- - - * Official IRC Channel: #ninenines on irc.freenode.net - * [Mailing Lists](http://lists.ninenines.eu) - * [Commercial Support](http://ninenines.eu/support) DELETED deps/cowlib/ebin/cow_cookie.beam Index: deps/cowlib/ebin/cow_cookie.beam ================================================================== --- deps/cowlib/ebin/cow_cookie.beam +++ /dev/null cannot compute difference between binary files DELETED deps/cowlib/ebin/cow_date.beam Index: deps/cowlib/ebin/cow_date.beam ================================================================== --- deps/cowlib/ebin/cow_date.beam +++ /dev/null cannot compute difference between binary files DELETED deps/cowlib/ebin/cow_http.beam Index: deps/cowlib/ebin/cow_http.beam ================================================================== --- deps/cowlib/ebin/cow_http.beam +++ /dev/null cannot compute difference between binary files DELETED deps/cowlib/ebin/cow_http_hd.beam Index: deps/cowlib/ebin/cow_http_hd.beam ================================================================== --- deps/cowlib/ebin/cow_http_hd.beam +++ /dev/null cannot compute difference between binary files DELETED deps/cowlib/ebin/cow_http_te.beam Index: deps/cowlib/ebin/cow_http_te.beam ================================================================== --- deps/cowlib/ebin/cow_http_te.beam +++ /dev/null cannot compute difference between binary files DELETED deps/cowlib/ebin/cow_mimetypes.beam Index: deps/cowlib/ebin/cow_mimetypes.beam ================================================================== --- deps/cowlib/ebin/cow_mimetypes.beam +++ /dev/null cannot compute difference between binary files DELETED deps/cowlib/ebin/cow_multipart.beam Index: deps/cowlib/ebin/cow_multipart.beam ================================================================== --- deps/cowlib/ebin/cow_multipart.beam +++ /dev/null cannot compute difference between binary files DELETED deps/cowlib/ebin/cow_qs.beam Index: deps/cowlib/ebin/cow_qs.beam ================================================================== --- deps/cowlib/ebin/cow_qs.beam +++ /dev/null cannot compute difference between binary files DELETED deps/cowlib/ebin/cow_spdy.beam Index: deps/cowlib/ebin/cow_spdy.beam ================================================================== --- deps/cowlib/ebin/cow_spdy.beam +++ /dev/null cannot compute difference between binary files DELETED deps/cowlib/ebin/cowlib.app Index: deps/cowlib/ebin/cowlib.app ================================================================== --- deps/cowlib/ebin/cowlib.app +++ /dev/null @@ -1,8 +0,0 @@ -{application,cowlib, - [{description,"Support library for manipulating Web protocols."}, - {vsn,"1.0.2"}, - {id,"git"}, - {modules,[cow_cookie,cow_date,cow_http,cow_http_hd,cow_http_te, - cow_mimetypes,cow_multipart,cow_qs,cow_spdy]}, - {registered,[]}, - {applications,[kernel,stdlib,crypto]}]}. DELETED deps/cowlib/erlang.mk Index: deps/cowlib/erlang.mk ================================================================== --- deps/cowlib/erlang.mk +++ /dev/null @@ -1,6056 +0,0 @@ -# Copyright (c) 2013-2015, Loïc Hoguin -# -# Permission to use, copy, modify, and/or distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -.PHONY: all app deps search rel docs install-docs check tests clean distclean help erlang-mk - -ERLANG_MK_FILENAME := $(realpath $(lastword $(MAKEFILE_LIST))) - -ERLANG_MK_VERSION = 1.2.0-646-gcf43676 - -# Core configuration. - -PROJECT ?= $(notdir $(CURDIR)) -PROJECT := $(strip $(PROJECT)) - -PROJECT_VERSION ?= rolling - -# Verbosity. - -V ?= 0 - -verbose_0 = @ -verbose = $(verbose_$(V)) - -gen_verbose_0 = @echo " GEN " $@; -gen_verbose = $(gen_verbose_$(V)) - -# Temporary files directory. - -ERLANG_MK_TMP ?= $(CURDIR)/.erlang.mk -export ERLANG_MK_TMP - -# "erl" command. - -ERL = erl +A0 -noinput -boot start_clean - -# Platform detection. -# @todo Add Windows/Cygwin detection eventually. - -ifeq ($(PLATFORM),) -UNAME_S := $(shell uname -s) - -ifeq ($(UNAME_S),Linux) -PLATFORM = linux -else ifeq ($(UNAME_S),Darwin) -PLATFORM = darwin -else ifeq ($(UNAME_S),SunOS) -PLATFORM = solaris -else ifeq ($(UNAME_S),GNU) -PLATFORM = gnu -else ifeq ($(UNAME_S),FreeBSD) -PLATFORM = freebsd -else ifeq ($(UNAME_S),NetBSD) -PLATFORM = netbsd -else ifeq ($(UNAME_S),OpenBSD) -PLATFORM = openbsd -else -$(error Unable to detect platform. Please open a ticket with the output of uname -a.) -endif - -export PLATFORM -endif - -# Core targets. - -ifneq ($(words $(MAKECMDGOALS)),1) -.NOTPARALLEL: -endif - -all:: deps - $(verbose) $(MAKE) --no-print-directory app - $(verbose) $(MAKE) --no-print-directory rel - -# Noop to avoid a Make warning when there's nothing to do. -rel:: - $(verbose) echo -n - -check:: clean app tests - -clean:: clean-crashdump - -clean-crashdump: -ifneq ($(wildcard erl_crash.dump),) - $(gen_verbose) rm -f erl_crash.dump -endif - -distclean:: clean - -help:: - $(verbose) printf "%s\n" \ - "erlang.mk (version $(ERLANG_MK_VERSION)) is distributed under the terms of the ISC License." \ - "Copyright (c) 2013-2015 Loïc Hoguin " \ - "" \ - "Usage: [V=1] $(MAKE) [-jNUM] [target]..." \ - "" \ - "Core targets:" \ - " all Run deps, app and rel targets in that order" \ - " app Compile the project" \ - " deps Fetch dependencies (if needed) and compile them" \ - " search q=... Search for a package in the built-in index" \ - " rel Build a release for this project, if applicable" \ - " docs Build the documentation for this project" \ - " install-docs Install the man pages for this project" \ - " check Compile and run all tests and analysis for this project" \ - " tests Run the tests for this project" \ - " clean Delete temporary and output files from most targets" \ - " distclean Delete all temporary and output files" \ - " help Display this help and exit" \ - " erlang-mk Update erlang.mk to the latest version" - -# Core functions. - -empty := -space := $(empty) $(empty) -tab := $(empty) $(empty) -comma := , - -define newline - - -endef - -define comma_list -$(subst $(space),$(comma),$(strip $(1))) -endef - -# Adding erlang.mk to make Erlang scripts who call init:get_plain_arguments() happy. -define erlang -$(ERL) $(2) -pz $(ERLANG_MK_TMP)/rebar/ebin -eval "$(subst $(newline),,$(subst ",\",$(1)))" -- erlang.mk -endef - -ifeq ($(shell which wget 2>/dev/null | wc -l), 1) -define core_http_get - wget --no-check-certificate -O $(1) $(2)|| rm $(1) -endef -else -define core_http_get.erl - ssl:start(), - inets:start(), - case httpc:request(get, {"$(2)", []}, [{autoredirect, true}], []) of - {ok, {{_, 200, _}, _, Body}} -> - case file:write_file("$(1)", Body) of - ok -> ok; - {error, R1} -> halt(R1) - end; - {error, R2} -> - halt(R2) - end, - halt(0). -endef - -define core_http_get - $(call erlang,$(call core_http_get.erl,$(1),$(2))) -endef -endif - -core_eq = $(and $(findstring $(1),$(2)),$(findstring $(2),$(1))) - -core_find = $(foreach d,$(call core_ls,$1*),$(call core_find,$d/,$2) $(filter $(subst *,%,$2),$d)) - -core_lc = $(subst A,a,$(subst B,b,$(subst C,c,$(subst D,d,$(subst E,e,$(subst F,f,$(subst G,g,$(subst H,h,$(subst I,i,$(subst J,j,$(subst K,k,$(subst L,l,$(subst M,m,$(subst N,n,$(subst O,o,$(subst P,p,$(subst Q,q,$(subst R,r,$(subst S,s,$(subst T,t,$(subst U,u,$(subst V,v,$(subst W,w,$(subst X,x,$(subst Y,y,$(subst Z,z,$(1))))))))))))))))))))))))))) - -# @todo On Windows: $(shell dir /B $(1)); make sure to handle when no file exists. -core_ls = $(filter-out $(1),$(shell echo $(1))) - -# Automated update. - -ERLANG_MK_BUILD_CONFIG ?= build.config -ERLANG_MK_BUILD_DIR ?= .erlang.mk.build - -erlang-mk: - git clone https://github.com/ninenines/erlang.mk $(ERLANG_MK_BUILD_DIR) - if [ -f $(ERLANG_MK_BUILD_CONFIG) ]; then cp $(ERLANG_MK_BUILD_CONFIG) $(ERLANG_MK_BUILD_DIR); fi - cd $(ERLANG_MK_BUILD_DIR) && $(MAKE) - cp $(ERLANG_MK_BUILD_DIR)/erlang.mk ./erlang.mk - rm -rf $(ERLANG_MK_BUILD_DIR) - -# The erlang.mk package index is bundled in the default erlang.mk build. -# Search for the string "copyright" to skip to the rest of the code. - -PACKAGES += aberth -pkg_aberth_name = aberth -pkg_aberth_description = Generic BERT-RPC server in Erlang -pkg_aberth_homepage = https://github.com/a13x/aberth -pkg_aberth_fetch = git -pkg_aberth_repo = https://github.com/a13x/aberth -pkg_aberth_commit = master - -PACKAGES += active -pkg_active_name = active -pkg_active_description = Active development for Erlang: rebuild and reload source/binary files while the VM is running -pkg_active_homepage = https://github.com/proger/active -pkg_active_fetch = git -pkg_active_repo = https://github.com/proger/active -pkg_active_commit = master - -PACKAGES += actordb_core -pkg_actordb_core_name = actordb_core -pkg_actordb_core_description = ActorDB main source -pkg_actordb_core_homepage = http://www.actordb.com/ -pkg_actordb_core_fetch = git -pkg_actordb_core_repo = https://github.com/biokoda/actordb_core -pkg_actordb_core_commit = master - -PACKAGES += actordb_thrift -pkg_actordb_thrift_name = actordb_thrift -pkg_actordb_thrift_description = Thrift API for ActorDB -pkg_actordb_thrift_homepage = http://www.actordb.com/ -pkg_actordb_thrift_fetch = git -pkg_actordb_thrift_repo = https://github.com/biokoda/actordb_thrift -pkg_actordb_thrift_commit = master - -PACKAGES += aleppo -pkg_aleppo_name = aleppo -pkg_aleppo_description = Alternative Erlang Pre-Processor -pkg_aleppo_homepage = https://github.com/ErlyORM/aleppo -pkg_aleppo_fetch = git -pkg_aleppo_repo = https://github.com/ErlyORM/aleppo -pkg_aleppo_commit = master - -PACKAGES += alog -pkg_alog_name = alog -pkg_alog_description = Simply the best logging framework for Erlang -pkg_alog_homepage = https://github.com/siberian-fast-food/alogger -pkg_alog_fetch = git -pkg_alog_repo = https://github.com/siberian-fast-food/alogger -pkg_alog_commit = master - -PACKAGES += amqp_client -pkg_amqp_client_name = amqp_client -pkg_amqp_client_description = RabbitMQ Erlang AMQP client -pkg_amqp_client_homepage = https://www.rabbitmq.com/erlang-client-user-guide.html -pkg_amqp_client_fetch = git -pkg_amqp_client_repo = https://github.com/rabbitmq/rabbitmq-erlang-client.git -pkg_amqp_client_commit = master - -PACKAGES += annotations -pkg_annotations_name = annotations -pkg_annotations_description = Simple code instrumentation utilities -pkg_annotations_homepage = https://github.com/hyperthunk/annotations -pkg_annotations_fetch = git -pkg_annotations_repo = https://github.com/hyperthunk/annotations -pkg_annotations_commit = master - -PACKAGES += antidote -pkg_antidote_name = antidote -pkg_antidote_description = Large-scale computation without synchronisation -pkg_antidote_homepage = https://syncfree.lip6.fr/ -pkg_antidote_fetch = git -pkg_antidote_repo = https://github.com/SyncFree/antidote -pkg_antidote_commit = master - -PACKAGES += apns -pkg_apns_name = apns -pkg_apns_description = Apple Push Notification Server for Erlang -pkg_apns_homepage = http://inaka.github.com/apns4erl -pkg_apns_fetch = git -pkg_apns_repo = https://github.com/inaka/apns4erl -pkg_apns_commit = 1.0.4 - -PACKAGES += azdht -pkg_azdht_name = azdht -pkg_azdht_description = Azureus Distributed Hash Table (DHT) in Erlang -pkg_azdht_homepage = https://github.com/arcusfelis/azdht -pkg_azdht_fetch = git -pkg_azdht_repo = https://github.com/arcusfelis/azdht -pkg_azdht_commit = master - -PACKAGES += backoff -pkg_backoff_name = backoff -pkg_backoff_description = Simple exponential backoffs in Erlang -pkg_backoff_homepage = https://github.com/ferd/backoff -pkg_backoff_fetch = git -pkg_backoff_repo = https://github.com/ferd/backoff -pkg_backoff_commit = master - -PACKAGES += barrel_tcp -pkg_barrel_tcp_name = barrel_tcp -pkg_barrel_tcp_description = barrel is a generic TCP acceptor pool with low latency in Erlang. -pkg_barrel_tcp_homepage = https://github.com/benoitc-attic/barrel_tcp -pkg_barrel_tcp_fetch = git -pkg_barrel_tcp_repo = https://github.com/benoitc-attic/barrel_tcp -pkg_barrel_tcp_commit = master - -PACKAGES += basho_bench -pkg_basho_bench_name = basho_bench -pkg_basho_bench_description = A load-generation and testing tool for basically whatever you can write a returning Erlang function for. -pkg_basho_bench_homepage = https://github.com/basho/basho_bench -pkg_basho_bench_fetch = git -pkg_basho_bench_repo = https://github.com/basho/basho_bench -pkg_basho_bench_commit = master - -PACKAGES += bcrypt -pkg_bcrypt_name = bcrypt -pkg_bcrypt_description = Bcrypt Erlang / C library -pkg_bcrypt_homepage = https://github.com/riverrun/branglecrypt -pkg_bcrypt_fetch = git -pkg_bcrypt_repo = https://github.com/riverrun/branglecrypt -pkg_bcrypt_commit = master - -PACKAGES += beam -pkg_beam_name = beam -pkg_beam_description = BEAM emulator written in Erlang -pkg_beam_homepage = https://github.com/tonyrog/beam -pkg_beam_fetch = git -pkg_beam_repo = https://github.com/tonyrog/beam -pkg_beam_commit = master - -PACKAGES += beanstalk -pkg_beanstalk_name = beanstalk -pkg_beanstalk_description = An Erlang client for beanstalkd -pkg_beanstalk_homepage = https://github.com/tim/erlang-beanstalk -pkg_beanstalk_fetch = git -pkg_beanstalk_repo = https://github.com/tim/erlang-beanstalk -pkg_beanstalk_commit = master - -PACKAGES += bear -pkg_bear_name = bear -pkg_bear_description = a set of statistics functions for erlang -pkg_bear_homepage = https://github.com/boundary/bear -pkg_bear_fetch = git -pkg_bear_repo = https://github.com/boundary/bear -pkg_bear_commit = master - -PACKAGES += bertconf -pkg_bertconf_name = bertconf -pkg_bertconf_description = Make ETS tables out of statc BERT files that are auto-reloaded -pkg_bertconf_homepage = https://github.com/ferd/bertconf -pkg_bertconf_fetch = git -pkg_bertconf_repo = https://github.com/ferd/bertconf -pkg_bertconf_commit = master - -PACKAGES += bifrost -pkg_bifrost_name = bifrost -pkg_bifrost_description = Erlang FTP Server Framework -pkg_bifrost_homepage = https://github.com/thorstadt/bifrost -pkg_bifrost_fetch = git -pkg_bifrost_repo = https://github.com/thorstadt/bifrost -pkg_bifrost_commit = master - -PACKAGES += binpp -pkg_binpp_name = binpp -pkg_binpp_description = Erlang Binary Pretty Printer -pkg_binpp_homepage = https://github.com/jtendo/binpp -pkg_binpp_fetch = git -pkg_binpp_repo = https://github.com/jtendo/binpp -pkg_binpp_commit = master - -PACKAGES += bisect -pkg_bisect_name = bisect -pkg_bisect_description = Ordered fixed-size binary dictionary in Erlang -pkg_bisect_homepage = https://github.com/knutin/bisect -pkg_bisect_fetch = git -pkg_bisect_repo = https://github.com/knutin/bisect -pkg_bisect_commit = master - -PACKAGES += bitcask -pkg_bitcask_name = bitcask -pkg_bitcask_description = because you need another a key/value storage engine -pkg_bitcask_homepage = https://github.com/basho/bitcask -pkg_bitcask_fetch = git -pkg_bitcask_repo = https://github.com/basho/bitcask -pkg_bitcask_commit = master - -PACKAGES += bitstore -pkg_bitstore_name = bitstore -pkg_bitstore_description = A document based ontology development environment -pkg_bitstore_homepage = https://github.com/bdionne/bitstore -pkg_bitstore_fetch = git -pkg_bitstore_repo = https://github.com/bdionne/bitstore -pkg_bitstore_commit = master - -PACKAGES += bootstrap -pkg_bootstrap_name = bootstrap -pkg_bootstrap_description = A simple, yet powerful Erlang cluster bootstrapping application. -pkg_bootstrap_homepage = https://github.com/schlagert/bootstrap -pkg_bootstrap_fetch = git -pkg_bootstrap_repo = https://github.com/schlagert/bootstrap -pkg_bootstrap_commit = master - -PACKAGES += boss_db -pkg_boss_db_name = boss_db -pkg_boss_db_description = BossDB: a sharded, caching, pooling, evented ORM for Erlang -pkg_boss_db_homepage = https://github.com/ErlyORM/boss_db -pkg_boss_db_fetch = git -pkg_boss_db_repo = https://github.com/ErlyORM/boss_db -pkg_boss_db_commit = master - -PACKAGES += boss -pkg_boss_name = boss -pkg_boss_description = Erlang web MVC, now featuring Comet -pkg_boss_homepage = https://github.com/ChicagoBoss/ChicagoBoss -pkg_boss_fetch = git -pkg_boss_repo = https://github.com/ChicagoBoss/ChicagoBoss -pkg_boss_commit = master - -PACKAGES += bson -pkg_bson_name = bson -pkg_bson_description = BSON documents in Erlang, see bsonspec.org -pkg_bson_homepage = https://github.com/comtihon/bson-erlang -pkg_bson_fetch = git -pkg_bson_repo = https://github.com/comtihon/bson-erlang -pkg_bson_commit = master - -PACKAGES += bullet -pkg_bullet_name = bullet -pkg_bullet_description = Simple, reliable, efficient streaming for Cowboy. -pkg_bullet_homepage = http://ninenines.eu -pkg_bullet_fetch = git -pkg_bullet_repo = https://github.com/extend/bullet -pkg_bullet_commit = master - -PACKAGES += cache -pkg_cache_name = cache -pkg_cache_description = Erlang in-memory cache -pkg_cache_homepage = https://github.com/fogfish/cache -pkg_cache_fetch = git -pkg_cache_repo = https://github.com/fogfish/cache -pkg_cache_commit = master - -PACKAGES += cake -pkg_cake_name = cake -pkg_cake_description = Really simple terminal colorization -pkg_cake_homepage = https://github.com/darach/cake-erl -pkg_cake_fetch = git -pkg_cake_repo = https://github.com/darach/cake-erl -pkg_cake_commit = v0.1.2 - -PACKAGES += carotene -pkg_carotene_name = carotene -pkg_carotene_description = Real-time server -pkg_carotene_homepage = https://github.com/carotene/carotene -pkg_carotene_fetch = git -pkg_carotene_repo = https://github.com/carotene/carotene -pkg_carotene_commit = master - -PACKAGES += cberl -pkg_cberl_name = cberl -pkg_cberl_description = NIF based Erlang bindings for Couchbase -pkg_cberl_homepage = https://github.com/chitika/cberl -pkg_cberl_fetch = git -pkg_cberl_repo = https://github.com/chitika/cberl -pkg_cberl_commit = master - -PACKAGES += cecho -pkg_cecho_name = cecho -pkg_cecho_description = An ncurses library for Erlang -pkg_cecho_homepage = https://github.com/mazenharake/cecho -pkg_cecho_fetch = git -pkg_cecho_repo = https://github.com/mazenharake/cecho -pkg_cecho_commit = master - -PACKAGES += cferl -pkg_cferl_name = cferl -pkg_cferl_description = Rackspace / Open Stack Cloud Files Erlang Client -pkg_cferl_homepage = https://github.com/ddossot/cferl -pkg_cferl_fetch = git -pkg_cferl_repo = https://github.com/ddossot/cferl -pkg_cferl_commit = master - -PACKAGES += chaos_monkey -pkg_chaos_monkey_name = chaos_monkey -pkg_chaos_monkey_description = This is The CHAOS MONKEY. It will kill your processes. -pkg_chaos_monkey_homepage = https://github.com/dLuna/chaos_monkey -pkg_chaos_monkey_fetch = git -pkg_chaos_monkey_repo = https://github.com/dLuna/chaos_monkey -pkg_chaos_monkey_commit = master - -PACKAGES += check_node -pkg_check_node_name = check_node -pkg_check_node_description = Nagios Scripts for monitoring Riak -pkg_check_node_homepage = https://github.com/basho-labs/riak_nagios -pkg_check_node_fetch = git -pkg_check_node_repo = https://github.com/basho-labs/riak_nagios -pkg_check_node_commit = master - -PACKAGES += chronos -pkg_chronos_name = chronos -pkg_chronos_description = Timer module for Erlang that makes it easy to abstact time out of the tests. -pkg_chronos_homepage = https://github.com/lehoff/chronos -pkg_chronos_fetch = git -pkg_chronos_repo = https://github.com/lehoff/chronos -pkg_chronos_commit = master - -PACKAGES += classifier -pkg_classifier_name = classifier -pkg_classifier_description = An Erlang Bayesian Filter and Text Classifier -pkg_classifier_homepage = https://github.com/inaka/classifier -pkg_classifier_fetch = git -pkg_classifier_repo = https://github.com/inaka/classifier -pkg_classifier_commit = master - -PACKAGES += clique -pkg_clique_name = clique -pkg_clique_description = CLI Framework for Erlang -pkg_clique_homepage = https://github.com/basho/clique -pkg_clique_fetch = git -pkg_clique_repo = https://github.com/basho/clique -pkg_clique_commit = develop - -PACKAGES += cl -pkg_cl_name = cl -pkg_cl_description = OpenCL binding for Erlang -pkg_cl_homepage = https://github.com/tonyrog/cl -pkg_cl_fetch = git -pkg_cl_repo = https://github.com/tonyrog/cl -pkg_cl_commit = master - -PACKAGES += cloudi_core -pkg_cloudi_core_name = cloudi_core -pkg_cloudi_core_description = CloudI internal service runtime -pkg_cloudi_core_homepage = http://cloudi.org/ -pkg_cloudi_core_fetch = git -pkg_cloudi_core_repo = https://github.com/CloudI/cloudi_core -pkg_cloudi_core_commit = master - -PACKAGES += cloudi_service_api_requests -pkg_cloudi_service_api_requests_name = cloudi_service_api_requests -pkg_cloudi_service_api_requests_description = CloudI Service API requests (JSON-RPC/Erlang-term support) -pkg_cloudi_service_api_requests_homepage = http://cloudi.org/ -pkg_cloudi_service_api_requests_fetch = git -pkg_cloudi_service_api_requests_repo = https://github.com/CloudI/cloudi_service_api_requests -pkg_cloudi_service_api_requests_commit = master - -PACKAGES += cloudi_service_db_cassandra_cql -pkg_cloudi_service_db_cassandra_cql_name = cloudi_service_db_cassandra_cql -pkg_cloudi_service_db_cassandra_cql_description = Cassandra CQL CloudI Service -pkg_cloudi_service_db_cassandra_cql_homepage = http://cloudi.org/ -pkg_cloudi_service_db_cassandra_cql_fetch = git -pkg_cloudi_service_db_cassandra_cql_repo = https://github.com/CloudI/cloudi_service_db_cassandra_cql -pkg_cloudi_service_db_cassandra_cql_commit = master - -PACKAGES += cloudi_service_db_cassandra -pkg_cloudi_service_db_cassandra_name = cloudi_service_db_cassandra -pkg_cloudi_service_db_cassandra_description = Cassandra CloudI Service -pkg_cloudi_service_db_cassandra_homepage = http://cloudi.org/ -pkg_cloudi_service_db_cassandra_fetch = git -pkg_cloudi_service_db_cassandra_repo = https://github.com/CloudI/cloudi_service_db_cassandra -pkg_cloudi_service_db_cassandra_commit = master - -PACKAGES += cloudi_service_db_couchdb -pkg_cloudi_service_db_couchdb_name = cloudi_service_db_couchdb -pkg_cloudi_service_db_couchdb_description = CouchDB CloudI Service -pkg_cloudi_service_db_couchdb_homepage = http://cloudi.org/ -pkg_cloudi_service_db_couchdb_fetch = git -pkg_cloudi_service_db_couchdb_repo = https://github.com/CloudI/cloudi_service_db_couchdb -pkg_cloudi_service_db_couchdb_commit = master - -PACKAGES += cloudi_service_db_elasticsearch -pkg_cloudi_service_db_elasticsearch_name = cloudi_service_db_elasticsearch -pkg_cloudi_service_db_elasticsearch_description = elasticsearch CloudI Service -pkg_cloudi_service_db_elasticsearch_homepage = http://cloudi.org/ -pkg_cloudi_service_db_elasticsearch_fetch = git -pkg_cloudi_service_db_elasticsearch_repo = https://github.com/CloudI/cloudi_service_db_elasticsearch -pkg_cloudi_service_db_elasticsearch_commit = master - -PACKAGES += cloudi_service_db_memcached -pkg_cloudi_service_db_memcached_name = cloudi_service_db_memcached -pkg_cloudi_service_db_memcached_description = memcached CloudI Service -pkg_cloudi_service_db_memcached_homepage = http://cloudi.org/ -pkg_cloudi_service_db_memcached_fetch = git -pkg_cloudi_service_db_memcached_repo = https://github.com/CloudI/cloudi_service_db_memcached -pkg_cloudi_service_db_memcached_commit = master - -PACKAGES += cloudi_service_db -pkg_cloudi_service_db_name = cloudi_service_db -pkg_cloudi_service_db_description = CloudI Database (in-memory/testing/generic) -pkg_cloudi_service_db_homepage = http://cloudi.org/ -pkg_cloudi_service_db_fetch = git -pkg_cloudi_service_db_repo = https://github.com/CloudI/cloudi_service_db -pkg_cloudi_service_db_commit = master - -PACKAGES += cloudi_service_db_mysql -pkg_cloudi_service_db_mysql_name = cloudi_service_db_mysql -pkg_cloudi_service_db_mysql_description = MySQL CloudI Service -pkg_cloudi_service_db_mysql_homepage = http://cloudi.org/ -pkg_cloudi_service_db_mysql_fetch = git -pkg_cloudi_service_db_mysql_repo = https://github.com/CloudI/cloudi_service_db_mysql -pkg_cloudi_service_db_mysql_commit = master - -PACKAGES += cloudi_service_db_pgsql -pkg_cloudi_service_db_pgsql_name = cloudi_service_db_pgsql -pkg_cloudi_service_db_pgsql_description = PostgreSQL CloudI Service -pkg_cloudi_service_db_pgsql_homepage = http://cloudi.org/ -pkg_cloudi_service_db_pgsql_fetch = git -pkg_cloudi_service_db_pgsql_repo = https://github.com/CloudI/cloudi_service_db_pgsql -pkg_cloudi_service_db_pgsql_commit = master - -PACKAGES += cloudi_service_db_riak -pkg_cloudi_service_db_riak_name = cloudi_service_db_riak -pkg_cloudi_service_db_riak_description = Riak CloudI Service -pkg_cloudi_service_db_riak_homepage = http://cloudi.org/ -pkg_cloudi_service_db_riak_fetch = git -pkg_cloudi_service_db_riak_repo = https://github.com/CloudI/cloudi_service_db_riak -pkg_cloudi_service_db_riak_commit = master - -PACKAGES += cloudi_service_db_tokyotyrant -pkg_cloudi_service_db_tokyotyrant_name = cloudi_service_db_tokyotyrant -pkg_cloudi_service_db_tokyotyrant_description = Tokyo Tyrant CloudI Service -pkg_cloudi_service_db_tokyotyrant_homepage = http://cloudi.org/ -pkg_cloudi_service_db_tokyotyrant_fetch = git -pkg_cloudi_service_db_tokyotyrant_repo = https://github.com/CloudI/cloudi_service_db_tokyotyrant -pkg_cloudi_service_db_tokyotyrant_commit = master - -PACKAGES += cloudi_service_filesystem -pkg_cloudi_service_filesystem_name = cloudi_service_filesystem -pkg_cloudi_service_filesystem_description = Filesystem CloudI Service -pkg_cloudi_service_filesystem_homepage = http://cloudi.org/ -pkg_cloudi_service_filesystem_fetch = git -pkg_cloudi_service_filesystem_repo = https://github.com/CloudI/cloudi_service_filesystem -pkg_cloudi_service_filesystem_commit = master - -PACKAGES += cloudi_service_http_client -pkg_cloudi_service_http_client_name = cloudi_service_http_client -pkg_cloudi_service_http_client_description = HTTP client CloudI Service -pkg_cloudi_service_http_client_homepage = http://cloudi.org/ -pkg_cloudi_service_http_client_fetch = git -pkg_cloudi_service_http_client_repo = https://github.com/CloudI/cloudi_service_http_client -pkg_cloudi_service_http_client_commit = master - -PACKAGES += cloudi_service_http_cowboy -pkg_cloudi_service_http_cowboy_name = cloudi_service_http_cowboy -pkg_cloudi_service_http_cowboy_description = cowboy HTTP/HTTPS CloudI Service -pkg_cloudi_service_http_cowboy_homepage = http://cloudi.org/ -pkg_cloudi_service_http_cowboy_fetch = git -pkg_cloudi_service_http_cowboy_repo = https://github.com/CloudI/cloudi_service_http_cowboy -pkg_cloudi_service_http_cowboy_commit = master - -PACKAGES += cloudi_service_http_elli -pkg_cloudi_service_http_elli_name = cloudi_service_http_elli -pkg_cloudi_service_http_elli_description = elli HTTP CloudI Service -pkg_cloudi_service_http_elli_homepage = http://cloudi.org/ -pkg_cloudi_service_http_elli_fetch = git -pkg_cloudi_service_http_elli_repo = https://github.com/CloudI/cloudi_service_http_elli -pkg_cloudi_service_http_elli_commit = master - -PACKAGES += cloudi_service_map_reduce -pkg_cloudi_service_map_reduce_name = cloudi_service_map_reduce -pkg_cloudi_service_map_reduce_description = Map/Reduce CloudI Service -pkg_cloudi_service_map_reduce_homepage = http://cloudi.org/ -pkg_cloudi_service_map_reduce_fetch = git -pkg_cloudi_service_map_reduce_repo = https://github.com/CloudI/cloudi_service_map_reduce -pkg_cloudi_service_map_reduce_commit = master - -PACKAGES += cloudi_service_oauth1 -pkg_cloudi_service_oauth1_name = cloudi_service_oauth1 -pkg_cloudi_service_oauth1_description = OAuth v1.0 CloudI Service -pkg_cloudi_service_oauth1_homepage = http://cloudi.org/ -pkg_cloudi_service_oauth1_fetch = git -pkg_cloudi_service_oauth1_repo = https://github.com/CloudI/cloudi_service_oauth1 -pkg_cloudi_service_oauth1_commit = master - -PACKAGES += cloudi_service_queue -pkg_cloudi_service_queue_name = cloudi_service_queue -pkg_cloudi_service_queue_description = Persistent Queue Service -pkg_cloudi_service_queue_homepage = http://cloudi.org/ -pkg_cloudi_service_queue_fetch = git -pkg_cloudi_service_queue_repo = https://github.com/CloudI/cloudi_service_queue -pkg_cloudi_service_queue_commit = master - -PACKAGES += cloudi_service_quorum -pkg_cloudi_service_quorum_name = cloudi_service_quorum -pkg_cloudi_service_quorum_description = CloudI Quorum Service -pkg_cloudi_service_quorum_homepage = http://cloudi.org/ -pkg_cloudi_service_quorum_fetch = git -pkg_cloudi_service_quorum_repo = https://github.com/CloudI/cloudi_service_quorum -pkg_cloudi_service_quorum_commit = master - -PACKAGES += cloudi_service_router -pkg_cloudi_service_router_name = cloudi_service_router -pkg_cloudi_service_router_description = CloudI Router Service -pkg_cloudi_service_router_homepage = http://cloudi.org/ -pkg_cloudi_service_router_fetch = git -pkg_cloudi_service_router_repo = https://github.com/CloudI/cloudi_service_router -pkg_cloudi_service_router_commit = master - -PACKAGES += cloudi_service_tcp -pkg_cloudi_service_tcp_name = cloudi_service_tcp -pkg_cloudi_service_tcp_description = TCP CloudI Service -pkg_cloudi_service_tcp_homepage = http://cloudi.org/ -pkg_cloudi_service_tcp_fetch = git -pkg_cloudi_service_tcp_repo = https://github.com/CloudI/cloudi_service_tcp -pkg_cloudi_service_tcp_commit = master - -PACKAGES += cloudi_service_timers -pkg_cloudi_service_timers_name = cloudi_service_timers -pkg_cloudi_service_timers_description = Timers CloudI Service -pkg_cloudi_service_timers_homepage = http://cloudi.org/ -pkg_cloudi_service_timers_fetch = git -pkg_cloudi_service_timers_repo = https://github.com/CloudI/cloudi_service_timers -pkg_cloudi_service_timers_commit = master - -PACKAGES += cloudi_service_udp -pkg_cloudi_service_udp_name = cloudi_service_udp -pkg_cloudi_service_udp_description = UDP CloudI Service -pkg_cloudi_service_udp_homepage = http://cloudi.org/ -pkg_cloudi_service_udp_fetch = git -pkg_cloudi_service_udp_repo = https://github.com/CloudI/cloudi_service_udp -pkg_cloudi_service_udp_commit = master - -PACKAGES += cloudi_service_validate -pkg_cloudi_service_validate_name = cloudi_service_validate -pkg_cloudi_service_validate_description = CloudI Validate Service -pkg_cloudi_service_validate_homepage = http://cloudi.org/ -pkg_cloudi_service_validate_fetch = git -pkg_cloudi_service_validate_repo = https://github.com/CloudI/cloudi_service_validate -pkg_cloudi_service_validate_commit = master - -PACKAGES += cloudi_service_zeromq -pkg_cloudi_service_zeromq_name = cloudi_service_zeromq -pkg_cloudi_service_zeromq_description = ZeroMQ CloudI Service -pkg_cloudi_service_zeromq_homepage = http://cloudi.org/ -pkg_cloudi_service_zeromq_fetch = git -pkg_cloudi_service_zeromq_repo = https://github.com/CloudI/cloudi_service_zeromq -pkg_cloudi_service_zeromq_commit = master - -PACKAGES += cluster_info -pkg_cluster_info_name = cluster_info -pkg_cluster_info_description = Fork of Hibari's nifty cluster_info OTP app -pkg_cluster_info_homepage = https://github.com/basho/cluster_info -pkg_cluster_info_fetch = git -pkg_cluster_info_repo = https://github.com/basho/cluster_info -pkg_cluster_info_commit = master - -PACKAGES += color -pkg_color_name = color -pkg_color_description = ANSI colors for your Erlang -pkg_color_homepage = https://github.com/julianduque/erlang-color -pkg_color_fetch = git -pkg_color_repo = https://github.com/julianduque/erlang-color -pkg_color_commit = master - -PACKAGES += confetti -pkg_confetti_name = confetti -pkg_confetti_description = Erlang configuration provider / application:get_env/2 on steroids -pkg_confetti_homepage = https://github.com/jtendo/confetti -pkg_confetti_fetch = git -pkg_confetti_repo = https://github.com/jtendo/confetti -pkg_confetti_commit = master - -PACKAGES += couchbeam -pkg_couchbeam_name = couchbeam -pkg_couchbeam_description = Apache CouchDB client in Erlang -pkg_couchbeam_homepage = https://github.com/benoitc/couchbeam -pkg_couchbeam_fetch = git -pkg_couchbeam_repo = https://github.com/benoitc/couchbeam -pkg_couchbeam_commit = master - -PACKAGES += couch -pkg_couch_name = couch -pkg_couch_description = A embeddable document oriented database compatible with Apache CouchDB -pkg_couch_homepage = https://github.com/benoitc/opencouch -pkg_couch_fetch = git -pkg_couch_repo = https://github.com/benoitc/opencouch -pkg_couch_commit = master - -PACKAGES += covertool -pkg_covertool_name = covertool -pkg_covertool_description = Tool to convert Erlang cover data files into Cobertura XML reports -pkg_covertool_homepage = https://github.com/idubrov/covertool -pkg_covertool_fetch = git -pkg_covertool_repo = https://github.com/idubrov/covertool -pkg_covertool_commit = master - -PACKAGES += cowboy -pkg_cowboy_name = cowboy -pkg_cowboy_description = Small, fast and modular HTTP server. -pkg_cowboy_homepage = http://ninenines.eu -pkg_cowboy_fetch = git -pkg_cowboy_repo = https://github.com/ninenines/cowboy -pkg_cowboy_commit = 1.0.1 - -PACKAGES += cowdb -pkg_cowdb_name = cowdb -pkg_cowdb_description = Pure Key/Value database library for Erlang Applications -pkg_cowdb_homepage = https://github.com/refuge/cowdb -pkg_cowdb_fetch = git -pkg_cowdb_repo = https://github.com/refuge/cowdb -pkg_cowdb_commit = master - -PACKAGES += cowlib -pkg_cowlib_name = cowlib -pkg_cowlib_description = Support library for manipulating Web protocols. -pkg_cowlib_homepage = http://ninenines.eu -pkg_cowlib_fetch = git -pkg_cowlib_repo = https://github.com/ninenines/cowlib -pkg_cowlib_commit = 1.0.1 - -PACKAGES += cpg -pkg_cpg_name = cpg -pkg_cpg_description = CloudI Process Groups -pkg_cpg_homepage = https://github.com/okeuday/cpg -pkg_cpg_fetch = git -pkg_cpg_repo = https://github.com/okeuday/cpg -pkg_cpg_commit = master - -PACKAGES += cqerl -pkg_cqerl_name = cqerl -pkg_cqerl_description = Native Erlang CQL client for Cassandra -pkg_cqerl_homepage = https://matehat.github.io/cqerl/ -pkg_cqerl_fetch = git -pkg_cqerl_repo = https://github.com/matehat/cqerl -pkg_cqerl_commit = master - -PACKAGES += cr -pkg_cr_name = cr -pkg_cr_description = Chain Replication -pkg_cr_homepage = https://synrc.com/apps/cr/doc/cr.htm -pkg_cr_fetch = git -pkg_cr_repo = https://github.com/spawnproc/cr -pkg_cr_commit = master - -PACKAGES += cuttlefish -pkg_cuttlefish_name = cuttlefish -pkg_cuttlefish_description = never lose your childlike sense of wonder baby cuttlefish, promise me? -pkg_cuttlefish_homepage = https://github.com/basho/cuttlefish -pkg_cuttlefish_fetch = git -pkg_cuttlefish_repo = https://github.com/basho/cuttlefish -pkg_cuttlefish_commit = master - -PACKAGES += damocles -pkg_damocles_name = damocles -pkg_damocles_description = Erlang library for generating adversarial network conditions for QAing distributed applications/systems on a single Linux box. -pkg_damocles_homepage = https://github.com/lostcolony/damocles -pkg_damocles_fetch = git -pkg_damocles_repo = https://github.com/lostcolony/damocles -pkg_damocles_commit = master - -PACKAGES += debbie -pkg_debbie_name = debbie -pkg_debbie_description = .DEB Built In Erlang -pkg_debbie_homepage = https://github.com/crownedgrouse/debbie -pkg_debbie_fetch = git -pkg_debbie_repo = https://github.com/crownedgrouse/debbie -pkg_debbie_commit = master - -PACKAGES += decimal -pkg_decimal_name = decimal -pkg_decimal_description = An Erlang decimal arithmetic library -pkg_decimal_homepage = https://github.com/tim/erlang-decimal -pkg_decimal_fetch = git -pkg_decimal_repo = https://github.com/tim/erlang-decimal -pkg_decimal_commit = master - -PACKAGES += detergent -pkg_detergent_name = detergent -pkg_detergent_description = An emulsifying Erlang SOAP library -pkg_detergent_homepage = https://github.com/devinus/detergent -pkg_detergent_fetch = git -pkg_detergent_repo = https://github.com/devinus/detergent -pkg_detergent_commit = master - -PACKAGES += detest -pkg_detest_name = detest -pkg_detest_description = Tool for running tests on a cluster of erlang nodes -pkg_detest_homepage = https://github.com/biokoda/detest -pkg_detest_fetch = git -pkg_detest_repo = https://github.com/biokoda/detest -pkg_detest_commit = master - -PACKAGES += dh_date -pkg_dh_date_name = dh_date -pkg_dh_date_description = Date formatting / parsing library for erlang -pkg_dh_date_homepage = https://github.com/daleharvey/dh_date -pkg_dh_date_fetch = git -pkg_dh_date_repo = https://github.com/daleharvey/dh_date -pkg_dh_date_commit = master - -PACKAGES += dhtcrawler -pkg_dhtcrawler_name = dhtcrawler -pkg_dhtcrawler_description = dhtcrawler is a DHT crawler written in erlang. It can join a DHT network and crawl many P2P torrents. -pkg_dhtcrawler_homepage = https://github.com/kevinlynx/dhtcrawler -pkg_dhtcrawler_fetch = git -pkg_dhtcrawler_repo = https://github.com/kevinlynx/dhtcrawler -pkg_dhtcrawler_commit = master - -PACKAGES += dirbusterl -pkg_dirbusterl_name = dirbusterl -pkg_dirbusterl_description = DirBuster successor in Erlang -pkg_dirbusterl_homepage = https://github.com/silentsignal/DirBustErl -pkg_dirbusterl_fetch = git -pkg_dirbusterl_repo = https://github.com/silentsignal/DirBustErl -pkg_dirbusterl_commit = master - -PACKAGES += dispcount -pkg_dispcount_name = dispcount -pkg_dispcount_description = Erlang task dispatcher based on ETS counters. -pkg_dispcount_homepage = https://github.com/ferd/dispcount -pkg_dispcount_fetch = git -pkg_dispcount_repo = https://github.com/ferd/dispcount -pkg_dispcount_commit = master - -PACKAGES += dlhttpc -pkg_dlhttpc_name = dlhttpc -pkg_dlhttpc_description = dispcount-based lhttpc fork for massive amounts of requests to limited endpoints -pkg_dlhttpc_homepage = https://github.com/ferd/dlhttpc -pkg_dlhttpc_fetch = git -pkg_dlhttpc_repo = https://github.com/ferd/dlhttpc -pkg_dlhttpc_commit = master - -PACKAGES += dns -pkg_dns_name = dns -pkg_dns_description = Erlang DNS library -pkg_dns_homepage = https://github.com/aetrion/dns_erlang -pkg_dns_fetch = git -pkg_dns_repo = https://github.com/aetrion/dns_erlang -pkg_dns_commit = master - -PACKAGES += dnssd -pkg_dnssd_name = dnssd -pkg_dnssd_description = Erlang interface to Apple's Bonjour D NS Service Discovery implementation -pkg_dnssd_homepage = https://github.com/benoitc/dnssd_erlang -pkg_dnssd_fetch = git -pkg_dnssd_repo = https://github.com/benoitc/dnssd_erlang -pkg_dnssd_commit = master - -PACKAGES += dtl -pkg_dtl_name = dtl -pkg_dtl_description = Django Template Language: A full-featured port of the Django template engine to Erlang. -pkg_dtl_homepage = https://github.com/oinksoft/dtl -pkg_dtl_fetch = git -pkg_dtl_repo = https://github.com/oinksoft/dtl -pkg_dtl_commit = master - -PACKAGES += dynamic_compile -pkg_dynamic_compile_name = dynamic_compile -pkg_dynamic_compile_description = compile and load erlang modules from string input -pkg_dynamic_compile_homepage = https://github.com/jkvor/dynamic_compile -pkg_dynamic_compile_fetch = git -pkg_dynamic_compile_repo = https://github.com/jkvor/dynamic_compile -pkg_dynamic_compile_commit = master - -PACKAGES += e2 -pkg_e2_name = e2 -pkg_e2_description = Library to simply writing correct OTP applications. -pkg_e2_homepage = http://e2project.org -pkg_e2_fetch = git -pkg_e2_repo = https://github.com/gar1t/e2 -pkg_e2_commit = master - -PACKAGES += eamf -pkg_eamf_name = eamf -pkg_eamf_description = eAMF provides Action Message Format (AMF) support for Erlang -pkg_eamf_homepage = https://github.com/mrinalwadhwa/eamf -pkg_eamf_fetch = git -pkg_eamf_repo = https://github.com/mrinalwadhwa/eamf -pkg_eamf_commit = master - -PACKAGES += eavro -pkg_eavro_name = eavro -pkg_eavro_description = Apache Avro encoder/decoder -pkg_eavro_homepage = https://github.com/SIfoxDevTeam/eavro -pkg_eavro_fetch = git -pkg_eavro_repo = https://github.com/SIfoxDevTeam/eavro -pkg_eavro_commit = master - -PACKAGES += ecapnp -pkg_ecapnp_name = ecapnp -pkg_ecapnp_description = Cap'n Proto library for Erlang -pkg_ecapnp_homepage = https://github.com/kaos/ecapnp -pkg_ecapnp_fetch = git -pkg_ecapnp_repo = https://github.com/kaos/ecapnp -pkg_ecapnp_commit = master - -PACKAGES += econfig -pkg_econfig_name = econfig -pkg_econfig_description = simple Erlang config handler using INI files -pkg_econfig_homepage = https://github.com/benoitc/econfig -pkg_econfig_fetch = git -pkg_econfig_repo = https://github.com/benoitc/econfig -pkg_econfig_commit = master - -PACKAGES += edate -pkg_edate_name = edate -pkg_edate_description = date manipulation library for erlang -pkg_edate_homepage = https://github.com/dweldon/edate -pkg_edate_fetch = git -pkg_edate_repo = https://github.com/dweldon/edate -pkg_edate_commit = master - -PACKAGES += edgar -pkg_edgar_name = edgar -pkg_edgar_description = Erlang Does GNU AR -pkg_edgar_homepage = https://github.com/crownedgrouse/edgar -pkg_edgar_fetch = git -pkg_edgar_repo = https://github.com/crownedgrouse/edgar -pkg_edgar_commit = master - -PACKAGES += edis -pkg_edis_name = edis -pkg_edis_description = An Erlang implementation of Redis KV Store -pkg_edis_homepage = http://inaka.github.com/edis/ -pkg_edis_fetch = git -pkg_edis_repo = https://github.com/inaka/edis -pkg_edis_commit = master - -PACKAGES += edns -pkg_edns_name = edns -pkg_edns_description = Erlang/OTP DNS server -pkg_edns_homepage = https://github.com/hcvst/erlang-dns -pkg_edns_fetch = git -pkg_edns_repo = https://github.com/hcvst/erlang-dns -pkg_edns_commit = master - -PACKAGES += edown -pkg_edown_name = edown -pkg_edown_description = EDoc extension for generating Github-flavored Markdown -pkg_edown_homepage = https://github.com/uwiger/edown -pkg_edown_fetch = git -pkg_edown_repo = https://github.com/uwiger/edown -pkg_edown_commit = master - -PACKAGES += eep_app -pkg_eep_app_name = eep_app -pkg_eep_app_description = Embedded Event Processing -pkg_eep_app_homepage = https://github.com/darach/eep-erl -pkg_eep_app_fetch = git -pkg_eep_app_repo = https://github.com/darach/eep-erl -pkg_eep_app_commit = master - -PACKAGES += eep -pkg_eep_name = eep -pkg_eep_description = Erlang Easy Profiling (eep) application provides a way to analyze application performance and call hierarchy -pkg_eep_homepage = https://github.com/virtan/eep -pkg_eep_fetch = git -pkg_eep_repo = https://github.com/virtan/eep -pkg_eep_commit = master - -PACKAGES += efene -pkg_efene_name = efene -pkg_efene_description = Alternative syntax for the Erlang Programming Language focusing on simplicity, ease of use and programmer UX -pkg_efene_homepage = https://github.com/efene/efene -pkg_efene_fetch = git -pkg_efene_repo = https://github.com/efene/efene -pkg_efene_commit = master - -PACKAGES += eganglia -pkg_eganglia_name = eganglia -pkg_eganglia_description = Erlang library to interact with Ganglia -pkg_eganglia_homepage = https://github.com/inaka/eganglia -pkg_eganglia_fetch = git -pkg_eganglia_repo = https://github.com/inaka/eganglia -pkg_eganglia_commit = v0.9.1 - -PACKAGES += egeoip -pkg_egeoip_name = egeoip -pkg_egeoip_description = Erlang IP Geolocation module, currently supporting the MaxMind GeoLite City Database. -pkg_egeoip_homepage = https://github.com/mochi/egeoip -pkg_egeoip_fetch = git -pkg_egeoip_repo = https://github.com/mochi/egeoip -pkg_egeoip_commit = master - -PACKAGES += ehsa -pkg_ehsa_name = ehsa -pkg_ehsa_description = Erlang HTTP server basic and digest authentication modules -pkg_ehsa_homepage = https://bitbucket.org/a12n/ehsa -pkg_ehsa_fetch = hg -pkg_ehsa_repo = https://bitbucket.org/a12n/ehsa -pkg_ehsa_commit = 2.0.4 - -PACKAGES += ejabberd -pkg_ejabberd_name = ejabberd -pkg_ejabberd_description = Robust, ubiquitous and massively scalable Jabber / XMPP Instant Messaging platform -pkg_ejabberd_homepage = https://github.com/processone/ejabberd -pkg_ejabberd_fetch = git -pkg_ejabberd_repo = https://github.com/processone/ejabberd -pkg_ejabberd_commit = master - -PACKAGES += ej -pkg_ej_name = ej -pkg_ej_description = Helper module for working with Erlang terms representing JSON -pkg_ej_homepage = https://github.com/seth/ej -pkg_ej_fetch = git -pkg_ej_repo = https://github.com/seth/ej -pkg_ej_commit = master - -PACKAGES += ejwt -pkg_ejwt_name = ejwt -pkg_ejwt_description = erlang library for JSON Web Token -pkg_ejwt_homepage = https://github.com/artefactop/ejwt -pkg_ejwt_fetch = git -pkg_ejwt_repo = https://github.com/artefactop/ejwt -pkg_ejwt_commit = master - -PACKAGES += ekaf -pkg_ekaf_name = ekaf -pkg_ekaf_description = A minimal, high-performance Kafka client in Erlang. -pkg_ekaf_homepage = https://github.com/helpshift/ekaf -pkg_ekaf_fetch = git -pkg_ekaf_repo = https://github.com/helpshift/ekaf -pkg_ekaf_commit = master - -PACKAGES += elarm -pkg_elarm_name = elarm -pkg_elarm_description = Alarm Manager for Erlang. -pkg_elarm_homepage = https://github.com/esl/elarm -pkg_elarm_fetch = git -pkg_elarm_repo = https://github.com/esl/elarm -pkg_elarm_commit = master - -PACKAGES += eleveldb -pkg_eleveldb_name = eleveldb -pkg_eleveldb_description = Erlang LevelDB API -pkg_eleveldb_homepage = https://github.com/basho/eleveldb -pkg_eleveldb_fetch = git -pkg_eleveldb_repo = https://github.com/basho/eleveldb -pkg_eleveldb_commit = master - -PACKAGES += elli -pkg_elli_name = elli -pkg_elli_description = Simple, robust and performant Erlang web server -pkg_elli_homepage = https://github.com/knutin/elli -pkg_elli_fetch = git -pkg_elli_repo = https://github.com/knutin/elli -pkg_elli_commit = master - -PACKAGES += elvis -pkg_elvis_name = elvis -pkg_elvis_description = Erlang Style Reviewer -pkg_elvis_homepage = https://github.com/inaka/elvis -pkg_elvis_fetch = git -pkg_elvis_repo = https://github.com/inaka/elvis -pkg_elvis_commit = 0.2.4 - -PACKAGES += emagick -pkg_emagick_name = emagick -pkg_emagick_description = Wrapper for Graphics/ImageMagick command line tool. -pkg_emagick_homepage = https://github.com/kivra/emagick -pkg_emagick_fetch = git -pkg_emagick_repo = https://github.com/kivra/emagick -pkg_emagick_commit = master - -PACKAGES += emysql -pkg_emysql_name = emysql -pkg_emysql_description = Stable, pure Erlang MySQL driver. -pkg_emysql_homepage = https://github.com/Eonblast/Emysql -pkg_emysql_fetch = git -pkg_emysql_repo = https://github.com/Eonblast/Emysql -pkg_emysql_commit = master - -PACKAGES += enm -pkg_enm_name = enm -pkg_enm_description = Erlang driver for nanomsg -pkg_enm_homepage = https://github.com/basho/enm -pkg_enm_fetch = git -pkg_enm_repo = https://github.com/basho/enm -pkg_enm_commit = master - -PACKAGES += entop -pkg_entop_name = entop -pkg_entop_description = A top-like tool for monitoring an Erlang node -pkg_entop_homepage = https://github.com/mazenharake/entop -pkg_entop_fetch = git -pkg_entop_repo = https://github.com/mazenharake/entop -pkg_entop_commit = master - -PACKAGES += epcap -pkg_epcap_name = epcap -pkg_epcap_description = Erlang packet capture interface using pcap -pkg_epcap_homepage = https://github.com/msantos/epcap -pkg_epcap_fetch = git -pkg_epcap_repo = https://github.com/msantos/epcap -pkg_epcap_commit = master - -PACKAGES += eper -pkg_eper_name = eper -pkg_eper_description = Erlang performance and debugging tools. -pkg_eper_homepage = https://github.com/massemanet/eper -pkg_eper_fetch = git -pkg_eper_repo = https://github.com/massemanet/eper -pkg_eper_commit = master - -PACKAGES += epgsql -pkg_epgsql_name = epgsql -pkg_epgsql_description = Erlang PostgreSQL client library. -pkg_epgsql_homepage = https://github.com/epgsql/epgsql -pkg_epgsql_fetch = git -pkg_epgsql_repo = https://github.com/epgsql/epgsql -pkg_epgsql_commit = master - -PACKAGES += episcina -pkg_episcina_name = episcina -pkg_episcina_description = A simple non intrusive resource pool for connections -pkg_episcina_homepage = https://github.com/erlware/episcina -pkg_episcina_fetch = git -pkg_episcina_repo = https://github.com/erlware/episcina -pkg_episcina_commit = master - -PACKAGES += eplot -pkg_eplot_name = eplot -pkg_eplot_description = A plot engine written in erlang. -pkg_eplot_homepage = https://github.com/psyeugenic/eplot -pkg_eplot_fetch = git -pkg_eplot_repo = https://github.com/psyeugenic/eplot -pkg_eplot_commit = master - -PACKAGES += epocxy -pkg_epocxy_name = epocxy -pkg_epocxy_description = Erlang Patterns of Concurrency -pkg_epocxy_homepage = https://github.com/duomark/epocxy -pkg_epocxy_fetch = git -pkg_epocxy_repo = https://github.com/duomark/epocxy -pkg_epocxy_commit = master - -PACKAGES += epubnub -pkg_epubnub_name = epubnub -pkg_epubnub_description = Erlang PubNub API -pkg_epubnub_homepage = https://github.com/tsloughter/epubnub -pkg_epubnub_fetch = git -pkg_epubnub_repo = https://github.com/tsloughter/epubnub -pkg_epubnub_commit = master - -PACKAGES += eqm -pkg_eqm_name = eqm -pkg_eqm_description = Erlang pub sub with supply-demand channels -pkg_eqm_homepage = https://github.com/loucash/eqm -pkg_eqm_fetch = git -pkg_eqm_repo = https://github.com/loucash/eqm -pkg_eqm_commit = master - -PACKAGES += eredis -pkg_eredis_name = eredis -pkg_eredis_description = Erlang Redis client -pkg_eredis_homepage = https://github.com/wooga/eredis -pkg_eredis_fetch = git -pkg_eredis_repo = https://github.com/wooga/eredis -pkg_eredis_commit = master - -PACKAGES += eredis_pool -pkg_eredis_pool_name = eredis_pool -pkg_eredis_pool_description = eredis_pool is Pool of Redis clients, using eredis and poolboy. -pkg_eredis_pool_homepage = https://github.com/hiroeorz/eredis_pool -pkg_eredis_pool_fetch = git -pkg_eredis_pool_repo = https://github.com/hiroeorz/eredis_pool -pkg_eredis_pool_commit = master - -PACKAGES += erlang_cep -pkg_erlang_cep_name = erlang_cep -pkg_erlang_cep_description = A basic CEP package written in erlang -pkg_erlang_cep_homepage = https://github.com/danmacklin/erlang_cep -pkg_erlang_cep_fetch = git -pkg_erlang_cep_repo = https://github.com/danmacklin/erlang_cep -pkg_erlang_cep_commit = master - -PACKAGES += erlang_js -pkg_erlang_js_name = erlang_js -pkg_erlang_js_description = A linked-in driver for Erlang to Mozilla's Spidermonkey Javascript runtime. -pkg_erlang_js_homepage = https://github.com/basho/erlang_js -pkg_erlang_js_fetch = git -pkg_erlang_js_repo = https://github.com/basho/erlang_js -pkg_erlang_js_commit = master - -PACKAGES += erlang_localtime -pkg_erlang_localtime_name = erlang_localtime -pkg_erlang_localtime_description = Erlang library for conversion from one local time to another -pkg_erlang_localtime_homepage = https://github.com/dmitryme/erlang_localtime -pkg_erlang_localtime_fetch = git -pkg_erlang_localtime_repo = https://github.com/dmitryme/erlang_localtime -pkg_erlang_localtime_commit = master - -PACKAGES += erlang_smtp -pkg_erlang_smtp_name = erlang_smtp -pkg_erlang_smtp_description = Erlang SMTP and POP3 server code. -pkg_erlang_smtp_homepage = https://github.com/tonyg/erlang-smtp -pkg_erlang_smtp_fetch = git -pkg_erlang_smtp_repo = https://github.com/tonyg/erlang-smtp -pkg_erlang_smtp_commit = master - -PACKAGES += erlang_term -pkg_erlang_term_name = erlang_term -pkg_erlang_term_description = Erlang Term Info -pkg_erlang_term_homepage = https://github.com/okeuday/erlang_term -pkg_erlang_term_fetch = git -pkg_erlang_term_repo = https://github.com/okeuday/erlang_term -pkg_erlang_term_commit = master - -PACKAGES += erlastic_search -pkg_erlastic_search_name = erlastic_search -pkg_erlastic_search_description = An Erlang app for communicating with Elastic Search's rest interface. -pkg_erlastic_search_homepage = https://github.com/tsloughter/erlastic_search -pkg_erlastic_search_fetch = git -pkg_erlastic_search_repo = https://github.com/tsloughter/erlastic_search -pkg_erlastic_search_commit = master - -PACKAGES += erlasticsearch -pkg_erlasticsearch_name = erlasticsearch -pkg_erlasticsearch_description = Erlang thrift interface to elastic_search -pkg_erlasticsearch_homepage = https://github.com/dieswaytoofast/erlasticsearch -pkg_erlasticsearch_fetch = git -pkg_erlasticsearch_repo = https://github.com/dieswaytoofast/erlasticsearch -pkg_erlasticsearch_commit = master - -PACKAGES += erlbrake -pkg_erlbrake_name = erlbrake -pkg_erlbrake_description = Erlang Airbrake notification client -pkg_erlbrake_homepage = https://github.com/kenpratt/erlbrake -pkg_erlbrake_fetch = git -pkg_erlbrake_repo = https://github.com/kenpratt/erlbrake -pkg_erlbrake_commit = master - -PACKAGES += erlcloud -pkg_erlcloud_name = erlcloud -pkg_erlcloud_description = Cloud Computing library for erlang (Amazon EC2, S3, SQS, SimpleDB, Mechanical Turk, ELB) -pkg_erlcloud_homepage = https://github.com/gleber/erlcloud -pkg_erlcloud_fetch = git -pkg_erlcloud_repo = https://github.com/gleber/erlcloud -pkg_erlcloud_commit = master - -PACKAGES += erlcron -pkg_erlcron_name = erlcron -pkg_erlcron_description = Erlang cronish system -pkg_erlcron_homepage = https://github.com/erlware/erlcron -pkg_erlcron_fetch = git -pkg_erlcron_repo = https://github.com/erlware/erlcron -pkg_erlcron_commit = master - -PACKAGES += erldb -pkg_erldb_name = erldb -pkg_erldb_description = ORM (Object-relational mapping) application implemented in Erlang -pkg_erldb_homepage = http://erldb.org -pkg_erldb_fetch = git -pkg_erldb_repo = https://github.com/erldb/erldb -pkg_erldb_commit = master - -PACKAGES += erldis -pkg_erldis_name = erldis -pkg_erldis_description = redis erlang client library -pkg_erldis_homepage = https://github.com/cstar/erldis -pkg_erldis_fetch = git -pkg_erldis_repo = https://github.com/cstar/erldis -pkg_erldis_commit = master - -PACKAGES += erldns -pkg_erldns_name = erldns -pkg_erldns_description = DNS server, in erlang. -pkg_erldns_homepage = https://github.com/aetrion/erl-dns -pkg_erldns_fetch = git -pkg_erldns_repo = https://github.com/aetrion/erl-dns -pkg_erldns_commit = master - -PACKAGES += erldocker -pkg_erldocker_name = erldocker -pkg_erldocker_description = Docker Remote API client for Erlang -pkg_erldocker_homepage = https://github.com/proger/erldocker -pkg_erldocker_fetch = git -pkg_erldocker_repo = https://github.com/proger/erldocker -pkg_erldocker_commit = master - -PACKAGES += erlfsmon -pkg_erlfsmon_name = erlfsmon -pkg_erlfsmon_description = Erlang filesystem event watcher for Linux and OSX -pkg_erlfsmon_homepage = https://github.com/proger/erlfsmon -pkg_erlfsmon_fetch = git -pkg_erlfsmon_repo = https://github.com/proger/erlfsmon -pkg_erlfsmon_commit = master - -PACKAGES += erlgit -pkg_erlgit_name = erlgit -pkg_erlgit_description = Erlang convenience wrapper around git executable -pkg_erlgit_homepage = https://github.com/gleber/erlgit -pkg_erlgit_fetch = git -pkg_erlgit_repo = https://github.com/gleber/erlgit -pkg_erlgit_commit = master - -PACKAGES += erlguten -pkg_erlguten_name = erlguten -pkg_erlguten_description = ErlGuten is a system for high-quality typesetting, written purely in Erlang. -pkg_erlguten_homepage = https://github.com/richcarl/erlguten -pkg_erlguten_fetch = git -pkg_erlguten_repo = https://github.com/richcarl/erlguten -pkg_erlguten_commit = master - -PACKAGES += erlmc -pkg_erlmc_name = erlmc -pkg_erlmc_description = Erlang memcached binary protocol client -pkg_erlmc_homepage = https://github.com/jkvor/erlmc -pkg_erlmc_fetch = git -pkg_erlmc_repo = https://github.com/jkvor/erlmc -pkg_erlmc_commit = master - -PACKAGES += erlmongo -pkg_erlmongo_name = erlmongo -pkg_erlmongo_description = Record based Erlang driver for MongoDB with gridfs support -pkg_erlmongo_homepage = https://github.com/SergejJurecko/erlmongo -pkg_erlmongo_fetch = git -pkg_erlmongo_repo = https://github.com/SergejJurecko/erlmongo -pkg_erlmongo_commit = master - -PACKAGES += erlog -pkg_erlog_name = erlog -pkg_erlog_description = Prolog interpreter in and for Erlang -pkg_erlog_homepage = https://github.com/rvirding/erlog -pkg_erlog_fetch = git -pkg_erlog_repo = https://github.com/rvirding/erlog -pkg_erlog_commit = master - -PACKAGES += erlpass -pkg_erlpass_name = erlpass -pkg_erlpass_description = A library to handle password hashing and changing in a safe manner, independent from any kind of storage whatsoever. -pkg_erlpass_homepage = https://github.com/ferd/erlpass -pkg_erlpass_fetch = git -pkg_erlpass_repo = https://github.com/ferd/erlpass -pkg_erlpass_commit = master - -PACKAGES += erlport -pkg_erlport_name = erlport -pkg_erlport_description = ErlPort - connect Erlang to other languages -pkg_erlport_homepage = https://github.com/hdima/erlport -pkg_erlport_fetch = git -pkg_erlport_repo = https://github.com/hdima/erlport -pkg_erlport_commit = master - -PACKAGES += erlsha2 -pkg_erlsha2_name = erlsha2 -pkg_erlsha2_description = SHA-224, SHA-256, SHA-384, SHA-512 implemented in Erlang NIFs. -pkg_erlsha2_homepage = https://github.com/vinoski/erlsha2 -pkg_erlsha2_fetch = git -pkg_erlsha2_repo = https://github.com/vinoski/erlsha2 -pkg_erlsha2_commit = master - -PACKAGES += erlsh -pkg_erlsh_name = erlsh -pkg_erlsh_description = Erlang shell tools -pkg_erlsh_homepage = https://github.com/proger/erlsh -pkg_erlsh_fetch = git -pkg_erlsh_repo = https://github.com/proger/erlsh -pkg_erlsh_commit = master - -PACKAGES += erlsom -pkg_erlsom_name = erlsom -pkg_erlsom_description = XML parser for Erlang -pkg_erlsom_homepage = https://github.com/willemdj/erlsom -pkg_erlsom_fetch = git -pkg_erlsom_repo = https://github.com/willemdj/erlsom -pkg_erlsom_commit = master - -PACKAGES += erl_streams -pkg_erl_streams_name = erl_streams -pkg_erl_streams_description = Streams in Erlang -pkg_erl_streams_homepage = https://github.com/epappas/erl_streams -pkg_erl_streams_fetch = git -pkg_erl_streams_repo = https://github.com/epappas/erl_streams -pkg_erl_streams_commit = master - -PACKAGES += erlubi -pkg_erlubi_name = erlubi -pkg_erlubi_description = Ubigraph Erlang Client (and Process Visualizer) -pkg_erlubi_homepage = https://github.com/krestenkrab/erlubi -pkg_erlubi_fetch = git -pkg_erlubi_repo = https://github.com/krestenkrab/erlubi -pkg_erlubi_commit = master - -PACKAGES += erlvolt -pkg_erlvolt_name = erlvolt -pkg_erlvolt_description = VoltDB Erlang Client Driver -pkg_erlvolt_homepage = https://github.com/VoltDB/voltdb-client-erlang -pkg_erlvolt_fetch = git -pkg_erlvolt_repo = https://github.com/VoltDB/voltdb-client-erlang -pkg_erlvolt_commit = master - -PACKAGES += erlware_commons -pkg_erlware_commons_name = erlware_commons -pkg_erlware_commons_description = Erlware Commons is an Erlware project focused on all aspects of reusable Erlang components. -pkg_erlware_commons_homepage = https://github.com/erlware/erlware_commons -pkg_erlware_commons_fetch = git -pkg_erlware_commons_repo = https://github.com/erlware/erlware_commons -pkg_erlware_commons_commit = master - -PACKAGES += erlydtl -pkg_erlydtl_name = erlydtl -pkg_erlydtl_description = Django Template Language for Erlang. -pkg_erlydtl_homepage = https://github.com/erlydtl/erlydtl -pkg_erlydtl_fetch = git -pkg_erlydtl_repo = https://github.com/erlydtl/erlydtl -pkg_erlydtl_commit = master - -PACKAGES += errd -pkg_errd_name = errd -pkg_errd_description = Erlang RRDTool library -pkg_errd_homepage = https://github.com/archaelus/errd -pkg_errd_fetch = git -pkg_errd_repo = https://github.com/archaelus/errd -pkg_errd_commit = master - -PACKAGES += erserve -pkg_erserve_name = erserve -pkg_erserve_description = Erlang/Rserve communication interface -pkg_erserve_homepage = https://github.com/del/erserve -pkg_erserve_fetch = git -pkg_erserve_repo = https://github.com/del/erserve -pkg_erserve_commit = master - -PACKAGES += erwa -pkg_erwa_name = erwa -pkg_erwa_description = A WAMP router and client written in Erlang. -pkg_erwa_homepage = https://github.com/bwegh/erwa -pkg_erwa_fetch = git -pkg_erwa_repo = https://github.com/bwegh/erwa -pkg_erwa_commit = 0.1.1 - -PACKAGES += espec -pkg_espec_name = espec -pkg_espec_description = ESpec: Behaviour driven development framework for Erlang -pkg_espec_homepage = https://github.com/lucaspiller/espec -pkg_espec_fetch = git -pkg_espec_repo = https://github.com/lucaspiller/espec -pkg_espec_commit = master - -PACKAGES += estatsd -pkg_estatsd_name = estatsd -pkg_estatsd_description = Erlang stats aggregation app that periodically flushes data to graphite -pkg_estatsd_homepage = https://github.com/RJ/estatsd -pkg_estatsd_fetch = git -pkg_estatsd_repo = https://github.com/RJ/estatsd -pkg_estatsd_commit = master - -PACKAGES += etap -pkg_etap_name = etap -pkg_etap_description = etap is a simple erlang testing library that provides TAP compliant output. -pkg_etap_homepage = https://github.com/ngerakines/etap -pkg_etap_fetch = git -pkg_etap_repo = https://github.com/ngerakines/etap -pkg_etap_commit = master - -PACKAGES += etest_http -pkg_etest_http_name = etest_http -pkg_etest_http_description = etest Assertions around HTTP (client-side) -pkg_etest_http_homepage = https://github.com/wooga/etest_http -pkg_etest_http_fetch = git -pkg_etest_http_repo = https://github.com/wooga/etest_http -pkg_etest_http_commit = master - -PACKAGES += etest -pkg_etest_name = etest -pkg_etest_description = A lightweight, convention over configuration test framework for Erlang -pkg_etest_homepage = https://github.com/wooga/etest -pkg_etest_fetch = git -pkg_etest_repo = https://github.com/wooga/etest -pkg_etest_commit = master - -PACKAGES += etoml -pkg_etoml_name = etoml -pkg_etoml_description = TOML language erlang parser -pkg_etoml_homepage = https://github.com/kalta/etoml -pkg_etoml_fetch = git -pkg_etoml_repo = https://github.com/kalta/etoml -pkg_etoml_commit = master - -PACKAGES += eunit_formatters -pkg_eunit_formatters_name = eunit_formatters -pkg_eunit_formatters_description = Because eunit's output sucks. Let's make it better. -pkg_eunit_formatters_homepage = https://github.com/seancribbs/eunit_formatters -pkg_eunit_formatters_fetch = git -pkg_eunit_formatters_repo = https://github.com/seancribbs/eunit_formatters -pkg_eunit_formatters_commit = master - -PACKAGES += eunit -pkg_eunit_name = eunit -pkg_eunit_description = The EUnit lightweight unit testing framework for Erlang - this is the canonical development repository. -pkg_eunit_homepage = https://github.com/richcarl/eunit -pkg_eunit_fetch = git -pkg_eunit_repo = https://github.com/richcarl/eunit -pkg_eunit_commit = master - -PACKAGES += euthanasia -pkg_euthanasia_name = euthanasia -pkg_euthanasia_description = Merciful killer for your Erlang processes -pkg_euthanasia_homepage = https://github.com/doubleyou/euthanasia -pkg_euthanasia_fetch = git -pkg_euthanasia_repo = https://github.com/doubleyou/euthanasia -pkg_euthanasia_commit = master - -PACKAGES += evum -pkg_evum_name = evum -pkg_evum_description = Spawn Linux VMs as Erlang processes in the Erlang VM -pkg_evum_homepage = https://github.com/msantos/evum -pkg_evum_fetch = git -pkg_evum_repo = https://github.com/msantos/evum -pkg_evum_commit = master - -PACKAGES += exec -pkg_exec_name = exec -pkg_exec_description = Execute and control OS processes from Erlang/OTP. -pkg_exec_homepage = http://saleyn.github.com/erlexec -pkg_exec_fetch = git -pkg_exec_repo = https://github.com/saleyn/erlexec -pkg_exec_commit = master - -PACKAGES += exml -pkg_exml_name = exml -pkg_exml_description = XML parsing library in Erlang -pkg_exml_homepage = https://github.com/paulgray/exml -pkg_exml_fetch = git -pkg_exml_repo = https://github.com/paulgray/exml -pkg_exml_commit = master - -PACKAGES += exometer -pkg_exometer_name = exometer -pkg_exometer_description = Basic measurement objects and probe behavior -pkg_exometer_homepage = https://github.com/Feuerlabs/exometer -pkg_exometer_fetch = git -pkg_exometer_repo = https://github.com/Feuerlabs/exometer -pkg_exometer_commit = 1.2 - -PACKAGES += exs1024 -pkg_exs1024_name = exs1024 -pkg_exs1024_description = Xorshift1024star pseudo random number generator for Erlang. -pkg_exs1024_homepage = https://github.com/jj1bdx/exs1024 -pkg_exs1024_fetch = git -pkg_exs1024_repo = https://github.com/jj1bdx/exs1024 -pkg_exs1024_commit = master - -PACKAGES += exs64 -pkg_exs64_name = exs64 -pkg_exs64_description = Xorshift64star pseudo random number generator for Erlang. -pkg_exs64_homepage = https://github.com/jj1bdx/exs64 -pkg_exs64_fetch = git -pkg_exs64_repo = https://github.com/jj1bdx/exs64 -pkg_exs64_commit = master - -PACKAGES += exsplus116 -pkg_exsplus116_name = exsplus116 -pkg_exsplus116_description = Xorshift116plus for Erlang -pkg_exsplus116_homepage = https://github.com/jj1bdx/exsplus116 -pkg_exsplus116_fetch = git -pkg_exsplus116_repo = https://github.com/jj1bdx/exsplus116 -pkg_exsplus116_commit = master - -PACKAGES += exsplus128 -pkg_exsplus128_name = exsplus128 -pkg_exsplus128_description = Xorshift128plus pseudo random number generator for Erlang. -pkg_exsplus128_homepage = https://github.com/jj1bdx/exsplus128 -pkg_exsplus128_fetch = git -pkg_exsplus128_repo = https://github.com/jj1bdx/exsplus128 -pkg_exsplus128_commit = master - -PACKAGES += ezmq -pkg_ezmq_name = ezmq -pkg_ezmq_description = zMQ implemented in Erlang -pkg_ezmq_homepage = https://github.com/RoadRunnr/ezmq -pkg_ezmq_fetch = git -pkg_ezmq_repo = https://github.com/RoadRunnr/ezmq -pkg_ezmq_commit = master - -PACKAGES += ezmtp -pkg_ezmtp_name = ezmtp -pkg_ezmtp_description = ZMTP protocol in pure Erlang. -pkg_ezmtp_homepage = https://github.com/a13x/ezmtp -pkg_ezmtp_fetch = git -pkg_ezmtp_repo = https://github.com/a13x/ezmtp -pkg_ezmtp_commit = master - -PACKAGES += fast_disk_log -pkg_fast_disk_log_name = fast_disk_log -pkg_fast_disk_log_description = Pool-based asynchronous Erlang disk logger -pkg_fast_disk_log_homepage = https://github.com/lpgauth/fast_disk_log -pkg_fast_disk_log_fetch = git -pkg_fast_disk_log_repo = https://github.com/lpgauth/fast_disk_log -pkg_fast_disk_log_commit = master - -PACKAGES += feeder -pkg_feeder_name = feeder -pkg_feeder_description = Stream parse RSS and Atom formatted XML feeds. -pkg_feeder_homepage = https://github.com/michaelnisi/feeder -pkg_feeder_fetch = git -pkg_feeder_repo = https://github.com/michaelnisi/feeder -pkg_feeder_commit = v1.4.6 - -PACKAGES += fix -pkg_fix_name = fix -pkg_fix_description = http://fixprotocol.org/ implementation. -pkg_fix_homepage = https://github.com/maxlapshin/fix -pkg_fix_fetch = git -pkg_fix_repo = https://github.com/maxlapshin/fix -pkg_fix_commit = master - -PACKAGES += flower -pkg_flower_name = flower -pkg_flower_description = FlowER - a Erlang OpenFlow development platform -pkg_flower_homepage = https://github.com/travelping/flower -pkg_flower_fetch = git -pkg_flower_repo = https://github.com/travelping/flower -pkg_flower_commit = master - -PACKAGES += fn -pkg_fn_name = fn -pkg_fn_description = Function utilities for Erlang -pkg_fn_homepage = https://github.com/reiddraper/fn -pkg_fn_fetch = git -pkg_fn_repo = https://github.com/reiddraper/fn -pkg_fn_commit = master - -PACKAGES += folsom_cowboy -pkg_folsom_cowboy_name = folsom_cowboy -pkg_folsom_cowboy_description = A Cowboy based Folsom HTTP Wrapper. -pkg_folsom_cowboy_homepage = https://github.com/boundary/folsom_cowboy -pkg_folsom_cowboy_fetch = git -pkg_folsom_cowboy_repo = https://github.com/boundary/folsom_cowboy -pkg_folsom_cowboy_commit = master - -PACKAGES += folsomite -pkg_folsomite_name = folsomite -pkg_folsomite_description = blow up your graphite / riemann server with folsom metrics -pkg_folsomite_homepage = https://github.com/campanja/folsomite -pkg_folsomite_fetch = git -pkg_folsomite_repo = https://github.com/campanja/folsomite -pkg_folsomite_commit = master - -PACKAGES += folsom -pkg_folsom_name = folsom -pkg_folsom_description = Expose Erlang Events and Metrics -pkg_folsom_homepage = https://github.com/boundary/folsom -pkg_folsom_fetch = git -pkg_folsom_repo = https://github.com/boundary/folsom -pkg_folsom_commit = master - -PACKAGES += fs -pkg_fs_name = fs -pkg_fs_description = Erlang FileSystem Listener -pkg_fs_homepage = https://github.com/synrc/fs -pkg_fs_fetch = git -pkg_fs_repo = https://github.com/synrc/fs -pkg_fs_commit = master - -PACKAGES += fuse -pkg_fuse_name = fuse -pkg_fuse_description = A Circuit Breaker for Erlang -pkg_fuse_homepage = https://github.com/jlouis/fuse -pkg_fuse_fetch = git -pkg_fuse_repo = https://github.com/jlouis/fuse -pkg_fuse_commit = master - -PACKAGES += gcm -pkg_gcm_name = gcm -pkg_gcm_description = An Erlang application for Google Cloud Messaging -pkg_gcm_homepage = https://github.com/pdincau/gcm-erlang -pkg_gcm_fetch = git -pkg_gcm_repo = https://github.com/pdincau/gcm-erlang -pkg_gcm_commit = master - -PACKAGES += gcprof -pkg_gcprof_name = gcprof -pkg_gcprof_description = Garbage Collection profiler for Erlang -pkg_gcprof_homepage = https://github.com/knutin/gcprof -pkg_gcprof_fetch = git -pkg_gcprof_repo = https://github.com/knutin/gcprof -pkg_gcprof_commit = master - -PACKAGES += geas -pkg_geas_name = geas -pkg_geas_description = Guess Erlang Application Scattering -pkg_geas_homepage = https://github.com/crownedgrouse/geas -pkg_geas_fetch = git -pkg_geas_repo = https://github.com/crownedgrouse/geas -pkg_geas_commit = master - -PACKAGES += geef -pkg_geef_name = geef -pkg_geef_description = Git NEEEEF (Erlang NIF) -pkg_geef_homepage = https://github.com/carlosmn/geef -pkg_geef_fetch = git -pkg_geef_repo = https://github.com/carlosmn/geef -pkg_geef_commit = master - -PACKAGES += gen_cycle -pkg_gen_cycle_name = gen_cycle -pkg_gen_cycle_description = Simple, generic OTP behaviour for recurring tasks -pkg_gen_cycle_homepage = https://github.com/aerosol/gen_cycle -pkg_gen_cycle_fetch = git -pkg_gen_cycle_repo = https://github.com/aerosol/gen_cycle -pkg_gen_cycle_commit = develop - -PACKAGES += gen_icmp -pkg_gen_icmp_name = gen_icmp -pkg_gen_icmp_description = Erlang interface to ICMP sockets -pkg_gen_icmp_homepage = https://github.com/msantos/gen_icmp -pkg_gen_icmp_fetch = git -pkg_gen_icmp_repo = https://github.com/msantos/gen_icmp -pkg_gen_icmp_commit = master - -PACKAGES += gen_nb_server -pkg_gen_nb_server_name = gen_nb_server -pkg_gen_nb_server_description = OTP behavior for writing non-blocking servers -pkg_gen_nb_server_homepage = https://github.com/kevsmith/gen_nb_server -pkg_gen_nb_server_fetch = git -pkg_gen_nb_server_repo = https://github.com/kevsmith/gen_nb_server -pkg_gen_nb_server_commit = master - -PACKAGES += gen_paxos -pkg_gen_paxos_name = gen_paxos -pkg_gen_paxos_description = An Erlang/OTP-style implementation of the PAXOS distributed consensus protocol -pkg_gen_paxos_homepage = https://github.com/gburd/gen_paxos -pkg_gen_paxos_fetch = git -pkg_gen_paxos_repo = https://github.com/gburd/gen_paxos -pkg_gen_paxos_commit = master - -PACKAGES += gen_smtp -pkg_gen_smtp_name = gen_smtp -pkg_gen_smtp_description = A generic Erlang SMTP server and client that can be extended via callback modules -pkg_gen_smtp_homepage = https://github.com/Vagabond/gen_smtp -pkg_gen_smtp_fetch = git -pkg_gen_smtp_repo = https://github.com/Vagabond/gen_smtp -pkg_gen_smtp_commit = master - -PACKAGES += gen_tracker -pkg_gen_tracker_name = gen_tracker -pkg_gen_tracker_description = supervisor with ets handling of children and their metadata -pkg_gen_tracker_homepage = https://github.com/erlyvideo/gen_tracker -pkg_gen_tracker_fetch = git -pkg_gen_tracker_repo = https://github.com/erlyvideo/gen_tracker -pkg_gen_tracker_commit = master - -PACKAGES += gen_unix -pkg_gen_unix_name = gen_unix -pkg_gen_unix_description = Erlang Unix socket interface -pkg_gen_unix_homepage = https://github.com/msantos/gen_unix -pkg_gen_unix_fetch = git -pkg_gen_unix_repo = https://github.com/msantos/gen_unix -pkg_gen_unix_commit = master - -PACKAGES += getopt -pkg_getopt_name = getopt -pkg_getopt_description = Module to parse command line arguments using the GNU getopt syntax -pkg_getopt_homepage = https://github.com/jcomellas/getopt -pkg_getopt_fetch = git -pkg_getopt_repo = https://github.com/jcomellas/getopt -pkg_getopt_commit = master - -PACKAGES += gettext -pkg_gettext_name = gettext -pkg_gettext_description = Erlang internationalization library. -pkg_gettext_homepage = https://github.com/etnt/gettext -pkg_gettext_fetch = git -pkg_gettext_repo = https://github.com/etnt/gettext -pkg_gettext_commit = master - -PACKAGES += giallo -pkg_giallo_name = giallo -pkg_giallo_description = Small and flexible web framework on top of Cowboy -pkg_giallo_homepage = https://github.com/kivra/giallo -pkg_giallo_fetch = git -pkg_giallo_repo = https://github.com/kivra/giallo -pkg_giallo_commit = master - -PACKAGES += gin -pkg_gin_name = gin -pkg_gin_description = The guards and for Erlang parse_transform -pkg_gin_homepage = https://github.com/mad-cocktail/gin -pkg_gin_fetch = git -pkg_gin_repo = https://github.com/mad-cocktail/gin -pkg_gin_commit = master - -PACKAGES += gitty -pkg_gitty_name = gitty -pkg_gitty_description = Git access in erlang -pkg_gitty_homepage = https://github.com/maxlapshin/gitty -pkg_gitty_fetch = git -pkg_gitty_repo = https://github.com/maxlapshin/gitty -pkg_gitty_commit = master - -PACKAGES += gold_fever -pkg_gold_fever_name = gold_fever -pkg_gold_fever_description = A Treasure Hunt for Erlangers -pkg_gold_fever_homepage = https://github.com/inaka/gold_fever -pkg_gold_fever_fetch = git -pkg_gold_fever_repo = https://github.com/inaka/gold_fever -pkg_gold_fever_commit = master - -PACKAGES += gossiperl -pkg_gossiperl_name = gossiperl -pkg_gossiperl_description = Gossip middleware in Erlang -pkg_gossiperl_homepage = http://gossiperl.com/ -pkg_gossiperl_fetch = git -pkg_gossiperl_repo = https://github.com/gossiperl/gossiperl -pkg_gossiperl_commit = master - -PACKAGES += gpb -pkg_gpb_name = gpb -pkg_gpb_description = A Google Protobuf implementation for Erlang -pkg_gpb_homepage = https://github.com/tomas-abrahamsson/gpb -pkg_gpb_fetch = git -pkg_gpb_repo = https://github.com/tomas-abrahamsson/gpb -pkg_gpb_commit = master - -PACKAGES += gproc -pkg_gproc_name = gproc -pkg_gproc_description = Extended process registry for Erlang -pkg_gproc_homepage = https://github.com/uwiger/gproc -pkg_gproc_fetch = git -pkg_gproc_repo = https://github.com/uwiger/gproc -pkg_gproc_commit = master - -PACKAGES += grapherl -pkg_grapherl_name = grapherl -pkg_grapherl_description = Create graphs of Erlang systems and programs -pkg_grapherl_homepage = https://github.com/eproxus/grapherl -pkg_grapherl_fetch = git -pkg_grapherl_repo = https://github.com/eproxus/grapherl -pkg_grapherl_commit = master - -PACKAGES += gun -pkg_gun_name = gun -pkg_gun_description = Asynchronous SPDY, HTTP and Websocket client written in Erlang. -pkg_gun_homepage = http//ninenines.eu -pkg_gun_fetch = git -pkg_gun_repo = https://github.com/ninenines/gun -pkg_gun_commit = master - -PACKAGES += gut -pkg_gut_name = gut -pkg_gut_description = gut is a template printing, aka scaffolding, tool for Erlang. Like rails generate or yeoman -pkg_gut_homepage = https://github.com/unbalancedparentheses/gut -pkg_gut_fetch = git -pkg_gut_repo = https://github.com/unbalancedparentheses/gut -pkg_gut_commit = master - -PACKAGES += hackney -pkg_hackney_name = hackney -pkg_hackney_description = simple HTTP client in Erlang -pkg_hackney_homepage = https://github.com/benoitc/hackney -pkg_hackney_fetch = git -pkg_hackney_repo = https://github.com/benoitc/hackney -pkg_hackney_commit = master - -PACKAGES += hamcrest -pkg_hamcrest_name = hamcrest -pkg_hamcrest_description = Erlang port of Hamcrest -pkg_hamcrest_homepage = https://github.com/hyperthunk/hamcrest-erlang -pkg_hamcrest_fetch = git -pkg_hamcrest_repo = https://github.com/hyperthunk/hamcrest-erlang -pkg_hamcrest_commit = master - -PACKAGES += hanoidb -pkg_hanoidb_name = hanoidb -pkg_hanoidb_description = Erlang LSM BTree Storage -pkg_hanoidb_homepage = https://github.com/krestenkrab/hanoidb -pkg_hanoidb_fetch = git -pkg_hanoidb_repo = https://github.com/krestenkrab/hanoidb -pkg_hanoidb_commit = master - -PACKAGES += hottub -pkg_hottub_name = hottub -pkg_hottub_description = Permanent Erlang Worker Pool -pkg_hottub_homepage = https://github.com/bfrog/hottub -pkg_hottub_fetch = git -pkg_hottub_repo = https://github.com/bfrog/hottub -pkg_hottub_commit = master - -PACKAGES += hpack -pkg_hpack_name = hpack -pkg_hpack_description = HPACK Implementation for Erlang -pkg_hpack_homepage = https://github.com/joedevivo/hpack -pkg_hpack_fetch = git -pkg_hpack_repo = https://github.com/joedevivo/hpack -pkg_hpack_commit = master - -PACKAGES += hyper -pkg_hyper_name = hyper -pkg_hyper_description = Erlang implementation of HyperLogLog -pkg_hyper_homepage = https://github.com/GameAnalytics/hyper -pkg_hyper_fetch = git -pkg_hyper_repo = https://github.com/GameAnalytics/hyper -pkg_hyper_commit = master - -PACKAGES += ibrowse -pkg_ibrowse_name = ibrowse -pkg_ibrowse_description = Erlang HTTP client -pkg_ibrowse_homepage = https://github.com/cmullaparthi/ibrowse -pkg_ibrowse_fetch = git -pkg_ibrowse_repo = https://github.com/cmullaparthi/ibrowse -pkg_ibrowse_commit = v4.1.1 - -PACKAGES += ierlang -pkg_ierlang_name = ierlang -pkg_ierlang_description = An Erlang language kernel for IPython. -pkg_ierlang_homepage = https://github.com/robbielynch/ierlang -pkg_ierlang_fetch = git -pkg_ierlang_repo = https://github.com/robbielynch/ierlang -pkg_ierlang_commit = master - -PACKAGES += iota -pkg_iota_name = iota -pkg_iota_description = iota (Inter-dependency Objective Testing Apparatus) - a tool to enforce clean separation of responsibilities in Erlang code -pkg_iota_homepage = https://github.com/jpgneves/iota -pkg_iota_fetch = git -pkg_iota_repo = https://github.com/jpgneves/iota -pkg_iota_commit = master - -PACKAGES += ircd -pkg_ircd_name = ircd -pkg_ircd_description = A pluggable IRC daemon application/library for Erlang. -pkg_ircd_homepage = https://github.com/tonyg/erlang-ircd -pkg_ircd_fetch = git -pkg_ircd_repo = https://github.com/tonyg/erlang-ircd -pkg_ircd_commit = master - -PACKAGES += irc_lib -pkg_irc_lib_name = irc_lib -pkg_irc_lib_description = Erlang irc client library -pkg_irc_lib_homepage = https://github.com/OtpChatBot/irc_lib -pkg_irc_lib_fetch = git -pkg_irc_lib_repo = https://github.com/OtpChatBot/irc_lib -pkg_irc_lib_commit = master - -PACKAGES += iris -pkg_iris_name = iris -pkg_iris_description = Iris Erlang binding -pkg_iris_homepage = https://github.com/project-iris/iris-erl -pkg_iris_fetch = git -pkg_iris_repo = https://github.com/project-iris/iris-erl -pkg_iris_commit = master - -PACKAGES += iso8601 -pkg_iso8601_name = iso8601 -pkg_iso8601_description = Erlang ISO 8601 date formatter/parser -pkg_iso8601_homepage = https://github.com/seansawyer/erlang_iso8601 -pkg_iso8601_fetch = git -pkg_iso8601_repo = https://github.com/seansawyer/erlang_iso8601 -pkg_iso8601_commit = master - -PACKAGES += itweet -pkg_itweet_name = itweet -pkg_itweet_description = Twitter Stream API on ibrowse -pkg_itweet_homepage = http://inaka.github.com/itweet/ -pkg_itweet_fetch = git -pkg_itweet_repo = https://github.com/inaka/itweet -pkg_itweet_commit = v2.0 - -PACKAGES += jerg -pkg_jerg_name = jerg -pkg_jerg_description = JSON Schema to Erlang Records Generator -pkg_jerg_homepage = https://github.com/ddossot/jerg -pkg_jerg_fetch = git -pkg_jerg_repo = https://github.com/ddossot/jerg -pkg_jerg_commit = master - -PACKAGES += jesse -pkg_jesse_name = jesse -pkg_jesse_description = jesse (JSon Schema Erlang) is an implementation of a json schema validator for Erlang. -pkg_jesse_homepage = https://github.com/klarna/jesse -pkg_jesse_fetch = git -pkg_jesse_repo = https://github.com/klarna/jesse -pkg_jesse_commit = master - -PACKAGES += jiffy -pkg_jiffy_name = jiffy -pkg_jiffy_description = JSON NIFs for Erlang. -pkg_jiffy_homepage = https://github.com/davisp/jiffy -pkg_jiffy_fetch = git -pkg_jiffy_repo = https://github.com/davisp/jiffy -pkg_jiffy_commit = master - -PACKAGES += jiffy_v -pkg_jiffy_v_name = jiffy_v -pkg_jiffy_v_description = JSON validation utility -pkg_jiffy_v_homepage = https://github.com/shizzard/jiffy-v -pkg_jiffy_v_fetch = git -pkg_jiffy_v_repo = https://github.com/shizzard/jiffy-v -pkg_jiffy_v_commit = 0.3.3 - -PACKAGES += jobs -pkg_jobs_name = jobs -pkg_jobs_description = a Job scheduler for load regulation -pkg_jobs_homepage = https://github.com/esl/jobs -pkg_jobs_fetch = git -pkg_jobs_repo = https://github.com/esl/jobs -pkg_jobs_commit = 0.3 - -PACKAGES += joxa -pkg_joxa_name = joxa -pkg_joxa_description = A Modern Lisp for the Erlang VM -pkg_joxa_homepage = https://github.com/joxa/joxa -pkg_joxa_fetch = git -pkg_joxa_repo = https://github.com/joxa/joxa -pkg_joxa_commit = master - -PACKAGES += jsonerl -pkg_jsonerl_name = jsonerl -pkg_jsonerl_description = yet another but slightly different erlang <-> json encoder/decoder -pkg_jsonerl_homepage = https://github.com/lambder/jsonerl -pkg_jsonerl_fetch = git -pkg_jsonerl_repo = https://github.com/lambder/jsonerl -pkg_jsonerl_commit = master - -PACKAGES += json -pkg_json_name = json -pkg_json_description = a high level json library for erlang (17.0+) -pkg_json_homepage = https://github.com/talentdeficit/json -pkg_json_fetch = git -pkg_json_repo = https://github.com/talentdeficit/json -pkg_json_commit = master - -PACKAGES += jsonpath -pkg_jsonpath_name = jsonpath -pkg_jsonpath_description = Fast Erlang JSON data retrieval and updates via javascript-like notation -pkg_jsonpath_homepage = https://github.com/GeneStevens/jsonpath -pkg_jsonpath_fetch = git -pkg_jsonpath_repo = https://github.com/GeneStevens/jsonpath -pkg_jsonpath_commit = master - -PACKAGES += json_rec -pkg_json_rec_name = json_rec -pkg_json_rec_description = JSON to erlang record -pkg_json_rec_homepage = https://github.com/justinkirby/json_rec -pkg_json_rec_fetch = git -pkg_json_rec_repo = https://github.com/justinkirby/json_rec -pkg_json_rec_commit = master - -PACKAGES += jsonx -pkg_jsonx_name = jsonx -pkg_jsonx_description = JSONX is an Erlang library for efficient decode and encode JSON, written in C. -pkg_jsonx_homepage = https://github.com/iskra/jsonx -pkg_jsonx_fetch = git -pkg_jsonx_repo = https://github.com/iskra/jsonx -pkg_jsonx_commit = master - -PACKAGES += jsx -pkg_jsx_name = jsx -pkg_jsx_description = An Erlang application for consuming, producing and manipulating JSON. -pkg_jsx_homepage = https://github.com/talentdeficit/jsx -pkg_jsx_fetch = git -pkg_jsx_repo = https://github.com/talentdeficit/jsx -pkg_jsx_commit = master - -PACKAGES += kafka -pkg_kafka_name = kafka -pkg_kafka_description = Kafka consumer and producer in Erlang -pkg_kafka_homepage = https://github.com/wooga/kafka-erlang -pkg_kafka_fetch = git -pkg_kafka_repo = https://github.com/wooga/kafka-erlang -pkg_kafka_commit = master - -PACKAGES += kai -pkg_kai_name = kai -pkg_kai_description = DHT storage by Takeshi Inoue -pkg_kai_homepage = https://github.com/synrc/kai -pkg_kai_fetch = git -pkg_kai_repo = https://github.com/synrc/kai -pkg_kai_commit = master - -PACKAGES += katja -pkg_katja_name = katja -pkg_katja_description = A simple Riemann client written in Erlang. -pkg_katja_homepage = https://github.com/nifoc/katja -pkg_katja_fetch = git -pkg_katja_repo = https://github.com/nifoc/katja -pkg_katja_commit = master - -PACKAGES += kdht -pkg_kdht_name = kdht -pkg_kdht_description = kdht is an erlang DHT implementation -pkg_kdht_homepage = https://github.com/kevinlynx/kdht -pkg_kdht_fetch = git -pkg_kdht_repo = https://github.com/kevinlynx/kdht -pkg_kdht_commit = master - -PACKAGES += key2value -pkg_key2value_name = key2value -pkg_key2value_description = Erlang 2-way map -pkg_key2value_homepage = https://github.com/okeuday/key2value -pkg_key2value_fetch = git -pkg_key2value_repo = https://github.com/okeuday/key2value -pkg_key2value_commit = master - -PACKAGES += keys1value -pkg_keys1value_name = keys1value -pkg_keys1value_description = Erlang set associative map for key lists -pkg_keys1value_homepage = https://github.com/okeuday/keys1value -pkg_keys1value_fetch = git -pkg_keys1value_repo = https://github.com/okeuday/keys1value -pkg_keys1value_commit = master - -PACKAGES += kinetic -pkg_kinetic_name = kinetic -pkg_kinetic_description = Erlang Kinesis Client -pkg_kinetic_homepage = https://github.com/AdRoll/kinetic -pkg_kinetic_fetch = git -pkg_kinetic_repo = https://github.com/AdRoll/kinetic -pkg_kinetic_commit = master - -PACKAGES += kjell -pkg_kjell_name = kjell -pkg_kjell_description = Erlang Shell -pkg_kjell_homepage = https://github.com/karlll/kjell -pkg_kjell_fetch = git -pkg_kjell_repo = https://github.com/karlll/kjell -pkg_kjell_commit = master - -PACKAGES += kraken -pkg_kraken_name = kraken -pkg_kraken_description = Distributed Pubsub Server for Realtime Apps -pkg_kraken_homepage = https://github.com/Asana/kraken -pkg_kraken_fetch = git -pkg_kraken_repo = https://github.com/Asana/kraken -pkg_kraken_commit = master - -PACKAGES += kucumberl -pkg_kucumberl_name = kucumberl -pkg_kucumberl_description = A pure-erlang, open-source, implementation of Cucumber -pkg_kucumberl_homepage = https://github.com/openshine/kucumberl -pkg_kucumberl_fetch = git -pkg_kucumberl_repo = https://github.com/openshine/kucumberl -pkg_kucumberl_commit = master - -PACKAGES += kvc -pkg_kvc_name = kvc -pkg_kvc_description = KVC - Key Value Coding for Erlang data structures -pkg_kvc_homepage = https://github.com/etrepum/kvc -pkg_kvc_fetch = git -pkg_kvc_repo = https://github.com/etrepum/kvc -pkg_kvc_commit = master - -PACKAGES += kvlists -pkg_kvlists_name = kvlists -pkg_kvlists_description = Lists of key-value pairs (decoded JSON) in Erlang -pkg_kvlists_homepage = https://github.com/jcomellas/kvlists -pkg_kvlists_fetch = git -pkg_kvlists_repo = https://github.com/jcomellas/kvlists -pkg_kvlists_commit = master - -PACKAGES += kvs -pkg_kvs_name = kvs -pkg_kvs_description = Container and Iterator -pkg_kvs_homepage = https://github.com/synrc/kvs -pkg_kvs_fetch = git -pkg_kvs_repo = https://github.com/synrc/kvs -pkg_kvs_commit = master - -PACKAGES += lager_amqp_backend -pkg_lager_amqp_backend_name = lager_amqp_backend -pkg_lager_amqp_backend_description = AMQP RabbitMQ Lager backend -pkg_lager_amqp_backend_homepage = https://github.com/jbrisbin/lager_amqp_backend -pkg_lager_amqp_backend_fetch = git -pkg_lager_amqp_backend_repo = https://github.com/jbrisbin/lager_amqp_backend -pkg_lager_amqp_backend_commit = master - -PACKAGES += lager -pkg_lager_name = lager -pkg_lager_description = A logging framework for Erlang/OTP. -pkg_lager_homepage = https://github.com/basho/lager -pkg_lager_fetch = git -pkg_lager_repo = https://github.com/basho/lager -pkg_lager_commit = master - -PACKAGES += lager_syslog -pkg_lager_syslog_name = lager_syslog -pkg_lager_syslog_description = Syslog backend for lager -pkg_lager_syslog_homepage = https://github.com/basho/lager_syslog -pkg_lager_syslog_fetch = git -pkg_lager_syslog_repo = https://github.com/basho/lager_syslog -pkg_lager_syslog_commit = master - -PACKAGES += lambdapad -pkg_lambdapad_name = lambdapad -pkg_lambdapad_description = Static site generator using Erlang. Yes, Erlang. -pkg_lambdapad_homepage = https://github.com/gar1t/lambdapad -pkg_lambdapad_fetch = git -pkg_lambdapad_repo = https://github.com/gar1t/lambdapad -pkg_lambdapad_commit = master - -PACKAGES += lasp -pkg_lasp_name = lasp -pkg_lasp_description = A Language for Distributed, Eventually Consistent Computations -pkg_lasp_homepage = http://lasp-lang.org/ -pkg_lasp_fetch = git -pkg_lasp_repo = https://github.com/lasp-lang/lasp -pkg_lasp_commit = master - -PACKAGES += lasse -pkg_lasse_name = lasse -pkg_lasse_description = SSE handler for Cowboy -pkg_lasse_homepage = https://github.com/inaka/lasse -pkg_lasse_fetch = git -pkg_lasse_repo = https://github.com/inaka/lasse -pkg_lasse_commit = 0.1.0 - -PACKAGES += ldap -pkg_ldap_name = ldap -pkg_ldap_description = LDAP server written in Erlang -pkg_ldap_homepage = https://github.com/spawnproc/ldap -pkg_ldap_fetch = git -pkg_ldap_repo = https://github.com/spawnproc/ldap -pkg_ldap_commit = master - -PACKAGES += lethink -pkg_lethink_name = lethink -pkg_lethink_description = erlang driver for rethinkdb -pkg_lethink_homepage = https://github.com/taybin/lethink -pkg_lethink_fetch = git -pkg_lethink_repo = https://github.com/taybin/lethink -pkg_lethink_commit = master - -PACKAGES += lfe -pkg_lfe_name = lfe -pkg_lfe_description = Lisp Flavoured Erlang (LFE) -pkg_lfe_homepage = https://github.com/rvirding/lfe -pkg_lfe_fetch = git -pkg_lfe_repo = https://github.com/rvirding/lfe -pkg_lfe_commit = master - -PACKAGES += ling -pkg_ling_name = ling -pkg_ling_description = Erlang on Xen -pkg_ling_homepage = https://github.com/cloudozer/ling -pkg_ling_fetch = git -pkg_ling_repo = https://github.com/cloudozer/ling -pkg_ling_commit = master - -PACKAGES += live -pkg_live_name = live -pkg_live_description = Automated module and configuration reloader. -pkg_live_homepage = http://ninenines.eu -pkg_live_fetch = git -pkg_live_repo = https://github.com/ninenines/live -pkg_live_commit = master - -PACKAGES += lmq -pkg_lmq_name = lmq -pkg_lmq_description = Lightweight Message Queue -pkg_lmq_homepage = https://github.com/iij/lmq -pkg_lmq_fetch = git -pkg_lmq_repo = https://github.com/iij/lmq -pkg_lmq_commit = master - -PACKAGES += locker -pkg_locker_name = locker -pkg_locker_description = Atomic distributed 'check and set' for short-lived keys -pkg_locker_homepage = https://github.com/wooga/locker -pkg_locker_fetch = git -pkg_locker_repo = https://github.com/wooga/locker -pkg_locker_commit = master - -PACKAGES += locks -pkg_locks_name = locks -pkg_locks_description = A scalable, deadlock-resolving resource locker -pkg_locks_homepage = https://github.com/uwiger/locks -pkg_locks_fetch = git -pkg_locks_repo = https://github.com/uwiger/locks -pkg_locks_commit = master - -PACKAGES += log4erl -pkg_log4erl_name = log4erl -pkg_log4erl_description = A logger for erlang in the spirit of Log4J. -pkg_log4erl_homepage = https://github.com/ahmednawras/log4erl -pkg_log4erl_fetch = git -pkg_log4erl_repo = https://github.com/ahmednawras/log4erl -pkg_log4erl_commit = master - -PACKAGES += lol -pkg_lol_name = lol -pkg_lol_description = Lisp on erLang, and programming is fun again -pkg_lol_homepage = https://github.com/b0oh/lol -pkg_lol_fetch = git -pkg_lol_repo = https://github.com/b0oh/lol -pkg_lol_commit = master - -PACKAGES += lucid -pkg_lucid_name = lucid -pkg_lucid_description = HTTP/2 server written in Erlang -pkg_lucid_homepage = https://github.com/tatsuhiro-t/lucid -pkg_lucid_fetch = git -pkg_lucid_repo = https://github.com/tatsuhiro-t/lucid -pkg_lucid_commit = master - -PACKAGES += luerl -pkg_luerl_name = luerl -pkg_luerl_description = Lua in Erlang -pkg_luerl_homepage = https://github.com/rvirding/luerl -pkg_luerl_fetch = git -pkg_luerl_repo = https://github.com/rvirding/luerl -pkg_luerl_commit = develop - -PACKAGES += luwak -pkg_luwak_name = luwak -pkg_luwak_description = Large-object storage interface for Riak -pkg_luwak_homepage = https://github.com/basho/luwak -pkg_luwak_fetch = git -pkg_luwak_repo = https://github.com/basho/luwak -pkg_luwak_commit = master - -PACKAGES += lux -pkg_lux_name = lux -pkg_lux_description = Lux (LUcid eXpect scripting) simplifies test automation and provides an Expect-style execution of commands -pkg_lux_homepage = https://github.com/hawk/lux -pkg_lux_fetch = git -pkg_lux_repo = https://github.com/hawk/lux -pkg_lux_commit = master - -PACKAGES += machi -pkg_machi_name = machi -pkg_machi_description = Machi file store -pkg_machi_homepage = https://github.com/basho/machi -pkg_machi_fetch = git -pkg_machi_repo = https://github.com/basho/machi -pkg_machi_commit = master - -PACKAGES += mad -pkg_mad_name = mad -pkg_mad_description = Small and Fast Rebar Replacement -pkg_mad_homepage = https://github.com/synrc/mad -pkg_mad_fetch = git -pkg_mad_repo = https://github.com/synrc/mad -pkg_mad_commit = master - -PACKAGES += marina -pkg_marina_name = marina -pkg_marina_description = Non-blocking Erlang Cassandra CQL3 client -pkg_marina_homepage = https://github.com/lpgauth/marina -pkg_marina_fetch = git -pkg_marina_repo = https://github.com/lpgauth/marina -pkg_marina_commit = master - -PACKAGES += mavg -pkg_mavg_name = mavg -pkg_mavg_description = Erlang :: Exponential moving average library -pkg_mavg_homepage = https://github.com/EchoTeam/mavg -pkg_mavg_fetch = git -pkg_mavg_repo = https://github.com/EchoTeam/mavg -pkg_mavg_commit = master - -PACKAGES += mcd -pkg_mcd_name = mcd -pkg_mcd_description = Fast memcached protocol client in pure Erlang -pkg_mcd_homepage = https://github.com/EchoTeam/mcd -pkg_mcd_fetch = git -pkg_mcd_repo = https://github.com/EchoTeam/mcd -pkg_mcd_commit = master - -PACKAGES += mcerlang -pkg_mcerlang_name = mcerlang -pkg_mcerlang_description = The McErlang model checker for Erlang -pkg_mcerlang_homepage = https://github.com/fredlund/McErlang -pkg_mcerlang_fetch = git -pkg_mcerlang_repo = https://github.com/fredlund/McErlang -pkg_mcerlang_commit = master - -PACKAGES += mc_erl -pkg_mc_erl_name = mc_erl -pkg_mc_erl_description = mc-erl is a server for Minecraft 1.4.7 written in Erlang. -pkg_mc_erl_homepage = https://github.com/clonejo/mc-erl -pkg_mc_erl_fetch = git -pkg_mc_erl_repo = https://github.com/clonejo/mc-erl -pkg_mc_erl_commit = master - -PACKAGES += meck -pkg_meck_name = meck -pkg_meck_description = A mocking library for Erlang -pkg_meck_homepage = https://github.com/eproxus/meck -pkg_meck_fetch = git -pkg_meck_repo = https://github.com/eproxus/meck -pkg_meck_commit = master - -PACKAGES += mekao -pkg_mekao_name = mekao -pkg_mekao_description = SQL constructor -pkg_mekao_homepage = https://github.com/ddosia/mekao -pkg_mekao_fetch = git -pkg_mekao_repo = https://github.com/ddosia/mekao -pkg_mekao_commit = master - -PACKAGES += memo -pkg_memo_name = memo -pkg_memo_description = Erlang memoization server -pkg_memo_homepage = https://github.com/tuncer/memo -pkg_memo_fetch = git -pkg_memo_repo = https://github.com/tuncer/memo -pkg_memo_commit = master - -PACKAGES += merge_index -pkg_merge_index_name = merge_index -pkg_merge_index_description = MergeIndex is an Erlang library for storing ordered sets on disk. It is very similar to an SSTable (in Google's Bigtable) or an HFile (in Hadoop). -pkg_merge_index_homepage = https://github.com/basho/merge_index -pkg_merge_index_fetch = git -pkg_merge_index_repo = https://github.com/basho/merge_index -pkg_merge_index_commit = master - -PACKAGES += merl -pkg_merl_name = merl -pkg_merl_description = Metaprogramming in Erlang -pkg_merl_homepage = https://github.com/richcarl/merl -pkg_merl_fetch = git -pkg_merl_repo = https://github.com/richcarl/merl -pkg_merl_commit = master - -PACKAGES += mimetypes -pkg_mimetypes_name = mimetypes -pkg_mimetypes_description = Erlang MIME types library -pkg_mimetypes_homepage = https://github.com/spawngrid/mimetypes -pkg_mimetypes_fetch = git -pkg_mimetypes_repo = https://github.com/spawngrid/mimetypes -pkg_mimetypes_commit = master - -PACKAGES += mixer -pkg_mixer_name = mixer -pkg_mixer_description = Mix in functions from other modules -pkg_mixer_homepage = https://github.com/chef/mixer -pkg_mixer_fetch = git -pkg_mixer_repo = https://github.com/chef/mixer -pkg_mixer_commit = master - -PACKAGES += mochiweb -pkg_mochiweb_name = mochiweb -pkg_mochiweb_description = MochiWeb is an Erlang library for building lightweight HTTP servers. -pkg_mochiweb_homepage = https://github.com/mochi/mochiweb -pkg_mochiweb_fetch = git -pkg_mochiweb_repo = https://github.com/mochi/mochiweb -pkg_mochiweb_commit = master - -PACKAGES += mochiweb_xpath -pkg_mochiweb_xpath_name = mochiweb_xpath -pkg_mochiweb_xpath_description = XPath support for mochiweb's html parser -pkg_mochiweb_xpath_homepage = https://github.com/retnuh/mochiweb_xpath -pkg_mochiweb_xpath_fetch = git -pkg_mochiweb_xpath_repo = https://github.com/retnuh/mochiweb_xpath -pkg_mochiweb_xpath_commit = master - -PACKAGES += mockgyver -pkg_mockgyver_name = mockgyver -pkg_mockgyver_description = A mocking library for Erlang -pkg_mockgyver_homepage = https://github.com/klajo/mockgyver -pkg_mockgyver_fetch = git -pkg_mockgyver_repo = https://github.com/klajo/mockgyver -pkg_mockgyver_commit = master - -PACKAGES += modlib -pkg_modlib_name = modlib -pkg_modlib_description = Web framework based on Erlang's inets httpd -pkg_modlib_homepage = https://github.com/gar1t/modlib -pkg_modlib_fetch = git -pkg_modlib_repo = https://github.com/gar1t/modlib -pkg_modlib_commit = master - -PACKAGES += mongodb -pkg_mongodb_name = mongodb -pkg_mongodb_description = MongoDB driver for Erlang -pkg_mongodb_homepage = https://github.com/comtihon/mongodb-erlang -pkg_mongodb_fetch = git -pkg_mongodb_repo = https://github.com/comtihon/mongodb-erlang -pkg_mongodb_commit = master - -PACKAGES += mongooseim -pkg_mongooseim_name = mongooseim -pkg_mongooseim_description = Jabber / XMPP server with focus on performance and scalability, by Erlang Solutions -pkg_mongooseim_homepage = https://www.erlang-solutions.com/products/mongooseim-massively-scalable-ejabberd-platform -pkg_mongooseim_fetch = git -pkg_mongooseim_repo = https://github.com/esl/MongooseIM -pkg_mongooseim_commit = master - -PACKAGES += moyo -pkg_moyo_name = moyo -pkg_moyo_description = Erlang utility functions library -pkg_moyo_homepage = https://github.com/dwango/moyo -pkg_moyo_fetch = git -pkg_moyo_repo = https://github.com/dwango/moyo -pkg_moyo_commit = master - -PACKAGES += msgpack -pkg_msgpack_name = msgpack -pkg_msgpack_description = MessagePack (de)serializer implementation for Erlang -pkg_msgpack_homepage = https://github.com/msgpack/msgpack-erlang -pkg_msgpack_fetch = git -pkg_msgpack_repo = https://github.com/msgpack/msgpack-erlang -pkg_msgpack_commit = master - -PACKAGES += mu2 -pkg_mu2_name = mu2 -pkg_mu2_description = Erlang mutation testing tool -pkg_mu2_homepage = https://github.com/ramsay-t/mu2 -pkg_mu2_fetch = git -pkg_mu2_repo = https://github.com/ramsay-t/mu2 -pkg_mu2_commit = master - -PACKAGES += mustache -pkg_mustache_name = mustache -pkg_mustache_description = Mustache template engine for Erlang. -pkg_mustache_homepage = https://github.com/mojombo/mustache.erl -pkg_mustache_fetch = git -pkg_mustache_repo = https://github.com/mojombo/mustache.erl -pkg_mustache_commit = master - -PACKAGES += myproto -pkg_myproto_name = myproto -pkg_myproto_description = MySQL Server Protocol in Erlang -pkg_myproto_homepage = https://github.com/altenwald/myproto -pkg_myproto_fetch = git -pkg_myproto_repo = https://github.com/altenwald/myproto -pkg_myproto_commit = master - -PACKAGES += mysql -pkg_mysql_name = mysql -pkg_mysql_description = Erlang MySQL Driver (from code.google.com) -pkg_mysql_homepage = https://github.com/dizzyd/erlang-mysql-driver -pkg_mysql_fetch = git -pkg_mysql_repo = https://github.com/dizzyd/erlang-mysql-driver -pkg_mysql_commit = master - -PACKAGES += n2o -pkg_n2o_name = n2o -pkg_n2o_description = WebSocket Application Server -pkg_n2o_homepage = https://github.com/5HT/n2o -pkg_n2o_fetch = git -pkg_n2o_repo = https://github.com/5HT/n2o -pkg_n2o_commit = master - -PACKAGES += nat_upnp -pkg_nat_upnp_name = nat_upnp -pkg_nat_upnp_description = Erlang library to map your internal port to an external using UNP IGD -pkg_nat_upnp_homepage = https://github.com/benoitc/nat_upnp -pkg_nat_upnp_fetch = git -pkg_nat_upnp_repo = https://github.com/benoitc/nat_upnp -pkg_nat_upnp_commit = master - -PACKAGES += neo4j -pkg_neo4j_name = neo4j -pkg_neo4j_description = Erlang client library for Neo4J. -pkg_neo4j_homepage = https://github.com/dmitriid/neo4j-erlang -pkg_neo4j_fetch = git -pkg_neo4j_repo = https://github.com/dmitriid/neo4j-erlang -pkg_neo4j_commit = master - -PACKAGES += neotoma -pkg_neotoma_name = neotoma -pkg_neotoma_description = Erlang library and packrat parser-generator for parsing expression grammars. -pkg_neotoma_homepage = https://github.com/seancribbs/neotoma -pkg_neotoma_fetch = git -pkg_neotoma_repo = https://github.com/seancribbs/neotoma -pkg_neotoma_commit = master - -PACKAGES += newrelic -pkg_newrelic_name = newrelic -pkg_newrelic_description = Erlang library for sending metrics to New Relic -pkg_newrelic_homepage = https://github.com/wooga/newrelic-erlang -pkg_newrelic_fetch = git -pkg_newrelic_repo = https://github.com/wooga/newrelic-erlang -pkg_newrelic_commit = master - -PACKAGES += nifty -pkg_nifty_name = nifty -pkg_nifty_description = Erlang NIF wrapper generator -pkg_nifty_homepage = https://github.com/parapluu/nifty -pkg_nifty_fetch = git -pkg_nifty_repo = https://github.com/parapluu/nifty -pkg_nifty_commit = master - -PACKAGES += nitrogen_core -pkg_nitrogen_core_name = nitrogen_core -pkg_nitrogen_core_description = The core Nitrogen library. -pkg_nitrogen_core_homepage = http://nitrogenproject.com/ -pkg_nitrogen_core_fetch = git -pkg_nitrogen_core_repo = https://github.com/nitrogen/nitrogen_core -pkg_nitrogen_core_commit = master - -PACKAGES += nkbase -pkg_nkbase_name = nkbase -pkg_nkbase_description = NkBASE distributed database -pkg_nkbase_homepage = https://github.com/Nekso/nkbase -pkg_nkbase_fetch = git -pkg_nkbase_repo = https://github.com/Nekso/nkbase -pkg_nkbase_commit = develop - -PACKAGES += nkdocker -pkg_nkdocker_name = nkdocker -pkg_nkdocker_description = Erlang Docker client -pkg_nkdocker_homepage = https://github.com/Nekso/nkdocker -pkg_nkdocker_fetch = git -pkg_nkdocker_repo = https://github.com/Nekso/nkdocker -pkg_nkdocker_commit = master - -PACKAGES += nkpacket -pkg_nkpacket_name = nkpacket -pkg_nkpacket_description = Generic Erlang transport layer -pkg_nkpacket_homepage = https://github.com/Nekso/nkpacket -pkg_nkpacket_fetch = git -pkg_nkpacket_repo = https://github.com/Nekso/nkpacket -pkg_nkpacket_commit = master - -PACKAGES += nodefinder -pkg_nodefinder_name = nodefinder -pkg_nodefinder_description = automatic node discovery via UDP multicast -pkg_nodefinder_homepage = https://github.com/erlanger/nodefinder -pkg_nodefinder_fetch = git -pkg_nodefinder_repo = https://github.com/okeuday/nodefinder -pkg_nodefinder_commit = master - -PACKAGES += nprocreg -pkg_nprocreg_name = nprocreg -pkg_nprocreg_description = Minimal Distributed Erlang Process Registry -pkg_nprocreg_homepage = http://nitrogenproject.com/ -pkg_nprocreg_fetch = git -pkg_nprocreg_repo = https://github.com/nitrogen/nprocreg -pkg_nprocreg_commit = master - -PACKAGES += oauth2c -pkg_oauth2c_name = oauth2c -pkg_oauth2c_description = Erlang OAuth2 Client -pkg_oauth2c_homepage = https://github.com/kivra/oauth2_client -pkg_oauth2c_fetch = git -pkg_oauth2c_repo = https://github.com/kivra/oauth2_client -pkg_oauth2c_commit = master - -PACKAGES += oauth2 -pkg_oauth2_name = oauth2 -pkg_oauth2_description = Erlang Oauth2 implementation -pkg_oauth2_homepage = https://github.com/kivra/oauth2 -pkg_oauth2_fetch = git -pkg_oauth2_repo = https://github.com/kivra/oauth2 -pkg_oauth2_commit = master - -PACKAGES += oauth -pkg_oauth_name = oauth -pkg_oauth_description = An Erlang OAuth 1.0 implementation -pkg_oauth_homepage = https://github.com/tim/erlang-oauth -pkg_oauth_fetch = git -pkg_oauth_repo = https://github.com/tim/erlang-oauth -pkg_oauth_commit = master - -PACKAGES += of_protocol -pkg_of_protocol_name = of_protocol -pkg_of_protocol_description = OpenFlow Protocol Library for Erlang -pkg_of_protocol_homepage = https://github.com/FlowForwarding/of_protocol -pkg_of_protocol_fetch = git -pkg_of_protocol_repo = https://github.com/FlowForwarding/of_protocol -pkg_of_protocol_commit = master - -PACKAGES += openflow -pkg_openflow_name = openflow -pkg_openflow_description = An OpenFlow controller written in pure erlang -pkg_openflow_homepage = https://github.com/renatoaguiar/erlang-openflow -pkg_openflow_fetch = git -pkg_openflow_repo = https://github.com/renatoaguiar/erlang-openflow -pkg_openflow_commit = master - -PACKAGES += openid -pkg_openid_name = openid -pkg_openid_description = Erlang OpenID -pkg_openid_homepage = https://github.com/brendonh/erl_openid -pkg_openid_fetch = git -pkg_openid_repo = https://github.com/brendonh/erl_openid -pkg_openid_commit = master - -PACKAGES += openpoker -pkg_openpoker_name = openpoker -pkg_openpoker_description = Genesis Texas hold'em Game Server -pkg_openpoker_homepage = https://github.com/hpyhacking/openpoker -pkg_openpoker_fetch = git -pkg_openpoker_repo = https://github.com/hpyhacking/openpoker -pkg_openpoker_commit = master - -PACKAGES += pal -pkg_pal_name = pal -pkg_pal_description = Pragmatic Authentication Library -pkg_pal_homepage = https://github.com/manifest/pal -pkg_pal_fetch = git -pkg_pal_repo = https://github.com/manifest/pal -pkg_pal_commit = master - -PACKAGES += parse_trans -pkg_parse_trans_name = parse_trans -pkg_parse_trans_description = Parse transform utilities for Erlang -pkg_parse_trans_homepage = https://github.com/uwiger/parse_trans -pkg_parse_trans_fetch = git -pkg_parse_trans_repo = https://github.com/uwiger/parse_trans -pkg_parse_trans_commit = master - -PACKAGES += parsexml -pkg_parsexml_name = parsexml -pkg_parsexml_description = Simple DOM XML parser with convenient and very simple API -pkg_parsexml_homepage = https://github.com/maxlapshin/parsexml -pkg_parsexml_fetch = git -pkg_parsexml_repo = https://github.com/maxlapshin/parsexml -pkg_parsexml_commit = master - -PACKAGES += pegjs -pkg_pegjs_name = pegjs -pkg_pegjs_description = An implementation of PEG.js grammar for Erlang. -pkg_pegjs_homepage = https://github.com/dmitriid/pegjs -pkg_pegjs_fetch = git -pkg_pegjs_repo = https://github.com/dmitriid/pegjs -pkg_pegjs_commit = 0.3 - -PACKAGES += percept2 -pkg_percept2_name = percept2 -pkg_percept2_description = Concurrent profiling tool for Erlang -pkg_percept2_homepage = https://github.com/huiqing/percept2 -pkg_percept2_fetch = git -pkg_percept2_repo = https://github.com/huiqing/percept2 -pkg_percept2_commit = master - -PACKAGES += pgsql -pkg_pgsql_name = pgsql -pkg_pgsql_description = Erlang PostgreSQL driver -pkg_pgsql_homepage = https://github.com/semiocast/pgsql -pkg_pgsql_fetch = git -pkg_pgsql_repo = https://github.com/semiocast/pgsql -pkg_pgsql_commit = master - -PACKAGES += pkgx -pkg_pkgx_name = pkgx -pkg_pkgx_description = Build .deb packages from Erlang releases -pkg_pkgx_homepage = https://github.com/arjan/pkgx -pkg_pkgx_fetch = git -pkg_pkgx_repo = https://github.com/arjan/pkgx -pkg_pkgx_commit = master - -PACKAGES += pkt -pkg_pkt_name = pkt -pkg_pkt_description = Erlang network protocol library -pkg_pkt_homepage = https://github.com/msantos/pkt -pkg_pkt_fetch = git -pkg_pkt_repo = https://github.com/msantos/pkt -pkg_pkt_commit = master - -PACKAGES += plain_fsm -pkg_plain_fsm_name = plain_fsm -pkg_plain_fsm_description = A behaviour/support library for writing plain Erlang FSMs. -pkg_plain_fsm_homepage = https://github.com/uwiger/plain_fsm -pkg_plain_fsm_fetch = git -pkg_plain_fsm_repo = https://github.com/uwiger/plain_fsm -pkg_plain_fsm_commit = master - -PACKAGES += plumtree -pkg_plumtree_name = plumtree -pkg_plumtree_description = Epidemic Broadcast Trees -pkg_plumtree_homepage = https://github.com/helium/plumtree -pkg_plumtree_fetch = git -pkg_plumtree_repo = https://github.com/helium/plumtree -pkg_plumtree_commit = master - -PACKAGES += pmod_transform -pkg_pmod_transform_name = pmod_transform -pkg_pmod_transform_description = Parse transform for parameterized modules -pkg_pmod_transform_homepage = https://github.com/erlang/pmod_transform -pkg_pmod_transform_fetch = git -pkg_pmod_transform_repo = https://github.com/erlang/pmod_transform -pkg_pmod_transform_commit = master - -PACKAGES += pobox -pkg_pobox_name = pobox -pkg_pobox_description = External buffer processes to protect against mailbox overflow in Erlang -pkg_pobox_homepage = https://github.com/ferd/pobox -pkg_pobox_fetch = git -pkg_pobox_repo = https://github.com/ferd/pobox -pkg_pobox_commit = master - -PACKAGES += ponos -pkg_ponos_name = ponos -pkg_ponos_description = ponos is a simple yet powerful load generator written in erlang -pkg_ponos_homepage = https://github.com/klarna/ponos -pkg_ponos_fetch = git -pkg_ponos_repo = https://github.com/klarna/ponos -pkg_ponos_commit = master - -PACKAGES += poolboy -pkg_poolboy_name = poolboy -pkg_poolboy_description = A hunky Erlang worker pool factory -pkg_poolboy_homepage = https://github.com/devinus/poolboy -pkg_poolboy_fetch = git -pkg_poolboy_repo = https://github.com/devinus/poolboy -pkg_poolboy_commit = master - -PACKAGES += pooler -pkg_pooler_name = pooler -pkg_pooler_description = An OTP Process Pool Application -pkg_pooler_homepage = https://github.com/seth/pooler -pkg_pooler_fetch = git -pkg_pooler_repo = https://github.com/seth/pooler -pkg_pooler_commit = master - -PACKAGES += pqueue -pkg_pqueue_name = pqueue -pkg_pqueue_description = Erlang Priority Queues -pkg_pqueue_homepage = https://github.com/okeuday/pqueue -pkg_pqueue_fetch = git -pkg_pqueue_repo = https://github.com/okeuday/pqueue -pkg_pqueue_commit = master - -PACKAGES += procket -pkg_procket_name = procket -pkg_procket_description = Erlang interface to low level socket operations -pkg_procket_homepage = http://blog.listincomprehension.com/search/label/procket -pkg_procket_fetch = git -pkg_procket_repo = https://github.com/msantos/procket -pkg_procket_commit = master - -PACKAGES += proper -pkg_proper_name = proper -pkg_proper_description = PropEr: a QuickCheck-inspired property-based testing tool for Erlang. -pkg_proper_homepage = http://proper.softlab.ntua.gr -pkg_proper_fetch = git -pkg_proper_repo = https://github.com/manopapad/proper -pkg_proper_commit = master - -PACKAGES += prop -pkg_prop_name = prop -pkg_prop_description = An Erlang code scaffolding and generator system. -pkg_prop_homepage = https://github.com/nuex/prop -pkg_prop_fetch = git -pkg_prop_repo = https://github.com/nuex/prop -pkg_prop_commit = master - -PACKAGES += props -pkg_props_name = props -pkg_props_description = Property structure library -pkg_props_homepage = https://github.com/greyarea/props -pkg_props_fetch = git -pkg_props_repo = https://github.com/greyarea/props -pkg_props_commit = master - -PACKAGES += protobuffs -pkg_protobuffs_name = protobuffs -pkg_protobuffs_description = An implementation of Google's Protocol Buffers for Erlang, based on ngerakines/erlang_protobuffs. -pkg_protobuffs_homepage = https://github.com/basho/erlang_protobuffs -pkg_protobuffs_fetch = git -pkg_protobuffs_repo = https://github.com/basho/erlang_protobuffs -pkg_protobuffs_commit = master - -PACKAGES += psycho -pkg_psycho_name = psycho -pkg_psycho_description = HTTP server that provides a WSGI-like interface for applications and middleware. -pkg_psycho_homepage = https://github.com/gar1t/psycho -pkg_psycho_fetch = git -pkg_psycho_repo = https://github.com/gar1t/psycho -pkg_psycho_commit = master - -PACKAGES += ptrackerl -pkg_ptrackerl_name = ptrackerl -pkg_ptrackerl_description = Pivotal Tracker API Client written in Erlang -pkg_ptrackerl_homepage = https://github.com/inaka/ptrackerl -pkg_ptrackerl_fetch = git -pkg_ptrackerl_repo = https://github.com/inaka/ptrackerl -pkg_ptrackerl_commit = master - -PACKAGES += purity -pkg_purity_name = purity -pkg_purity_description = A side-effect analyzer for Erlang -pkg_purity_homepage = https://github.com/mpitid/purity -pkg_purity_fetch = git -pkg_purity_repo = https://github.com/mpitid/purity -pkg_purity_commit = master - -PACKAGES += push_service -pkg_push_service_name = push_service -pkg_push_service_description = Push service -pkg_push_service_homepage = https://github.com/hairyhum/push_service -pkg_push_service_fetch = git -pkg_push_service_repo = https://github.com/hairyhum/push_service -pkg_push_service_commit = master - -PACKAGES += qdate -pkg_qdate_name = qdate -pkg_qdate_description = Date, time, and timezone parsing, formatting, and conversion for Erlang. -pkg_qdate_homepage = https://github.com/choptastic/qdate -pkg_qdate_fetch = git -pkg_qdate_repo = https://github.com/choptastic/qdate -pkg_qdate_commit = 0.4.0 - -PACKAGES += qrcode -pkg_qrcode_name = qrcode -pkg_qrcode_description = QR Code encoder in Erlang -pkg_qrcode_homepage = https://github.com/komone/qrcode -pkg_qrcode_fetch = git -pkg_qrcode_repo = https://github.com/komone/qrcode -pkg_qrcode_commit = master - -PACKAGES += quest -pkg_quest_name = quest -pkg_quest_description = Learn Erlang through this set of challenges. An interactive system for getting to know Erlang. -pkg_quest_homepage = https://github.com/eriksoe/ErlangQuest -pkg_quest_fetch = git -pkg_quest_repo = https://github.com/eriksoe/ErlangQuest -pkg_quest_commit = master - -PACKAGES += quickrand -pkg_quickrand_name = quickrand -pkg_quickrand_description = Quick Erlang Random Number Generation -pkg_quickrand_homepage = https://github.com/okeuday/quickrand -pkg_quickrand_fetch = git -pkg_quickrand_repo = https://github.com/okeuday/quickrand -pkg_quickrand_commit = master - -PACKAGES += rabbit_exchange_type_riak -pkg_rabbit_exchange_type_riak_name = rabbit_exchange_type_riak -pkg_rabbit_exchange_type_riak_description = Custom RabbitMQ exchange type for sticking messages in Riak -pkg_rabbit_exchange_type_riak_homepage = https://github.com/jbrisbin/riak-exchange -pkg_rabbit_exchange_type_riak_fetch = git -pkg_rabbit_exchange_type_riak_repo = https://github.com/jbrisbin/riak-exchange -pkg_rabbit_exchange_type_riak_commit = master - -PACKAGES += rabbit -pkg_rabbit_name = rabbit -pkg_rabbit_description = RabbitMQ Server -pkg_rabbit_homepage = https://www.rabbitmq.com/ -pkg_rabbit_fetch = git -pkg_rabbit_repo = https://github.com/rabbitmq/rabbitmq-server.git -pkg_rabbit_commit = master - -PACKAGES += rack -pkg_rack_name = rack -pkg_rack_description = Rack handler for erlang -pkg_rack_homepage = https://github.com/erlyvideo/rack -pkg_rack_fetch = git -pkg_rack_repo = https://github.com/erlyvideo/rack -pkg_rack_commit = master - -PACKAGES += radierl -pkg_radierl_name = radierl -pkg_radierl_description = RADIUS protocol stack implemented in Erlang. -pkg_radierl_homepage = https://github.com/vances/radierl -pkg_radierl_fetch = git -pkg_radierl_repo = https://github.com/vances/radierl -pkg_radierl_commit = master - -PACKAGES += rafter -pkg_rafter_name = rafter -pkg_rafter_description = An Erlang library application which implements the Raft consensus protocol -pkg_rafter_homepage = https://github.com/andrewjstone/rafter -pkg_rafter_fetch = git -pkg_rafter_repo = https://github.com/andrewjstone/rafter -pkg_rafter_commit = master - -PACKAGES += ranch -pkg_ranch_name = ranch -pkg_ranch_description = Socket acceptor pool for TCP protocols. -pkg_ranch_homepage = http://ninenines.eu -pkg_ranch_fetch = git -pkg_ranch_repo = https://github.com/ninenines/ranch -pkg_ranch_commit = 1.1.0 - -PACKAGES += rbeacon -pkg_rbeacon_name = rbeacon -pkg_rbeacon_description = LAN discovery and presence in Erlang. -pkg_rbeacon_homepage = https://github.com/refuge/rbeacon -pkg_rbeacon_fetch = git -pkg_rbeacon_repo = https://github.com/refuge/rbeacon -pkg_rbeacon_commit = master - -PACKAGES += rebar -pkg_rebar_name = rebar -pkg_rebar_description = Erlang build tool that makes it easy to compile and test Erlang applications, port drivers and releases. -pkg_rebar_homepage = http://www.rebar3.org -pkg_rebar_fetch = git -pkg_rebar_repo = https://github.com/rebar/rebar3 -pkg_rebar_commit = master - -PACKAGES += rebus -pkg_rebus_name = rebus -pkg_rebus_description = A stupid simple, internal, pub/sub event bus written in- and for Erlang. -pkg_rebus_homepage = https://github.com/olle/rebus -pkg_rebus_fetch = git -pkg_rebus_repo = https://github.com/olle/rebus -pkg_rebus_commit = master - -PACKAGES += rec2json -pkg_rec2json_name = rec2json -pkg_rec2json_description = Compile erlang record definitions into modules to convert them to/from json easily. -pkg_rec2json_homepage = https://github.com/lordnull/rec2json -pkg_rec2json_fetch = git -pkg_rec2json_repo = https://github.com/lordnull/rec2json -pkg_rec2json_commit = master - -PACKAGES += recon -pkg_recon_name = recon -pkg_recon_description = Collection of functions and scripts to debug Erlang in production. -pkg_recon_homepage = https://github.com/ferd/recon -pkg_recon_fetch = git -pkg_recon_repo = https://github.com/ferd/recon -pkg_recon_commit = 2.2.1 - -PACKAGES += record_info -pkg_record_info_name = record_info -pkg_record_info_description = Convert between record and proplist -pkg_record_info_homepage = https://github.com/bipthelin/erlang-record_info -pkg_record_info_fetch = git -pkg_record_info_repo = https://github.com/bipthelin/erlang-record_info -pkg_record_info_commit = master - -PACKAGES += redgrid -pkg_redgrid_name = redgrid -pkg_redgrid_description = automatic Erlang node discovery via redis -pkg_redgrid_homepage = https://github.com/jkvor/redgrid -pkg_redgrid_fetch = git -pkg_redgrid_repo = https://github.com/jkvor/redgrid -pkg_redgrid_commit = master - -PACKAGES += redo -pkg_redo_name = redo -pkg_redo_description = pipelined erlang redis client -pkg_redo_homepage = https://github.com/jkvor/redo -pkg_redo_fetch = git -pkg_redo_repo = https://github.com/jkvor/redo -pkg_redo_commit = master - -PACKAGES += reltool_util -pkg_reltool_util_name = reltool_util -pkg_reltool_util_description = Erlang reltool utility functionality application -pkg_reltool_util_homepage = https://github.com/okeuday/reltool_util -pkg_reltool_util_fetch = git -pkg_reltool_util_repo = https://github.com/okeuday/reltool_util -pkg_reltool_util_commit = master - -PACKAGES += relx -pkg_relx_name = relx -pkg_relx_description = Sane, simple release creation for Erlang -pkg_relx_homepage = https://github.com/erlware/relx -pkg_relx_fetch = git -pkg_relx_repo = https://github.com/erlware/relx -pkg_relx_commit = master - -PACKAGES += resource_discovery -pkg_resource_discovery_name = resource_discovery -pkg_resource_discovery_description = An application used to dynamically discover resources present in an Erlang node cluster. -pkg_resource_discovery_homepage = http://erlware.org/ -pkg_resource_discovery_fetch = git -pkg_resource_discovery_repo = https://github.com/erlware/resource_discovery -pkg_resource_discovery_commit = master - -PACKAGES += restc -pkg_restc_name = restc -pkg_restc_description = Erlang Rest Client -pkg_restc_homepage = https://github.com/kivra/restclient -pkg_restc_fetch = git -pkg_restc_repo = https://github.com/kivra/restclient -pkg_restc_commit = master - -PACKAGES += rfc4627_jsonrpc -pkg_rfc4627_jsonrpc_name = rfc4627_jsonrpc -pkg_rfc4627_jsonrpc_description = Erlang RFC4627 (JSON) codec and JSON-RPC server implementation. -pkg_rfc4627_jsonrpc_homepage = https://github.com/tonyg/erlang-rfc4627 -pkg_rfc4627_jsonrpc_fetch = git -pkg_rfc4627_jsonrpc_repo = https://github.com/tonyg/erlang-rfc4627 -pkg_rfc4627_jsonrpc_commit = master - -PACKAGES += riakc -pkg_riakc_name = riakc -pkg_riakc_description = Erlang clients for Riak. -pkg_riakc_homepage = https://github.com/basho/riak-erlang-client -pkg_riakc_fetch = git -pkg_riakc_repo = https://github.com/basho/riak-erlang-client -pkg_riakc_commit = master - -PACKAGES += riak_control -pkg_riak_control_name = riak_control -pkg_riak_control_description = Webmachine-based administration interface for Riak. -pkg_riak_control_homepage = https://github.com/basho/riak_control -pkg_riak_control_fetch = git -pkg_riak_control_repo = https://github.com/basho/riak_control -pkg_riak_control_commit = master - -PACKAGES += riak_core -pkg_riak_core_name = riak_core -pkg_riak_core_description = Distributed systems infrastructure used by Riak. -pkg_riak_core_homepage = https://github.com/basho/riak_core -pkg_riak_core_fetch = git -pkg_riak_core_repo = https://github.com/basho/riak_core -pkg_riak_core_commit = master - -PACKAGES += riak_dt -pkg_riak_dt_name = riak_dt -pkg_riak_dt_description = Convergent replicated datatypes in Erlang -pkg_riak_dt_homepage = https://github.com/basho/riak_dt -pkg_riak_dt_fetch = git -pkg_riak_dt_repo = https://github.com/basho/riak_dt -pkg_riak_dt_commit = master - -PACKAGES += riak_ensemble -pkg_riak_ensemble_name = riak_ensemble -pkg_riak_ensemble_description = Multi-Paxos framework in Erlang -pkg_riak_ensemble_homepage = https://github.com/basho/riak_ensemble -pkg_riak_ensemble_fetch = git -pkg_riak_ensemble_repo = https://github.com/basho/riak_ensemble -pkg_riak_ensemble_commit = master - -PACKAGES += riakhttpc -pkg_riakhttpc_name = riakhttpc -pkg_riakhttpc_description = Riak Erlang client using the HTTP interface -pkg_riakhttpc_homepage = https://github.com/basho/riak-erlang-http-client -pkg_riakhttpc_fetch = git -pkg_riakhttpc_repo = https://github.com/basho/riak-erlang-http-client -pkg_riakhttpc_commit = master - -PACKAGES += riak_kv -pkg_riak_kv_name = riak_kv -pkg_riak_kv_description = Riak Key/Value Store -pkg_riak_kv_homepage = https://github.com/basho/riak_kv -pkg_riak_kv_fetch = git -pkg_riak_kv_repo = https://github.com/basho/riak_kv -pkg_riak_kv_commit = master - -PACKAGES += riaknostic -pkg_riaknostic_name = riaknostic -pkg_riaknostic_description = A diagnostic tool for Riak installations, to find common errors asap -pkg_riaknostic_homepage = https://github.com/basho/riaknostic -pkg_riaknostic_fetch = git -pkg_riaknostic_repo = https://github.com/basho/riaknostic -pkg_riaknostic_commit = master - -PACKAGES += riak_pg -pkg_riak_pg_name = riak_pg -pkg_riak_pg_description = Distributed process groups with riak_core. -pkg_riak_pg_homepage = https://github.com/cmeiklejohn/riak_pg -pkg_riak_pg_fetch = git -pkg_riak_pg_repo = https://github.com/cmeiklejohn/riak_pg -pkg_riak_pg_commit = master - -PACKAGES += riak_pipe -pkg_riak_pipe_name = riak_pipe -pkg_riak_pipe_description = Riak Pipelines -pkg_riak_pipe_homepage = https://github.com/basho/riak_pipe -pkg_riak_pipe_fetch = git -pkg_riak_pipe_repo = https://github.com/basho/riak_pipe -pkg_riak_pipe_commit = master - -PACKAGES += riakpool -pkg_riakpool_name = riakpool -pkg_riakpool_description = erlang riak client pool -pkg_riakpool_homepage = https://github.com/dweldon/riakpool -pkg_riakpool_fetch = git -pkg_riakpool_repo = https://github.com/dweldon/riakpool -pkg_riakpool_commit = master - -PACKAGES += riak_sysmon -pkg_riak_sysmon_name = riak_sysmon -pkg_riak_sysmon_description = Simple OTP app for managing Erlang VM system_monitor event messages -pkg_riak_sysmon_homepage = https://github.com/basho/riak_sysmon -pkg_riak_sysmon_fetch = git -pkg_riak_sysmon_repo = https://github.com/basho/riak_sysmon -pkg_riak_sysmon_commit = master - -PACKAGES += riak_test -pkg_riak_test_name = riak_test -pkg_riak_test_description = I'm in your cluster, testing your riaks -pkg_riak_test_homepage = https://github.com/basho/riak_test -pkg_riak_test_fetch = git -pkg_riak_test_repo = https://github.com/basho/riak_test -pkg_riak_test_commit = master - -PACKAGES += rivus_cep -pkg_rivus_cep_name = rivus_cep -pkg_rivus_cep_description = Complex event processing in Erlang -pkg_rivus_cep_homepage = https://github.com/vascokk/rivus_cep -pkg_rivus_cep_fetch = git -pkg_rivus_cep_repo = https://github.com/vascokk/rivus_cep -pkg_rivus_cep_commit = master - -PACKAGES += rlimit -pkg_rlimit_name = rlimit -pkg_rlimit_description = Magnus Klaar's rate limiter code from etorrent -pkg_rlimit_homepage = https://github.com/jlouis/rlimit -pkg_rlimit_fetch = git -pkg_rlimit_repo = https://github.com/jlouis/rlimit -pkg_rlimit_commit = master - -PACKAGES += safetyvalve -pkg_safetyvalve_name = safetyvalve -pkg_safetyvalve_description = A safety valve for your erlang node -pkg_safetyvalve_homepage = https://github.com/jlouis/safetyvalve -pkg_safetyvalve_fetch = git -pkg_safetyvalve_repo = https://github.com/jlouis/safetyvalve -pkg_safetyvalve_commit = master - -PACKAGES += seestar -pkg_seestar_name = seestar -pkg_seestar_description = The Erlang client for Cassandra 1.2+ binary protocol -pkg_seestar_homepage = https://github.com/iamaleksey/seestar -pkg_seestar_fetch = git -pkg_seestar_repo = https://github.com/iamaleksey/seestar -pkg_seestar_commit = master - -PACKAGES += service -pkg_service_name = service -pkg_service_description = A minimal Erlang behavior for creating CloudI internal services -pkg_service_homepage = http://cloudi.org/ -pkg_service_fetch = git -pkg_service_repo = https://github.com/CloudI/service -pkg_service_commit = master - -PACKAGES += setup -pkg_setup_name = setup -pkg_setup_description = Generic setup utility for Erlang-based systems -pkg_setup_homepage = https://github.com/uwiger/setup -pkg_setup_fetch = git -pkg_setup_repo = https://github.com/uwiger/setup -pkg_setup_commit = master - -PACKAGES += sext -pkg_sext_name = sext -pkg_sext_description = Sortable Erlang Term Serialization -pkg_sext_homepage = https://github.com/uwiger/sext -pkg_sext_fetch = git -pkg_sext_repo = https://github.com/uwiger/sext -pkg_sext_commit = master - -PACKAGES += sfmt -pkg_sfmt_name = sfmt -pkg_sfmt_description = SFMT pseudo random number generator for Erlang. -pkg_sfmt_homepage = https://github.com/jj1bdx/sfmt-erlang -pkg_sfmt_fetch = git -pkg_sfmt_repo = https://github.com/jj1bdx/sfmt-erlang -pkg_sfmt_commit = master - -PACKAGES += sgte -pkg_sgte_name = sgte -pkg_sgte_description = A simple Erlang Template Engine -pkg_sgte_homepage = https://github.com/filippo/sgte -pkg_sgte_fetch = git -pkg_sgte_repo = https://github.com/filippo/sgte -pkg_sgte_commit = master - -PACKAGES += sheriff -pkg_sheriff_name = sheriff -pkg_sheriff_description = Parse transform for type based validation. -pkg_sheriff_homepage = http://ninenines.eu -pkg_sheriff_fetch = git -pkg_sheriff_repo = https://github.com/extend/sheriff -pkg_sheriff_commit = master - -PACKAGES += shotgun -pkg_shotgun_name = shotgun -pkg_shotgun_description = better than just a gun -pkg_shotgun_homepage = https://github.com/inaka/shotgun -pkg_shotgun_fetch = git -pkg_shotgun_repo = https://github.com/inaka/shotgun -pkg_shotgun_commit = 0.1.0 - -PACKAGES += sidejob -pkg_sidejob_name = sidejob -pkg_sidejob_description = Parallel worker and capacity limiting library for Erlang -pkg_sidejob_homepage = https://github.com/basho/sidejob -pkg_sidejob_fetch = git -pkg_sidejob_repo = https://github.com/basho/sidejob -pkg_sidejob_commit = master - -PACKAGES += sieve -pkg_sieve_name = sieve -pkg_sieve_description = sieve is a simple TCP routing proxy (layer 7) in erlang -pkg_sieve_homepage = https://github.com/benoitc/sieve -pkg_sieve_fetch = git -pkg_sieve_repo = https://github.com/benoitc/sieve -pkg_sieve_commit = master - -PACKAGES += sighandler -pkg_sighandler_name = sighandler -pkg_sighandler_description = Handle UNIX signals in Er lang -pkg_sighandler_homepage = https://github.com/jkingsbery/sighandler -pkg_sighandler_fetch = git -pkg_sighandler_repo = https://github.com/jkingsbery/sighandler -pkg_sighandler_commit = master - -PACKAGES += simhash -pkg_simhash_name = simhash -pkg_simhash_description = Simhashing for Erlang -- hashing algorithm to find near-duplicates in binary data. -pkg_simhash_homepage = https://github.com/ferd/simhash -pkg_simhash_fetch = git -pkg_simhash_repo = https://github.com/ferd/simhash -pkg_simhash_commit = master - -PACKAGES += simple_bridge -pkg_simple_bridge_name = simple_bridge -pkg_simple_bridge_description = A simple, standardized interface library to Erlang HTTP Servers. -pkg_simple_bridge_homepage = https://github.com/nitrogen/simple_bridge -pkg_simple_bridge_fetch = git -pkg_simple_bridge_repo = https://github.com/nitrogen/simple_bridge -pkg_simple_bridge_commit = master - -PACKAGES += simple_oauth2 -pkg_simple_oauth2_name = simple_oauth2 -pkg_simple_oauth2_description = Simple erlang OAuth2 client module for any http server framework (Google, Facebook, Yandex, Vkontakte are preconfigured) -pkg_simple_oauth2_homepage = https://github.com/virtan/simple_oauth2 -pkg_simple_oauth2_fetch = git -pkg_simple_oauth2_repo = https://github.com/virtan/simple_oauth2 -pkg_simple_oauth2_commit = master - -PACKAGES += skel -pkg_skel_name = skel -pkg_skel_description = A Streaming Process-based Skeleton Library for Erlang -pkg_skel_homepage = https://github.com/ParaPhrase/skel -pkg_skel_fetch = git -pkg_skel_repo = https://github.com/ParaPhrase/skel -pkg_skel_commit = master - -PACKAGES += smother -pkg_smother_name = smother -pkg_smother_description = Extended code coverage metrics for Erlang. -pkg_smother_homepage = https://ramsay-t.github.io/Smother/ -pkg_smother_fetch = git -pkg_smother_repo = https://github.com/ramsay-t/Smother -pkg_smother_commit = master - -PACKAGES += social -pkg_social_name = social -pkg_social_description = Cowboy handler for social login via OAuth2 providers -pkg_social_homepage = https://github.com/dvv/social -pkg_social_fetch = git -pkg_social_repo = https://github.com/dvv/social -pkg_social_commit = master - -PACKAGES += spapi_router -pkg_spapi_router_name = spapi_router -pkg_spapi_router_description = Partially-connected Erlang clustering -pkg_spapi_router_homepage = https://github.com/spilgames/spapi-router -pkg_spapi_router_fetch = git -pkg_spapi_router_repo = https://github.com/spilgames/spapi-router -pkg_spapi_router_commit = master - -PACKAGES += sqerl -pkg_sqerl_name = sqerl -pkg_sqerl_description = An Erlang-flavoured SQL DSL -pkg_sqerl_homepage = https://github.com/hairyhum/sqerl -pkg_sqerl_fetch = git -pkg_sqerl_repo = https://github.com/hairyhum/sqerl -pkg_sqerl_commit = master - -PACKAGES += srly -pkg_srly_name = srly -pkg_srly_description = Native Erlang Unix serial interface -pkg_srly_homepage = https://github.com/msantos/srly -pkg_srly_fetch = git -pkg_srly_repo = https://github.com/msantos/srly -pkg_srly_commit = master - -PACKAGES += sshrpc -pkg_sshrpc_name = sshrpc -pkg_sshrpc_description = Erlang SSH RPC module (experimental) -pkg_sshrpc_homepage = https://github.com/jj1bdx/sshrpc -pkg_sshrpc_fetch = git -pkg_sshrpc_repo = https://github.com/jj1bdx/sshrpc -pkg_sshrpc_commit = master - -PACKAGES += stable -pkg_stable_name = stable -pkg_stable_description = Library of assorted helpers for Cowboy web server. -pkg_stable_homepage = https://github.com/dvv/stable -pkg_stable_fetch = git -pkg_stable_repo = https://github.com/dvv/stable -pkg_stable_commit = master - -PACKAGES += statebox -pkg_statebox_name = statebox -pkg_statebox_description = Erlang state monad with merge/conflict-resolution capabilities. Useful for Riak. -pkg_statebox_homepage = https://github.com/mochi/statebox -pkg_statebox_fetch = git -pkg_statebox_repo = https://github.com/mochi/statebox -pkg_statebox_commit = master - -PACKAGES += statebox_riak -pkg_statebox_riak_name = statebox_riak -pkg_statebox_riak_description = Convenience library that makes it easier to use statebox with riak, extracted from best practices in our production code at Mochi Media. -pkg_statebox_riak_homepage = https://github.com/mochi/statebox_riak -pkg_statebox_riak_fetch = git -pkg_statebox_riak_repo = https://github.com/mochi/statebox_riak -pkg_statebox_riak_commit = master - -PACKAGES += statman -pkg_statman_name = statman -pkg_statman_description = Efficiently collect massive volumes of metrics inside the Erlang VM -pkg_statman_homepage = https://github.com/knutin/statman -pkg_statman_fetch = git -pkg_statman_repo = https://github.com/knutin/statman -pkg_statman_commit = master - -PACKAGES += statsderl -pkg_statsderl_name = statsderl -pkg_statsderl_description = StatsD client (erlang) -pkg_statsderl_homepage = https://github.com/lpgauth/statsderl -pkg_statsderl_fetch = git -pkg_statsderl_repo = https://github.com/lpgauth/statsderl -pkg_statsderl_commit = master - -PACKAGES += stdinout_pool -pkg_stdinout_pool_name = stdinout_pool -pkg_stdinout_pool_description = stdinout_pool : stuff goes in, stuff goes out. there's never any miscommunication. -pkg_stdinout_pool_homepage = https://github.com/mattsta/erlang-stdinout-pool -pkg_stdinout_pool_fetch = git -pkg_stdinout_pool_repo = https://github.com/mattsta/erlang-stdinout-pool -pkg_stdinout_pool_commit = master - -PACKAGES += stockdb -pkg_stockdb_name = stockdb -pkg_stockdb_description = Database for storing Stock Exchange quotes in erlang -pkg_stockdb_homepage = https://github.com/maxlapshin/stockdb -pkg_stockdb_fetch = git -pkg_stockdb_repo = https://github.com/maxlapshin/stockdb -pkg_stockdb_commit = master - -PACKAGES += stripe -pkg_stripe_name = stripe -pkg_stripe_description = Erlang interface to the stripe.com API -pkg_stripe_homepage = https://github.com/mattsta/stripe-erlang -pkg_stripe_fetch = git -pkg_stripe_repo = https://github.com/mattsta/stripe-erlang -pkg_stripe_commit = v1 - -PACKAGES += surrogate -pkg_surrogate_name = surrogate -pkg_surrogate_description = Proxy server written in erlang. Supports reverse proxy load balancing and forward proxy with http (including CONNECT), socks4, socks5, and transparent proxy modes. -pkg_surrogate_homepage = https://github.com/skruger/Surrogate -pkg_surrogate_fetch = git -pkg_surrogate_repo = https://github.com/skruger/Surrogate -pkg_surrogate_commit = master - -PACKAGES += swab -pkg_swab_name = swab -pkg_swab_description = General purpose buffer handling module -pkg_swab_homepage = https://github.com/crownedgrouse/swab -pkg_swab_fetch = git -pkg_swab_repo = https://github.com/crownedgrouse/swab -pkg_swab_commit = master - -PACKAGES += swarm -pkg_swarm_name = swarm -pkg_swarm_description = Fast and simple acceptor pool for Erlang -pkg_swarm_homepage = https://github.com/jeremey/swarm -pkg_swarm_fetch = git -pkg_swarm_repo = https://github.com/jeremey/swarm -pkg_swarm_commit = master - -PACKAGES += switchboard -pkg_switchboard_name = switchboard -pkg_switchboard_description = A framework for processing email using worker plugins. -pkg_switchboard_homepage = https://github.com/thusfresh/switchboard -pkg_switchboard_fetch = git -pkg_switchboard_repo = https://github.com/thusfresh/switchboard -pkg_switchboard_commit = master - -PACKAGES += sync -pkg_sync_name = sync -pkg_sync_description = On-the-fly recompiling and reloading in Erlang. -pkg_sync_homepage = https://github.com/rustyio/sync -pkg_sync_fetch = git -pkg_sync_repo = https://github.com/rustyio/sync -pkg_sync_commit = master - -PACKAGES += syn -pkg_syn_name = syn -pkg_syn_description = A global process registry for Erlang. -pkg_syn_homepage = https://github.com/ostinelli/syn -pkg_syn_fetch = git -pkg_syn_repo = https://github.com/ostinelli/syn -pkg_syn_commit = master - -PACKAGES += syntaxerl -pkg_syntaxerl_name = syntaxerl -pkg_syntaxerl_description = Syntax checker for Erlang -pkg_syntaxerl_homepage = https://github.com/ten0s/syntaxerl -pkg_syntaxerl_fetch = git -pkg_syntaxerl_repo = https://github.com/ten0s/syntaxerl -pkg_syntaxerl_commit = master - -PACKAGES += syslog -pkg_syslog_name = syslog -pkg_syslog_description = Erlang port driver for interacting with syslog via syslog(3) -pkg_syslog_homepage = https://github.com/Vagabond/erlang-syslog -pkg_syslog_fetch = git -pkg_syslog_repo = https://github.com/Vagabond/erlang-syslog -pkg_syslog_commit = master - -PACKAGES += taskforce -pkg_taskforce_name = taskforce -pkg_taskforce_description = Erlang worker pools for controlled parallelisation of arbitrary tasks. -pkg_taskforce_homepage = https://github.com/g-andrade/taskforce -pkg_taskforce_fetch = git -pkg_taskforce_repo = https://github.com/g-andrade/taskforce -pkg_taskforce_commit = master - -PACKAGES += tddreloader -pkg_tddreloader_name = tddreloader -pkg_tddreloader_description = Shell utility for recompiling, reloading, and testing code as it changes -pkg_tddreloader_homepage = https://github.com/version2beta/tddreloader -pkg_tddreloader_fetch = git -pkg_tddreloader_repo = https://github.com/version2beta/tddreloader -pkg_tddreloader_commit = master - -PACKAGES += tempo -pkg_tempo_name = tempo -pkg_tempo_description = NIF-based date and time parsing and formatting for Erlang. -pkg_tempo_homepage = https://github.com/selectel/tempo -pkg_tempo_fetch = git -pkg_tempo_repo = https://github.com/selectel/tempo -pkg_tempo_commit = master - -PACKAGES += ticktick -pkg_ticktick_name = ticktick -pkg_ticktick_description = Ticktick is an id generator for message service. -pkg_ticktick_homepage = https://github.com/ericliang/ticktick -pkg_ticktick_fetch = git -pkg_ticktick_repo = https://github.com/ericliang/ticktick -pkg_ticktick_commit = master - -PACKAGES += tinymq -pkg_tinymq_name = tinymq -pkg_tinymq_description = TinyMQ - a diminutive, in-memory message queue -pkg_tinymq_homepage = https://github.com/ChicagoBoss/tinymq -pkg_tinymq_fetch = git -pkg_tinymq_repo = https://github.com/ChicagoBoss/tinymq -pkg_tinymq_commit = master - -PACKAGES += tinymt -pkg_tinymt_name = tinymt -pkg_tinymt_description = TinyMT pseudo random number generator for Erlang. -pkg_tinymt_homepage = https://github.com/jj1bdx/tinymt-erlang -pkg_tinymt_fetch = git -pkg_tinymt_repo = https://github.com/jj1bdx/tinymt-erlang -pkg_tinymt_commit = master - -PACKAGES += tirerl -pkg_tirerl_name = tirerl -pkg_tirerl_description = Erlang interface to Elastic Search -pkg_tirerl_homepage = https://github.com/inaka/tirerl -pkg_tirerl_fetch = git -pkg_tirerl_repo = https://github.com/inaka/tirerl -pkg_tirerl_commit = master - -PACKAGES += traffic_tools -pkg_traffic_tools_name = traffic_tools -pkg_traffic_tools_description = Simple traffic limiting library -pkg_traffic_tools_homepage = https://github.com/systra/traffic_tools -pkg_traffic_tools_fetch = git -pkg_traffic_tools_repo = https://github.com/systra/traffic_tools -pkg_traffic_tools_commit = master - -PACKAGES += trails -pkg_trails_name = trails -pkg_trails_description = A couple of improvements over Cowboy Routes -pkg_trails_homepage = http://inaka.github.io/cowboy-trails/ -pkg_trails_fetch = git -pkg_trails_repo = https://github.com/inaka/cowboy-trails -pkg_trails_commit = master - -PACKAGES += trane -pkg_trane_name = trane -pkg_trane_description = SAX style broken HTML parser in Erlang -pkg_trane_homepage = https://github.com/massemanet/trane -pkg_trane_fetch = git -pkg_trane_repo = https://github.com/massemanet/trane -pkg_trane_commit = master - -PACKAGES += transit -pkg_transit_name = transit -pkg_transit_description = transit format for erlang -pkg_transit_homepage = https://github.com/isaiah/transit-erlang -pkg_transit_fetch = git -pkg_transit_repo = https://github.com/isaiah/transit-erlang -pkg_transit_commit = master - -PACKAGES += trie -pkg_trie_name = trie -pkg_trie_description = Erlang Trie Implementation -pkg_trie_homepage = https://github.com/okeuday/trie -pkg_trie_fetch = git -pkg_trie_repo = https://github.com/okeuday/trie -pkg_trie_commit = master - -PACKAGES += triq -pkg_triq_name = triq -pkg_triq_description = Trifork QuickCheck -pkg_triq_homepage = https://github.com/krestenkrab/triq -pkg_triq_fetch = git -pkg_triq_repo = https://github.com/krestenkrab/triq -pkg_triq_commit = master - -PACKAGES += tunctl -pkg_tunctl_name = tunctl -pkg_tunctl_description = Erlang TUN/TAP interface -pkg_tunctl_homepage = https://github.com/msantos/tunctl -pkg_tunctl_fetch = git -pkg_tunctl_repo = https://github.com/msantos/tunctl -pkg_tunctl_commit = master - -PACKAGES += twerl -pkg_twerl_name = twerl -pkg_twerl_description = Erlang client for the Twitter Streaming API -pkg_twerl_homepage = https://github.com/lucaspiller/twerl -pkg_twerl_fetch = git -pkg_twerl_repo = https://github.com/lucaspiller/twerl -pkg_twerl_commit = oauth - -PACKAGES += twitter_erlang -pkg_twitter_erlang_name = twitter_erlang -pkg_twitter_erlang_description = An Erlang twitter client -pkg_twitter_erlang_homepage = https://github.com/ngerakines/erlang_twitter -pkg_twitter_erlang_fetch = git -pkg_twitter_erlang_repo = https://github.com/ngerakines/erlang_twitter -pkg_twitter_erlang_commit = master - -PACKAGES += ucol_nif -pkg_ucol_nif_name = ucol_nif -pkg_ucol_nif_description = ICU based collation Erlang module -pkg_ucol_nif_homepage = https://github.com/refuge/ucol_nif -pkg_ucol_nif_fetch = git -pkg_ucol_nif_repo = https://github.com/refuge/ucol_nif -pkg_ucol_nif_commit = master - -PACKAGES += unicorn -pkg_unicorn_name = unicorn -pkg_unicorn_description = Generic configuration server -pkg_unicorn_homepage = https://github.com/shizzard/unicorn -pkg_unicorn_fetch = git -pkg_unicorn_repo = https://github.com/shizzard/unicorn -pkg_unicorn_commit = 0.3.0 - -PACKAGES += unsplit -pkg_unsplit_name = unsplit -pkg_unsplit_description = Resolves conflicts in Mnesia after network splits -pkg_unsplit_homepage = https://github.com/uwiger/unsplit -pkg_unsplit_fetch = git -pkg_unsplit_repo = https://github.com/uwiger/unsplit -pkg_unsplit_commit = master - -PACKAGES += uuid -pkg_uuid_name = uuid -pkg_uuid_description = Erlang UUID Implementation -pkg_uuid_homepage = https://github.com/okeuday/uuid -pkg_uuid_fetch = git -pkg_uuid_repo = https://github.com/okeuday/uuid -pkg_uuid_commit = v1.4.0 - -PACKAGES += ux -pkg_ux_name = ux -pkg_ux_description = Unicode eXtention for Erlang (Strings, Collation) -pkg_ux_homepage = https://github.com/erlang-unicode/ux -pkg_ux_fetch = git -pkg_ux_repo = https://github.com/erlang-unicode/ux -pkg_ux_commit = master - -PACKAGES += vert -pkg_vert_name = vert -pkg_vert_description = Erlang binding to libvirt virtualization API -pkg_vert_homepage = https://github.com/msantos/erlang-libvirt -pkg_vert_fetch = git -pkg_vert_repo = https://github.com/msantos/erlang-libvirt -pkg_vert_commit = master - -PACKAGES += verx -pkg_verx_name = verx -pkg_verx_description = Erlang implementation of the libvirtd remote protocol -pkg_verx_homepage = https://github.com/msantos/verx -pkg_verx_fetch = git -pkg_verx_repo = https://github.com/msantos/verx -pkg_verx_commit = master - -PACKAGES += vmq_acl -pkg_vmq_acl_name = vmq_acl -pkg_vmq_acl_description = Component of VerneMQ: A distributed MQTT message broker -pkg_vmq_acl_homepage = https://verne.mq/ -pkg_vmq_acl_fetch = git -pkg_vmq_acl_repo = https://github.com/erlio/vmq_acl -pkg_vmq_acl_commit = master - -PACKAGES += vmq_bridge -pkg_vmq_bridge_name = vmq_bridge -pkg_vmq_bridge_description = Component of VerneMQ: A distributed MQTT message broker -pkg_vmq_bridge_homepage = https://verne.mq/ -pkg_vmq_bridge_fetch = git -pkg_vmq_bridge_repo = https://github.com/erlio/vmq_bridge -pkg_vmq_bridge_commit = master - -PACKAGES += vmq_graphite -pkg_vmq_graphite_name = vmq_graphite -pkg_vmq_graphite_description = Component of VerneMQ: A distributed MQTT message broker -pkg_vmq_graphite_homepage = https://verne.mq/ -pkg_vmq_graphite_fetch = git -pkg_vmq_graphite_repo = https://github.com/erlio/vmq_graphite -pkg_vmq_graphite_commit = master - -PACKAGES += vmq_passwd -pkg_vmq_passwd_name = vmq_passwd -pkg_vmq_passwd_description = Component of VerneMQ: A distributed MQTT message broker -pkg_vmq_passwd_homepage = https://verne.mq/ -pkg_vmq_passwd_fetch = git -pkg_vmq_passwd_repo = https://github.com/erlio/vmq_passwd -pkg_vmq_passwd_commit = master - -PACKAGES += vmq_server -pkg_vmq_server_name = vmq_server -pkg_vmq_server_description = Component of VerneMQ: A distributed MQTT message broker -pkg_vmq_server_homepage = https://verne.mq/ -pkg_vmq_server_fetch = git -pkg_vmq_server_repo = https://github.com/erlio/vmq_server -pkg_vmq_server_commit = master - -PACKAGES += vmq_snmp -pkg_vmq_snmp_name = vmq_snmp -pkg_vmq_snmp_description = Component of VerneMQ: A distributed MQTT message broker -pkg_vmq_snmp_homepage = https://verne.mq/ -pkg_vmq_snmp_fetch = git -pkg_vmq_snmp_repo = https://github.com/erlio/vmq_snmp -pkg_vmq_snmp_commit = master - -PACKAGES += vmq_systree -pkg_vmq_systree_name = vmq_systree -pkg_vmq_systree_description = Component of VerneMQ: A distributed MQTT message broker -pkg_vmq_systree_homepage = https://verne.mq/ -pkg_vmq_systree_fetch = git -pkg_vmq_systree_repo = https://github.com/erlio/vmq_systree -pkg_vmq_systree_commit = master - -PACKAGES += vmstats -pkg_vmstats_name = vmstats -pkg_vmstats_description = tiny Erlang app that works in conjunction with statsderl in order to generate information on the Erlang VM for graphite logs. -pkg_vmstats_homepage = https://github.com/ferd/vmstats -pkg_vmstats_fetch = git -pkg_vmstats_repo = https://github.com/ferd/vmstats -pkg_vmstats_commit = master - -PACKAGES += walrus -pkg_walrus_name = walrus -pkg_walrus_description = Walrus - Mustache-like Templating -pkg_walrus_homepage = https://github.com/devinus/walrus -pkg_walrus_fetch = git -pkg_walrus_repo = https://github.com/devinus/walrus -pkg_walrus_commit = master - -PACKAGES += webmachine -pkg_webmachine_name = webmachine -pkg_webmachine_description = A REST-based system for building web applications. -pkg_webmachine_homepage = https://github.com/basho/webmachine -pkg_webmachine_fetch = git -pkg_webmachine_repo = https://github.com/basho/webmachine -pkg_webmachine_commit = master - -PACKAGES += websocket_client -pkg_websocket_client_name = websocket_client -pkg_websocket_client_description = Erlang websocket client (ws and wss supported) -pkg_websocket_client_homepage = https://github.com/jeremyong/websocket_client -pkg_websocket_client_fetch = git -pkg_websocket_client_repo = https://github.com/jeremyong/websocket_client -pkg_websocket_client_commit = master - -PACKAGES += worker_pool -pkg_worker_pool_name = worker_pool -pkg_worker_pool_description = a simple erlang worker pool -pkg_worker_pool_homepage = https://github.com/inaka/worker_pool -pkg_worker_pool_fetch = git -pkg_worker_pool_repo = https://github.com/inaka/worker_pool -pkg_worker_pool_commit = 1.0.2 - -PACKAGES += wrangler -pkg_wrangler_name = wrangler -pkg_wrangler_description = Import of the Wrangler svn repository. -pkg_wrangler_homepage = http://www.cs.kent.ac.uk/projects/wrangler/Home.html -pkg_wrangler_fetch = git -pkg_wrangler_repo = https://github.com/RefactoringTools/wrangler -pkg_wrangler_commit = master - -PACKAGES += wsock -pkg_wsock_name = wsock -pkg_wsock_description = Erlang library to build WebSocket clients and servers -pkg_wsock_homepage = https://github.com/madtrick/wsock -pkg_wsock_fetch = git -pkg_wsock_repo = https://github.com/madtrick/wsock -pkg_wsock_commit = master - -PACKAGES += xhttpc -pkg_xhttpc_name = xhttpc -pkg_xhttpc_description = Extensible HTTP Client for Erlang -pkg_xhttpc_homepage = https://github.com/seriyps/xhttpc -pkg_xhttpc_fetch = git -pkg_xhttpc_repo = https://github.com/seriyps/xhttpc -pkg_xhttpc_commit = master - -PACKAGES += xref_runner -pkg_xref_runner_name = xref_runner -pkg_xref_runner_description = Erlang Xref Runner (inspired in rebar xref) -pkg_xref_runner_homepage = https://github.com/inaka/xref_runner -pkg_xref_runner_fetch = git -pkg_xref_runner_repo = https://github.com/inaka/xref_runner -pkg_xref_runner_commit = 0.2.0 - -PACKAGES += yamerl -pkg_yamerl_name = yamerl -pkg_yamerl_description = YAML 1.2 parser in pure Erlang -pkg_yamerl_homepage = https://github.com/yakaz/yamerl -pkg_yamerl_fetch = git -pkg_yamerl_repo = https://github.com/yakaz/yamerl -pkg_yamerl_commit = master - -PACKAGES += yamler -pkg_yamler_name = yamler -pkg_yamler_description = libyaml-based yaml loader for Erlang -pkg_yamler_homepage = https://github.com/goertzenator/yamler -pkg_yamler_fetch = git -pkg_yamler_repo = https://github.com/goertzenator/yamler -pkg_yamler_commit = master - -PACKAGES += yaws -pkg_yaws_name = yaws -pkg_yaws_description = Yaws webserver -pkg_yaws_homepage = http://yaws.hyber.org -pkg_yaws_fetch = git -pkg_yaws_repo = https://github.com/klacke/yaws -pkg_yaws_commit = master - -PACKAGES += zab_engine -pkg_zab_engine_name = zab_engine -pkg_zab_engine_description = zab propotocol implement by erlang -pkg_zab_engine_homepage = https://github.com/xinmingyao/zab_engine -pkg_zab_engine_fetch = git -pkg_zab_engine_repo = https://github.com/xinmingyao/zab_engine -pkg_zab_engine_commit = master - -PACKAGES += zeta -pkg_zeta_name = zeta -pkg_zeta_description = HTTP access log parser in Erlang -pkg_zeta_homepage = https://github.com/s1n4/zeta -pkg_zeta_fetch = git -pkg_zeta_repo = https://github.com/s1n4/zeta -pkg_zeta_commit = - -PACKAGES += zippers -pkg_zippers_name = zippers -pkg_zippers_description = A library for functional zipper data structures in Erlang. Read more on zippers -pkg_zippers_homepage = https://github.com/ferd/zippers -pkg_zippers_fetch = git -pkg_zippers_repo = https://github.com/ferd/zippers -pkg_zippers_commit = master - -PACKAGES += zlists -pkg_zlists_name = zlists -pkg_zlists_description = Erlang lazy lists library. -pkg_zlists_homepage = https://github.com/vjache/erlang-zlists -pkg_zlists_fetch = git -pkg_zlists_repo = https://github.com/vjache/erlang-zlists -pkg_zlists_commit = master - -PACKAGES += zraft_lib -pkg_zraft_lib_name = zraft_lib -pkg_zraft_lib_description = Erlang raft consensus protocol implementation -pkg_zraft_lib_homepage = https://github.com/dreyk/zraft_lib -pkg_zraft_lib_fetch = git -pkg_zraft_lib_repo = https://github.com/dreyk/zraft_lib -pkg_zraft_lib_commit = master - -PACKAGES += zucchini -pkg_zucchini_name = zucchini -pkg_zucchini_description = An Erlang INI parser -pkg_zucchini_homepage = https://github.com/devinus/zucchini -pkg_zucchini_fetch = git -pkg_zucchini_repo = https://github.com/devinus/zucchini -pkg_zucchini_commit = master - -# Copyright (c) 2015, Loïc Hoguin -# This file is part of erlang.mk and subject to the terms of the ISC License. - -.PHONY: search - -define pkg_print - $(verbose) printf "%s\n" \ - $(if $(call core_eq,$(1),$(pkg_$(1)_name)),,"Pkg name: $(1)") \ - "App name: $(pkg_$(1)_name)" \ - "Description: $(pkg_$(1)_description)" \ - "Home page: $(pkg_$(1)_homepage)" \ - "Fetch with: $(pkg_$(1)_fetch)" \ - "Repository: $(pkg_$(1)_repo)" \ - "Commit: $(pkg_$(1)_commit)" \ - "" - -endef - -search: -ifdef q - $(foreach p,$(PACKAGES), \ - $(if $(findstring $(call core_lc,$(q)),$(call core_lc,$(pkg_$(p)_name) $(pkg_$(p)_description))), \ - $(call pkg_print,$(p)))) -else - $(foreach p,$(PACKAGES),$(call pkg_print,$(p))) -endif - -# Copyright (c) 2013-2015, Loïc Hoguin -# This file is part of erlang.mk and subject to the terms of the ISC License. - -.PHONY: distclean-deps distclean-pkg - -# Configuration. - -IGNORE_DEPS ?= - -DEPS_DIR ?= $(CURDIR)/deps -export DEPS_DIR - -REBAR_DEPS_DIR = $(DEPS_DIR) -export REBAR_DEPS_DIR - -ALL_DEPS_DIRS = $(addprefix $(DEPS_DIR)/,$(filter-out $(IGNORE_DEPS),$(DEPS))) - -ifeq ($(filter $(DEPS_DIR),$(subst :, ,$(ERL_LIBS))),) -ifeq ($(ERL_LIBS),) - ERL_LIBS = $(DEPS_DIR) -else - ERL_LIBS := $(ERL_LIBS):$(DEPS_DIR) -endif -endif -export ERL_LIBS - -# Verbosity. - -dep_verbose_0 = @echo " DEP " $(1); -dep_verbose = $(dep_verbose_$(V)) - -# Core targets. - -ifneq ($(SKIP_DEPS),) -deps:: -else -deps:: $(ALL_DEPS_DIRS) -ifneq ($(IS_DEP),1) - $(verbose) rm -f $(ERLANG_MK_TMP)/deps.log -endif - $(verbose) mkdir -p $(ERLANG_MK_TMP) - $(verbose) for dep in $(ALL_DEPS_DIRS) ; do \ - if grep -qs ^$$dep$$ $(ERLANG_MK_TMP)/deps.log; then \ - echo -n; \ - else \ - echo $$dep >> $(ERLANG_MK_TMP)/deps.log; \ - if [ -f $$dep/GNUmakefile ] || [ -f $$dep/makefile ] || [ -f $$dep/Makefile ]; then \ - $(MAKE) -C $$dep IS_DEP=1 || exit $$?; \ - else \ - echo "ERROR: No Makefile to build dependency $$dep."; \ - exit 1; \ - fi \ - fi \ - done -endif - -distclean:: distclean-deps distclean-pkg - -# Deps related targets. - -# @todo rename GNUmakefile and makefile into Makefile first, if they exist -# While Makefile file could be GNUmakefile or makefile, -# in practice only Makefile is needed so far. -define dep_autopatch - if [ -f $(DEPS_DIR)/$(1)/Makefile ]; then \ - if [ 0 != `grep -c "include ../\w*\.mk" $(DEPS_DIR)/$(1)/Makefile` ]; then \ - $(call dep_autopatch2,$(1)); \ - elif [ 0 != `grep -ci rebar $(DEPS_DIR)/$(1)/Makefile` ]; then \ - $(call dep_autopatch2,$(1)); \ - elif [ -n "`find $(DEPS_DIR)/$(1)/ -type f -name \*.mk -not -name erlang.mk -exec grep -i rebar '{}' \;`" ]; then \ - $(call dep_autopatch2,$(1)); \ - else \ - if [ -f $(DEPS_DIR)/$(1)/erlang.mk ]; then \ - $(call erlang,$(call dep_autopatch_appsrc.erl,$(1))); \ - $(call dep_autopatch_erlang_mk,$(1)); \ - else \ - $(call erlang,$(call dep_autopatch_app.erl,$(1))); \ - fi \ - fi \ - else \ - if [ ! -d $(DEPS_DIR)/$(1)/src/ ]; then \ - $(call dep_autopatch_noop,$(1)); \ - else \ - $(call dep_autopatch2,$(1)); \ - fi \ - fi -endef - -define dep_autopatch2 - $(call erlang,$(call dep_autopatch_appsrc.erl,$(1))); \ - if [ -f $(DEPS_DIR)/$(1)/rebar.config -o -f $(DEPS_DIR)/$(1)/rebar.config.script ]; then \ - $(call dep_autopatch_fetch_rebar); \ - $(call dep_autopatch_rebar,$(1)); \ - else \ - $(call dep_autopatch_gen,$(1)); \ - fi -endef - -define dep_autopatch_noop - printf "noop:\n" > $(DEPS_DIR)/$(1)/Makefile -endef - -# Overwrite erlang.mk with the current file by default. -ifeq ($(NO_AUTOPATCH_ERLANG_MK),) -define dep_autopatch_erlang_mk - echo "include $(ERLANG_MK_FILENAME)" > $(DEPS_DIR)/$(1)/erlang.mk -endef -else -define dep_autopatch_erlang_mk - echo -n -endef -endif - -define dep_autopatch_gen - printf "%s\n" \ - "ERLC_OPTS = +debug_info" \ - "include ../../erlang.mk" > $(DEPS_DIR)/$(1)/Makefile -endef - -define dep_autopatch_fetch_rebar - mkdir -p $(ERLANG_MK_TMP); \ - if [ ! -d $(ERLANG_MK_TMP)/rebar ]; then \ - git clone -q -n -- https://github.com/rebar/rebar $(ERLANG_MK_TMP)/rebar; \ - cd $(ERLANG_MK_TMP)/rebar; \ - git checkout -q 791db716b5a3a7671e0b351f95ddf24b848ee173; \ - $(MAKE); \ - cd -; \ - fi -endef - -define dep_autopatch_rebar - if [ -f $(DEPS_DIR)/$(1)/Makefile ]; then \ - mv $(DEPS_DIR)/$(1)/Makefile $(DEPS_DIR)/$(1)/Makefile.orig.mk; \ - fi; \ - $(call erlang,$(call dep_autopatch_rebar.erl,$(1))); \ - rm -f $(DEPS_DIR)/$(1)/ebin/$(1).app -endef - -define dep_autopatch_rebar.erl - application:set_env(rebar, log_level, debug), - Conf1 = case file:consult("$(DEPS_DIR)/$(1)/rebar.config") of - {ok, Conf0} -> Conf0; - _ -> [] - end, - {Conf, OsEnv} = fun() -> - case filelib:is_file("$(DEPS_DIR)/$(1)/rebar.config.script") of - false -> {Conf1, []}; - true -> - Bindings0 = erl_eval:new_bindings(), - Bindings1 = erl_eval:add_binding('CONFIG', Conf1, Bindings0), - Bindings = erl_eval:add_binding('SCRIPT', "$(DEPS_DIR)/$(1)/rebar.config.script", Bindings1), - Before = os:getenv(), - {ok, Conf2} = file:script("$(DEPS_DIR)/$(1)/rebar.config.script", Bindings), - {Conf2, lists:foldl(fun(E, Acc) -> lists:delete(E, Acc) end, os:getenv(), Before)} - end - end(), - Write = fun (Text) -> - file:write_file("$(DEPS_DIR)/$(1)/Makefile", Text, [append]) - end, - Escape = fun (Text) -> - re:replace(Text, "\\\\$$$$", "\$$$$$$$$", [global, {return, list}]) - end, - Write("IGNORE_DEPS = edown eper eunit_formatters meck node_package " - "rebar_lock_deps_plugin rebar_vsn_plugin reltool_util\n"), - Write("C_SRC_DIR = /path/do/not/exist\n"), - Write("DRV_CFLAGS = -fPIC\nexport DRV_CFLAGS\n"), - Write(["ERLANG_ARCH = ", rebar_utils:wordsize(), "\nexport ERLANG_ARCH\n"]), - fun() -> - Write("ERLC_OPTS = +debug_info\nexport ERLC_OPTS\n"), - case lists:keyfind(erl_opts, 1, Conf) of - false -> ok; - {_, ErlOpts} -> - lists:foreach(fun - ({d, D}) -> - Write("ERLC_OPTS += -D" ++ atom_to_list(D) ++ "=1\n"); - ({i, I}) -> - Write(["ERLC_OPTS += -I ", I, "\n"]); - ({platform_define, Regex, D}) -> - case rebar_utils:is_arch(Regex) of - true -> Write("ERLC_OPTS += -D" ++ atom_to_list(D) ++ "=1\n"); - false -> ok - end; - ({parse_transform, PT}) -> - Write("ERLC_OPTS += +'{parse_transform, " ++ atom_to_list(PT) ++ "}'\n"); - (_) -> ok - end, ErlOpts) - end, - Write("\n") - end(), - fun() -> - File = case lists:keyfind(deps, 1, Conf) of - false -> []; - {_, Deps} -> - [begin case case Dep of - {N, S} when is_atom(N), is_list(S) -> {N, {hex, S}}; - {N, S} when is_tuple(S) -> {N, S}; - {N, _, S} -> {N, S}; - {N, _, S, _} -> {N, S}; - _ -> false - end of - false -> ok; - {Name, Source} -> - {Method, Repo, Commit} = case Source of - {hex, V} -> {hex, V, undefined}; - {git, R} -> {git, R, master}; - {M, R, {branch, C}} -> {M, R, C}; - {M, R, {ref, C}} -> {M, R, C}; - {M, R, {tag, C}} -> {M, R, C}; - {M, R, C} -> {M, R, C} - end, - Write(io_lib:format("DEPS += ~s\ndep_~s = ~s ~s ~s~n", [Name, Name, Method, Repo, Commit])) - end end || Dep <- Deps] - end - end(), - fun() -> - case lists:keyfind(erl_first_files, 1, Conf) of - false -> ok; - {_, Files} -> - Names = [[" ", case lists:reverse(F) of - "lre." ++ Elif -> lists:reverse(Elif); - Elif -> lists:reverse(Elif) - end] || "src/" ++ F <- Files], - Write(io_lib:format("COMPILE_FIRST +=~s\n", [Names])) - end - end(), - FindFirst = fun(F, Fd) -> - case io:parse_erl_form(Fd, undefined) of - {ok, {attribute, _, compile, {parse_transform, PT}}, _} -> - [PT, F(F, Fd)]; - {ok, {attribute, _, compile, CompileOpts}, _} when is_list(CompileOpts) -> - case proplists:get_value(parse_transform, CompileOpts) of - undefined -> [F(F, Fd)]; - PT -> [PT, F(F, Fd)] - end; - {ok, {attribute, _, include, Hrl}, _} -> - case file:open("$(DEPS_DIR)/$(1)/include/" ++ Hrl, [read]) of - {ok, HrlFd} -> [F(F, HrlFd), F(F, Fd)]; - _ -> - case file:open("$(DEPS_DIR)/$(1)/src/" ++ Hrl, [read]) of - {ok, HrlFd} -> [F(F, HrlFd), F(F, Fd)]; - _ -> [F(F, Fd)] - end - end; - {ok, {attribute, _, include_lib, "$(1)/include/" ++ Hrl}, _} -> - {ok, HrlFd} = file:open("$(DEPS_DIR)/$(1)/include/" ++ Hrl, [read]), - [F(F, HrlFd), F(F, Fd)]; - {ok, {attribute, _, include_lib, Hrl}, _} -> - case file:open("$(DEPS_DIR)/$(1)/include/" ++ Hrl, [read]) of - {ok, HrlFd} -> [F(F, HrlFd), F(F, Fd)]; - _ -> [F(F, Fd)] - end; - {ok, {attribute, _, import, {Imp, _}}, _} -> - case file:open("$(DEPS_DIR)/$(1)/src/" ++ atom_to_list(Imp) ++ ".erl", [read]) of - {ok, ImpFd} -> [Imp, F(F, ImpFd), F(F, Fd)]; - _ -> [F(F, Fd)] - end; - {eof, _} -> - file:close(Fd), - []; - _ -> - F(F, Fd) - end - end, - fun() -> - ErlFiles = filelib:wildcard("$(DEPS_DIR)/$(1)/src/*.erl"), - First0 = lists:usort(lists:flatten([begin - {ok, Fd} = file:open(F, [read]), - FindFirst(FindFirst, Fd) - end || F <- ErlFiles])), - First = lists:flatten([begin - {ok, Fd} = file:open("$(DEPS_DIR)/$(1)/src/" ++ atom_to_list(M) ++ ".erl", [read]), - FindFirst(FindFirst, Fd) - end || M <- First0, lists:member("$(DEPS_DIR)/$(1)/src/" ++ atom_to_list(M) ++ ".erl", ErlFiles)]) ++ First0, - Write(["COMPILE_FIRST +=", [[" ", atom_to_list(M)] || M <- First, - lists:member("$(DEPS_DIR)/$(1)/src/" ++ atom_to_list(M) ++ ".erl", ErlFiles)], "\n"]) - end(), - Write("\n\nrebar_dep: preprocess pre-deps deps pre-app app\n"), - Write("\npreprocess::\n"), - Write("\npre-deps::\n"), - Write("\npre-app::\n"), - PatchHook = fun(Cmd) -> - case Cmd of - "make -C" ++ Cmd1 -> "$$$$\(MAKE) -C" ++ Escape(Cmd1); - "gmake -C" ++ Cmd1 -> "$$$$\(MAKE) -C" ++ Escape(Cmd1); - "make " ++ Cmd1 -> "$$$$\(MAKE) -f Makefile.orig.mk " ++ Escape(Cmd1); - "gmake " ++ Cmd1 -> "$$$$\(MAKE) -f Makefile.orig.mk " ++ Escape(Cmd1); - _ -> Escape(Cmd) - end - end, - fun() -> - case lists:keyfind(pre_hooks, 1, Conf) of - false -> ok; - {_, Hooks} -> - [case H of - {'get-deps', Cmd} -> - Write("\npre-deps::\n\t" ++ PatchHook(Cmd) ++ "\n"); - {compile, Cmd} -> - Write("\npre-app::\n\tCC=$$$$\(CC) " ++ PatchHook(Cmd) ++ "\n"); - {Regex, compile, Cmd} -> - case rebar_utils:is_arch(Regex) of - true -> Write("\npre-app::\n\tCC=$$$$\(CC) " ++ PatchHook(Cmd) ++ "\n"); - false -> ok - end; - _ -> ok - end || H <- Hooks] - end - end(), - ShellToMk = fun(V) -> - re:replace(re:replace(V, "(\\\\$$$$)(\\\\w*)", "\\\\1(\\\\2)", [global]), - "-Werror\\\\b", "", [{return, list}, global]) - end, - PortSpecs = fun() -> - case lists:keyfind(port_specs, 1, Conf) of - false -> - case filelib:is_dir("$(DEPS_DIR)/$(1)/c_src") of - false -> []; - true -> - [{"priv/" ++ proplists:get_value(so_name, Conf, "$(1)_drv.so"), - proplists:get_value(port_sources, Conf, ["c_src/*.c"]), []}] - end; - {_, Specs} -> - lists:flatten([case S of - {Output, Input} -> {ShellToMk(Output), Input, []}; - {Regex, Output, Input} -> - case rebar_utils:is_arch(Regex) of - true -> {ShellToMk(Output), Input, []}; - false -> [] - end; - {Regex, Output, Input, [{env, Env}]} -> - case rebar_utils:is_arch(Regex) of - true -> {ShellToMk(Output), Input, Env}; - false -> [] - end - end || S <- Specs]) - end - end(), - PortSpecWrite = fun (Text) -> - file:write_file("$(DEPS_DIR)/$(1)/c_src/Makefile.erlang.mk", Text, [append]) - end, - case PortSpecs of - [] -> ok; - _ -> - Write("\npre-app::\n\t$$$$\(MAKE) -f c_src/Makefile.erlang.mk\n"), - PortSpecWrite(io_lib:format("ERL_CFLAGS = -finline-functions -Wall -fPIC -I ~s/erts-~s/include -I ~s\n", - [code:root_dir(), erlang:system_info(version), code:lib_dir(erl_interface, include)])), - PortSpecWrite(io_lib:format("ERL_LDFLAGS = -L ~s -lerl_interface -lei\n", - [code:lib_dir(erl_interface, lib)])), - [PortSpecWrite(["\n", E, "\n"]) || E <- OsEnv], - FilterEnv = fun(Env) -> - lists:flatten([case E of - {_, _} -> E; - {Regex, K, V} -> - case rebar_utils:is_arch(Regex) of - true -> {K, V}; - false -> [] - end - end || E <- Env]) - end, - MergeEnv = fun(Env) -> - lists:foldl(fun ({K, V}, Acc) -> - case lists:keyfind(K, 1, Acc) of - false -> [{K, rebar_utils:expand_env_variable(V, K, "")}|Acc]; - {_, V0} -> [{K, rebar_utils:expand_env_variable(V, K, V0)}|Acc] - end - end, [], Env) - end, - PortEnv = case lists:keyfind(port_env, 1, Conf) of - false -> []; - {_, PortEnv0} -> FilterEnv(PortEnv0) - end, - PortSpec = fun ({Output, Input0, Env}) -> - filelib:ensure_dir("$(DEPS_DIR)/$(1)/" ++ Output), - Input = [[" ", I] || I <- Input0], - PortSpecWrite([ - [["\n", K, " = ", ShellToMk(V)] || {K, V} <- lists:reverse(MergeEnv(PortEnv))], - case $(PLATFORM) of - darwin -> "\n\nLDFLAGS += -flat_namespace -undefined suppress"; - _ -> "" - end, - "\n\nall:: ", Output, "\n\n", - "%.o: %.c\n\t$$$$\(CC) -c -o $$$$\@ $$$$\< $$$$\(CFLAGS) $$$$\(ERL_CFLAGS) $$$$\(DRV_CFLAGS) $$$$\(EXE_CFLAGS)\n\n", - "%.o: %.C\n\t$$$$\(CXX) -c -o $$$$\@ $$$$\< $$$$\(CXXFLAGS) $$$$\(ERL_CFLAGS) $$$$\(DRV_CFLAGS) $$$$\(EXE_CFLAGS)\n\n", - "%.o: %.cc\n\t$$$$\(CXX) -c -o $$$$\@ $$$$\< $$$$\(CXXFLAGS) $$$$\(ERL_CFLAGS) $$$$\(DRV_CFLAGS) $$$$\(EXE_CFLAGS)\n\n", - "%.o: %.cpp\n\t$$$$\(CXX) -c -o $$$$\@ $$$$\< $$$$\(CXXFLAGS) $$$$\(ERL_CFLAGS) $$$$\(DRV_CFLAGS) $$$$\(EXE_CFLAGS)\n\n", - [[Output, ": ", K, " = ", ShellToMk(V), "\n"] || {K, V} <- lists:reverse(MergeEnv(FilterEnv(Env)))], - Output, ": $$$$\(foreach ext,.c .C .cc .cpp,", - "$$$$\(patsubst %$$$$\(ext),%.o,$$$$\(filter %$$$$\(ext),$$$$\(wildcard", Input, "))))\n", - "\t$$$$\(CC) -o $$$$\@ $$$$\? $$$$\(LDFLAGS) $$$$\(ERL_LDFLAGS) $$$$\(DRV_LDFLAGS) $$$$\(EXE_LDFLAGS)", - case filename:extension(Output) of - [] -> "\n"; - _ -> " -shared\n" - end]) - end, - [PortSpec(S) || S <- PortSpecs] - end, - Write("\ninclude $(ERLANG_MK_FILENAME)"), - RunPlugin = fun(Plugin, Step) -> - case erlang:function_exported(Plugin, Step, 2) of - false -> ok; - true -> - c:cd("$(DEPS_DIR)/$(1)/"), - Ret = Plugin:Step({config, "", Conf, dict:new(), dict:new(), dict:new(), - dict:store(base_dir, "", dict:new())}, undefined), - io:format("rebar plugin ~p step ~p ret ~p~n", [Plugin, Step, Ret]) - end - end, - fun() -> - case lists:keyfind(plugins, 1, Conf) of - false -> ok; - {_, Plugins} -> - [begin - case lists:keyfind(deps, 1, Conf) of - false -> ok; - {_, Deps} -> - case lists:keyfind(P, 1, Deps) of - false -> ok; - _ -> - Path = "$(DEPS_DIR)/" ++ atom_to_list(P), - io:format("~s", [os:cmd("$(MAKE) -C $(DEPS_DIR)/$(1) " ++ Path)]), - io:format("~s", [os:cmd("$(MAKE) -C " ++ Path ++ " IS_DEP=1")]), - code:add_patha(Path ++ "/ebin") - end - end - end || P <- Plugins], - [case code:load_file(P) of - {module, P} -> ok; - _ -> - case lists:keyfind(plugin_dir, 1, Conf) of - false -> ok; - {_, PluginsDir} -> - ErlFile = "$(DEPS_DIR)/$(1)/" ++ PluginsDir ++ "/" ++ atom_to_list(P) ++ ".erl", - {ok, P, Bin} = compile:file(ErlFile, [binary]), - {module, P} = code:load_binary(P, ErlFile, Bin) - end - end || P <- Plugins], - [RunPlugin(P, preprocess) || P <- Plugins], - [RunPlugin(P, pre_compile) || P <- Plugins] - end - end(), - halt() -endef - -define dep_autopatch_app.erl - UpdateModules = fun(App) -> - case filelib:is_regular(App) of - false -> ok; - true -> - {ok, [{application, $(1), L0}]} = file:consult(App), - Mods = filelib:fold_files("$(DEPS_DIR)/$(1)/src", "\\\\.erl$$$$", true, - fun (F, Acc) -> [list_to_atom(filename:rootname(filename:basename(F)))|Acc] end, []), - L = lists:keystore(modules, 1, L0, {modules, Mods}), - ok = file:write_file(App, io_lib:format("~p.~n", [{application, $(1), L}])) - end - end, - UpdateModules("$(DEPS_DIR)/$(1)/ebin/$(1).app"), - halt() -endef - -define dep_autopatch_appsrc.erl - AppSrcOut = "$(DEPS_DIR)/$(1)/src/$(1).app.src", - AppSrcIn = case filelib:is_regular(AppSrcOut) of false -> "$(DEPS_DIR)/$(1)/ebin/$(1).app"; true -> AppSrcOut end, - case filelib:is_regular(AppSrcIn) of - false -> ok; - true -> - {ok, [{application, $(1), L0}]} = file:consult(AppSrcIn), - L1 = lists:keystore(modules, 1, L0, {modules, []}), - L2 = case lists:keyfind(vsn, 1, L1) of {_, git} -> lists:keyreplace(vsn, 1, L1, {vsn, "git"}); _ -> L1 end, - L3 = case lists:keyfind(registered, 1, L2) of false -> [{registered, []}|L2]; _ -> L2 end, - ok = file:write_file(AppSrcOut, io_lib:format("~p.~n", [{application, $(1), L3}])), - case AppSrcOut of AppSrcIn -> ok; _ -> ok = file:delete(AppSrcIn) end - end, - halt() -endef - -define dep_fetch_git - git clone -q -n -- $(call dep_repo,$(1)) $(DEPS_DIR)/$(call dep_name,$(1)); \ - cd $(DEPS_DIR)/$(call dep_name,$(1)) && git checkout -q $(call dep_commit,$(1)); -endef - -define dep_fetch_hg - hg clone -q -U $(call dep_repo,$(1)) $(DEPS_DIR)/$(call dep_name,$(1)); \ - cd $(DEPS_DIR)/$(call dep_name,$(1)) && hg update -q $(call dep_commit,$(1)); -endef - -define dep_fetch_svn - svn checkout -q $(call dep_repo,$(1)) $(DEPS_DIR)/$(call dep_name,$(1)); -endef - -define dep_fetch_cp - cp -R $(call dep_repo,$(1)) $(DEPS_DIR)/$(call dep_name,$(1)); -endef - -define dep_fetch_hex.erl - ssl:start(), - inets:start(), - {ok, {{_, 200, _}, _, Body}} = httpc:request(get, - {"https://s3.amazonaws.com/s3.hex.pm/tarballs/$(1)-$(2).tar", []}, - [], [{body_format, binary}]), - {ok, Files} = erl_tar:extract({binary, Body}, [memory]), - {_, Source} = lists:keyfind("contents.tar.gz", 1, Files), - ok = erl_tar:extract({binary, Source}, [{cwd, "$(DEPS_DIR)/$(1)"}, compressed]), - halt() -endef - -# Hex only has a package version. No need to look in the Erlang.mk packages. -define dep_fetch_hex - $(call erlang,$(call dep_fetch_hex.erl,$(1),$(strip $(word 2,$(dep_$(1)))))); -endef - -define dep_fetch_fail - echo "Unknown or invalid dependency: $(1). Please consult the erlang.mk README for instructions." >&2; \ - exit 78; -endef - -# Kept for compatibility purposes with older Erlang.mk configuration. -define dep_fetch_legacy - $(warning WARNING: '$(1)' dependency configuration uses deprecated format.) \ - git clone -q -n -- $(word 1,$(dep_$(1))) $(DEPS_DIR)/$(1); \ - cd $(DEPS_DIR)/$(1) && git checkout -q $(if $(word 2,$(dep_$(1))),$(word 2,$(dep_$(1))),master); -endef - -define dep_fetch - $(if $(dep_$(1)), \ - $(if $(dep_fetch_$(word 1,$(dep_$(1)))), \ - $(word 1,$(dep_$(1))), \ - legacy), \ - $(if $(filter $(1),$(PACKAGES)), \ - $(pkg_$(1)_fetch), \ - fail)) -endef - -dep_name = $(if $(dep_$(1)),$(1),$(pkg_$(1)_name)) -dep_repo = $(patsubst git://github.com/%,https://github.com/%, \ - $(if $(dep_$(1)),$(word 2,$(dep_$(1))),$(pkg_$(1)_repo))) -dep_commit = $(if $(dep_$(1)),$(word 3,$(dep_$(1))),$(pkg_$(1)_commit)) - -define dep_target -$(DEPS_DIR)/$(1): - $(verbose) mkdir -p $(DEPS_DIR) - $(dep_verbose) $(call dep_fetch_$(strip $(call dep_fetch,$(1))),$(1)) - $(verbose) if [ -f $(DEPS_DIR)/$(1)/configure.ac -o -f $(DEPS_DIR)/$(1)/configure.in ]; then \ - echo " AUTO " $(1); \ - cd $(DEPS_DIR)/$(1) && autoreconf -Wall -vif -I m4; \ - fi - - $(verbose) if [ -f $(DEPS_DIR)/$(1)/configure ]; then \ - echo " CONF " $(1); \ - cd $(DEPS_DIR)/$(1) && ./configure; \ - fi -ifeq ($(filter $(1),$(NO_AUTOPATCH)),) - $(verbose) if [ "$(1)" = "amqp_client" -a "$(RABBITMQ_CLIENT_PATCH)" ]; then \ - if [ ! -d $(DEPS_DIR)/rabbitmq-codegen ]; then \ - echo " PATCH Downloading rabbitmq-codegen"; \ - git clone https://github.com/rabbitmq/rabbitmq-codegen.git $(DEPS_DIR)/rabbitmq-codegen; \ - fi; \ - if [ ! -d $(DEPS_DIR)/rabbitmq-server ]; then \ - echo " PATCH Downloading rabbitmq-server"; \ - git clone https://github.com/rabbitmq/rabbitmq-server.git $(DEPS_DIR)/rabbitmq-server; \ - fi; \ - ln -s $(DEPS_DIR)/amqp_client/deps/rabbit_common-0.0.0 $(DEPS_DIR)/rabbit_common; \ - elif [ "$(1)" = "rabbit" -a "$(RABBITMQ_SERVER_PATCH)" ]; then \ - if [ ! -d $(DEPS_DIR)/rabbitmq-codegen ]; then \ - echo " PATCH Downloading rabbitmq-codegen"; \ - git clone https://github.com/rabbitmq/rabbitmq-codegen.git $(DEPS_DIR)/rabbitmq-codegen; \ - fi \ - else \ - $(call dep_autopatch,$(1)) \ - fi -endif -endef - -$(foreach dep,$(DEPS),$(eval $(call dep_target,$(dep)))) - -distclean-deps: - $(gen_verbose) rm -rf $(DEPS_DIR) - -# Copyright (c) 2015, Loïc Hoguin -# This file is part of erlang.mk and subject to the terms of the ISC License. - -# Verbosity. - -proto_verbose_0 = @echo " PROTO " $(filter %.proto,$(?F)); -proto_verbose = $(proto_verbose_$(V)) - -# Core targets. - -define compile_proto - $(verbose) mkdir -p ebin/ include/ - $(proto_verbose) $(call erlang,$(call compile_proto.erl,$(1))) - $(proto_verbose) erlc +debug_info -o ebin/ ebin/*.erl - $(verbose) rm ebin/*.erl -endef - -define compile_proto.erl - [begin - Dir = filename:dirname(filename:dirname(F)), - protobuffs_compile:generate_source(F, - [{output_include_dir, Dir ++ "/include"}, - {output_src_dir, Dir ++ "/ebin"}]) - end || F <- string:tokens("$(1)", " ")], - halt(). -endef - -ifneq ($(wildcard src/),) -ebin/$(PROJECT).app:: $(sort $(call core_find,src/,*.proto)) - $(if $(strip $?),$(call compile_proto,$?)) -endif - -# Copyright (c) 2013-2015, Loïc Hoguin -# This file is part of erlang.mk and subject to the terms of the ISC License. - -.PHONY: clean-app - -# Configuration. - -ERLC_OPTS ?= -Werror +debug_info +warn_export_vars +warn_shadow_vars \ - +warn_obsolete_guard # +bin_opt_info +warn_export_all +warn_missing_spec -COMPILE_FIRST ?= -COMPILE_FIRST_PATHS = $(addprefix src/,$(addsuffix .erl,$(COMPILE_FIRST))) -ERLC_EXCLUDE ?= -ERLC_EXCLUDE_PATHS = $(addprefix src/,$(addsuffix .erl,$(ERLC_EXCLUDE))) - -ERLC_MIB_OPTS ?= -COMPILE_MIB_FIRST ?= -COMPILE_MIB_FIRST_PATHS = $(addprefix mibs/,$(addsuffix .mib,$(COMPILE_MIB_FIRST))) - -# Verbosity. - -app_verbose_0 = @echo " APP " $(PROJECT); -app_verbose = $(app_verbose_$(V)) - -appsrc_verbose_0 = @echo " APP " $(PROJECT).app.src; -appsrc_verbose = $(appsrc_verbose_$(V)) - -erlc_verbose_0 = @echo " ERLC " $(filter-out $(patsubst %,%.erl,$(ERLC_EXCLUDE)),\ - $(filter %.erl %.core,$(?F))); -erlc_verbose = $(erlc_verbose_$(V)) - -xyrl_verbose_0 = @echo " XYRL " $(filter %.xrl %.yrl,$(?F)); -xyrl_verbose = $(xyrl_verbose_$(V)) - -asn1_verbose_0 = @echo " ASN1 " $(filter %.asn1,$(?F)); -asn1_verbose = $(asn1_verbose_$(V)) - -mib_verbose_0 = @echo " MIB " $(filter %.bin %.mib,$(?F)); -mib_verbose = $(mib_verbose_$(V)) - -# Targets. - -ifeq ($(wildcard ebin/test),) -app:: app-build -else -app:: clean app-build -endif - -ifeq ($(wildcard src/$(PROJECT)_app.erl),) -define app_file -{application, $(PROJECT), [ - {description, "$(PROJECT_DESCRIPTION)"}, - {vsn, "$(PROJECT_VERSION)"}, - {id, "$(1)"}, - {modules, [$(call comma_list,$(2))]}, - {registered, []}, - {applications, [$(call comma_list,kernel stdlib $(OTP_DEPS) $(DEPS))]} -]}. -endef -else -define app_file -{application, $(PROJECT), [ - {description, "$(PROJECT_DESCRIPTION)"}, - {vsn, "$(PROJECT_VERSION)"}, - {id, "$(1)"}, - {modules, [$(call comma_list,$(2))]}, - {registered, [$(call comma_list,$(PROJECT)_sup $(PROJECT_REGISTERED))]}, - {applications, [$(call comma_list,kernel stdlib $(OTP_DEPS) $(DEPS))]}, - {mod, {$(PROJECT)_app, []}} -]}. -endef -endif - -app-build: erlc-include ebin/$(PROJECT).app - $(eval GITDESCRIBE := $(shell git describe --dirty --abbrev=7 --tags --always --first-parent 2>/dev/null || true)) - $(eval MODULES := $(patsubst %,'%',$(sort $(notdir $(basename $(shell find ebin -type f -name *.beam)))))) -ifeq ($(wildcard src/$(PROJECT).app.src),) - $(app_verbose) echo $(subst $(newline),,$(subst ",\",$(call app_file,$(GITDESCRIBE),$(MODULES)))) \ - > ebin/$(PROJECT).app -else - $(verbose) if [ -z "$$(grep -E '^[^%]*{\s*modules\s*,' src/$(PROJECT).app.src)" ]; then \ - echo "Empty modules entry not found in $(PROJECT).app.src. Please consult the erlang.mk README for instructions." >&2; \ - exit 1; \ - fi - $(appsrc_verbose) cat src/$(PROJECT).app.src \ - | sed "s/{[[:space:]]*modules[[:space:]]*,[[:space:]]*\[\]}/{modules, \[$(call comma_list,$(MODULES))\]}/" \ - | sed "s/{id,[[:space:]]*\"git\"}/{id, \"$(GITDESCRIBE)\"}/" \ - > ebin/$(PROJECT).app -endif - -erlc-include: - - $(verbose) if [ -d ebin/ ]; then \ - find include/ src/ -type f -name \*.hrl -newer ebin -exec touch $(shell find src/ -type f -name "*.erl") \; 2>/dev/null || printf ''; \ - fi - -define compile_erl - $(erlc_verbose) erlc -v $(if $(IS_DEP),$(filter-out -Werror,$(ERLC_OPTS)),$(ERLC_OPTS)) -o ebin/ \ - -pa ebin/ -I include/ $(filter-out $(ERLC_EXCLUDE_PATHS),\ - $(COMPILE_FIRST_PATHS) $(1)) -endef - -define compile_xyrl - $(xyrl_verbose) erlc -v -o ebin/ $(1) - $(xyrl_verbose) erlc $(ERLC_OPTS) -o ebin/ ebin/*.erl - $(verbose) rm ebin/*.erl -endef - -define compile_asn1 - $(asn1_verbose) erlc -v -I include/ -o ebin/ $(1) - $(verbose) mv ebin/*.hrl include/ - $(verbose) mv ebin/*.asn1db include/ - $(verbose) rm ebin/*.erl -endef - -define compile_mib - $(mib_verbose) erlc -v $(ERLC_MIB_OPTS) -o priv/mibs/ \ - -I priv/mibs/ $(COMPILE_MIB_FIRST_PATHS) $(1) - $(mib_verbose) erlc -o include/ -- priv/mibs/*.bin -endef - -ifneq ($(wildcard src/),) -ebin/$(PROJECT).app:: - $(verbose) mkdir -p ebin/ - -ifneq ($(wildcard asn1/),) -ebin/$(PROJECT).app:: $(sort $(call core_find,asn1/,*.asn1)) - $(verbose) mkdir -p include - $(if $(strip $?),$(call compile_asn1,$?)) -endif - -ifneq ($(wildcard mibs/),) -ebin/$(PROJECT).app:: $(sort $(call core_find,mibs/,*.mib)) - $(verbose) mkdir -p priv/mibs/ include - $(if $(strip $?),$(call compile_mib,$?)) -endif - -ebin/$(PROJECT).app:: $(sort $(call core_find,src/,*.erl *.core)) - $(if $(strip $?),$(call compile_erl,$?)) - -ebin/$(PROJECT).app:: $(sort $(call core_find,src/,*.xrl *.yrl)) - $(if $(strip $?),$(call compile_xyrl,$?)) -endif - -clean:: clean-app - -clean-app: - $(gen_verbose) rm -rf ebin/ priv/mibs/ \ - $(addprefix include/,$(addsuffix .hrl,$(notdir $(basename $(call core_find,mibs/,*.mib))))) - -# Copyright (c) 2015, Viktor Söderqvist -# This file is part of erlang.mk and subject to the terms of the ISC License. - -.PHONY: docs-deps - -# Configuration. - -ALL_DOC_DEPS_DIRS = $(addprefix $(DEPS_DIR)/,$(DOC_DEPS)) - -# Targets. - -$(foreach dep,$(DOC_DEPS),$(eval $(call dep_target,$(dep)))) - -ifneq ($(SKIP_DEPS),) -doc-deps: -else -doc-deps: $(ALL_DOC_DEPS_DIRS) - $(verbose) for dep in $(ALL_DOC_DEPS_DIRS) ; do $(MAKE) -C $$dep; done -endif - -# Copyright (c) 2015, Loïc Hoguin -# This file is part of erlang.mk and subject to the terms of the ISC License. - -.PHONY: test-deps test-dir test-build clean-test-dir - -# Configuration. - -TEST_DIR ?= $(CURDIR)/test - -ALL_TEST_DEPS_DIRS = $(addprefix $(DEPS_DIR)/,$(TEST_DEPS)) - -TEST_ERLC_OPTS ?= +debug_info +warn_export_vars +warn_shadow_vars +warn_obsolete_guard -TEST_ERLC_OPTS += -DTEST=1 - -# Targets. - -$(foreach dep,$(TEST_DEPS),$(eval $(call dep_target,$(dep)))) - -ifneq ($(SKIP_DEPS),) -test-deps: -else -test-deps: $(ALL_TEST_DEPS_DIRS) - $(verbose) for dep in $(ALL_TEST_DEPS_DIRS) ; do $(MAKE) -C $$dep IS_DEP=1; done -endif - -ifneq ($(wildcard $(TEST_DIR)),) -test-dir: - $(gen_verbose) erlc -v $(TEST_ERLC_OPTS) -I include/ -o $(TEST_DIR) \ - $(call core_find,$(TEST_DIR)/,*.erl) -pa ebin/ -endif - -ifeq ($(wildcard ebin/test),) -test-build:: ERLC_OPTS=$(TEST_ERLC_OPTS) -test-build:: clean deps test-deps - $(verbose) $(MAKE) --no-print-directory app-build test-dir ERLC_OPTS="$(TEST_ERLC_OPTS)" - $(gen_verbose) touch ebin/test -else -test-build:: ERLC_OPTS=$(TEST_ERLC_OPTS) -test-build:: deps test-deps - $(verbose) $(MAKE) --no-print-directory app-build test-dir ERLC_OPTS="$(TEST_ERLC_OPTS)" -endif - -clean:: clean-test-dir - -clean-test-dir: -ifneq ($(wildcard $(TEST_DIR)/*.beam),) - $(gen_verbose) rm -f $(TEST_DIR)/*.beam -endif - -# Copyright (c) 2015, Loïc Hoguin -# This file is part of erlang.mk and subject to the terms of the ISC License. - -.PHONY: asciidoc asciidoc-guide asciidoc-manual install-asciidoc distclean-asciidoc - -MAN_INSTALL_PATH ?= /usr/local/share/man -MAN_SECTIONS ?= 3 7 - -docs:: asciidoc - -asciidoc: distclean-asciidoc doc-deps asciidoc-guide asciidoc-manual - -ifeq ($(wildcard doc/src/guide/book.asciidoc),) -asciidoc-guide: -else -asciidoc-guide: - a2x -v -f pdf doc/src/guide/book.asciidoc && mv doc/src/guide/book.pdf doc/guide.pdf - a2x -v -f chunked doc/src/guide/book.asciidoc && mv doc/src/guide/book.chunked/ doc/html/ -endif - -ifeq ($(wildcard doc/src/manual/*.asciidoc),) -asciidoc-manual: -else -asciidoc-manual: - for f in doc/src/manual/*.asciidoc ; do \ - a2x -v -f manpage $$f ; \ - done - for s in $(MAN_SECTIONS); do \ - mkdir -p doc/man$$s/ ; \ - mv doc/src/manual/*.$$s doc/man$$s/ ; \ - gzip doc/man$$s/*.$$s ; \ - done - -install-docs:: install-asciidoc - -install-asciidoc: asciidoc-manual - for s in $(MAN_SECTIONS); do \ - mkdir -p $(MAN_INSTALL_PATH)/man$$s/ ; \ - install -g 0 -o 0 -m 0644 doc/man$$s/*.gz $(MAN_INSTALL_PATH)/man$$s/ ; \ - done -endif - -distclean:: distclean-asciidoc - -distclean-asciidoc: - $(gen_verbose) rm -rf doc/html/ doc/guide.pdf doc/man3/ doc/man7/ - -# Copyright (c) 2014-2015, Loïc Hoguin -# This file is part of erlang.mk and subject to the terms of the ISC License. - -.PHONY: bootstrap bootstrap-lib bootstrap-rel new list-templates - -# Core targets. - -help:: - $(verbose) printf "%s\n" "" \ - "Bootstrap targets:" \ - " bootstrap Generate a skeleton of an OTP application" \ - " bootstrap-lib Generate a skeleton of an OTP library" \ - " bootstrap-rel Generate the files needed to build a release" \ - " new t=TPL n=NAME Generate a module NAME based on the template TPL" \ - " list-templates List available templates" - -# Bootstrap templates. - -define bs_appsrc -{application, $(PROJECT), [ - {description, ""}, - {vsn, "0.1.0"}, - {id, "git"}, - {modules, []}, - {registered, []}, - {applications, [ - kernel, - stdlib - ]}, - {mod, {$(PROJECT)_app, []}}, - {env, []} -]}. -endef - -define bs_appsrc_lib -{application, $(PROJECT), [ - {description, ""}, - {vsn, "0.1.0"}, - {id, "git"}, - {modules, []}, - {registered, []}, - {applications, [ - kernel, - stdlib - ]} -]}. -endef - -ifdef SP -define bs_Makefile -PROJECT = $(PROJECT) - -# Whitespace to be used when creating files from templates. -SP = $(SP) - -include erlang.mk -endef -else -define bs_Makefile -PROJECT = $(PROJECT) -include erlang.mk -endef -endif - -define bs_app --module($(PROJECT)_app). --behaviour(application). - --export([start/2]). --export([stop/1]). - -start(_Type, _Args) -> - $(PROJECT)_sup:start_link(). - -stop(_State) -> - ok. -endef - -define bs_relx_config -{release, {$(PROJECT)_release, "1"}, [$(PROJECT)]}. -{extended_start_script, true}. -{sys_config, "rel/sys.config"}. -{vm_args, "rel/vm.args"}. -endef - -define bs_sys_config -[ -]. -endef - -define bs_vm_args --name $(PROJECT)@127.0.0.1 --setcookie $(PROJECT) --heart -endef - -# Normal templates. - -define tpl_supervisor --module($(n)). --behaviour(supervisor). - --export([start_link/0]). --export([init/1]). - -start_link() -> - supervisor:start_link({local, ?MODULE}, ?MODULE, []). - -init([]) -> - Procs = [], - {ok, {{one_for_one, 1, 5}, Procs}}. -endef - -define tpl_gen_server --module($(n)). --behaviour(gen_server). - -%% API. --export([start_link/0]). - -%% gen_server. --export([init/1]). --export([handle_call/3]). --export([handle_cast/2]). --export([handle_info/2]). --export([terminate/2]). --export([code_change/3]). - --record(state, { -}). - -%% API. - --spec start_link() -> {ok, pid()}. -start_link() -> - gen_server:start_link(?MODULE, [], []). - -%% gen_server. - -init([]) -> - {ok, #state{}}. - -handle_call(_Request, _From, State) -> - {reply, ignored, State}. - -handle_cast(_Msg, State) -> - {noreply, State}. - -handle_info(_Info, State) -> - {noreply, State}. - -terminate(_Reason, _State) -> - ok. - -code_change(_OldVsn, State, _Extra) -> - {ok, State}. -endef - -define tpl_cowboy_http --module($(n)). --behaviour(cowboy_http_handler). - --export([init/3]). --export([handle/2]). --export([terminate/3]). - --record(state, { -}). - -init(_, Req, _Opts) -> - {ok, Req, #state{}}. - -handle(Req, State=#state{}) -> - {ok, Req2} = cowboy_req:reply(200, Req), - {ok, Req2, State}. - -terminate(_Reason, _Req, _State) -> - ok. -endef - -define tpl_gen_fsm --module($(n)). --behaviour(gen_fsm). - -%% API. --export([start_link/0]). - -%% gen_fsm. --export([init/1]). --export([state_name/2]). --export([handle_event/3]). --export([state_name/3]). --export([handle_sync_event/4]). --export([handle_info/3]). --export([terminate/3]). --export([code_change/4]). - --record(state, { -}). - -%% API. - --spec start_link() -> {ok, pid()}. -start_link() -> - gen_fsm:start_link(?MODULE, [], []). - -%% gen_fsm. - -init([]) -> - {ok, state_name, #state{}}. - -state_name(_Event, StateData) -> - {next_state, state_name, StateData}. - -handle_event(_Event, StateName, StateData) -> - {next_state, StateName, StateData}. - -state_name(_Event, _From, StateData) -> - {reply, ignored, state_name, StateData}. - -handle_sync_event(_Event, _From, StateName, StateData) -> - {reply, ignored, StateName, StateData}. - -handle_info(_Info, StateName, StateData) -> - {next_state, StateName, StateData}. - -terminate(_Reason, _StateName, _StateData) -> - ok. - -code_change(_OldVsn, StateName, StateData, _Extra) -> - {ok, StateName, StateData}. -endef - -define tpl_cowboy_loop --module($(n)). --behaviour(cowboy_loop_handler). - --export([init/3]). --export([info/3]). --export([terminate/3]). - --record(state, { -}). - -init(_, Req, _Opts) -> - {loop, Req, #state{}, 5000, hibernate}. - -info(_Info, Req, State) -> - {loop, Req, State, hibernate}. - -terminate(_Reason, _Req, _State) -> - ok. -endef - -define tpl_cowboy_rest --module($(n)). - --export([init/3]). --export([content_types_provided/2]). --export([get_html/2]). - -init(_, _Req, _Opts) -> - {upgrade, protocol, cowboy_rest}. - -content_types_provided(Req, State) -> - {[{{<<"text">>, <<"html">>, '*'}, get_html}], Req, State}. - -get_html(Req, State) -> - {<<"This is REST!">>, Req, State}. -endef - -define tpl_cowboy_ws --module($(n)). --behaviour(cowboy_websocket_handler). - --export([init/3]). --export([websocket_init/3]). --export([websocket_handle/3]). --export([websocket_info/3]). --export([websocket_terminate/3]). - --record(state, { -}). - -init(_, _, _) -> - {upgrade, protocol, cowboy_websocket}. - -websocket_init(_, Req, _Opts) -> - Req2 = cowboy_req:compact(Req), - {ok, Req2, #state{}}. - -websocket_handle({text, Data}, Req, State) -> - {reply, {text, Data}, Req, State}; -websocket_handle({binary, Data}, Req, State) -> - {reply, {binary, Data}, Req, State}; -websocket_handle(_Frame, Req, State) -> - {ok, Req, State}. - -websocket_info(_Info, Req, State) -> - {ok, Req, State}. - -websocket_terminate(_Reason, _Req, _State) -> - ok. -endef - -define tpl_ranch_protocol --module($(n)). --behaviour(ranch_protocol). - --export([start_link/4]). --export([init/4]). - --type opts() :: []. --export_type([opts/0]). - --record(state, { - socket :: inet:socket(), - transport :: module() -}). - -start_link(Ref, Socket, Transport, Opts) -> - Pid = spawn_link(?MODULE, init, [Ref, Socket, Transport, Opts]), - {ok, Pid}. - --spec init(ranch:ref(), inet:socket(), module(), opts()) -> ok. -init(Ref, Socket, Transport, _Opts) -> - ok = ranch:accept_ack(Ref), - loop(#state{socket=Socket, transport=Transport}). - -loop(State) -> - loop(State). -endef - -# Plugin-specific targets. - -define render_template - $(verbose) echo "$${_$(1)}" > $(2) -endef - -ifndef WS -ifdef SP -WS = $(subst a,,a $(wordlist 1,$(SP),a a a a a a a a a a a a a a a a a a a a)) -else -WS = $(tab) -endif -endif - -$(foreach template,$(filter bs_% tpl_%,$(.VARIABLES)), \ - $(eval _$(template) = $$(subst $$(tab),$$(WS),$$($(template)))) \ - $(eval export _$(template))) - -bootstrap: -ifneq ($(wildcard src/),) - $(error Error: src/ directory already exists) -endif - $(call render_template,bs_Makefile,Makefile) - $(verbose) mkdir src/ - $(call render_template,bs_appsrc,src/$(PROJECT).app.src) - $(call render_template,bs_app,src/$(PROJECT)_app.erl) - $(eval n := $(PROJECT)_sup) - $(call render_template,tpl_supervisor,src/$(PROJECT)_sup.erl) - -bootstrap-lib: -ifneq ($(wildcard src/),) - $(error Error: src/ directory already exists) -endif - $(call render_template,bs_Makefile,Makefile) - $(verbose) mkdir src/ - $(call render_template,bs_appsrc_lib,src/$(PROJECT).app.src) - -bootstrap-rel: -ifneq ($(wildcard relx.config),) - $(error Error: relx.config already exists) -endif -ifneq ($(wildcard rel/),) - $(error Error: rel/ directory already exists) -endif - $(call render_template,bs_relx_config,relx.config) - $(verbose) mkdir rel/ - $(call render_template,bs_sys_config,rel/sys.config) - $(call render_template,bs_vm_args,rel/vm.args) - -new: -ifeq ($(wildcard src/),) - $(error Error: src/ directory does not exist) -endif -ifndef t - $(error Usage: $(MAKE) new t=TEMPLATE n=NAME) -endif -ifndef tpl_$(t) - $(error Unknown template) -endif -ifndef n - $(error Usage: $(MAKE) new t=TEMPLATE n=NAME) -endif - $(call render_template,tpl_$(t),src/$(n).erl) - -list-templates: - $(verbose) echo Available templates: $(sort $(patsubst tpl_%,%,$(filter tpl_%,$(.VARIABLES)))) - -# Copyright (c) 2014-2015, Loïc Hoguin -# This file is part of erlang.mk and subject to the terms of the ISC License. - -.PHONY: clean-c_src distclean-c_src-env - -# Configuration. - -C_SRC_DIR ?= $(CURDIR)/c_src -C_SRC_ENV ?= $(C_SRC_DIR)/env.mk -C_SRC_OUTPUT ?= $(CURDIR)/priv/$(PROJECT).so -C_SRC_TYPE ?= shared - -# System type and C compiler/flags. - -ifeq ($(PLATFORM),darwin) - CC ?= cc - CFLAGS ?= -O3 -std=c99 -arch x86_64 -finline-functions -Wall -Wmissing-prototypes - CXXFLAGS ?= -O3 -arch x86_64 -finline-functions -Wall - LDFLAGS ?= -arch x86_64 -flat_namespace -undefined suppress -else ifeq ($(PLATFORM),freebsd) - CC ?= cc - CFLAGS ?= -O3 -std=c99 -finline-functions -Wall -Wmissing-prototypes - CXXFLAGS ?= -O3 -finline-functions -Wall -else ifeq ($(PLATFORM),linux) - CC ?= gcc - CFLAGS ?= -O3 -std=c99 -finline-functions -Wall -Wmissing-prototypes - CXXFLAGS ?= -O3 -finline-functions -Wall -endif - -CFLAGS += -fPIC -I $(ERTS_INCLUDE_DIR) -I $(ERL_INTERFACE_INCLUDE_DIR) -CXXFLAGS += -fPIC -I $(ERTS_INCLUDE_DIR) -I $(ERL_INTERFACE_INCLUDE_DIR) - -LDLIBS += -L $(ERL_INTERFACE_LIB_DIR) -lerl_interface -lei - -ifeq ($(C_SRC_TYPE),shared) -LDFLAGS += -shared -endif - -# Verbosity. - -c_verbose_0 = @echo " C " $(?F); -c_verbose = $(c_verbose_$(V)) - -cpp_verbose_0 = @echo " CPP " $(?F); -cpp_verbose = $(cpp_verbose_$(V)) - -link_verbose_0 = @echo " LD " $(@F); -link_verbose = $(link_verbose_$(V)) - -# Targets. - -ifeq ($(wildcard $(C_SRC_DIR)),) -else ifneq ($(wildcard $(C_SRC_DIR)/Makefile),) -app:: app-c_src - -test-build:: app-c_src - -app-c_src: - $(MAKE) -C $(C_SRC_DIR) - -clean:: - $(MAKE) -C $(C_SRC_DIR) clean - -else - -ifeq ($(SOURCES),) -SOURCES := $(sort $(call core_find,$(C_SRC_DIR)/,*.c *.C *.cc *.cpp)) -endif -OBJECTS = $(addsuffix .o, $(basename $(SOURCES))) - -COMPILE_C = $(c_verbose) $(CC) $(CFLAGS) $(CPPFLAGS) -c -COMPILE_CPP = $(cpp_verbose) $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c - -app:: $(C_SRC_ENV) $(C_SRC_OUTPUT) - -test-build:: $(C_SRC_ENV) $(C_SRC_OUTPUT) - -$(C_SRC_OUTPUT): $(OBJECTS) - $(verbose) mkdir -p priv/ - $(link_verbose) $(CC) $(OBJECTS) $(LDFLAGS) $(LDLIBS) -o $(C_SRC_OUTPUT) - -%.o: %.c - $(COMPILE_C) $(OUTPUT_OPTION) $< - -%.o: %.cc - $(COMPILE_CPP) $(OUTPUT_OPTION) $< - -%.o: %.C - $(COMPILE_CPP) $(OUTPUT_OPTION) $< - -%.o: %.cpp - $(COMPILE_CPP) $(OUTPUT_OPTION) $< - -clean:: clean-c_src - -clean-c_src: - $(gen_verbose) rm -f $(C_SRC_OUTPUT) $(OBJECTS) - -endif - -ifneq ($(wildcard $(C_SRC_DIR)),) -$(C_SRC_ENV): - $(verbose) $(ERL) -eval "file:write_file(\"$(C_SRC_ENV)\", \ - io_lib:format( \ - \"ERTS_INCLUDE_DIR ?= ~s/erts-~s/include/~n\" \ - \"ERL_INTERFACE_INCLUDE_DIR ?= ~s~n\" \ - \"ERL_INTERFACE_LIB_DIR ?= ~s~n\", \ - [code:root_dir(), erlang:system_info(version), \ - code:lib_dir(erl_interface, include), \ - code:lib_dir(erl_interface, lib)])), \ - halt()." - -distclean:: distclean-c_src-env - -distclean-c_src-env: - $(gen_verbose) rm -f $(C_SRC_ENV) - --include $(C_SRC_ENV) -endif - -# Copyright (c) 2015, Loïc Hoguin -# This file is part of erlang.mk and subject to the terms of the ISC License. - -.PHONY: ci ci-setup distclean-kerl - -KERL ?= $(CURDIR)/kerl -export KERL - -KERL_URL ?= https://raw.githubusercontent.com/yrashk/kerl/master/kerl - -OTP_GIT ?= https://github.com/erlang/otp - -CI_INSTALL_DIR ?= $(HOME)/erlang -CI_OTP ?= - -ifeq ($(strip $(CI_OTP)),) -ci:: -else -ci:: $(addprefix ci-,$(CI_OTP)) - -ci-prepare: $(addprefix $(CI_INSTALL_DIR)/,$(CI_OTP)) - -ci-setup:: - -ci_verbose_0 = @echo " CI " $(1); -ci_verbose = $(ci_verbose_$(V)) - -define ci_target -ci-$(1): $(CI_INSTALL_DIR)/$(1) - $(ci_verbose) \ - PATH="$(CI_INSTALL_DIR)/$(1)/bin:$(PATH)" \ - CI_OTP_RELEASE="$(1)" \ - CT_OPTS="-label $(1)" \ - $(MAKE) clean ci-setup tests -endef - -$(foreach otp,$(CI_OTP),$(eval $(call ci_target,$(otp)))) - -define ci_otp_target -ifeq ($(wildcard $(CI_INSTALL_DIR)/$(1)),) -$(CI_INSTALL_DIR)/$(1): $(KERL) - $(KERL) build git $(OTP_GIT) $(1) $(1) - $(KERL) install $(1) $(CI_INSTALL_DIR)/$(1) -endif -endef - -$(foreach otp,$(CI_OTP),$(eval $(call ci_otp_target,$(otp)))) - -$(KERL): - $(gen_verbose) $(call core_http_get,$(KERL),$(KERL_URL)) - $(verbose) chmod +x $(KERL) - -help:: - $(verbose) printf "%s\n" "" \ - "Continuous Integration targets:" \ - " ci Run '$(MAKE) tests' on all configured Erlang versions." \ - "" \ - "The CI_OTP variable must be defined with the Erlang versions" \ - "that must be tested. For example: CI_OTP = OTP-17.3.4 OTP-17.5.3" - -distclean:: distclean-kerl - -distclean-kerl: - $(gen_verbose) rm -rf $(KERL) -endif - -# Copyright (c) 2013-2015, Loïc Hoguin -# This file is part of erlang.mk and subject to the terms of the ISC License. - -.PHONY: ct distclean-ct - -# Configuration. - -CT_OPTS ?= -ifneq ($(wildcard $(TEST_DIR)),) - CT_SUITES ?= $(sort $(subst _SUITE.erl,,$(notdir $(call core_find,$(TEST_DIR)/,*_SUITE.erl)))) -else - CT_SUITES ?= -endif - -# Core targets. - -tests:: ct - -distclean:: distclean-ct - -help:: - $(verbose) printf "%s\n" "" \ - "Common_test targets:" \ - " ct Run all the common_test suites for this project" \ - "" \ - "All your common_test suites have their associated targets." \ - "A suite named http_SUITE can be ran using the ct-http target." - -# Plugin-specific targets. - -CT_RUN = ct_run \ - -no_auto_compile \ - -noinput \ - -pa $(CURDIR)/ebin $(DEPS_DIR)/*/ebin $(TEST_DIR) \ - -dir $(TEST_DIR) \ - -logdir $(CURDIR)/logs - -ifeq ($(CT_SUITES),) -ct: -else -ct: test-build - $(verbose) mkdir -p $(CURDIR)/logs/ - $(gen_verbose) $(CT_RUN) -suite $(addsuffix _SUITE,$(CT_SUITES)) $(CT_OPTS) -endif - -define ct_suite_target -ct-$(1): test-build - $(verbose) mkdir -p $(CURDIR)/logs/ - $(gen_verbose) $(CT_RUN) -suite $(addsuffix _SUITE,$(1)) $(CT_OPTS) -endef - -$(foreach test,$(CT_SUITES),$(eval $(call ct_suite_target,$(test)))) - -distclean-ct: - $(gen_verbose) rm -rf $(CURDIR)/logs/ - -# Copyright (c) 2013-2015, Loïc Hoguin -# This file is part of erlang.mk and subject to the terms of the ISC License. - -.PHONY: plt distclean-plt dialyze - -# Configuration. - -DIALYZER_PLT ?= $(CURDIR)/.$(PROJECT).plt -export DIALYZER_PLT - -PLT_APPS ?= -DIALYZER_DIRS ?= --src -r src -DIALYZER_OPTS ?= -Werror_handling -Wrace_conditions \ - -Wunmatched_returns # -Wunderspecs - -# Core targets. - -check:: dialyze - -distclean:: distclean-plt - -help:: - $(verbose) printf "%s\n" "" \ - "Dialyzer targets:" \ - " plt Build a PLT file for this project" \ - " dialyze Analyze the project using Dialyzer" - -# Plugin-specific targets. - -$(DIALYZER_PLT): deps app - $(verbose) dialyzer --build_plt --apps erts kernel stdlib $(PLT_APPS) $(OTP_DEPS) $(ALL_DEPS_DIRS) - -plt: $(DIALYZER_PLT) - -distclean-plt: - $(gen_verbose) rm -f $(DIALYZER_PLT) - -ifneq ($(wildcard $(DIALYZER_PLT)),) -dialyze: -else -dialyze: $(DIALYZER_PLT) -endif - $(verbose) dialyzer --no_native $(DIALYZER_DIRS) $(DIALYZER_OPTS) - -# Copyright (c) 2013-2015, Loïc Hoguin -# This file is part of erlang.mk and subject to the terms of the ISC License. - -.PHONY: distclean-edoc edoc - -# Configuration. - -EDOC_OPTS ?= - -# Core targets. - -docs:: distclean-edoc edoc - -distclean:: distclean-edoc - -# Plugin-specific targets. - -edoc: doc-deps - $(gen_verbose) $(ERL) -eval 'edoc:application($(PROJECT), ".", [$(EDOC_OPTS)]), halt().' - -distclean-edoc: - $(gen_verbose) rm -f doc/*.css doc/*.html doc/*.png doc/edoc-info - -# Copyright (c) 2015, Erlang Solutions Ltd. -# This file is part of erlang.mk and subject to the terms of the ISC License. - -.PHONY: elvis distclean-elvis - -# Configuration. - -ELVIS_CONFIG ?= $(CURDIR)/elvis.config - -ELVIS ?= $(CURDIR)/elvis -export ELVIS - -ELVIS_URL ?= https://github.com/inaka/elvis/releases/download/0.2.5-beta2/elvis -ELVIS_CONFIG_URL ?= https://github.com/inaka/elvis/releases/download/0.2.5-beta2/elvis.config -ELVIS_OPTS ?= - -# Core targets. - -help:: - $(verbose) printf "%s\n" "" \ - "Elvis targets:" \ - " elvis Run Elvis using the local elvis.config or download the default otherwise" - -distclean:: distclean-elvis - -# Plugin-specific targets. - -$(ELVIS): - $(gen_verbose) $(call core_http_get,$(ELVIS),$(ELVIS_URL)) - $(verbose) chmod +x $(ELVIS) - -$(ELVIS_CONFIG): - $(verbose) $(call core_http_get,$(ELVIS_CONFIG),$(ELVIS_CONFIG_URL)) - -elvis: $(ELVIS) $(ELVIS_CONFIG) - $(verbose) $(ELVIS) rock -c $(ELVIS_CONFIG) $(ELVIS_OPTS) - -distclean-elvis: - $(gen_verbose) rm -rf $(ELVIS) - -# Copyright (c) 2013-2015, Loïc Hoguin -# This file is part of erlang.mk and subject to the terms of the ISC License. - -# Configuration. - -DTL_FULL_PATH ?= 0 -DTL_PATH ?= templates/ -DTL_SUFFIX ?= _dtl - -# Verbosity. - -dtl_verbose_0 = @echo " DTL " $(filter %.dtl,$(?F)); -dtl_verbose = $(dtl_verbose_$(V)) - -# Core targets. - -define erlydtl_compile.erl - [begin - Module0 = case $(DTL_FULL_PATH) of - 0 -> - filename:basename(F, ".dtl"); - 1 -> - "$(DTL_PATH)" ++ F2 = filename:rootname(F, ".dtl"), - re:replace(F2, "/", "_", [{return, list}, global]) - end, - Module = list_to_atom(string:to_lower(Module0) ++ "$(DTL_SUFFIX)"), - case erlydtl:compile(F, Module, [{out_dir, "ebin/"}, return_errors, {doc_root, "templates"}]) of - ok -> ok; - {ok, _} -> ok - end - end || F <- string:tokens("$(1)", " ")], - halt(). -endef - -ifneq ($(wildcard src/),) -ebin/$(PROJECT).app:: $(sort $(call core_find,$(DTL_PATH),*.dtl)) - $(if $(strip $?),\ - $(dtl_verbose) $(call erlang,$(call erlydtl_compile.erl,$?,-pa ebin/ $(DEPS_DIR)/erlydtl/ebin/))) -endif - -# Copyright (c) 2014 Dave Cottlehuber -# This file is part of erlang.mk and subject to the terms of the ISC License. - -.PHONY: distclean-escript escript - -# Configuration. - -ESCRIPT_NAME ?= $(PROJECT) -ESCRIPT_COMMENT ?= This is an -*- erlang -*- file - -ESCRIPT_BEAMS ?= "ebin/*", "deps/*/ebin/*" -ESCRIPT_SYS_CONFIG ?= "rel/sys.config" -ESCRIPT_EMU_ARGS ?= -pa . \ - -sasl errlog_type error \ - -escript main $(ESCRIPT_NAME) -ESCRIPT_SHEBANG ?= /usr/bin/env escript -ESCRIPT_STATIC ?= "deps/*/priv/**", "priv/**" - -# Core targets. - -distclean:: distclean-escript - -help:: - $(verbose) printf "%s\n" "" \ - "Escript targets:" \ - " escript Build an executable escript archive" \ - -# Plugin-specific targets. - -# Based on https://github.com/synrc/mad/blob/master/src/mad_bundle.erl -# Copyright (c) 2013 Maxim Sokhatsky, Synrc Research Center -# Modified MIT License, https://github.com/synrc/mad/blob/master/LICENSE : -# Software may only be used for the great good and the true happiness of all -# sentient beings. - -define ESCRIPT_RAW -'Read = fun(F) -> {ok, B} = file:read_file(filename:absname(F)), B end,'\ -'Files = fun(L) -> A = lists:concat([filelib:wildcard(X)||X<- L ]),'\ -' [F || F <- A, not filelib:is_dir(F) ] end,'\ -'Squash = fun(L) -> [{filename:basename(F), Read(F) } || F <- L ] end,'\ -'Zip = fun(A, L) -> {ok,{_,Z}} = zip:create(A, L, [{compress,all},memory]), Z end,'\ -'Ez = fun(Escript) ->'\ -' Static = Files([$(ESCRIPT_STATIC)]),'\ -' Beams = Squash(Files([$(ESCRIPT_BEAMS), $(ESCRIPT_SYS_CONFIG)])),'\ -' Archive = Beams ++ [{ "static.gz", Zip("static.gz", Static)}],'\ -' escript:create(Escript, [ $(ESCRIPT_OPTIONS)'\ -' {archive, Archive, [memory]},'\ -' {shebang, "$(ESCRIPT_SHEBANG)"},'\ -' {comment, "$(ESCRIPT_COMMENT)"},'\ -' {emu_args, " $(ESCRIPT_EMU_ARGS)"}'\ -' ]),'\ -' file:change_mode(Escript, 8#755)'\ -'end,'\ -'Ez("$(ESCRIPT_NAME)"),'\ -'halt().' -endef - -ESCRIPT_COMMAND = $(subst ' ',,$(ESCRIPT_RAW)) - -escript:: distclean-escript deps app - $(gen_verbose) $(ERL) -eval $(ESCRIPT_COMMAND) - -distclean-escript: - $(gen_verbose) rm -f $(ESCRIPT_NAME) - -# Copyright (c) 2014, Enrique Fernandez -# Copyright (c) 2015, Loïc Hoguin -# This file is contributed to erlang.mk and subject to the terms of the ISC License. - -.PHONY: eunit - -# Configuration - -EUNIT_OPTS ?= - -# Core targets. - -tests:: eunit - -help:: - $(verbose) printf "%s\n" "" \ - "EUnit targets:" \ - " eunit Run all the EUnit tests for this project" - -# Plugin-specific targets. - -define eunit.erl - case "$(COVER)" of - "" -> ok; - _ -> - case cover:compile_beam_directory("ebin") of - {error, _} -> halt(1); - _ -> ok - end - end, - case eunit:test([$(call comma_list,$(1))], [$(EUNIT_OPTS)]) of - ok -> ok; - error -> halt(2) - end, - case "$(COVER)" of - "" -> ok; - _ -> - cover:export("eunit.coverdata") - end, - halt() -endef - -EUNIT_EBIN_MODS = $(notdir $(basename $(call core_find,ebin/,*.beam))) -EUNIT_TEST_MODS = $(notdir $(basename $(call core_find,$(TEST_DIR)/,*.beam))) -EUNIT_MODS = $(foreach mod,$(EUNIT_EBIN_MODS) $(filter-out \ - $(patsubst %,%_tests,$(EUNIT_EBIN_MODS)),$(EUNIT_TEST_MODS)),{module,'$(mod)'}) - -eunit: test-build - $(gen_verbose) $(ERL) -pa $(TEST_DIR) $(DEPS_DIR)/*/ebin ebin \ - -eval "$(subst $(newline),,$(subst ",\",$(call eunit.erl,$(EUNIT_MODS))))" - -# Copyright (c) 2013-2015, Loïc Hoguin -# This file is part of erlang.mk and subject to the terms of the ISC License. - -.PHONY: relx-rel distclean-relx-rel distclean-relx run - -# Configuration. - -RELX_CONFIG ?= $(CURDIR)/relx.config - -RELX ?= $(CURDIR)/relx -export RELX - -RELX_URL ?= https://github.com/erlware/relx/releases/download/v2.0.0/relx -RELX_OPTS ?= -RELX_OUTPUT_DIR ?= _rel - -ifeq ($(firstword $(RELX_OPTS)),-o) - RELX_OUTPUT_DIR = $(word 2,$(RELX_OPTS)) -else - RELX_OPTS += -o $(RELX_OUTPUT_DIR) -endif - -# Core targets. - -ifeq ($(IS_DEP),) -ifneq ($(wildcard $(RELX_CONFIG)),) -rel:: distclean-relx-rel relx-rel -endif -endif - -distclean:: distclean-relx-rel distclean-relx - -# Plugin-specific targets. - -$(RELX): - $(gen_verbose) $(call core_http_get,$(RELX),$(RELX_URL)) - $(verbose) chmod +x $(RELX) - -relx-rel: $(RELX) - $(verbose) $(RELX) -c $(RELX_CONFIG) $(RELX_OPTS) - -distclean-relx-rel: - $(gen_verbose) rm -rf $(RELX_OUTPUT_DIR) - -distclean-relx: - $(gen_verbose) rm -rf $(RELX) - -# Run target. - -ifeq ($(wildcard $(RELX_CONFIG)),) -run: -else - -define get_relx_release.erl - {ok, Config} = file:consult("$(RELX_CONFIG)"), - {release, {Name, _}, _} = lists:keyfind(release, 1, Config), - io:format("~s", [Name]), - halt(0). -endef - -RELX_RELEASE = `$(call erlang,$(get_relx_release.erl))` - -run: all - $(verbose) $(RELX_OUTPUT_DIR)/$(RELX_RELEASE)/bin/$(RELX_RELEASE) console - -help:: - $(verbose) printf "%s\n" "" \ - "Relx targets:" \ - " run Compile the project, build the release and run it" - -endif - -# Copyright (c) 2014, M Robert Martin -# This file is contributed to erlang.mk and subject to the terms of the ISC License. - -.PHONY: shell - -# Configuration. - -SHELL_PATH ?= -pa $(CURDIR)/ebin $(DEPS_DIR)/*/ebin -SHELL_OPTS ?= - -ALL_SHELL_DEPS_DIRS = $(addprefix $(DEPS_DIR)/,$(SHELL_DEPS)) - -# Core targets - -help:: - $(verbose) printf "%s\n" "" \ - "Shell targets:" \ - " shell Run an erlang shell with SHELL_OPTS or reasonable default" - -# Plugin-specific targets. - -$(foreach dep,$(SHELL_DEPS),$(eval $(call dep_target,$(dep)))) - -build-shell-deps: $(ALL_SHELL_DEPS_DIRS) - $(verbose) for dep in $(ALL_SHELL_DEPS_DIRS) ; do $(MAKE) -C $$dep ; done - -shell: build-shell-deps - $(gen_verbose) erl $(SHELL_PATH) $(SHELL_OPTS) - -# Copyright (c) 2015, Loïc Hoguin -# This file is part of erlang.mk and subject to the terms of the ISC License. - -ifeq ($(filter triq,$(DEPS) $(TEST_DEPS)),triq) -.PHONY: triq - -# Targets. - -tests:: triq - -define triq_check.erl - code:add_pathsa(["$(CURDIR)/ebin", "$(DEPS_DIR)/*/ebin"]), - try - case $(1) of - all -> [true] =:= lists:usort([triq:check(M) || M <- [$(call comma_list,$(3))]]); - module -> triq:check($(2)); - function -> triq:check($(2)) - end - of - true -> halt(0); - _ -> halt(1) - catch error:undef -> - io:format("Undefined property or module~n"), - halt(0) - end. -endef - -ifdef t -ifeq (,$(findstring :,$(t))) -triq: test-build - $(verbose) $(call erlang,$(call triq_check.erl,module,$(t))) -else -triq: test-build - $(verbose) echo Testing $(t)/0 - $(verbose) $(call erlang,$(call triq_check.erl,function,$(t)())) -endif -else -triq: test-build - $(eval MODULES := $(patsubst %,'%',$(sort $(notdir $(basename $(wildcard ebin/*.beam)))))) - $(gen_verbose) $(call erlang,$(call triq_check.erl,all,undefined,$(MODULES))) -endif -endif - -# Copyright (c) 2015, Erlang Solutions Ltd. -# This file is part of erlang.mk and subject to the terms of the ISC License. - -.PHONY: xref distclean-xref - -# Configuration. - -ifeq ($(XREF_CONFIG),) - XREF_ARGS := -else - XREF_ARGS := -c $(XREF_CONFIG) -endif - -XREFR ?= $(CURDIR)/xrefr -export XREFR - -XREFR_URL ?= https://github.com/inaka/xref_runner/releases/download/0.2.2/xrefr - -# Core targets. - -help:: - $(verbose) printf "%s\n" "" \ - "Xref targets:" \ - " xref Run Xrefr using $XREF_CONFIG as config file if defined" - -distclean:: distclean-xref - -# Plugin-specific targets. - -$(XREFR): - $(gen_verbose) $(call core_http_get,$(XREFR),$(XREFR_URL)) - $(verbose) chmod +x $(XREFR) - -xref: deps app $(XREFR) - $(gen_verbose) $(XREFR) $(XREFR_ARGS) - -distclean-xref: - $(gen_verbose) rm -rf $(XREFR) - -# Copyright 2015, Viktor Söderqvist -# This file is part of erlang.mk and subject to the terms of the ISC License. - -COVER_REPORT_DIR = cover - -# Hook in coverage to ct - -ifdef COVER -ifdef CT_RUN -# All modules in 'ebin' -COVER_MODS = $(notdir $(basename $(call core_ls,ebin/*.beam))) - -test-build:: $(TEST_DIR)/ct.cover.spec - -$(TEST_DIR)/ct.cover.spec: - $(verbose) echo Cover mods: $(COVER_MODS) - $(gen_verbose) printf "%s\n" \ - '{incl_mods,[$(subst $(space),$(comma),$(COVER_MODS))]}.' \ - '{export,"$(CURDIR)/ct.coverdata"}.' > $@ - -CT_RUN += -cover $(TEST_DIR)/ct.cover.spec -endif -endif - -# Core targets - -ifdef COVER -ifneq ($(COVER_REPORT_DIR),) -tests:: - $(verbose) $(MAKE) --no-print-directory cover-report -endif -endif - -clean:: coverdata-clean - -ifneq ($(COVER_REPORT_DIR),) -distclean:: cover-report-clean -endif - -help:: - $(verbose) printf "%s\n" "" \ - "Cover targets:" \ - " cover-report Generate a HTML coverage report from previously collected" \ - " cover data." \ - " all.coverdata Merge {eunit,ct}.coverdata into one coverdata file." \ - "" \ - "If COVER=1 is set, coverage data is generated by the targets eunit and ct. The" \ - "target tests additionally generates a HTML coverage report from the combined" \ - "coverdata files from each of these testing tools. HTML reports can be disabled" \ - "by setting COVER_REPORT_DIR to empty." - -# Plugin specific targets - -COVERDATA = $(filter-out all.coverdata,$(wildcard *.coverdata)) - -.PHONY: coverdata-clean -coverdata-clean: - $(gen_verbose) rm -f *.coverdata ct.cover.spec - -# Merge all coverdata files into one. -all.coverdata: $(COVERDATA) - $(gen_verbose) $(ERL) -eval ' \ - $(foreach f,$(COVERDATA),cover:import("$(f)") == ok orelse halt(1),) \ - cover:export("$@"), halt(0).' - -# These are only defined if COVER_REPORT_DIR is non-empty. Set COVER_REPORT_DIR to -# empty if you want the coverdata files but not the HTML report. -ifneq ($(COVER_REPORT_DIR),) - -.PHONY: cover-report-clean cover-report - -cover-report-clean: - $(gen_verbose) rm -rf $(COVER_REPORT_DIR) - -ifeq ($(COVERDATA),) -cover-report: -else - -# Modules which include eunit.hrl always contain one line without coverage -# because eunit defines test/0 which is never called. We compensate for this. -EUNIT_HRL_MODS = $(subst $(space),$(comma),$(shell \ - grep -e '^\s*-include.*include/eunit\.hrl"' src/*.erl \ - | sed "s/^src\/\(.*\)\.erl:.*/'\1'/" | uniq)) - -define cover_report.erl - $(foreach f,$(COVERDATA),cover:import("$(f)") == ok orelse halt(1),) - Ms = cover:imported_modules(), - [cover:analyse_to_file(M, "$(COVER_REPORT_DIR)/" ++ atom_to_list(M) - ++ ".COVER.html", [html]) || M <- Ms], - Report = [begin {ok, R} = cover:analyse(M, module), R end || M <- Ms], - EunitHrlMods = [$(EUNIT_HRL_MODS)], - Report1 = [{M, {Y, case lists:member(M, EunitHrlMods) of - true -> N - 1; false -> N end}} || {M, {Y, N}} <- Report], - TotalY = lists:sum([Y || {_, {Y, _}} <- Report1]), - TotalN = lists:sum([N || {_, {_, N}} <- Report1]), - TotalPerc = round(100 * TotalY / (TotalY + TotalN)), - {ok, F} = file:open("$(COVER_REPORT_DIR)/index.html", [write]), - io:format(F, "~n" - "~n" - "Coverage report~n" - "~n", []), - io:format(F, "

Coverage

~n

Total: ~p%

~n", [TotalPerc]), - io:format(F, "~n", []), - [io:format(F, "" - "~n", - [M, M, round(100 * Y / (Y + N))]) || {M, {Y, N}} <- Report1], - How = "$(subst $(space),$(comma)$(space),$(basename $(COVERDATA)))", - Date = "$(shell date -u "+%Y-%m-%dT%H:%M:%SZ")", - io:format(F, "
ModuleCoverage
~p~p%
~n" - "

Generated using ~s and erlang.mk on ~s.

~n" - "", [How, Date]), - halt(). -endef - -cover-report: - $(gen_verbose) mkdir -p $(COVER_REPORT_DIR) - $(gen_verbose) $(call erlang,$(cover_report.erl)) - -endif -endif # ifneq ($(COVER_REPORT_DIR),) DELETED deps/cowlib/include/cow_inline.hrl Index: deps/cowlib/include/cow_inline.hrl ================================================================== --- deps/cowlib/include/cow_inline.hrl +++ /dev/null @@ -1,388 +0,0 @@ -%% Copyright (c) 2014, Loïc Hoguin -%% -%% Permission to use, copy, modify, and/or distribute this software for any -%% purpose with or without fee is hereby granted, provided that the above -%% copyright notice and this permission notice appear in all copies. -%% -%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - --ifndef(COW_INLINE_HRL). --define(COW_INLINE_HRL, 1). - -%% INLINE_LOWERCASE(Function, Rest, Acc, ...) -%% -%% To be included at the end of a case block. -%% Defined for up to 10 extra arguments. - --define(INLINE_LOWERCASE(Function, Rest, Acc), - $A -> Function(Rest, << Acc/binary, $a >>); - $B -> Function(Rest, << Acc/binary, $b >>); - $C -> Function(Rest, << Acc/binary, $c >>); - $D -> Function(Rest, << Acc/binary, $d >>); - $E -> Function(Rest, << Acc/binary, $e >>); - $F -> Function(Rest, << Acc/binary, $f >>); - $G -> Function(Rest, << Acc/binary, $g >>); - $H -> Function(Rest, << Acc/binary, $h >>); - $I -> Function(Rest, << Acc/binary, $i >>); - $J -> Function(Rest, << Acc/binary, $j >>); - $K -> Function(Rest, << Acc/binary, $k >>); - $L -> Function(Rest, << Acc/binary, $l >>); - $M -> Function(Rest, << Acc/binary, $m >>); - $N -> Function(Rest, << Acc/binary, $n >>); - $O -> Function(Rest, << Acc/binary, $o >>); - $P -> Function(Rest, << Acc/binary, $p >>); - $Q -> Function(Rest, << Acc/binary, $q >>); - $R -> Function(Rest, << Acc/binary, $r >>); - $S -> Function(Rest, << Acc/binary, $s >>); - $T -> Function(Rest, << Acc/binary, $t >>); - $U -> Function(Rest, << Acc/binary, $u >>); - $V -> Function(Rest, << Acc/binary, $v >>); - $W -> Function(Rest, << Acc/binary, $w >>); - $X -> Function(Rest, << Acc/binary, $x >>); - $Y -> Function(Rest, << Acc/binary, $y >>); - $Z -> Function(Rest, << Acc/binary, $z >>); - C -> Function(Rest, << Acc/binary, C >>) -). - --define(INLINE_LOWERCASE(Function, Rest, A0, Acc), - $A -> Function(Rest, A0, << Acc/binary, $a >>); - $B -> Function(Rest, A0, << Acc/binary, $b >>); - $C -> Function(Rest, A0, << Acc/binary, $c >>); - $D -> Function(Rest, A0, << Acc/binary, $d >>); - $E -> Function(Rest, A0, << Acc/binary, $e >>); - $F -> Function(Rest, A0, << Acc/binary, $f >>); - $G -> Function(Rest, A0, << Acc/binary, $g >>); - $H -> Function(Rest, A0, << Acc/binary, $h >>); - $I -> Function(Rest, A0, << Acc/binary, $i >>); - $J -> Function(Rest, A0, << Acc/binary, $j >>); - $K -> Function(Rest, A0, << Acc/binary, $k >>); - $L -> Function(Rest, A0, << Acc/binary, $l >>); - $M -> Function(Rest, A0, << Acc/binary, $m >>); - $N -> Function(Rest, A0, << Acc/binary, $n >>); - $O -> Function(Rest, A0, << Acc/binary, $o >>); - $P -> Function(Rest, A0, << Acc/binary, $p >>); - $Q -> Function(Rest, A0, << Acc/binary, $q >>); - $R -> Function(Rest, A0, << Acc/binary, $r >>); - $S -> Function(Rest, A0, << Acc/binary, $s >>); - $T -> Function(Rest, A0, << Acc/binary, $t >>); - $U -> Function(Rest, A0, << Acc/binary, $u >>); - $V -> Function(Rest, A0, << Acc/binary, $v >>); - $W -> Function(Rest, A0, << Acc/binary, $w >>); - $X -> Function(Rest, A0, << Acc/binary, $x >>); - $Y -> Function(Rest, A0, << Acc/binary, $y >>); - $Z -> Function(Rest, A0, << Acc/binary, $z >>); - C -> Function(Rest, A0, << Acc/binary, C >>) -). - --define(INLINE_LOWERCASE(Function, Rest, A0, A1, Acc), - $A -> Function(Rest, A0, A1, << Acc/binary, $a >>); - $B -> Function(Rest, A0, A1, << Acc/binary, $b >>); - $C -> Function(Rest, A0, A1, << Acc/binary, $c >>); - $D -> Function(Rest, A0, A1, << Acc/binary, $d >>); - $E -> Function(Rest, A0, A1, << Acc/binary, $e >>); - $F -> Function(Rest, A0, A1, << Acc/binary, $f >>); - $G -> Function(Rest, A0, A1, << Acc/binary, $g >>); - $H -> Function(Rest, A0, A1, << Acc/binary, $h >>); - $I -> Function(Rest, A0, A1, << Acc/binary, $i >>); - $J -> Function(Rest, A0, A1, << Acc/binary, $j >>); - $K -> Function(Rest, A0, A1, << Acc/binary, $k >>); - $L -> Function(Rest, A0, A1, << Acc/binary, $l >>); - $M -> Function(Rest, A0, A1, << Acc/binary, $m >>); - $N -> Function(Rest, A0, A1, << Acc/binary, $n >>); - $O -> Function(Rest, A0, A1, << Acc/binary, $o >>); - $P -> Function(Rest, A0, A1, << Acc/binary, $p >>); - $Q -> Function(Rest, A0, A1, << Acc/binary, $q >>); - $R -> Function(Rest, A0, A1, << Acc/binary, $r >>); - $S -> Function(Rest, A0, A1, << Acc/binary, $s >>); - $T -> Function(Rest, A0, A1, << Acc/binary, $t >>); - $U -> Function(Rest, A0, A1, << Acc/binary, $u >>); - $V -> Function(Rest, A0, A1, << Acc/binary, $v >>); - $W -> Function(Rest, A0, A1, << Acc/binary, $w >>); - $X -> Function(Rest, A0, A1, << Acc/binary, $x >>); - $Y -> Function(Rest, A0, A1, << Acc/binary, $y >>); - $Z -> Function(Rest, A0, A1, << Acc/binary, $z >>); - C -> Function(Rest, A0, A1, << Acc/binary, C >>) -). - --define(INLINE_LOWERCASE(Function, Rest, A0, A1, A2, Acc), - $A -> Function(Rest, A0, A1, A2, << Acc/binary, $a >>); - $B -> Function(Rest, A0, A1, A2, << Acc/binary, $b >>); - $C -> Function(Rest, A0, A1, A2, << Acc/binary, $c >>); - $D -> Function(Rest, A0, A1, A2, << Acc/binary, $d >>); - $E -> Function(Rest, A0, A1, A2, << Acc/binary, $e >>); - $F -> Function(Rest, A0, A1, A2, << Acc/binary, $f >>); - $G -> Function(Rest, A0, A1, A2, << Acc/binary, $g >>); - $H -> Function(Rest, A0, A1, A2, << Acc/binary, $h >>); - $I -> Function(Rest, A0, A1, A2, << Acc/binary, $i >>); - $J -> Function(Rest, A0, A1, A2, << Acc/binary, $j >>); - $K -> Function(Rest, A0, A1, A2, << Acc/binary, $k >>); - $L -> Function(Rest, A0, A1, A2, << Acc/binary, $l >>); - $M -> Function(Rest, A0, A1, A2, << Acc/binary, $m >>); - $N -> Function(Rest, A0, A1, A2, << Acc/binary, $n >>); - $O -> Function(Rest, A0, A1, A2, << Acc/binary, $o >>); - $P -> Function(Rest, A0, A1, A2, << Acc/binary, $p >>); - $Q -> Function(Rest, A0, A1, A2, << Acc/binary, $q >>); - $R -> Function(Rest, A0, A1, A2, << Acc/binary, $r >>); - $S -> Function(Rest, A0, A1, A2, << Acc/binary, $s >>); - $T -> Function(Rest, A0, A1, A2, << Acc/binary, $t >>); - $U -> Function(Rest, A0, A1, A2, << Acc/binary, $u >>); - $V -> Function(Rest, A0, A1, A2, << Acc/binary, $v >>); - $W -> Function(Rest, A0, A1, A2, << Acc/binary, $w >>); - $X -> Function(Rest, A0, A1, A2, << Acc/binary, $x >>); - $Y -> Function(Rest, A0, A1, A2, << Acc/binary, $y >>); - $Z -> Function(Rest, A0, A1, A2, << Acc/binary, $z >>); - C -> Function(Rest, A0, A1, A2, << Acc/binary, C >>) -). - --define(INLINE_LOWERCASE(Function, Rest, A0, A1, A2, A3, Acc), - $A -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $a >>); - $B -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $b >>); - $C -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $c >>); - $D -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $d >>); - $E -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $e >>); - $F -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $f >>); - $G -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $g >>); - $H -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $h >>); - $I -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $i >>); - $J -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $j >>); - $K -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $k >>); - $L -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $l >>); - $M -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $m >>); - $N -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $n >>); - $O -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $o >>); - $P -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $p >>); - $Q -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $q >>); - $R -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $r >>); - $S -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $s >>); - $T -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $t >>); - $U -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $u >>); - $V -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $v >>); - $W -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $w >>); - $X -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $x >>); - $Y -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $y >>); - $Z -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $z >>); - C -> Function(Rest, A0, A1, A2, A3, << Acc/binary, C >>) -). - --define(INLINE_LOWERCASE(Function, Rest, A0, A1, A2, A3, A4, Acc), - $A -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $a >>); - $B -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $b >>); - $C -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $c >>); - $D -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $d >>); - $E -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $e >>); - $F -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $f >>); - $G -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $g >>); - $H -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $h >>); - $I -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $i >>); - $J -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $j >>); - $K -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $k >>); - $L -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $l >>); - $M -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $m >>); - $N -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $n >>); - $O -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $o >>); - $P -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $p >>); - $Q -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $q >>); - $R -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $r >>); - $S -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $s >>); - $T -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $t >>); - $U -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $u >>); - $V -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $v >>); - $W -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $w >>); - $X -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $x >>); - $Y -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $y >>); - $Z -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $z >>); - C -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, C >>) -). - --define(INLINE_LOWERCASE(Function, Rest, A0, A1, A2, A3, A4, A5, Acc), - $A -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $a >>); - $B -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $b >>); - $C -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $c >>); - $D -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $d >>); - $E -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $e >>); - $F -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $f >>); - $G -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $g >>); - $H -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $h >>); - $I -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $i >>); - $J -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $j >>); - $K -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $k >>); - $L -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $l >>); - $M -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $m >>); - $N -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $n >>); - $O -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $o >>); - $P -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $p >>); - $Q -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $q >>); - $R -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $r >>); - $S -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $s >>); - $T -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $t >>); - $U -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $u >>); - $V -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $v >>); - $W -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $w >>); - $X -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $x >>); - $Y -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $y >>); - $Z -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $z >>); - C -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, C >>) -). - --define(INLINE_LOWERCASE(Function, Rest, A0, A1, A2, A3, A4, A5, A6, Acc), - $A -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $a >>); - $B -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $b >>); - $C -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $c >>); - $D -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $d >>); - $E -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $e >>); - $F -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $f >>); - $G -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $g >>); - $H -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $h >>); - $I -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $i >>); - $J -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $j >>); - $K -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $k >>); - $L -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $l >>); - $M -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $m >>); - $N -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $n >>); - $O -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $o >>); - $P -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $p >>); - $Q -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $q >>); - $R -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $r >>); - $S -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $s >>); - $T -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $t >>); - $U -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $u >>); - $V -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $v >>); - $W -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $w >>); - $X -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $x >>); - $Y -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $y >>); - $Z -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $z >>); - C -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, C >>) -). - --define(INLINE_LOWERCASE(Function, Rest, A0, A1, A2, A3, A4, A5, A6, A7, Acc), - $A -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $a >>); - $B -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $b >>); - $C -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $c >>); - $D -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $d >>); - $E -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $e >>); - $F -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $f >>); - $G -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $g >>); - $H -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $h >>); - $I -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $i >>); - $J -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $j >>); - $K -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $k >>); - $L -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $l >>); - $M -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $m >>); - $N -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $n >>); - $O -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $o >>); - $P -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $p >>); - $Q -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $q >>); - $R -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $r >>); - $S -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $s >>); - $T -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $t >>); - $U -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $u >>); - $V -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $v >>); - $W -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $w >>); - $X -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $x >>); - $Y -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $y >>); - $Z -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $z >>); - C -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, C >>) -). - --define(INLINE_LOWERCASE(Function, Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, Acc), - $A -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $a >>); - $B -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $b >>); - $C -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $c >>); - $D -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $d >>); - $E -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $e >>); - $F -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $f >>); - $G -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $g >>); - $H -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $h >>); - $I -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $i >>); - $J -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $j >>); - $K -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $k >>); - $L -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $l >>); - $M -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $m >>); - $N -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $n >>); - $O -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $o >>); - $P -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $p >>); - $Q -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $q >>); - $R -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $r >>); - $S -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $s >>); - $T -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $t >>); - $U -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $u >>); - $V -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $v >>); - $W -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $w >>); - $X -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $x >>); - $Y -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $y >>); - $Z -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $z >>); - C -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, C >>) -). - --define(INLINE_LOWERCASE(Function, Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, Acc), - $A -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $a >>); - $B -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $b >>); - $C -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $c >>); - $D -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $d >>); - $E -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $e >>); - $F -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $f >>); - $G -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $g >>); - $H -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $h >>); - $I -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $i >>); - $J -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $j >>); - $K -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $k >>); - $L -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $l >>); - $M -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $m >>); - $N -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $n >>); - $O -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $o >>); - $P -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $p >>); - $Q -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $q >>); - $R -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $r >>); - $S -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $s >>); - $T -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $t >>); - $U -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $u >>); - $V -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $v >>); - $W -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $w >>); - $X -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $x >>); - $Y -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $y >>); - $Z -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $z >>); - C -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, C >>) -). - -%% INLINE_LOWERCASE_BC(Bin) -%% -%% Lowercase the entire binary string in a binary comprehension. - --define(INLINE_LOWERCASE_BC(Bin), - << << case C of - $A -> $a; - $B -> $b; - $C -> $c; - $D -> $d; - $E -> $e; - $F -> $f; - $G -> $g; - $H -> $h; - $I -> $i; - $J -> $j; - $K -> $k; - $L -> $l; - $M -> $m; - $N -> $n; - $O -> $o; - $P -> $p; - $Q -> $q; - $R -> $r; - $S -> $s; - $T -> $t; - $U -> $u; - $V -> $v; - $W -> $w; - $X -> $x; - $Y -> $y; - $Z -> $z; - C -> C - end >> || << C >> <= Bin >>). - --endif. DELETED deps/cowlib/src/cow_cookie.erl Index: deps/cowlib/src/cow_cookie.erl ================================================================== --- deps/cowlib/src/cow_cookie.erl +++ /dev/null @@ -1,275 +0,0 @@ -%% Copyright (c) 2013-2014, Loïc Hoguin -%% -%% Permission to use, copy, modify, and/or distribute this software for any -%% purpose with or without fee is hereby granted, provided that the above -%% copyright notice and this permission notice appear in all copies. -%% -%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - --module(cow_cookie). - --export([parse_cookie/1]). --export([setcookie/3]). - --type cookie_option() :: {max_age, non_neg_integer()} - | {domain, binary()} | {path, binary()} - | {secure, boolean()} | {http_only, boolean()}. --type cookie_opts() :: [cookie_option()]. --export_type([cookie_opts/0]). - -%% @doc Parse a cookie header string and return a list of key/values. - --spec parse_cookie(binary()) -> [{binary(), binary()}] | {error, badarg}. -parse_cookie(Cookie) -> - parse_cookie(Cookie, []). - -parse_cookie(<<>>, Acc) -> - lists:reverse(Acc); -parse_cookie(<< $\s, Rest/binary >>, Acc) -> - parse_cookie(Rest, Acc); -parse_cookie(<< $\t, Rest/binary >>, Acc) -> - parse_cookie(Rest, Acc); -parse_cookie(<< $,, Rest/binary >>, Acc) -> - parse_cookie(Rest, Acc); -parse_cookie(<< $;, Rest/binary >>, Acc) -> - parse_cookie(Rest, Acc); -parse_cookie(<< $$, Rest/binary >>, Acc) -> - skip_cookie(Rest, Acc); -parse_cookie(Cookie, Acc) -> - parse_cookie_name(Cookie, Acc, <<>>). - -skip_cookie(<<>>, Acc) -> - lists:reverse(Acc); -skip_cookie(<< $,, Rest/binary >>, Acc) -> - parse_cookie(Rest, Acc); -skip_cookie(<< $;, Rest/binary >>, Acc) -> - parse_cookie(Rest, Acc); -skip_cookie(<< _, Rest/binary >>, Acc) -> - skip_cookie(Rest, Acc). - -parse_cookie_name(<<>>, _, _) -> - {error, badarg}; -parse_cookie_name(<< $=, _/binary >>, _, <<>>) -> - {error, badarg}; -parse_cookie_name(<< $=, Rest/binary >>, Acc, Name) -> - parse_cookie_value(Rest, Acc, Name, <<>>); -parse_cookie_name(<< $,, _/binary >>, _, _) -> - {error, badarg}; -parse_cookie_name(<< $;, _/binary >>, _, _) -> - {error, badarg}; -parse_cookie_name(<< $\s, _/binary >>, _, _) -> - {error, badarg}; -parse_cookie_name(<< $\t, _/binary >>, _, _) -> - {error, badarg}; -parse_cookie_name(<< $\r, _/binary >>, _, _) -> - {error, badarg}; -parse_cookie_name(<< $\n, _/binary >>, _, _) -> - {error, badarg}; -parse_cookie_name(<< $\013, _/binary >>, _, _) -> - {error, badarg}; -parse_cookie_name(<< $\014, _/binary >>, _, _) -> - {error, badarg}; -parse_cookie_name(<< C, Rest/binary >>, Acc, Name) -> - parse_cookie_name(Rest, Acc, << Name/binary, C >>). - -parse_cookie_value(<<>>, Acc, Name, Value) -> - lists:reverse([{Name, parse_cookie_trim(Value)}|Acc]); -parse_cookie_value(<< $;, Rest/binary >>, Acc, Name, Value) -> - parse_cookie(Rest, [{Name, parse_cookie_trim(Value)}|Acc]); -parse_cookie_value(<< $\t, _/binary >>, _, _, _) -> - {error, badarg}; -parse_cookie_value(<< $\r, _/binary >>, _, _, _) -> - {error, badarg}; -parse_cookie_value(<< $\n, _/binary >>, _, _, _) -> - {error, badarg}; -parse_cookie_value(<< $\013, _/binary >>, _, _, _) -> - {error, badarg}; -parse_cookie_value(<< $\014, _/binary >>, _, _, _) -> - {error, badarg}; -parse_cookie_value(<< C, Rest/binary >>, Acc, Name, Value) -> - parse_cookie_value(Rest, Acc, Name, << Value/binary, C >>). - -parse_cookie_trim(Value = <<>>) -> - Value; -parse_cookie_trim(Value) -> - case binary:last(Value) of - $\s -> - Size = byte_size(Value) - 1, - << Value2:Size/binary, _ >> = Value, - parse_cookie_trim(Value2); - _ -> - Value - end. - --ifdef(TEST). -parse_cookie_test_() -> - %% {Value, Result}. - Tests = [ - {<<"name=value; name2=value2">>, [ - {<<"name">>, <<"value">>}, - {<<"name2">>, <<"value2">>} - ]}, - {<<"$Version=1; Customer=WILE_E_COYOTE; $Path=/acme">>, [ - {<<"Customer">>, <<"WILE_E_COYOTE">>} - ]}, - {<<"$Version=1; Customer=WILE_E_COYOTE; $Path=/acme; " - "Part_Number=Rocket_Launcher_0001; $Path=/acme; " - "Shipping=FedEx; $Path=/acme">>, [ - {<<"Customer">>, <<"WILE_E_COYOTE">>}, - {<<"Part_Number">>, <<"Rocket_Launcher_0001">>}, - {<<"Shipping">>, <<"FedEx">>} - ]}, - %% Space in value. - {<<"foo=Thu Jul 11 2013 15:38:43 GMT+0400 (MSK)">>, - [{<<"foo">>, <<"Thu Jul 11 2013 15:38:43 GMT+0400 (MSK)">>}]}, - %% Comma in value. Google Analytics sets that kind of cookies. - {<<"refk=sOUZDzq2w2; sk=B602064E0139D842D620C7569640DBB4C81C45080651" - "9CC124EF794863E10E80; __utma=64249653.825741573.1380181332.1400" - "015657.1400019557.703; __utmb=64249653.1.10.1400019557; __utmc=" - "64249653; __utmz=64249653.1400019557.703.13.utmcsr=bluesky.chic" - "agotribune.com|utmccn=(referral)|utmcmd=referral|utmcct=/origin" - "als/chi-12-indispensable-digital-tools-bsi,0,0.storygallery">>, [ - {<<"refk">>, <<"sOUZDzq2w2">>}, - {<<"sk">>, <<"B602064E0139D842D620C7569640DBB4C81C45080651" - "9CC124EF794863E10E80">>}, - {<<"__utma">>, <<"64249653.825741573.1380181332.1400" - "015657.1400019557.703">>}, - {<<"__utmb">>, <<"64249653.1.10.1400019557">>}, - {<<"__utmc">>, <<"64249653">>}, - {<<"__utmz">>, <<"64249653.1400019557.703.13.utmcsr=bluesky.chic" - "agotribune.com|utmccn=(referral)|utmcmd=referral|utmcct=/origin" - "als/chi-12-indispensable-digital-tools-bsi,0,0.storygallery">>} - ]}, - %% Potential edge cases (initially from Mochiweb). - {<<"foo=\\x">>, [{<<"foo">>, <<"\\x">>}]}, - {<<"=">>, {error, badarg}}, - {<<" foo ; bar ">>, {error, badarg}}, - {<<"foo=;bar=">>, [{<<"foo">>, <<>>}, {<<"bar">>, <<>>}]}, - {<<"foo=\\\";;bar ">>, {error, badarg}}, - {<<"foo=\\\";;bar=good ">>, - [{<<"foo">>, <<"\\\"">>}, {<<"bar">>, <<"good">>}]}, - {<<"foo=\"\\\";bar">>, {error, badarg}}, - {<<>>, []}, - {<<"foo=bar , baz=wibble ">>, [{<<"foo">>, <<"bar , baz=wibble">>}]} - ], - [{V, fun() -> R = parse_cookie(V) end} || {V, R} <- Tests]. --endif. - -%% @doc Convert a cookie name, value and options to its iodata form. -%% @end -%% -%% Initially from Mochiweb: -%% * Copyright 2007 Mochi Media, Inc. -%% Initial binary implementation: -%% * Copyright 2011 Thomas Burdick - --spec setcookie(iodata(), iodata(), cookie_opts()) -> iodata(). -setcookie(Name, Value, Opts) -> - nomatch = binary:match(iolist_to_binary(Name), [<<$=>>, <<$,>>, <<$;>>, - <<$\s>>, <<$\t>>, <<$\r>>, <<$\n>>, <<$\013>>, <<$\014>>]), - nomatch = binary:match(iolist_to_binary(Value), [<<$,>>, <<$;>>, - <<$\s>>, <<$\t>>, <<$\r>>, <<$\n>>, <<$\013>>, <<$\014>>]), - MaxAgeBin = case lists:keyfind(max_age, 1, Opts) of - false -> <<>>; - {_, 0} -> - %% MSIE requires an Expires date in the past to delete a cookie. - <<"; Expires=Thu, 01-Jan-1970 00:00:01 GMT; Max-Age=0">>; - {_, MaxAge} when is_integer(MaxAge), MaxAge > 0 -> - UTC = calendar:universal_time(), - Secs = calendar:datetime_to_gregorian_seconds(UTC), - Expires = calendar:gregorian_seconds_to_datetime(Secs + MaxAge), - [<<"; Expires=">>, cow_date:rfc2109(Expires), - <<"; Max-Age=">>, integer_to_list(MaxAge)] - end, - DomainBin = case lists:keyfind(domain, 1, Opts) of - false -> <<>>; - {_, Domain} -> [<<"; Domain=">>, Domain] - end, - PathBin = case lists:keyfind(path, 1, Opts) of - false -> <<>>; - {_, Path} -> [<<"; Path=">>, Path] - end, - SecureBin = case lists:keyfind(secure, 1, Opts) of - false -> <<>>; - {_, false} -> <<>>; - {_, true} -> <<"; Secure">> - end, - HttpOnlyBin = case lists:keyfind(http_only, 1, Opts) of - false -> <<>>; - {_, false} -> <<>>; - {_, true} -> <<"; HttpOnly">> - end, - [Name, <<"=">>, Value, <<"; Version=1">>, - MaxAgeBin, DomainBin, PathBin, SecureBin, HttpOnlyBin]. - --ifdef(TEST). -setcookie_test_() -> - %% {Name, Value, Opts, Result} - Tests = [ - {<<"Customer">>, <<"WILE_E_COYOTE">>, - [{http_only, true}, {domain, <<"acme.com">>}], - <<"Customer=WILE_E_COYOTE; Version=1; " - "Domain=acme.com; HttpOnly">>}, - {<<"Customer">>, <<"WILE_E_COYOTE">>, - [{path, <<"/acme">>}], - <<"Customer=WILE_E_COYOTE; Version=1; Path=/acme">>}, - {<<"Customer">>, <<"WILE_E_COYOTE">>, - [{secure, true}], - <<"Customer=WILE_E_COYOTE; Version=1; Secure">>}, - {<<"Customer">>, <<"WILE_E_COYOTE">>, - [{secure, false}, {http_only, false}], - <<"Customer=WILE_E_COYOTE; Version=1">>}, - {<<"Customer">>, <<"WILE_E_COYOTE">>, - [{path, <<"/acme">>}, {badoption, <<"negatory">>}], - <<"Customer=WILE_E_COYOTE; Version=1; Path=/acme">>} - ], - [{R, fun() -> R = iolist_to_binary(setcookie(N, V, O)) end} - || {N, V, O, R} <- Tests]. - -setcookie_max_age_test() -> - F = fun(N, V, O) -> - binary:split(iolist_to_binary( - setcookie(N, V, O)), <<";">>, [global]) - end, - [<<"Customer=WILE_E_COYOTE">>, - <<" Version=1">>, - <<" Expires=", _/binary>>, - <<" Max-Age=111">>, - <<" Secure">>] = F(<<"Customer">>, <<"WILE_E_COYOTE">>, - [{max_age, 111}, {secure, true}]), - case catch F(<<"Customer">>, <<"WILE_E_COYOTE">>, [{max_age, -111}]) of - {'EXIT', {{case_clause, {max_age, -111}}, _}} -> ok - end, - [<<"Customer=WILE_E_COYOTE">>, - <<" Version=1">>, - <<" Expires=", _/binary>>, - <<" Max-Age=86417">>] = F(<<"Customer">>, <<"WILE_E_COYOTE">>, - [{max_age, 86417}]), - ok. - -setcookie_failures_test_() -> - F = fun(N, V) -> - try setcookie(N, V, []) of - _ -> - false - catch _:_ -> - true - end - end, - Tests = [ - {<<"Na=me">>, <<"Value">>}, - {<<"Name;">>, <<"Value">>}, - {<<"\r\name">>, <<"Value">>}, - {<<"Name">>, <<"Value;">>}, - {<<"Name">>, <<"\value">>} - ], - [{iolist_to_binary(io_lib:format("{~p, ~p} failure", [N, V])), - fun() -> true = F(N, V) end} - || {N, V} <- Tests]. --endif. DELETED deps/cowlib/src/cow_date.erl Index: deps/cowlib/src/cow_date.erl ================================================================== --- deps/cowlib/src/cow_date.erl +++ /dev/null @@ -1,206 +0,0 @@ -%% Copyright (c) 2013-2014, Loïc Hoguin -%% -%% Permission to use, copy, modify, and/or distribute this software for any -%% purpose with or without fee is hereby granted, provided that the above -%% copyright notice and this permission notice appear in all copies. -%% -%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - --module(cow_date). - --export([rfc2109/1]). - -%% @doc Return the date formatted according to RFC2109. - --spec rfc2109(calendar:datetime()) -> binary(). -rfc2109({Date = {Y, Mo, D}, {H, Mi, S}}) -> - Wday = calendar:day_of_the_week(Date), - << (weekday(Wday))/binary, ", ", - (pad_int(D))/binary, "-", - (month(Mo))/binary, "-", - (year(Y))/binary, " ", - (pad_int(H))/binary, ":", - (pad_int(Mi))/binary, ":", - (pad_int(S))/binary, " GMT" >>. - --ifdef(TEST). -rfc2109_test_() -> - Tests = [ - {<<"Sat, 14-May-2011 14:25:33 GMT">>, {{2011, 5, 14}, {14, 25, 33}}}, - {<<"Sun, 01-Jan-2012 00:00:00 GMT">>, {{2012, 1, 1}, { 0, 0, 0}}} - ], - [{R, fun() -> R = rfc2109(D) end} || {R, D} <- Tests]. --endif. - --ifdef(PERF). -horse_rfc2019_20130101_000000() -> - horse:repeat(100000, - rfc2109({{2013, 1, 1}, {0, 0, 0}}) - ). - -horse_rfc2019_20131231_235959() -> - horse:repeat(100000, - rfc2109({{2013, 12, 31}, {23, 59, 59}}) - ). - -horse_rfc2019_12340506_070809() -> - horse:repeat(100000, - rfc2109({{1234, 5, 6}, {7, 8, 9}}) - ). --endif. - -%% Internal. - --spec pad_int(0..59) -> <<_:16>>. -pad_int( 0) -> <<"00">>; -pad_int( 1) -> <<"01">>; -pad_int( 2) -> <<"02">>; -pad_int( 3) -> <<"03">>; -pad_int( 4) -> <<"04">>; -pad_int( 5) -> <<"05">>; -pad_int( 6) -> <<"06">>; -pad_int( 7) -> <<"07">>; -pad_int( 8) -> <<"08">>; -pad_int( 9) -> <<"09">>; -pad_int(10) -> <<"10">>; -pad_int(11) -> <<"11">>; -pad_int(12) -> <<"12">>; -pad_int(13) -> <<"13">>; -pad_int(14) -> <<"14">>; -pad_int(15) -> <<"15">>; -pad_int(16) -> <<"16">>; -pad_int(17) -> <<"17">>; -pad_int(18) -> <<"18">>; -pad_int(19) -> <<"19">>; -pad_int(20) -> <<"20">>; -pad_int(21) -> <<"21">>; -pad_int(22) -> <<"22">>; -pad_int(23) -> <<"23">>; -pad_int(24) -> <<"24">>; -pad_int(25) -> <<"25">>; -pad_int(26) -> <<"26">>; -pad_int(27) -> <<"27">>; -pad_int(28) -> <<"28">>; -pad_int(29) -> <<"29">>; -pad_int(30) -> <<"30">>; -pad_int(31) -> <<"31">>; -pad_int(32) -> <<"32">>; -pad_int(33) -> <<"33">>; -pad_int(34) -> <<"34">>; -pad_int(35) -> <<"35">>; -pad_int(36) -> <<"36">>; -pad_int(37) -> <<"37">>; -pad_int(38) -> <<"38">>; -pad_int(39) -> <<"39">>; -pad_int(40) -> <<"40">>; -pad_int(41) -> <<"41">>; -pad_int(42) -> <<"42">>; -pad_int(43) -> <<"43">>; -pad_int(44) -> <<"44">>; -pad_int(45) -> <<"45">>; -pad_int(46) -> <<"46">>; -pad_int(47) -> <<"47">>; -pad_int(48) -> <<"48">>; -pad_int(49) -> <<"49">>; -pad_int(50) -> <<"50">>; -pad_int(51) -> <<"51">>; -pad_int(52) -> <<"52">>; -pad_int(53) -> <<"53">>; -pad_int(54) -> <<"54">>; -pad_int(55) -> <<"55">>; -pad_int(56) -> <<"56">>; -pad_int(57) -> <<"57">>; -pad_int(58) -> <<"58">>; -pad_int(59) -> <<"59">>. - --spec weekday(1..7) -> <<_:24>>. -weekday(1) -> <<"Mon">>; -weekday(2) -> <<"Tue">>; -weekday(3) -> <<"Wed">>; -weekday(4) -> <<"Thu">>; -weekday(5) -> <<"Fri">>; -weekday(6) -> <<"Sat">>; -weekday(7) -> <<"Sun">>. - --spec month(1..12) -> <<_:24>>. -month( 1) -> <<"Jan">>; -month( 2) -> <<"Feb">>; -month( 3) -> <<"Mar">>; -month( 4) -> <<"Apr">>; -month( 5) -> <<"May">>; -month( 6) -> <<"Jun">>; -month( 7) -> <<"Jul">>; -month( 8) -> <<"Aug">>; -month( 9) -> <<"Sep">>; -month(10) -> <<"Oct">>; -month(11) -> <<"Nov">>; -month(12) -> <<"Dec">>. - --spec year(pos_integer()) -> <<_:32>>. -year(1970) -> <<"1970">>; -year(1971) -> <<"1971">>; -year(1972) -> <<"1972">>; -year(1973) -> <<"1973">>; -year(1974) -> <<"1974">>; -year(1975) -> <<"1975">>; -year(1976) -> <<"1976">>; -year(1977) -> <<"1977">>; -year(1978) -> <<"1978">>; -year(1979) -> <<"1979">>; -year(1980) -> <<"1980">>; -year(1981) -> <<"1981">>; -year(1982) -> <<"1982">>; -year(1983) -> <<"1983">>; -year(1984) -> <<"1984">>; -year(1985) -> <<"1985">>; -year(1986) -> <<"1986">>; -year(1987) -> <<"1987">>; -year(1988) -> <<"1988">>; -year(1989) -> <<"1989">>; -year(1990) -> <<"1990">>; -year(1991) -> <<"1991">>; -year(1992) -> <<"1992">>; -year(1993) -> <<"1993">>; -year(1994) -> <<"1994">>; -year(1995) -> <<"1995">>; -year(1996) -> <<"1996">>; -year(1997) -> <<"1997">>; -year(1998) -> <<"1998">>; -year(1999) -> <<"1999">>; -year(2000) -> <<"2000">>; -year(2001) -> <<"2001">>; -year(2002) -> <<"2002">>; -year(2003) -> <<"2003">>; -year(2004) -> <<"2004">>; -year(2005) -> <<"2005">>; -year(2006) -> <<"2006">>; -year(2007) -> <<"2007">>; -year(2008) -> <<"2008">>; -year(2009) -> <<"2009">>; -year(2010) -> <<"2010">>; -year(2011) -> <<"2011">>; -year(2012) -> <<"2012">>; -year(2013) -> <<"2013">>; -year(2014) -> <<"2014">>; -year(2015) -> <<"2015">>; -year(2016) -> <<"2016">>; -year(2017) -> <<"2017">>; -year(2018) -> <<"2018">>; -year(2019) -> <<"2019">>; -year(2020) -> <<"2020">>; -year(2021) -> <<"2021">>; -year(2022) -> <<"2022">>; -year(2023) -> <<"2023">>; -year(2024) -> <<"2024">>; -year(2025) -> <<"2025">>; -year(2026) -> <<"2026">>; -year(2027) -> <<"2027">>; -year(2028) -> <<"2028">>; -year(2029) -> <<"2029">>; -year(Year) -> list_to_binary(integer_to_list(Year)). DELETED deps/cowlib/src/cow_http.erl Index: deps/cowlib/src/cow_http.erl ================================================================== --- deps/cowlib/src/cow_http.erl +++ /dev/null @@ -1,301 +0,0 @@ -%% Copyright (c) 2013-2014, Loïc Hoguin -%% -%% Permission to use, copy, modify, and/or distribute this software for any -%% purpose with or without fee is hereby granted, provided that the above -%% copyright notice and this permission notice appear in all copies. -%% -%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - --module(cow_http). - -%% @todo parse_request_line --export([parse_status_line/1]). --export([parse_headers/1]). - --export([parse_fullhost/1]). --export([parse_fullpath/1]). --export([parse_version/1]). - --export([request/4]). --export([version/1]). - --type version() :: 'HTTP/1.0' | 'HTTP/1.1'. --type status() :: 100..999. --type headers() :: [{binary(), iodata()}]. - --include("cow_inline.hrl"). - -%% @doc Parse the status line. - --spec parse_status_line(binary()) -> {version(), status(), binary(), binary()}. -parse_status_line(<< "HTTP/1.1 200 OK\r\n", Rest/bits >>) -> - {'HTTP/1.1', 200, <<"OK">>, Rest}; -parse_status_line(<< "HTTP/1.1 404 Not Found\r\n", Rest/bits >>) -> - {'HTTP/1.1', 404, <<"Not Found">>, Rest}; -parse_status_line(<< "HTTP/1.1 500 Internal Server Error\r\n", Rest/bits >>) -> - {'HTTP/1.1', 500, <<"Internal Server Error">>, Rest}; -parse_status_line(<< "HTTP/1.1 ", Status/bits >>) -> - parse_status_line(Status, 'HTTP/1.1'); -parse_status_line(<< "HTTP/1.0 ", Status/bits >>) -> - parse_status_line(Status, 'HTTP/1.0'). - -parse_status_line(<< H, T, U, " ", Rest/bits >>, Version) - when $0 =< H, H =< $9, $0 =< T, T =< $9, $0 =< U, U =< $9 -> - Status = (H - $0) * 100 + (T - $0) * 10 + (U - $0), - {Pos, _} = binary:match(Rest, <<"\r">>), - << StatusStr:Pos/binary, "\r\n", Rest2/bits >> = Rest, - {Version, Status, StatusStr, Rest2}. - --ifdef(TEST). -parse_status_line_test_() -> - Tests = [ - {<<"HTTP/1.1 200 OK\r\nRest">>, - {'HTTP/1.1', 200, <<"OK">>, <<"Rest">>}}, - {<<"HTTP/1.0 404 Not Found\r\nRest">>, - {'HTTP/1.0', 404, <<"Not Found">>, <<"Rest">>}}, - {<<"HTTP/1.1 500 Something very funny here\r\nRest">>, - {'HTTP/1.1', 500, <<"Something very funny here">>, <<"Rest">>}}, - {<<"HTTP/1.1 200 \r\nRest">>, - {'HTTP/1.1', 200, <<>>, <<"Rest">>}} - ], - [{V, fun() -> R = parse_status_line(V) end} - || {V, R} <- Tests]. - -parse_status_line_error_test_() -> - Tests = [ - <<>>, - <<"HTTP/1.1">>, - <<"HTTP/1.1 200\r\n">>, - <<"HTTP/1.1 200 OK">>, - <<"HTTP/1.1 200 OK\r">>, - <<"HTTP/1.1 200 OK\n">>, - <<"HTTP/0.9 200 OK\r\n">>, - <<"HTTP/1.1 42 Answer\r\n">>, - <<"HTTP/1.1 999999999 More than OK\r\n">>, - <<"content-type: text/plain\r\n">>, - <<0:80, "\r\n">> - ], - [{V, fun() -> {'EXIT', _} = (catch parse_status_line(V)) end} - || V <- Tests]. --endif. - --ifdef(PERF). -horse_parse_status_line_200() -> - horse:repeat(200000, - parse_status_line(<<"HTTP/1.1 200 OK\r\n">>) - ). - -horse_parse_status_line_404() -> - horse:repeat(200000, - parse_status_line(<<"HTTP/1.1 404 Not Found\r\n">>) - ). - -horse_parse_status_line_500() -> - horse:repeat(200000, - parse_status_line(<<"HTTP/1.1 500 Internal Server Error\r\n">>) - ). - -horse_parse_status_line_other() -> - horse:repeat(200000, - parse_status_line(<<"HTTP/1.1 416 Requested range not satisfiable\r\n">>) - ). --endif. - -%% @doc Parse the list of headers. - --spec parse_headers(binary()) -> {[{binary(), binary()}], binary()}. -parse_headers(Data) -> - parse_header(Data, []). - -parse_header(<< $\r, $\n, Rest/bits >>, Acc) -> - {lists:reverse(Acc), Rest}; -parse_header(Data, Acc) -> - parse_hd_name(Data, Acc, <<>>). - -parse_hd_name(<< C, Rest/bits >>, Acc, SoFar) -> - case C of - $: -> parse_hd_before_value(Rest, Acc, SoFar); - $\s -> parse_hd_name_ws(Rest, Acc, SoFar); - $\t -> parse_hd_name_ws(Rest, Acc, SoFar); - ?INLINE_LOWERCASE(parse_hd_name, Rest, Acc, SoFar) - end. - -parse_hd_name_ws(<< C, Rest/bits >>, Acc, Name) -> - case C of - $: -> parse_hd_before_value(Rest, Acc, Name); - $\s -> parse_hd_name_ws(Rest, Acc, Name); - $\t -> parse_hd_name_ws(Rest, Acc, Name) - end. - -parse_hd_before_value(<< $\s, Rest/bits >>, Acc, Name) -> - parse_hd_before_value(Rest, Acc, Name); -parse_hd_before_value(<< $\t, Rest/bits >>, Acc, Name) -> - parse_hd_before_value(Rest, Acc, Name); -parse_hd_before_value(Data, Acc, Name) -> - parse_hd_value(Data, Acc, Name, <<>>). - -parse_hd_value(<< $\r, Rest/bits >>, Acc, Name, SoFar) -> - case Rest of - << $\n, C, Rest2/bits >> when C =:= $\s; C =:= $\t -> - parse_hd_value(Rest2, Acc, Name, << SoFar/binary, C >>); - << $\n, Rest2/bits >> -> - parse_header(Rest2, [{Name, SoFar}|Acc]) - end; -parse_hd_value(<< C, Rest/bits >>, Acc, Name, SoFar) -> - parse_hd_value(Rest, Acc, Name, << SoFar/binary, C >>). - --ifdef(TEST). -parse_headers_test_() -> - Tests = [ - {<<"\r\nRest">>, - {[], <<"Rest">>}}, - {<<"Server: Erlang/R17\r\n" - "Date: Sun, 23 Feb 2014 09:30:39 GMT\r\n" - "Multiline-Header: why hello!\r\n" - " I didn't see you all the way over there!\r\n" - "Content-Length: 12\r\n" - "Content-Type: text/plain\r\n" - "\r\nRest">>, - {[{<<"server">>, <<"Erlang/R17">>}, - {<<"date">>, <<"Sun, 23 Feb 2014 09:30:39 GMT">>}, - {<<"multiline-header">>, - <<"why hello! I didn't see you all the way over there!">>}, - {<<"content-length">>, <<"12">>}, - {<<"content-type">>, <<"text/plain">>}], - <<"Rest">>}} - ], - [{V, fun() -> R = parse_headers(V) end} - || {V, R} <- Tests]. - -parse_headers_error_test_() -> - Tests = [ - <<>>, - <<"\r">>, - <<"Malformed\r\n\r\n">>, - <<"content-type: text/plain\r\nMalformed\r\n\r\n">>, - <<"HTTP/1.1 200 OK\r\n\r\n">>, - <<0:80, "\r\n\r\n">>, - <<"content-type: text/plain\r\ncontent-length: 12\r\n">> - ], - [{V, fun() -> {'EXIT', _} = (catch parse_headers(V)) end} - || V <- Tests]. --endif. - --ifdef(PERF). -horse_parse_headers() -> - horse:repeat(50000, - parse_headers(<<"Server: Erlang/R17\r\n" - "Date: Sun, 23 Feb 2014 09:30:39 GMT\r\n" - "Multiline-Header: why hello!\r\n" - " I didn't see you all the way over there!\r\n" - "Content-Length: 12\r\n" - "Content-Type: text/plain\r\n" - "\r\nRest">>) - ). --endif. - -%% @doc Extract host and port from a binary. -%% -%% Because the hostname is case insensitive it is converted -%% to lowercase. - --spec parse_fullhost(binary()) -> {binary(), undefined | non_neg_integer()}. -parse_fullhost(Fullhost) -> - parse_fullhost(Fullhost, false, <<>>). - -parse_fullhost(<< $[, Rest/bits >>, false, <<>>) -> - parse_fullhost(Rest, true, << $[ >>); -parse_fullhost(<<>>, false, Acc) -> - {Acc, undefined}; -%% @todo Optimize. -parse_fullhost(<< $:, Rest/bits >>, false, Acc) -> - {Acc, list_to_integer(binary_to_list(Rest))}; -parse_fullhost(<< $], Rest/bits >>, true, Acc) -> - parse_fullhost(Rest, false, << Acc/binary, $] >>); -parse_fullhost(<< C, Rest/bits >>, E, Acc) -> - case C of - ?INLINE_LOWERCASE(parse_fullhost, Rest, E, Acc) - end. - --ifdef(TEST). -parse_fullhost_test() -> - {<<"example.org">>, 8080} = parse_fullhost(<<"example.org:8080">>), - {<<"example.org">>, undefined} = parse_fullhost(<<"example.org">>), - {<<"192.0.2.1">>, 8080} = parse_fullhost(<<"192.0.2.1:8080">>), - {<<"192.0.2.1">>, undefined} = parse_fullhost(<<"192.0.2.1">>), - {<<"[2001:db8::1]">>, 8080} = parse_fullhost(<<"[2001:db8::1]:8080">>), - {<<"[2001:db8::1]">>, undefined} = parse_fullhost(<<"[2001:db8::1]">>), - {<<"[::ffff:192.0.2.1]">>, 8080} - = parse_fullhost(<<"[::ffff:192.0.2.1]:8080">>), - {<<"[::ffff:192.0.2.1]">>, undefined} - = parse_fullhost(<<"[::ffff:192.0.2.1]">>), - ok. --endif. - -%% @doc Extract path and query string from a binary. - --spec parse_fullpath(binary()) -> {binary(), binary()}. -parse_fullpath(Fullpath) -> - parse_fullpath(Fullpath, <<>>). - -parse_fullpath(<<>>, Path) -> - {Path, <<>>}; -parse_fullpath(<< $?, Qs/binary >>, Path) -> - {Path, Qs}; -parse_fullpath(<< C, Rest/binary >>, SoFar) -> - parse_fullpath(Rest, << SoFar/binary, C >>). - --ifdef(TEST). -parse_fullpath_test() -> - {<<"*">>, <<>>} = parse_fullpath(<<"*">>), - {<<"/">>, <<>>} = parse_fullpath(<<"/">>), - {<<"/path/to/resource">>, <<>>} = parse_fullpath(<<"/path/to/resource">>), - {<<"/">>, <<>>} = parse_fullpath(<<"/?">>), - {<<"/">>, <<"q=cowboy">>} = parse_fullpath(<<"/?q=cowboy">>), - {<<"/path/to/resource">>, <<"q=cowboy">>} - = parse_fullpath(<<"/path/to/resource?q=cowboy">>), - ok. --endif. - -%% @doc Convert an HTTP version to atom. - --spec parse_version(binary()) -> version(). -parse_version(<<"HTTP/1.1">>) -> 'HTTP/1.1'; -parse_version(<<"HTTP/1.0">>) -> 'HTTP/1.0'. - --ifdef(TEST). -parse_version_test() -> - 'HTTP/1.1' = parse_version(<<"HTTP/1.1">>), - 'HTTP/1.0' = parse_version(<<"HTTP/1.0">>), - {'EXIT', _} = (catch parse_version(<<"HTTP/1.2">>)), - ok. --endif. - -%% @doc Return formatted request-line and headers. -%% @todo Add tests when the corresponding reverse functions are added. - --spec request(binary(), iodata(), version(), headers()) -> iodata(). -request(Method, Path, Version, Headers) -> - [Method, <<" ">>, Path, <<" ">>, version(Version), <<"\r\n">>, - [[N, <<": ">>, V, <<"\r\n">>] || {N, V} <- Headers], - <<"\r\n">>]. - -%% @doc Return the version as a binary. - --spec version(version()) -> binary(). -version('HTTP/1.1') -> <<"HTTP/1.1">>; -version('HTTP/1.0') -> <<"HTTP/1.0">>. - --ifdef(TEST). -version_test() -> - <<"HTTP/1.1">> = version('HTTP/1.1'), - <<"HTTP/1.0">> = version('HTTP/1.0'), - {'EXIT', _} = (catch version('HTTP/1.2')), - ok. --endif. DELETED deps/cowlib/src/cow_http_hd.erl Index: deps/cowlib/src/cow_http_hd.erl ================================================================== --- deps/cowlib/src/cow_http_hd.erl +++ /dev/null @@ -1,194 +0,0 @@ -%% Copyright (c) 2014, Loïc Hoguin -%% -%% Permission to use, copy, modify, and/or distribute this software for any -%% purpose with or without fee is hereby granted, provided that the above -%% copyright notice and this permission notice appear in all copies. -%% -%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - --module(cow_http_hd). - --export([parse_connection/1]). --export([parse_content_length/1]). --export([parse_transfer_encoding/1]). - --include("cow_inline.hrl"). - -%% @doc Parse the Connection header. - --spec parse_connection(binary()) -> [binary()]. -parse_connection(<<"close">>) -> - [<<"close">>]; -parse_connection(<<"keep-alive">>) -> - [<<"keep-alive">>]; -parse_connection(Connection) -> - nonempty(token_ci_list(Connection, [])). - --ifdef(TEST). -parse_connection_test_() -> - Tests = [ - {<<"close">>, [<<"close">>]}, - {<<"ClOsE">>, [<<"close">>]}, - {<<"Keep-Alive">>, [<<"keep-alive">>]}, - {<<"keep-alive, Upgrade">>, [<<"keep-alive">>, <<"upgrade">>]} - ], - [{V, fun() -> R = parse_connection(V) end} || {V, R} <- Tests]. --endif. - --ifdef(PERF). -horse_parse_connection_close() -> - horse:repeat(200000, - parse_connection(<<"close">>) - ). - -horse_parse_connection_keepalive() -> - horse:repeat(200000, - parse_connection(<<"keep-alive">>) - ). - -horse_parse_connection_keepalive_upgrade() -> - horse:repeat(200000, - parse_connection(<<"keep-alive, upgrade">>) - ). --endif. - -%% @doc Parse the Content-Length header. -%% -%% The value has at least one digit, and may be followed by whitespace. - --spec parse_content_length(binary()) -> non_neg_integer(). -parse_content_length(<< $0 >>) -> 0; -parse_content_length(<< $0, R/bits >>) -> number(R, 0); -parse_content_length(<< $1, R/bits >>) -> number(R, 1); -parse_content_length(<< $2, R/bits >>) -> number(R, 2); -parse_content_length(<< $3, R/bits >>) -> number(R, 3); -parse_content_length(<< $4, R/bits >>) -> number(R, 4); -parse_content_length(<< $5, R/bits >>) -> number(R, 5); -parse_content_length(<< $6, R/bits >>) -> number(R, 6); -parse_content_length(<< $7, R/bits >>) -> number(R, 7); -parse_content_length(<< $8, R/bits >>) -> number(R, 8); -parse_content_length(<< $9, R/bits >>) -> number(R, 9). - --ifdef(TEST). -parse_content_length_test_() -> - Tests = [ - {<<"0">>, 0}, - {<<"42 ">>, 42}, - {<<"69\t">>, 69}, - {<<"1337">>, 1337}, - {<<"1234567890">>, 1234567890}, - {<<"1234567890 ">>, 1234567890} - ], - [{V, fun() -> R = parse_content_length(V) end} || {V, R} <- Tests]. --endif. - --ifdef(PERF). -horse_parse_content_length_zero() -> - horse:repeat(100000, - parse_content_length(<<"0">>) - ). - -horse_parse_content_length_giga() -> - horse:repeat(100000, - parse_content_length(<<"1234567890">>) - ). --endif. - -%% @doc Parse the Transfer-Encoding header. -%% -%% @todo Extension parameters. - --spec parse_transfer_encoding(binary()) -> [binary()]. -parse_transfer_encoding(<<"chunked">>) -> - [<<"chunked">>]; -parse_transfer_encoding(TransferEncoding) -> - nonempty(token_ci_list(TransferEncoding, [])). - --ifdef(TEST). -parse_transfer_encoding_test_() -> - Tests = [ - {<<"a , , , ">>, [<<"a">>]}, - {<<" , , , a">>, [<<"a">>]}, - {<<"a , , b">>, [<<"a">>, <<"b">>]}, - {<<"chunked">>, [<<"chunked">>]}, - {<<"chunked, something">>, [<<"chunked">>, <<"something">>]} - ], - [{V, fun() -> R = parse_transfer_encoding(V) end} || {V, R} <- Tests]. - -parse_transfer_encoding_error_test_() -> - Tests = [ - <<>>, - <<" ">>, - <<" , ">>, - <<",,,">>, - <<"a b">> - ], - [{V, fun() -> {'EXIT', _} = (catch parse_transfer_encoding(V)) end} - || V <- Tests]. --endif. - --ifdef(PERF). -horse_parse_transfer_encoding_chunked() -> - horse:repeat(200000, - parse_transfer_encoding(<<"chunked">>) - ). - -horse_parse_transfer_encoding_custom() -> - horse:repeat(200000, - parse_transfer_encoding(<<"chunked, something">>) - ). --endif. - -%% Internal. - -%% Only return if the list is not empty. -nonempty(L) when L =/= [] -> L. - -%% Parse a number optionally followed by whitespace. -number(<< $0, R/bits >>, Acc) -> number(R, Acc * 10); -number(<< $1, R/bits >>, Acc) -> number(R, Acc * 10 + 1); -number(<< $2, R/bits >>, Acc) -> number(R, Acc * 10 + 2); -number(<< $3, R/bits >>, Acc) -> number(R, Acc * 10 + 3); -number(<< $4, R/bits >>, Acc) -> number(R, Acc * 10 + 4); -number(<< $5, R/bits >>, Acc) -> number(R, Acc * 10 + 5); -number(<< $6, R/bits >>, Acc) -> number(R, Acc * 10 + 6); -number(<< $7, R/bits >>, Acc) -> number(R, Acc * 10 + 7); -number(<< $8, R/bits >>, Acc) -> number(R, Acc * 10 + 8); -number(<< $9, R/bits >>, Acc) -> number(R, Acc * 10 + 9); -number(<< $\s, R/bits >>, Acc) -> ws_end(R), Acc; -number(<< $\t, R/bits >>, Acc) -> ws_end(R), Acc; -number(<<>>, Acc) -> Acc. - -ws_end(<< $\s, R/bits >>) -> ws_end(R); -ws_end(<< $\t, R/bits >>) -> ws_end(R); -ws_end(<<>>) -> ok. - -%% Parse a list of case insensitive tokens. -token_ci_list(<<>>, Acc) -> lists:reverse(Acc); -token_ci_list(<< $\s, R/bits >>, Acc) -> token_ci_list(R, Acc); -token_ci_list(<< $\t, R/bits >>, Acc) -> token_ci_list(R, Acc); -token_ci_list(<< $,, R/bits >>, Acc) -> token_ci_list(R, Acc); -token_ci_list(<< C, R/bits >>, Acc) -> - case C of - ?INLINE_LOWERCASE(token_ci_list, R, Acc, <<>>) - end. - -token_ci_list(<<>>, Acc, T) -> lists:reverse([T|Acc]); -token_ci_list(<< $\s, R/bits >>, Acc, T) -> token_ci_list_sep(R, Acc, T); -token_ci_list(<< $\t, R/bits >>, Acc, T) -> token_ci_list_sep(R, Acc, T); -token_ci_list(<< $,, R/bits >>, Acc, T) -> token_ci_list(R, [T|Acc]); -token_ci_list(<< C, R/bits >>, Acc, T) -> - case C of - ?INLINE_LOWERCASE(token_ci_list, R, Acc, T) - end. - -token_ci_list_sep(<<>>, Acc, T) -> lists:reverse([T|Acc]); -token_ci_list_sep(<< $\s, R/bits >>, Acc, T) -> token_ci_list_sep(R, Acc, T); -token_ci_list_sep(<< $\t, R/bits >>, Acc, T) -> token_ci_list_sep(R, Acc, T); -token_ci_list_sep(<< $,, R/bits >>, Acc, T) -> token_ci_list(R, [T|Acc]). DELETED deps/cowlib/src/cow_http_te.erl Index: deps/cowlib/src/cow_http_te.erl ================================================================== --- deps/cowlib/src/cow_http_te.erl +++ /dev/null @@ -1,327 +0,0 @@ -%% Copyright (c) 2014, Loïc Hoguin -%% -%% Permission to use, copy, modify, and/or distribute this software for any -%% purpose with or without fee is hereby granted, provided that the above -%% copyright notice and this permission notice appear in all copies. -%% -%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - --module(cow_http_te). - -%% Identity. --export([stream_identity/2]). --export([identity/1]). - -%% Chunked. --export([stream_chunked/2]). --export([chunk/1]). --export([last_chunk/0]). - -%% The state type is the same for both identity and chunked. --type state() :: {non_neg_integer(), non_neg_integer()}. - --type decode_ret() :: more - | {more, Data::binary(), state()} - | {more, Data::binary(), RemLen::non_neg_integer(), state()} - | {more, Data::binary(), Rest::binary(), state()} - | {done, TotalLen::non_neg_integer(), Rest::binary()} - | {done, Data::binary(), TotalLen::non_neg_integer(), Rest::binary()}. --export_type([decode_ret/0]). - --ifdef(EXTRA). -dripfeed(<< C, Rest/bits >>, Acc, State, F) -> - case F(<< Acc/binary, C >>, State) of - more -> - dripfeed(Rest, << Acc/binary, C >>, State, F); - {more, _, State2} -> - dripfeed(Rest, <<>>, State2, F); - {more, _, Length, State2} when is_integer(Length) -> - dripfeed(Rest, <<>>, State2, F); - {more, _, Acc2, State2} -> - dripfeed(Rest, Acc2, State2, F); - {done, _, <<>>} -> - ok; - {done, _, _, <<>>} -> - ok - end. --endif. - -%% Identity. - -%% @doc Decode an identity stream. - --spec stream_identity(Data, State) - -> {more, Data, Len, State} | {done, Data, Len, Data} - when Data::binary(), State::state(), Len::non_neg_integer(). -stream_identity(Data, {Streamed, Total}) -> - Streamed2 = Streamed + byte_size(Data), - if - Streamed2 < Total -> - {more, Data, Total - Streamed2, {Streamed2, Total}}; - true -> - Size = Total - Streamed, - << Data2:Size/binary, Rest/bits >> = Data, - {done, Data2, Total, Rest} - end. - --spec identity(Data) -> Data when Data::iodata(). -identity(Data) -> - Data. - --ifdef(TEST). -stream_identity_test() -> - {done, <<>>, 0, <<>>} - = stream_identity(identity(<<>>), {0, 0}), - {done, <<"\r\n">>, 2, <<>>} - = stream_identity(identity(<<"\r\n">>), {0, 2}), - {done, << 0:80000 >>, 10000, <<>>} - = stream_identity(identity(<< 0:80000 >>), {0, 10000}), - ok. - -stream_identity_parts_test() -> - {more, << 0:8000 >>, 1999, S1} - = stream_identity(<< 0:8000 >>, {0, 2999}), - {more, << 0:8000 >>, 999, S2} - = stream_identity(<< 0:8000 >>, S1), - {done, << 0:7992 >>, 2999, <<>>} - = stream_identity(<< 0:7992 >>, S2), - ok. --endif. - --ifdef(PERF). -%% Using the same data as the chunked one for comparison. - -horse_stream_identity() -> - horse:repeat(10000, - stream_identity(<< - "4\r\n" - "Wiki\r\n" - "5\r\n" - "pedia\r\n" - "e\r\n" - " in\r\n\r\nchunks.\r\n" - "0\r\n" - "\r\n">>, {0, 43}) - ). - -horse_stream_identity_dripfeed() -> - horse:repeat(10000, - dripfeed(<< - "4\r\n" - "Wiki\r\n" - "5\r\n" - "pedia\r\n" - "e\r\n" - " in\r\n\r\nchunks.\r\n" - "0\r\n" - "\r\n">>, <<>>, {0, 43}, fun stream_identity/2) - ). --endif. - -%% Chunked. - -%% @doc Decode a chunked stream. - --spec stream_chunked(Data, State) - -> more | {more, Data, State} | {more, Data, Len, State} - | {more, Data, Data, State} - | {done, Len, Data} | {done, Data, Len, Data} - when Data::binary(), State::state(), Len::non_neg_integer(). -stream_chunked(Data, State) -> - stream_chunked(Data, State, <<>>). - -%% New chunk. -stream_chunked(Data = << C, _/bits >>, {0, Streamed}, Acc) when C =/= $\r -> - case chunked_len(Data, Streamed, Acc, 0) of - {next, Rest, State, Acc2} -> - stream_chunked(Rest, State, Acc2); - {more, State, Acc2} -> - {more, Acc2, Data, State}; - Ret -> - Ret - end; -%% Trailing \r\n before next chunk. -stream_chunked(<< "\r\n", Rest/bits >>, {2, Streamed}, Acc) -> - stream_chunked(Rest, {0, Streamed}, Acc); -%% Trailing \r before next chunk. -stream_chunked(<< "\r" >>, {2, Streamed}, Acc) -> - {more, Acc, {1, Streamed}}; -%% Trailing \n before next chunk. -stream_chunked(<< "\n", Rest/bits >>, {1, Streamed}, Acc) -> - stream_chunked(Rest, {0, Streamed}, Acc); -%% More data needed. -stream_chunked(<<>>, State = {Rem, _}, Acc) -> - {more, Acc, Rem, State}; -%% Chunk data. -stream_chunked(Data, {Rem, Streamed}, Acc) when Rem > 2 -> - DataSize = byte_size(Data), - RemSize = Rem - 2, - case Data of - << Chunk:RemSize/binary, "\r\n", Rest/bits >> -> - stream_chunked(Rest, {0, Streamed + RemSize}, << Acc/binary, Chunk/binary >>); - << Chunk:RemSize/binary, "\r" >> -> - {more, << Acc/binary, Chunk/binary >>, {1, Streamed + RemSize}}; - %% Everything in Data is part of the chunk. - _ -> - Rem2 = Rem - DataSize, - {more, << Acc/binary, Data/binary >>, Rem2, {Rem2, Streamed + DataSize}} - end. - -chunked_len(<< $0, R/bits >>, S, A, Len) -> chunked_len(R, S, A, Len * 16); -chunked_len(<< $1, R/bits >>, S, A, Len) -> chunked_len(R, S, A, Len * 16 + 1); -chunked_len(<< $2, R/bits >>, S, A, Len) -> chunked_len(R, S, A, Len * 16 + 2); -chunked_len(<< $3, R/bits >>, S, A, Len) -> chunked_len(R, S, A, Len * 16 + 3); -chunked_len(<< $4, R/bits >>, S, A, Len) -> chunked_len(R, S, A, Len * 16 + 4); -chunked_len(<< $5, R/bits >>, S, A, Len) -> chunked_len(R, S, A, Len * 16 + 5); -chunked_len(<< $6, R/bits >>, S, A, Len) -> chunked_len(R, S, A, Len * 16 + 6); -chunked_len(<< $7, R/bits >>, S, A, Len) -> chunked_len(R, S, A, Len * 16 + 7); -chunked_len(<< $8, R/bits >>, S, A, Len) -> chunked_len(R, S, A, Len * 16 + 8); -chunked_len(<< $9, R/bits >>, S, A, Len) -> chunked_len(R, S, A, Len * 16 + 9); -chunked_len(<< $A, R/bits >>, S, A, Len) -> chunked_len(R, S, A, Len * 16 + 10); -chunked_len(<< $B, R/bits >>, S, A, Len) -> chunked_len(R, S, A, Len * 16 + 11); -chunked_len(<< $C, R/bits >>, S, A, Len) -> chunked_len(R, S, A, Len * 16 + 12); -chunked_len(<< $D, R/bits >>, S, A, Len) -> chunked_len(R, S, A, Len * 16 + 13); -chunked_len(<< $E, R/bits >>, S, A, Len) -> chunked_len(R, S, A, Len * 16 + 14); -chunked_len(<< $F, R/bits >>, S, A, Len) -> chunked_len(R, S, A, Len * 16 + 15); -chunked_len(<< $a, R/bits >>, S, A, Len) -> chunked_len(R, S, A, Len * 16 + 10); -chunked_len(<< $b, R/bits >>, S, A, Len) -> chunked_len(R, S, A, Len * 16 + 11); -chunked_len(<< $c, R/bits >>, S, A, Len) -> chunked_len(R, S, A, Len * 16 + 12); -chunked_len(<< $d, R/bits >>, S, A, Len) -> chunked_len(R, S, A, Len * 16 + 13); -chunked_len(<< $e, R/bits >>, S, A, Len) -> chunked_len(R, S, A, Len * 16 + 14); -chunked_len(<< $f, R/bits >>, S, A, Len) -> chunked_len(R, S, A, Len * 16 + 15); -%% Final chunk. -chunked_len(<< "\r\n\r\n", R/bits >>, S, <<>>, 0) -> {done, S, R}; -chunked_len(<< "\r\n\r\n", R/bits >>, S, A, 0) -> {done, A, S, R}; -chunked_len(_, _, _, 0) -> more; -%% Normal chunk. Add 2 to Len for the trailing \r\n. -chunked_len(<< "\r\n", R/bits >>, S, A, Len) -> {next, R, {Len + 2, S}, A}; -chunked_len(<<"\r">>, _, <<>>, _) -> more; -chunked_len(<<"\r">>, S, A, _) -> {more, {0, S}, A}; -chunked_len(<<>>, _, <<>>, _) -> more; -chunked_len(<<>>, S, A, _) -> {more, {0, S}, A}. - -%% @doc Encode a chunk. - --spec chunk(D) -> D when D::iodata(). -chunk(Data) -> - [integer_to_list(iolist_size(Data), 16), <<"\r\n">>, - Data, <<"\r\n">>]. - -%% @doc Encode the last chunk of a chunked stream. - --spec last_chunk() -> << _:40 >>. -last_chunk() -> - <<"0\r\n\r\n">>. - --ifdef(TEST). -stream_chunked_identity_test() -> - {done, <<"Wikipedia in\r\n\r\nchunks.">>, 23, <<>>} - = stream_chunked(iolist_to_binary([ - chunk("Wiki"), - chunk("pedia"), - chunk(" in\r\n\r\nchunks."), - last_chunk() - ]), {0, 0}), - ok. - -stream_chunked_one_pass_test() -> - {done, 0, <<>>} = stream_chunked(<<"0\r\n\r\n">>, {0, 0}), - {done, <<"Wikipedia in\r\n\r\nchunks.">>, 23, <<>>} - = stream_chunked(<< - "4\r\n" - "Wiki\r\n" - "5\r\n" - "pedia\r\n" - "e\r\n" - " in\r\n\r\nchunks.\r\n" - "0\r\n" - "\r\n">>, {0, 0}), - ok. - -stream_chunked_n_passes_test() -> - S0 = {0, 0}, - more = stream_chunked(<<"4\r">>, S0), - {more, <<>>, 6, S1} = stream_chunked(<<"4\r\n">>, S0), - {more, <<"Wiki">>, 0, S2} = stream_chunked(<<"Wiki\r\n">>, S1), - {more, <<"pedia">>, <<"e\r">>, S3} = stream_chunked(<<"5\r\npedia\r\ne\r">>, S2), - {more, <<" in\r\n\r\nchunks.">>, 2, S4} = stream_chunked(<<"e\r\n in\r\n\r\nchunks.">>, S3), - {done, 23, <<>>} = stream_chunked(<<"\r\n0\r\n\r\n">>, S4), - %% A few extra for coverage purposes. - more = stream_chunked(<<"\n3">>, {1, 0}), - {more, <<"abc">>, 2, {2, 3}} = stream_chunked(<<"\n3\r\nabc">>, {1, 0}), - {more, <<"abc">>, {1, 3}} = stream_chunked(<<"3\r\nabc\r">>, {0, 0}), - {more, <<"abc">>, <<"123">>, {0, 3}} = stream_chunked(<<"3\r\nabc\r\n123">>, {0, 0}), - ok. - -stream_chunked_dripfeed_test() -> - dripfeed(<< - "4\r\n" - "Wiki\r\n" - "5\r\n" - "pedia\r\n" - "e\r\n" - " in\r\n\r\nchunks.\r\n" - "0\r\n" - "\r\n">>, <<>>, {0, 0}, fun stream_chunked/2). - -do_body_to_chunks(_, <<>>, Acc) -> - lists:reverse([<<"0\r\n\r\n">>|Acc]); -do_body_to_chunks(ChunkSize, Body, Acc) -> - BodySize = byte_size(Body), - ChunkSize2 = case BodySize < ChunkSize of - true -> BodySize; - false -> ChunkSize - end, - << Chunk:ChunkSize2/binary, Rest/binary >> = Body, - ChunkSizeBin = list_to_binary(integer_to_list(ChunkSize2, 16)), - do_body_to_chunks(ChunkSize, Rest, - [<< ChunkSizeBin/binary, "\r\n", Chunk/binary, "\r\n" >>|Acc]). - -stream_chunked_dripfeed2_test() -> - Body = list_to_binary(io_lib:format("~p", [lists:seq(1, 100)])), - Body2 = iolist_to_binary(do_body_to_chunks(50, Body, [])), - dripfeed(Body2, <<>>, {0, 0}, fun stream_chunked/2). - -stream_chunked_error_test_() -> - Tests = [ - {<<>>, undefined}, - {<<"\n\naaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa">>, {2, 0}} - ], - [{lists:flatten(io_lib:format("value ~p state ~p", [V, S])), - fun() -> {'EXIT', _} = (catch stream_chunked(V, S)) end} - || {V, S} <- Tests]. --endif. - --ifdef(PERF). -horse_stream_chunked() -> - horse:repeat(10000, - stream_chunked(<< - "4\r\n" - "Wiki\r\n" - "5\r\n" - "pedia\r\n" - "e\r\n" - " in\r\n\r\nchunks.\r\n" - "0\r\n" - "\r\n">>, {0, 0}) - ). - -horse_stream_chunked_dripfeed() -> - horse:repeat(10000, - dripfeed(<< - "4\r\n" - "Wiki\r\n" - "5\r\n" - "pedia\r\n" - "e\r\n" - " in\r\n\r\nchunks.\r\n" - "0\r\n" - "\r\n">>, <<>>, {0, 43}, fun stream_chunked/2) - ). --endif. DELETED deps/cowlib/src/cow_mimetypes.erl Index: deps/cowlib/src/cow_mimetypes.erl ================================================================== --- deps/cowlib/src/cow_mimetypes.erl +++ /dev/null @@ -1,1041 +0,0 @@ -%% Copyright (c) 2013-2014, Loïc Hoguin -%% -%% Permission to use, copy, modify, and/or distribute this software for any -%% purpose with or without fee is hereby granted, provided that the above -%% copyright notice and this permission notice appear in all copies. -%% -%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - --module(cow_mimetypes). - --export([all/1]). --export([web/1]). - -%% @doc Return the mimetype for any file by looking at its extension. - --spec all(binary()) -> {binary(), binary(), []}. -all(Path) -> - case filename:extension(Path) of - <<>> -> {<<"application">>, <<"octet-stream">>, []}; - << $., Ext/binary >> -> all_ext(Ext) - end. - -%% @doc Return the mimetype for a Web related file by looking at its extension. - --spec web(binary()) -> {binary(), binary(), []}. -web(Path) -> - case filename:extension(Path) of - <<>> -> {<<"application">>, <<"octet-stream">>, []}; - << $., Ext/binary >> -> web_ext(Ext) - end. - -%% Internal. - -%% GENERATED -all_ext(<<"123">>) -> {<<"application">>, <<"vnd.lotus-1-2-3">>, []}; -all_ext(<<"3dml">>) -> {<<"text">>, <<"vnd.in3d.3dml">>, []}; -all_ext(<<"3ds">>) -> {<<"image">>, <<"x-3ds">>, []}; -all_ext(<<"3g2">>) -> {<<"video">>, <<"3gpp2">>, []}; -all_ext(<<"3gp">>) -> {<<"video">>, <<"3gpp">>, []}; -all_ext(<<"7z">>) -> {<<"application">>, <<"x-7z-compressed">>, []}; -all_ext(<<"aab">>) -> {<<"application">>, <<"x-authorware-bin">>, []}; -all_ext(<<"aac">>) -> {<<"audio">>, <<"x-aac">>, []}; -all_ext(<<"aam">>) -> {<<"application">>, <<"x-authorware-map">>, []}; -all_ext(<<"aas">>) -> {<<"application">>, <<"x-authorware-seg">>, []}; -all_ext(<<"abw">>) -> {<<"application">>, <<"x-abiword">>, []}; -all_ext(<<"ac">>) -> {<<"application">>, <<"pkix-attr-cert">>, []}; -all_ext(<<"acc">>) -> {<<"application">>, <<"vnd.americandynamics.acc">>, []}; -all_ext(<<"ace">>) -> {<<"application">>, <<"x-ace-compressed">>, []}; -all_ext(<<"acu">>) -> {<<"application">>, <<"vnd.acucobol">>, []}; -all_ext(<<"acutc">>) -> {<<"application">>, <<"vnd.acucorp">>, []}; -all_ext(<<"adp">>) -> {<<"audio">>, <<"adpcm">>, []}; -all_ext(<<"aep">>) -> {<<"application">>, <<"vnd.audiograph">>, []}; -all_ext(<<"afm">>) -> {<<"application">>, <<"x-font-type1">>, []}; -all_ext(<<"afp">>) -> {<<"application">>, <<"vnd.ibm.modcap">>, []}; -all_ext(<<"ahead">>) -> {<<"application">>, <<"vnd.ahead.space">>, []}; -all_ext(<<"ai">>) -> {<<"application">>, <<"postscript">>, []}; -all_ext(<<"aif">>) -> {<<"audio">>, <<"x-aiff">>, []}; -all_ext(<<"aifc">>) -> {<<"audio">>, <<"x-aiff">>, []}; -all_ext(<<"aiff">>) -> {<<"audio">>, <<"x-aiff">>, []}; -all_ext(<<"air">>) -> {<<"application">>, <<"vnd.adobe.air-application-installer-package+zip">>, []}; -all_ext(<<"ait">>) -> {<<"application">>, <<"vnd.dvb.ait">>, []}; -all_ext(<<"ami">>) -> {<<"application">>, <<"vnd.amiga.ami">>, []}; -all_ext(<<"apk">>) -> {<<"application">>, <<"vnd.android.package-archive">>, []}; -all_ext(<<"appcache">>) -> {<<"text">>, <<"cache-manifest">>, []}; -all_ext(<<"application">>) -> {<<"application">>, <<"x-ms-application">>, []}; -all_ext(<<"apr">>) -> {<<"application">>, <<"vnd.lotus-approach">>, []}; -all_ext(<<"arc">>) -> {<<"application">>, <<"x-freearc">>, []}; -all_ext(<<"asc">>) -> {<<"application">>, <<"pgp-signature">>, []}; -all_ext(<<"asf">>) -> {<<"video">>, <<"x-ms-asf">>, []}; -all_ext(<<"asm">>) -> {<<"text">>, <<"x-asm">>, []}; -all_ext(<<"aso">>) -> {<<"application">>, <<"vnd.accpac.simply.aso">>, []}; -all_ext(<<"asx">>) -> {<<"video">>, <<"x-ms-asf">>, []}; -all_ext(<<"atc">>) -> {<<"application">>, <<"vnd.acucorp">>, []}; -all_ext(<<"atom">>) -> {<<"application">>, <<"atom+xml">>, []}; -all_ext(<<"atomcat">>) -> {<<"application">>, <<"atomcat+xml">>, []}; -all_ext(<<"atomsvc">>) -> {<<"application">>, <<"atomsvc+xml">>, []}; -all_ext(<<"atx">>) -> {<<"application">>, <<"vnd.antix.game-component">>, []}; -all_ext(<<"au">>) -> {<<"audio">>, <<"basic">>, []}; -all_ext(<<"avi">>) -> {<<"video">>, <<"x-msvideo">>, []}; -all_ext(<<"aw">>) -> {<<"application">>, <<"applixware">>, []}; -all_ext(<<"azf">>) -> {<<"application">>, <<"vnd.airzip.filesecure.azf">>, []}; -all_ext(<<"azs">>) -> {<<"application">>, <<"vnd.airzip.filesecure.azs">>, []}; -all_ext(<<"azw">>) -> {<<"application">>, <<"vnd.amazon.ebook">>, []}; -all_ext(<<"bat">>) -> {<<"application">>, <<"x-msdownload">>, []}; -all_ext(<<"bcpio">>) -> {<<"application">>, <<"x-bcpio">>, []}; -all_ext(<<"bdf">>) -> {<<"application">>, <<"x-font-bdf">>, []}; -all_ext(<<"bdm">>) -> {<<"application">>, <<"vnd.syncml.dm+wbxml">>, []}; -all_ext(<<"bed">>) -> {<<"application">>, <<"vnd.realvnc.bed">>, []}; -all_ext(<<"bh2">>) -> {<<"application">>, <<"vnd.fujitsu.oasysprs">>, []}; -all_ext(<<"bin">>) -> {<<"application">>, <<"octet-stream">>, []}; -all_ext(<<"blb">>) -> {<<"application">>, <<"x-blorb">>, []}; -all_ext(<<"blorb">>) -> {<<"application">>, <<"x-blorb">>, []}; -all_ext(<<"bmi">>) -> {<<"application">>, <<"vnd.bmi">>, []}; -all_ext(<<"bmp">>) -> {<<"image">>, <<"bmp">>, []}; -all_ext(<<"book">>) -> {<<"application">>, <<"vnd.framemaker">>, []}; -all_ext(<<"box">>) -> {<<"application">>, <<"vnd.previewsystems.box">>, []}; -all_ext(<<"boz">>) -> {<<"application">>, <<"x-bzip2">>, []}; -all_ext(<<"bpk">>) -> {<<"application">>, <<"octet-stream">>, []}; -all_ext(<<"btif">>) -> {<<"image">>, <<"prs.btif">>, []}; -all_ext(<<"bz2">>) -> {<<"application">>, <<"x-bzip2">>, []}; -all_ext(<<"bz">>) -> {<<"application">>, <<"x-bzip">>, []}; -all_ext(<<"c11amc">>) -> {<<"application">>, <<"vnd.cluetrust.cartomobile-config">>, []}; -all_ext(<<"c11amz">>) -> {<<"application">>, <<"vnd.cluetrust.cartomobile-config-pkg">>, []}; -all_ext(<<"c4d">>) -> {<<"application">>, <<"vnd.clonk.c4group">>, []}; -all_ext(<<"c4f">>) -> {<<"application">>, <<"vnd.clonk.c4group">>, []}; -all_ext(<<"c4g">>) -> {<<"application">>, <<"vnd.clonk.c4group">>, []}; -all_ext(<<"c4p">>) -> {<<"application">>, <<"vnd.clonk.c4group">>, []}; -all_ext(<<"c4u">>) -> {<<"application">>, <<"vnd.clonk.c4group">>, []}; -all_ext(<<"cab">>) -> {<<"application">>, <<"vnd.ms-cab-compressed">>, []}; -all_ext(<<"caf">>) -> {<<"audio">>, <<"x-caf">>, []}; -all_ext(<<"cap">>) -> {<<"application">>, <<"vnd.tcpdump.pcap">>, []}; -all_ext(<<"car">>) -> {<<"application">>, <<"vnd.curl.car">>, []}; -all_ext(<<"cat">>) -> {<<"application">>, <<"vnd.ms-pki.seccat">>, []}; -all_ext(<<"cb7">>) -> {<<"application">>, <<"x-cbr">>, []}; -all_ext(<<"cba">>) -> {<<"application">>, <<"x-cbr">>, []}; -all_ext(<<"cbr">>) -> {<<"application">>, <<"x-cbr">>, []}; -all_ext(<<"cbt">>) -> {<<"application">>, <<"x-cbr">>, []}; -all_ext(<<"cbz">>) -> {<<"application">>, <<"x-cbr">>, []}; -all_ext(<<"cct">>) -> {<<"application">>, <<"x-director">>, []}; -all_ext(<<"cc">>) -> {<<"text">>, <<"x-c">>, []}; -all_ext(<<"ccxml">>) -> {<<"application">>, <<"ccxml+xml">>, []}; -all_ext(<<"cdbcmsg">>) -> {<<"application">>, <<"vnd.contact.cmsg">>, []}; -all_ext(<<"cdf">>) -> {<<"application">>, <<"x-netcdf">>, []}; -all_ext(<<"cdkey">>) -> {<<"application">>, <<"vnd.mediastation.cdkey">>, []}; -all_ext(<<"cdmia">>) -> {<<"application">>, <<"cdmi-capability">>, []}; -all_ext(<<"cdmic">>) -> {<<"application">>, <<"cdmi-container">>, []}; -all_ext(<<"cdmid">>) -> {<<"application">>, <<"cdmi-domain">>, []}; -all_ext(<<"cdmio">>) -> {<<"application">>, <<"cdmi-object">>, []}; -all_ext(<<"cdmiq">>) -> {<<"application">>, <<"cdmi-queue">>, []}; -all_ext(<<"cdx">>) -> {<<"chemical">>, <<"x-cdx">>, []}; -all_ext(<<"cdxml">>) -> {<<"application">>, <<"vnd.chemdraw+xml">>, []}; -all_ext(<<"cdy">>) -> {<<"application">>, <<"vnd.cinderella">>, []}; -all_ext(<<"cer">>) -> {<<"application">>, <<"pkix-cert">>, []}; -all_ext(<<"cfs">>) -> {<<"application">>, <<"x-cfs-compressed">>, []}; -all_ext(<<"cgm">>) -> {<<"image">>, <<"cgm">>, []}; -all_ext(<<"chat">>) -> {<<"application">>, <<"x-chat">>, []}; -all_ext(<<"chm">>) -> {<<"application">>, <<"vnd.ms-htmlhelp">>, []}; -all_ext(<<"chrt">>) -> {<<"application">>, <<"vnd.kde.kchart">>, []}; -all_ext(<<"cif">>) -> {<<"chemical">>, <<"x-cif">>, []}; -all_ext(<<"cii">>) -> {<<"application">>, <<"vnd.anser-web-certificate-issue-initiation">>, []}; -all_ext(<<"cil">>) -> {<<"application">>, <<"vnd.ms-artgalry">>, []}; -all_ext(<<"cla">>) -> {<<"application">>, <<"vnd.claymore">>, []}; -all_ext(<<"class">>) -> {<<"application">>, <<"java-vm">>, []}; -all_ext(<<"clkk">>) -> {<<"application">>, <<"vnd.crick.clicker.keyboard">>, []}; -all_ext(<<"clkp">>) -> {<<"application">>, <<"vnd.crick.clicker.palette">>, []}; -all_ext(<<"clkt">>) -> {<<"application">>, <<"vnd.crick.clicker.template">>, []}; -all_ext(<<"clkw">>) -> {<<"application">>, <<"vnd.crick.clicker.wordbank">>, []}; -all_ext(<<"clkx">>) -> {<<"application">>, <<"vnd.crick.clicker">>, []}; -all_ext(<<"clp">>) -> {<<"application">>, <<"x-msclip">>, []}; -all_ext(<<"cmc">>) -> {<<"application">>, <<"vnd.cosmocaller">>, []}; -all_ext(<<"cmdf">>) -> {<<"chemical">>, <<"x-cmdf">>, []}; -all_ext(<<"cml">>) -> {<<"chemical">>, <<"x-cml">>, []}; -all_ext(<<"cmp">>) -> {<<"application">>, <<"vnd.yellowriver-custom-menu">>, []}; -all_ext(<<"cmx">>) -> {<<"image">>, <<"x-cmx">>, []}; -all_ext(<<"cod">>) -> {<<"application">>, <<"vnd.rim.cod">>, []}; -all_ext(<<"com">>) -> {<<"application">>, <<"x-msdownload">>, []}; -all_ext(<<"conf">>) -> {<<"text">>, <<"plain">>, []}; -all_ext(<<"cpio">>) -> {<<"application">>, <<"x-cpio">>, []}; -all_ext(<<"cpp">>) -> {<<"text">>, <<"x-c">>, []}; -all_ext(<<"cpt">>) -> {<<"application">>, <<"mac-compactpro">>, []}; -all_ext(<<"crd">>) -> {<<"application">>, <<"x-mscardfile">>, []}; -all_ext(<<"crl">>) -> {<<"application">>, <<"pkix-crl">>, []}; -all_ext(<<"crt">>) -> {<<"application">>, <<"x-x509-ca-cert">>, []}; -all_ext(<<"cryptonote">>) -> {<<"application">>, <<"vnd.rig.cryptonote">>, []}; -all_ext(<<"csh">>) -> {<<"application">>, <<"x-csh">>, []}; -all_ext(<<"csml">>) -> {<<"chemical">>, <<"x-csml">>, []}; -all_ext(<<"csp">>) -> {<<"application">>, <<"vnd.commonspace">>, []}; -all_ext(<<"css">>) -> {<<"text">>, <<"css">>, []}; -all_ext(<<"cst">>) -> {<<"application">>, <<"x-director">>, []}; -all_ext(<<"csv">>) -> {<<"text">>, <<"csv">>, []}; -all_ext(<<"c">>) -> {<<"text">>, <<"x-c">>, []}; -all_ext(<<"cu">>) -> {<<"application">>, <<"cu-seeme">>, []}; -all_ext(<<"curl">>) -> {<<"text">>, <<"vnd.curl">>, []}; -all_ext(<<"cww">>) -> {<<"application">>, <<"prs.cww">>, []}; -all_ext(<<"cxt">>) -> {<<"application">>, <<"x-director">>, []}; -all_ext(<<"cxx">>) -> {<<"text">>, <<"x-c">>, []}; -all_ext(<<"dae">>) -> {<<"model">>, <<"vnd.collada+xml">>, []}; -all_ext(<<"daf">>) -> {<<"application">>, <<"vnd.mobius.daf">>, []}; -all_ext(<<"dart">>) -> {<<"application">>, <<"vnd.dart">>, []}; -all_ext(<<"dataless">>) -> {<<"application">>, <<"vnd.fdsn.seed">>, []}; -all_ext(<<"davmount">>) -> {<<"application">>, <<"davmount+xml">>, []}; -all_ext(<<"dbk">>) -> {<<"application">>, <<"docbook+xml">>, []}; -all_ext(<<"dcr">>) -> {<<"application">>, <<"x-director">>, []}; -all_ext(<<"dcurl">>) -> {<<"text">>, <<"vnd.curl.dcurl">>, []}; -all_ext(<<"dd2">>) -> {<<"application">>, <<"vnd.oma.dd2+xml">>, []}; -all_ext(<<"ddd">>) -> {<<"application">>, <<"vnd.fujixerox.ddd">>, []}; -all_ext(<<"deb">>) -> {<<"application">>, <<"x-debian-package">>, []}; -all_ext(<<"def">>) -> {<<"text">>, <<"plain">>, []}; -all_ext(<<"deploy">>) -> {<<"application">>, <<"octet-stream">>, []}; -all_ext(<<"der">>) -> {<<"application">>, <<"x-x509-ca-cert">>, []}; -all_ext(<<"dfac">>) -> {<<"application">>, <<"vnd.dreamfactory">>, []}; -all_ext(<<"dgc">>) -> {<<"application">>, <<"x-dgc-compressed">>, []}; -all_ext(<<"dic">>) -> {<<"text">>, <<"x-c">>, []}; -all_ext(<<"dir">>) -> {<<"application">>, <<"x-director">>, []}; -all_ext(<<"dis">>) -> {<<"application">>, <<"vnd.mobius.dis">>, []}; -all_ext(<<"dist">>) -> {<<"application">>, <<"octet-stream">>, []}; -all_ext(<<"distz">>) -> {<<"application">>, <<"octet-stream">>, []}; -all_ext(<<"djv">>) -> {<<"image">>, <<"vnd.djvu">>, []}; -all_ext(<<"djvu">>) -> {<<"image">>, <<"vnd.djvu">>, []}; -all_ext(<<"dll">>) -> {<<"application">>, <<"x-msdownload">>, []}; -all_ext(<<"dmg">>) -> {<<"application">>, <<"x-apple-diskimage">>, []}; -all_ext(<<"dmp">>) -> {<<"application">>, <<"vnd.tcpdump.pcap">>, []}; -all_ext(<<"dms">>) -> {<<"application">>, <<"octet-stream">>, []}; -all_ext(<<"dna">>) -> {<<"application">>, <<"vnd.dna">>, []}; -all_ext(<<"doc">>) -> {<<"application">>, <<"msword">>, []}; -all_ext(<<"docm">>) -> {<<"application">>, <<"vnd.ms-word.document.macroenabled.12">>, []}; -all_ext(<<"docx">>) -> {<<"application">>, <<"vnd.openxmlformats-officedocument.wordprocessingml.document">>, []}; -all_ext(<<"dot">>) -> {<<"application">>, <<"msword">>, []}; -all_ext(<<"dotm">>) -> {<<"application">>, <<"vnd.ms-word.template.macroenabled.12">>, []}; -all_ext(<<"dotx">>) -> {<<"application">>, <<"vnd.openxmlformats-officedocument.wordprocessingml.template">>, []}; -all_ext(<<"dp">>) -> {<<"application">>, <<"vnd.osgi.dp">>, []}; -all_ext(<<"dpg">>) -> {<<"application">>, <<"vnd.dpgraph">>, []}; -all_ext(<<"dra">>) -> {<<"audio">>, <<"vnd.dra">>, []}; -all_ext(<<"dsc">>) -> {<<"text">>, <<"prs.lines.tag">>, []}; -all_ext(<<"dssc">>) -> {<<"application">>, <<"dssc+der">>, []}; -all_ext(<<"dtb">>) -> {<<"application">>, <<"x-dtbook+xml">>, []}; -all_ext(<<"dtd">>) -> {<<"application">>, <<"xml-dtd">>, []}; -all_ext(<<"dts">>) -> {<<"audio">>, <<"vnd.dts">>, []}; -all_ext(<<"dtshd">>) -> {<<"audio">>, <<"vnd.dts.hd">>, []}; -all_ext(<<"dump">>) -> {<<"application">>, <<"octet-stream">>, []}; -all_ext(<<"dvb">>) -> {<<"video">>, <<"vnd.dvb.file">>, []}; -all_ext(<<"dvi">>) -> {<<"application">>, <<"x-dvi">>, []}; -all_ext(<<"dwf">>) -> {<<"model">>, <<"vnd.dwf">>, []}; -all_ext(<<"dwg">>) -> {<<"image">>, <<"vnd.dwg">>, []}; -all_ext(<<"dxf">>) -> {<<"image">>, <<"vnd.dxf">>, []}; -all_ext(<<"dxp">>) -> {<<"application">>, <<"vnd.spotfire.dxp">>, []}; -all_ext(<<"dxr">>) -> {<<"application">>, <<"x-director">>, []}; -all_ext(<<"ecelp4800">>) -> {<<"audio">>, <<"vnd.nuera.ecelp4800">>, []}; -all_ext(<<"ecelp7470">>) -> {<<"audio">>, <<"vnd.nuera.ecelp7470">>, []}; -all_ext(<<"ecelp9600">>) -> {<<"audio">>, <<"vnd.nuera.ecelp9600">>, []}; -all_ext(<<"ecma">>) -> {<<"application">>, <<"ecmascript">>, []}; -all_ext(<<"edm">>) -> {<<"application">>, <<"vnd.novadigm.edm">>, []}; -all_ext(<<"edx">>) -> {<<"application">>, <<"vnd.novadigm.edx">>, []}; -all_ext(<<"efif">>) -> {<<"application">>, <<"vnd.picsel">>, []}; -all_ext(<<"ei6">>) -> {<<"application">>, <<"vnd.pg.osasli">>, []}; -all_ext(<<"elc">>) -> {<<"application">>, <<"octet-stream">>, []}; -all_ext(<<"emf">>) -> {<<"application">>, <<"x-msmetafile">>, []}; -all_ext(<<"eml">>) -> {<<"message">>, <<"rfc822">>, []}; -all_ext(<<"emma">>) -> {<<"application">>, <<"emma+xml">>, []}; -all_ext(<<"emz">>) -> {<<"application">>, <<"x-msmetafile">>, []}; -all_ext(<<"eol">>) -> {<<"audio">>, <<"vnd.digital-winds">>, []}; -all_ext(<<"eot">>) -> {<<"application">>, <<"vnd.ms-fontobject">>, []}; -all_ext(<<"eps">>) -> {<<"application">>, <<"postscript">>, []}; -all_ext(<<"epub">>) -> {<<"application">>, <<"epub+zip">>, []}; -all_ext(<<"es3">>) -> {<<"application">>, <<"vnd.eszigno3+xml">>, []}; -all_ext(<<"esa">>) -> {<<"application">>, <<"vnd.osgi.subsystem">>, []}; -all_ext(<<"esf">>) -> {<<"application">>, <<"vnd.epson.esf">>, []}; -all_ext(<<"et3">>) -> {<<"application">>, <<"vnd.eszigno3+xml">>, []}; -all_ext(<<"etx">>) -> {<<"text">>, <<"x-setext">>, []}; -all_ext(<<"eva">>) -> {<<"application">>, <<"x-eva">>, []}; -all_ext(<<"evy">>) -> {<<"application">>, <<"x-envoy">>, []}; -all_ext(<<"exe">>) -> {<<"application">>, <<"x-msdownload">>, []}; -all_ext(<<"exi">>) -> {<<"application">>, <<"exi">>, []}; -all_ext(<<"ext">>) -> {<<"application">>, <<"vnd.novadigm.ext">>, []}; -all_ext(<<"ez2">>) -> {<<"application">>, <<"vnd.ezpix-album">>, []}; -all_ext(<<"ez3">>) -> {<<"application">>, <<"vnd.ezpix-package">>, []}; -all_ext(<<"ez">>) -> {<<"application">>, <<"andrew-inset">>, []}; -all_ext(<<"f4v">>) -> {<<"video">>, <<"x-f4v">>, []}; -all_ext(<<"f77">>) -> {<<"text">>, <<"x-fortran">>, []}; -all_ext(<<"f90">>) -> {<<"text">>, <<"x-fortran">>, []}; -all_ext(<<"fbs">>) -> {<<"image">>, <<"vnd.fastbidsheet">>, []}; -all_ext(<<"fcdt">>) -> {<<"application">>, <<"vnd.adobe.formscentral.fcdt">>, []}; -all_ext(<<"fcs">>) -> {<<"application">>, <<"vnd.isac.fcs">>, []}; -all_ext(<<"fdf">>) -> {<<"application">>, <<"vnd.fdf">>, []}; -all_ext(<<"fe_launch">>) -> {<<"application">>, <<"vnd.denovo.fcselayout-link">>, []}; -all_ext(<<"fg5">>) -> {<<"application">>, <<"vnd.fujitsu.oasysgp">>, []}; -all_ext(<<"fgd">>) -> {<<"application">>, <<"x-director">>, []}; -all_ext(<<"fh4">>) -> {<<"image">>, <<"x-freehand">>, []}; -all_ext(<<"fh5">>) -> {<<"image">>, <<"x-freehand">>, []}; -all_ext(<<"fh7">>) -> {<<"image">>, <<"x-freehand">>, []}; -all_ext(<<"fhc">>) -> {<<"image">>, <<"x-freehand">>, []}; -all_ext(<<"fh">>) -> {<<"image">>, <<"x-freehand">>, []}; -all_ext(<<"fig">>) -> {<<"application">>, <<"x-xfig">>, []}; -all_ext(<<"flac">>) -> {<<"audio">>, <<"x-flac">>, []}; -all_ext(<<"fli">>) -> {<<"video">>, <<"x-fli">>, []}; -all_ext(<<"flo">>) -> {<<"application">>, <<"vnd.micrografx.flo">>, []}; -all_ext(<<"flv">>) -> {<<"video">>, <<"x-flv">>, []}; -all_ext(<<"flw">>) -> {<<"application">>, <<"vnd.kde.kivio">>, []}; -all_ext(<<"flx">>) -> {<<"text">>, <<"vnd.fmi.flexstor">>, []}; -all_ext(<<"fly">>) -> {<<"text">>, <<"vnd.fly">>, []}; -all_ext(<<"fm">>) -> {<<"application">>, <<"vnd.framemaker">>, []}; -all_ext(<<"fnc">>) -> {<<"application">>, <<"vnd.frogans.fnc">>, []}; -all_ext(<<"for">>) -> {<<"text">>, <<"x-fortran">>, []}; -all_ext(<<"fpx">>) -> {<<"image">>, <<"vnd.fpx">>, []}; -all_ext(<<"frame">>) -> {<<"application">>, <<"vnd.framemaker">>, []}; -all_ext(<<"fsc">>) -> {<<"application">>, <<"vnd.fsc.weblaunch">>, []}; -all_ext(<<"fst">>) -> {<<"image">>, <<"vnd.fst">>, []}; -all_ext(<<"ftc">>) -> {<<"application">>, <<"vnd.fluxtime.clip">>, []}; -all_ext(<<"f">>) -> {<<"text">>, <<"x-fortran">>, []}; -all_ext(<<"fti">>) -> {<<"application">>, <<"vnd.anser-web-funds-transfer-initiation">>, []}; -all_ext(<<"fvt">>) -> {<<"video">>, <<"vnd.fvt">>, []}; -all_ext(<<"fxp">>) -> {<<"application">>, <<"vnd.adobe.fxp">>, []}; -all_ext(<<"fxpl">>) -> {<<"application">>, <<"vnd.adobe.fxp">>, []}; -all_ext(<<"fzs">>) -> {<<"application">>, <<"vnd.fuzzysheet">>, []}; -all_ext(<<"g2w">>) -> {<<"application">>, <<"vnd.geoplan">>, []}; -all_ext(<<"g3">>) -> {<<"image">>, <<"g3fax">>, []}; -all_ext(<<"g3w">>) -> {<<"application">>, <<"vnd.geospace">>, []}; -all_ext(<<"gac">>) -> {<<"application">>, <<"vnd.groove-account">>, []}; -all_ext(<<"gam">>) -> {<<"application">>, <<"x-tads">>, []}; -all_ext(<<"gbr">>) -> {<<"application">>, <<"rpki-ghostbusters">>, []}; -all_ext(<<"gca">>) -> {<<"application">>, <<"x-gca-compressed">>, []}; -all_ext(<<"gdl">>) -> {<<"model">>, <<"vnd.gdl">>, []}; -all_ext(<<"geo">>) -> {<<"application">>, <<"vnd.dynageo">>, []}; -all_ext(<<"gex">>) -> {<<"application">>, <<"vnd.geometry-explorer">>, []}; -all_ext(<<"ggb">>) -> {<<"application">>, <<"vnd.geogebra.file">>, []}; -all_ext(<<"ggt">>) -> {<<"application">>, <<"vnd.geogebra.tool">>, []}; -all_ext(<<"ghf">>) -> {<<"application">>, <<"vnd.groove-help">>, []}; -all_ext(<<"gif">>) -> {<<"image">>, <<"gif">>, []}; -all_ext(<<"gim">>) -> {<<"application">>, <<"vnd.groove-identity-message">>, []}; -all_ext(<<"gml">>) -> {<<"application">>, <<"gml+xml">>, []}; -all_ext(<<"gmx">>) -> {<<"application">>, <<"vnd.gmx">>, []}; -all_ext(<<"gnumeric">>) -> {<<"application">>, <<"x-gnumeric">>, []}; -all_ext(<<"gph">>) -> {<<"application">>, <<"vnd.flographit">>, []}; -all_ext(<<"gpx">>) -> {<<"application">>, <<"gpx+xml">>, []}; -all_ext(<<"gqf">>) -> {<<"application">>, <<"vnd.grafeq">>, []}; -all_ext(<<"gqs">>) -> {<<"application">>, <<"vnd.grafeq">>, []}; -all_ext(<<"gram">>) -> {<<"application">>, <<"srgs">>, []}; -all_ext(<<"gramps">>) -> {<<"application">>, <<"x-gramps-xml">>, []}; -all_ext(<<"gre">>) -> {<<"application">>, <<"vnd.geometry-explorer">>, []}; -all_ext(<<"grv">>) -> {<<"application">>, <<"vnd.groove-injector">>, []}; -all_ext(<<"grxml">>) -> {<<"application">>, <<"srgs+xml">>, []}; -all_ext(<<"gsf">>) -> {<<"application">>, <<"x-font-ghostscript">>, []}; -all_ext(<<"gtar">>) -> {<<"application">>, <<"x-gtar">>, []}; -all_ext(<<"gtm">>) -> {<<"application">>, <<"vnd.groove-tool-message">>, []}; -all_ext(<<"gtw">>) -> {<<"model">>, <<"vnd.gtw">>, []}; -all_ext(<<"gv">>) -> {<<"text">>, <<"vnd.graphviz">>, []}; -all_ext(<<"gxf">>) -> {<<"application">>, <<"gxf">>, []}; -all_ext(<<"gxt">>) -> {<<"application">>, <<"vnd.geonext">>, []}; -all_ext(<<"h261">>) -> {<<"video">>, <<"h261">>, []}; -all_ext(<<"h263">>) -> {<<"video">>, <<"h263">>, []}; -all_ext(<<"h264">>) -> {<<"video">>, <<"h264">>, []}; -all_ext(<<"hal">>) -> {<<"application">>, <<"vnd.hal+xml">>, []}; -all_ext(<<"hbci">>) -> {<<"application">>, <<"vnd.hbci">>, []}; -all_ext(<<"hdf">>) -> {<<"application">>, <<"x-hdf">>, []}; -all_ext(<<"hh">>) -> {<<"text">>, <<"x-c">>, []}; -all_ext(<<"hlp">>) -> {<<"application">>, <<"winhlp">>, []}; -all_ext(<<"hpgl">>) -> {<<"application">>, <<"vnd.hp-hpgl">>, []}; -all_ext(<<"hpid">>) -> {<<"application">>, <<"vnd.hp-hpid">>, []}; -all_ext(<<"hps">>) -> {<<"application">>, <<"vnd.hp-hps">>, []}; -all_ext(<<"hqx">>) -> {<<"application">>, <<"mac-binhex40">>, []}; -all_ext(<<"h">>) -> {<<"text">>, <<"x-c">>, []}; -all_ext(<<"htke">>) -> {<<"application">>, <<"vnd.kenameaapp">>, []}; -all_ext(<<"html">>) -> {<<"text">>, <<"html">>, []}; -all_ext(<<"htm">>) -> {<<"text">>, <<"html">>, []}; -all_ext(<<"hvd">>) -> {<<"application">>, <<"vnd.yamaha.hv-dic">>, []}; -all_ext(<<"hvp">>) -> {<<"application">>, <<"vnd.yamaha.hv-voice">>, []}; -all_ext(<<"hvs">>) -> {<<"application">>, <<"vnd.yamaha.hv-script">>, []}; -all_ext(<<"i2g">>) -> {<<"application">>, <<"vnd.intergeo">>, []}; -all_ext(<<"icc">>) -> {<<"application">>, <<"vnd.iccprofile">>, []}; -all_ext(<<"ice">>) -> {<<"x-conference">>, <<"x-cooltalk">>, []}; -all_ext(<<"icm">>) -> {<<"application">>, <<"vnd.iccprofile">>, []}; -all_ext(<<"ico">>) -> {<<"image">>, <<"x-icon">>, []}; -all_ext(<<"ics">>) -> {<<"text">>, <<"calendar">>, []}; -all_ext(<<"ief">>) -> {<<"image">>, <<"ief">>, []}; -all_ext(<<"ifb">>) -> {<<"text">>, <<"calendar">>, []}; -all_ext(<<"ifm">>) -> {<<"application">>, <<"vnd.shana.informed.formdata">>, []}; -all_ext(<<"iges">>) -> {<<"model">>, <<"iges">>, []}; -all_ext(<<"igl">>) -> {<<"application">>, <<"vnd.igloader">>, []}; -all_ext(<<"igm">>) -> {<<"application">>, <<"vnd.insors.igm">>, []}; -all_ext(<<"igs">>) -> {<<"model">>, <<"iges">>, []}; -all_ext(<<"igx">>) -> {<<"application">>, <<"vnd.micrografx.igx">>, []}; -all_ext(<<"iif">>) -> {<<"application">>, <<"vnd.shana.informed.interchange">>, []}; -all_ext(<<"imp">>) -> {<<"application">>, <<"vnd.accpac.simply.imp">>, []}; -all_ext(<<"ims">>) -> {<<"application">>, <<"vnd.ms-ims">>, []}; -all_ext(<<"ink">>) -> {<<"application">>, <<"inkml+xml">>, []}; -all_ext(<<"inkml">>) -> {<<"application">>, <<"inkml+xml">>, []}; -all_ext(<<"install">>) -> {<<"application">>, <<"x-install-instructions">>, []}; -all_ext(<<"in">>) -> {<<"text">>, <<"plain">>, []}; -all_ext(<<"iota">>) -> {<<"application">>, <<"vnd.astraea-software.iota">>, []}; -all_ext(<<"ipfix">>) -> {<<"application">>, <<"ipfix">>, []}; -all_ext(<<"ipk">>) -> {<<"application">>, <<"vnd.shana.informed.package">>, []}; -all_ext(<<"irm">>) -> {<<"application">>, <<"vnd.ibm.rights-management">>, []}; -all_ext(<<"irp">>) -> {<<"application">>, <<"vnd.irepository.package+xml">>, []}; -all_ext(<<"iso">>) -> {<<"application">>, <<"x-iso9660-image">>, []}; -all_ext(<<"itp">>) -> {<<"application">>, <<"vnd.shana.informed.formtemplate">>, []}; -all_ext(<<"ivp">>) -> {<<"application">>, <<"vnd.immervision-ivp">>, []}; -all_ext(<<"ivu">>) -> {<<"application">>, <<"vnd.immervision-ivu">>, []}; -all_ext(<<"jad">>) -> {<<"text">>, <<"vnd.sun.j2me.app-descriptor">>, []}; -all_ext(<<"jam">>) -> {<<"application">>, <<"vnd.jam">>, []}; -all_ext(<<"jar">>) -> {<<"application">>, <<"java-archive">>, []}; -all_ext(<<"java">>) -> {<<"text">>, <<"x-java-source">>, []}; -all_ext(<<"jisp">>) -> {<<"application">>, <<"vnd.jisp">>, []}; -all_ext(<<"jlt">>) -> {<<"application">>, <<"vnd.hp-jlyt">>, []}; -all_ext(<<"jnlp">>) -> {<<"application">>, <<"x-java-jnlp-file">>, []}; -all_ext(<<"joda">>) -> {<<"application">>, <<"vnd.joost.joda-archive">>, []}; -all_ext(<<"jpeg">>) -> {<<"image">>, <<"jpeg">>, []}; -all_ext(<<"jpe">>) -> {<<"image">>, <<"jpeg">>, []}; -all_ext(<<"jpg">>) -> {<<"image">>, <<"jpeg">>, []}; -all_ext(<<"jpgm">>) -> {<<"video">>, <<"jpm">>, []}; -all_ext(<<"jpgv">>) -> {<<"video">>, <<"jpeg">>, []}; -all_ext(<<"jpm">>) -> {<<"video">>, <<"jpm">>, []}; -all_ext(<<"js">>) -> {<<"application">>, <<"javascript">>, []}; -all_ext(<<"json">>) -> {<<"application">>, <<"json">>, []}; -all_ext(<<"jsonml">>) -> {<<"application">>, <<"jsonml+json">>, []}; -all_ext(<<"kar">>) -> {<<"audio">>, <<"midi">>, []}; -all_ext(<<"karbon">>) -> {<<"application">>, <<"vnd.kde.karbon">>, []}; -all_ext(<<"kfo">>) -> {<<"application">>, <<"vnd.kde.kformula">>, []}; -all_ext(<<"kia">>) -> {<<"application">>, <<"vnd.kidspiration">>, []}; -all_ext(<<"kml">>) -> {<<"application">>, <<"vnd.google-earth.kml+xml">>, []}; -all_ext(<<"kmz">>) -> {<<"application">>, <<"vnd.google-earth.kmz">>, []}; -all_ext(<<"kne">>) -> {<<"application">>, <<"vnd.kinar">>, []}; -all_ext(<<"knp">>) -> {<<"application">>, <<"vnd.kinar">>, []}; -all_ext(<<"kon">>) -> {<<"application">>, <<"vnd.kde.kontour">>, []}; -all_ext(<<"kpr">>) -> {<<"application">>, <<"vnd.kde.kpresenter">>, []}; -all_ext(<<"kpt">>) -> {<<"application">>, <<"vnd.kde.kpresenter">>, []}; -all_ext(<<"kpxx">>) -> {<<"application">>, <<"vnd.ds-keypoint">>, []}; -all_ext(<<"ksp">>) -> {<<"application">>, <<"vnd.kde.kspread">>, []}; -all_ext(<<"ktr">>) -> {<<"application">>, <<"vnd.kahootz">>, []}; -all_ext(<<"ktx">>) -> {<<"image">>, <<"ktx">>, []}; -all_ext(<<"ktz">>) -> {<<"application">>, <<"vnd.kahootz">>, []}; -all_ext(<<"kwd">>) -> {<<"application">>, <<"vnd.kde.kword">>, []}; -all_ext(<<"kwt">>) -> {<<"application">>, <<"vnd.kde.kword">>, []}; -all_ext(<<"lasxml">>) -> {<<"application">>, <<"vnd.las.las+xml">>, []}; -all_ext(<<"latex">>) -> {<<"application">>, <<"x-latex">>, []}; -all_ext(<<"lbd">>) -> {<<"application">>, <<"vnd.llamagraphics.life-balance.desktop">>, []}; -all_ext(<<"lbe">>) -> {<<"application">>, <<"vnd.llamagraphics.life-balance.exchange+xml">>, []}; -all_ext(<<"les">>) -> {<<"application">>, <<"vnd.hhe.lesson-player">>, []}; -all_ext(<<"lha">>) -> {<<"application">>, <<"x-lzh-compressed">>, []}; -all_ext(<<"link66">>) -> {<<"application">>, <<"vnd.route66.link66+xml">>, []}; -all_ext(<<"list3820">>) -> {<<"application">>, <<"vnd.ibm.modcap">>, []}; -all_ext(<<"listafp">>) -> {<<"application">>, <<"vnd.ibm.modcap">>, []}; -all_ext(<<"list">>) -> {<<"text">>, <<"plain">>, []}; -all_ext(<<"lnk">>) -> {<<"application">>, <<"x-ms-shortcut">>, []}; -all_ext(<<"log">>) -> {<<"text">>, <<"plain">>, []}; -all_ext(<<"lostxml">>) -> {<<"application">>, <<"lost+xml">>, []}; -all_ext(<<"lrf">>) -> {<<"application">>, <<"octet-stream">>, []}; -all_ext(<<"lrm">>) -> {<<"application">>, <<"vnd.ms-lrm">>, []}; -all_ext(<<"ltf">>) -> {<<"application">>, <<"vnd.frogans.ltf">>, []}; -all_ext(<<"lvp">>) -> {<<"audio">>, <<"vnd.lucent.voice">>, []}; -all_ext(<<"lwp">>) -> {<<"application">>, <<"vnd.lotus-wordpro">>, []}; -all_ext(<<"lzh">>) -> {<<"application">>, <<"x-lzh-compressed">>, []}; -all_ext(<<"m13">>) -> {<<"application">>, <<"x-msmediaview">>, []}; -all_ext(<<"m14">>) -> {<<"application">>, <<"x-msmediaview">>, []}; -all_ext(<<"m1v">>) -> {<<"video">>, <<"mpeg">>, []}; -all_ext(<<"m21">>) -> {<<"application">>, <<"mp21">>, []}; -all_ext(<<"m2a">>) -> {<<"audio">>, <<"mpeg">>, []}; -all_ext(<<"m2v">>) -> {<<"video">>, <<"mpeg">>, []}; -all_ext(<<"m3a">>) -> {<<"audio">>, <<"mpeg">>, []}; -all_ext(<<"m3u8">>) -> {<<"application">>, <<"vnd.apple.mpegurl">>, []}; -all_ext(<<"m3u">>) -> {<<"audio">>, <<"x-mpegurl">>, []}; -all_ext(<<"m4u">>) -> {<<"video">>, <<"vnd.mpegurl">>, []}; -all_ext(<<"m4v">>) -> {<<"video">>, <<"x-m4v">>, []}; -all_ext(<<"ma">>) -> {<<"application">>, <<"mathematica">>, []}; -all_ext(<<"mads">>) -> {<<"application">>, <<"mads+xml">>, []}; -all_ext(<<"mag">>) -> {<<"application">>, <<"vnd.ecowin.chart">>, []}; -all_ext(<<"maker">>) -> {<<"application">>, <<"vnd.framemaker">>, []}; -all_ext(<<"man">>) -> {<<"text">>, <<"troff">>, []}; -all_ext(<<"mar">>) -> {<<"application">>, <<"octet-stream">>, []}; -all_ext(<<"mathml">>) -> {<<"application">>, <<"mathml+xml">>, []}; -all_ext(<<"mb">>) -> {<<"application">>, <<"mathematica">>, []}; -all_ext(<<"mbk">>) -> {<<"application">>, <<"vnd.mobius.mbk">>, []}; -all_ext(<<"mbox">>) -> {<<"application">>, <<"mbox">>, []}; -all_ext(<<"mc1">>) -> {<<"application">>, <<"vnd.medcalcdata">>, []}; -all_ext(<<"mcd">>) -> {<<"application">>, <<"vnd.mcd">>, []}; -all_ext(<<"mcurl">>) -> {<<"text">>, <<"vnd.curl.mcurl">>, []}; -all_ext(<<"mdb">>) -> {<<"application">>, <<"x-msaccess">>, []}; -all_ext(<<"mdi">>) -> {<<"image">>, <<"vnd.ms-modi">>, []}; -all_ext(<<"mesh">>) -> {<<"model">>, <<"mesh">>, []}; -all_ext(<<"meta4">>) -> {<<"application">>, <<"metalink4+xml">>, []}; -all_ext(<<"metalink">>) -> {<<"application">>, <<"metalink+xml">>, []}; -all_ext(<<"me">>) -> {<<"text">>, <<"troff">>, []}; -all_ext(<<"mets">>) -> {<<"application">>, <<"mets+xml">>, []}; -all_ext(<<"mfm">>) -> {<<"application">>, <<"vnd.mfmp">>, []}; -all_ext(<<"mft">>) -> {<<"application">>, <<"rpki-manifest">>, []}; -all_ext(<<"mgp">>) -> {<<"application">>, <<"vnd.osgeo.mapguide.package">>, []}; -all_ext(<<"mgz">>) -> {<<"application">>, <<"vnd.proteus.magazine">>, []}; -all_ext(<<"mid">>) -> {<<"audio">>, <<"midi">>, []}; -all_ext(<<"midi">>) -> {<<"audio">>, <<"midi">>, []}; -all_ext(<<"mie">>) -> {<<"application">>, <<"x-mie">>, []}; -all_ext(<<"mif">>) -> {<<"application">>, <<"vnd.mif">>, []}; -all_ext(<<"mime">>) -> {<<"message">>, <<"rfc822">>, []}; -all_ext(<<"mj2">>) -> {<<"video">>, <<"mj2">>, []}; -all_ext(<<"mjp2">>) -> {<<"video">>, <<"mj2">>, []}; -all_ext(<<"mk3d">>) -> {<<"video">>, <<"x-matroska">>, []}; -all_ext(<<"mka">>) -> {<<"audio">>, <<"x-matroska">>, []}; -all_ext(<<"mks">>) -> {<<"video">>, <<"x-matroska">>, []}; -all_ext(<<"mkv">>) -> {<<"video">>, <<"x-matroska">>, []}; -all_ext(<<"mlp">>) -> {<<"application">>, <<"vnd.dolby.mlp">>, []}; -all_ext(<<"mmd">>) -> {<<"application">>, <<"vnd.chipnuts.karaoke-mmd">>, []}; -all_ext(<<"mmf">>) -> {<<"application">>, <<"vnd.smaf">>, []}; -all_ext(<<"mmr">>) -> {<<"image">>, <<"vnd.fujixerox.edmics-mmr">>, []}; -all_ext(<<"mng">>) -> {<<"video">>, <<"x-mng">>, []}; -all_ext(<<"mny">>) -> {<<"application">>, <<"x-msmoney">>, []}; -all_ext(<<"mobi">>) -> {<<"application">>, <<"x-mobipocket-ebook">>, []}; -all_ext(<<"mods">>) -> {<<"application">>, <<"mods+xml">>, []}; -all_ext(<<"movie">>) -> {<<"video">>, <<"x-sgi-movie">>, []}; -all_ext(<<"mov">>) -> {<<"video">>, <<"quicktime">>, []}; -all_ext(<<"mp21">>) -> {<<"application">>, <<"mp21">>, []}; -all_ext(<<"mp2a">>) -> {<<"audio">>, <<"mpeg">>, []}; -all_ext(<<"mp2">>) -> {<<"audio">>, <<"mpeg">>, []}; -all_ext(<<"mp3">>) -> {<<"audio">>, <<"mpeg">>, []}; -all_ext(<<"mp4a">>) -> {<<"audio">>, <<"mp4">>, []}; -all_ext(<<"mp4s">>) -> {<<"application">>, <<"mp4">>, []}; -all_ext(<<"mp4">>) -> {<<"video">>, <<"mp4">>, []}; -all_ext(<<"mp4v">>) -> {<<"video">>, <<"mp4">>, []}; -all_ext(<<"mpc">>) -> {<<"application">>, <<"vnd.mophun.certificate">>, []}; -all_ext(<<"mpeg">>) -> {<<"video">>, <<"mpeg">>, []}; -all_ext(<<"mpe">>) -> {<<"video">>, <<"mpeg">>, []}; -all_ext(<<"mpg4">>) -> {<<"video">>, <<"mp4">>, []}; -all_ext(<<"mpga">>) -> {<<"audio">>, <<"mpeg">>, []}; -all_ext(<<"mpg">>) -> {<<"video">>, <<"mpeg">>, []}; -all_ext(<<"mpkg">>) -> {<<"application">>, <<"vnd.apple.installer+xml">>, []}; -all_ext(<<"mpm">>) -> {<<"application">>, <<"vnd.blueice.multipass">>, []}; -all_ext(<<"mpn">>) -> {<<"application">>, <<"vnd.mophun.application">>, []}; -all_ext(<<"mpp">>) -> {<<"application">>, <<"vnd.ms-project">>, []}; -all_ext(<<"mpt">>) -> {<<"application">>, <<"vnd.ms-project">>, []}; -all_ext(<<"mpy">>) -> {<<"application">>, <<"vnd.ibm.minipay">>, []}; -all_ext(<<"mqy">>) -> {<<"application">>, <<"vnd.mobius.mqy">>, []}; -all_ext(<<"mrc">>) -> {<<"application">>, <<"marc">>, []}; -all_ext(<<"mrcx">>) -> {<<"application">>, <<"marcxml+xml">>, []}; -all_ext(<<"mscml">>) -> {<<"application">>, <<"mediaservercontrol+xml">>, []}; -all_ext(<<"mseed">>) -> {<<"application">>, <<"vnd.fdsn.mseed">>, []}; -all_ext(<<"mseq">>) -> {<<"application">>, <<"vnd.mseq">>, []}; -all_ext(<<"msf">>) -> {<<"application">>, <<"vnd.epson.msf">>, []}; -all_ext(<<"msh">>) -> {<<"model">>, <<"mesh">>, []}; -all_ext(<<"msi">>) -> {<<"application">>, <<"x-msdownload">>, []}; -all_ext(<<"msl">>) -> {<<"application">>, <<"vnd.mobius.msl">>, []}; -all_ext(<<"ms">>) -> {<<"text">>, <<"troff">>, []}; -all_ext(<<"msty">>) -> {<<"application">>, <<"vnd.muvee.style">>, []}; -all_ext(<<"mts">>) -> {<<"model">>, <<"vnd.mts">>, []}; -all_ext(<<"mus">>) -> {<<"application">>, <<"vnd.musician">>, []}; -all_ext(<<"musicxml">>) -> {<<"application">>, <<"vnd.recordare.musicxml+xml">>, []}; -all_ext(<<"mvb">>) -> {<<"application">>, <<"x-msmediaview">>, []}; -all_ext(<<"mwf">>) -> {<<"application">>, <<"vnd.mfer">>, []}; -all_ext(<<"mxf">>) -> {<<"application">>, <<"mxf">>, []}; -all_ext(<<"mxl">>) -> {<<"application">>, <<"vnd.recordare.musicxml">>, []}; -all_ext(<<"mxml">>) -> {<<"application">>, <<"xv+xml">>, []}; -all_ext(<<"mxs">>) -> {<<"application">>, <<"vnd.triscape.mxs">>, []}; -all_ext(<<"mxu">>) -> {<<"video">>, <<"vnd.mpegurl">>, []}; -all_ext(<<"n3">>) -> {<<"text">>, <<"n3">>, []}; -all_ext(<<"nb">>) -> {<<"application">>, <<"mathematica">>, []}; -all_ext(<<"nbp">>) -> {<<"application">>, <<"vnd.wolfram.player">>, []}; -all_ext(<<"nc">>) -> {<<"application">>, <<"x-netcdf">>, []}; -all_ext(<<"ncx">>) -> {<<"application">>, <<"x-dtbncx+xml">>, []}; -all_ext(<<"nfo">>) -> {<<"text">>, <<"x-nfo">>, []}; -all_ext(<<"n-gage">>) -> {<<"application">>, <<"vnd.nokia.n-gage.symbian.install">>, []}; -all_ext(<<"ngdat">>) -> {<<"application">>, <<"vnd.nokia.n-gage.data">>, []}; -all_ext(<<"nitf">>) -> {<<"application">>, <<"vnd.nitf">>, []}; -all_ext(<<"nlu">>) -> {<<"application">>, <<"vnd.neurolanguage.nlu">>, []}; -all_ext(<<"nml">>) -> {<<"application">>, <<"vnd.enliven">>, []}; -all_ext(<<"nnd">>) -> {<<"application">>, <<"vnd.noblenet-directory">>, []}; -all_ext(<<"nns">>) -> {<<"application">>, <<"vnd.noblenet-sealer">>, []}; -all_ext(<<"nnw">>) -> {<<"application">>, <<"vnd.noblenet-web">>, []}; -all_ext(<<"npx">>) -> {<<"image">>, <<"vnd.net-fpx">>, []}; -all_ext(<<"nsc">>) -> {<<"application">>, <<"x-conference">>, []}; -all_ext(<<"nsf">>) -> {<<"application">>, <<"vnd.lotus-notes">>, []}; -all_ext(<<"ntf">>) -> {<<"application">>, <<"vnd.nitf">>, []}; -all_ext(<<"nzb">>) -> {<<"application">>, <<"x-nzb">>, []}; -all_ext(<<"oa2">>) -> {<<"application">>, <<"vnd.fujitsu.oasys2">>, []}; -all_ext(<<"oa3">>) -> {<<"application">>, <<"vnd.fujitsu.oasys3">>, []}; -all_ext(<<"oas">>) -> {<<"application">>, <<"vnd.fujitsu.oasys">>, []}; -all_ext(<<"obd">>) -> {<<"application">>, <<"x-msbinder">>, []}; -all_ext(<<"obj">>) -> {<<"application">>, <<"x-tgif">>, []}; -all_ext(<<"oda">>) -> {<<"application">>, <<"oda">>, []}; -all_ext(<<"odb">>) -> {<<"application">>, <<"vnd.oasis.opendocument.database">>, []}; -all_ext(<<"odc">>) -> {<<"application">>, <<"vnd.oasis.opendocument.chart">>, []}; -all_ext(<<"odf">>) -> {<<"application">>, <<"vnd.oasis.opendocument.formula">>, []}; -all_ext(<<"odft">>) -> {<<"application">>, <<"vnd.oasis.opendocument.formula-template">>, []}; -all_ext(<<"odg">>) -> {<<"application">>, <<"vnd.oasis.opendocument.graphics">>, []}; -all_ext(<<"odi">>) -> {<<"application">>, <<"vnd.oasis.opendocument.image">>, []}; -all_ext(<<"odm">>) -> {<<"application">>, <<"vnd.oasis.opendocument.text-master">>, []}; -all_ext(<<"odp">>) -> {<<"application">>, <<"vnd.oasis.opendocument.presentation">>, []}; -all_ext(<<"ods">>) -> {<<"application">>, <<"vnd.oasis.opendocument.spreadsheet">>, []}; -all_ext(<<"odt">>) -> {<<"application">>, <<"vnd.oasis.opendocument.text">>, []}; -all_ext(<<"oga">>) -> {<<"audio">>, <<"ogg">>, []}; -all_ext(<<"ogg">>) -> {<<"audio">>, <<"ogg">>, []}; -all_ext(<<"ogv">>) -> {<<"video">>, <<"ogg">>, []}; -all_ext(<<"ogx">>) -> {<<"application">>, <<"ogg">>, []}; -all_ext(<<"omdoc">>) -> {<<"application">>, <<"omdoc+xml">>, []}; -all_ext(<<"onepkg">>) -> {<<"application">>, <<"onenote">>, []}; -all_ext(<<"onetmp">>) -> {<<"application">>, <<"onenote">>, []}; -all_ext(<<"onetoc2">>) -> {<<"application">>, <<"onenote">>, []}; -all_ext(<<"onetoc">>) -> {<<"application">>, <<"onenote">>, []}; -all_ext(<<"opf">>) -> {<<"application">>, <<"oebps-package+xml">>, []}; -all_ext(<<"opml">>) -> {<<"text">>, <<"x-opml">>, []}; -all_ext(<<"oprc">>) -> {<<"application">>, <<"vnd.palm">>, []}; -all_ext(<<"org">>) -> {<<"application">>, <<"vnd.lotus-organizer">>, []}; -all_ext(<<"osf">>) -> {<<"application">>, <<"vnd.yamaha.openscoreformat">>, []}; -all_ext(<<"osfpvg">>) -> {<<"application">>, <<"vnd.yamaha.openscoreformat.osfpvg+xml">>, []}; -all_ext(<<"otc">>) -> {<<"application">>, <<"vnd.oasis.opendocument.chart-template">>, []}; -all_ext(<<"otf">>) -> {<<"application">>, <<"x-font-otf">>, []}; -all_ext(<<"otg">>) -> {<<"application">>, <<"vnd.oasis.opendocument.graphics-template">>, []}; -all_ext(<<"oth">>) -> {<<"application">>, <<"vnd.oasis.opendocument.text-web">>, []}; -all_ext(<<"oti">>) -> {<<"application">>, <<"vnd.oasis.opendocument.image-template">>, []}; -all_ext(<<"otp">>) -> {<<"application">>, <<"vnd.oasis.opendocument.presentation-template">>, []}; -all_ext(<<"ots">>) -> {<<"application">>, <<"vnd.oasis.opendocument.spreadsheet-template">>, []}; -all_ext(<<"ott">>) -> {<<"application">>, <<"vnd.oasis.opendocument.text-template">>, []}; -all_ext(<<"oxps">>) -> {<<"application">>, <<"oxps">>, []}; -all_ext(<<"oxt">>) -> {<<"application">>, <<"vnd.openofficeorg.extension">>, []}; -all_ext(<<"p10">>) -> {<<"application">>, <<"pkcs10">>, []}; -all_ext(<<"p12">>) -> {<<"application">>, <<"x-pkcs12">>, []}; -all_ext(<<"p7b">>) -> {<<"application">>, <<"x-pkcs7-certificates">>, []}; -all_ext(<<"p7c">>) -> {<<"application">>, <<"pkcs7-mime">>, []}; -all_ext(<<"p7m">>) -> {<<"application">>, <<"pkcs7-mime">>, []}; -all_ext(<<"p7r">>) -> {<<"application">>, <<"x-pkcs7-certreqresp">>, []}; -all_ext(<<"p7s">>) -> {<<"application">>, <<"pkcs7-signature">>, []}; -all_ext(<<"p8">>) -> {<<"application">>, <<"pkcs8">>, []}; -all_ext(<<"pas">>) -> {<<"text">>, <<"x-pascal">>, []}; -all_ext(<<"paw">>) -> {<<"application">>, <<"vnd.pawaafile">>, []}; -all_ext(<<"pbd">>) -> {<<"application">>, <<"vnd.powerbuilder6">>, []}; -all_ext(<<"pbm">>) -> {<<"image">>, <<"x-portable-bitmap">>, []}; -all_ext(<<"pcap">>) -> {<<"application">>, <<"vnd.tcpdump.pcap">>, []}; -all_ext(<<"pcf">>) -> {<<"application">>, <<"x-font-pcf">>, []}; -all_ext(<<"pcl">>) -> {<<"application">>, <<"vnd.hp-pcl">>, []}; -all_ext(<<"pclxl">>) -> {<<"application">>, <<"vnd.hp-pclxl">>, []}; -all_ext(<<"pct">>) -> {<<"image">>, <<"x-pict">>, []}; -all_ext(<<"pcurl">>) -> {<<"application">>, <<"vnd.curl.pcurl">>, []}; -all_ext(<<"pcx">>) -> {<<"image">>, <<"x-pcx">>, []}; -all_ext(<<"pdb">>) -> {<<"application">>, <<"vnd.palm">>, []}; -all_ext(<<"pdf">>) -> {<<"application">>, <<"pdf">>, []}; -all_ext(<<"pfa">>) -> {<<"application">>, <<"x-font-type1">>, []}; -all_ext(<<"pfb">>) -> {<<"application">>, <<"x-font-type1">>, []}; -all_ext(<<"pfm">>) -> {<<"application">>, <<"x-font-type1">>, []}; -all_ext(<<"pfr">>) -> {<<"application">>, <<"font-tdpfr">>, []}; -all_ext(<<"pfx">>) -> {<<"application">>, <<"x-pkcs12">>, []}; -all_ext(<<"pgm">>) -> {<<"image">>, <<"x-portable-graymap">>, []}; -all_ext(<<"pgn">>) -> {<<"application">>, <<"x-chess-pgn">>, []}; -all_ext(<<"pgp">>) -> {<<"application">>, <<"pgp-encrypted">>, []}; -all_ext(<<"pic">>) -> {<<"image">>, <<"x-pict">>, []}; -all_ext(<<"pkg">>) -> {<<"application">>, <<"octet-stream">>, []}; -all_ext(<<"pki">>) -> {<<"application">>, <<"pkixcmp">>, []}; -all_ext(<<"pkipath">>) -> {<<"application">>, <<"pkix-pkipath">>, []}; -all_ext(<<"plb">>) -> {<<"application">>, <<"vnd.3gpp.pic-bw-large">>, []}; -all_ext(<<"plc">>) -> {<<"application">>, <<"vnd.mobius.plc">>, []}; -all_ext(<<"plf">>) -> {<<"application">>, <<"vnd.pocketlearn">>, []}; -all_ext(<<"pls">>) -> {<<"application">>, <<"pls+xml">>, []}; -all_ext(<<"pml">>) -> {<<"application">>, <<"vnd.ctc-posml">>, []}; -all_ext(<<"png">>) -> {<<"image">>, <<"png">>, []}; -all_ext(<<"pnm">>) -> {<<"image">>, <<"x-portable-anymap">>, []}; -all_ext(<<"portpkg">>) -> {<<"application">>, <<"vnd.macports.portpkg">>, []}; -all_ext(<<"pot">>) -> {<<"application">>, <<"vnd.ms-powerpoint">>, []}; -all_ext(<<"potm">>) -> {<<"application">>, <<"vnd.ms-powerpoint.template.macroenabled.12">>, []}; -all_ext(<<"potx">>) -> {<<"application">>, <<"vnd.openxmlformats-officedocument.presentationml.template">>, []}; -all_ext(<<"ppam">>) -> {<<"application">>, <<"vnd.ms-powerpoint.addin.macroenabled.12">>, []}; -all_ext(<<"ppd">>) -> {<<"application">>, <<"vnd.cups-ppd">>, []}; -all_ext(<<"ppm">>) -> {<<"image">>, <<"x-portable-pixmap">>, []}; -all_ext(<<"pps">>) -> {<<"application">>, <<"vnd.ms-powerpoint">>, []}; -all_ext(<<"ppsm">>) -> {<<"application">>, <<"vnd.ms-powerpoint.slideshow.macroenabled.12">>, []}; -all_ext(<<"ppsx">>) -> {<<"application">>, <<"vnd.openxmlformats-officedocument.presentationml.slideshow">>, []}; -all_ext(<<"ppt">>) -> {<<"application">>, <<"vnd.ms-powerpoint">>, []}; -all_ext(<<"pptm">>) -> {<<"application">>, <<"vnd.ms-powerpoint.presentation.macroenabled.12">>, []}; -all_ext(<<"pptx">>) -> {<<"application">>, <<"vnd.openxmlformats-officedocument.presentationml.presentation">>, []}; -all_ext(<<"pqa">>) -> {<<"application">>, <<"vnd.palm">>, []}; -all_ext(<<"prc">>) -> {<<"application">>, <<"x-mobipocket-ebook">>, []}; -all_ext(<<"pre">>) -> {<<"application">>, <<"vnd.lotus-freelance">>, []}; -all_ext(<<"prf">>) -> {<<"application">>, <<"pics-rules">>, []}; -all_ext(<<"ps">>) -> {<<"application">>, <<"postscript">>, []}; -all_ext(<<"psb">>) -> {<<"application">>, <<"vnd.3gpp.pic-bw-small">>, []}; -all_ext(<<"psd">>) -> {<<"image">>, <<"vnd.adobe.photoshop">>, []}; -all_ext(<<"psf">>) -> {<<"application">>, <<"x-font-linux-psf">>, []}; -all_ext(<<"pskcxml">>) -> {<<"application">>, <<"pskc+xml">>, []}; -all_ext(<<"p">>) -> {<<"text">>, <<"x-pascal">>, []}; -all_ext(<<"ptid">>) -> {<<"application">>, <<"vnd.pvi.ptid1">>, []}; -all_ext(<<"pub">>) -> {<<"application">>, <<"x-mspublisher">>, []}; -all_ext(<<"pvb">>) -> {<<"application">>, <<"vnd.3gpp.pic-bw-var">>, []}; -all_ext(<<"pwn">>) -> {<<"application">>, <<"vnd.3m.post-it-notes">>, []}; -all_ext(<<"pya">>) -> {<<"audio">>, <<"vnd.ms-playready.media.pya">>, []}; -all_ext(<<"pyv">>) -> {<<"video">>, <<"vnd.ms-playready.media.pyv">>, []}; -all_ext(<<"qam">>) -> {<<"application">>, <<"vnd.epson.quickanime">>, []}; -all_ext(<<"qbo">>) -> {<<"application">>, <<"vnd.intu.qbo">>, []}; -all_ext(<<"qfx">>) -> {<<"application">>, <<"vnd.intu.qfx">>, []}; -all_ext(<<"qps">>) -> {<<"application">>, <<"vnd.publishare-delta-tree">>, []}; -all_ext(<<"qt">>) -> {<<"video">>, <<"quicktime">>, []}; -all_ext(<<"qwd">>) -> {<<"application">>, <<"vnd.quark.quarkxpress">>, []}; -all_ext(<<"qwt">>) -> {<<"application">>, <<"vnd.quark.quarkxpress">>, []}; -all_ext(<<"qxb">>) -> {<<"application">>, <<"vnd.quark.quarkxpress">>, []}; -all_ext(<<"qxd">>) -> {<<"application">>, <<"vnd.quark.quarkxpress">>, []}; -all_ext(<<"qxl">>) -> {<<"application">>, <<"vnd.quark.quarkxpress">>, []}; -all_ext(<<"qxt">>) -> {<<"application">>, <<"vnd.quark.quarkxpress">>, []}; -all_ext(<<"ra">>) -> {<<"audio">>, <<"x-pn-realaudio">>, []}; -all_ext(<<"ram">>) -> {<<"audio">>, <<"x-pn-realaudio">>, []}; -all_ext(<<"rar">>) -> {<<"application">>, <<"x-rar-compressed">>, []}; -all_ext(<<"ras">>) -> {<<"image">>, <<"x-cmu-raster">>, []}; -all_ext(<<"rcprofile">>) -> {<<"application">>, <<"vnd.ipunplugged.rcprofile">>, []}; -all_ext(<<"rdf">>) -> {<<"application">>, <<"rdf+xml">>, []}; -all_ext(<<"rdz">>) -> {<<"application">>, <<"vnd.data-vision.rdz">>, []}; -all_ext(<<"rep">>) -> {<<"application">>, <<"vnd.businessobjects">>, []}; -all_ext(<<"res">>) -> {<<"application">>, <<"x-dtbresource+xml">>, []}; -all_ext(<<"rgb">>) -> {<<"image">>, <<"x-rgb">>, []}; -all_ext(<<"rif">>) -> {<<"application">>, <<"reginfo+xml">>, []}; -all_ext(<<"rip">>) -> {<<"audio">>, <<"vnd.rip">>, []}; -all_ext(<<"ris">>) -> {<<"application">>, <<"x-research-info-systems">>, []}; -all_ext(<<"rl">>) -> {<<"application">>, <<"resource-lists+xml">>, []}; -all_ext(<<"rlc">>) -> {<<"image">>, <<"vnd.fujixerox.edmics-rlc">>, []}; -all_ext(<<"rld">>) -> {<<"application">>, <<"resource-lists-diff+xml">>, []}; -all_ext(<<"rm">>) -> {<<"application">>, <<"vnd.rn-realmedia">>, []}; -all_ext(<<"rmi">>) -> {<<"audio">>, <<"midi">>, []}; -all_ext(<<"rmp">>) -> {<<"audio">>, <<"x-pn-realaudio-plugin">>, []}; -all_ext(<<"rms">>) -> {<<"application">>, <<"vnd.jcp.javame.midlet-rms">>, []}; -all_ext(<<"rmvb">>) -> {<<"application">>, <<"vnd.rn-realmedia-vbr">>, []}; -all_ext(<<"rnc">>) -> {<<"application">>, <<"relax-ng-compact-syntax">>, []}; -all_ext(<<"roa">>) -> {<<"application">>, <<"rpki-roa">>, []}; -all_ext(<<"roff">>) -> {<<"text">>, <<"troff">>, []}; -all_ext(<<"rp9">>) -> {<<"application">>, <<"vnd.cloanto.rp9">>, []}; -all_ext(<<"rpss">>) -> {<<"application">>, <<"vnd.nokia.radio-presets">>, []}; -all_ext(<<"rpst">>) -> {<<"application">>, <<"vnd.nokia.radio-preset">>, []}; -all_ext(<<"rq">>) -> {<<"application">>, <<"sparql-query">>, []}; -all_ext(<<"rs">>) -> {<<"application">>, <<"rls-services+xml">>, []}; -all_ext(<<"rsd">>) -> {<<"application">>, <<"rsd+xml">>, []}; -all_ext(<<"rss">>) -> {<<"application">>, <<"rss+xml">>, []}; -all_ext(<<"rtf">>) -> {<<"application">>, <<"rtf">>, []}; -all_ext(<<"rtx">>) -> {<<"text">>, <<"richtext">>, []}; -all_ext(<<"s3m">>) -> {<<"audio">>, <<"s3m">>, []}; -all_ext(<<"saf">>) -> {<<"application">>, <<"vnd.yamaha.smaf-audio">>, []}; -all_ext(<<"sbml">>) -> {<<"application">>, <<"sbml+xml">>, []}; -all_ext(<<"sc">>) -> {<<"application">>, <<"vnd.ibm.secure-container">>, []}; -all_ext(<<"scd">>) -> {<<"application">>, <<"x-msschedule">>, []}; -all_ext(<<"scm">>) -> {<<"application">>, <<"vnd.lotus-screencam">>, []}; -all_ext(<<"scq">>) -> {<<"application">>, <<"scvp-cv-request">>, []}; -all_ext(<<"scs">>) -> {<<"application">>, <<"scvp-cv-response">>, []}; -all_ext(<<"scurl">>) -> {<<"text">>, <<"vnd.curl.scurl">>, []}; -all_ext(<<"sda">>) -> {<<"application">>, <<"vnd.stardivision.draw">>, []}; -all_ext(<<"sdc">>) -> {<<"application">>, <<"vnd.stardivision.calc">>, []}; -all_ext(<<"sdd">>) -> {<<"application">>, <<"vnd.stardivision.impress">>, []}; -all_ext(<<"sdkd">>) -> {<<"application">>, <<"vnd.solent.sdkm+xml">>, []}; -all_ext(<<"sdkm">>) -> {<<"application">>, <<"vnd.solent.sdkm+xml">>, []}; -all_ext(<<"sdp">>) -> {<<"application">>, <<"sdp">>, []}; -all_ext(<<"sdw">>) -> {<<"application">>, <<"vnd.stardivision.writer">>, []}; -all_ext(<<"see">>) -> {<<"application">>, <<"vnd.seemail">>, []}; -all_ext(<<"seed">>) -> {<<"application">>, <<"vnd.fdsn.seed">>, []}; -all_ext(<<"sema">>) -> {<<"application">>, <<"vnd.sema">>, []}; -all_ext(<<"semd">>) -> {<<"application">>, <<"vnd.semd">>, []}; -all_ext(<<"semf">>) -> {<<"application">>, <<"vnd.semf">>, []}; -all_ext(<<"ser">>) -> {<<"application">>, <<"java-serialized-object">>, []}; -all_ext(<<"setpay">>) -> {<<"application">>, <<"set-payment-initiation">>, []}; -all_ext(<<"setreg">>) -> {<<"application">>, <<"set-registration-initiation">>, []}; -all_ext(<<"sfd-hdstx">>) -> {<<"application">>, <<"vnd.hydrostatix.sof-data">>, []}; -all_ext(<<"sfs">>) -> {<<"application">>, <<"vnd.spotfire.sfs">>, []}; -all_ext(<<"sfv">>) -> {<<"text">>, <<"x-sfv">>, []}; -all_ext(<<"sgi">>) -> {<<"image">>, <<"sgi">>, []}; -all_ext(<<"sgl">>) -> {<<"application">>, <<"vnd.stardivision.writer-global">>, []}; -all_ext(<<"sgml">>) -> {<<"text">>, <<"sgml">>, []}; -all_ext(<<"sgm">>) -> {<<"text">>, <<"sgml">>, []}; -all_ext(<<"sh">>) -> {<<"application">>, <<"x-sh">>, []}; -all_ext(<<"shar">>) -> {<<"application">>, <<"x-shar">>, []}; -all_ext(<<"shf">>) -> {<<"application">>, <<"shf+xml">>, []}; -all_ext(<<"sid">>) -> {<<"image">>, <<"x-mrsid-image">>, []}; -all_ext(<<"sig">>) -> {<<"application">>, <<"pgp-signature">>, []}; -all_ext(<<"sil">>) -> {<<"audio">>, <<"silk">>, []}; -all_ext(<<"silo">>) -> {<<"model">>, <<"mesh">>, []}; -all_ext(<<"sis">>) -> {<<"application">>, <<"vnd.symbian.install">>, []}; -all_ext(<<"sisx">>) -> {<<"application">>, <<"vnd.symbian.install">>, []}; -all_ext(<<"sit">>) -> {<<"application">>, <<"x-stuffit">>, []}; -all_ext(<<"sitx">>) -> {<<"application">>, <<"x-stuffitx">>, []}; -all_ext(<<"skd">>) -> {<<"application">>, <<"vnd.koan">>, []}; -all_ext(<<"skm">>) -> {<<"application">>, <<"vnd.koan">>, []}; -all_ext(<<"skp">>) -> {<<"application">>, <<"vnd.koan">>, []}; -all_ext(<<"skt">>) -> {<<"application">>, <<"vnd.koan">>, []}; -all_ext(<<"sldm">>) -> {<<"application">>, <<"vnd.ms-powerpoint.slide.macroenabled.12">>, []}; -all_ext(<<"sldx">>) -> {<<"application">>, <<"vnd.openxmlformats-officedocument.presentationml.slide">>, []}; -all_ext(<<"slt">>) -> {<<"application">>, <<"vnd.epson.salt">>, []}; -all_ext(<<"sm">>) -> {<<"application">>, <<"vnd.stepmania.stepchart">>, []}; -all_ext(<<"smf">>) -> {<<"application">>, <<"vnd.stardivision.math">>, []}; -all_ext(<<"smi">>) -> {<<"application">>, <<"smil+xml">>, []}; -all_ext(<<"smil">>) -> {<<"application">>, <<"smil+xml">>, []}; -all_ext(<<"smv">>) -> {<<"video">>, <<"x-smv">>, []}; -all_ext(<<"smzip">>) -> {<<"application">>, <<"vnd.stepmania.package">>, []}; -all_ext(<<"snd">>) -> {<<"audio">>, <<"basic">>, []}; -all_ext(<<"snf">>) -> {<<"application">>, <<"x-font-snf">>, []}; -all_ext(<<"so">>) -> {<<"application">>, <<"octet-stream">>, []}; -all_ext(<<"spc">>) -> {<<"application">>, <<"x-pkcs7-certificates">>, []}; -all_ext(<<"spf">>) -> {<<"application">>, <<"vnd.yamaha.smaf-phrase">>, []}; -all_ext(<<"spl">>) -> {<<"application">>, <<"x-futuresplash">>, []}; -all_ext(<<"spot">>) -> {<<"text">>, <<"vnd.in3d.spot">>, []}; -all_ext(<<"spp">>) -> {<<"application">>, <<"scvp-vp-response">>, []}; -all_ext(<<"spq">>) -> {<<"application">>, <<"scvp-vp-request">>, []}; -all_ext(<<"spx">>) -> {<<"audio">>, <<"ogg">>, []}; -all_ext(<<"sql">>) -> {<<"application">>, <<"x-sql">>, []}; -all_ext(<<"src">>) -> {<<"application">>, <<"x-wais-source">>, []}; -all_ext(<<"srt">>) -> {<<"application">>, <<"x-subrip">>, []}; -all_ext(<<"sru">>) -> {<<"application">>, <<"sru+xml">>, []}; -all_ext(<<"srx">>) -> {<<"application">>, <<"sparql-results+xml">>, []}; -all_ext(<<"ssdl">>) -> {<<"application">>, <<"ssdl+xml">>, []}; -all_ext(<<"sse">>) -> {<<"application">>, <<"vnd.kodak-descriptor">>, []}; -all_ext(<<"ssf">>) -> {<<"application">>, <<"vnd.epson.ssf">>, []}; -all_ext(<<"ssml">>) -> {<<"application">>, <<"ssml+xml">>, []}; -all_ext(<<"st">>) -> {<<"application">>, <<"vnd.sailingtracker.track">>, []}; -all_ext(<<"stc">>) -> {<<"application">>, <<"vnd.sun.xml.calc.template">>, []}; -all_ext(<<"std">>) -> {<<"application">>, <<"vnd.sun.xml.draw.template">>, []}; -all_ext(<<"s">>) -> {<<"text">>, <<"x-asm">>, []}; -all_ext(<<"stf">>) -> {<<"application">>, <<"vnd.wt.stf">>, []}; -all_ext(<<"sti">>) -> {<<"application">>, <<"vnd.sun.xml.impress.template">>, []}; -all_ext(<<"stk">>) -> {<<"application">>, <<"hyperstudio">>, []}; -all_ext(<<"stl">>) -> {<<"application">>, <<"vnd.ms-pki.stl">>, []}; -all_ext(<<"str">>) -> {<<"application">>, <<"vnd.pg.format">>, []}; -all_ext(<<"stw">>) -> {<<"application">>, <<"vnd.sun.xml.writer.template">>, []}; -all_ext(<<"sub">>) -> {<<"image">>, <<"vnd.dvb.subtitle">>, []}; -all_ext(<<"sus">>) -> {<<"application">>, <<"vnd.sus-calendar">>, []}; -all_ext(<<"susp">>) -> {<<"application">>, <<"vnd.sus-calendar">>, []}; -all_ext(<<"sv4cpio">>) -> {<<"application">>, <<"x-sv4cpio">>, []}; -all_ext(<<"sv4crc">>) -> {<<"application">>, <<"x-sv4crc">>, []}; -all_ext(<<"svc">>) -> {<<"application">>, <<"vnd.dvb.service">>, []}; -all_ext(<<"svd">>) -> {<<"application">>, <<"vnd.svd">>, []}; -all_ext(<<"svg">>) -> {<<"image">>, <<"svg+xml">>, []}; -all_ext(<<"svgz">>) -> {<<"image">>, <<"svg+xml">>, []}; -all_ext(<<"swa">>) -> {<<"application">>, <<"x-director">>, []}; -all_ext(<<"swf">>) -> {<<"application">>, <<"x-shockwave-flash">>, []}; -all_ext(<<"swi">>) -> {<<"application">>, <<"vnd.aristanetworks.swi">>, []}; -all_ext(<<"sxc">>) -> {<<"application">>, <<"vnd.sun.xml.calc">>, []}; -all_ext(<<"sxd">>) -> {<<"application">>, <<"vnd.sun.xml.draw">>, []}; -all_ext(<<"sxg">>) -> {<<"application">>, <<"vnd.sun.xml.writer.global">>, []}; -all_ext(<<"sxi">>) -> {<<"application">>, <<"vnd.sun.xml.impress">>, []}; -all_ext(<<"sxm">>) -> {<<"application">>, <<"vnd.sun.xml.math">>, []}; -all_ext(<<"sxw">>) -> {<<"application">>, <<"vnd.sun.xml.writer">>, []}; -all_ext(<<"t3">>) -> {<<"application">>, <<"x-t3vm-image">>, []}; -all_ext(<<"taglet">>) -> {<<"application">>, <<"vnd.mynfc">>, []}; -all_ext(<<"tao">>) -> {<<"application">>, <<"vnd.tao.intent-module-archive">>, []}; -all_ext(<<"tar">>) -> {<<"application">>, <<"x-tar">>, []}; -all_ext(<<"tcap">>) -> {<<"application">>, <<"vnd.3gpp2.tcap">>, []}; -all_ext(<<"tcl">>) -> {<<"application">>, <<"x-tcl">>, []}; -all_ext(<<"teacher">>) -> {<<"application">>, <<"vnd.smart.teacher">>, []}; -all_ext(<<"tei">>) -> {<<"application">>, <<"tei+xml">>, []}; -all_ext(<<"teicorpus">>) -> {<<"application">>, <<"tei+xml">>, []}; -all_ext(<<"tex">>) -> {<<"application">>, <<"x-tex">>, []}; -all_ext(<<"texi">>) -> {<<"application">>, <<"x-texinfo">>, []}; -all_ext(<<"texinfo">>) -> {<<"application">>, <<"x-texinfo">>, []}; -all_ext(<<"text">>) -> {<<"text">>, <<"plain">>, []}; -all_ext(<<"tfi">>) -> {<<"application">>, <<"thraud+xml">>, []}; -all_ext(<<"tfm">>) -> {<<"application">>, <<"x-tex-tfm">>, []}; -all_ext(<<"tga">>) -> {<<"image">>, <<"x-tga">>, []}; -all_ext(<<"thmx">>) -> {<<"application">>, <<"vnd.ms-officetheme">>, []}; -all_ext(<<"tiff">>) -> {<<"image">>, <<"tiff">>, []}; -all_ext(<<"tif">>) -> {<<"image">>, <<"tiff">>, []}; -all_ext(<<"tmo">>) -> {<<"application">>, <<"vnd.tmobile-livetv">>, []}; -all_ext(<<"torrent">>) -> {<<"application">>, <<"x-bittorrent">>, []}; -all_ext(<<"tpl">>) -> {<<"application">>, <<"vnd.groove-tool-template">>, []}; -all_ext(<<"tpt">>) -> {<<"application">>, <<"vnd.trid.tpt">>, []}; -all_ext(<<"tra">>) -> {<<"application">>, <<"vnd.trueapp">>, []}; -all_ext(<<"trm">>) -> {<<"application">>, <<"x-msterminal">>, []}; -all_ext(<<"tr">>) -> {<<"text">>, <<"troff">>, []}; -all_ext(<<"tsd">>) -> {<<"application">>, <<"timestamped-data">>, []}; -all_ext(<<"tsv">>) -> {<<"text">>, <<"tab-separated-values">>, []}; -all_ext(<<"ttc">>) -> {<<"application">>, <<"x-font-ttf">>, []}; -all_ext(<<"t">>) -> {<<"text">>, <<"troff">>, []}; -all_ext(<<"ttf">>) -> {<<"application">>, <<"x-font-ttf">>, []}; -all_ext(<<"ttl">>) -> {<<"text">>, <<"turtle">>, []}; -all_ext(<<"twd">>) -> {<<"application">>, <<"vnd.simtech-mindmapper">>, []}; -all_ext(<<"twds">>) -> {<<"application">>, <<"vnd.simtech-mindmapper">>, []}; -all_ext(<<"txd">>) -> {<<"application">>, <<"vnd.genomatix.tuxedo">>, []}; -all_ext(<<"txf">>) -> {<<"application">>, <<"vnd.mobius.txf">>, []}; -all_ext(<<"txt">>) -> {<<"text">>, <<"plain">>, []}; -all_ext(<<"u32">>) -> {<<"application">>, <<"x-authorware-bin">>, []}; -all_ext(<<"udeb">>) -> {<<"application">>, <<"x-debian-package">>, []}; -all_ext(<<"ufd">>) -> {<<"application">>, <<"vnd.ufdl">>, []}; -all_ext(<<"ufdl">>) -> {<<"application">>, <<"vnd.ufdl">>, []}; -all_ext(<<"ulx">>) -> {<<"application">>, <<"x-glulx">>, []}; -all_ext(<<"umj">>) -> {<<"application">>, <<"vnd.umajin">>, []}; -all_ext(<<"unityweb">>) -> {<<"application">>, <<"vnd.unity">>, []}; -all_ext(<<"uoml">>) -> {<<"application">>, <<"vnd.uoml+xml">>, []}; -all_ext(<<"uris">>) -> {<<"text">>, <<"uri-list">>, []}; -all_ext(<<"uri">>) -> {<<"text">>, <<"uri-list">>, []}; -all_ext(<<"urls">>) -> {<<"text">>, <<"uri-list">>, []}; -all_ext(<<"ustar">>) -> {<<"application">>, <<"x-ustar">>, []}; -all_ext(<<"utz">>) -> {<<"application">>, <<"vnd.uiq.theme">>, []}; -all_ext(<<"uu">>) -> {<<"text">>, <<"x-uuencode">>, []}; -all_ext(<<"uva">>) -> {<<"audio">>, <<"vnd.dece.audio">>, []}; -all_ext(<<"uvd">>) -> {<<"application">>, <<"vnd.dece.data">>, []}; -all_ext(<<"uvf">>) -> {<<"application">>, <<"vnd.dece.data">>, []}; -all_ext(<<"uvg">>) -> {<<"image">>, <<"vnd.dece.graphic">>, []}; -all_ext(<<"uvh">>) -> {<<"video">>, <<"vnd.dece.hd">>, []}; -all_ext(<<"uvi">>) -> {<<"image">>, <<"vnd.dece.graphic">>, []}; -all_ext(<<"uvm">>) -> {<<"video">>, <<"vnd.dece.mobile">>, []}; -all_ext(<<"uvp">>) -> {<<"video">>, <<"vnd.dece.pd">>, []}; -all_ext(<<"uvs">>) -> {<<"video">>, <<"vnd.dece.sd">>, []}; -all_ext(<<"uvt">>) -> {<<"application">>, <<"vnd.dece.ttml+xml">>, []}; -all_ext(<<"uvu">>) -> {<<"video">>, <<"vnd.uvvu.mp4">>, []}; -all_ext(<<"uvva">>) -> {<<"audio">>, <<"vnd.dece.audio">>, []}; -all_ext(<<"uvvd">>) -> {<<"application">>, <<"vnd.dece.data">>, []}; -all_ext(<<"uvvf">>) -> {<<"application">>, <<"vnd.dece.data">>, []}; -all_ext(<<"uvvg">>) -> {<<"image">>, <<"vnd.dece.graphic">>, []}; -all_ext(<<"uvvh">>) -> {<<"video">>, <<"vnd.dece.hd">>, []}; -all_ext(<<"uvvi">>) -> {<<"image">>, <<"vnd.dece.graphic">>, []}; -all_ext(<<"uvvm">>) -> {<<"video">>, <<"vnd.dece.mobile">>, []}; -all_ext(<<"uvvp">>) -> {<<"video">>, <<"vnd.dece.pd">>, []}; -all_ext(<<"uvvs">>) -> {<<"video">>, <<"vnd.dece.sd">>, []}; -all_ext(<<"uvvt">>) -> {<<"application">>, <<"vnd.dece.ttml+xml">>, []}; -all_ext(<<"uvvu">>) -> {<<"video">>, <<"vnd.uvvu.mp4">>, []}; -all_ext(<<"uvv">>) -> {<<"video">>, <<"vnd.dece.video">>, []}; -all_ext(<<"uvvv">>) -> {<<"video">>, <<"vnd.dece.video">>, []}; -all_ext(<<"uvvx">>) -> {<<"application">>, <<"vnd.dece.unspecified">>, []}; -all_ext(<<"uvvz">>) -> {<<"application">>, <<"vnd.dece.zip">>, []}; -all_ext(<<"uvx">>) -> {<<"application">>, <<"vnd.dece.unspecified">>, []}; -all_ext(<<"uvz">>) -> {<<"application">>, <<"vnd.dece.zip">>, []}; -all_ext(<<"vcard">>) -> {<<"text">>, <<"vcard">>, []}; -all_ext(<<"vcd">>) -> {<<"application">>, <<"x-cdlink">>, []}; -all_ext(<<"vcf">>) -> {<<"text">>, <<"x-vcard">>, []}; -all_ext(<<"vcg">>) -> {<<"application">>, <<"vnd.groove-vcard">>, []}; -all_ext(<<"vcs">>) -> {<<"text">>, <<"x-vcalendar">>, []}; -all_ext(<<"vcx">>) -> {<<"application">>, <<"vnd.vcx">>, []}; -all_ext(<<"vis">>) -> {<<"application">>, <<"vnd.visionary">>, []}; -all_ext(<<"viv">>) -> {<<"video">>, <<"vnd.vivo">>, []}; -all_ext(<<"vob">>) -> {<<"video">>, <<"x-ms-vob">>, []}; -all_ext(<<"vor">>) -> {<<"application">>, <<"vnd.stardivision.writer">>, []}; -all_ext(<<"vox">>) -> {<<"application">>, <<"x-authorware-bin">>, []}; -all_ext(<<"vrml">>) -> {<<"model">>, <<"vrml">>, []}; -all_ext(<<"vsd">>) -> {<<"application">>, <<"vnd.visio">>, []}; -all_ext(<<"vsf">>) -> {<<"application">>, <<"vnd.vsf">>, []}; -all_ext(<<"vss">>) -> {<<"application">>, <<"vnd.visio">>, []}; -all_ext(<<"vst">>) -> {<<"application">>, <<"vnd.visio">>, []}; -all_ext(<<"vsw">>) -> {<<"application">>, <<"vnd.visio">>, []}; -all_ext(<<"vtu">>) -> {<<"model">>, <<"vnd.vtu">>, []}; -all_ext(<<"vxml">>) -> {<<"application">>, <<"voicexml+xml">>, []}; -all_ext(<<"w3d">>) -> {<<"application">>, <<"x-director">>, []}; -all_ext(<<"wad">>) -> {<<"application">>, <<"x-doom">>, []}; -all_ext(<<"wav">>) -> {<<"audio">>, <<"x-wav">>, []}; -all_ext(<<"wax">>) -> {<<"audio">>, <<"x-ms-wax">>, []}; -all_ext(<<"wbmp">>) -> {<<"image">>, <<"vnd.wap.wbmp">>, []}; -all_ext(<<"wbs">>) -> {<<"application">>, <<"vnd.criticaltools.wbs+xml">>, []}; -all_ext(<<"wbxml">>) -> {<<"application">>, <<"vnd.wap.wbxml">>, []}; -all_ext(<<"wcm">>) -> {<<"application">>, <<"vnd.ms-works">>, []}; -all_ext(<<"wdb">>) -> {<<"application">>, <<"vnd.ms-works">>, []}; -all_ext(<<"wdp">>) -> {<<"image">>, <<"vnd.ms-photo">>, []}; -all_ext(<<"weba">>) -> {<<"audio">>, <<"webm">>, []}; -all_ext(<<"webm">>) -> {<<"video">>, <<"webm">>, []}; -all_ext(<<"webp">>) -> {<<"image">>, <<"webp">>, []}; -all_ext(<<"wg">>) -> {<<"application">>, <<"vnd.pmi.widget">>, []}; -all_ext(<<"wgt">>) -> {<<"application">>, <<"widget">>, []}; -all_ext(<<"wks">>) -> {<<"application">>, <<"vnd.ms-works">>, []}; -all_ext(<<"wma">>) -> {<<"audio">>, <<"x-ms-wma">>, []}; -all_ext(<<"wmd">>) -> {<<"application">>, <<"x-ms-wmd">>, []}; -all_ext(<<"wmf">>) -> {<<"application">>, <<"x-msmetafile">>, []}; -all_ext(<<"wmlc">>) -> {<<"application">>, <<"vnd.wap.wmlc">>, []}; -all_ext(<<"wmlsc">>) -> {<<"application">>, <<"vnd.wap.wmlscriptc">>, []}; -all_ext(<<"wmls">>) -> {<<"text">>, <<"vnd.wap.wmlscript">>, []}; -all_ext(<<"wml">>) -> {<<"text">>, <<"vnd.wap.wml">>, []}; -all_ext(<<"wm">>) -> {<<"video">>, <<"x-ms-wm">>, []}; -all_ext(<<"wmv">>) -> {<<"video">>, <<"x-ms-wmv">>, []}; -all_ext(<<"wmx">>) -> {<<"video">>, <<"x-ms-wmx">>, []}; -all_ext(<<"wmz">>) -> {<<"application">>, <<"x-msmetafile">>, []}; -all_ext(<<"woff">>) -> {<<"application">>, <<"font-woff">>, []}; -all_ext(<<"wpd">>) -> {<<"application">>, <<"vnd.wordperfect">>, []}; -all_ext(<<"wpl">>) -> {<<"application">>, <<"vnd.ms-wpl">>, []}; -all_ext(<<"wps">>) -> {<<"application">>, <<"vnd.ms-works">>, []}; -all_ext(<<"wqd">>) -> {<<"application">>, <<"vnd.wqd">>, []}; -all_ext(<<"wri">>) -> {<<"application">>, <<"x-mswrite">>, []}; -all_ext(<<"wrl">>) -> {<<"model">>, <<"vrml">>, []}; -all_ext(<<"wsdl">>) -> {<<"application">>, <<"wsdl+xml">>, []}; -all_ext(<<"wspolicy">>) -> {<<"application">>, <<"wspolicy+xml">>, []}; -all_ext(<<"wtb">>) -> {<<"application">>, <<"vnd.webturbo">>, []}; -all_ext(<<"wvx">>) -> {<<"video">>, <<"x-ms-wvx">>, []}; -all_ext(<<"x32">>) -> {<<"application">>, <<"x-authorware-bin">>, []}; -all_ext(<<"x3db">>) -> {<<"model">>, <<"x3d+binary">>, []}; -all_ext(<<"x3dbz">>) -> {<<"model">>, <<"x3d+binary">>, []}; -all_ext(<<"x3d">>) -> {<<"model">>, <<"x3d+xml">>, []}; -all_ext(<<"x3dv">>) -> {<<"model">>, <<"x3d+vrml">>, []}; -all_ext(<<"x3dvz">>) -> {<<"model">>, <<"x3d+vrml">>, []}; -all_ext(<<"x3dz">>) -> {<<"model">>, <<"x3d+xml">>, []}; -all_ext(<<"xaml">>) -> {<<"application">>, <<"xaml+xml">>, []}; -all_ext(<<"xap">>) -> {<<"application">>, <<"x-silverlight-app">>, []}; -all_ext(<<"xar">>) -> {<<"application">>, <<"vnd.xara">>, []}; -all_ext(<<"xbap">>) -> {<<"application">>, <<"x-ms-xbap">>, []}; -all_ext(<<"xbd">>) -> {<<"application">>, <<"vnd.fujixerox.docuworks.binder">>, []}; -all_ext(<<"xbm">>) -> {<<"image">>, <<"x-xbitmap">>, []}; -all_ext(<<"xdf">>) -> {<<"application">>, <<"xcap-diff+xml">>, []}; -all_ext(<<"xdm">>) -> {<<"application">>, <<"vnd.syncml.dm+xml">>, []}; -all_ext(<<"xdp">>) -> {<<"application">>, <<"vnd.adobe.xdp+xml">>, []}; -all_ext(<<"xdssc">>) -> {<<"application">>, <<"dssc+xml">>, []}; -all_ext(<<"xdw">>) -> {<<"application">>, <<"vnd.fujixerox.docuworks">>, []}; -all_ext(<<"xenc">>) -> {<<"application">>, <<"xenc+xml">>, []}; -all_ext(<<"xer">>) -> {<<"application">>, <<"patch-ops-error+xml">>, []}; -all_ext(<<"xfdf">>) -> {<<"application">>, <<"vnd.adobe.xfdf">>, []}; -all_ext(<<"xfdl">>) -> {<<"application">>, <<"vnd.xfdl">>, []}; -all_ext(<<"xht">>) -> {<<"application">>, <<"xhtml+xml">>, []}; -all_ext(<<"xhtml">>) -> {<<"application">>, <<"xhtml+xml">>, []}; -all_ext(<<"xhvml">>) -> {<<"application">>, <<"xv+xml">>, []}; -all_ext(<<"xif">>) -> {<<"image">>, <<"vnd.xiff">>, []}; -all_ext(<<"xla">>) -> {<<"application">>, <<"vnd.ms-excel">>, []}; -all_ext(<<"xlam">>) -> {<<"application">>, <<"vnd.ms-excel.addin.macroenabled.12">>, []}; -all_ext(<<"xlc">>) -> {<<"application">>, <<"vnd.ms-excel">>, []}; -all_ext(<<"xlf">>) -> {<<"application">>, <<"x-xliff+xml">>, []}; -all_ext(<<"xlm">>) -> {<<"application">>, <<"vnd.ms-excel">>, []}; -all_ext(<<"xls">>) -> {<<"application">>, <<"vnd.ms-excel">>, []}; -all_ext(<<"xlsb">>) -> {<<"application">>, <<"vnd.ms-excel.sheet.binary.macroenabled.12">>, []}; -all_ext(<<"xlsm">>) -> {<<"application">>, <<"vnd.ms-excel.sheet.macroenabled.12">>, []}; -all_ext(<<"xlsx">>) -> {<<"application">>, <<"vnd.openxmlformats-officedocument.spreadsheetml.sheet">>, []}; -all_ext(<<"xlt">>) -> {<<"application">>, <<"vnd.ms-excel">>, []}; -all_ext(<<"xltm">>) -> {<<"application">>, <<"vnd.ms-excel.template.macroenabled.12">>, []}; -all_ext(<<"xltx">>) -> {<<"application">>, <<"vnd.openxmlformats-officedocument.spreadsheetml.template">>, []}; -all_ext(<<"xlw">>) -> {<<"application">>, <<"vnd.ms-excel">>, []}; -all_ext(<<"xm">>) -> {<<"audio">>, <<"xm">>, []}; -all_ext(<<"xml">>) -> {<<"application">>, <<"xml">>, []}; -all_ext(<<"xo">>) -> {<<"application">>, <<"vnd.olpc-sugar">>, []}; -all_ext(<<"xop">>) -> {<<"application">>, <<"xop+xml">>, []}; -all_ext(<<"xpi">>) -> {<<"application">>, <<"x-xpinstall">>, []}; -all_ext(<<"xpl">>) -> {<<"application">>, <<"xproc+xml">>, []}; -all_ext(<<"xpm">>) -> {<<"image">>, <<"x-xpixmap">>, []}; -all_ext(<<"xpr">>) -> {<<"application">>, <<"vnd.is-xpr">>, []}; -all_ext(<<"xps">>) -> {<<"application">>, <<"vnd.ms-xpsdocument">>, []}; -all_ext(<<"xpw">>) -> {<<"application">>, <<"vnd.intercon.formnet">>, []}; -all_ext(<<"xpx">>) -> {<<"application">>, <<"vnd.intercon.formnet">>, []}; -all_ext(<<"xsl">>) -> {<<"application">>, <<"xml">>, []}; -all_ext(<<"xslt">>) -> {<<"application">>, <<"xslt+xml">>, []}; -all_ext(<<"xsm">>) -> {<<"application">>, <<"vnd.syncml+xml">>, []}; -all_ext(<<"xspf">>) -> {<<"application">>, <<"xspf+xml">>, []}; -all_ext(<<"xul">>) -> {<<"application">>, <<"vnd.mozilla.xul+xml">>, []}; -all_ext(<<"xvm">>) -> {<<"application">>, <<"xv+xml">>, []}; -all_ext(<<"xvml">>) -> {<<"application">>, <<"xv+xml">>, []}; -all_ext(<<"xwd">>) -> {<<"image">>, <<"x-xwindowdump">>, []}; -all_ext(<<"xyz">>) -> {<<"chemical">>, <<"x-xyz">>, []}; -all_ext(<<"xz">>) -> {<<"application">>, <<"x-xz">>, []}; -all_ext(<<"yang">>) -> {<<"application">>, <<"yang">>, []}; -all_ext(<<"yin">>) -> {<<"application">>, <<"yin+xml">>, []}; -all_ext(<<"z1">>) -> {<<"application">>, <<"x-zmachine">>, []}; -all_ext(<<"z2">>) -> {<<"application">>, <<"x-zmachine">>, []}; -all_ext(<<"z3">>) -> {<<"application">>, <<"x-zmachine">>, []}; -all_ext(<<"z4">>) -> {<<"application">>, <<"x-zmachine">>, []}; -all_ext(<<"z5">>) -> {<<"application">>, <<"x-zmachine">>, []}; -all_ext(<<"z6">>) -> {<<"application">>, <<"x-zmachine">>, []}; -all_ext(<<"z7">>) -> {<<"application">>, <<"x-zmachine">>, []}; -all_ext(<<"z8">>) -> {<<"application">>, <<"x-zmachine">>, []}; -all_ext(<<"zaz">>) -> {<<"application">>, <<"vnd.zzazz.deck+xml">>, []}; -all_ext(<<"zip">>) -> {<<"application">>, <<"zip">>, []}; -all_ext(<<"zir">>) -> {<<"application">>, <<"vnd.zul">>, []}; -all_ext(<<"zirz">>) -> {<<"application">>, <<"vnd.zul">>, []}; -all_ext(<<"zmm">>) -> {<<"application">>, <<"vnd.handheld-entertainment+xml">>, []}; -%% GENERATED -all_ext(_) -> {<<"application">>, <<"octet-stream">>, []}. - -web_ext(<<"css">>) -> {<<"text">>, <<"css">>, []}; -web_ext(<<"gif">>) -> {<<"image">>, <<"gif">>, []}; -web_ext(<<"html">>) -> {<<"text">>, <<"html">>, []}; -web_ext(<<"htm">>) -> {<<"text">>, <<"html">>, []}; -web_ext(<<"ico">>) -> {<<"image">>, <<"x-icon">>, []}; -web_ext(<<"jpeg">>) -> {<<"image">>, <<"jpeg">>, []}; -web_ext(<<"jpg">>) -> {<<"image">>, <<"jpeg">>, []}; -web_ext(<<"js">>) -> {<<"application">>, <<"javascript">>, []}; -web_ext(<<"mp3">>) -> {<<"audio">>, <<"mpeg">>, []}; -web_ext(<<"mp4">>) -> {<<"video">>, <<"mp4">>, []}; -web_ext(<<"ogg">>) -> {<<"audio">>, <<"ogg">>, []}; -web_ext(<<"ogv">>) -> {<<"video">>, <<"ogg">>, []}; -web_ext(<<"png">>) -> {<<"image">>, <<"png">>, []}; -web_ext(<<"svg">>) -> {<<"image">>, <<"svg+xml">>, []}; -web_ext(<<"wav">>) -> {<<"audio">>, <<"x-wav">>, []}; -web_ext(<<"webm">>) -> {<<"video">>, <<"webm">>, []}; -web_ext(_) -> {<<"application">>, <<"octet-stream">>, []}. DELETED deps/cowlib/src/cow_mimetypes.erl.src Index: deps/cowlib/src/cow_mimetypes.erl.src ================================================================== --- deps/cowlib/src/cow_mimetypes.erl.src +++ /dev/null @@ -1,59 +0,0 @@ -%% Copyright (c) 2013-2014, Loïc Hoguin -%% -%% Permission to use, copy, modify, and/or distribute this software for any -%% purpose with or without fee is hereby granted, provided that the above -%% copyright notice and this permission notice appear in all copies. -%% -%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - --module(cow_mimetypes). - --export([all/1]). --export([web/1]). - -%% @doc Return the mimetype for any file by looking at its extension. - --spec all(file:filename_all()) -> {binary(), binary(), []}. -all(Path) -> - case filename:extension(Path) of - <<>> -> {<<"application">>, <<"octet-stream">>, []}; - << $., Ext/binary >> -> all_ext(Ext) - end. - -%% @doc Return the mimetype for a Web related file by looking at its extension. - --spec web(file:filename_all()) -> {binary(), binary(), []}. -web(Path) -> - case filename:extension(Path) of - <<>> -> {<<"application">>, <<"octet-stream">>, []}; - << $., Ext/binary >> -> web_ext(Ext) - end. - -%% Internal. - -%% GENERATED -all_ext(_) -> {<<"application">>, <<"octet-stream">>, []}. - -web_ext(<<"css">>) -> {<<"text">>, <<"css">>, []}; -web_ext(<<"gif">>) -> {<<"image">>, <<"gif">>, []}; -web_ext(<<"html">>) -> {<<"text">>, <<"html">>, []}; -web_ext(<<"htm">>) -> {<<"text">>, <<"html">>, []}; -web_ext(<<"ico">>) -> {<<"image">>, <<"x-icon">>, []}; -web_ext(<<"jpeg">>) -> {<<"image">>, <<"jpeg">>, []}; -web_ext(<<"jpg">>) -> {<<"image">>, <<"jpeg">>, []}; -web_ext(<<"js">>) -> {<<"application">>, <<"javascript">>, []}; -web_ext(<<"mp3">>) -> {<<"audio">>, <<"mpeg">>, []}; -web_ext(<<"mp4">>) -> {<<"video">>, <<"mp4">>, []}; -web_ext(<<"ogg">>) -> {<<"audio">>, <<"ogg">>, []}; -web_ext(<<"ogv">>) -> {<<"video">>, <<"ogg">>, []}; -web_ext(<<"png">>) -> {<<"image">>, <<"png">>, []}; -web_ext(<<"svg">>) -> {<<"image">>, <<"svg+xml">>, []}; -web_ext(<<"wav">>) -> {<<"audio">>, <<"x-wav">>, []}; -web_ext(<<"webm">>) -> {<<"video">>, <<"webm">>, []}; -web_ext(_) -> {<<"application">>, <<"octet-stream">>, []}. DELETED deps/cowlib/src/cow_multipart.erl Index: deps/cowlib/src/cow_multipart.erl ================================================================== --- deps/cowlib/src/cow_multipart.erl +++ /dev/null @@ -1,752 +0,0 @@ -%% Copyright (c) 2014, Loïc Hoguin -%% -%% Permission to use, copy, modify, and/or distribute this software for any -%% purpose with or without fee is hereby granted, provided that the above -%% copyright notice and this permission notice appear in all copies. -%% -%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - --module(cow_multipart). - -%% Parsing. --export([parse_headers/2]). --export([parse_body/2]). - -%% Building. --export([boundary/0]). --export([first_part/2]). --export([part/2]). --export([close/1]). - -%% Headers. --export([form_data/1]). --export([parse_content_disposition/1]). --export([parse_content_transfer_encoding/1]). --export([parse_content_type/1]). - --type headers() :: [{iodata(), iodata()}]. --export_type([headers/0]). - --include("cow_inline.hrl"). - --define(TEST1_MIME, << - "This is a message with multiple parts in MIME format.\r\n" - "--frontier\r\n" - "Content-Type: text/plain\r\n" - "\r\n" - "This is the body of the message.\r\n" - "--frontier\r\n" - "Content-Type: application/octet-stream\r\n" - "Content-Transfer-Encoding: base64\r\n" - "\r\n" - "PGh0bWw+CiAgPGhlYWQ+CiAgPC9oZWFkPgogIDxib2R5PgogICAgPHA+VGhpcyBpcyB0aGUg\r\n" - "Ym9keSBvZiB0aGUgbWVzc2FnZS48L3A+CiAgPC9ib2R5Pgo8L2h0bWw+Cg==\r\n" - "--frontier--" ->>). --define(TEST1_BOUNDARY, <<"frontier">>). - --define(TEST2_MIME, << - "--AaB03x\r\n" - "Content-Disposition: form-data; name=\"submit-name\"\r\n" - "\r\n" - "Larry\r\n" - "--AaB03x\r\n" - "Content-Disposition: form-data; name=\"files\"\r\n" - "Content-Type: multipart/mixed; boundary=BbC04y\r\n" - "\r\n" - "--BbC04y\r\n" - "Content-Disposition: file; filename=\"file1.txt\"\r\n" - "Content-Type: text/plain\r\n" - "\r\n" - "... contents of file1.txt ...\r\n" - "--BbC04y\r\n" - "Content-Disposition: file; filename=\"file2.gif\"\r\n" - "Content-Type: image/gif\r\n" - "Content-Transfer-Encoding: binary\r\n" - "\r\n" - "...contents of file2.gif...\r\n" - "--BbC04y--\r\n" - "--AaB03x--" ->>). --define(TEST2_BOUNDARY, <<"AaB03x">>). - --define(TEST3_MIME, << - "This is the preamble.\r\n" - "--boundary\r\n" - "Content-Type: text/plain\r\n" - "\r\n" - "This is the body of the message.\r\n" - "--boundary--" - "\r\nThis is the epilogue. Here it includes leading CRLF" ->>). --define(TEST3_BOUNDARY, <<"boundary">>). - --define(TEST4_MIME, << - "This is the preamble.\r\n" - "--boundary\r\n" - "Content-Type: text/plain\r\n" - "\r\n" - "This is the body of the message.\r\n" - "--boundary--" - "\r\n" ->>). --define(TEST4_BOUNDARY, <<"boundary">>). - -%% Parsing. -%% -%% The multipart format is defined in RFC 2045. - -%% @doc Parse the headers for the next multipart part. -%% -%% This function skips any preamble before the boundary. -%% The preamble may be retrieved using parse_body/2. -%% -%% This function will accept input of any size, it is -%% up to the caller to limit it if needed. - --spec parse_headers(binary(), binary()) - -> more | {more, binary()} - | {ok, headers(), binary()} - | {done, binary()}. -%% If the stream starts with the boundary we can make a few assumptions -%% and quickly figure out if we got the complete list of headers. -parse_headers(<< "--", Stream/bits >>, Boundary) -> - BoundarySize = byte_size(Boundary), - case Stream of - %% Last boundary. Return the epilogue. - << Boundary:BoundarySize/binary, "--", Stream2/bits >> -> - {done, Stream2}; - << Boundary:BoundarySize/binary, Stream2/bits >> -> - %% We have all the headers only if there is a \r\n\r\n - %% somewhere in the data after the boundary. - case binary:match(Stream2, <<"\r\n\r\n">>) of - nomatch -> - more; - _ -> - before_parse_headers(Stream2) - end; - %% If there isn't enough to represent Boundary \r\n\r\n - %% then we definitely don't have all the headers. - _ when byte_size(Stream) < byte_size(Boundary) + 4 -> - more; - %% Otherwise we have preamble data to skip. - %% We still got rid of the first two misleading bytes. - _ -> - skip_preamble(Stream, Boundary) - end; -%% Otherwise we have preamble data to skip. -parse_headers(Stream, Boundary) -> - skip_preamble(Stream, Boundary). - -%% We need to find the boundary and a \r\n\r\n after that. -%% Since the boundary isn't at the start, it must be right -%% after a \r\n too. -skip_preamble(Stream, Boundary) -> - case binary:match(Stream, <<"\r\n--", Boundary/bits >>) of - %% No boundary, need more data. - nomatch -> - %% We can safely skip the size of the stream - %% minus the last 3 bytes which may be a partial boundary. - SkipSize = byte_size(Stream) - 3, - case SkipSize > 0 of - false -> - more; - true -> - << _:SkipSize/binary, Stream2/bits >> = Stream, - {more, Stream2} - end; - {Start, Length} -> - Start2 = Start + Length, - << _:Start2/binary, Stream2/bits >> = Stream, - case Stream2 of - %% Last boundary. Return the epilogue. - << "--", Stream3/bits >> -> - {done, Stream3}; - _ -> - case binary:match(Stream, <<"\r\n\r\n">>) of - %% We don't have the full headers. - nomatch -> - {more, Stream2}; - _ -> - before_parse_headers(Stream2) - end - end - end. - -%% There is a line break right after the boundary, skip it. -%% -%% We only skip it now because there might be no headers at all, -%% which means the \r\n\r\n indicating the end of headers also -%% includes this line break. -before_parse_headers(<< "\r\n", Stream/bits >>) -> - parse_hd_name(Stream, [], <<>>). - -parse_hd_name(<< C, Rest/bits >>, H, SoFar) -> - case C of - $: -> parse_hd_before_value(Rest, H, SoFar); - $\s -> parse_hd_name_ws(Rest, H, SoFar); - $\t -> parse_hd_name_ws(Rest, H, SoFar); - ?INLINE_LOWERCASE(parse_hd_name, Rest, H, SoFar) - end. - -parse_hd_name_ws(<< C, Rest/bits >>, H, Name) -> - case C of - $\s -> parse_hd_name_ws(Rest, H, Name); - $\t -> parse_hd_name_ws(Rest, H, Name); - $: -> parse_hd_before_value(Rest, H, Name) - end. - -parse_hd_before_value(<< $\s, Rest/bits >>, H, N) -> - parse_hd_before_value(Rest, H, N); -parse_hd_before_value(<< $\t, Rest/bits >>, H, N) -> - parse_hd_before_value(Rest, H, N); -parse_hd_before_value(Buffer, H, N) -> - parse_hd_value(Buffer, H, N, <<>>). - -parse_hd_value(<< $\r, Rest/bits >>, Headers, Name, SoFar) -> - case Rest of - << "\n\r\n", Rest2/bits >> -> - {ok, [{Name, SoFar}|Headers], Rest2}; - << $\n, C, Rest2/bits >> when C =:= $\s; C =:= $\t -> - parse_hd_value(Rest2, Headers, Name, SoFar); - << $\n, Rest2/bits >> -> - parse_hd_name(Rest2, [{Name, SoFar}|Headers], <<>>) - end; -parse_hd_value(<< C, Rest/bits >>, H, N, SoFar) -> - parse_hd_value(Rest, H, N, << SoFar/binary, C >>). - -%% @doc Parse the body of the current multipart part. -%% -%% The body is everything until the next boundary. - --spec parse_body(binary(), binary()) - -> {ok, binary()} | {ok, binary(), binary()} - | done | {done, binary()} | {done, binary(), binary()}. -parse_body(Stream, Boundary) -> - BoundarySize = byte_size(Boundary), - case Stream of - << "--", Boundary:BoundarySize/binary, _/bits >> -> - done; - _ -> - case binary:match(Stream, << "\r\n--", Boundary/bits >>) of - %% No boundary, check for a possible partial at the end. - %% Return more or less of the body depending on the result. - nomatch -> - StreamSize = byte_size(Stream), - From = StreamSize - BoundarySize - 3, - MatchOpts = if - %% Binary too small to contain boundary, check it fully. - From < 0 -> []; - %% Optimize, only check the end of the binary. - true -> [{scope, {From, StreamSize - From}}] - end, - case binary:match(Stream, <<"\r">>, MatchOpts) of - nomatch -> - {ok, Stream}; - {Pos, _} -> - case Stream of - << Body:Pos/binary >> -> - {ok, Body}; - << Body:Pos/binary, Rest/bits >> -> - {ok, Body, Rest} - end - end; - %% Boundary found, this is the last chunk of the body. - {Pos, _} -> - case Stream of - << Body:Pos/binary, "\r\n" >> -> - {done, Body}; - << Body:Pos/binary, "\r\n", Rest/bits >> -> - {done, Body, Rest}; - << Body:Pos/binary, Rest/bits >> -> - {done, Body, Rest} - end - end - end. - --ifdef(TEST). -parse_test() -> - H1 = [{<<"content-type">>, <<"text/plain">>}], - Body1 = <<"This is the body of the message.">>, - H2 = lists:sort([{<<"content-type">>, <<"application/octet-stream">>}, - {<<"content-transfer-encoding">>, <<"base64">>}]), - Body2 = <<"PGh0bWw+CiAgPGhlYWQ+CiAgPC9oZWFkPgogIDxib2R5PgogICAgPHA+VGhpcyBpcyB0aGUg\r\n" - "Ym9keSBvZiB0aGUgbWVzc2FnZS48L3A+CiAgPC9ib2R5Pgo8L2h0bWw+Cg==">>, - {ok, H1, Rest} = parse_headers(?TEST1_MIME, ?TEST1_BOUNDARY), - {done, Body1, Rest2} = parse_body(Rest, ?TEST1_BOUNDARY), - done = parse_body(Rest2, ?TEST1_BOUNDARY), - {ok, H2Unsorted, Rest3} = parse_headers(Rest2, ?TEST1_BOUNDARY), - H2 = lists:sort(H2Unsorted), - {done, Body2, Rest4} = parse_body(Rest3, ?TEST1_BOUNDARY), - done = parse_body(Rest4, ?TEST1_BOUNDARY), - {done, <<>>} = parse_headers(Rest4, ?TEST1_BOUNDARY), - ok. - -parse_interleaved_test() -> - H1 = [{<<"content-disposition">>, <<"form-data; name=\"submit-name\"">>}], - Body1 = <<"Larry">>, - H2 = lists:sort([{<<"content-disposition">>, <<"form-data; name=\"files\"">>}, - {<<"content-type">>, <<"multipart/mixed; boundary=BbC04y">>}]), - InH1 = lists:sort([{<<"content-disposition">>, <<"file; filename=\"file1.txt\"">>}, - {<<"content-type">>, <<"text/plain">>}]), - InBody1 = <<"... contents of file1.txt ...">>, - InH2 = lists:sort([{<<"content-disposition">>, <<"file; filename=\"file2.gif\"">>}, - {<<"content-type">>, <<"image/gif">>}, - {<<"content-transfer-encoding">>, <<"binary">>}]), - InBody2 = <<"...contents of file2.gif...">>, - {ok, H1, Rest} = parse_headers(?TEST2_MIME, ?TEST2_BOUNDARY), - {done, Body1, Rest2} = parse_body(Rest, ?TEST2_BOUNDARY), - done = parse_body(Rest2, ?TEST2_BOUNDARY), - {ok, H2Unsorted, Rest3} = parse_headers(Rest2, ?TEST2_BOUNDARY), - H2 = lists:sort(H2Unsorted), - {_, ContentType} = lists:keyfind(<<"content-type">>, 1, H2), - {<<"multipart">>, <<"mixed">>, [{<<"boundary">>, InBoundary}]} - = parse_content_type(ContentType), - {ok, InH1Unsorted, InRest} = parse_headers(Rest3, InBoundary), - InH1 = lists:sort(InH1Unsorted), - {done, InBody1, InRest2} = parse_body(InRest, InBoundary), - done = parse_body(InRest2, InBoundary), - {ok, InH2Unsorted, InRest3} = parse_headers(InRest2, InBoundary), - InH2 = lists:sort(InH2Unsorted), - {done, InBody2, InRest4} = parse_body(InRest3, InBoundary), - done = parse_body(InRest4, InBoundary), - {done, Rest4} = parse_headers(InRest4, InBoundary), - {done, <<>>} = parse_headers(Rest4, ?TEST2_BOUNDARY), - ok. - -parse_epilogue_test() -> - H1 = [{<<"content-type">>, <<"text/plain">>}], - Body1 = <<"This is the body of the message.">>, - Epilogue = <<"\r\nThis is the epilogue. Here it includes leading CRLF">>, - {ok, H1, Rest} = parse_headers(?TEST3_MIME, ?TEST3_BOUNDARY), - {done, Body1, Rest2} = parse_body(Rest, ?TEST3_BOUNDARY), - done = parse_body(Rest2, ?TEST3_BOUNDARY), - {done, Epilogue} = parse_headers(Rest2, ?TEST3_BOUNDARY), - ok. - -parse_epilogue_crlf_test() -> - H1 = [{<<"content-type">>, <<"text/plain">>}], - Body1 = <<"This is the body of the message.">>, - Epilogue = <<"\r\n">>, - {ok, H1, Rest} = parse_headers(?TEST4_MIME, ?TEST4_BOUNDARY), - {done, Body1, Rest2} = parse_body(Rest, ?TEST4_BOUNDARY), - done = parse_body(Rest2, ?TEST4_BOUNDARY), - {done, Epilogue} = parse_headers(Rest2, ?TEST4_BOUNDARY), - ok. - -parse_partial_test() -> - {ok, <<0:8000, "abcdef">>, <<"\rghij">>} - = parse_body(<<0:8000, "abcdef\rghij">>, <<"boundary">>), - {ok, <<"abcdef">>, <<"\rghij">>} - = parse_body(<<"abcdef\rghij">>, <<"boundary">>), - {ok, <<"abc">>, <<"\rdef">>} - = parse_body(<<"abc\rdef">>, <<"boundaryboundary">>), - {ok, <<0:8000, "abcdef">>, <<"\r\nghij">>} - = parse_body(<<0:8000, "abcdef\r\nghij">>, <<"boundary">>), - {ok, <<"abcdef">>, <<"\r\nghij">>} - = parse_body(<<"abcdef\r\nghij">>, <<"boundary">>), - {ok, <<"abc">>, <<"\r\ndef">>} - = parse_body(<<"abc\r\ndef">>, <<"boundaryboundary">>), - {ok, <<"boundary">>, <<"\r">>} - = parse_body(<<"boundary\r">>, <<"boundary">>), - {ok, <<"boundary">>, <<"\r\n">>} - = parse_body(<<"boundary\r\n">>, <<"boundary">>), - {ok, <<"boundary">>, <<"\r\n-">>} - = parse_body(<<"boundary\r\n-">>, <<"boundary">>), - {ok, <<"boundary">>, <<"\r\n--">>} - = parse_body(<<"boundary\r\n--">>, <<"boundary">>), - ok. --endif. - --ifdef(PERF). -perf_parse_multipart(Stream, Boundary) -> - case parse_headers(Stream, Boundary) of - {ok, _, Rest} -> - {_, _, Rest2} = parse_body(Rest, Boundary), - perf_parse_multipart(Rest2, Boundary); - {done, _} -> - ok - end. - -horse_parse() -> - horse:repeat(50000, - perf_parse_multipart(?TEST1_MIME, ?TEST1_BOUNDARY) - ). --endif. - -%% Building. - -%% @doc Generate a new random boundary. -%% -%% The boundary generated has a low probability of ever appearing -%% in the data. - --spec boundary() -> binary(). -boundary() -> - base64:encode(crypto:rand_bytes(48)). - -%% @doc Return the first part's head. -%% -%% This works exactly like the part/2 function except there is -%% no leading \r\n. It's not required to use this function, -%% just makes the output a little smaller and prettier. - --spec first_part(binary(), headers()) -> iodata(). -first_part(Boundary, Headers) -> - [<<"--">>, Boundary, <<"\r\n">>, headers_to_iolist(Headers, [])]. - -%% @doc Return a part's head. - --spec part(binary(), headers()) -> iodata(). -part(Boundary, Headers) -> - [<<"\r\n--">>, Boundary, <<"\r\n">>, headers_to_iolist(Headers, [])]. - -headers_to_iolist([], Acc) -> - lists:reverse([<<"\r\n">>|Acc]); -headers_to_iolist([{N, V}|Tail], Acc) -> - %% We don't want to create a sublist so we list the - %% values in reverse order so that it gets reversed properly. - headers_to_iolist(Tail, [<<"\r\n">>, V, <<": ">>, N|Acc]). - -%% @doc Return the closing delimiter of the multipart message. - --spec close(binary()) -> iodata(). -close(Boundary) -> - [<<"\r\n--">>, Boundary, <<"--">>]. - --ifdef(TEST). -build_test() -> - Result = string:to_lower(binary_to_list(?TEST1_MIME)), - Result = string:to_lower(binary_to_list(iolist_to_binary([ - <<"This is a message with multiple parts in MIME format.\r\n">>, - first_part(?TEST1_BOUNDARY, [{<<"content-type">>, <<"text/plain">>}]), - <<"This is the body of the message.">>, - part(?TEST1_BOUNDARY, [ - {<<"content-type">>, <<"application/octet-stream">>}, - {<<"content-transfer-encoding">>, <<"base64">>}]), - <<"PGh0bWw+CiAgPGhlYWQ+CiAgPC9oZWFkPgogIDxib2R5PgogICAgPHA+VGhpcyBpcyB0aGUg\r\n" - "Ym9keSBvZiB0aGUgbWVzc2FnZS48L3A+CiAgPC9ib2R5Pgo8L2h0bWw+Cg==">>, - close(?TEST1_BOUNDARY) - ]))), - ok. - -identity_test() -> - B = boundary(), - Preamble = <<"This is a message with multiple parts in MIME format.">>, - H1 = [{<<"content-type">>, <<"text/plain">>}], - Body1 = <<"This is the body of the message.">>, - H2 = lists:sort([{<<"content-type">>, <<"application/octet-stream">>}, - {<<"content-transfer-encoding">>, <<"base64">>}]), - Body2 = <<"PGh0bWw+CiAgPGhlYWQ+CiAgPC9oZWFkPgogIDxib2R5PgogICAgPHA+VGhpcyBpcyB0aGUg\r\n" - "Ym9keSBvZiB0aGUgbWVzc2FnZS48L3A+CiAgPC9ib2R5Pgo8L2h0bWw+Cg==">>, - Epilogue = <<"Gotta go fast!">>, - M = iolist_to_binary([ - Preamble, - part(B, H1), Body1, - part(B, H2), Body2, - close(B), - Epilogue - ]), - {done, Preamble, M2} = parse_body(M, B), - {ok, H1, M3} = parse_headers(M2, B), - {done, Body1, M4} = parse_body(M3, B), - {ok, H2Unsorted, M5} = parse_headers(M4, B), - H2 = lists:sort(H2Unsorted), - {done, Body2, M6} = parse_body(M5, B), - {done, Epilogue} = parse_headers(M6, B), - ok. --endif. - --ifdef(PERF). -perf_build_multipart() -> - B = boundary(), - [ - <<"preamble\r\n">>, - first_part(B, [{<<"content-type">>, <<"text/plain">>}]), - <<"This is the body of the message.">>, - part(B, [ - {<<"content-type">>, <<"application/octet-stream">>}, - {<<"content-transfer-encoding">>, <<"base64">>}]), - <<"PGh0bWw+CiAgPGhlYWQ+CiAgPC9oZWFkPgogIDxib2R5PgogICAgPHA+VGhpcyBpcyB0aGUg\r\n" - "Ym9keSBvZiB0aGUgbWVzc2FnZS48L3A+CiAgPC9ib2R5Pgo8L2h0bWw+Cg==">>, - close(B), - <<"epilogue">> - ]. - -horse_build() -> - horse:repeat(50000, - perf_build_multipart() - ). --endif. - -%% Headers. - -%% @doc Convenience function for extracting information from headers -%% when parsing a multipart/form-data stream. - --spec form_data(headers()) - -> {data, binary()} - | {file, binary(), binary(), binary(), binary()}. -form_data(Headers) -> - {_, DispositionBin} = lists:keyfind(<<"content-disposition">>, 1, Headers), - {<<"form-data">>, Params} = parse_content_disposition(DispositionBin), - {_, FieldName} = lists:keyfind(<<"name">>, 1, Params), - case lists:keyfind(<<"filename">>, 1, Params) of - false -> - {data, FieldName}; - {_, Filename} -> - Type = case lists:keyfind(<<"content-type">>, 1, Headers) of - false -> <<"text/plain">>; - {_, T} -> T - end, - TransferEncoding = case lists:keyfind( - <<"content-transfer-encoding">>, 1, Headers) of - false -> <<"7bit">>; - {_, TE} -> TE - end, - {file, FieldName, Filename, Type, TransferEncoding} - end. - --ifdef(TEST). -form_data_test_() -> - Tests = [ - {[{<<"content-disposition">>, <<"form-data; name=\"submit-name\"">>}], - {data, <<"submit-name">>}}, - {[{<<"content-disposition">>, - <<"form-data; name=\"files\"; filename=\"file1.txt\"">>}, - {<<"content-type">>, <<"text/x-plain">>}], - {file, <<"files">>, <<"file1.txt">>, - <<"text/x-plain">>, <<"7bit">>}} - ], - [{lists:flatten(io_lib:format("~p", [V])), - fun() -> R = form_data(V) end} || {V, R} <- Tests]. --endif. - -%% @todo parse_content_description -%% @todo parse_content_id - -%% @doc Parse an RFC 2183 content-disposition value. -%% @todo Support RFC 2231. - --spec parse_content_disposition(binary()) - -> {binary(), [{binary(), binary()}]}. -parse_content_disposition(Bin) -> - parse_cd_type(Bin, <<>>). - -parse_cd_type(<<>>, Acc) -> - {Acc, []}; -parse_cd_type(<< C, Rest/bits >>, Acc) -> - case C of - $; -> {Acc, parse_before_param(Rest, [])}; - $\s -> {Acc, parse_before_param(Rest, [])}; - $\t -> {Acc, parse_before_param(Rest, [])}; - ?INLINE_LOWERCASE(parse_cd_type, Rest, Acc) - end. - --ifdef(TEST). -parse_content_disposition_test_() -> - Tests = [ - {<<"inline">>, {<<"inline">>, []}}, - {<<"attachment">>, {<<"attachment">>, []}}, - {<<"attachment; filename=genome.jpeg;" - " modification-date=\"Wed, 12 Feb 1997 16:29:51 -0500\";">>, - {<<"attachment">>, [ - {<<"filename">>, <<"genome.jpeg">>}, - {<<"modification-date">>, <<"Wed, 12 Feb 1997 16:29:51 -0500">>} - ]}}, - {<<"form-data; name=\"user\"">>, - {<<"form-data">>, [{<<"name">>, <<"user">>}]}}, - {<<"form-data; NAME=\"submit-name\"">>, - {<<"form-data">>, [{<<"name">>, <<"submit-name">>}]}}, - {<<"form-data; name=\"files\"; filename=\"file1.txt\"">>, - {<<"form-data">>, [ - {<<"name">>, <<"files">>}, - {<<"filename">>, <<"file1.txt">>} - ]}}, - {<<"file; filename=\"file1.txt\"">>, - {<<"file">>, [{<<"filename">>, <<"file1.txt">>}]}}, - {<<"file; filename=\"file2.gif\"">>, - {<<"file">>, [{<<"filename">>, <<"file2.gif">>}]}} - ], - [{V, fun() -> R = parse_content_disposition(V) end} || {V, R} <- Tests]. --endif. - --ifdef(PERF). -horse_parse_content_disposition_attachment() -> - horse:repeat(100000, - parse_content_disposition(<<"attachment; filename=genome.jpeg;" - " modification-date=\"Wed, 12 Feb 1997 16:29:51 -0500\";">>) - ). - -horse_parse_content_disposition_form_data() -> - horse:repeat(100000, - parse_content_disposition( - <<"form-data; name=\"files\"; filename=\"file1.txt\"">>) - ). - -horse_parse_content_disposition_inline() -> - horse:repeat(100000, - parse_content_disposition(<<"inline">>) - ). --endif. - -%% @doc Parse an RFC 2045 content-transfer-encoding header. - --spec parse_content_transfer_encoding(binary()) -> binary(). -parse_content_transfer_encoding(Bin) -> - ?INLINE_LOWERCASE_BC(Bin). - --ifdef(TEST). -parse_content_transfer_encoding_test_() -> - Tests = [ - {<<"7bit">>, <<"7bit">>}, - {<<"7BIT">>, <<"7bit">>}, - {<<"8bit">>, <<"8bit">>}, - {<<"binary">>, <<"binary">>}, - {<<"quoted-printable">>, <<"quoted-printable">>}, - {<<"base64">>, <<"base64">>}, - {<<"Base64">>, <<"base64">>}, - {<<"BASE64">>, <<"base64">>}, - {<<"bAsE64">>, <<"base64">>} - ], - [{V, fun() -> R = parse_content_transfer_encoding(V) end} - || {V, R} <- Tests]. --endif. - --ifdef(PERF). -horse_parse_content_transfer_encoding() -> - horse:repeat(100000, - parse_content_transfer_encoding(<<"QUOTED-PRINTABLE">>) - ). --endif. - -%% @doc Parse an RFC 2045 content-type header. - --spec parse_content_type(binary()) - -> {binary(), binary(), [{binary(), binary()}]}. -parse_content_type(Bin) -> - parse_ct_type(Bin, <<>>). - -parse_ct_type(<< C, Rest/bits >>, Acc) -> - case C of - $/ -> parse_ct_subtype(Rest, Acc, <<>>); - ?INLINE_LOWERCASE(parse_ct_type, Rest, Acc) - end. - -parse_ct_subtype(<<>>, Type, Subtype) when Subtype =/= <<>> -> - {Type, Subtype, []}; -parse_ct_subtype(<< C, Rest/bits >>, Type, Acc) -> - case C of - $; -> {Type, Acc, parse_before_param(Rest, [])}; - $\s -> {Type, Acc, parse_before_param(Rest, [])}; - $\t -> {Type, Acc, parse_before_param(Rest, [])}; - ?INLINE_LOWERCASE(parse_ct_subtype, Rest, Type, Acc) - end. - --ifdef(TEST). -parse_content_type_test_() -> - Tests = [ - {<<"image/gif">>, - {<<"image">>, <<"gif">>, []}}, - {<<"text/plain">>, - {<<"text">>, <<"plain">>, []}}, - {<<"text/plain; charset=us-ascii">>, - {<<"text">>, <<"plain">>, [{<<"charset">>, <<"us-ascii">>}]}}, - {<<"text/plain; charset=\"us-ascii\"">>, - {<<"text">>, <<"plain">>, [{<<"charset">>, <<"us-ascii">>}]}}, - {<<"multipart/form-data; boundary=AaB03x">>, - {<<"multipart">>, <<"form-data">>, - [{<<"boundary">>, <<"AaB03x">>}]}}, - {<<"multipart/mixed; boundary=BbC04y">>, - {<<"multipart">>, <<"mixed">>, [{<<"boundary">>, <<"BbC04y">>}]}}, - {<<"multipart/mixed; boundary=--------">>, - {<<"multipart">>, <<"mixed">>, [{<<"boundary">>, <<"--------">>}]}}, - {<<"application/x-horse; filename=genome.jpeg;" - " some-date=\"Wed, 12 Feb 1997 16:29:51 -0500\";" - " charset=us-ascii; empty=; number=12345">>, - {<<"application">>, <<"x-horse">>, [ - {<<"filename">>, <<"genome.jpeg">>}, - {<<"some-date">>, <<"Wed, 12 Feb 1997 16:29:51 -0500">>}, - {<<"charset">>, <<"us-ascii">>}, - {<<"empty">>, <<>>}, - {<<"number">>, <<"12345">>} - ]}} - ], - [{V, fun() -> R = parse_content_type(V) end} - || {V, R} <- Tests]. --endif. - --ifdef(PERF). -horse_parse_content_type_zero() -> - horse:repeat(100000, - parse_content_type(<<"text/plain">>) - ). - -horse_parse_content_type_one() -> - horse:repeat(100000, - parse_content_type(<<"text/plain; charset=\"us-ascii\"">>) - ). - -horse_parse_content_type_five() -> - horse:repeat(100000, - parse_content_type(<<"application/x-horse; filename=genome.jpeg;" - " some-date=\"Wed, 12 Feb 1997 16:29:51 -0500\";" - " charset=us-ascii; empty=; number=12345">>) - ). --endif. - -%% @doc Parse RFC 2045 parameters. - -parse_before_param(<<>>, Params) -> - lists:reverse(Params); -parse_before_param(<< C, Rest/bits >>, Params) -> - case C of - $; -> parse_before_param(Rest, Params); - $\s -> parse_before_param(Rest, Params); - $\t -> parse_before_param(Rest, Params); - ?INLINE_LOWERCASE(parse_param_name, Rest, Params, <<>>) - end. - -parse_param_name(<<>>, Params, Acc) -> - lists:reverse([{Acc, <<>>}|Params]); -parse_param_name(<< C, Rest/bits >>, Params, Acc) -> - case C of - $= -> parse_param_value(Rest, Params, Acc); - ?INLINE_LOWERCASE(parse_param_name, Rest, Params, Acc) - end. - -parse_param_value(<<>>, Params, Name) -> - lists:reverse([{Name, <<>>}|Params]); -parse_param_value(<< C, Rest/bits >>, Params, Name) -> - case C of - $" -> parse_param_quoted_value(Rest, Params, Name, <<>>); - $; -> parse_before_param(Rest, [{Name, <<>>}|Params]); - $\s -> parse_before_param(Rest, [{Name, <<>>}|Params]); - $\t -> parse_before_param(Rest, [{Name, <<>>}|Params]); - C -> parse_param_value(Rest, Params, Name, << C >>) - end. - -parse_param_value(<<>>, Params, Name, Acc) -> - lists:reverse([{Name, Acc}|Params]); -parse_param_value(<< C, Rest/bits >>, Params, Name, Acc) -> - case C of - $; -> parse_before_param(Rest, [{Name, Acc}|Params]); - $\s -> parse_before_param(Rest, [{Name, Acc}|Params]); - $\t -> parse_before_param(Rest, [{Name, Acc}|Params]); - C -> parse_param_value(Rest, Params, Name, << Acc/binary, C >>) - end. - -%% We expect a final $" so no need to test for <<>>. -parse_param_quoted_value(<< $\\, C, Rest/bits >>, Params, Name, Acc) -> - parse_param_quoted_value(Rest, Params, Name, << Acc/binary, C >>); -parse_param_quoted_value(<< $", Rest/bits >>, Params, Name, Acc) -> - parse_before_param(Rest, [{Name, Acc}|Params]); -parse_param_quoted_value(<< C, Rest/bits >>, Params, Name, Acc) - when C =/= $\r -> - parse_param_quoted_value(Rest, Params, Name, << Acc/binary, C >>). DELETED deps/cowlib/src/cow_qs.erl Index: deps/cowlib/src/cow_qs.erl ================================================================== --- deps/cowlib/src/cow_qs.erl +++ /dev/null @@ -1,571 +0,0 @@ -%% Copyright (c) 2013-2014, Loïc Hoguin -%% -%% Permission to use, copy, modify, and/or distribute this software for any -%% purpose with or without fee is hereby granted, provided that the above -%% copyright notice and this permission notice appear in all copies. -%% -%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - --module(cow_qs). - --export([parse_qs/1]). --export([qs/1]). --export([urldecode/1]). --export([urlencode/1]). - --type qs_vals() :: [{binary(), binary() | true}]. - -%% @doc Parse an application/x-www-form-urlencoded string. -%% -%% The percent decoding is inlined to greatly improve the performance -%% by avoiding copying binaries twice (once for extracting, once for -%% decoding) instead of just extracting the proper representation. - --spec parse_qs(binary()) -> qs_vals(). -parse_qs(B) -> - parse_qs_name(B, [], <<>>). - -parse_qs_name(<< $%, H, L, Rest/bits >>, Acc, Name) -> - C = (unhex(H) bsl 4 bor unhex(L)), - parse_qs_name(Rest, Acc, << Name/bits, C >>); -parse_qs_name(<< $+, Rest/bits >>, Acc, Name) -> - parse_qs_name(Rest, Acc, << Name/bits, " " >>); -parse_qs_name(<< $=, Rest/bits >>, Acc, Name) when Name =/= <<>> -> - parse_qs_value(Rest, Acc, Name, <<>>); -parse_qs_name(<< $&, Rest/bits >>, Acc, Name) -> - case Name of - <<>> -> parse_qs_name(Rest, Acc, <<>>); - _ -> parse_qs_name(Rest, [{Name, true}|Acc], <<>>) - end; -parse_qs_name(<< C, Rest/bits >>, Acc, Name) when C =/= $%, C =/= $= -> - parse_qs_name(Rest, Acc, << Name/bits, C >>); -parse_qs_name(<<>>, Acc, Name) -> - case Name of - <<>> -> lists:reverse(Acc); - _ -> lists:reverse([{Name, true}|Acc]) - end. - -parse_qs_value(<< $%, H, L, Rest/bits >>, Acc, Name, Value) -> - C = (unhex(H) bsl 4 bor unhex(L)), - parse_qs_value(Rest, Acc, Name, << Value/bits, C >>); -parse_qs_value(<< $+, Rest/bits >>, Acc, Name, Value) -> - parse_qs_value(Rest, Acc, Name, << Value/bits, " " >>); -parse_qs_value(<< $&, Rest/bits >>, Acc, Name, Value) -> - parse_qs_name(Rest, [{Name, Value}|Acc], <<>>); -parse_qs_value(<< C, Rest/bits >>, Acc, Name, Value) when C =/= $% -> - parse_qs_value(Rest, Acc, Name, << Value/bits, C >>); -parse_qs_value(<<>>, Acc, Name, Value) -> - lists:reverse([{Name, Value}|Acc]). - --ifdef(TEST). -parse_qs_test_() -> - Tests = [ - {<<>>, []}, - {<<"&">>, []}, - {<<"a">>, [{<<"a">>, true}]}, - {<<"a&">>, [{<<"a">>, true}]}, - {<<"&a">>, [{<<"a">>, true}]}, - {<<"a&b">>, [{<<"a">>, true}, {<<"b">>, true}]}, - {<<"a&&b">>, [{<<"a">>, true}, {<<"b">>, true}]}, - {<<"a&b&">>, [{<<"a">>, true}, {<<"b">>, true}]}, - {<<"=">>, error}, - {<<"=b">>, error}, - {<<"a=">>, [{<<"a">>, <<>>}]}, - {<<"a=b">>, [{<<"a">>, <<"b">>}]}, - {<<"a=&b=">>, [{<<"a">>, <<>>}, {<<"b">>, <<>>}]}, - {<<"a=b&c&d=e">>, [{<<"a">>, <<"b">>}, - {<<"c">>, true}, {<<"d">>, <<"e">>}]}, - {<<"a=b=c&d=e=f&g=h=i">>, [{<<"a">>, <<"b=c">>}, - {<<"d">>, <<"e=f">>}, {<<"g">>, <<"h=i">>}]}, - {<<"+">>, [{<<" ">>, true}]}, - {<<"+=+">>, [{<<" ">>, <<" ">>}]}, - {<<"a+b=c+d">>, [{<<"a b">>, <<"c d">>}]}, - {<<"+a+=+b+&+c+=+d+">>, [{<<" a ">>, <<" b ">>}, - {<<" c ">>, <<" d ">>}]}, - {<<"a%20b=c%20d">>, [{<<"a b">>, <<"c d">>}]}, - {<<"%25%26%3D=%25%26%3D&_-.=.-_">>, [{<<"%&=">>, <<"%&=">>}, - {<<"_-.">>, <<".-_">>}]}, - {<<"for=extend%2Franch">>, [{<<"for">>, <<"extend/ranch">>}]} - ], - [{Qs, fun() -> - E = try parse_qs(Qs) of - R -> R - catch _:_ -> - error - end - end} || {Qs, E} <- Tests]. - -parse_qs_identity_test_() -> - Tests = [ - <<"+">>, - <<"hl=en&q=erlang+cowboy">>, - <<"direction=desc&for=extend%2Franch&sort=updated&state=open">>, - <<"i=EWiIXmPj5gl6&v=QowBp0oDLQXdd4x_GwiywA&ip=98.20.31.81&" - "la=en&pg=New8.undertonebrandsafe.com%2F698a2525065ee2" - "60c0b2f2aaad89ab82&re=&sz=1&fc=1&fr=140&br=3&bv=11.0." - "696.16&os=3&ov=&rs=vpl&k=cookies%7Csale%7Cbrowser%7Cm" - "ore%7Cprivacy%7Cstatistics%7Cactivities%7Cauction%7Ce" - "mail%7Cfree%7Cin...&t=112373&xt=5%7C61%7C0&tz=-1&ev=x" - "&tk=&za=1&ortb-za=1&zu=&zl=&ax=U&ay=U&ortb-pid=536454" - ".55&ortb-sid=112373.8&seats=999&ortb-xt=IAB24&ortb-ugc=">>, - <<"i=9pQNskA&v=0ySQQd1F&ev=12345678&t=12345&sz=3&ip=67.58." - "236.89&la=en&pg=http%3A%2F%2Fwww.yahoo.com%2Fpage1.ht" - "m&re=http%3A%2F%2Fsearch.google.com&fc=1&fr=1&br=2&bv" - "=3.0.14&os=1&ov=XP&k=cars%2Cford&rs=js&xt=5%7C22%7C23" - "4&tz=%2B180&tk=key1%3Dvalue1%7Ckey2%3Dvalue2&zl=4%2C5" - "%2C6&za=4&zu=competitor.com&ua=Mozilla%2F5.0+%28Windo" - "ws%3B+U%3B+Windows+NT+6.1%3B+en-US%29+AppleWebKit%2F5" - "34.13+%28KHTML%2C+like+Gecko%29+Chrome%2F9.0.597.98+S" - "afari%2F534.13&ortb-za=1%2C6%2C13&ortb-pid=521732&ort" - "b-sid=521732&ortb-xt=IAB3&ortb-ugc=">> - ], - [{V, fun() -> V = qs(parse_qs(V)) end} || V <- Tests]. --endif. - --ifdef(PERF). -horse_parse_qs_shorter() -> - horse:repeat(20000, - parse_qs(<<"hl=en&q=erlang%20cowboy">>) - ). - -horse_parse_qs_short() -> - horse:repeat(20000, - parse_qs( - <<"direction=desc&for=extend%2Franch&sort=updated&state=open">>) - ). - -horse_parse_qs_long() -> - horse:repeat(20000, - parse_qs(<<"i=EWiIXmPj5gl6&v=QowBp0oDLQXdd4x_GwiywA&ip=98.20.31.81&" - "la=en&pg=New8.undertonebrandsafe.com%2F698a2525065ee260c0b2f2a" - "aad89ab82&re=&sz=1&fc=1&fr=140&br=3&bv=11.0.696.16&os=3&ov=&rs" - "=vpl&k=cookies%7Csale%7Cbrowser%7Cmore%7Cprivacy%7Cstatistics%" - "7Cactivities%7Cauction%7Cemail%7Cfree%7Cin...&t=112373&xt=5%7C" - "61%7C0&tz=-1&ev=x&tk=&za=1&ortb-za=1&zu=&zl=&ax=U&ay=U&ortb-pi" - "d=536454.55&ortb-sid=112373.8&seats=999&ortb-xt=IAB24&ortb-ugc" - "=">>) - ). - -horse_parse_qs_longer() -> - horse:repeat(20000, - parse_qs(<<"i=9pQNskA&v=0ySQQd1F&ev=12345678&t=12345&sz=3&ip=67.58." - "236.89&la=en&pg=http%3A%2F%2Fwww.yahoo.com%2Fpage1.htm&re=http" - "%3A%2F%2Fsearch.google.com&fc=1&fr=1&br=2&bv=3.0.14&os=1&ov=XP" - "&k=cars%2cford&rs=js&xt=5%7c22%7c234&tz=%2b180&tk=key1%3Dvalue" - "1%7Ckey2%3Dvalue2&zl=4,5,6&za=4&zu=competitor.com&ua=Mozilla%2" - "F5.0%20(Windows%3B%20U%3B%20Windows%20NT%206.1%3B%20en-US)%20A" - "ppleWebKit%2F534.13%20(KHTML%2C%20like%20Gecko)%20Chrome%2F9.0" - ".597.98%20Safari%2F534.13&ortb-za=1%2C6%2C13&ortb-pid=521732&o" - "rtb-sid=521732&ortb-xt=IAB3&ortb-ugc=">>) - ). --endif. - -%% @doc Build an application/x-www-form-urlencoded string. - --spec qs(qs_vals()) -> binary(). -qs([]) -> - <<>>; -qs(L) -> - qs(L, <<>>). - -qs([], Acc) -> - << $&, Qs/bits >> = Acc, - Qs; -qs([{Name, true}|Tail], Acc) -> - Acc2 = urlencode(Name, << Acc/bits, $& >>), - qs(Tail, Acc2); -qs([{Name, Value}|Tail], Acc) -> - Acc2 = urlencode(Name, << Acc/bits, $& >>), - Acc3 = urlencode(Value, << Acc2/bits, $= >>), - qs(Tail, Acc3). - --define(QS_SHORTER, [ - {<<"hl">>, <<"en">>}, - {<<"q">>, <<"erlang cowboy">>} -]). - --define(QS_SHORT, [ - {<<"direction">>, <<"desc">>}, - {<<"for">>, <<"extend/ranch">>}, - {<<"sort">>, <<"updated">>}, - {<<"state">>, <<"open">>} -]). - --define(QS_LONG, [ - {<<"i">>, <<"EWiIXmPj5gl6">>}, - {<<"v">>, <<"QowBp0oDLQXdd4x_GwiywA">>}, - {<<"ip">>, <<"98.20.31.81">>}, - {<<"la">>, <<"en">>}, - {<<"pg">>, <<"New8.undertonebrandsafe.com/" - "698a2525065ee260c0b2f2aaad89ab82">>}, - {<<"re">>, <<>>}, - {<<"sz">>, <<"1">>}, - {<<"fc">>, <<"1">>}, - {<<"fr">>, <<"140">>}, - {<<"br">>, <<"3">>}, - {<<"bv">>, <<"11.0.696.16">>}, - {<<"os">>, <<"3">>}, - {<<"ov">>, <<>>}, - {<<"rs">>, <<"vpl">>}, - {<<"k">>, <<"cookies|sale|browser|more|privacy|statistics|" - "activities|auction|email|free|in...">>}, - {<<"t">>, <<"112373">>}, - {<<"xt">>, <<"5|61|0">>}, - {<<"tz">>, <<"-1">>}, - {<<"ev">>, <<"x">>}, - {<<"tk">>, <<>>}, - {<<"za">>, <<"1">>}, - {<<"ortb-za">>, <<"1">>}, - {<<"zu">>, <<>>}, - {<<"zl">>, <<>>}, - {<<"ax">>, <<"U">>}, - {<<"ay">>, <<"U">>}, - {<<"ortb-pid">>, <<"536454.55">>}, - {<<"ortb-sid">>, <<"112373.8">>}, - {<<"seats">>, <<"999">>}, - {<<"ortb-xt">>, <<"IAB24">>}, - {<<"ortb-ugc">>, <<>>} -]). - --define(QS_LONGER, [ - {<<"i">>, <<"9pQNskA">>}, - {<<"v">>, <<"0ySQQd1F">>}, - {<<"ev">>, <<"12345678">>}, - {<<"t">>, <<"12345">>}, - {<<"sz">>, <<"3">>}, - {<<"ip">>, <<"67.58.236.89">>}, - {<<"la">>, <<"en">>}, - {<<"pg">>, <<"http://www.yahoo.com/page1.htm">>}, - {<<"re">>, <<"http://search.google.com">>}, - {<<"fc">>, <<"1">>}, - {<<"fr">>, <<"1">>}, - {<<"br">>, <<"2">>}, - {<<"bv">>, <<"3.0.14">>}, - {<<"os">>, <<"1">>}, - {<<"ov">>, <<"XP">>}, - {<<"k">>, <<"cars,ford">>}, - {<<"rs">>, <<"js">>}, - {<<"xt">>, <<"5|22|234">>}, - {<<"tz">>, <<"+180">>}, - {<<"tk">>, <<"key1=value1|key2=value2">>}, - {<<"zl">>, <<"4,5,6">>}, - {<<"za">>, <<"4">>}, - {<<"zu">>, <<"competitor.com">>}, - {<<"ua">>, <<"Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) " - "AppleWebKit/534.13 (KHTML, like Gecko) Chrome/9.0.597.98 " - "Safari/534.13">>}, - {<<"ortb-za">>, <<"1,6,13">>}, - {<<"ortb-pid">>, <<"521732">>}, - {<<"ortb-sid">>, <<"521732">>}, - {<<"ortb-xt">>, <<"IAB3">>}, - {<<"ortb-ugc">>, <<>>} -]). - --ifdef(TEST). -qs_test_() -> - Tests = [ - {[<<"a">>], error}, - {[{<<"a">>, <<"b">>, <<"c">>}], error}, - {[], <<>>}, - {[{<<"a">>, true}], <<"a">>}, - {[{<<"a">>, true}, {<<"b">>, true}], <<"a&b">>}, - {[{<<"a">>, <<>>}], <<"a=">>}, - {[{<<"a">>, <<"b">>}], <<"a=b">>}, - {[{<<"a">>, <<>>}, {<<"b">>, <<>>}], <<"a=&b=">>}, - {[{<<"a">>, <<"b">>}, {<<"c">>, true}, {<<"d">>, <<"e">>}], - <<"a=b&c&d=e">>}, - {[{<<"a">>, <<"b=c">>}, {<<"d">>, <<"e=f">>}, {<<"g">>, <<"h=i">>}], - <<"a=b%3Dc&d=e%3Df&g=h%3Di">>}, - {[{<<" ">>, true}], <<"+">>}, - {[{<<" ">>, <<" ">>}], <<"+=+">>}, - {[{<<"a b">>, <<"c d">>}], <<"a+b=c+d">>}, - {[{<<" a ">>, <<" b ">>}, {<<" c ">>, <<" d ">>}], - <<"+a+=+b+&+c+=+d+">>}, - {[{<<"%&=">>, <<"%&=">>}, {<<"_-.">>, <<".-_">>}], - <<"%25%26%3D=%25%26%3D&_-.=.-_">>}, - {[{<<"for">>, <<"extend/ranch">>}], <<"for=extend%2Franch">>} - ], - [{lists:flatten(io_lib:format("~p", [Vals])), fun() -> - E = try qs(Vals) of - R -> R - catch _:_ -> - error - end - end} || {Vals, E} <- Tests]. - -qs_identity_test_() -> - Tests = [ - [{<<"+">>, true}], - ?QS_SHORTER, - ?QS_SHORT, - ?QS_LONG, - ?QS_LONGER - ], - [{lists:flatten(io_lib:format("~p", [V])), fun() -> - V = parse_qs(qs(V)) - end} || V <- Tests]. --endif. - --ifdef(PERF). -horse_qs_shorter() -> - horse:repeat(20000, qs(?QS_SHORTER)). - -horse_qs_short() -> - horse:repeat(20000, qs(?QS_SHORT)). - -horse_qs_long() -> - horse:repeat(20000, qs(?QS_LONG)). - -horse_qs_longer() -> - horse:repeat(20000, qs(?QS_LONGER)). --endif. - -%% @doc Decode a percent encoded string (x-www-form-urlencoded rules). - --spec urldecode(B) -> B when B::binary(). -urldecode(B) -> - urldecode(B, <<>>). - -urldecode(<< $%, H, L, Rest/bits >>, Acc) -> - C = (unhex(H) bsl 4 bor unhex(L)), - urldecode(Rest, << Acc/bits, C >>); -urldecode(<< $+, Rest/bits >>, Acc) -> - urldecode(Rest, << Acc/bits, " " >>); -urldecode(<< C, Rest/bits >>, Acc) when C =/= $% -> - urldecode(Rest, << Acc/bits, C >>); -urldecode(<<>>, Acc) -> - Acc. - -unhex($0) -> 0; -unhex($1) -> 1; -unhex($2) -> 2; -unhex($3) -> 3; -unhex($4) -> 4; -unhex($5) -> 5; -unhex($6) -> 6; -unhex($7) -> 7; -unhex($8) -> 8; -unhex($9) -> 9; -unhex($A) -> 10; -unhex($B) -> 11; -unhex($C) -> 12; -unhex($D) -> 13; -unhex($E) -> 14; -unhex($F) -> 15; -unhex($a) -> 10; -unhex($b) -> 11; -unhex($c) -> 12; -unhex($d) -> 13; -unhex($e) -> 14; -unhex($f) -> 15. - --ifdef(TEST). -urldecode_test_() -> - Tests = [ - {<<"%20">>, <<" ">>}, - {<<"+">>, <<" ">>}, - {<<"%00">>, <<0>>}, - {<<"%fF">>, <<255>>}, - {<<"123">>, <<"123">>}, - {<<"%i5">>, error}, - {<<"%5">>, error} - ], - [{Qs, fun() -> - E = try urldecode(Qs) of - R -> R - catch _:_ -> - error - end - end} || {Qs, E} <- Tests]. - -urldecode_identity_test_() -> - Tests = [ - <<"+">>, - <<"nothingnothingnothingnothing">>, - <<"Small+fast+modular+HTTP+server">>, - <<"Small%2C+fast%2C+modular+HTTP+server.">>, - <<"%E3%83%84%E3%82%A4%E3%83%B3%E3%82%BD%E3%82%A6%E3%83" - "%AB%E3%80%9C%E8%BC%AA%E5%BB%BB%E3%81%99%E3%82%8B%E6%97%8B%E5" - "%BE%8B%E3%80%9C">> - ], - [{V, fun() -> V = urlencode(urldecode(V)) end} || V <- Tests]. --endif. - --ifdef(PERF). -horse_urldecode() -> - horse:repeat(100000, - urldecode(<<"nothingnothingnothingnothing">>) - ). - -horse_urldecode_plus() -> - horse:repeat(100000, - urldecode(<<"Small+fast+modular+HTTP+server">>) - ). - -horse_urldecode_hex() -> - horse:repeat(100000, - urldecode(<<"Small%2C%20fast%2C%20modular%20HTTP%20server.">>) - ). - -horse_urldecode_jp_hex() -> - horse:repeat(100000, - urldecode(<<"%E3%83%84%E3%82%A4%E3%83%B3%E3%82%BD%E3%82%A6%E3%83" - "%AB%E3%80%9C%E8%BC%AA%E5%BB%BB%E3%81%99%E3%82%8B%E6%97%8B%E5" - "%BE%8B%E3%80%9C">>) - ). - -horse_urldecode_mix() -> - horse:repeat(100000, - urldecode(<<"Small%2C+fast%2C+modular+HTTP+server.">>) - ). --endif. - -%% @doc Percent encode a string (x-www-form-urlencoded rules). - --spec urlencode(B) -> B when B::binary(). -urlencode(B) -> - urlencode(B, <<>>). - -urlencode(<< $\s, Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $+ >>); -urlencode(<< $-, Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $- >>); -urlencode(<< $., Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $. >>); -urlencode(<< $0, Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $0 >>); -urlencode(<< $1, Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $1 >>); -urlencode(<< $2, Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $2 >>); -urlencode(<< $3, Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $3 >>); -urlencode(<< $4, Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $4 >>); -urlencode(<< $5, Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $5 >>); -urlencode(<< $6, Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $6 >>); -urlencode(<< $7, Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $7 >>); -urlencode(<< $8, Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $8 >>); -urlencode(<< $9, Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $9 >>); -urlencode(<< $A, Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $A >>); -urlencode(<< $B, Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $B >>); -urlencode(<< $C, Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $C >>); -urlencode(<< $D, Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $D >>); -urlencode(<< $E, Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $E >>); -urlencode(<< $F, Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $F >>); -urlencode(<< $G, Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $G >>); -urlencode(<< $H, Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $H >>); -urlencode(<< $I, Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $I >>); -urlencode(<< $J, Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $J >>); -urlencode(<< $K, Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $K >>); -urlencode(<< $L, Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $L >>); -urlencode(<< $M, Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $M >>); -urlencode(<< $N, Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $N >>); -urlencode(<< $O, Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $O >>); -urlencode(<< $P, Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $P >>); -urlencode(<< $Q, Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $Q >>); -urlencode(<< $R, Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $R >>); -urlencode(<< $S, Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $S >>); -urlencode(<< $T, Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $T >>); -urlencode(<< $U, Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $U >>); -urlencode(<< $V, Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $V >>); -urlencode(<< $W, Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $W >>); -urlencode(<< $X, Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $X >>); -urlencode(<< $Y, Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $Y >>); -urlencode(<< $Z, Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $Z >>); -urlencode(<< $_, Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $_ >>); -urlencode(<< $a, Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $a >>); -urlencode(<< $b, Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $b >>); -urlencode(<< $c, Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $c >>); -urlencode(<< $d, Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $d >>); -urlencode(<< $e, Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $e >>); -urlencode(<< $f, Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $f >>); -urlencode(<< $g, Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $g >>); -urlencode(<< $h, Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $h >>); -urlencode(<< $i, Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $i >>); -urlencode(<< $j, Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $j >>); -urlencode(<< $k, Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $k >>); -urlencode(<< $l, Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $l >>); -urlencode(<< $m, Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $m >>); -urlencode(<< $n, Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $n >>); -urlencode(<< $o, Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $o >>); -urlencode(<< $p, Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $p >>); -urlencode(<< $q, Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $q >>); -urlencode(<< $r, Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $r >>); -urlencode(<< $s, Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $s >>); -urlencode(<< $t, Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $t >>); -urlencode(<< $u, Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $u >>); -urlencode(<< $v, Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $v >>); -urlencode(<< $w, Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $w >>); -urlencode(<< $x, Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $x >>); -urlencode(<< $y, Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $y >>); -urlencode(<< $z, Rest/bits >>, Acc) -> urlencode(Rest, << Acc/bits, $z >>); -urlencode(<< C, Rest/bits >>, Acc) -> - H = hex(C bsr 4), - L = hex(C band 16#0f), - urlencode(Rest, << Acc/bits, $%, H, L >>); -urlencode(<<>>, Acc) -> - Acc. - -hex( 0) -> $0; -hex( 1) -> $1; -hex( 2) -> $2; -hex( 3) -> $3; -hex( 4) -> $4; -hex( 5) -> $5; -hex( 6) -> $6; -hex( 7) -> $7; -hex( 8) -> $8; -hex( 9) -> $9; -hex(10) -> $A; -hex(11) -> $B; -hex(12) -> $C; -hex(13) -> $D; -hex(14) -> $E; -hex(15) -> $F. - --ifdef(TEST). -urlencode_test_() -> - Tests = [ - {<<255, 0>>, <<"%FF%00">>}, - {<<255, " ">>, <<"%FF+">>}, - {<<" ">>, <<"+">>}, - {<<"aBc123">>, <<"aBc123">>}, - {<<".-_">>, <<".-_">>} - ], - [{V, fun() -> E = urlencode(V) end} || {V, E} <- Tests]. - -urlencode_identity_test_() -> - Tests = [ - <<"+">>, - <<"nothingnothingnothingnothing">>, - <<"Small fast modular HTTP server">>, - <<"Small, fast, modular HTTP server.">>, - <<227,131,132,227,130,164,227,131,179,227,130,189,227, - 130,166,227,131,171,227,128,156,232,188,170,229,187,187,227, - 129,153,227,130,139,230,151,139,229,190,139,227,128,156>> - ], - [{V, fun() -> V = urldecode(urlencode(V)) end} || V <- Tests]. --endif. - --ifdef(PERF). -horse_urlencode() -> - horse:repeat(100000, - urlencode(<<"nothingnothingnothingnothing">>) - ). - -horse_urlencode_plus() -> - horse:repeat(100000, - urlencode(<<"Small fast modular HTTP server">>) - ). - -horse_urlencode_jp() -> - horse:repeat(100000, - urlencode(<<227,131,132,227,130,164,227,131,179,227,130,189,227, - 130,166,227,131,171,227,128,156,232,188,170,229,187,187,227, - 129,153,227,130,139,230,151,139,229,190,139,227,128,156>>) - ). - -horse_urlencode_mix() -> - horse:repeat(100000, - urlencode(<<"Small, fast, modular HTTP server.">>) - ). --endif. DELETED deps/cowlib/src/cow_spdy.erl Index: deps/cowlib/src/cow_spdy.erl ================================================================== --- deps/cowlib/src/cow_spdy.erl +++ /dev/null @@ -1,265 +0,0 @@ -%% Copyright (c) 2013-2014, Loïc Hoguin -%% -%% Permission to use, copy, modify, and/or distribute this software for any -%% purpose with or without fee is hereby granted, provided that the above -%% copyright notice and this permission notice appear in all copies. -%% -%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - --module(cow_spdy). - -%% Zstream. --export([deflate_init/0]). --export([inflate_init/0]). - -%% Parse. --export([split/1]). --export([parse/2]). - -%% Build. --export([data/3]). --export([syn_stream/12]). --export([syn_reply/6]). --export([rst_stream/2]). -%% @todo settings --export([ping/1]). --export([goaway/2]). -%% @todo headers -%% @todo window_update - --include("cow_spdy.hrl"). - -%% Zstream. - -deflate_init() -> - Zdef = zlib:open(), - ok = zlib:deflateInit(Zdef), - _ = zlib:deflateSetDictionary(Zdef, ?ZDICT), - Zdef. - -inflate_init() -> - Zinf = zlib:open(), - ok = zlib:inflateInit(Zinf), - Zinf. - -%% Parse. - -split(Data = << _:40, Length:24, _/bits >>) - when byte_size(Data) >= Length + 8 -> - Length2 = Length + 8, - << Frame:Length2/binary, Rest/bits >> = Data, - {true, Frame, Rest}; -split(_) -> - false. - -parse(<< 0:1, StreamID:31, 0:7, IsFinFlag:1, _:24, Data/bits >>, _) -> - {data, StreamID, from_flag(IsFinFlag), Data}; -parse(<< 1:1, 3:15, 1:16, 0:6, IsUnidirectionalFlag:1, IsFinFlag:1, - _:25, StreamID:31, _:1, AssocToStreamID:31, Priority:3, _:5, - 0:8, Rest/bits >>, Zinf) -> - case parse_headers(Rest, Zinf) of - {ok, Headers, [{<<":host">>, Host}, {<<":method">>, Method}, - {<<":path">>, Path}, {<<":scheme">>, Scheme}, - {<<":version">>, Version}]} -> - {syn_stream, StreamID, AssocToStreamID, from_flag(IsFinFlag), - from_flag(IsUnidirectionalFlag), Priority, Method, - Scheme, Host, Path, Version, Headers}; - _ -> - {error, badprotocol} - end; -parse(<< 1:1, 3:15, 2:16, 0:7, IsFinFlag:1, _:25, - StreamID:31, Rest/bits >>, Zinf) -> - case parse_headers(Rest, Zinf) of - {ok, Headers, [{<<":status">>, Status}, {<<":version">>, Version}]} -> - {syn_reply, StreamID, from_flag(IsFinFlag), - Status, Version, Headers}; - _ -> - {error, badprotocol} - end; -parse(<< 1:1, 3:15, 3:16, 0:8, _:56, StatusCode:32 >>, _) - when StatusCode =:= 0; StatusCode > 11 -> - {error, badprotocol}; -parse(<< 1:1, 3:15, 3:16, 0:8, _:25, StreamID:31, StatusCode:32 >>, _) -> - Status = case StatusCode of - 1 -> protocol_error; - 2 -> invalid_stream; - 3 -> refused_stream; - 4 -> unsupported_version; - 5 -> cancel; - 6 -> internal_error; - 7 -> flow_control_error; - 8 -> stream_in_use; - 9 -> stream_already_closed; - 10 -> invalid_credentials; - 11 -> frame_too_large - end, - {rst_stream, StreamID, Status}; -parse(<< 1:1, 3:15, 4:16, 0:7, ClearSettingsFlag:1, _:24, - NbEntries:32, Rest/bits >>, _) -> - try - Settings = [begin - Is0 = 0, - Key = case ID of - 1 -> upload_bandwidth; - 2 -> download_bandwidth; - 3 -> round_trip_time; - 4 -> max_concurrent_streams; - 5 -> current_cwnd; - 6 -> download_retrans_rate; - 7 -> initial_window_size; - 8 -> client_certificate_vector_size - end, - {Key, Value, from_flag(PersistFlag), from_flag(WasPersistedFlag)} - end || << Is0:6, WasPersistedFlag:1, PersistFlag:1, - ID:24, Value:32 >> <= Rest], - NbEntries = length(Settings), - {settings, from_flag(ClearSettingsFlag), Settings} - catch _:_ -> - {error, badprotocol} - end; -parse(<< 1:1, 3:15, 6:16, 0:8, _:24, PingID:32 >>, _) -> - {ping, PingID}; -parse(<< 1:1, 3:15, 7:16, 0:8, _:56, StatusCode:32 >>, _) - when StatusCode > 2 -> - {error, badprotocol}; -parse(<< 1:1, 3:15, 7:16, 0:8, _:25, LastGoodStreamID:31, - StatusCode:32 >>, _) -> - Status = case StatusCode of - 0 -> ok; - 1 -> protocol_error; - 2 -> internal_error - end, - {goaway, LastGoodStreamID, Status}; -parse(<< 1:1, 3:15, 8:16, 0:7, IsFinFlag:1, _:25, StreamID:31, - Rest/bits >>, Zinf) -> - case parse_headers(Rest, Zinf) of - {ok, Headers, []} -> - {headers, StreamID, from_flag(IsFinFlag), Headers}; - _ -> - {error, badprotocol} - end; -parse(<< 1:1, 3:15, 9:16, 0:8, _:57, 0:31 >>, _) -> - {error, badprotocol}; -parse(<< 1:1, 3:15, 9:16, 0:8, _:25, StreamID:31, - _:1, DeltaWindowSize:31 >>, _) -> - {window_update, StreamID, DeltaWindowSize}; -parse(_, _) -> - {error, badprotocol}. - -parse_headers(Data, Zinf) -> - [<< NbHeaders:32, Rest/bits >>] = inflate(Zinf, Data), - parse_headers(Rest, NbHeaders, [], []). - -parse_headers(<<>>, 0, Headers, SpHeaders) -> - {ok, lists:reverse(Headers), lists:sort(SpHeaders)}; -parse_headers(<<>>, _, _, _) -> - error; -parse_headers(_, 0, _, _) -> - error; -parse_headers(<< 0:32, _/bits >>, _, _, _) -> - error; -parse_headers(<< L1:32, Key:L1/binary, L2:32, Value:L2/binary, Rest/bits >>, - NbHeaders, Acc, SpAcc) -> - case Key of - << $:, _/bits >> -> - parse_headers(Rest, NbHeaders - 1, Acc, - lists:keystore(Key, 1, SpAcc, {Key, Value})); - _ -> - parse_headers(Rest, NbHeaders - 1, [{Key, Value}|Acc], SpAcc) - end. - -inflate(Zinf, Data) -> - try - zlib:inflate(Zinf, Data) - catch _:_ -> - ok = zlib:inflateSetDictionary(Zinf, ?ZDICT), - zlib:inflate(Zinf, <<>>) - end. - -from_flag(0) -> false; -from_flag(1) -> true. - -%% Build. - -data(StreamID, IsFin, Data) -> - IsFinFlag = to_flag(IsFin), - Length = iolist_size(Data), - [<< 0:1, StreamID:31, 0:7, IsFinFlag:1, Length:24 >>, Data]. - -syn_stream(Zdef, StreamID, AssocToStreamID, IsFin, IsUnidirectional, - Priority, Method, Scheme, Host, Path, Version, Headers) -> - IsFinFlag = to_flag(IsFin), - IsUnidirectionalFlag = to_flag(IsUnidirectional), - HeaderBlock = build_headers(Zdef, [ - {<<":method">>, Method}, - {<<":scheme">>, Scheme}, - {<<":host">>, Host}, - {<<":path">>, Path}, - {<<":version">>, Version} - |Headers]), - Length = 10 + iolist_size(HeaderBlock), - [<< 1:1, 3:15, 1:16, 0:6, IsUnidirectionalFlag:1, IsFinFlag:1, - Length:24, 0:1, StreamID:31, 0:1, AssocToStreamID:31, - Priority:3, 0:5, 0:8 >>, HeaderBlock]. - -syn_reply(Zdef, StreamID, IsFin, Status, Version, Headers) -> - IsFinFlag = to_flag(IsFin), - HeaderBlock = build_headers(Zdef, [ - {<<":status">>, Status}, - {<<":version">>, Version} - |Headers]), - Length = 4 + iolist_size(HeaderBlock), - [<< 1:1, 3:15, 2:16, 0:7, IsFinFlag:1, Length:24, - 0:1, StreamID:31 >>, HeaderBlock]. - -rst_stream(StreamID, Status) -> - StatusCode = case Status of - protocol_error -> 1; - invalid_stream -> 2; - refused_stream -> 3; - unsupported_version -> 4; - cancel -> 5; - internal_error -> 6; - flow_control_error -> 7; - stream_in_use -> 8; - stream_already_closed -> 9; - invalid_credentials -> 10; - frame_too_large -> 11 - end, - << 1:1, 3:15, 3:16, 0:8, 8:24, - 0:1, StreamID:31, StatusCode:32 >>. - -%% @todo settings - -ping(PingID) -> - << 1:1, 3:15, 6:16, 0:8, 4:24, PingID:32 >>. - -goaway(LastGoodStreamID, Status) -> - StatusCode = case Status of - ok -> 0; - protocol_error -> 1; - internal_error -> 2 - end, - << 1:1, 3:15, 7:16, 0:8, 8:24, - 0:1, LastGoodStreamID:31, StatusCode:32 >>. - -%% @todo headers -%% @todo window_update - -build_headers(Zdef, Headers) -> - NbHeaders = length(Headers), - Headers2 = [begin - L1 = iolist_size(Key), - L2 = iolist_size(Value), - [<< L1:32 >>, Key, << L2:32 >>, Value] - end || {Key, Value} <- Headers], - zlib:deflate(Zdef, [<< NbHeaders:32 >>, Headers2], full). - -to_flag(false) -> 0; -to_flag(true) -> 1. DELETED deps/cowlib/src/cow_spdy.hrl Index: deps/cowlib/src/cow_spdy.hrl ================================================================== --- deps/cowlib/src/cow_spdy.hrl +++ /dev/null @@ -1,181 +0,0 @@ -%% Zlib dictionary. - --define(ZDICT, << - 16#00, 16#00, 16#00, 16#07, 16#6f, 16#70, 16#74, 16#69, - 16#6f, 16#6e, 16#73, 16#00, 16#00, 16#00, 16#04, 16#68, - 16#65, 16#61, 16#64, 16#00, 16#00, 16#00, 16#04, 16#70, - 16#6f, 16#73, 16#74, 16#00, 16#00, 16#00, 16#03, 16#70, - 16#75, 16#74, 16#00, 16#00, 16#00, 16#06, 16#64, 16#65, - 16#6c, 16#65, 16#74, 16#65, 16#00, 16#00, 16#00, 16#05, - 16#74, 16#72, 16#61, 16#63, 16#65, 16#00, 16#00, 16#00, - 16#06, 16#61, 16#63, 16#63, 16#65, 16#70, 16#74, 16#00, - 16#00, 16#00, 16#0e, 16#61, 16#63, 16#63, 16#65, 16#70, - 16#74, 16#2d, 16#63, 16#68, 16#61, 16#72, 16#73, 16#65, - 16#74, 16#00, 16#00, 16#00, 16#0f, 16#61, 16#63, 16#63, - 16#65, 16#70, 16#74, 16#2d, 16#65, 16#6e, 16#63, 16#6f, - 16#64, 16#69, 16#6e, 16#67, 16#00, 16#00, 16#00, 16#0f, - 16#61, 16#63, 16#63, 16#65, 16#70, 16#74, 16#2d, 16#6c, - 16#61, 16#6e, 16#67, 16#75, 16#61, 16#67, 16#65, 16#00, - 16#00, 16#00, 16#0d, 16#61, 16#63, 16#63, 16#65, 16#70, - 16#74, 16#2d, 16#72, 16#61, 16#6e, 16#67, 16#65, 16#73, - 16#00, 16#00, 16#00, 16#03, 16#61, 16#67, 16#65, 16#00, - 16#00, 16#00, 16#05, 16#61, 16#6c, 16#6c, 16#6f, 16#77, - 16#00, 16#00, 16#00, 16#0d, 16#61, 16#75, 16#74, 16#68, - 16#6f, 16#72, 16#69, 16#7a, 16#61, 16#74, 16#69, 16#6f, - 16#6e, 16#00, 16#00, 16#00, 16#0d, 16#63, 16#61, 16#63, - 16#68, 16#65, 16#2d, 16#63, 16#6f, 16#6e, 16#74, 16#72, - 16#6f, 16#6c, 16#00, 16#00, 16#00, 16#0a, 16#63, 16#6f, - 16#6e, 16#6e, 16#65, 16#63, 16#74, 16#69, 16#6f, 16#6e, - 16#00, 16#00, 16#00, 16#0c, 16#63, 16#6f, 16#6e, 16#74, - 16#65, 16#6e, 16#74, 16#2d, 16#62, 16#61, 16#73, 16#65, - 16#00, 16#00, 16#00, 16#10, 16#63, 16#6f, 16#6e, 16#74, - 16#65, 16#6e, 16#74, 16#2d, 16#65, 16#6e, 16#63, 16#6f, - 16#64, 16#69, 16#6e, 16#67, 16#00, 16#00, 16#00, 16#10, - 16#63, 16#6f, 16#6e, 16#74, 16#65, 16#6e, 16#74, 16#2d, - 16#6c, 16#61, 16#6e, 16#67, 16#75, 16#61, 16#67, 16#65, - 16#00, 16#00, 16#00, 16#0e, 16#63, 16#6f, 16#6e, 16#74, - 16#65, 16#6e, 16#74, 16#2d, 16#6c, 16#65, 16#6e, 16#67, - 16#74, 16#68, 16#00, 16#00, 16#00, 16#10, 16#63, 16#6f, - 16#6e, 16#74, 16#65, 16#6e, 16#74, 16#2d, 16#6c, 16#6f, - 16#63, 16#61, 16#74, 16#69, 16#6f, 16#6e, 16#00, 16#00, - 16#00, 16#0b, 16#63, 16#6f, 16#6e, 16#74, 16#65, 16#6e, - 16#74, 16#2d, 16#6d, 16#64, 16#35, 16#00, 16#00, 16#00, - 16#0d, 16#63, 16#6f, 16#6e, 16#74, 16#65, 16#6e, 16#74, - 16#2d, 16#72, 16#61, 16#6e, 16#67, 16#65, 16#00, 16#00, - 16#00, 16#0c, 16#63, 16#6f, 16#6e, 16#74, 16#65, 16#6e, - 16#74, 16#2d, 16#74, 16#79, 16#70, 16#65, 16#00, 16#00, - 16#00, 16#04, 16#64, 16#61, 16#74, 16#65, 16#00, 16#00, - 16#00, 16#04, 16#65, 16#74, 16#61, 16#67, 16#00, 16#00, - 16#00, 16#06, 16#65, 16#78, 16#70, 16#65, 16#63, 16#74, - 16#00, 16#00, 16#00, 16#07, 16#65, 16#78, 16#70, 16#69, - 16#72, 16#65, 16#73, 16#00, 16#00, 16#00, 16#04, 16#66, - 16#72, 16#6f, 16#6d, 16#00, 16#00, 16#00, 16#04, 16#68, - 16#6f, 16#73, 16#74, 16#00, 16#00, 16#00, 16#08, 16#69, - 16#66, 16#2d, 16#6d, 16#61, 16#74, 16#63, 16#68, 16#00, - 16#00, 16#00, 16#11, 16#69, 16#66, 16#2d, 16#6d, 16#6f, - 16#64, 16#69, 16#66, 16#69, 16#65, 16#64, 16#2d, 16#73, - 16#69, 16#6e, 16#63, 16#65, 16#00, 16#00, 16#00, 16#0d, - 16#69, 16#66, 16#2d, 16#6e, 16#6f, 16#6e, 16#65, 16#2d, - 16#6d, 16#61, 16#74, 16#63, 16#68, 16#00, 16#00, 16#00, - 16#08, 16#69, 16#66, 16#2d, 16#72, 16#61, 16#6e, 16#67, - 16#65, 16#00, 16#00, 16#00, 16#13, 16#69, 16#66, 16#2d, - 16#75, 16#6e, 16#6d, 16#6f, 16#64, 16#69, 16#66, 16#69, - 16#65, 16#64, 16#2d, 16#73, 16#69, 16#6e, 16#63, 16#65, - 16#00, 16#00, 16#00, 16#0d, 16#6c, 16#61, 16#73, 16#74, - 16#2d, 16#6d, 16#6f, 16#64, 16#69, 16#66, 16#69, 16#65, - 16#64, 16#00, 16#00, 16#00, 16#08, 16#6c, 16#6f, 16#63, - 16#61, 16#74, 16#69, 16#6f, 16#6e, 16#00, 16#00, 16#00, - 16#0c, 16#6d, 16#61, 16#78, 16#2d, 16#66, 16#6f, 16#72, - 16#77, 16#61, 16#72, 16#64, 16#73, 16#00, 16#00, 16#00, - 16#06, 16#70, 16#72, 16#61, 16#67, 16#6d, 16#61, 16#00, - 16#00, 16#00, 16#12, 16#70, 16#72, 16#6f, 16#78, 16#79, - 16#2d, 16#61, 16#75, 16#74, 16#68, 16#65, 16#6e, 16#74, - 16#69, 16#63, 16#61, 16#74, 16#65, 16#00, 16#00, 16#00, - 16#13, 16#70, 16#72, 16#6f, 16#78, 16#79, 16#2d, 16#61, - 16#75, 16#74, 16#68, 16#6f, 16#72, 16#69, 16#7a, 16#61, - 16#74, 16#69, 16#6f, 16#6e, 16#00, 16#00, 16#00, 16#05, - 16#72, 16#61, 16#6e, 16#67, 16#65, 16#00, 16#00, 16#00, - 16#07, 16#72, 16#65, 16#66, 16#65, 16#72, 16#65, 16#72, - 16#00, 16#00, 16#00, 16#0b, 16#72, 16#65, 16#74, 16#72, - 16#79, 16#2d, 16#61, 16#66, 16#74, 16#65, 16#72, 16#00, - 16#00, 16#00, 16#06, 16#73, 16#65, 16#72, 16#76, 16#65, - 16#72, 16#00, 16#00, 16#00, 16#02, 16#74, 16#65, 16#00, - 16#00, 16#00, 16#07, 16#74, 16#72, 16#61, 16#69, 16#6c, - 16#65, 16#72, 16#00, 16#00, 16#00, 16#11, 16#74, 16#72, - 16#61, 16#6e, 16#73, 16#66, 16#65, 16#72, 16#2d, 16#65, - 16#6e, 16#63, 16#6f, 16#64, 16#69, 16#6e, 16#67, 16#00, - 16#00, 16#00, 16#07, 16#75, 16#70, 16#67, 16#72, 16#61, - 16#64, 16#65, 16#00, 16#00, 16#00, 16#0a, 16#75, 16#73, - 16#65, 16#72, 16#2d, 16#61, 16#67, 16#65, 16#6e, 16#74, - 16#00, 16#00, 16#00, 16#04, 16#76, 16#61, 16#72, 16#79, - 16#00, 16#00, 16#00, 16#03, 16#76, 16#69, 16#61, 16#00, - 16#00, 16#00, 16#07, 16#77, 16#61, 16#72, 16#6e, 16#69, - 16#6e, 16#67, 16#00, 16#00, 16#00, 16#10, 16#77, 16#77, - 16#77, 16#2d, 16#61, 16#75, 16#74, 16#68, 16#65, 16#6e, - 16#74, 16#69, 16#63, 16#61, 16#74, 16#65, 16#00, 16#00, - 16#00, 16#06, 16#6d, 16#65, 16#74, 16#68, 16#6f, 16#64, - 16#00, 16#00, 16#00, 16#03, 16#67, 16#65, 16#74, 16#00, - 16#00, 16#00, 16#06, 16#73, 16#74, 16#61, 16#74, 16#75, - 16#73, 16#00, 16#00, 16#00, 16#06, 16#32, 16#30, 16#30, - 16#20, 16#4f, 16#4b, 16#00, 16#00, 16#00, 16#07, 16#76, - 16#65, 16#72, 16#73, 16#69, 16#6f, 16#6e, 16#00, 16#00, - 16#00, 16#08, 16#48, 16#54, 16#54, 16#50, 16#2f, 16#31, - 16#2e, 16#31, 16#00, 16#00, 16#00, 16#03, 16#75, 16#72, - 16#6c, 16#00, 16#00, 16#00, 16#06, 16#70, 16#75, 16#62, - 16#6c, 16#69, 16#63, 16#00, 16#00, 16#00, 16#0a, 16#73, - 16#65, 16#74, 16#2d, 16#63, 16#6f, 16#6f, 16#6b, 16#69, - 16#65, 16#00, 16#00, 16#00, 16#0a, 16#6b, 16#65, 16#65, - 16#70, 16#2d, 16#61, 16#6c, 16#69, 16#76, 16#65, 16#00, - 16#00, 16#00, 16#06, 16#6f, 16#72, 16#69, 16#67, 16#69, - 16#6e, 16#31, 16#30, 16#30, 16#31, 16#30, 16#31, 16#32, - 16#30, 16#31, 16#32, 16#30, 16#32, 16#32, 16#30, 16#35, - 16#32, 16#30, 16#36, 16#33, 16#30, 16#30, 16#33, 16#30, - 16#32, 16#33, 16#30, 16#33, 16#33, 16#30, 16#34, 16#33, - 16#30, 16#35, 16#33, 16#30, 16#36, 16#33, 16#30, 16#37, - 16#34, 16#30, 16#32, 16#34, 16#30, 16#35, 16#34, 16#30, - 16#36, 16#34, 16#30, 16#37, 16#34, 16#30, 16#38, 16#34, - 16#30, 16#39, 16#34, 16#31, 16#30, 16#34, 16#31, 16#31, - 16#34, 16#31, 16#32, 16#34, 16#31, 16#33, 16#34, 16#31, - 16#34, 16#34, 16#31, 16#35, 16#34, 16#31, 16#36, 16#34, - 16#31, 16#37, 16#35, 16#30, 16#32, 16#35, 16#30, 16#34, - 16#35, 16#30, 16#35, 16#32, 16#30, 16#33, 16#20, 16#4e, - 16#6f, 16#6e, 16#2d, 16#41, 16#75, 16#74, 16#68, 16#6f, - 16#72, 16#69, 16#74, 16#61, 16#74, 16#69, 16#76, 16#65, - 16#20, 16#49, 16#6e, 16#66, 16#6f, 16#72, 16#6d, 16#61, - 16#74, 16#69, 16#6f, 16#6e, 16#32, 16#30, 16#34, 16#20, - 16#4e, 16#6f, 16#20, 16#43, 16#6f, 16#6e, 16#74, 16#65, - 16#6e, 16#74, 16#33, 16#30, 16#31, 16#20, 16#4d, 16#6f, - 16#76, 16#65, 16#64, 16#20, 16#50, 16#65, 16#72, 16#6d, - 16#61, 16#6e, 16#65, 16#6e, 16#74, 16#6c, 16#79, 16#34, - 16#30, 16#30, 16#20, 16#42, 16#61, 16#64, 16#20, 16#52, - 16#65, 16#71, 16#75, 16#65, 16#73, 16#74, 16#34, 16#30, - 16#31, 16#20, 16#55, 16#6e, 16#61, 16#75, 16#74, 16#68, - 16#6f, 16#72, 16#69, 16#7a, 16#65, 16#64, 16#34, 16#30, - 16#33, 16#20, 16#46, 16#6f, 16#72, 16#62, 16#69, 16#64, - 16#64, 16#65, 16#6e, 16#34, 16#30, 16#34, 16#20, 16#4e, - 16#6f, 16#74, 16#20, 16#46, 16#6f, 16#75, 16#6e, 16#64, - 16#35, 16#30, 16#30, 16#20, 16#49, 16#6e, 16#74, 16#65, - 16#72, 16#6e, 16#61, 16#6c, 16#20, 16#53, 16#65, 16#72, - 16#76, 16#65, 16#72, 16#20, 16#45, 16#72, 16#72, 16#6f, - 16#72, 16#35, 16#30, 16#31, 16#20, 16#4e, 16#6f, 16#74, - 16#20, 16#49, 16#6d, 16#70, 16#6c, 16#65, 16#6d, 16#65, - 16#6e, 16#74, 16#65, 16#64, 16#35, 16#30, 16#33, 16#20, - 16#53, 16#65, 16#72, 16#76, 16#69, 16#63, 16#65, 16#20, - 16#55, 16#6e, 16#61, 16#76, 16#61, 16#69, 16#6c, 16#61, - 16#62, 16#6c, 16#65, 16#4a, 16#61, 16#6e, 16#20, 16#46, - 16#65, 16#62, 16#20, 16#4d, 16#61, 16#72, 16#20, 16#41, - 16#70, 16#72, 16#20, 16#4d, 16#61, 16#79, 16#20, 16#4a, - 16#75, 16#6e, 16#20, 16#4a, 16#75, 16#6c, 16#20, 16#41, - 16#75, 16#67, 16#20, 16#53, 16#65, 16#70, 16#74, 16#20, - 16#4f, 16#63, 16#74, 16#20, 16#4e, 16#6f, 16#76, 16#20, - 16#44, 16#65, 16#63, 16#20, 16#30, 16#30, 16#3a, 16#30, - 16#30, 16#3a, 16#30, 16#30, 16#20, 16#4d, 16#6f, 16#6e, - 16#2c, 16#20, 16#54, 16#75, 16#65, 16#2c, 16#20, 16#57, - 16#65, 16#64, 16#2c, 16#20, 16#54, 16#68, 16#75, 16#2c, - 16#20, 16#46, 16#72, 16#69, 16#2c, 16#20, 16#53, 16#61, - 16#74, 16#2c, 16#20, 16#53, 16#75, 16#6e, 16#2c, 16#20, - 16#47, 16#4d, 16#54, 16#63, 16#68, 16#75, 16#6e, 16#6b, - 16#65, 16#64, 16#2c, 16#74, 16#65, 16#78, 16#74, 16#2f, - 16#68, 16#74, 16#6d, 16#6c, 16#2c, 16#69, 16#6d, 16#61, - 16#67, 16#65, 16#2f, 16#70, 16#6e, 16#67, 16#2c, 16#69, - 16#6d, 16#61, 16#67, 16#65, 16#2f, 16#6a, 16#70, 16#67, - 16#2c, 16#69, 16#6d, 16#61, 16#67, 16#65, 16#2f, 16#67, - 16#69, 16#66, 16#2c, 16#61, 16#70, 16#70, 16#6c, 16#69, - 16#63, 16#61, 16#74, 16#69, 16#6f, 16#6e, 16#2f, 16#78, - 16#6d, 16#6c, 16#2c, 16#61, 16#70, 16#70, 16#6c, 16#69, - 16#63, 16#61, 16#74, 16#69, 16#6f, 16#6e, 16#2f, 16#78, - 16#68, 16#74, 16#6d, 16#6c, 16#2b, 16#78, 16#6d, 16#6c, - 16#2c, 16#74, 16#65, 16#78, 16#74, 16#2f, 16#70, 16#6c, - 16#61, 16#69, 16#6e, 16#2c, 16#74, 16#65, 16#78, 16#74, - 16#2f, 16#6a, 16#61, 16#76, 16#61, 16#73, 16#63, 16#72, - 16#69, 16#70, 16#74, 16#2c, 16#70, 16#75, 16#62, 16#6c, - 16#69, 16#63, 16#70, 16#72, 16#69, 16#76, 16#61, 16#74, - 16#65, 16#6d, 16#61, 16#78, 16#2d, 16#61, 16#67, 16#65, - 16#3d, 16#67, 16#7a, 16#69, 16#70, 16#2c, 16#64, 16#65, - 16#66, 16#6c, 16#61, 16#74, 16#65, 16#2c, 16#73, 16#64, - 16#63, 16#68, 16#63, 16#68, 16#61, 16#72, 16#73, 16#65, - 16#74, 16#3d, 16#75, 16#74, 16#66, 16#2d, 16#38, 16#63, - 16#68, 16#61, 16#72, 16#73, 16#65, 16#74, 16#3d, 16#69, - 16#73, 16#6f, 16#2d, 16#38, 16#38, 16#35, 16#39, 16#2d, - 16#31, 16#2c, 16#75, 16#74, 16#66, 16#2d, 16#2c, 16#2a, - 16#2c, 16#65, 16#6e, 16#71, 16#3d, 16#30, 16#2e >>). DELETED deps/cowlib/src/cowlib.app.src Index: deps/cowlib/src/cowlib.app.src ================================================================== --- deps/cowlib/src/cowlib.app.src +++ /dev/null @@ -1,26 +0,0 @@ -%% Copyright (c) 2013-2014, Loïc Hoguin -%% -%% Permission to use, copy, modify, and/or distribute this software for any -%% purpose with or without fee is hereby granted, provided that the above -%% copyright notice and this permission notice appear in all copies. -%% -%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -{application, cowlib, [ - {description, "Support library for manipulating Web protocols."}, - {vsn, "1.0.2"}, - {id, "git"}, - {modules, []}, - {registered, []}, - {applications, [ - kernel, - stdlib, - crypto - ]} -]}. DELETED deps/plug/CHANGELOG.md Index: deps/plug/CHANGELOG.md ================================================================== --- deps/plug/CHANGELOG.md +++ /dev/null @@ -1,318 +0,0 @@ -## Changelog - -## v1.0.3 - -* Enhancements - * Raise if new lines are used in header values - -* Bug fix - * Allow mime type lookup of uppercase extensions - * Do not validate uppercase headers in production to avoid performance hits - * Prevent Plug.Parsers from clobbering existing conn.params when part of it is unfetched - -## v1.0.2 - -* Bug fix - * Ensure cookie store returns a Session ID so they can be dropped - -## v1.0.1 - -* Enhancements - * Allow configuring all options supported by the underlying transport (i.e. cowboy) - -## v1.0.0 - -* Enhancements - * Allow custom headers in `Plug.Static` - -* Bug fix - * No longer automatically assume "priv" for cert and key files for Cowboy SSL - * Raise if response has been sent more than once in test connection - * Raise when body is nil on `Plug.Conn.resp/3` - * Show more info and escape messages in `Plug.Debugger` - -## v0.14.0 - -* Enhancements - * Support `:rewrite_on` on `Plug.SSL` - * Add `Plug.Conn.merge_resp_headers/2` - -* Bug fix - * Ensure message encryptor and verifier do not error on bad data - -## v0.13.1 - -* Enhancements - * Add `conn.request_path` - * Raise if `put_session/3` is invoked when response is sent - -* Bug fixes - * Fix empty params being encoded into query string as '&' - -* Deprecations - * `Plug.Conn.full_path/2` is deprecated in favor of `conn.request_path` - * `Plug.Test.put_req_header/3` and `Plug.Test.delete_req_header/3` is deprecated in favor of similarly named functions in `Plug.Conn` - -## v0.13.0 - -* Enhancements - * Raise if a header in upcase is given - * Store timestamps in sessions ETS table and document each entry format - * Allow private options when specifying routes in `Plug.Router` - * Allow the session to be cleared and ignored when an invalid CSRF token is given - * Allow log level to be configured in `Plug.Logger` - * Generate masked CSRF tokens to avoid BREACH attacks - -* Backwards incompatible changes - * `Plug.Logger` no longer sets the request id. Use `Plug.RequestId` instead - -## v0.12.2 - -* Enhancements - * Add `Plug.HTML` - -* Bug fixes - * Do not crash on poorly encoded cookies - * Decode parameters before matching on the router - -## v0.12.1 - -* Enhancements - * Add `Plug.SSL` with redirection from HTTP and HSTS support - * Remove the need for `:encrypt` option from `Plug.Session.COOKIE`. The need for encryption can be fully specified by passing `:encrypted_salt` option. This improvement is backwards compatible. - -* Bug fixes - * Ensure we don't parse body params if they were already parsed - -## v0.12.0 - -* Enhancements - * Add `query_params` and `body_params` to keep query and body parameters apart from `params` - * Allow custom encoders when encoding query parameters - * Assert valid utf-8 on url encoded and multipart bodies - -* Bug fixes - * Use only body parameters when detecting method override - * Add Vary header when serving gzipped content in Plug.Static - -* Deprecations - * `fetch_params/2` is deprecated in favor of `fetch_query_params/2` - -## v0.11.3 - -* Bug fixes - * Ensure test adapter reuses the given connection - -* Deprecations - * The `:headers` option in `Plug.Test.conn/4` is deprecated in favor of `put_req_header/3` - -## v0.11.2 - -* Enhancements - * Add `:log_on_halt` option to `Plug.Builder` and `Plug.Router` - * Use raw files and delayed writes on upload - -* Bug fixes - * Do not read the whole request body at once - * Improve performance of url encoded params - -* Deprecations - * `Plug.Builder.compile/1` and `Plug.Builder.compile/2` are deprecated in favor of explicit `Plug.Builder.compile/3` - -## v0.11.1 - -* Enhancements - * Allow Plug mimes to be configured via application environment - * Extend JSON parser to be compatible with all json compatible content types. This includes types with suffix `+json` - * Add `Plug.Conn.clear_session/1` - -* Bug fixes - * Do not require cowboy at compile time - * Also parse request bodies on DELETE requests - -## v0.11.0 - -* Enhancements - * Add `Plug.Conn.async_assign/3` and `Plug.Conn.await_assign/3` to start and await for assigns asynchronously, mimic'ing `Task.async/1` and `Task.await/2` behaviour - * Add `Plug.Conn.WrapperError` to propagate an error with the connection for better debugging by either `Plug.Debugger` or `Plug.ErrorHandler` - * Add `Plug.Conn.update_resp_header/4` to update a response header or set its initial value if not present - -* Bug fixes - * Skip parsing of files when no filename is sent - * Fix how script_name are accumulated with multiple calls to `Plug.Router.forward/2` - -* Backwards incompatible changes - * `Plug.CSRFProtection` now uses a session to store tokens. Tokens are now generated on demand and can be accessed via `Plug.CSRFProtection.get_csrf_token/0` - -## v0.10.0 - -* Enhancements - * Add `:only` option to `Plug.Static` to avoid all requests triggering file system queries - * Add ETag management to `Plug.Static` when requests to not contain a versioned query string - * Enforce atom or string keys in `Plug.Conn.put_session/3` and friends and normalize keys to strings - -* Bug fixes - * Add UTF-8 tag to debugger templates - -* Backwards incompatible changes - * `Plug.CSRFProtection` now uses a cookie instead of session and expects a `"_csrf_token"` parameter instead of `"csrf_token"` - -## v0.9.0 - -* Enhancements - * Add `Plug.Conn.full_path/1` - * Add `Plug.CSRFProtection` that adds cross-forgery protection - * Add `Plug.ErrorHandler` that allows an error page to be sent on crashes (instead of a blank one) - * Support host option in `Plug.Router` - -* Backwards incompatible changes - * Add `Plug.Router.Utils.build_match/1` was renamed to `build_path_match/1` - -## v0.8.4 - -* Bug fixes - * Clean up `{:plug_conn, :sent}` messages from listener inbox and ensure connection works accross processes - -* Deprecations - * Deprecate `recycle/2` in favor of `recycle_cookies` in Plug.Test - -## v0.8.3 - -* Enhancements - * Use PKCS7 padding in MessageEncryptor (the same as OpenSSL) - * Add support for custom serializers in cookie session store - * Allow customization of key generation in cookie session store - * Automatically import `Plug.Conn` in Plug builder - * Render errors from Plug when using Ranch/Cowboy nicely - * Provide `Plug.Crypto.secure_compare/2` for comparing binaries - * Add `Plug.Debugger` for helpful pages whenever there is a failure during a request - -* Deprecations - * Deprecate `:accept` in favor of `:pass` in Plug.Parsers - -## v0.8.2 - -* Enhancements - * Add `Plug.Conn.Utils.media_type/1` to provide media type parsing with wildcard support - * Do not print adapter data by default when inspecting the connection - * Allow plug_status to simplify the definition of plug aware exceptions - * Allow cache headers in `Plug.Static` to be turned off - -* Bug fix - * Support dots on header parameter parsing - -## v0.8.1 - -* Enhancements - * Add a `Plug.Parsers.JSON` that expects a JSON decoder as argument - -* Bug fix - * Properly populate `params` field for test connections - * Fix `Plug.Logger` not reporting the proper path - -## v0.8.0 - -* Enhancements - * Add `fetch_session/2`, `fetch_params/2` and `fetch_cookies/2` so they can be pluggable - * Raise an error message on invalid router indentifiers - * Add `put_status/2` and support atom status codes - * Add `secret_key_base` field to the connection - -* Backwards incompatible changes - * Add `encryption_salt` and `signing_salt` to the CookieStore and derive actual keys from `secret_key_base` - -## v0.7.0 - -* Enhancements - * Support Elixir 1.0.0-rc1 - * Support haltable pipelines with `Plug.Conn.halt/2` - * Ensure both Plug.Builder and Plug.Router's `call/2` are overridable - -* Bug fix - * Properly report times in Logger - -* Backwards incompatible changes - * Remove support for Plug wrappers - -## v0.6.0 - -* Enhancements - * Add `Plug.Logger` - * Add `conn.peer` and `conn.remote_ip` - * Add `Plug.Conn.sendfile/5` - * Allow `call/2` from `Plug.Builder` to be overridable - -## v0.5.3 - -* Enhancements - * Update to Cowboy v1.0.0 - * Update mime types list - * Update to Elixir v0.15.0 - -## v0.5.2 - -* Enhancements - * Update to Elixir v0.14.3 - * Cowboy adapter now returns `{:error,:eaddrinuse}` when port is already in use - * Add `Plug.Test.recycle/2` that copies relevant data between connections for future requests - -## v0.5.1 - -* Enhancements - * Add ability to configure when `Plug.Parsers` raises `UnsupportedMediaTypeError` - * Add `Plug.Conn.Query.encode/1` - * Add `CookieStore` for session - -* Bug fixes - * Ensure plug parses content-type with CRLF as LWS - -## v0.5.0 - -* Enhancements - * Update to Elixir v0.14.0 - * Update Cowboy adapter to v0.10.0 - * Add `Plug.Conn.read_body/2` - -* Backwards incompatible changes - * `Plug.Parsers` now expect `:length` instead of `:limit` and also accept `:read_length` and `:read_timeout` - -## v0.4.4 - -* Enhancements - * Update to Elixir v0.13.3 - -## v0.4.3 - -* Enhancements - * Update to Elixir v0.13.2 - -## v0.4.2 - -* Enhancements - * Update to Elixir v0.13.1 - -## v0.4.1 - -* Enhancements - * Remove `:mime` dependency in favor of `Plug.MIME` - * Improve errors when Cowboy is not available - * First hex package release - -## v0.4.0 - -* Enhancements - * Support `before_send/1` callbacks - * Add `Plug.Static` - * Allow iodata as the body - * Do not allow response headers to be set if the response was already sent - * Add `Plug.Conn.private` to be used as storage by libraries/frameworks - * Add `get_req_header` and `get_resp_header` for fetching request and response headers - -* Backwards incompatible changes - * `Plug.Connection` was removed in favor of `Plug.Conn` - * `Plug.Conn` is now a struct - * assigns, cookies, params and sessions have been converted to maps - -## v0.3.0 - -* Definition of the Plug specification DELETED deps/plug/LICENSE Index: deps/plug/LICENSE ================================================================== --- deps/plug/LICENSE +++ /dev/null @@ -1,13 +0,0 @@ -Copyright (c) 2013 Plataformatec. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. DELETED deps/plug/README.md Index: deps/plug/README.md ================================================================== --- deps/plug/README.md +++ /dev/null @@ -1,181 +0,0 @@ -# Plug - -[![Build Status](https://travis-ci.org/elixir-lang/plug.svg?branch=master)](https://travis-ci.org/elixir-lang/plug) -[![Inline docs](http://inch-ci.org/github/elixir-lang/plug.svg?branch=master)](http://inch-ci.org/github/elixir-lang/plug) - -Plug is: - -1. A specification for composable modules between web applications -2. Connection adapters for different web servers in the Erlang VM - -[Documentation for Plug is available online](http://hexdocs.pm/plug/). - -## Hello world - -```elixir -defmodule MyPlug do - import Plug.Conn - - def init(options) do - # initialize options - - options - end - - def call(conn, _opts) do - conn - |> put_resp_content_type("text/plain") - |> send_resp(200, "Hello world") - end -end -``` - -The snippet above shows a very simple example on how to use Plug. Save that snippet to a file and run it inside the plug application with: - - $ iex -S mix - iex> c "path/to/file.ex" - [MyPlug] - iex> {:ok, _} = Plug.Adapters.Cowboy.http MyPlug, [] - {:ok, #PID<...>} - -Access "http://localhost:4000/" and we are done! - -## Installation - -You can use plug in your projects in two steps: - -1. Add plug and your webserver of choice (currently cowboy) to your `mix.exs` dependencies: - - ```elixir - def deps do - [{:cowboy, "~> 1.0.0"}, - {:plug, "~> 1.0"}] - end - ``` - -2. List both `:cowboy` and `:plug` as your application dependencies: - - ```elixir - def application do - [applications: [:cowboy, :plug]] - end - ``` - -## The Plug.Conn - -In the hello world example, we defined our first plug. What is a plug after all? - -A plug takes two shapes. It is a function that receives a connection and a set of options as arguments and returns the connection or it is a module that provides an `init/1` function to initialize options and implement the `call/2` function, receiving the connection and the initialized options, and returning the connection. - -As per the specification above, a connection is represented by the `Plug.Conn` struct: - -```elixir -%Plug.Conn{host: "www.example.com", - path_info: ["bar", "baz"], - ...} -``` - -Data can be read directly from the connection and also pattern matched on. Manipulating the connection often happens with the use of the functions defined in the `Plug.Conn` module. In our example, both `put_resp_content_type/2` and `send_resp/3` are defined in `Plug.Conn`. - -Remember that, as everything else in Elixir, **a connection is immutable**, so every manipulation returns a new copy of the connection: - -```elixir -conn = put_resp_content_type(conn, "text/plain") -conn = send_resp(conn, 200, "ok") -conn -``` - -Finally, keep in mind that a connection is a **direct interface to the underlying web server**. When you call `send_resp/3` above, it will immediately send the given status and body back to the client. This makes features like streaming a breeze to work with. - -## The Plug Router - -In practice, developers rarely write their own plugs. For example, Plug ships with a router that allows developers to quickly match on incoming requests and perform some action: - -```elixir -defmodule AppRouter do - use Plug.Router - - plug :match - plug :dispatch - - get "/hello" do - send_resp(conn, 200, "world") - end - - forward "/users", to: UsersRouter - - match _ do - send_resp(conn, 404, "oops") - end -end -``` - -The router is a plug and, not only that, it contains its own plug pipeline too. The example above says that when the router is invoked, it will invoke the `:match` plug, represented by a local `match/2` function, and then call the `:dispatch` plug which will execute the matched code. - -Plug ships with many plugs that you can add to the router plug pipeline, allowing you to plug something before a route matches or before a route is dispatched to. For example, if you want to add logging to the router, just do: - -```elixir -plug Plug.Logger -plug :match -plug :dispatch -``` - -Note `Plug.Router` compiles all of your routes into a single function and relies on the Erlang VM to optimize the underlying routes into a tree lookup, instead of a linear lookup that would instead match route-per-route. This means route lookups are extremely fast in Plug! - -This also means that a catch all `match` is recommended to be defined, as in the example above, otherwise routing fails with a function clause error (as it would in any regular Elixir function). - -Each route needs to return the connection as per the Plug specification. See `Plug.Router` docs for more information. - -## Testing plugs - -Plug ships with a `Plug.Test` module that makes testing your plugs easy. Here is how we can test the router from above (or any other plug): - -```elixir -defmodule MyPlugTest do - use ExUnit.Case, async: true - use Plug.Test - - @opts AppRouter.init([]) - - test "returns hello world" do - # Create a test connection - conn = conn(:get, "/hello") - - # Invoke the plug - conn = AppRouter.call(conn, @opts) - - # Assert the response and status - assert conn.state == :sent - assert conn.status == 200 - assert conn.resp_body == "world" - end -end -``` - -### Available Plugs - -This project aims to ship with different plugs that can be re-used across applications: - - * `Plug.CSRFProtection` - adds Cross-Site Request Forgery protection to your application. Typically required if you are using `Plug.Session`; - * `Plug.Head` - converts HEAD requests to GET requests; - * `Plug.Logger` - logs requests; - * `Plug.MethodOverride` - overrides a request method with one specified in headers; - * `Plug.Parsers` - responsible for parsing the request body given its content-type; - * `Plug.RequestId` - sets up a request ID to be used in logs; - * `Plug.Session` - handles session management and storage; - * `Plug.SSL` - enforce requests through SSL; - * `Plug.Static` - serves static files; - -You can go into more details about each of them [in our docs](http://hexdocs.pm/plug/). - -### Helper modules - -Modules that can be used after you use `Plug.Router` or `Plug.Builder` to help development: - - * `Plug.Debugger` - shows a helpful debugging page every time there is a failure in a request; - * `Plug.ErrorHandler` - allows developers to customize error pages in case of crashes instead of sending a blank one; - -## License - -Plug source code is released under Apache 2 License. -Check LICENSE file for more information. DELETED deps/plug/lib/plug.ex Index: deps/plug/lib/plug.ex ================================================================== --- deps/plug/lib/plug.ex +++ /dev/null @@ -1,68 +0,0 @@ -defmodule Plug do - @moduledoc """ - The plug specification. - - There are two kind of plugs: function plugs and module plugs. - - #### Function plugs - - A function plug is any function that receives a connection and a set of - options and returns a connection. Its type signature must be: - - (Plug.Conn.t, Plug.opts) :: Plug.Conn.t - - #### Module plugs - - A module plug is an extension of the function plug. It is a module that must - export: - - * a `call/2` function with the signature defined above - * an `init/1` function which takes a set of options and initializes it. - - The result returned by `init/1` is passed as second argument to `call/2`. Note - that `init/1` may be called during compilation and as such it must not return - pids, ports or values that are not specific to the runtime. - - The API expected by a module plug is defined as a behaviour by the - `Plug` module (this module). - - ## Examples - - Here's an example of a function plug: - - def json_header_plug(conn, opts) do - conn |> put_resp_content_type("application/json") - end - - Here's an example of a module plug: - - defmodule JSONHeaderPlug do - def init(opts) do - opts - end - - def call(conn, _opts) do - conn |> put_resp_content_type("application/json") - end - end - - ## The Plug pipeline - - The `Plug.Builder` module provides conveniences for building plug - pipelines. - """ - - @type opts :: tuple | atom | integer | float | [opts] - - use Behaviour - use Application - - defcallback init(opts) :: opts - defcallback call(Plug.Conn.t, opts) :: Plug.Conn.t - - @doc false - def start(_type, _args) do - Logger.add_translator {Plug.Adapters.Translator, :translate} - Plug.Supervisor.start_link() - end -end DELETED deps/plug/lib/plug/adapters/cowboy.ex Index: deps/plug/lib/plug/adapters/cowboy.ex ================================================================== --- deps/plug/lib/plug/adapters/cowboy.ex +++ /dev/null @@ -1,225 +0,0 @@ -defmodule Plug.Adapters.Cowboy do - @moduledoc """ - Adapter interface to the Cowboy webserver. - - ## Options - - * `:ip` - the ip to bind the server to. - Must be a tuple in the format `{x, y, z, w}`. - - * `:port` - the port to run the server. - Defaults to 4000 (http) and 4040 (https). - - * `:acceptors` - the number of acceptors for the listener. - Defaults to 100. - - * `:max_connections` - max number of connections supported. - Defaults to `:infinity`. - - * `:dispatch` - manually configure Cowboy's dispatch. - If this option is used, the given plug won't be initialized - nor dispatched to (and doing so becomes the user's responsibility). - - * `:ref` - the reference name to be used. - Defaults to `plug.HTTP` (http) and `plug.HTTPS` (https). - This is the value that needs to be given on shutdown. - - * `:compress` - Cowboy will attempt to compress the response body. - Defaults to false. - - * `:timeout` - Time in ms with no requests before Cowboy closes the connection. - Defaults to 5000ms. - - * `:protocol_options` - Specifies remaining protocol options, - see [Cowboy protocol docs](http://ninenines.eu/docs/en/cowboy/1.0/manual/cowboy_protocol/). - - All other options are given to the underlying transport. - """ - - # Made public with @doc false for testing. - @doc false - def args(scheme, plug, opts, cowboy_options) do - cowboy_options - |> Keyword.put_new(:ref, build_ref(plug, scheme)) - |> Keyword.put_new(:dispatch, cowboy_options[:dispatch] || dispatch_for(plug, opts)) - |> normalize_cowboy_options(scheme) - |> to_args() - end - - @doc """ - Run cowboy under http. - - ## Example - - # Starts a new interface - Plug.Adapters.Cowboy.http MyPlug, [], port: 80 - - # The interface above can be shutdown with - Plug.Adapters.Cowboy.shutdown MyPlug.HTTP - - """ - @spec http(module(), Keyword.t, Keyword.t) :: - {:ok, pid} | {:error, :eaddrinuse} | {:error, term} - def http(plug, opts, cowboy_options \\ []) do - run(:http, plug, opts, cowboy_options) - end - - @doc """ - Run cowboy under https. - - Besides the options described in the module documentation, - this module also accepts all options defined in [the `ssl` - erlang module] (http://www.erlang.org/doc/man/ssl.html), - like keyfile, certfile, cacertfile and others. - - The certificate files can be given as a relative path. - For such, the `:otp_app` option must also be given and - certificates will be looked from the priv directory of - the given application. - - ## Example - - # Starts a new interface - Plug.Adapters.Cowboy.https MyPlug, [], - port: 443, - password: "SECRET", - otp_app: :my_app, - keyfile: "priv/ssl/key.pem", - certfile: "priv/ssl/cert.pem" - - # The interface above can be shutdown with - Plug.Adapters.Cowboy.shutdown MyPlug.HTTPS - - """ - @spec https(module(), Keyword.t, Keyword.t) :: - {:ok, pid} | {:error, :eaddrinuse} | {:error, term} - def https(plug, opts, cowboy_options \\ []) do - Application.ensure_all_started(:ssl) - run(:https, plug, opts, cowboy_options) - end - - @doc """ - Shutdowns the given reference. - """ - def shutdown(ref) do - :cowboy.stop_listener(ref) - end - - @doc """ - Returns a child spec to be supervised by your application. - """ - def child_spec(scheme, plug, opts, cowboy_options \\ []) do - [ref, nb_acceptors, trans_opts, proto_opts] = args(scheme, plug, opts, cowboy_options) - ranch_module = case scheme do - :http -> :ranch_tcp - :https -> :ranch_ssl - end - :ranch.child_spec(ref, nb_acceptors, ranch_module, trans_opts, :cowboy_protocol, proto_opts) - end - - ## Helpers - - @http_cowboy_options [port: 4000] - @https_cowboy_options [port: 4040] - @protocol_options [:timeout, :compress] - - defp run(scheme, plug, opts, cowboy_options) do - case Application.ensure_all_started(:cowboy) do - {:ok, _} -> - :ok - {:error, {:cowboy, _}} -> - raise "could not start the cowboy application. Please ensure it is listed " <> - "as a dependency both in deps and application in your mix.exs" - end - apply(:cowboy, :"start_#{scheme}", args(scheme, plug, opts, cowboy_options)) - end - - defp normalize_cowboy_options(cowboy_options, :http) do - Keyword.merge @http_cowboy_options, cowboy_options - end - - defp normalize_cowboy_options(cowboy_options, :https) do - assert_ssl_options(cowboy_options) - cowboy_options = Keyword.merge @https_cowboy_options, cowboy_options - cowboy_options = Enum.reduce [:keyfile, :certfile, :cacertfile], cowboy_options, &normalize_ssl_file(&1, &2) - cowboy_options = Enum.reduce [:password], cowboy_options, &to_char_list(&2, &1) - cowboy_options - end - - defp to_args(all_opts) do - {initial_transport_options, opts} = Enum.partition(all_opts, &is_atom/1) - opts = Keyword.delete(opts, :otp_app) - {ref, opts} = Keyword.pop(opts, :ref) - {dispatch, opts} = Keyword.pop(opts, :dispatch) - {acceptors, opts} = Keyword.pop(opts, :acceptors, 100) - {protocol_options, opts} = Keyword.pop(opts, :protocol_options, []) - - dispatch = :cowboy_router.compile(dispatch) - {extra_options, transport_options} = Keyword.split(opts, @protocol_options) - protocol_options = [env: [dispatch: dispatch]] ++ protocol_options ++ extra_options - - [ref, acceptors, initial_transport_options ++ transport_options, protocol_options] - end - - defp build_ref(plug, scheme) do - Module.concat(plug, scheme |> to_string |> String.upcase) - end - - defp dispatch_for(plug, opts) do - opts = plug.init(opts) - [{:_, [ {:_, Plug.Adapters.Cowboy.Handler, {plug, opts}} ]}] - end - - defp normalize_ssl_file(key, cowboy_options) do - value = cowboy_options[key] - - cond do - is_nil(value) -> - cowboy_options - Path.type(value) == :absolute -> - put_ssl_file cowboy_options, key, value - true -> - put_ssl_file cowboy_options, key, Path.expand(value, otp_app(cowboy_options)) - end - end - - defp assert_ssl_options(cowboy_options) do - unless Keyword.has_key?(cowboy_options, :key) or - Keyword.has_key?(cowboy_options, :keyfile) do - fail "missing option :key/:keyfile" - end - unless Keyword.has_key?(cowboy_options, :cert) or - Keyword.has_key?(cowboy_options, :certfile) do - fail "missing option :cert/:certfile" - end - end - - defp put_ssl_file(cowboy_options, key, value) do - value = to_char_list(value) - unless File.exists?(value) do - fail "the file #{value} required by SSL's #{inspect key} does not exist" - end - Keyword.put(cowboy_options, key, value) - end - - defp otp_app(cowboy_options) do - if app = cowboy_options[:otp_app] do - Application.app_dir(app) - else - fail "to use a relative certificate with https, the :otp_app " <> - "option needs to be given to the adapter" - end - end - - defp to_char_list(cowboy_options, key) do - if value = cowboy_options[key] do - Keyword.put cowboy_options, key, to_char_list(value) - else - cowboy_options - end - end - - defp fail(message) do - raise ArgumentError, message: "could not start Cowboy adapter, " <> message - end -end DELETED deps/plug/lib/plug/adapters/cowboy/conn.ex Index: deps/plug/lib/plug/adapters/cowboy/conn.ex ================================================================== --- deps/plug/lib/plug/adapters/cowboy/conn.ex +++ /dev/null @@ -1,158 +0,0 @@ -defmodule Plug.Adapters.Cowboy.Conn do - @behaviour Plug.Conn.Adapter - @moduledoc false - - alias :cowboy_req, as: Request - - def conn(req, transport) do - {path, req} = Request.path req - {host, req} = Request.host req - {port, req} = Request.port req - {meth, req} = Request.method req - {hdrs, req} = Request.headers req - {qs, req} = Request.qs req - {peer, req} = Request.peer req - {remote_ip, _} = peer - - %Plug.Conn{ - adapter: {__MODULE__, req}, - host: host, - method: meth, - owner: self(), - path_info: split_path(path), - peer: peer, - port: port, - remote_ip: remote_ip, - query_string: qs, - req_headers: hdrs, - request_path: path, - scheme: scheme(transport) - } - end - - def send_resp(req, status, headers, body) do - {:ok, req} = Request.reply(status, headers, body, req) - {:ok, nil, req} - end - - def send_file(req, status, headers, path, offset, length) do - %File.Stat{type: :regular, size: size} = File.stat!(path) - - length = - cond do - length == :all -> size - is_integer(length) -> length - end - - body_fun = fn(socket, transport) -> transport.sendfile(socket, path, offset, length) end - - {:ok, req} = Request.reply(status, headers, Request.set_resp_body_fun(length, body_fun, req)) - {:ok, nil, req} - end - - def send_chunked(req, status, headers) do - {:ok, req} = Request.chunked_reply(status, headers, req) - {:ok, nil, req} - end - - def chunk(req, body) do - Request.chunk(body, req) - end - - def read_req_body(req, opts \\ []) do - Request.body(req, opts) - end - - def parse_req_multipart(req, opts, callback) do - # We need to remove the length from the list - # otherwise cowboy will attempt to load the - # whole length at once. - {limit, opts} = Keyword.pop(opts, :length, 8_000_000) - {:ok, limit, acc, req} = parse_multipart(Request.part(req), limit, opts, [], callback) - - params = Enum.reduce(acc, %{}, &Plug.Conn.Query.decode_pair/2) - - if limit > 0 do - {:ok, params, req} - else - {:more, params, req} - end - end - - ## Helpers - - defp scheme(:tcp), do: :http - defp scheme(:ssl), do: :https - - defp split_path(path) do - segments = :binary.split(path, "/", [:global]) - for segment <- segments, segment != "", do: segment - end - - ## Multipart - - defp parse_multipart({:ok, headers, req}, limit, opts, acc, callback) when limit >= 0 do - case callback.(headers) do - {:binary, name} -> - {:ok, limit, body, req} = - parse_multipart_body(Request.part_body(req, opts), limit, opts, "") - - Plug.Conn.Utils.validate_utf8!(body, "multipart body") - parse_multipart(Request.part(req), limit, opts, [{name, body}|acc], callback) - - {:file, name, path, %Plug.Upload{} = uploaded} -> - {:ok, file} = File.open(path, [:write, :binary, :delayed_write, :raw]) - - {:ok, limit, req} = - parse_multipart_file(Request.part_body(req, opts), limit, opts, file) - - :ok = File.close(file) - parse_multipart(Request.part(req), limit, opts, [{name, uploaded}|acc], callback) - - :skip -> - parse_multipart(Request.part(req), limit, opts, acc, callback) - end - end - - defp parse_multipart({:ok, _headers, req}, limit, _opts, acc, _callback) do - {:ok, limit, acc, req} - end - - defp parse_multipart({:done, req}, limit, _opts, acc, _callback) do - {:ok, limit, acc, req} - end - - defp parse_multipart_body({:more, tail, req}, limit, opts, body) when limit >= 0 do - parse_multipart_body(Request.part_body(req, opts), limit - byte_size(tail), opts, body <> tail) - end - - defp parse_multipart_body({:more, _tail, req}, limit, _opts, body) do - {:ok, limit, body, req} - end - - defp parse_multipart_body({:ok, tail, req}, limit, _opts, body) when limit >= byte_size(tail) do - {:ok, limit, body <> tail, req} - end - - defp parse_multipart_body({:ok, _tail, req}, limit, _opts, body) do - {:ok, limit, body, req} - end - - defp parse_multipart_file({:more, tail, req}, limit, opts, file) when limit >= 0 do - IO.binwrite(file, tail) - parse_multipart_file(Request.part_body(req, opts), limit - byte_size(tail), opts, file) - end - - defp parse_multipart_file({:more, _tail, req}, limit, _opts, _file) do - {:ok, limit, req} - end - - defp parse_multipart_file({:ok, tail, req}, limit, _opts, file) when limit >= byte_size(tail) do - IO.binwrite(file, tail) - {:ok, limit, req} - end - - defp parse_multipart_file({:ok, _tail, req}, limit, _opts, _file) do - {:ok, limit, req} - end -end DELETED deps/plug/lib/plug/adapters/cowboy/handler.ex Index: deps/plug/lib/plug/adapters/cowboy/handler.ex ================================================================== --- deps/plug/lib/plug/adapters/cowboy/handler.ex +++ /dev/null @@ -1,53 +0,0 @@ -defmodule Plug.Adapters.Cowboy.Handler do - @moduledoc false - @connection Plug.Adapters.Cowboy.Conn - @already_sent {:plug_conn, :sent} - - def init({transport, :http}, req, {plug, opts}) when transport in [:tcp, :ssl] do - {:upgrade, :protocol, __MODULE__, req, {transport, plug, opts}} - end - - def upgrade(req, env, __MODULE__, {transport, plug, opts}) do - conn = @connection.conn(req, transport) - try do - %{adapter: {@connection, req}} = - conn - |> plug.call(opts) - |> maybe_send(plug) - - {:ok, req, [{:result, :ok} | env]} - catch - :error, value -> - stack = System.stacktrace() - exception = Exception.normalize(:error, value, stack) - reason = {{exception, stack}, {plug, :call, [conn, opts]}} - terminate(reason, req, stack) - :throw, value -> - stack = System.stacktrace() - reason = {{{:nocatch, value}, stack}, {plug, :call, [conn, opts]}} - terminate(reason, req, stack) - :exit, value -> - stack = System.stacktrace() - reason = {value, {plug, :call, [conn, opts]}} - terminate(reason, req, stack) - after - receive do - @already_sent -> :ok - after - 0 -> :ok - end - end - end - - defp maybe_send(%Plug.Conn{state: :unset}, _plug), do: raise Plug.Conn.NotSentError - defp maybe_send(%Plug.Conn{state: :set} = conn, _plug), do: Plug.Conn.send_resp(conn) - defp maybe_send(%Plug.Conn{} = conn, _plug), do: conn - defp maybe_send(other, plug) do - raise "Cowboy adapter expected #{inspect plug} to return Plug.Conn but got: #{inspect other}" - end - - defp terminate(reason, req, stack) do - :cowboy_req.maybe_reply(stack, req) - exit(reason) - end -end DELETED deps/plug/lib/plug/adapters/test/conn.ex Index: deps/plug/lib/plug/adapters/test/conn.ex ================================================================== --- deps/plug/lib/plug/adapters/test/conn.ex +++ /dev/null @@ -1,141 +0,0 @@ -defmodule Plug.Adapters.Test.Conn do - @behaviour Plug.Conn.Adapter - @moduledoc false - - ## Test helpers - - def conn(conn, method, uri, body_or_params) do - maybe_flush() - - uri = URI.parse(uri) - method = method |> to_string |> String.upcase - query = uri.query || "" - owner = self() - - {body, params, req_headers} = body_or_params(body_or_params, query, conn.req_headers) - state = %{method: method, params: params, req_body: body, - chunks: nil, ref: make_ref, owner: owner} - - %Plug.Conn{conn | - adapter: {__MODULE__, state}, - host: uri.host || "www.example.com", - method: method, - owner: owner, - path_info: split_path(uri.path), - port: uri.port || 80, - peer: {{127, 0, 0, 1}, 111317}, - remote_ip: {127, 0, 0, 1}, - req_headers: req_headers, - request_path: uri.path, - query_string: query, - params: params || %Plug.Conn.Unfetched{aspect: :params}, - scheme: (uri.scheme || "http") |> String.downcase |> String.to_atom} - end - - ## Connection adapter - - def send_resp(%{method: "HEAD"} = state, status, headers, _body) do - do_send state, status, headers, "" - end - def send_resp(state, status, headers, body) do - do_send state, status, headers, IO.iodata_to_binary(body) - end - - def send_file(%{method: "HEAD"} = state, status, headers, _path, _offset, _length) do - do_send state, status, headers, "" - end - def send_file(state, status, headers, path, offset, length) do - %File.Stat{type: :regular, size: size} = File.stat!(path) - - length = - cond do - length == :all -> size - is_integer(length) -> length - end - - {:ok, data} = File.open!(path, [:read, :binary], fn device -> - :file.pread(device, offset, length) - end) - - do_send state, status, headers, data - end - - def send_chunked(state, _status, _headers), - do: {:ok, "", %{state | chunks: ""}} - def chunk(%{method: "HEAD"} = state, _body), - do: {:ok, "", state} - def chunk(%{chunks: chunks} = state, body) do - body = chunks <> IO.iodata_to_binary(body) - {:ok, body, %{state | chunks: body}} - end - - defp do_send(%{owner: owner, ref: ref} = state, status, headers, body) do - send owner, {ref, {status, headers, body}} - {:ok, body, state} - end - - def read_req_body(%{req_body: body} = state, opts \\ []) do - size = min(byte_size(body), Keyword.get(opts, :length, 8_000_000)) - data = :binary.part(body, 0, size) - rest = :binary.part(body, size, byte_size(body) - size) - tag = - case rest do - "" -> :ok - _ -> :more - end - {tag, data, %{state | req_body: rest}} - end - - def parse_req_multipart(%{params: multipart} = state, _limit, _callback) do - {:ok, multipart, %{state | params: nil}} - end - - ## Private helpers - - defp body_or_params(nil, _query, headers), - do: {"", nil, headers} - - defp body_or_params(body, _query, headers) when is_binary(body) do - {body, nil, headers} - end - - defp body_or_params(params, query, headers) when is_list(params) do - body_or_params(Enum.into(params, %{}), query, headers) - end - - defp body_or_params(params, query, headers) when is_map(params) do - headers = :lists.keystore("content-type", 1, headers, - {"content-type", "multipart/mixed; charset: utf-8"}) - params = Map.merge(Plug.Conn.Query.decode(query), stringify_params(params)) - {"", params, headers} - end - - defp stringify_params([{_, _}|_] = params), - do: Enum.into(params, %{}, &stringify_kv/1) - defp stringify_params([_|_] = params), - do: Enum.map(params, &stringify_params/1) - defp stringify_params(%{__struct__: mod} = struct) when is_atom(mod), - do: struct - defp stringify_params(%{} = params), - do: Enum.into(params, %{}, &stringify_kv/1) - defp stringify_params(other), - do: other - - defp stringify_kv({k, v}), - do: {to_string(k), stringify_params(v)} - - defp split_path(path) do - segments = :binary.split(path, "/", [:global]) - for segment <- segments, segment != "", do: segment - end - - @already_sent {:plug_conn, :sent} - - defp maybe_flush() do - receive do - @already_sent -> :ok - after - 0 -> :ok - end - end -end DELETED deps/plug/lib/plug/adapters/translator.ex Index: deps/plug/lib/plug/adapters/translator.ex ================================================================== --- deps/plug/lib/plug/adapters/translator.ex +++ /dev/null @@ -1,54 +0,0 @@ -defmodule Plug.Adapters.Translator do - @moduledoc """ - A translator module shared by adapters that ship with Plug. - - We host all translations in a single module which is added - to Logger when the :plug application starts. - """ - - ## Entry point - - @doc """ - The `translate/4` function expected by custom Logger translators. - """ - def translate(min_level, :error, :format, - {'Ranch listener' ++ _, [ref, protocol, pid, reason]}) do - {:ok, translate_ranch(min_level, ref, protocol, pid, reason)} - end - - def translate(_min_level, _level, _kind, _data) do - :none - end - - ## Ranch/Cowboy - - defp translate_ranch(min_level, _ref, :cowboy_protocol, pid, - {reason, {mod, :call, [%Plug.Conn{} = conn, _opts]}}) do - [inspect(pid), " running ", inspect(mod), " terminated\n", - conn_info(min_level, conn) | - Exception.format(:exit, reason, [])] - end - - defp translate_ranch(_min_level, ref, protocol, pid, reason) do - ["Ranch protocol ", inspect(pid), " (", inspect(protocol), - ") of listener ", inspect(ref), " terminated\n" | - Exception.format(:exit, reason, [])] - end - - ## Helpers - - defp conn_info(_min_level, conn) do - [server_info(conn), request_info(conn)] - end - - defp server_info(%Plug.Conn{host: host, port: port, scheme: scheme}) do - ["Server: ", host, ":", Integer.to_string(port), ?\s, ?(, Atom.to_string(scheme), ?), ?\n] - end - - defp request_info(%Plug.Conn{method: method, query_string: query_string} = conn) do - ["Request: ", method, ?\s, path_to_iodata(conn.request_path, query_string), ?\n] - end - - defp path_to_iodata(path, ""), do: path - defp path_to_iodata(path, qs), do: [path, ??, qs] -end DELETED deps/plug/lib/plug/builder.ex Index: deps/plug/lib/plug/builder.ex ================================================================== --- deps/plug/lib/plug/builder.ex +++ /dev/null @@ -1,271 +0,0 @@ -defmodule Plug.Builder do - @moduledoc """ - Conveniences for building plugs. - - This module can be `use`-d into a module in order to build - a plug pipeline: - - defmodule MyApp do - use Plug.Builder - - plug Plug.Logger - plug :hello, upper: true - - # A function from another module can be plugged too, provided it's - # imported into the current module first. - import AnotherModule, only: [interesting_plug: 2] - plug :interesting_plug - - def hello(conn, opts) do - body = if opts[:upper], do: "WORLD", else: "world" - send_resp(conn, 200, body) - end - end - - Multiple plugs can be defined with the `plug/2` macro, forming a pipeline. - The plugs in the pipeline will be executed in the order they've been added - through the `plug/2` macro. In the example above, `Plug.Logger` will be - called first and then the `:hello` function plug will be called on the - resulting connection. - - `Plug.Builder` also imports the `Plug.Conn` module, making functions like - `send_resp/3` available. - - ## Options - - When used, the following options are accepted by `Plug.Builder`: - - * `:log_on_halt` - accepts the level to log whenever the request is halted - - ## Plug behaviour - - Internally, `Plug.Builder` implements the `Plug` behaviour, which means both - the `init/1` and `call/2` functions are defined. - - By implementing the Plug API, `Plug.Builder` guarantees this module is a plug - and can be handed to a web server or used as part of another pipeline. - - ## Overriding the default Plug API functions - - Both the `init/1` and `call/2` functions defined by `Plug.Builder` can be - manually overridden. For example, the `init/1` function provided by - `Plug.Builder` returns the options that it receives as an argument, but its - behaviour can be customized: - - defmodule PlugWithCustomOptions do - use Plug.Builder - plug Plug.Logger - - def init(opts) do - opts - end - end - - The `call/2` function that `Plug.Builder` provides is used internally to - execute all the plugs listed using the `plug` macro, so overriding the - `call/2` function generally implies using `super` in order to still call the - plug chain: - - defmodule PlugWithCustomCall do - use Plug.Builder - plug Plug.Logger - plug Plug.Head - - def call(conn, _opts) do - super(conn, opts) # calls Plug.Logger and Plug.Head - assign(conn, :called_all_plugs, true) - end - end - - - ## Halting a plug pipeline - - A plug pipeline can be halted with `Plug.Conn.halt/1`. The builder will - prevent further plugs downstream from being invoked and return the current - connection. In the following example, the `Plug.Logger` plug never gets - called: - - defmodule PlugUsingHalt do - use Plug.Builder - - plug :stopper - plug Plug.Logger - - def stopper(conn, _opts) do - halt(conn) - end - end - """ - - @type plug :: module | atom - - @doc false - defmacro __using__(opts) do - quote do - @behaviour Plug - @plug_builder_opts unquote(opts) - - def init(opts) do - opts - end - - def call(conn, opts) do - plug_builder_call(conn, opts) - end - - defoverridable [init: 1, call: 2] - - import Plug.Conn - import Plug.Builder, only: [plug: 1, plug: 2] - - Module.register_attribute(__MODULE__, :plugs, accumulate: true) - @before_compile Plug.Builder - end - end - - @doc false - defmacro __before_compile__(env) do - plugs = Module.get_attribute(env.module, :plugs) - builder_opts = Module.get_attribute(env.module, :plug_builder_opts) - - if plugs == [] do - raise "no plugs have been defined in #{inspect env.module}" - end - - {conn, body} = Plug.Builder.compile(env, plugs, builder_opts) - - quote do - defp plug_builder_call(unquote(conn), _), do: unquote(body) - end - end - - @doc """ - A macro that stores a new plug. `opts` will be passed unchanged to the new - plug. - - This macro doesn't add any guards when adding the new plug to the pipeline; - for more information about adding plugs with guards see `compile/1`. - - ## Examples - - plug Plug.Logger # plug module - plug :foo, some_options: true # plug function - - """ - defmacro plug(plug, opts \\ []) do - quote do - @plugs {unquote(plug), unquote(opts), true} - end - end - - @doc """ - Compiles a plug pipeline. - - Each element of the plug pipeline (according to the type signature of this - function) has the form: - - {plug_name, options, guards} - - Note that this function expects a reversed pipeline (with the last plug that - has to be called coming first in the pipeline). - - The function returns a tuple with the first element being a quoted reference - to the connection and the second element being the compiled quoted pipeline. - - ## Examples - - Plug.Builder.compile(env, [ - {Plug.Logger, [], true}, # no guards, as added by the Plug.Builder.plug/2 macro - {Plug.Head, [], quote(do: a when is_binary(a))} - ], []) - - """ - @spec compile(Macro.Env.t, [{plug, Plug.opts, Macro.t}], Keyword.t) :: {Macro.t, Macro.t} - def compile(env, pipeline, builder_opts) do - conn = quote do: conn - {conn, Enum.reduce(pipeline, conn, "e_plug(init_plug(&1), &2, env, builder_opts))} - end - - # Initializes the options of a plug at compile time. - defp init_plug({plug, opts, guards}) do - case Atom.to_char_list(plug) do - 'Elixir.' ++ _ -> init_module_plug(plug, opts, guards) - _ -> init_fun_plug(plug, opts, guards) - end - end - - defp init_module_plug(plug, opts, guards) do - initialized_opts = plug.init(opts) - - if function_exported?(plug, :call, 2) do - {:module, plug, initialized_opts, guards} - else - raise ArgumentError, message: "#{inspect plug} plug must implement call/2" - end - end - - defp init_fun_plug(plug, opts, guards) do - {:function, plug, opts, guards} - end - - # `acc` is a series of nested plug calls in the form of - # plug3(plug2(plug1(conn))). `quote_plug` wraps a new plug around that series - # of calls. - defp quote_plug({plug_type, plug, opts, guards}, acc, env, builder_opts) do - call = quote_plug_call(plug_type, plug, opts) - - error_message = case plug_type do - :module -> "expected #{inspect plug}.call/2 to return a Plug.Conn" - :function -> "expected #{plug}/2 to return a Plug.Conn" - end <> ", all plugs must receive a connection (conn) and return a connection" - - quote do - case unquote(compile_guards(call, guards)) do - %Plug.Conn{halted: true} = conn -> - unquote(log_halt(plug_type, plug, env, builder_opts)) - conn - %Plug.Conn{} = conn -> - unquote(acc) - _ -> - raise unquote(error_message) - end - end - end - - defp quote_plug_call(:function, plug, opts) do - quote do: unquote(plug)(conn, unquote(Macro.escape(opts))) - end - - defp quote_plug_call(:module, plug, opts) do - quote do: unquote(plug).call(conn, unquote(Macro.escape(opts))) - end - - defp compile_guards(call, true) do - call - end - - defp compile_guards(call, guards) do - quote do - case true do - true when unquote(guards) -> unquote(call) - true -> conn - end - end - end - - defp log_halt(plug_type, plug, env, builder_opts) do - if level = builder_opts[:log_on_halt] do - message = case plug_type do - :module -> "#{inspect env.module} halted in #{inspect plug}.call/2" - :function -> "#{inspect env.module} halted in #{inspect plug}/2" - end - - quote do - require Logger - Logger.unquote(level)(unquote(message)) - end - else - nil - end - end -end DELETED deps/plug/lib/plug/conn.ex Index: deps/plug/lib/plug/conn.ex ================================================================== --- deps/plug/lib/plug/conn.ex +++ /dev/null @@ -1,969 +0,0 @@ -alias Plug.Conn.Unfetched - -defmodule Plug.Conn do - @moduledoc """ - The Plug connection. - - This module defines a `Plug.Conn` struct and the main functions - for working with Plug connections. - - Note request headers are normalized to lowercase and response - headers are expected to have lower-case keys. - - ## Request fields - - These fields contain request information: - - * `host` - the requested host as a binary, example: `"www.example.com"` - * `method` - the request method as a binary, example: `"GET"` - * `path_info` - the path split into segments, example: `["hello", "world"]` - * `script_name` - the initial portion of the URL's path that corresponds to the application - routing, as segments, example: ["sub","app"]. - * `request_path` - the requested path, example: `/trailing/and//double//slashes/` - * `port` - the requested port as an integer, example: `80` - * `peer` - the actual TCP peer that connected, example: `{{127, 0, 0, 1}, 12345}`. Often this - is not the actual IP and port of the client, but rather of a load-balancer or request-router. - * `remote_ip` - the IP of the client, example: `{151, 236, 219, 228}`. This field is meant to - be overwritten by plugs that understand e.g. the `X-Forwarded-For` header or HAProxy's PROXY - protocol. It defaults to peer's IP. - * `req_headers` - the request headers as a list, example: `[{"content-type", "text/plain"}]` - * `scheme` - the request scheme as an atom, example: `:http` - * `query_string` - the request query string as a binary, example: `"foo=bar"` - - ## Fetchable fields - - The request information in these fields is not populated until it is fetched - using the associated `fetch_` function. For example, the `cookies` field uses - `fetch_cookies/2`. - - If you access these fields before fetching them, they will be returned as - `Plug.Conn.Unfetched` structs. - - * `cookies`- the request cookies with the response cookies - * `query_params` - the request query params - * `params` - the request params. Usually populated by a plug, like `Plug.Parsers` - * `req_cookies` - the request cookies (without the response ones) - - ## Response fields - - These fields contain response information: - - * `resp_body` - the response body, by default is an empty string. It is set - to nil after the response is set, except for test connections. - * `resp_charset` - the response charset, defaults to "utf-8" - * `resp_cookies` - the response cookies with their name and options - * `resp_headers` - the response headers as a dict, by default `cache-control` - is set to `"max-age=0, private, must-revalidate"` - * `status` - the response status - - Furthermore, the `before_send` field stores callbacks that are invoked - before the connection is sent. Callbacks are invoked in the reverse order - they are registered (callbacks registered first are invoked last) in order - to reproduce a pipeline ordering. - - ## Connection fields - - * `assigns` - shared user data as a dict - * `owner` - the Elixir process that owns the connection - * `halted` - the boolean status on whether the pipeline was halted - * `secret_key_base` - a secret key used to verify and encrypt cookies. - the field must be set manually whenever one of those features are used. - This data must be kept in the connection and never used directly, always - use `Plug.Crypto.KeyGenerator.generate/3` to derive keys from it - * `state` - the connection state - - The connection state is used to track the connection lifecycle. It starts - as `:unset` but is changed to `:set` (via `Plug.Conn.resp/3`) or `:file` - (when invoked via `Plug.Conn.send_file/3`). Its final result is - `:sent` or `:chunked` depending on the response model. - - ## Private fields - - These fields are reserved for libraries/framework usage. - - * `adapter` - holds the adapter information in a tuple - * `private` - shared library data as a dict - - ## Protocols - - `Plug.Conn` implements both the Collectable and Inspect protocols - out of the box. The inspect protocol provides a nice representation - of the connection while the collectable protocol allows developers - to easily chunk data. For example: - - # Send the chunked response headers - conn = send_chunked(conn, 200) - - # Pipe the given list into a connection - # Each item is emitted as a chunk - Enum.into(~w(each chunk as a word), conn) - - """ - - @type adapter :: {module, term} - @type assigns :: %{atom => any} - @type before_send :: [(t -> t)] - @type body :: iodata | nil - @type cookies :: %{binary => binary} - @type halted :: boolean - @type headers :: [{binary, binary}] - @type host :: binary - @type int_status :: non_neg_integer | nil - @type owner :: pid - @type method :: binary - @type param :: binary | %{binary => param} | [param] - @type params :: %{binary => param} - @type peer :: {:inet.ip_address, :inet.port_number} - @type port_number :: :inet.port_number - @type query_string :: String.t - @type resp_cookies :: %{binary => %{}} - @type scheme :: :http | :https - @type secret_key_base :: binary | nil - @type segments :: [binary] - @type state :: :unset | :set | :file | :chunked | :sent - @type status :: atom | int_status - - @type t :: %__MODULE__{ - adapter: adapter, - assigns: assigns, - before_send: before_send, - body_params: params | Unfetched.t, - cookies: cookies | Unfetched.t, - host: host, - method: method, - owner: owner, - params: params | Unfetched.t, - path_info: segments, - port: :inet.port_number, - private: assigns, - query_params: params | Unfetched.t, - query_string: query_string, - peer: peer, - remote_ip: :inet.ip_address, - req_cookies: cookies | Unfetched.t, - req_headers: headers, - request_path: binary, - resp_body: body, - resp_cookies: resp_cookies, - resp_headers: headers, - scheme: scheme, - script_name: segments, - secret_key_base: secret_key_base, - state: state, - status: int_status} - - defstruct adapter: {Plug.Conn, nil}, - assigns: %{}, - before_send: [], - body_params: %Unfetched{aspect: :body_params}, - cookies: %Unfetched{aspect: :cookies}, - halted: false, - host: "www.example.com", - method: "GET", - owner: nil, - params: %Unfetched{aspect: :params}, - path_info: [], - port: 0, - private: %{}, - query_params: %Unfetched{aspect: :query_params}, - query_string: "", - peer: nil, - remote_ip: nil, - req_cookies: %Unfetched{aspect: :cookies}, - req_headers: [], - request_path: "", - resp_body: nil, - resp_cookies: %{}, - resp_headers: [{"cache-control", "max-age=0, private, must-revalidate"}], - scheme: :http, - script_name: [], - secret_key_base: nil, - state: :unset, - status: nil - - defmodule NotSentError do - defexception message: "no response was set nor sent from the connection" - - @moduledoc """ - Error raised when no response is sent in a request - """ - end - - defmodule AlreadySentError do - defexception message: "the response was already sent" - - @moduledoc """ - Error raised when trying to modify or send an already sent response - """ - end - - defmodule InvalidHeaderError do - defexception message: "header is invalid" - - @moduledoc ~S""" - Error raised when trying to send a header that errors, for example: - - * the header key contains uppercase chars - * the header value contains newlines \n - """ - end - - alias Plug.Conn - @already_sent {:plug_conn, :sent} - @unsent [:unset, :set] - - @doc """ - Assigns a value to a key in the connection - - ## Examples - - iex> conn.assigns[:hello] - nil - iex> conn = assign(conn, :hello, :world) - iex> conn.assigns[:hello] - :world - - """ - @spec assign(t, atom, term) :: t - def assign(%Conn{assigns: assigns} = conn, key, value) when is_atom(key) do - %{conn | assigns: Map.put(assigns, key, value)} - end - - @doc """ - Starts a task to assign a value to a key in the connection. - - `await_assign/2` can be used to wait for the async task to complete and - retrieve the resulting value. - - Behind the scenes, it uses `Task.async/1`. - - ## Examples - - iex> conn.assigns[:hello] - nil - iex> conn = async_assign(conn, :hello, fn -> :world end) - iex> conn.assigns[:hello] - %Task{...} - - """ - @spec async_assign(t, atom, (() -> term)) :: t - def async_assign(%Conn{} = conn, key, fun) when is_atom(key) and is_function(fun, 0) do - assign(conn, key, Task.async(fun)) - end - - @doc """ - Awaits the completion of an async assign. - - Returns a connection with the value resulting from the async assignment placed - under `key` in the `:assigns` field. - - Behind the scenes, it uses `Task.await/2`. - - ## Examples - - iex> conn.assigns[:hello] - nil - iex> conn = async_assign(conn, :hello, fn -> :world end) - iex> conn = await_assign(conn, :hello) # blocks until `conn.assigns[:hello]` is available - iex> conn.assigns[:hello] - :world - - """ - @spec await_assign(t, atom, timeout) :: t - def await_assign(%Conn{} = conn, key, timeout \\ 5000) when is_atom(key) do - task = Map.fetch!(conn.assigns, key) - assign(conn, key, Task.await(task, timeout)) - end - - @doc """ - Assigns a new **private** key and value in the connection. - - This storage is meant to be used by libraries and frameworks to avoid writing - to the user storage (the `:assigns` field). It is recommended for - libraries/frameworks to prefix the keys with the library name. - - For example, if some plug needs to store a `:hello` key, it - should do so as `:plug_hello`: - - iex> conn.private[:plug_hello] - nil - iex> conn = put_private(conn, :plug_hello, :world) - iex> conn.private[:plug_hello] - :world - - """ - @spec put_private(t, atom, term) :: t - def put_private(%Conn{private: private} = conn, key, value) when is_atom(key) do - %{conn | private: Map.put(private, key, value)} - end - - @doc """ - Stores the given status code in the connection. - - The status code can be `nil`, an integer or an atom. The list of allowed - atoms is available in `Plug.Conn.Status`. - - Raises a `Plug.Conn.AlreadySentError` if the connection has already been - `:sent`. - """ - @spec put_status(t, status) :: t - def put_status(%Conn{state: :sent}, _status), - do: raise AlreadySentError - def put_status(%Conn{} = conn, nil), - do: %{conn | status: nil} - def put_status(%Conn{} = conn, status), - do: %{conn | status: Plug.Conn.Status.code(status)} - - @doc """ - Sends a response to the client. - - It expects the connection state to be `:set`, otherwise raises an - `ArgumentError` for `:unset` connections or a `Plug.Conn.AlreadySentError` for - already `:sent` connections. - - At the end sets the connection state to `:sent`. - """ - @spec send_resp(t) :: t | no_return - def send_resp(conn) - - def send_resp(%Conn{state: :unset}) do - raise ArgumentError, message: "cannot send a response that was not set" - end - - def send_resp(%Conn{adapter: {adapter, payload}, state: :set, owner: owner} = conn) do - conn = run_before_send(conn, :set) - {:ok, body, payload} = adapter.send_resp(payload, conn.status, conn.resp_headers, conn.resp_body) - send owner, @already_sent - %{conn | adapter: {adapter, payload}, resp_body: body, state: :sent} - end - - def send_resp(%Conn{}) do - raise AlreadySentError - end - - @doc """ - Sends a file as the response body with the given `status` - and optionally starting at the given offset until the given length. - - If available, the file is sent directly over the socket using - the operating system `sendfile` operation. - - It expects a connection that has not been `:sent` yet and sets its - state to `:sent` afterwards. Otherwise raises `Plug.Conn.AlreadySentError`. - """ - @spec send_file(t, status, filename :: binary, offset ::integer, length :: integer | :all) :: t | no_return - def send_file(conn, status, file, offset \\ 0, length \\ :all) - - def send_file(%Conn{state: state}, status, _file, _offset, _length) - when not state in @unsent do - _ = Plug.Conn.Status.code(status) - raise AlreadySentError - end - - def send_file(%Conn{adapter: {adapter, payload}, owner: owner} = conn, status, file, offset, length) - when is_binary(file) do - conn = run_before_send(%{conn | status: Plug.Conn.Status.code(status), resp_body: nil}, :file) - {:ok, body, payload} = adapter.send_file(payload, conn.status, conn.resp_headers, file, offset, length) - send owner, @already_sent - %{conn | adapter: {adapter, payload}, state: :sent, resp_body: body} - end - - @doc """ - Sends the response headers as a chunked response. - - It expects a connection that has not been `:sent` yet and sets its - state to `:chunked` afterwards. Otherwise raises `Plug.Conn.AlreadySentError`. - """ - @spec send_chunked(t, status) :: t | no_return - def send_chunked(%Conn{state: state}, status) - when not state in @unsent do - _ = Plug.Conn.Status.code(status) - raise AlreadySentError - end - - def send_chunked(%Conn{adapter: {adapter, payload}, owner: owner} = conn, status) do - conn = run_before_send(%{conn | status: Plug.Conn.Status.code(status), resp_body: nil}, :chunked) - {:ok, body, payload} = adapter.send_chunked(payload, conn.status, conn.resp_headers) - send owner, @already_sent - %{conn | adapter: {adapter, payload}, resp_body: body} - end - - @doc """ - Sends a chunk as part of a chunked response. - - It expects a connection with state `:chunked` as set by - `send_chunked/2`. It returns `{:ok, conn}` in case of success, - otherwise `{:error, reason}`. - """ - @spec chunk(t, body) :: {:ok, t} | {:error, term} | no_return - def chunk(%Conn{adapter: {adapter, payload}, state: :chunked} = conn, chunk) do - case adapter.chunk(payload, chunk) do - :ok -> {:ok, conn} - {:ok, body, payload} -> {:ok, %{conn | resp_body: body, adapter: {adapter, payload}}} - {:error, _} = error -> error - end - end - - def chunk(%Conn{}, chunk) when is_binary(chunk) or is_list(chunk) do - raise ArgumentError, message: "chunk/2 expects a chunked response. Please ensure " <> - "you have called send_chunked/2 before you send a chunk" - end - - @doc """ - Sends a response with the given status and body. - - See `send_resp/1` for more information. - """ - @spec send_resp(t, status, body) :: t | no_return - def send_resp(%Conn{} = conn, status, body) do - conn |> resp(status, body) |> send_resp() - end - - @doc """ - Sets the response to the given `status` and `body`. - - It sets the connection state to `:set` (if not already `:set`) - and raises `Plug.Conn.AlreadySentError` if it was already `:sent`. - """ - @spec resp(t, status, body) :: t - def resp(%Conn{state: state}, status, _body) - when not state in @unsent do - _ = Plug.Conn.Status.code(status) - raise AlreadySentError - end - - def resp(%Conn{}, _status, nil) do - raise ArgumentError, "response body cannot be set to nil" - end - - def resp(%Conn{} = conn, status, body) - when is_binary(body) or is_list(body) do - %{conn | status: Plug.Conn.Status.code(status), resp_body: body, state: :set} - end - - @doc """ - Returns the values of the request header specified by `key`. - """ - @spec get_req_header(t, binary) :: [binary] - def get_req_header(%Conn{req_headers: headers}, key) when is_binary(key) do - for {k, v} <- headers, k == key, do: v - end - - @doc """ - Adds a new request header (`key`) if not present, otherwise replaces the - previous value of that header with `value`. - - Raises a `Plug.Conn.AlreadySentError` if the connection has already been - `:sent`. - """ - @spec put_req_header(t, binary, binary) :: t - def put_req_header(%Conn{state: :sent}, _key, _value) do - raise AlreadySentError - end - - def put_req_header(%Conn{adapter: adapter, req_headers: headers} = conn, key, value) when - is_binary(key) and is_binary(value) do - validate_header_key!(adapter, key) - %{conn | req_headers: List.keystore(headers, key, 0, {key, value})} - end - - @doc """ - Deletes a request header if present. - - Raises a `Plug.Conn.AlreadySentError` if the connection has already been - `:sent`. - """ - @spec delete_req_header(t, binary) :: t - def delete_req_header(%Conn{state: :sent}, _key) do - raise AlreadySentError - end - - def delete_req_header(%Conn{req_headers: headers} = conn, key) when - is_binary(key) do - %{conn | req_headers: List.keydelete(headers, key, 0)} - end - - @doc """ - Updates a request header if present, otherwise it sets it to an initial - value. - - Raises a `Plug.Conn.AlreadySentError` if the connection has already been - `:sent`. - """ - @spec update_req_header(t, binary, binary, (binary -> binary)) :: t - def update_req_header(%Conn{state: :sent}, _key, _initial, _fun) do - raise AlreadySentError - end - - def update_req_header(%Conn{} = conn, key, initial, fun) when - is_binary(key) and is_binary(initial) and is_function(fun, 1) do - case get_req_header(conn, key) do - [] -> put_req_header(conn, key, initial) - [current|_] -> put_req_header(conn, key, fun.(current)) - end - end - - @doc """ - Returns the values of the response header specified by `key`. - - ## Examples - - iex> conn = %{conn | resp_headers: [{"content-type", "text/plain"}]} - iex> conn |> get_resp_header("content-type") - ["text/plain"] - - """ - @spec get_resp_header(t, binary) :: [binary] - def get_resp_header(%Conn{resp_headers: headers}, key) when is_binary(key) do - for {k, v} <- headers, k == key, do: v - end - - @doc """ - Adds a new response header (`key`) if not present, otherwise replaces the - previous value of that header with `value`. - - Raises a `Plug.Conn.AlreadySentError` if the connection has already been - `:sent`. - """ - @spec put_resp_header(t, binary, binary) :: t - def put_resp_header(%Conn{state: :sent}, _key, _value) do - raise AlreadySentError - end - - def put_resp_header(%Conn{adapter: adapter, resp_headers: headers} = conn, key, value) when - is_binary(key) and is_binary(value) do - validate_header_key!(adapter, key) - validate_header_value!(value) - %{conn | resp_headers: List.keystore(headers, key, 0, {key, value})} - end - - @doc """ - Merges a series of response headers into the connection. - """ - @spec merge_resp_headers(t, Enum.t) :: t - def merge_resp_headers(%Conn{state: :sent}, _headers) do - raise AlreadySentError - end - - def merge_resp_headers(conn, headers) when headers == %{} do - conn - end - - def merge_resp_headers(%Conn{resp_headers: current} = conn, headers) do - headers = - Enum.reduce headers, current, fn - {key, value}, acc when is_binary(key) and is_binary(value) -> - List.keystore(acc, key, 0, {key, value}) - end - %{conn | resp_headers: headers} - end - - @doc """ - Deletes a response header if present. - - Raises a `Plug.Conn.AlreadySentError` if the connection has already been - `:sent`. - """ - @spec delete_resp_header(t, binary) :: t - def delete_resp_header(%Conn{state: :sent}, _key) do - raise AlreadySentError - end - - def delete_resp_header(%Conn{resp_headers: headers} = conn, key) when - is_binary(key) do - %{conn | resp_headers: List.keydelete(headers, key, 0)} - end - - @doc """ - Updates a response header if present, otherwise it sets it to an initial - value. - - Raises a `Plug.Conn.AlreadySentError` if the connection has already been - `:sent`. - """ - @spec update_resp_header(t, binary, binary, (binary -> binary)) :: t - def update_resp_header(%Conn{state: :sent}, _key, _initial, _fun) do - raise AlreadySentError - end - - def update_resp_header(%Conn{} = conn, key, initial, fun) when - is_binary(key) and is_binary(initial) and is_function(fun, 1) do - case get_resp_header(conn, key) do - [] -> put_resp_header(conn, key, initial) - [current|_] -> put_resp_header(conn, key, fun.(current)) - end - end - - @doc """ - Sets the value of the `"content-type"` response header taking into account the - `charset`. - """ - @spec put_resp_content_type(t, binary, binary | nil) :: t - def put_resp_content_type(conn, content_type, charset \\ "utf-8") - - def put_resp_content_type(conn, content_type, nil) when is_binary(content_type) do - conn |> put_resp_header("content-type", content_type) - end - - def put_resp_content_type(conn, content_type, charset) when - is_binary(content_type) and is_binary(charset) do - conn |> put_resp_header("content-type", "#{content_type}; charset=#{charset}") - end - - @doc """ - Fetches query parameters from the query string. - - This function does not fetch parameters from the body. To fetch - parameters from the body, use the `Plug.Parsers` plug. - """ - @spec fetch_query_params(t, Keyword.t) :: t - def fetch_query_params(conn, opts \\ []) - - def fetch_query_params(%Conn{query_params: %Unfetched{}, params: params, - query_string: query_string} = conn, _opts) do - Plug.Conn.Utils.validate_utf8!(query_string, "query string") - query_params = Plug.Conn.Query.decode(query_string) - - case params do - %Unfetched{} -> %{conn | query_params: query_params, params: query_params} - %{} -> %{conn | query_params: query_params, params: Map.merge(query_params, params)} - end - end - - def fetch_query_params(%Conn{} = conn, _opts) do - conn - end - - @doc """ - Reads the request body. - - This function reads a chunk of the request body up to a given `:length`. If - there is more data to be read, then `{:more, partial_body, conn}` is - returned. Otherwise `{:ok, body, conn}` is returned. In case of an error - reading the socket, `{:error, reason}` is returned as per `:gen_tcp.recv/2`. - - In order to, for instance, support slower clients you can tune the - `:read_length` and `:read_timeout` options. These specify how much time should - be allowed to pass for each read from the underlying socket. - - Because the request body can be of any size, reading the body will only - work once, as Plug will not cache the result of these operations. If you - need to access the body multiple times, it is your responsibility to store - it. Finally keep in mind some plugs like `Plug.Parsers` may read the body, - so the body may be unavailable after accessing such plugs. - - This function is able to handle both chunked and identity transfer-encoding - by default. - - ## Options - - * `:length` - sets the maximum number of bytes to read from the body for each - chunk, defaults to 8_000_000 bytes - * `:read_length` - sets the amount of bytes to read at one time from the - underlying socket to fill the chunk, defaults to 1_000_000 bytes - * `:read_timeout` - sets the timeout for each socket read, defaults to - 15_000 ms - - The values above are not meant to be exact. For example, setting the - length to 8_000_000 may end-up reading some hundred bytes more from - the socket until we halt. - - ## Examples - - {:ok, body, conn} = Plug.Conn.read_body(conn, length: 1_000_000) - - """ - @spec read_body(t, Keyword.t) :: {:ok, binary, t} | - {:more, binary, t} | - {:error, term} - def read_body(%Conn{adapter: {adapter, state}} = conn, opts \\ []) do - case adapter.read_req_body(state, opts) do - {:ok, data, state} -> - {:ok, data, %{conn | adapter: {adapter, state}}} - {:more, data, state} -> - {:more, data, %{conn | adapter: {adapter, state}}} - {:error, reason} -> - {:error, reason} - end - end - - @doc """ - Fetches cookies from the request headers. - """ - @spec fetch_cookies(t, Keyword.t) :: t - def fetch_cookies(conn, opts \\ []) - - def fetch_cookies(%Conn{req_cookies: %Unfetched{}, - resp_cookies: resp_cookies, - req_headers: req_headers} = conn, _opts) do - req_cookies = - for {"cookie", cookie} <- req_headers, - kv <- Plug.Conn.Cookies.decode(cookie), - into: %{}, - do: kv - - cookies = Enum.reduce(resp_cookies, req_cookies, fn - {key, opts}, acc -> - if value = Map.get(opts, :value) do - Map.put(acc, key, value) - else - Map.delete(acc, key) - end - end) - - %{conn | req_cookies: req_cookies, cookies: cookies} - end - - def fetch_cookies(%Conn{} = conn, _opts) do - conn - end - - @doc """ - Puts a response cookie. - - ## Options - - * `:domain` - the domain the cookie applies to - * `:max_age` - the cookie max-age - * `:path` - the path the cookie applies to - * `:http_only` - when false, the cookie is accessible beyond http - * `:secure` - if the cookie must be sent only over https. Defaults - to true when the connection is https - - """ - @spec put_resp_cookie(t, binary, binary, Keyword.t) :: t - def put_resp_cookie(%Conn{resp_cookies: resp_cookies, scheme: scheme} = conn, key, value, opts \\ []) when - is_binary(key) and is_binary(value) and is_list(opts) do - cookie = [{:value, value}|opts] |> :maps.from_list() |> maybe_secure_cookie(scheme) - resp_cookies = Map.put(resp_cookies, key, cookie) - %{conn | resp_cookies: resp_cookies} |> update_cookies(&Map.put(&1, key, value)) - end - - defp maybe_secure_cookie(cookie, :https), do: Map.put_new(cookie, :secure, true) - defp maybe_secure_cookie(cookie, _), do: cookie - - @epoch {{1970, 1, 1}, {0, 0, 0}} - - @doc """ - Deletes a response cookie. - - Deleting a cookie requires the same options as to when the cookie was put. - Check `put_resp_cookie/4` for more information. - """ - @spec delete_resp_cookie(t, binary, Keyword.t) :: t - def delete_resp_cookie(%Conn{resp_cookies: resp_cookies} = conn, key, opts \\ []) when - is_binary(key) and is_list(opts) do - opts = [universal_time: @epoch, max_age: 0] ++ opts - resp_cookies = Map.put(resp_cookies, key, :maps.from_list(opts)) - %{conn | resp_cookies: resp_cookies} |> update_cookies(&Map.delete(&1, key)) - end - - @doc """ - Fetches the session from the session store. Will also fetch cookies. - """ - @spec fetch_session(t, Keyword.t) :: t - def fetch_session(conn, opts \\ []) - - def fetch_session(%Conn{private: private} = conn, _opts) do - case Map.fetch(private, :plug_session_fetch) do - {:ok, :done} -> conn - {:ok, fun} -> conn |> fetch_cookies |> fun.() - :error -> raise ArgumentError, "cannot fetch session without a configured session plug" - end - end - - @doc """ - Puts the specified `value` in the session for the given `key`. - - The key can be a string or an atom, where atoms are - automatically converted to strings. Can only be invoked - on unsent `conn`s. Will raise otherwise. - """ - @spec put_session(t, String.t | atom, any) :: t - def put_session(%Conn{state: state}, _key, _value) when not state in @unsent, - do: raise AlreadySentError - def put_session(conn, key, value) do - put_session(conn, &Map.put(&1, session_key(key), value)) - end - - @doc """ - Returns session value for the given `key`. - - The key can be a string or an atom, where atoms are - automatically converted to strings. - """ - @spec get_session(t, String.t | atom) :: any - def get_session(conn, key) do - conn |> get_session |> Map.get(session_key(key)) - end - - @doc """ - Deletes the session for the given `key`. - - The key can be a string or an atom, where atoms are - automatically converted to strings. - """ - @spec delete_session(t, String.t | atom) :: t - def delete_session(%Conn{state: state}, _key) when not state in @unsent, - do: raise AlreadySentError - def delete_session(conn, key) do - put_session(conn, &Map.delete(&1, session_key(key))) - end - - @doc """ - Clears the entire session. - - This function removes every key from the session, clearing the session. - - Note that, even if `clear_session/1` is used, the session is still sent to the - client. If the session should be effectively *dropped*, `configure_session/2` - should be used with the `:drop` option set to `true`. - """ - @spec clear_session(t) :: t - def clear_session(conn) do - put_session(conn, fn(_existing) -> Map.new end) - end - - @doc """ - Configures the session. - - ## Options - - * `:renew` - generates a new session id for the cookie - * `:drop` - drops the session, a session cookie will not be included in the - response - * `:ignore` - ignores all changes made to the session in this request cycle - - """ - @spec configure_session(t, Keyword.t) :: t - def configure_session(%Conn{state: state}, _opts) when not state in @unsent, - do: raise AlreadySentError - def configure_session(conn, opts) do - # Ensure the session is available. - _ = get_session(conn) - - cond do - opts[:renew] -> put_private(conn, :plug_session_info, :renew) - opts[:drop] -> put_private(conn, :plug_session_info, :drop) - opts[:ignore] -> put_private(conn, :plug_session_info, :ignore) - true -> conn - end - end - - @doc """ - Registers a callback to be invoked before the response is sent. - - Callbacks are invoked in the reverse order they are defined (callbacks - defined first are invoked last). - """ - @spec register_before_send(t, (t -> t)) :: t - def register_before_send(%Conn{state: state}, _callback) - when not state in @unsent do - raise AlreadySentError - end - - def register_before_send(%Conn{before_send: before_send} = conn, callback) - when is_function(callback, 1) do - %{conn | before_send: [callback|before_send]} - end - - @doc """ - Halts the Plug pipeline by preventing further plugs downstream from being - invoked. See the docs for `Plug.Builder` for more information on halting a - plug pipeline. - """ - @spec halt(t) :: t - def halt(%Conn{} = conn) do - %{conn | halted: true} - end - - ## Helpers - - defp run_before_send(%Conn{before_send: before_send} = conn, new) do - conn = Enum.reduce before_send, %{conn | state: new}, &(&1.(&2)) - if conn.state != new do - raise ArgumentError, message: "cannot send/change response from run_before_send callback" - end - %{conn | resp_headers: merge_headers(conn.resp_headers, conn.resp_cookies)} - end - - defp merge_headers(headers, cookies) do - Enum.reduce(cookies, headers, fn {key, opts}, acc -> - [{"set-cookie", Plug.Conn.Cookies.encode(key, opts)}|acc] - end) - end - - defp update_cookies(%Conn{state: :sent}, _fun), - do: raise AlreadySentError - defp update_cookies(%Conn{cookies: %Unfetched{}} = conn, _fun), - do: conn - defp update_cookies(%Conn{cookies: cookies} = conn, fun), - do: %{conn | cookies: fun.(cookies)} - - defp session_key(binary) when is_binary(binary), do: binary - defp session_key(atom) when is_atom(atom), do: Atom.to_string(atom) - - defp get_session(%Conn{private: private}) do - if session = Map.get(private, :plug_session) do - session - else - raise ArgumentError, message: "session not fetched, call fetch_session/2" - end - end - - defp put_session(conn, fun) do - private = conn.private - |> Map.put(:plug_session, get_session(conn) |> fun.()) - |> Map.put_new(:plug_session_info, :write) - - %{conn | private: private} - end - - defp validate_header_key!({Plug.Adapters.Test.Conn, _}, key) do - unless valid_header_key?(key) do - raise InvalidHeaderError, message: "header key is not lowercase: " <> inspect(key) - end - end - - defp validate_header_key!(_adapter, _key) do - :ok - end - - # Any string containing an UPPERCASE char is not valid. - defp valid_header_key?(<>) when h in ?A..?Z, do: false - defp valid_header_key?(<<_, t::binary>>), do: valid_header_key?(t) - defp valid_header_key?(<<>>), do: true - defp valid_header_key?(_), do: false - - defp validate_header_value!(value) do - case :binary.match(value, "\n") do - {_, _} -> raise InvalidHeaderError, message: "header value contains newline (\\n): " <> inspect(value) - :nomatch -> :ok - end - end -end - -defimpl Inspect, for: Plug.Conn do - def inspect(conn, opts) do - conn = - if opts.limit == :infinity do - conn - else - update_in conn.adapter, fn {adapter, _data} -> {adapter, :...} end - end - - Inspect.Any.inspect(conn, opts) - end -end - -defimpl Collectable, for: Plug.Conn do - def into(conn) do - {conn, fn - conn, {:cont, x} -> - {:ok, conn} = Plug.Conn.chunk(conn, x) - conn - conn, _ -> - conn - end} - end -end DELETED deps/plug/lib/plug/conn/adapter.ex Index: deps/plug/lib/plug/conn/adapter.ex ================================================================== --- deps/plug/lib/plug/conn/adapter.ex +++ /dev/null @@ -1,99 +0,0 @@ -defmodule Plug.Conn.Adapter do - @moduledoc """ - Specification of the connection adapter API implemented by webservers - """ - use Behaviour - - alias Plug.Conn - @typep payload :: term - - @doc """ - Sends the given status, headers and body as a response - back to the client. - - If the request has method `"HEAD"`, the adapter should - not send the response to the client. - - Webservers are advised to return `nil` as the sent_body, - as the body can no longer be manipulated. However, the - test implementation returns the actual body so it can - be used during testing. - """ - defcallback send_resp(payload, Conn.status, Conn.headers, Conn.body) :: - {:ok, sent_body :: binary | nil, payload} - - @doc """ - Sends the given status, headers and file as a response - back to the client. - - If the request has method `"HEAD"`, the adapter should - not send the response to the client. - - Webservers are advised to return `nil` as the sent_body, - as the body can no longer be manipulated. However, the - test implementation returns the actual body so it can - be used during testing. - """ - defcallback send_file(payload, Conn.status, Conn.headers, file :: binary, - offset :: integer, length :: integer | :all) :: - {:ok, sent_body :: binary | nil, payload} - - @doc """ - Sends the given status, headers as the beginning of - a chunked response to the client. - - Webservers are advised to return `nil` as the sent_body, - as the body can no longer be manipulated. However, the - test implementation returns the actual body so it can - be used during testing. - """ - defcallback send_chunked(payload, Conn.status, Conn.headers) :: - {:ok, sent_body :: binary | nil, payload} - - @doc """ - Sends a chunk in the chunked response. - - If the request has method `"HEAD"`, the adapter should - not send the response to the client. - - Webservers are advised to return `:ok` and not modify - any further state for each chunk. However, the test - implementation returns the actual body and payload so - it can be used during testing. - """ - defcallback chunk(payload, Conn.status) :: - :ok | {:ok, sent_body :: binary, payload} | {:error, term} - - @doc """ - Reads the request body. - - Read the docs in `Plug.Conn.read_body/2` for the supported - options and expected behaviour. - """ - defcallback read_req_body(payload, options :: Keyword.t) :: - {:ok, data :: binary, payload} | - {:more, data :: binary, payload} | - {:error, term} - - @doc """ - Parses a multipart request. - - This function receives the payload, the body limit and a callback. - When parsing each multipart segment, the parser should invoke the - given fallback passing the headers for that segment, before consuming - the body. The callback will return one of the following values: - - * `{:binary, name}` - the current segment must be treated as a regular - binary value with the given `name` - * `{:file, name, file, upload} - the current segment is a file upload with `name` - and contents should be written to the given `file` - * `:skip` - this multipart segment should be skipped - - This function may return a `:ok` or `:more` tuple. The first one is - returned when there is no more multipart data to be processed. - - For the supported options, please read `Plug.Conn.read_body/2` docs. - """ - defcallback parse_req_multipart(payload, options :: Keyword.t, fun) :: - {:ok, Conn.params, payload} | {:more, Conn.params, payload} -end DELETED deps/plug/lib/plug/conn/cookies.ex Index: deps/plug/lib/plug/conn/cookies.ex ================================================================== --- deps/plug/lib/plug/conn/cookies.ex +++ /dev/null @@ -1,131 +0,0 @@ -defmodule Plug.Conn.Cookies do - @moduledoc """ - Conveniences for encoding and decoding cookies. - """ - - @doc """ - Decodes the given cookies as given in a request header. - - If a cookie is invalid, it is automatically discarded from the result. - - ## Examples - - iex> decode("key1=value1, key2=value2") - %{"key1" => "value1", "key2" => "value2"} - - """ - def decode(cookie) do - do_decode(:binary.split(cookie, [";", ","], [:global]), %{}) - end - - defp do_decode([], acc), - do: acc - defp do_decode([h|t], acc) do - case decode_kv(h) do - {k, v} -> do_decode(t, Map.put(acc, k, v)) - false -> do_decode(t, acc) - end - end - - defp decode_kv(""), - do: false - defp decode_kv(<< ?$, _ :: binary >>), - do: false - defp decode_kv(<< h, t :: binary >>) when h in [?\s, ?\t], - do: decode_kv(t) - defp decode_kv(kv), - do: decode_key(kv, "") - - defp decode_key("", _key), - do: false - defp decode_key(<< ?=, _ :: binary >>, ""), - do: false - defp decode_key(<< ?=, t :: binary >>, key), - do: decode_value(t, "", key, "") - defp decode_key(<< h, _ :: binary >>, _key) when h in [?\s, ?\t, ?\r, ?\n, ?\v, ?\f], - do: false - defp decode_key(<< h, t :: binary >>, key), - do: decode_key(t, << key :: binary, h >>) - - defp decode_value("", _spaces, key, value), - do: {key, value} - defp decode_value(<< ?\s, t :: binary >>, spaces, key, value), - do: decode_value(t, << spaces :: binary, ?\s >>, key, value) - defp decode_value(<< h, _ :: binary >>, _spaces, _key, _value) when h in [?\t, ?\r, ?\n, ?\v, ?\f], - do: false - defp decode_value(<< h, t :: binary >>, spaces, key, value), - do: decode_value(t, "", key, << value :: binary, spaces :: binary , h >>) - - @doc """ - Encodes the given cookies as expected in a response header. - """ - def encode(key, opts \\ %{}) when is_map(opts) do - value = Map.get(opts, :value) - path = Map.get(opts, :path, "/") - header = "#{key}=#{value}; path=#{path}" - - if domain = Map.get(opts, :domain) do - header = header <> "; domain=#{domain}" - end - - if max_age = Map.get(opts, :max_age) do - time = Map.get(opts, :universal_time) || :calendar.universal_time - time = add_seconds(time, max_age) - header = header <> "; expires=" <> rfc2822(time) <> "; max-age=" <> Integer.to_string(max_age) - end - - if Map.get(opts, :secure, false) do - header = header <> "; secure" - end - - if Map.get(opts, :http_only, true) do - header = header <> "; HttpOnly" - end - - header - end - - defp pad(number) when number in 0..9, do: <> - defp pad(number), do: Integer.to_string(number) - - defp rfc2822({{year, month, day} = date, {hour, minute, second}}) do - weekday_name = weekday_name(:calendar.day_of_the_week(date)) - month_name = month_name(month) - padded_day = pad(day) - padded_hour = pad(hour) - padded_minute = pad(minute) - padded_second = pad(second) - binary_year = Integer.to_string(year) - - weekday_name <> ", " <> padded_day <> - " " <> month_name <> " " <> binary_year <> - " " <> padded_hour <> ":" <> padded_minute <> - ":" <> padded_second <> " GMT" - end - - defp weekday_name(1), do: "Mon" - defp weekday_name(2), do: "Tue" - defp weekday_name(3), do: "Wed" - defp weekday_name(4), do: "Thu" - defp weekday_name(5), do: "Fri" - defp weekday_name(6), do: "Sat" - defp weekday_name(7), do: "Sun" - - defp month_name(1), do: "Jan" - defp month_name(2), do: "Feb" - defp month_name(3), do: "Mar" - defp month_name(4), do: "Apr" - defp month_name(5), do: "May" - defp month_name(6), do: "Jun" - defp month_name(7), do: "Jul" - defp month_name(8), do: "Aug" - defp month_name(9), do: "Sep" - defp month_name(10), do: "Oct" - defp month_name(11), do: "Nov" - defp month_name(12), do: "Dec" - - defp add_seconds(time, seconds_to_add) do - time_seconds = :calendar.datetime_to_gregorian_seconds(time) - :calendar.gregorian_seconds_to_datetime(time_seconds + seconds_to_add) - end -end DELETED deps/plug/lib/plug/conn/query.ex Index: deps/plug/lib/plug/conn/query.ex ================================================================== --- deps/plug/lib/plug/conn/query.ex +++ /dev/null @@ -1,219 +0,0 @@ -defmodule Plug.Conn.Query do - @moduledoc """ - Conveniences for decoding and encoding url encoded queries. - - Plug allows a developer to build query strings - that map to Elixir structures in order to make - manipulation of such structures easier on the server - side. Here are some examples: - - iex> decode("foo=bar")["foo"] - "bar" - - If a value is given more than once, the last value takes precedence: - - iex> decode("foo=bar&foo=baz")["foo"] - "baz" - - Nested structures can be created via `[key]`: - - iex> decode("foo[bar]=baz")["foo"]["bar"] - "baz" - - Lists are created with `[]`: - - iex> decode("foo[]=bar&foo[]=baz")["foo"] - ["bar", "baz"] - - Dicts can be encoded: - - iex> encode(%{foo: "bar", baz: "bat"}) - "baz=bat&foo=bar" - - Encoding keyword lists preserves the order of the fields: - - iex> encode([foo: "bar", baz: "bat"]) - "foo=bar&baz=bat" - - When encoding keyword lists with duplicate keys, the key that comes first - takes precedence: - - iex> encode([foo: "bar", foo: "bat"]) - "foo=bar" - - Encoding named lists: - - iex> encode(%{foo: ["bar", "baz"]}) - "foo[]=bar&foo[]=baz" - - Encoding nested structures: - - iex> encode(%{foo: %{bar: "baz"}}) - "foo[bar]=baz" - - """ - - @doc """ - Decodes the given binary. - """ - def decode(query, initial \\ %{}) - - def decode("", initial) do - initial - end - - def decode(query, initial) do - parts = :binary.split(query, "&", [:global]) - Enum.reduce(Enum.reverse(parts), initial, &decode_string_pair(&1, &2)) - end - - defp decode_string_pair(binary, acc) do - current = - case :binary.split(binary, "=") do - [key, value] -> - {URI.decode_www_form(key), URI.decode_www_form(value)} - [key] -> - {URI.decode_www_form(key), nil} - end - - decode_pair(current, acc) - end - - @doc """ - Decodes the given tuple and stores it in the accumulator. - It parses the key and stores the value into the current - accumulator. - - Parameter lists are added to the accumulator in reverse - order, so be sure to pass the parameters in reverse order. - """ - def decode_pair({key, value}, acc) do - parts = - if key != "" and :binary.last(key) == ?] do - # Remove trailing ] - subkey = :binary.part(key, 0, byte_size(key) - 1) - - # Split the first [ then split remaining ][. - # - # users[address][street #=> [ "users", "address][street" ] - # - case :binary.split(subkey, "[") do - [key, subpart] -> - [key|:binary.split(subpart, "][", [:global])] - _ -> - [key] - end - else - [key] - end - - assign_parts parts, value, acc - end - - # We always assign the value in the last segment. - # `age=17` would match here. - defp assign_parts([key], value, acc) do - Map.put_new(acc, key, value) - end - - # The current segment is a list. We simply prepend - # the item to the list or create a new one if it does - # not yet. This assumes that items are iterated in - # reverse order. - defp assign_parts([key,""|t], value, acc) do - case Map.fetch(acc, key) do - {:ok, current} when is_list(current) -> - Map.put(acc, key, assign_list(t, current, value)) - :error -> - Map.put(acc, key, assign_list(t, [], value)) - _ -> - acc - end - end - - # The current segment is a parent segment of a - # map. We need to create a map and then - # continue looping. - defp assign_parts([key|t], value, acc) do - case Map.fetch(acc, key) do - {:ok, %{} = current} -> - Map.put(acc, key, assign_parts(t, value, current)) - :error -> - Map.put(acc, key, assign_parts(t, value, %{})) - _ -> - acc - end - end - - defp assign_list(t, current, value) do - if value = assign_list(t, value), do: [value|current], else: current - end - - defp assign_list([], value), do: value - defp assign_list(t, value), do: assign_parts(t, value, %{}) - - @doc """ - Encodes the given dict. - """ - def encode(dict, encoder \\ &to_string/1) do - IO.iodata_to_binary encode_pair("", dict, encoder) - end - - # covers structs - defp encode_pair(field, %{__struct__: struct} = map, encoder) when is_atom(struct) do - [field, ?=|encode_value(map, encoder)] - end - - # covers maps - defp encode_pair(parent_field, %{} = map, encoder) do - encode_dict(map, parent_field, encoder) - end - - # covers keyword lists - defp encode_pair(parent_field, list, encoder) when is_list(list) and is_tuple(hd(list)) do - encode_dict(Enum.uniq(list, &elem(&1, 0)), parent_field, encoder) - end - - # covers non-keyword lists - defp encode_pair(parent_field, list, encoder) when is_list(list) do - prune Enum.flat_map list, fn value -> - [?&, encode_pair(parent_field <> "[]", value, encoder)] - end - end - - # covers nil - defp encode_pair(field, nil, _encoder) do - [field, ?=] - end - - # encoder fallback - defp encode_pair(field, value, encoder) do - [field, ?=|encode_value(value, encoder)] - end - - defp encode_dict(dict, parent_field, encoder) do - prune Enum.flat_map dict, fn - {_, value} when value in [%{}, []] -> - [] - {field, value} -> - field = - if parent_field == "" do - encode_key(field) - else - parent_field <> "[" <> encode_key(field) <> "]" - end - [?&, encode_pair(field, value, encoder)] - end - end - - defp encode_key(item) do - item |> to_string |> URI.encode_www_form - end - - defp encode_value(item, encoder) do - item |> encoder.() |> URI.encode_www_form - end - - defp prune([?&|t]), do: t - defp prune([]), do: [] -end DELETED deps/plug/lib/plug/conn/status.ex Index: deps/plug/lib/plug/conn/status.ex ================================================================== --- deps/plug/lib/plug/conn/status.ex +++ /dev/null @@ -1,93 +0,0 @@ -defmodule Plug.Conn.Status do - @moduledoc """ - Conveniences for working with status codes. - """ - - statuses = [ - continue: 100, - switching_protocols: 101, - processing: 102, - ok: 200, - created: 201, - accepted: 202, - non_authoritative_information: 203, - no_content: 204, - reset_content: 205, - partial_content: 206, - multi_status: 207, - already_reported: 208, - instance_manipulation_used: 226, - multiple_choices: 300, - moved_permanently: 301, - found: 302, - see_other: 303, - not_modified: 304, - use_proxy: 305, - reserved: 306, - temporary_redirect: 307, - permanent_redirect: 308, - bad_request: 400, - unauthorized: 401, - payment_required: 402, - forbidden: 403, - not_found: 404, - method_not_allowed: 405, - not_acceptable: 406, - proxy_authentication_required: 407, - request_timeout: 408, - conflict: 409, - gone: 410, - length_required: 411, - precondition_failed: 412, - request_entity_too_large: 413, - request_uri_too_long: 414, - unsupported_media_type: 415, - requested_range_not_satisfiable: 416, - expectation_failed: 417, - im_a_teapot: 418, - misdirected_request: 421, - unprocessable_entity: 422, - locked: 423, - failed_dependency: 424, - upgrade_required: 426, - precondition_required: 428, - too_many_requests: 429, - request_header_fields_too_large: 431, - internal_server_error: 500, - not_implemented: 501, - bad_gateway: 502, - service_unavailable: 503, - gateway_timeout: 504, - http_version_not_supported: 505, - variant_also_negotiates: 506, - insufficient_storage: 507, - loop_detected: 508, - not_extended: 510, - network_authentication_required: 511 - ] - - doc = Enum.map(statuses, fn {atom, code} -> - " * `#{inspect atom}` - #{code}\n" - end) - - @doc """ - Returns the status code given an integer or a known atom. - - ## Known status codes - - The following status codes can be given as atoms with their - respective value shown next: - - #{doc} - """ - @spec code(integer | atom) :: integer - def code(integer_or_atom) - - def code(integer) when integer in 100..999 do - integer - end - - for {atom, code} <- statuses do - def code(unquote(atom)), do: unquote(code) - end -end DELETED deps/plug/lib/plug/conn/unfetched.ex Index: deps/plug/lib/plug/conn/unfetched.ex ================================================================== --- deps/plug/lib/plug/conn/unfetched.ex +++ /dev/null @@ -1,25 +0,0 @@ -defmodule Plug.Conn.Unfetched do - @moduledoc """ - A struct used as default on unfetched fields. - - The `:aspect` key of the struct specifies what field is still unfetched. - - ## Examples - - unfetched = %Plug.Conn.Unfetched{aspect: :cookies} - - """ - - defstruct [:aspect] - @type t :: %__MODULE__{aspect: atom()} - - @doc false - def get(%{aspect: aspect}, key, _value) do - raise ArgumentError, "cannot get key #{inspect key} from conn.#{aspect} because they were not fetched" - end - - @doc false - def get_and_update(%{aspect: aspect}, key, _fun) do - raise ArgumentError, "cannot get_and_update key #{inspect key} from conn.#{aspect} because they were not fetched" - end -end DELETED deps/plug/lib/plug/conn/utils.ex Index: deps/plug/lib/plug/conn/utils.ex ================================================================== --- deps/plug/lib/plug/conn/utils.ex +++ /dev/null @@ -1,296 +0,0 @@ -defmodule Plug.Conn.Utils do - @moduledoc """ - Utilities for working with connection data - """ - - @type params :: [{binary, binary}] - - @upper ?A..?Z - @lower ?a..?z - @alpha ?0..?9 - @other [?., ?-, ?+] - @space [?\s, ?\t] - @specials ~c|()<>@,;:\\"/[]?={}| - - @doc ~S""" - Parses media types (with wildcards). - - Type and subtype are case insensitive while the - sensitiveness of params depends on their keys and - therefore are not handled by this parser. - - Returns: - - * `{:ok, type, subtype, map_of_params}` if everything goes fine - * `:error` if the media type isn't valid - - ## Examples - - iex> media_type "text/plain" - {:ok, "text", "plain", %{}} - - iex> media_type "APPLICATION/vnd.ms-data+XML" - {:ok, "application", "vnd.ms-data+xml", %{}} - - iex> media_type "text/*; q=1.0" - {:ok, "text", "*", %{"q" => "1.0"}} - - iex> media_type "*/*; q=1.0" - {:ok, "*", "*", %{"q" => "1.0"}} - - iex> media_type "x y" - :error - - iex> media_type "*/html" - :error - - iex> media_type "/" - :error - - iex> media_type "x/y z" - :error - - """ - @spec media_type(binary) :: {:ok, type :: binary, subtype :: binary, params} | :error - def media_type(binary) do - case strip_spaces(binary) do - "*/*" <> t -> mt_params(t, "*", "*") - t -> mt_first(t, "") - end - end - - defp mt_first(<>, acc) when acc != "", - do: mt_wildcard(t, acc) - defp mt_first(<>, acc) when h in @upper, - do: mt_first(t, <>) - defp mt_first(<>, acc) when h in @lower or h in @alpha or h == ?-, - do: mt_first(t, <>) - defp mt_first(_, _acc), - do: :error - - defp mt_wildcard(<>, first), - do: mt_params(t, first, "*") - defp mt_wildcard(t, first), - do: mt_second(t, "", first) - - defp mt_second(<>, acc, first) when h in @upper, - do: mt_second(t, <>, first) - defp mt_second(<>, acc, first) when h in @lower or h in @alpha or h in @other, - do: mt_second(t, <>, first) - defp mt_second(t, acc, first), - do: mt_params(t, first, acc) - - defp mt_params(t, first, second) do - case strip_spaces(t) do - "" -> {:ok, first, second, %{}} - ";" <> t -> {:ok, first, second, params(t)} - _ -> :error - end - end - - @doc ~S""" - Parses content type (without wildcards). - - It is similar to `media_type/1` except wildcards are - not accepted in the type nor in the subtype. - - ## Examples - - iex> content_type "x-sample/json; charset=utf-8" - {:ok, "x-sample", "json", %{"charset" => "utf-8"}} - - iex> content_type "x-sample/json ; charset=utf-8 ; foo=bar" - {:ok, "x-sample", "json", %{"charset" => "utf-8", "foo" => "bar"}} - - iex> content_type "\r\n text/plain;\r\n charset=utf-8\r\n" - {:ok, "text", "plain", %{"charset" => "utf-8"}} - - iex> content_type "text/plain" - {:ok, "text", "plain", %{}} - - iex> content_type "x/*" - :error - - iex> content_type "*/*" - :error - - """ - @spec content_type(binary) :: {:ok, type :: binary, subtype :: binary, params} | :error - def content_type(binary) do - case media_type(binary) do - {:ok, _, "*", _} -> :error - {:ok, _, _, _} = ok -> ok - :error -> :error - end - end - - @doc """ - Parses headers parameters. - - Keys are case insensitive and downcased, - invalid key-value pairs are discarded. - - ## Examples - - iex> params("foo=bar") - %{"foo" => "bar"} - - iex> params(" foo=bar ") - %{"foo" => "bar"} - - iex> params("FOO=bar") - %{"foo" => "bar"} - - iex> params("Foo=bar; baz=BOING") - %{"foo" => "bar", "baz" => "BOING"} - - iex> params("foo=BAR ; wat") - %{"foo" => "BAR"} - - iex> params("=") - %{} - - """ - @spec params(binary) :: params - def params(t) do - t - |> :binary.split(";", [:global]) - |> Enum.reduce(%{}, ¶ms/2) - end - - defp params(param, acc) do - case params_key(strip_spaces(param), "") do - {k, v} -> Map.put(acc, k, v) - false -> acc - end - end - - defp params_key(<>, acc) when acc != "", - do: params_value(t, acc) - defp params_key(<>, _acc) when h in @specials or h in @space or h < 32 or h === 127, - do: false - defp params_key(<>, acc), - do: params_key(t, <>) - defp params_key(<<>>, _acc), - do: false - - defp params_value(token, key) do - case token(token) do - false -> false - value -> {key, value} - end - end - - @doc ~S""" - Parses a value as defined in [RFC-1341][1]. - For convenience, trims whitespace at the end of the token. - Returns `false` if the token is invalid. - - [1]: http://www.w3.org/Protocols/rfc1341/4_Content-Type.html - - ## Examples - - iex> token("foo") - "foo" - - iex> token("foo-bar") - "foo-bar" - - iex> token("") - false - - iex> token(~s[""]) - "" - - iex> token(~S["\""]) - "\"" - - iex> token("foo ") - "foo" - - iex> token("foo bar") - false - - """ - @spec token(binary) :: binary | false - def token(""), - do: false - def token(<>), - do: quoted_token(quoted, "") - def token(token), - do: unquoted_token(token, "") - - defp quoted_token(<<>>, _acc), - do: false - defp quoted_token(<>, acc), - do: strip_spaces(t) == "" and acc - defp quoted_token(<>, acc), - do: quoted_token(t, <>) - defp quoted_token(<>, acc), - do: quoted_token(t, <>) - - defp unquoted_token(<<>>, acc), - do: acc - defp unquoted_token("\r\n" <> t, acc), - do: strip_spaces(t) == "" and acc - defp unquoted_token(<>, acc) when h in @space, - do: strip_spaces(t) == "" and acc - defp unquoted_token(<>, _acc) when h in @specials or h < 32 or h === 127, - do: false - defp unquoted_token(<>, acc), - do: unquoted_token(t, <>) - - @doc """ - Parses a comma-separated list of header values. - - ## Examples - - iex> list("foo, bar") - ["foo", "bar"] - - iex> list("foobar") - ["foobar"] - - iex> list("") - [] - - iex> list("empties, , are,, filtered") - ["empties", "are", "filtered"] - - """ - @spec list(binary) :: [binary] - def list(binary) do - for elem <- :binary.split(binary, ",", [:global]), - (stripped = strip_spaces(elem)) != "", - do: stripped - end - - @doc """ - Validates the given binary is valid UTF-8. - """ - @spec validate_utf8!(binary, binary) :: :ok | no_return - def validate_utf8!(<<_ :: utf8, t :: binary>>, context) do - validate_utf8!(t, context) - end - - def validate_utf8!(<>, context) do - raise Plug.Parsers.BadEncodingError, - message: "invalid UTF-8 on #{context}, got byte #{h}" - end - - def validate_utf8!(<<>>, _context) do - :ok - end - - ## Helpers - - defp strip_spaces("\r\n" <> t), - do: strip_spaces(t) - defp strip_spaces(<>) when h in [?\s, ?\t], - do: strip_spaces(t) - defp strip_spaces(t), - do: t - - defp downcase_char(char) when char in @upper, do: char + 32 - defp downcase_char(char), do: char -end DELETED deps/plug/lib/plug/conn/wrapper_error.ex Index: deps/plug/lib/plug/conn/wrapper_error.ex ================================================================== --- deps/plug/lib/plug/conn/wrapper_error.ex +++ /dev/null @@ -1,26 +0,0 @@ -defmodule Plug.Conn.WrapperError do - @moduledoc """ - Wraps the connection in an error which is meant - to be handled upper in the stack. - - Used by both `Plug.Debugger` and `Plug.ErrorHandler`. - """ - defexception [:conn, :kind, :reason, :stack] - - def message(%{kind: kind, reason: reason, stack: stack}) do - Exception.format_banner(kind, reason, stack) - end - - @doc """ - Reraises an error or a wrapped one. - """ - def reraise(_conn, :error, %__MODULE__{stack: stack} = reason) do - :erlang.raise(:error, reason, stack) - end - - def reraise(conn, kind, reason) do - stack = System.stacktrace - wrapper = %__MODULE__{conn: conn, kind: kind, reason: reason, stack: stack} - :erlang.raise(:error, wrapper, stack) - end -end DELETED deps/plug/lib/plug/crypto.ex Index: deps/plug/lib/plug/crypto.ex ================================================================== --- deps/plug/lib/plug/crypto.ex +++ /dev/null @@ -1,67 +0,0 @@ -defmodule Plug.Crypto do - @moduledoc """ - Namespace and module for crypto functionality. - """ - - use Bitwise - - @doc """ - Masks the token on the left with the token on the right. - - Both tokens are required to have the same size. - """ - def mask(left, right) do - mask(left, right, "") - end - - defp mask(<>, <>, acc) do - mask(left, right, <>) - end - - defp mask(<<>>, <<>>, acc) do - acc - end - - @doc """ - Compares the two binaries (one being masked) in constant-time to avoid - timing attacks. - - It is assumed the right token is masked according to the given mask. - """ - def masked_compare(left, right, mask) do - if byte_size(left) == byte_size(right) do - masked_compare(left, right, mask, 0) == 0 - else - false - end - end - - defp masked_compare(<>, <>, <>, acc) do - masked_compare(left, right, mask, acc ||| (x ^^^ (y ^^^ z))) - end - - defp masked_compare(<<>>, <<>>, <<>>, acc) do - acc - end - - @doc """ - Compares the two binaries in constant-time to avoid timing attacks. - - See: http://codahale.com/a-lesson-in-timing-attacks/ - """ - def secure_compare(left, right) do - if byte_size(left) == byte_size(right) do - secure_compare(left, right, 0) == 0 - else - false - end - end - - defp secure_compare(<>, <>, acc) do - secure_compare(left, right, acc ||| (x ^^^ y)) - end - - defp secure_compare(<<>>, <<>>, acc) do - acc - end -end DELETED deps/plug/lib/plug/crypto/key_generator.ex Index: deps/plug/lib/plug/crypto/key_generator.ex ================================================================== --- deps/plug/lib/plug/crypto/key_generator.ex +++ /dev/null @@ -1,80 +0,0 @@ -defmodule Plug.Crypto.KeyGenerator do - @moduledoc """ - `KeyGenerator` implements PBKDF2 (Password-Based Key Derivation Function 2), - part of PKCS #5 v2.0 (Password-Based Cryptography Specification). - - It can be used to derive a number of keys for various purposes from a given - secret. This lets applications have a single secure secret, but avoid reusing - that key in multiple incompatible contexts. - - see http://tools.ietf.org/html/rfc2898#section-5.2 - """ - - use Bitwise - @max_length bsl(1, 32) - 1 - - @doc """ - Returns a derived key suitable for use. - - ## Options - - * `:iterations` - defaults to 1000 (increase to at least 2^16 if used for passwords); - * `:length` - a length in octets for the derived key. Defaults to 32; - * `:digest` - an hmac function to use as the pseudo-random function. Defaults to `:sha256`; - * `:cache` - an ETS table name to be used as cache. - Only use an ETS table as cache if the secret and salt is a bound set of values. - For example: `:ets.new(:your_name, [:named_table, :public, read_concurrency: true])` - - """ - def generate(secret, salt, opts \\ []) do - iterations = Keyword.get(opts, :iterations, 1000) - length = Keyword.get(opts, :length, 32) - digest = Keyword.get(opts, :digest, :sha256) - cache = Keyword.get(opts, :cache) - - if length > @max_length do - raise ArgumentError, "length must be less than or equal to #{@max_length}" - else - with_cache cache, {secret, salt, iterations, length, digest}, fn -> - generate(mac_fun(digest, secret), salt, iterations, length, 1, [], 0) - end - end - end - - defp with_cache(nil, _key, fun), do: fun.() - defp with_cache(ets, key, fun) do - case :ets.lookup(ets, key) do - [{_key, value}] -> - value - [] -> - value = fun.() - :ets.insert(ets, [{key, value}]) - value - end - end - - defp generate(_fun, _salt, _iterations, max_length, _block_index, acc, length) - when length >= max_length do - key = acc |> Enum.reverse |> IO.iodata_to_binary - <> = key - bin - end - - defp generate(fun, salt, iterations, max_length, block_index, acc, length) do - initial = fun.(<>) - block = iterate(fun, iterations - 1, initial, initial) - generate(fun, salt, iterations, max_length, block_index + 1, - [block | acc], byte_size(block) + length) - end - - defp iterate(_fun, 0, _prev, acc), do: acc - - defp iterate(fun, iteration, prev, acc) do - next = fun.(prev) - iterate(fun, iteration - 1, next, :crypto.exor(next, acc)) - end - - defp mac_fun(digest, secret) do - &:crypto.hmac(digest, secret, &1) - end -end DELETED deps/plug/lib/plug/crypto/message_encryptor.ex Index: deps/plug/lib/plug/crypto/message_encryptor.ex ================================================================== --- deps/plug/lib/plug/crypto/message_encryptor.ex +++ /dev/null @@ -1,105 +0,0 @@ -defmodule Plug.Crypto.MessageEncryptor do - @moduledoc ~S""" - `MessageEncryptor` is a simple way to encrypt values which get stored - somewhere you don't trust. - - The cipher text and initialization vector are base64 encoded and - returned to you. - - This can be used in situations similar to the `MessageVerifier`, but where - you don't want users to be able to determine the value of the payload. - - ## Example - - secret_key_base = "072d1e0157c008193fe48a670cce031faa4e..." - encrypted_cookie_salt = "encrypted cookie" - encrypted_signed_cookie_salt = "signed encrypted cookie" - - secret = KeyGenerator.generate(secret_key_base, encrypted_cookie_salt) - sign_secret = KeyGenerator.generate(secret_key_base, encrypted_signed_cookie_salt) - - data = "José" - encrypted = MessageEncryptor.encrypt_and_sign(data, secret, sign_secret) - decrypted = MessageEncryptor.verify_and_decrypt(encrypted, secret, sign_secret) - decrypted # => "José" - """ - - alias Plug.Crypto.MessageVerifier - - @doc """ - Encrypts and signs a message. - """ - def encrypt_and_sign(message, secret, sign_secret, cipher \\ :aes_cbc256) - when is_binary(message) and is_binary(secret) and is_binary(sign_secret) do - iv = :crypto.strong_rand_bytes(16) - - message - |> pad_message - |> encrypt(cipher, secret, iv) - |> Base.encode64() - |> Kernel.<>("--#{Base.encode64(iv)}") - |> MessageVerifier.sign(sign_secret) - end - - @doc """ - Decrypts and verifies a message. - - We need to verify the message in order to avoid padding attacks. - Reference: http://www.limited-entropy.com/padding-oracle-attacks - """ - def verify_and_decrypt(encrypted, secret, sign_secret, cipher \\ :aes_cbc256) - when is_binary(encrypted) and is_binary(secret) and is_binary(sign_secret) do - case MessageVerifier.verify(encrypted, sign_secret) do - {:ok, verified} -> - [encrypted, iv] = String.split(verified, "--") - case Base.decode64(encrypted) do - {:ok, encrypted} -> - case Base.decode64(iv) do - {:ok, iv} -> - encrypted |> decrypt(cipher, secret, iv) |> unpad_message - :error -> - :error - end - :error -> - :error - end - :error -> - :error - end - end - - defp encrypt(message, cipher, secret, iv) do - :crypto.block_encrypt(cipher, trim_secret(secret), iv, message) - end - - defp decrypt(encrypted, cipher, secret, iv) do - :crypto.block_decrypt(cipher, trim_secret(secret), iv, encrypted) - end - - defp pad_message(msg) do - bytes_remaining = rem(byte_size(msg), 16) - padding_size = 16 - bytes_remaining - msg <> :binary.copy(<>, padding_size) - end - - defp unpad_message(msg) do - padding_size = :binary.last(msg) - if padding_size <= 16 do - msg_size = byte_size(msg) - if binary_part(msg, msg_size, -padding_size) == :binary.copy(<>, padding_size) do - {:ok, binary_part(msg, 0, msg_size - padding_size)} - else - :error - end - else - :error - end - end - - defp trim_secret(secret) do - case byte_size(secret) do - large when large > 32 -> :binary.part(secret, 0, 32) - _ -> secret - end - end -end DELETED deps/plug/lib/plug/crypto/message_verifier.ex Index: deps/plug/lib/plug/crypto/message_verifier.ex ================================================================== --- deps/plug/lib/plug/crypto/message_verifier.ex +++ /dev/null @@ -1,38 +0,0 @@ -defmodule Plug.Crypto.MessageVerifier do - @moduledoc """ - `MessageVerifier` makes it easy to generate and verify messages - which are signed to prevent tampering. - - For example, the cookie store uses this verifier to send data - to the client. The data can be read by the client, but cannot be - tampered with. - """ - - @doc """ - Decodes and verifies the encoded binary was not tampared with. - """ - def verify(binary, secret) when is_binary(binary) and is_binary(secret) do - case String.split(binary, "--") do - [content, digest] when content != "" and digest != "" -> - if Plug.Crypto.secure_compare(digest(secret, content), digest) do - Base.decode64(content) - else - :error - end - _ -> - :error - end - end - - @doc """ - Signs a binary according to the given secret. - """ - def sign(binary, secret) when is_binary(binary) and is_binary(secret) do - encoded = Base.encode64(binary) - encoded <> "--" <> digest(secret, encoded) - end - - defp digest(secret, data) do - :crypto.hmac(:sha, secret, data) |> Base.encode64 - end -end DELETED deps/plug/lib/plug/csrf_protection.ex Index: deps/plug/lib/plug/csrf_protection.ex ================================================================== --- deps/plug/lib/plug/csrf_protection.ex +++ /dev/null @@ -1,225 +0,0 @@ -defmodule Plug.CSRFProtection do - @moduledoc """ - Plug to protect from cross-site request forgery. - - For this plug to work, it expects a session to have been - previously fetched. It will then compare the plug stored - in the session with the one sent by the request to determine - the validity of the request. For an invaid request the action - taken is based on the `:with` option. - - The token may be sent by the request either via the params - with key "_csrf_token" or a header with name "x-csrf-token". - - GET requests are not protected, as they should not have any - side-effect or change your application state. JavaScript - requests are an exception: by using a script tag, external - websites can embed server-side generated JavaScript, which - can leak information. For this reason, this plug also forbids - any GET JavaScript request that is not XHR (or AJAX). - - ## Token generation - - This plug won't generate tokens automatically. Instead, - tokens will be generated only when required by calling - `Plug.CSRFProtection.get_csrf_token/0`. The token is then - stored in the process dictionary to be set in the request. - - One may wonder: why the process dictionary? - - The CSRF token is usually generated inside forms which may - be isolated from the connection. Storing them in the process - dictionary allows them to be generated as a side-effect, - becoming one of those rare situations where using the process - dictionary is useful. - - ## Options - - * `:with` - should be one of `:exception` or `:clear_session`. Defaults to - `:exception`. - * `:exception` - for invalid requests, this plug will raise - `Plug.CSRFProtection.InvalidCSRFTokenError`. - * `:clear_session` - for invalid requests, this plug will set an empty - session for only this request. Also any changes to the session during this - request will be ignored. - - ## Disabling - - You may disable this plug by doing - `Plug.Conn.put_private(:plug_skip_csrf_protection, true)`. This was made - available for disabling `Plug.CSRFProtection` in tests and not for dynamically - skipping `Plug.CSRFProtection` in production code. If you want specific routes to - skip `Plug.CSRFProtection`, then use a different stack of plugs for that route that - does not include `Plug.CSRFProtection`. - - ## Examples - - plug Plug.Session, ... - plug :fetch_session - plug Plug.CSRFProtection - - """ - - import Plug.Conn - require Bitwise - @unprotected_methods ~w(HEAD GET OPTIONS) - - defmodule InvalidCSRFTokenError do - @moduledoc "Error raised when CSRF token is invalid." - - message = - "invalid CSRF (Cross Site Forgery Protection) token, make sure all " - <> "requests include a '_csrf_token' param or an 'x-csrf-token' header" - - defexception message: message, plug_status: 403 - end - - defmodule InvalidCrossOriginRequestError do - @moduledoc "Error raised when non-XHR requests are used for Javascript responses." - - message = - "security warning: an embedded - DELETED deps/plug/lib/plug/test.ex Index: deps/plug/lib/plug/test.ex ================================================================== --- deps/plug/lib/plug/test.ex +++ /dev/null @@ -1,126 +0,0 @@ -defmodule Plug.Test do - @moduledoc """ - Conveniences for testing plugs. - - This module can be used in your test cases, like this: - - use ExUnit.Case, async: true - use Plug.Test - - Using this module will: - - * import all the functions from this module - * import all the functions from the `Plug.Conn` module - """ - - @doc false - defmacro __using__(_) do - quote do - import Plug.Test - import Plug.Conn - end - end - - alias Plug.Conn - @typep params :: binary | list | map | nil - - @doc """ - Creates a test connection. - - The request `method` and `path` are required arguments. `method` may be any - value that implements `to_string/1` and it will properly converted and - normalized (e.g., `:get` or `"post"`). - - The `params_or_body` field must be one of: - - * `nil` - meaning there is no body; - * a binary - containing a request body. For such cases, `:headers` - must be given as option with a content-type; - * a map or list - containing the parameters which will automatically - set the content-type to multipart. The map or list may contain - other lists or maps and all entries will be normalized to string - keys; - - ## Examples - - conn(:get, "/foo", "bar=10") - conn(:post, "/") - conn("patch", "/", "") |> put_req_header("content-type", "application/json") - - """ - @spec conn(String.Chars.t, binary, params) :: Conn.t - def conn(method, path, params_or_body \\ nil) do - Plug.Adapters.Test.Conn.conn(%Plug.Conn{}, method, path, params_or_body) - end - - @doc """ - Returns the sent response. - - This function is useful when the code being invoked crashes and - there is a need to verify a particular response was sent even with - the crash. It returns a tuple with `{status, headers, body}`. - """ - def sent_resp(%Conn{adapter: {Plug.Adapters.Test.Conn, %{ref: ref}}}) do - case receive_resp(ref) do - :no_resp -> - raise "no sent response available for the given connection. " <> - "Maybe the application did not send anything?" - response -> - case receive_resp(ref) do - :no_resp -> - send(self, {ref, response}) - response - _otherwise -> - raise "a response for the given connection has been sent more than once" - end - end - end - - defp receive_resp(ref) do - receive do - {^ref, response} -> response - after - 0 -> :no_resp - end - end - - @doc """ - Puts a request cookie. - """ - @spec put_req_cookie(Conn.t, binary, binary) :: Conn.t - def put_req_cookie(conn, key, value) when is_binary(key) and is_binary(value) do - conn = delete_req_cookie(conn, key) - %{conn | req_headers: [{"cookie", "#{key}=#{value}"}|conn.req_headers]} - end - - @doc """ - Deletes a request cookie. - """ - @spec delete_req_cookie(Conn.t, binary) :: Conn.t - def delete_req_cookie(%Conn{req_cookies: %Plug.Conn.Unfetched{}} = conn, key) - when is_binary(key) do - key = "#{key}=" - size = byte_size(key) - fun = &match?({"cookie", value} when binary_part(value, 0, size) == key, &1) - %{conn | req_headers: Enum.reject(conn.req_headers, fun)} - end - - def delete_req_cookie(_conn, key) when is_binary(key) do - raise ArgumentError, - message: "cannot put/delete request cookies after cookies were fetched" - end - - @doc """ - Moves cookies from a connection into a new connection for subsequent requests. - - This function copies the cookie information in `old_conn` into `new_conn`, - emulating multiple requests done by clients where cookies are always passed - forward, and returns the new version of `new_conn`. - """ - @spec recycle_cookies(Conn.t, Conn.t) :: Conn.t - def recycle_cookies(new_conn, old_conn) do - Enum.reduce Plug.Conn.fetch_cookies(old_conn).cookies, new_conn, fn - {key, value}, acc -> put_req_cookie(acc, to_string(key), value) - end - end -end DELETED deps/plug/lib/plug/upload.ex Index: deps/plug/lib/plug/upload.ex ================================================================== --- deps/plug/lib/plug/upload.ex +++ /dev/null @@ -1,168 +0,0 @@ -defmodule Plug.Upload do - @moduledoc """ - A server (a `GenServer` specifically) that manages uploaded files. - - Uploaded files are stored in a temporary directory - and removed from that directory after the process that - requested the file dies. - - During the request, files are represented with - a `Plug.Upload` struct that contains three fields: - - * `:path` - the path to the uploaded file on the filesystem - * `:content_type` - the content type of the uploaded file - * `:filename` - the filename of the uploaded file given in the request - - **Note**: as mentioned in the documentation for `Plug.Parsers`, the `:plug` - application has to be started in order to upload files and use the - `Plug.Upload` module. - """ - - defstruct [:path, :content_type, :filename] - @type t :: %__MODULE__{ - path: Path.t, - filename: binary, - content_type: binary | nil - } - - @doc """ - Requests a random file to be created in the upload directory - with the given prefix. - """ - @spec random_file(binary) :: - {:ok, binary} | - {:too_many_attempts, binary, pos_integer} | - {:no_tmp, [binary]} - def random_file(prefix) do - GenServer.call(plug_server, {:random, prefix}) - end - - @doc """ - Requests a random file to be created in the upload directory - with the given prefix. Raises on failure. - """ - @spec random_file!(binary) :: binary | no_return - def random_file!(prefix) do - case random_file(prefix) do - {:ok, path} -> - path - {:too_many_attempts, tmp, attempts} -> - raise "tried #{attempts} times to create an uploaded file at #{tmp} but failed. What gives?" - {:no_tmp, _tmps} -> - raise "could not create a tmp directory to store uploads. Set PLUG_TMPDIR to a directory with write permission" - end - end - - defp plug_server do - Process.whereis(__MODULE__) || - raise "could not find process Plug.Upload. Have you started the :plug application?" - end - - use GenServer - - @doc """ - Starts the upload handling server. - """ - def start_link() do - GenServer.start_link(__MODULE__, :ok, [name: __MODULE__]) - end - - ## Callbacks - - @temp_env_vars ~w(PLUG_TMPDIR TMPDIR TMP TEMP)s - @max_attempts 10 - - @doc false - def init(:ok) do - tmp = Enum.find_value @temp_env_vars, "/tmp", &System.get_env/1 - cwd = Path.join(File.cwd!, "tmp") - ets = :ets.new(:plug_uploads, [:private]) - {:ok, {[tmp, cwd], ets}} - end - - @doc false - def handle_call({:random, prefix}, {pid, _ref}, {tmps, ets} = state) do - case find_tmp_dir(pid, tmps, ets) do - {:ok, tmp, paths} -> - {:reply, open_random_file(prefix, tmp, 0, pid, ets, paths), state} - {:no_tmp, _} = error -> - {:reply, error, state} - end - end - - def handle_call(msg, from, state) do - super(msg, from, state) - end - - @doc false - def handle_info({:DOWN, _ref, :process, pid, _reason}, {_, ets} = state) do - case :ets.lookup(ets, pid) do - [{pid, _tmp, paths}] -> - :ets.delete(ets, pid) - Enum.each paths, &:file.delete/1 - [] -> - :ok - end - {:noreply, state} - end - - def handle_info(msg, state) do - super(msg, state) - end - - ## Helpers - - defp find_tmp_dir(pid, tmps, ets) do - case :ets.lookup(ets, pid) do - [{^pid, tmp, paths}] -> - {:ok, tmp, paths} - [] -> - if tmp = ensure_tmp_dir(tmps) do - :erlang.monitor(:process, pid) - :ets.insert(ets, {pid, tmp, []}) - {:ok, tmp, []} - else - {:no_tmp, tmps} - end - end - end - - defp ensure_tmp_dir(tmps) do - {mega, _, _} = :os.timestamp - subdir = "/plug-" <> i(mega) - Enum.find_value(tmps, &write_tmp_dir(&1 <> subdir)) - end - - defp write_tmp_dir(path) do - case File.mkdir_p(path) do - :ok -> path - {:error, _} -> nil - end - end - - defp open_random_file(prefix, tmp, attempts, pid, ets, paths) when attempts < @max_attempts do - path = path(prefix, tmp) - - case :file.write_file(path, "", [:write, :raw, :exclusive, :binary]) do - :ok -> - :ets.update_element(ets, pid, {3, [path|paths]}) - {:ok, path} - {:error, reason} when reason in [:eexist, :eaccess] -> - open_random_file(prefix, tmp, attempts + 1, pid, ets, paths) - end - end - - defp open_random_file(_prefix, tmp, attempts, _pid, _ets, _paths) do - {:too_many_attempts, tmp, attempts} - end - - @compile {:inline, i: 1} - - defp i(integer), do: Integer.to_string(integer) - - defp path(prefix, tmp) do - {_mega, sec, micro} = :os.timestamp - scheduler_id = :erlang.system_info(:scheduler_id) - tmp <> "/" <> prefix <> "-" <> i(sec) <> "-" <> i(micro) <> "-" <> i(scheduler_id) - end -end DELETED deps/plug/mix.exs Index: deps/plug/mix.exs ================================================================== --- deps/plug/mix.exs +++ /dev/null @@ -1,38 +0,0 @@ -defmodule Plug.Mixfile do - use Mix.Project - - @version "1.0.3" - - def project do - [app: :plug, - version: @version, - elixir: "~> 1.0", - deps: deps, - package: package, - description: "A specification and conveniences for composable " <> - "modules between web applications", - name: "Plug", - docs: [extras: ["README.md"], main: "extra-readme", - source_ref: "v#{@version}", - source_url: "https://github.com/elixir-lang/plug"]] - end - - # Configuration for the OTP application - def application do - [applications: [:crypto, :logger], - mod: {Plug, []}] - end - - def deps do - [{:cowboy, "~> 1.0", optional: true}, - {:earmark, "~> 0.1", only: :docs}, - {:ex_doc, "~> 0.10", only: :docs}, - {:inch_ex, only: :docs}, - {:hackney, "~> 1.2.0", only: :test}] - end - - defp package do - %{licenses: ["Apache 2"], - links: %{"GitHub" => "https://github.com/elixir-lang/plug"}} - end -end DELETED deps/ranch/AUTHORS Index: deps/ranch/AUTHORS ================================================================== --- deps/ranch/AUTHORS +++ /dev/null @@ -1,33 +0,0 @@ -Ranch is available thanks to the work of: - -Loïc Hoguin -James Fish -Andrew Majorov -Ransom Richardson -Fred Hebert -Geoff Cant -Klaus Trainer -josh rotenberg -0x00F6 -Alexander Zhuravlev -Ali Sabil -Andre Graf -Andrew Thompson -Jihyun Yu -Slava Yurin -Stéphane Wirtel -Xiao Jia - -The Ranch code was initially part of Cowboy. Before it was -split into a separate project, the following people worked -on the code that then became Ranch: - -Loïc Hoguin -Ali Sabil -Andrew Thompson -DeadZen -Hunter Morris -Jesper Louis Andersen -Paul Oliver -Roberto Ostinelli -Steven Gravell DELETED deps/ranch/LICENSE Index: deps/ranch/LICENSE ================================================================== --- deps/ranch/LICENSE +++ /dev/null @@ -1,13 +0,0 @@ -Copyright (c) 2011-2015, Loïc Hoguin - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. DELETED deps/ranch/Makefile Index: deps/ranch/Makefile ================================================================== --- deps/ranch/Makefile +++ /dev/null @@ -1,32 +0,0 @@ -# See LICENSE for licensing information. - -PROJECT = ranch - -# Options. - -COMPILE_FIRST = ranch_transport -CT_OPTS += -pa test -ct_hooks ranch_ct_hook [] -PLT_APPS = crypto public_key ssl -CI_OTP = \ - OTP_R15B01 OTP_R15B02 OTP_R15B03-1 \ - OTP_R16B OTP_R16B01 OTP_R16B02 OTP_R16B03-1 \ - OTP-17.0.2 OTP-17.1.2 OTP-17.2.2 OTP-17.3.4 OTP-17.4.1 OTP-17.5.6.2 \ - OTP-18.0.2 - -# Dependencies. - -TEST_DEPS = ct_helper -dep_ct_helper = git https://github.com/ninenines/ct_helper master - -# Standard targets. - -include erlang.mk - -# Also dialyze the tests. - -DIALYZER_OPTS += --src -r test - -# Use erl_make_certs from the tested release. - -ci-setup:: $(DEPS_DIR)/ct_helper - cp ~/.kerl/builds/$(CI_OTP_RELEASE)/otp_src_git/lib/ssl/test/erl_make_certs.erl deps/ct_helper/src/ DELETED deps/ranch/ebin/ranch.app Index: deps/ranch/ebin/ranch.app ================================================================== --- deps/ranch/ebin/ranch.app +++ /dev/null @@ -1,12 +0,0 @@ -{application,ranch, - [{description,"Socket acceptor pool for TCP protocols."}, - {vsn,"1.2.0"}, - {id,"git"}, - {modules,[ranch,ranch_acceptor,ranch_acceptors_sup,ranch_app, - ranch_conns_sup,ranch_listener_sup,ranch_protocol, - ranch_server,ranch_ssl,ranch_sup,ranch_tcp, - ranch_transport]}, - {registered,[ranch_sup,ranch_server]}, - {applications,[kernel,stdlib]}, - {mod,{ranch_app,[]}}, - {env,[]}]}. DELETED deps/ranch/ebin/ranch.beam Index: deps/ranch/ebin/ranch.beam ================================================================== --- deps/ranch/ebin/ranch.beam +++ /dev/null cannot compute difference between binary files DELETED deps/ranch/ebin/ranch_acceptor.beam Index: deps/ranch/ebin/ranch_acceptor.beam ================================================================== --- deps/ranch/ebin/ranch_acceptor.beam +++ /dev/null cannot compute difference between binary files DELETED deps/ranch/ebin/ranch_acceptors_sup.beam Index: deps/ranch/ebin/ranch_acceptors_sup.beam ================================================================== --- deps/ranch/ebin/ranch_acceptors_sup.beam +++ /dev/null cannot compute difference between binary files DELETED deps/ranch/ebin/ranch_app.beam Index: deps/ranch/ebin/ranch_app.beam ================================================================== --- deps/ranch/ebin/ranch_app.beam +++ /dev/null cannot compute difference between binary files DELETED deps/ranch/ebin/ranch_conns_sup.beam Index: deps/ranch/ebin/ranch_conns_sup.beam ================================================================== --- deps/ranch/ebin/ranch_conns_sup.beam +++ /dev/null cannot compute difference between binary files DELETED deps/ranch/ebin/ranch_listener_sup.beam Index: deps/ranch/ebin/ranch_listener_sup.beam ================================================================== --- deps/ranch/ebin/ranch_listener_sup.beam +++ /dev/null cannot compute difference between binary files DELETED deps/ranch/ebin/ranch_protocol.beam Index: deps/ranch/ebin/ranch_protocol.beam ================================================================== --- deps/ranch/ebin/ranch_protocol.beam +++ /dev/null cannot compute difference between binary files DELETED deps/ranch/ebin/ranch_server.beam Index: deps/ranch/ebin/ranch_server.beam ================================================================== --- deps/ranch/ebin/ranch_server.beam +++ /dev/null cannot compute difference between binary files DELETED deps/ranch/ebin/ranch_ssl.beam Index: deps/ranch/ebin/ranch_ssl.beam ================================================================== --- deps/ranch/ebin/ranch_ssl.beam +++ /dev/null cannot compute difference between binary files DELETED deps/ranch/ebin/ranch_sup.beam Index: deps/ranch/ebin/ranch_sup.beam ================================================================== --- deps/ranch/ebin/ranch_sup.beam +++ /dev/null cannot compute difference between binary files DELETED deps/ranch/ebin/ranch_tcp.beam Index: deps/ranch/ebin/ranch_tcp.beam ================================================================== --- deps/ranch/ebin/ranch_tcp.beam +++ /dev/null cannot compute difference between binary files DELETED deps/ranch/ebin/ranch_transport.beam Index: deps/ranch/ebin/ranch_transport.beam ================================================================== --- deps/ranch/ebin/ranch_transport.beam +++ /dev/null cannot compute difference between binary files DELETED deps/ranch/erlang.mk Index: deps/ranch/erlang.mk ================================================================== --- deps/ranch/erlang.mk +++ /dev/null @@ -1,6029 +0,0 @@ -# Copyright (c) 2013-2015, Loïc Hoguin -# -# Permission to use, copy, modify, and/or distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -.PHONY: all app deps search rel docs install-docs check tests clean distclean help erlang-mk - -ERLANG_MK_FILENAME := $(realpath $(lastword $(MAKEFILE_LIST))) - -ERLANG_MK_VERSION = 1.2.0-633-g8a32e48 - -# Core configuration. - -PROJECT ?= $(notdir $(CURDIR)) -PROJECT := $(strip $(PROJECT)) - -PROJECT_VERSION ?= rolling - -# Verbosity. - -V ?= 0 - -verbose_0 = @ -verbose = $(verbose_$(V)) - -gen_verbose_0 = @echo " GEN " $@; -gen_verbose = $(gen_verbose_$(V)) - -# Temporary files directory. - -ERLANG_MK_TMP ?= $(CURDIR)/.erlang.mk -export ERLANG_MK_TMP - -# "erl" command. - -ERL = erl +A0 -noinput -boot start_clean - -# Platform detection. -# @todo Add Windows/Cygwin detection eventually. - -ifeq ($(PLATFORM),) -UNAME_S := $(shell uname -s) - -ifeq ($(UNAME_S),Linux) -PLATFORM = linux -else ifeq ($(UNAME_S),Darwin) -PLATFORM = darwin -else ifeq ($(UNAME_S),SunOS) -PLATFORM = solaris -else ifeq ($(UNAME_S),GNU) -PLATFORM = gnu -else ifeq ($(UNAME_S),FreeBSD) -PLATFORM = freebsd -else ifeq ($(UNAME_S),NetBSD) -PLATFORM = netbsd -else ifeq ($(UNAME_S),OpenBSD) -PLATFORM = openbsd -else -$(error Unable to detect platform. Please open a ticket with the output of uname -a.) -endif - -export PLATFORM -endif - -# Core targets. - -ifneq ($(words $(MAKECMDGOALS)),1) -.NOTPARALLEL: -endif - -all:: deps - $(verbose) $(MAKE) --no-print-directory app - $(verbose) $(MAKE) --no-print-directory rel - -# Noop to avoid a Make warning when there's nothing to do. -rel:: - $(verbose) echo -n - -check:: clean app tests - -clean:: clean-crashdump - -clean-crashdump: -ifneq ($(wildcard erl_crash.dump),) - $(gen_verbose) rm -f erl_crash.dump -endif - -distclean:: clean - -help:: - $(verbose) printf "%s\n" \ - "erlang.mk (version $(ERLANG_MK_VERSION)) is distributed under the terms of the ISC License." \ - "Copyright (c) 2013-2015 Loïc Hoguin " \ - "" \ - "Usage: [V=1] $(MAKE) [-jNUM] [target]..." \ - "" \ - "Core targets:" \ - " all Run deps, app and rel targets in that order" \ - " app Compile the project" \ - " deps Fetch dependencies (if needed) and compile them" \ - " search q=... Search for a package in the built-in index" \ - " rel Build a release for this project, if applicable" \ - " docs Build the documentation for this project" \ - " install-docs Install the man pages for this project" \ - " check Compile and run all tests and analysis for this project" \ - " tests Run the tests for this project" \ - " clean Delete temporary and output files from most targets" \ - " distclean Delete all temporary and output files" \ - " help Display this help and exit" \ - " erlang-mk Update erlang.mk to the latest version" - -# Core functions. - -empty := -space := $(empty) $(empty) -tab := $(empty) $(empty) -comma := , - -define newline - - -endef - -define comma_list -$(subst $(space),$(comma),$(strip $(1))) -endef - -# Adding erlang.mk to make Erlang scripts who call init:get_plain_arguments() happy. -define erlang -$(ERL) -pz $(ERLANG_MK_TMP)/rebar/ebin -eval "$(subst $(newline),,$(subst ",\",$(1)))" -- erlang.mk -endef - -ifeq ($(shell which wget 2>/dev/null | wc -l), 1) -define core_http_get - wget --no-check-certificate -O $(1) $(2)|| rm $(1) -endef -else -define core_http_get.erl - ssl:start(), - inets:start(), - case httpc:request(get, {"$(2)", []}, [{autoredirect, true}], []) of - {ok, {{_, 200, _}, _, Body}} -> - case file:write_file("$(1)", Body) of - ok -> ok; - {error, R1} -> halt(R1) - end; - {error, R2} -> - halt(R2) - end, - halt(0). -endef - -define core_http_get - $(call erlang,$(call core_http_get.erl,$(1),$(2))) -endef -endif - -core_eq = $(and $(findstring $(1),$(2)),$(findstring $(2),$(1))) - -core_find = $(foreach d,$(call core_ls,$1*),$(call core_find,$d/,$2) $(filter $(subst *,%,$2),$d)) - -core_lc = $(subst A,a,$(subst B,b,$(subst C,c,$(subst D,d,$(subst E,e,$(subst F,f,$(subst G,g,$(subst H,h,$(subst I,i,$(subst J,j,$(subst K,k,$(subst L,l,$(subst M,m,$(subst N,n,$(subst O,o,$(subst P,p,$(subst Q,q,$(subst R,r,$(subst S,s,$(subst T,t,$(subst U,u,$(subst V,v,$(subst W,w,$(subst X,x,$(subst Y,y,$(subst Z,z,$(1))))))))))))))))))))))))))) - -# @todo On Windows: $(shell dir /B $(1)); make sure to handle when no file exists. -core_ls = $(filter-out $(1),$(shell echo $(1))) - -# Automated update. - -ERLANG_MK_BUILD_CONFIG ?= build.config -ERLANG_MK_BUILD_DIR ?= .erlang.mk.build - -erlang-mk: - git clone https://github.com/ninenines/erlang.mk $(ERLANG_MK_BUILD_DIR) - if [ -f $(ERLANG_MK_BUILD_CONFIG) ]; then cp $(ERLANG_MK_BUILD_CONFIG) $(ERLANG_MK_BUILD_DIR); fi - cd $(ERLANG_MK_BUILD_DIR) && $(MAKE) - cp $(ERLANG_MK_BUILD_DIR)/erlang.mk ./erlang.mk - rm -rf $(ERLANG_MK_BUILD_DIR) - -# The erlang.mk package index is bundled in the default erlang.mk build. -# Search for the string "copyright" to skip to the rest of the code. - -PACKAGES += aberth -pkg_aberth_name = aberth -pkg_aberth_description = Generic BERT-RPC server in Erlang -pkg_aberth_homepage = https://github.com/a13x/aberth -pkg_aberth_fetch = git -pkg_aberth_repo = https://github.com/a13x/aberth -pkg_aberth_commit = master - -PACKAGES += active -pkg_active_name = active -pkg_active_description = Active development for Erlang: rebuild and reload source/binary files while the VM is running -pkg_active_homepage = https://github.com/proger/active -pkg_active_fetch = git -pkg_active_repo = https://github.com/proger/active -pkg_active_commit = master - -PACKAGES += actordb_core -pkg_actordb_core_name = actordb_core -pkg_actordb_core_description = ActorDB main source -pkg_actordb_core_homepage = http://www.actordb.com/ -pkg_actordb_core_fetch = git -pkg_actordb_core_repo = https://github.com/biokoda/actordb_core -pkg_actordb_core_commit = master - -PACKAGES += actordb_thrift -pkg_actordb_thrift_name = actordb_thrift -pkg_actordb_thrift_description = Thrift API for ActorDB -pkg_actordb_thrift_homepage = http://www.actordb.com/ -pkg_actordb_thrift_fetch = git -pkg_actordb_thrift_repo = https://github.com/biokoda/actordb_thrift -pkg_actordb_thrift_commit = master - -PACKAGES += aleppo -pkg_aleppo_name = aleppo -pkg_aleppo_description = Alternative Erlang Pre-Processor -pkg_aleppo_homepage = https://github.com/ErlyORM/aleppo -pkg_aleppo_fetch = git -pkg_aleppo_repo = https://github.com/ErlyORM/aleppo -pkg_aleppo_commit = master - -PACKAGES += alog -pkg_alog_name = alog -pkg_alog_description = Simply the best logging framework for Erlang -pkg_alog_homepage = https://github.com/siberian-fast-food/alogger -pkg_alog_fetch = git -pkg_alog_repo = https://github.com/siberian-fast-food/alogger -pkg_alog_commit = master - -PACKAGES += amqp_client -pkg_amqp_client_name = amqp_client -pkg_amqp_client_description = RabbitMQ Erlang AMQP client -pkg_amqp_client_homepage = https://www.rabbitmq.com/erlang-client-user-guide.html -pkg_amqp_client_fetch = git -pkg_amqp_client_repo = https://github.com/rabbitmq/rabbitmq-erlang-client.git -pkg_amqp_client_commit = master - -PACKAGES += annotations -pkg_annotations_name = annotations -pkg_annotations_description = Simple code instrumentation utilities -pkg_annotations_homepage = https://github.com/hyperthunk/annotations -pkg_annotations_fetch = git -pkg_annotations_repo = https://github.com/hyperthunk/annotations -pkg_annotations_commit = master - -PACKAGES += antidote -pkg_antidote_name = antidote -pkg_antidote_description = Large-scale computation without synchronisation -pkg_antidote_homepage = https://syncfree.lip6.fr/ -pkg_antidote_fetch = git -pkg_antidote_repo = https://github.com/SyncFree/antidote -pkg_antidote_commit = master - -PACKAGES += apns -pkg_apns_name = apns -pkg_apns_description = Apple Push Notification Server for Erlang -pkg_apns_homepage = http://inaka.github.com/apns4erl -pkg_apns_fetch = git -pkg_apns_repo = https://github.com/inaka/apns4erl -pkg_apns_commit = 1.0.4 - -PACKAGES += azdht -pkg_azdht_name = azdht -pkg_azdht_description = Azureus Distributed Hash Table (DHT) in Erlang -pkg_azdht_homepage = https://github.com/arcusfelis/azdht -pkg_azdht_fetch = git -pkg_azdht_repo = https://github.com/arcusfelis/azdht -pkg_azdht_commit = master - -PACKAGES += backoff -pkg_backoff_name = backoff -pkg_backoff_description = Simple exponential backoffs in Erlang -pkg_backoff_homepage = https://github.com/ferd/backoff -pkg_backoff_fetch = git -pkg_backoff_repo = https://github.com/ferd/backoff -pkg_backoff_commit = master - -PACKAGES += barrel_tcp -pkg_barrel_tcp_name = barrel_tcp -pkg_barrel_tcp_description = barrel is a generic TCP acceptor pool with low latency in Erlang. -pkg_barrel_tcp_homepage = https://github.com/benoitc-attic/barrel_tcp -pkg_barrel_tcp_fetch = git -pkg_barrel_tcp_repo = https://github.com/benoitc-attic/barrel_tcp -pkg_barrel_tcp_commit = master - -PACKAGES += basho_bench -pkg_basho_bench_name = basho_bench -pkg_basho_bench_description = A load-generation and testing tool for basically whatever you can write a returning Erlang function for. -pkg_basho_bench_homepage = https://github.com/basho/basho_bench -pkg_basho_bench_fetch = git -pkg_basho_bench_repo = https://github.com/basho/basho_bench -pkg_basho_bench_commit = master - -PACKAGES += bcrypt -pkg_bcrypt_name = bcrypt -pkg_bcrypt_description = Bcrypt Erlang / C library -pkg_bcrypt_homepage = https://github.com/riverrun/branglecrypt -pkg_bcrypt_fetch = git -pkg_bcrypt_repo = https://github.com/riverrun/branglecrypt -pkg_bcrypt_commit = master - -PACKAGES += beam -pkg_beam_name = beam -pkg_beam_description = BEAM emulator written in Erlang -pkg_beam_homepage = https://github.com/tonyrog/beam -pkg_beam_fetch = git -pkg_beam_repo = https://github.com/tonyrog/beam -pkg_beam_commit = master - -PACKAGES += beanstalk -pkg_beanstalk_name = beanstalk -pkg_beanstalk_description = An Erlang client for beanstalkd -pkg_beanstalk_homepage = https://github.com/tim/erlang-beanstalk -pkg_beanstalk_fetch = git -pkg_beanstalk_repo = https://github.com/tim/erlang-beanstalk -pkg_beanstalk_commit = master - -PACKAGES += bear -pkg_bear_name = bear -pkg_bear_description = a set of statistics functions for erlang -pkg_bear_homepage = https://github.com/boundary/bear -pkg_bear_fetch = git -pkg_bear_repo = https://github.com/boundary/bear -pkg_bear_commit = master - -PACKAGES += bertconf -pkg_bertconf_name = bertconf -pkg_bertconf_description = Make ETS tables out of statc BERT files that are auto-reloaded -pkg_bertconf_homepage = https://github.com/ferd/bertconf -pkg_bertconf_fetch = git -pkg_bertconf_repo = https://github.com/ferd/bertconf -pkg_bertconf_commit = master - -PACKAGES += bifrost -pkg_bifrost_name = bifrost -pkg_bifrost_description = Erlang FTP Server Framework -pkg_bifrost_homepage = https://github.com/thorstadt/bifrost -pkg_bifrost_fetch = git -pkg_bifrost_repo = https://github.com/thorstadt/bifrost -pkg_bifrost_commit = master - -PACKAGES += binpp -pkg_binpp_name = binpp -pkg_binpp_description = Erlang Binary Pretty Printer -pkg_binpp_homepage = https://github.com/jtendo/binpp -pkg_binpp_fetch = git -pkg_binpp_repo = https://github.com/jtendo/binpp -pkg_binpp_commit = master - -PACKAGES += bisect -pkg_bisect_name = bisect -pkg_bisect_description = Ordered fixed-size binary dictionary in Erlang -pkg_bisect_homepage = https://github.com/knutin/bisect -pkg_bisect_fetch = git -pkg_bisect_repo = https://github.com/knutin/bisect -pkg_bisect_commit = master - -PACKAGES += bitcask -pkg_bitcask_name = bitcask -pkg_bitcask_description = because you need another a key/value storage engine -pkg_bitcask_homepage = https://github.com/basho/bitcask -pkg_bitcask_fetch = git -pkg_bitcask_repo = https://github.com/basho/bitcask -pkg_bitcask_commit = master - -PACKAGES += bitstore -pkg_bitstore_name = bitstore -pkg_bitstore_description = A document based ontology development environment -pkg_bitstore_homepage = https://github.com/bdionne/bitstore -pkg_bitstore_fetch = git -pkg_bitstore_repo = https://github.com/bdionne/bitstore -pkg_bitstore_commit = master - -PACKAGES += bootstrap -pkg_bootstrap_name = bootstrap -pkg_bootstrap_description = A simple, yet powerful Erlang cluster bootstrapping application. -pkg_bootstrap_homepage = https://github.com/schlagert/bootstrap -pkg_bootstrap_fetch = git -pkg_bootstrap_repo = https://github.com/schlagert/bootstrap -pkg_bootstrap_commit = master - -PACKAGES += boss_db -pkg_boss_db_name = boss_db -pkg_boss_db_description = BossDB: a sharded, caching, pooling, evented ORM for Erlang -pkg_boss_db_homepage = https://github.com/ErlyORM/boss_db -pkg_boss_db_fetch = git -pkg_boss_db_repo = https://github.com/ErlyORM/boss_db -pkg_boss_db_commit = master - -PACKAGES += boss -pkg_boss_name = boss -pkg_boss_description = Erlang web MVC, now featuring Comet -pkg_boss_homepage = https://github.com/ChicagoBoss/ChicagoBoss -pkg_boss_fetch = git -pkg_boss_repo = https://github.com/ChicagoBoss/ChicagoBoss -pkg_boss_commit = master - -PACKAGES += bson -pkg_bson_name = bson -pkg_bson_description = BSON documents in Erlang, see bsonspec.org -pkg_bson_homepage = https://github.com/comtihon/bson-erlang -pkg_bson_fetch = git -pkg_bson_repo = https://github.com/comtihon/bson-erlang -pkg_bson_commit = master - -PACKAGES += bullet -pkg_bullet_name = bullet -pkg_bullet_description = Simple, reliable, efficient streaming for Cowboy. -pkg_bullet_homepage = http://ninenines.eu -pkg_bullet_fetch = git -pkg_bullet_repo = https://github.com/extend/bullet -pkg_bullet_commit = master - -PACKAGES += cache -pkg_cache_name = cache -pkg_cache_description = Erlang in-memory cache -pkg_cache_homepage = https://github.com/fogfish/cache -pkg_cache_fetch = git -pkg_cache_repo = https://github.com/fogfish/cache -pkg_cache_commit = master - -PACKAGES += cake -pkg_cake_name = cake -pkg_cake_description = Really simple terminal colorization -pkg_cake_homepage = https://github.com/darach/cake-erl -pkg_cake_fetch = git -pkg_cake_repo = https://github.com/darach/cake-erl -pkg_cake_commit = v0.1.2 - -PACKAGES += carotene -pkg_carotene_name = carotene -pkg_carotene_description = Real-time server -pkg_carotene_homepage = https://github.com/carotene/carotene -pkg_carotene_fetch = git -pkg_carotene_repo = https://github.com/carotene/carotene -pkg_carotene_commit = master - -PACKAGES += cberl -pkg_cberl_name = cberl -pkg_cberl_description = NIF based Erlang bindings for Couchbase -pkg_cberl_homepage = https://github.com/chitika/cberl -pkg_cberl_fetch = git -pkg_cberl_repo = https://github.com/chitika/cberl -pkg_cberl_commit = master - -PACKAGES += cecho -pkg_cecho_name = cecho -pkg_cecho_description = An ncurses library for Erlang -pkg_cecho_homepage = https://github.com/mazenharake/cecho -pkg_cecho_fetch = git -pkg_cecho_repo = https://github.com/mazenharake/cecho -pkg_cecho_commit = master - -PACKAGES += cferl -pkg_cferl_name = cferl -pkg_cferl_description = Rackspace / Open Stack Cloud Files Erlang Client -pkg_cferl_homepage = https://github.com/ddossot/cferl -pkg_cferl_fetch = git -pkg_cferl_repo = https://github.com/ddossot/cferl -pkg_cferl_commit = master - -PACKAGES += chaos_monkey -pkg_chaos_monkey_name = chaos_monkey -pkg_chaos_monkey_description = This is The CHAOS MONKEY. It will kill your processes. -pkg_chaos_monkey_homepage = https://github.com/dLuna/chaos_monkey -pkg_chaos_monkey_fetch = git -pkg_chaos_monkey_repo = https://github.com/dLuna/chaos_monkey -pkg_chaos_monkey_commit = master - -PACKAGES += check_node -pkg_check_node_name = check_node -pkg_check_node_description = Nagios Scripts for monitoring Riak -pkg_check_node_homepage = https://github.com/basho-labs/riak_nagios -pkg_check_node_fetch = git -pkg_check_node_repo = https://github.com/basho-labs/riak_nagios -pkg_check_node_commit = master - -PACKAGES += chronos -pkg_chronos_name = chronos -pkg_chronos_description = Timer module for Erlang that makes it easy to abstact time out of the tests. -pkg_chronos_homepage = https://github.com/lehoff/chronos -pkg_chronos_fetch = git -pkg_chronos_repo = https://github.com/lehoff/chronos -pkg_chronos_commit = master - -PACKAGES += classifier -pkg_classifier_name = classifier -pkg_classifier_description = An Erlang Bayesian Filter and Text Classifier -pkg_classifier_homepage = https://github.com/inaka/classifier -pkg_classifier_fetch = git -pkg_classifier_repo = https://github.com/inaka/classifier -pkg_classifier_commit = master - -PACKAGES += clique -pkg_clique_name = clique -pkg_clique_description = CLI Framework for Erlang -pkg_clique_homepage = https://github.com/basho/clique -pkg_clique_fetch = git -pkg_clique_repo = https://github.com/basho/clique -pkg_clique_commit = develop - -PACKAGES += cl -pkg_cl_name = cl -pkg_cl_description = OpenCL binding for Erlang -pkg_cl_homepage = https://github.com/tonyrog/cl -pkg_cl_fetch = git -pkg_cl_repo = https://github.com/tonyrog/cl -pkg_cl_commit = master - -PACKAGES += cloudi_core -pkg_cloudi_core_name = cloudi_core -pkg_cloudi_core_description = CloudI internal service runtime -pkg_cloudi_core_homepage = http://cloudi.org/ -pkg_cloudi_core_fetch = git -pkg_cloudi_core_repo = https://github.com/CloudI/cloudi_core -pkg_cloudi_core_commit = master - -PACKAGES += cloudi_service_api_requests -pkg_cloudi_service_api_requests_name = cloudi_service_api_requests -pkg_cloudi_service_api_requests_description = CloudI Service API requests (JSON-RPC/Erlang-term support) -pkg_cloudi_service_api_requests_homepage = http://cloudi.org/ -pkg_cloudi_service_api_requests_fetch = git -pkg_cloudi_service_api_requests_repo = https://github.com/CloudI/cloudi_service_api_requests -pkg_cloudi_service_api_requests_commit = master - -PACKAGES += cloudi_service_db_cassandra_cql -pkg_cloudi_service_db_cassandra_cql_name = cloudi_service_db_cassandra_cql -pkg_cloudi_service_db_cassandra_cql_description = Cassandra CQL CloudI Service -pkg_cloudi_service_db_cassandra_cql_homepage = http://cloudi.org/ -pkg_cloudi_service_db_cassandra_cql_fetch = git -pkg_cloudi_service_db_cassandra_cql_repo = https://github.com/CloudI/cloudi_service_db_cassandra_cql -pkg_cloudi_service_db_cassandra_cql_commit = master - -PACKAGES += cloudi_service_db_cassandra -pkg_cloudi_service_db_cassandra_name = cloudi_service_db_cassandra -pkg_cloudi_service_db_cassandra_description = Cassandra CloudI Service -pkg_cloudi_service_db_cassandra_homepage = http://cloudi.org/ -pkg_cloudi_service_db_cassandra_fetch = git -pkg_cloudi_service_db_cassandra_repo = https://github.com/CloudI/cloudi_service_db_cassandra -pkg_cloudi_service_db_cassandra_commit = master - -PACKAGES += cloudi_service_db_couchdb -pkg_cloudi_service_db_couchdb_name = cloudi_service_db_couchdb -pkg_cloudi_service_db_couchdb_description = CouchDB CloudI Service -pkg_cloudi_service_db_couchdb_homepage = http://cloudi.org/ -pkg_cloudi_service_db_couchdb_fetch = git -pkg_cloudi_service_db_couchdb_repo = https://github.com/CloudI/cloudi_service_db_couchdb -pkg_cloudi_service_db_couchdb_commit = master - -PACKAGES += cloudi_service_db_elasticsearch -pkg_cloudi_service_db_elasticsearch_name = cloudi_service_db_elasticsearch -pkg_cloudi_service_db_elasticsearch_description = elasticsearch CloudI Service -pkg_cloudi_service_db_elasticsearch_homepage = http://cloudi.org/ -pkg_cloudi_service_db_elasticsearch_fetch = git -pkg_cloudi_service_db_elasticsearch_repo = https://github.com/CloudI/cloudi_service_db_elasticsearch -pkg_cloudi_service_db_elasticsearch_commit = master - -PACKAGES += cloudi_service_db_memcached -pkg_cloudi_service_db_memcached_name = cloudi_service_db_memcached -pkg_cloudi_service_db_memcached_description = memcached CloudI Service -pkg_cloudi_service_db_memcached_homepage = http://cloudi.org/ -pkg_cloudi_service_db_memcached_fetch = git -pkg_cloudi_service_db_memcached_repo = https://github.com/CloudI/cloudi_service_db_memcached -pkg_cloudi_service_db_memcached_commit = master - -PACKAGES += cloudi_service_db -pkg_cloudi_service_db_name = cloudi_service_db -pkg_cloudi_service_db_description = CloudI Database (in-memory/testing/generic) -pkg_cloudi_service_db_homepage = http://cloudi.org/ -pkg_cloudi_service_db_fetch = git -pkg_cloudi_service_db_repo = https://github.com/CloudI/cloudi_service_db -pkg_cloudi_service_db_commit = master - -PACKAGES += cloudi_service_db_mysql -pkg_cloudi_service_db_mysql_name = cloudi_service_db_mysql -pkg_cloudi_service_db_mysql_description = MySQL CloudI Service -pkg_cloudi_service_db_mysql_homepage = http://cloudi.org/ -pkg_cloudi_service_db_mysql_fetch = git -pkg_cloudi_service_db_mysql_repo = https://github.com/CloudI/cloudi_service_db_mysql -pkg_cloudi_service_db_mysql_commit = master - -PACKAGES += cloudi_service_db_pgsql -pkg_cloudi_service_db_pgsql_name = cloudi_service_db_pgsql -pkg_cloudi_service_db_pgsql_description = PostgreSQL CloudI Service -pkg_cloudi_service_db_pgsql_homepage = http://cloudi.org/ -pkg_cloudi_service_db_pgsql_fetch = git -pkg_cloudi_service_db_pgsql_repo = https://github.com/CloudI/cloudi_service_db_pgsql -pkg_cloudi_service_db_pgsql_commit = master - -PACKAGES += cloudi_service_db_riak -pkg_cloudi_service_db_riak_name = cloudi_service_db_riak -pkg_cloudi_service_db_riak_description = Riak CloudI Service -pkg_cloudi_service_db_riak_homepage = http://cloudi.org/ -pkg_cloudi_service_db_riak_fetch = git -pkg_cloudi_service_db_riak_repo = https://github.com/CloudI/cloudi_service_db_riak -pkg_cloudi_service_db_riak_commit = master - -PACKAGES += cloudi_service_db_tokyotyrant -pkg_cloudi_service_db_tokyotyrant_name = cloudi_service_db_tokyotyrant -pkg_cloudi_service_db_tokyotyrant_description = Tokyo Tyrant CloudI Service -pkg_cloudi_service_db_tokyotyrant_homepage = http://cloudi.org/ -pkg_cloudi_service_db_tokyotyrant_fetch = git -pkg_cloudi_service_db_tokyotyrant_repo = https://github.com/CloudI/cloudi_service_db_tokyotyrant -pkg_cloudi_service_db_tokyotyrant_commit = master - -PACKAGES += cloudi_service_filesystem -pkg_cloudi_service_filesystem_name = cloudi_service_filesystem -pkg_cloudi_service_filesystem_description = Filesystem CloudI Service -pkg_cloudi_service_filesystem_homepage = http://cloudi.org/ -pkg_cloudi_service_filesystem_fetch = git -pkg_cloudi_service_filesystem_repo = https://github.com/CloudI/cloudi_service_filesystem -pkg_cloudi_service_filesystem_commit = master - -PACKAGES += cloudi_service_http_client -pkg_cloudi_service_http_client_name = cloudi_service_http_client -pkg_cloudi_service_http_client_description = HTTP client CloudI Service -pkg_cloudi_service_http_client_homepage = http://cloudi.org/ -pkg_cloudi_service_http_client_fetch = git -pkg_cloudi_service_http_client_repo = https://github.com/CloudI/cloudi_service_http_client -pkg_cloudi_service_http_client_commit = master - -PACKAGES += cloudi_service_http_cowboy -pkg_cloudi_service_http_cowboy_name = cloudi_service_http_cowboy -pkg_cloudi_service_http_cowboy_description = cowboy HTTP/HTTPS CloudI Service -pkg_cloudi_service_http_cowboy_homepage = http://cloudi.org/ -pkg_cloudi_service_http_cowboy_fetch = git -pkg_cloudi_service_http_cowboy_repo = https://github.com/CloudI/cloudi_service_http_cowboy -pkg_cloudi_service_http_cowboy_commit = master - -PACKAGES += cloudi_service_http_elli -pkg_cloudi_service_http_elli_name = cloudi_service_http_elli -pkg_cloudi_service_http_elli_description = elli HTTP CloudI Service -pkg_cloudi_service_http_elli_homepage = http://cloudi.org/ -pkg_cloudi_service_http_elli_fetch = git -pkg_cloudi_service_http_elli_repo = https://github.com/CloudI/cloudi_service_http_elli -pkg_cloudi_service_http_elli_commit = master - -PACKAGES += cloudi_service_map_reduce -pkg_cloudi_service_map_reduce_name = cloudi_service_map_reduce -pkg_cloudi_service_map_reduce_description = Map/Reduce CloudI Service -pkg_cloudi_service_map_reduce_homepage = http://cloudi.org/ -pkg_cloudi_service_map_reduce_fetch = git -pkg_cloudi_service_map_reduce_repo = https://github.com/CloudI/cloudi_service_map_reduce -pkg_cloudi_service_map_reduce_commit = master - -PACKAGES += cloudi_service_oauth1 -pkg_cloudi_service_oauth1_name = cloudi_service_oauth1 -pkg_cloudi_service_oauth1_description = OAuth v1.0 CloudI Service -pkg_cloudi_service_oauth1_homepage = http://cloudi.org/ -pkg_cloudi_service_oauth1_fetch = git -pkg_cloudi_service_oauth1_repo = https://github.com/CloudI/cloudi_service_oauth1 -pkg_cloudi_service_oauth1_commit = master - -PACKAGES += cloudi_service_queue -pkg_cloudi_service_queue_name = cloudi_service_queue -pkg_cloudi_service_queue_description = Persistent Queue Service -pkg_cloudi_service_queue_homepage = http://cloudi.org/ -pkg_cloudi_service_queue_fetch = git -pkg_cloudi_service_queue_repo = https://github.com/CloudI/cloudi_service_queue -pkg_cloudi_service_queue_commit = master - -PACKAGES += cloudi_service_quorum -pkg_cloudi_service_quorum_name = cloudi_service_quorum -pkg_cloudi_service_quorum_description = CloudI Quorum Service -pkg_cloudi_service_quorum_homepage = http://cloudi.org/ -pkg_cloudi_service_quorum_fetch = git -pkg_cloudi_service_quorum_repo = https://github.com/CloudI/cloudi_service_quorum -pkg_cloudi_service_quorum_commit = master - -PACKAGES += cloudi_service_router -pkg_cloudi_service_router_name = cloudi_service_router -pkg_cloudi_service_router_description = CloudI Router Service -pkg_cloudi_service_router_homepage = http://cloudi.org/ -pkg_cloudi_service_router_fetch = git -pkg_cloudi_service_router_repo = https://github.com/CloudI/cloudi_service_router -pkg_cloudi_service_router_commit = master - -PACKAGES += cloudi_service_tcp -pkg_cloudi_service_tcp_name = cloudi_service_tcp -pkg_cloudi_service_tcp_description = TCP CloudI Service -pkg_cloudi_service_tcp_homepage = http://cloudi.org/ -pkg_cloudi_service_tcp_fetch = git -pkg_cloudi_service_tcp_repo = https://github.com/CloudI/cloudi_service_tcp -pkg_cloudi_service_tcp_commit = master - -PACKAGES += cloudi_service_timers -pkg_cloudi_service_timers_name = cloudi_service_timers -pkg_cloudi_service_timers_description = Timers CloudI Service -pkg_cloudi_service_timers_homepage = http://cloudi.org/ -pkg_cloudi_service_timers_fetch = git -pkg_cloudi_service_timers_repo = https://github.com/CloudI/cloudi_service_timers -pkg_cloudi_service_timers_commit = master - -PACKAGES += cloudi_service_udp -pkg_cloudi_service_udp_name = cloudi_service_udp -pkg_cloudi_service_udp_description = UDP CloudI Service -pkg_cloudi_service_udp_homepage = http://cloudi.org/ -pkg_cloudi_service_udp_fetch = git -pkg_cloudi_service_udp_repo = https://github.com/CloudI/cloudi_service_udp -pkg_cloudi_service_udp_commit = master - -PACKAGES += cloudi_service_validate -pkg_cloudi_service_validate_name = cloudi_service_validate -pkg_cloudi_service_validate_description = CloudI Validate Service -pkg_cloudi_service_validate_homepage = http://cloudi.org/ -pkg_cloudi_service_validate_fetch = git -pkg_cloudi_service_validate_repo = https://github.com/CloudI/cloudi_service_validate -pkg_cloudi_service_validate_commit = master - -PACKAGES += cloudi_service_zeromq -pkg_cloudi_service_zeromq_name = cloudi_service_zeromq -pkg_cloudi_service_zeromq_description = ZeroMQ CloudI Service -pkg_cloudi_service_zeromq_homepage = http://cloudi.org/ -pkg_cloudi_service_zeromq_fetch = git -pkg_cloudi_service_zeromq_repo = https://github.com/CloudI/cloudi_service_zeromq -pkg_cloudi_service_zeromq_commit = master - -PACKAGES += cluster_info -pkg_cluster_info_name = cluster_info -pkg_cluster_info_description = Fork of Hibari's nifty cluster_info OTP app -pkg_cluster_info_homepage = https://github.com/basho/cluster_info -pkg_cluster_info_fetch = git -pkg_cluster_info_repo = https://github.com/basho/cluster_info -pkg_cluster_info_commit = master - -PACKAGES += color -pkg_color_name = color -pkg_color_description = ANSI colors for your Erlang -pkg_color_homepage = https://github.com/julianduque/erlang-color -pkg_color_fetch = git -pkg_color_repo = https://github.com/julianduque/erlang-color -pkg_color_commit = master - -PACKAGES += confetti -pkg_confetti_name = confetti -pkg_confetti_description = Erlang configuration provider / application:get_env/2 on steroids -pkg_confetti_homepage = https://github.com/jtendo/confetti -pkg_confetti_fetch = git -pkg_confetti_repo = https://github.com/jtendo/confetti -pkg_confetti_commit = master - -PACKAGES += couchbeam -pkg_couchbeam_name = couchbeam -pkg_couchbeam_description = Apache CouchDB client in Erlang -pkg_couchbeam_homepage = https://github.com/benoitc/couchbeam -pkg_couchbeam_fetch = git -pkg_couchbeam_repo = https://github.com/benoitc/couchbeam -pkg_couchbeam_commit = master - -PACKAGES += couch -pkg_couch_name = couch -pkg_couch_description = A embeddable document oriented database compatible with Apache CouchDB -pkg_couch_homepage = https://github.com/benoitc/opencouch -pkg_couch_fetch = git -pkg_couch_repo = https://github.com/benoitc/opencouch -pkg_couch_commit = master - -PACKAGES += covertool -pkg_covertool_name = covertool -pkg_covertool_description = Tool to convert Erlang cover data files into Cobertura XML reports -pkg_covertool_homepage = https://github.com/idubrov/covertool -pkg_covertool_fetch = git -pkg_covertool_repo = https://github.com/idubrov/covertool -pkg_covertool_commit = master - -PACKAGES += cowboy -pkg_cowboy_name = cowboy -pkg_cowboy_description = Small, fast and modular HTTP server. -pkg_cowboy_homepage = http://ninenines.eu -pkg_cowboy_fetch = git -pkg_cowboy_repo = https://github.com/ninenines/cowboy -pkg_cowboy_commit = 1.0.1 - -PACKAGES += cowdb -pkg_cowdb_name = cowdb -pkg_cowdb_description = Pure Key/Value database library for Erlang Applications -pkg_cowdb_homepage = https://github.com/refuge/cowdb -pkg_cowdb_fetch = git -pkg_cowdb_repo = https://github.com/refuge/cowdb -pkg_cowdb_commit = master - -PACKAGES += cowlib -pkg_cowlib_name = cowlib -pkg_cowlib_description = Support library for manipulating Web protocols. -pkg_cowlib_homepage = http://ninenines.eu -pkg_cowlib_fetch = git -pkg_cowlib_repo = https://github.com/ninenines/cowlib -pkg_cowlib_commit = 1.0.1 - -PACKAGES += cpg -pkg_cpg_name = cpg -pkg_cpg_description = CloudI Process Groups -pkg_cpg_homepage = https://github.com/okeuday/cpg -pkg_cpg_fetch = git -pkg_cpg_repo = https://github.com/okeuday/cpg -pkg_cpg_commit = master - -PACKAGES += cqerl -pkg_cqerl_name = cqerl -pkg_cqerl_description = Native Erlang CQL client for Cassandra -pkg_cqerl_homepage = https://matehat.github.io/cqerl/ -pkg_cqerl_fetch = git -pkg_cqerl_repo = https://github.com/matehat/cqerl -pkg_cqerl_commit = master - -PACKAGES += cr -pkg_cr_name = cr -pkg_cr_description = Chain Replication -pkg_cr_homepage = https://synrc.com/apps/cr/doc/cr.htm -pkg_cr_fetch = git -pkg_cr_repo = https://github.com/spawnproc/cr -pkg_cr_commit = master - -PACKAGES += cuttlefish -pkg_cuttlefish_name = cuttlefish -pkg_cuttlefish_description = never lose your childlike sense of wonder baby cuttlefish, promise me? -pkg_cuttlefish_homepage = https://github.com/basho/cuttlefish -pkg_cuttlefish_fetch = git -pkg_cuttlefish_repo = https://github.com/basho/cuttlefish -pkg_cuttlefish_commit = master - -PACKAGES += damocles -pkg_damocles_name = damocles -pkg_damocles_description = Erlang library for generating adversarial network conditions for QAing distributed applications/systems on a single Linux box. -pkg_damocles_homepage = https://github.com/lostcolony/damocles -pkg_damocles_fetch = git -pkg_damocles_repo = https://github.com/lostcolony/damocles -pkg_damocles_commit = master - -PACKAGES += debbie -pkg_debbie_name = debbie -pkg_debbie_description = .DEB Built In Erlang -pkg_debbie_homepage = https://github.com/crownedgrouse/debbie -pkg_debbie_fetch = git -pkg_debbie_repo = https://github.com/crownedgrouse/debbie -pkg_debbie_commit = master - -PACKAGES += decimal -pkg_decimal_name = decimal -pkg_decimal_description = An Erlang decimal arithmetic library -pkg_decimal_homepage = https://github.com/tim/erlang-decimal -pkg_decimal_fetch = git -pkg_decimal_repo = https://github.com/tim/erlang-decimal -pkg_decimal_commit = master - -PACKAGES += detergent -pkg_detergent_name = detergent -pkg_detergent_description = An emulsifying Erlang SOAP library -pkg_detergent_homepage = https://github.com/devinus/detergent -pkg_detergent_fetch = git -pkg_detergent_repo = https://github.com/devinus/detergent -pkg_detergent_commit = master - -PACKAGES += detest -pkg_detest_name = detest -pkg_detest_description = Tool for running tests on a cluster of erlang nodes -pkg_detest_homepage = https://github.com/biokoda/detest -pkg_detest_fetch = git -pkg_detest_repo = https://github.com/biokoda/detest -pkg_detest_commit = master - -PACKAGES += dh_date -pkg_dh_date_name = dh_date -pkg_dh_date_description = Date formatting / parsing library for erlang -pkg_dh_date_homepage = https://github.com/daleharvey/dh_date -pkg_dh_date_fetch = git -pkg_dh_date_repo = https://github.com/daleharvey/dh_date -pkg_dh_date_commit = master - -PACKAGES += dhtcrawler -pkg_dhtcrawler_name = dhtcrawler -pkg_dhtcrawler_description = dhtcrawler is a DHT crawler written in erlang. It can join a DHT network and crawl many P2P torrents. -pkg_dhtcrawler_homepage = https://github.com/kevinlynx/dhtcrawler -pkg_dhtcrawler_fetch = git -pkg_dhtcrawler_repo = https://github.com/kevinlynx/dhtcrawler -pkg_dhtcrawler_commit = master - -PACKAGES += dirbusterl -pkg_dirbusterl_name = dirbusterl -pkg_dirbusterl_description = DirBuster successor in Erlang -pkg_dirbusterl_homepage = https://github.com/silentsignal/DirBustErl -pkg_dirbusterl_fetch = git -pkg_dirbusterl_repo = https://github.com/silentsignal/DirBustErl -pkg_dirbusterl_commit = master - -PACKAGES += dispcount -pkg_dispcount_name = dispcount -pkg_dispcount_description = Erlang task dispatcher based on ETS counters. -pkg_dispcount_homepage = https://github.com/ferd/dispcount -pkg_dispcount_fetch = git -pkg_dispcount_repo = https://github.com/ferd/dispcount -pkg_dispcount_commit = master - -PACKAGES += dlhttpc -pkg_dlhttpc_name = dlhttpc -pkg_dlhttpc_description = dispcount-based lhttpc fork for massive amounts of requests to limited endpoints -pkg_dlhttpc_homepage = https://github.com/ferd/dlhttpc -pkg_dlhttpc_fetch = git -pkg_dlhttpc_repo = https://github.com/ferd/dlhttpc -pkg_dlhttpc_commit = master - -PACKAGES += dns -pkg_dns_name = dns -pkg_dns_description = Erlang DNS library -pkg_dns_homepage = https://github.com/aetrion/dns_erlang -pkg_dns_fetch = git -pkg_dns_repo = https://github.com/aetrion/dns_erlang -pkg_dns_commit = master - -PACKAGES += dnssd -pkg_dnssd_name = dnssd -pkg_dnssd_description = Erlang interface to Apple's Bonjour D NS Service Discovery implementation -pkg_dnssd_homepage = https://github.com/benoitc/dnssd_erlang -pkg_dnssd_fetch = git -pkg_dnssd_repo = https://github.com/benoitc/dnssd_erlang -pkg_dnssd_commit = master - -PACKAGES += dtl -pkg_dtl_name = dtl -pkg_dtl_description = Django Template Language: A full-featured port of the Django template engine to Erlang. -pkg_dtl_homepage = https://github.com/oinksoft/dtl -pkg_dtl_fetch = git -pkg_dtl_repo = https://github.com/oinksoft/dtl -pkg_dtl_commit = master - -PACKAGES += dynamic_compile -pkg_dynamic_compile_name = dynamic_compile -pkg_dynamic_compile_description = compile and load erlang modules from string input -pkg_dynamic_compile_homepage = https://github.com/jkvor/dynamic_compile -pkg_dynamic_compile_fetch = git -pkg_dynamic_compile_repo = https://github.com/jkvor/dynamic_compile -pkg_dynamic_compile_commit = master - -PACKAGES += e2 -pkg_e2_name = e2 -pkg_e2_description = Library to simply writing correct OTP applications. -pkg_e2_homepage = http://e2project.org -pkg_e2_fetch = git -pkg_e2_repo = https://github.com/gar1t/e2 -pkg_e2_commit = master - -PACKAGES += eamf -pkg_eamf_name = eamf -pkg_eamf_description = eAMF provides Action Message Format (AMF) support for Erlang -pkg_eamf_homepage = https://github.com/mrinalwadhwa/eamf -pkg_eamf_fetch = git -pkg_eamf_repo = https://github.com/mrinalwadhwa/eamf -pkg_eamf_commit = master - -PACKAGES += eavro -pkg_eavro_name = eavro -pkg_eavro_description = Apache Avro encoder/decoder -pkg_eavro_homepage = https://github.com/SIfoxDevTeam/eavro -pkg_eavro_fetch = git -pkg_eavro_repo = https://github.com/SIfoxDevTeam/eavro -pkg_eavro_commit = master - -PACKAGES += ecapnp -pkg_ecapnp_name = ecapnp -pkg_ecapnp_description = Cap'n Proto library for Erlang -pkg_ecapnp_homepage = https://github.com/kaos/ecapnp -pkg_ecapnp_fetch = git -pkg_ecapnp_repo = https://github.com/kaos/ecapnp -pkg_ecapnp_commit = master - -PACKAGES += econfig -pkg_econfig_name = econfig -pkg_econfig_description = simple Erlang config handler using INI files -pkg_econfig_homepage = https://github.com/benoitc/econfig -pkg_econfig_fetch = git -pkg_econfig_repo = https://github.com/benoitc/econfig -pkg_econfig_commit = master - -PACKAGES += edate -pkg_edate_name = edate -pkg_edate_description = date manipulation library for erlang -pkg_edate_homepage = https://github.com/dweldon/edate -pkg_edate_fetch = git -pkg_edate_repo = https://github.com/dweldon/edate -pkg_edate_commit = master - -PACKAGES += edgar -pkg_edgar_name = edgar -pkg_edgar_description = Erlang Does GNU AR -pkg_edgar_homepage = https://github.com/crownedgrouse/edgar -pkg_edgar_fetch = git -pkg_edgar_repo = https://github.com/crownedgrouse/edgar -pkg_edgar_commit = master - -PACKAGES += edis -pkg_edis_name = edis -pkg_edis_description = An Erlang implementation of Redis KV Store -pkg_edis_homepage = http://inaka.github.com/edis/ -pkg_edis_fetch = git -pkg_edis_repo = https://github.com/inaka/edis -pkg_edis_commit = master - -PACKAGES += edns -pkg_edns_name = edns -pkg_edns_description = Erlang/OTP DNS server -pkg_edns_homepage = https://github.com/hcvst/erlang-dns -pkg_edns_fetch = git -pkg_edns_repo = https://github.com/hcvst/erlang-dns -pkg_edns_commit = master - -PACKAGES += edown -pkg_edown_name = edown -pkg_edown_description = EDoc extension for generating Github-flavored Markdown -pkg_edown_homepage = https://github.com/uwiger/edown -pkg_edown_fetch = git -pkg_edown_repo = https://github.com/uwiger/edown -pkg_edown_commit = master - -PACKAGES += eep_app -pkg_eep_app_name = eep_app -pkg_eep_app_description = Embedded Event Processing -pkg_eep_app_homepage = https://github.com/darach/eep-erl -pkg_eep_app_fetch = git -pkg_eep_app_repo = https://github.com/darach/eep-erl -pkg_eep_app_commit = master - -PACKAGES += eep -pkg_eep_name = eep -pkg_eep_description = Erlang Easy Profiling (eep) application provides a way to analyze application performance and call hierarchy -pkg_eep_homepage = https://github.com/virtan/eep -pkg_eep_fetch = git -pkg_eep_repo = https://github.com/virtan/eep -pkg_eep_commit = master - -PACKAGES += efene -pkg_efene_name = efene -pkg_efene_description = Alternative syntax for the Erlang Programming Language focusing on simplicity, ease of use and programmer UX -pkg_efene_homepage = https://github.com/efene/efene -pkg_efene_fetch = git -pkg_efene_repo = https://github.com/efene/efene -pkg_efene_commit = master - -PACKAGES += eganglia -pkg_eganglia_name = eganglia -pkg_eganglia_description = Erlang library to interact with Ganglia -pkg_eganglia_homepage = https://github.com/inaka/eganglia -pkg_eganglia_fetch = git -pkg_eganglia_repo = https://github.com/inaka/eganglia -pkg_eganglia_commit = v0.9.1 - -PACKAGES += egeoip -pkg_egeoip_name = egeoip -pkg_egeoip_description = Erlang IP Geolocation module, currently supporting the MaxMind GeoLite City Database. -pkg_egeoip_homepage = https://github.com/mochi/egeoip -pkg_egeoip_fetch = git -pkg_egeoip_repo = https://github.com/mochi/egeoip -pkg_egeoip_commit = master - -PACKAGES += ehsa -pkg_ehsa_name = ehsa -pkg_ehsa_description = Erlang HTTP server basic and digest authentication modules -pkg_ehsa_homepage = https://bitbucket.org/a12n/ehsa -pkg_ehsa_fetch = hg -pkg_ehsa_repo = https://bitbucket.org/a12n/ehsa -pkg_ehsa_commit = 2.0.4 - -PACKAGES += ejabberd -pkg_ejabberd_name = ejabberd -pkg_ejabberd_description = Robust, ubiquitous and massively scalable Jabber / XMPP Instant Messaging platform -pkg_ejabberd_homepage = https://github.com/processone/ejabberd -pkg_ejabberd_fetch = git -pkg_ejabberd_repo = https://github.com/processone/ejabberd -pkg_ejabberd_commit = master - -PACKAGES += ej -pkg_ej_name = ej -pkg_ej_description = Helper module for working with Erlang terms representing JSON -pkg_ej_homepage = https://github.com/seth/ej -pkg_ej_fetch = git -pkg_ej_repo = https://github.com/seth/ej -pkg_ej_commit = master - -PACKAGES += ejwt -pkg_ejwt_name = ejwt -pkg_ejwt_description = erlang library for JSON Web Token -pkg_ejwt_homepage = https://github.com/artefactop/ejwt -pkg_ejwt_fetch = git -pkg_ejwt_repo = https://github.com/artefactop/ejwt -pkg_ejwt_commit = master - -PACKAGES += ekaf -pkg_ekaf_name = ekaf -pkg_ekaf_description = A minimal, high-performance Kafka client in Erlang. -pkg_ekaf_homepage = https://github.com/helpshift/ekaf -pkg_ekaf_fetch = git -pkg_ekaf_repo = https://github.com/helpshift/ekaf -pkg_ekaf_commit = master - -PACKAGES += elarm -pkg_elarm_name = elarm -pkg_elarm_description = Alarm Manager for Erlang. -pkg_elarm_homepage = https://github.com/esl/elarm -pkg_elarm_fetch = git -pkg_elarm_repo = https://github.com/esl/elarm -pkg_elarm_commit = master - -PACKAGES += eleveldb -pkg_eleveldb_name = eleveldb -pkg_eleveldb_description = Erlang LevelDB API -pkg_eleveldb_homepage = https://github.com/basho/eleveldb -pkg_eleveldb_fetch = git -pkg_eleveldb_repo = https://github.com/basho/eleveldb -pkg_eleveldb_commit = master - -PACKAGES += elli -pkg_elli_name = elli -pkg_elli_description = Simple, robust and performant Erlang web server -pkg_elli_homepage = https://github.com/knutin/elli -pkg_elli_fetch = git -pkg_elli_repo = https://github.com/knutin/elli -pkg_elli_commit = master - -PACKAGES += elvis -pkg_elvis_name = elvis -pkg_elvis_description = Erlang Style Reviewer -pkg_elvis_homepage = https://github.com/inaka/elvis -pkg_elvis_fetch = git -pkg_elvis_repo = https://github.com/inaka/elvis -pkg_elvis_commit = 0.2.4 - -PACKAGES += emagick -pkg_emagick_name = emagick -pkg_emagick_description = Wrapper for Graphics/ImageMagick command line tool. -pkg_emagick_homepage = https://github.com/kivra/emagick -pkg_emagick_fetch = git -pkg_emagick_repo = https://github.com/kivra/emagick -pkg_emagick_commit = master - -PACKAGES += emysql -pkg_emysql_name = emysql -pkg_emysql_description = Stable, pure Erlang MySQL driver. -pkg_emysql_homepage = https://github.com/Eonblast/Emysql -pkg_emysql_fetch = git -pkg_emysql_repo = https://github.com/Eonblast/Emysql -pkg_emysql_commit = master - -PACKAGES += enm -pkg_enm_name = enm -pkg_enm_description = Erlang driver for nanomsg -pkg_enm_homepage = https://github.com/basho/enm -pkg_enm_fetch = git -pkg_enm_repo = https://github.com/basho/enm -pkg_enm_commit = master - -PACKAGES += entop -pkg_entop_name = entop -pkg_entop_description = A top-like tool for monitoring an Erlang node -pkg_entop_homepage = https://github.com/mazenharake/entop -pkg_entop_fetch = git -pkg_entop_repo = https://github.com/mazenharake/entop -pkg_entop_commit = master - -PACKAGES += epcap -pkg_epcap_name = epcap -pkg_epcap_description = Erlang packet capture interface using pcap -pkg_epcap_homepage = https://github.com/msantos/epcap -pkg_epcap_fetch = git -pkg_epcap_repo = https://github.com/msantos/epcap -pkg_epcap_commit = master - -PACKAGES += eper -pkg_eper_name = eper -pkg_eper_description = Erlang performance and debugging tools. -pkg_eper_homepage = https://github.com/massemanet/eper -pkg_eper_fetch = git -pkg_eper_repo = https://github.com/massemanet/eper -pkg_eper_commit = master - -PACKAGES += epgsql -pkg_epgsql_name = epgsql -pkg_epgsql_description = Erlang PostgreSQL client library. -pkg_epgsql_homepage = https://github.com/epgsql/epgsql -pkg_epgsql_fetch = git -pkg_epgsql_repo = https://github.com/epgsql/epgsql -pkg_epgsql_commit = master - -PACKAGES += episcina -pkg_episcina_name = episcina -pkg_episcina_description = A simple non intrusive resource pool for connections -pkg_episcina_homepage = https://github.com/erlware/episcina -pkg_episcina_fetch = git -pkg_episcina_repo = https://github.com/erlware/episcina -pkg_episcina_commit = master - -PACKAGES += eplot -pkg_eplot_name = eplot -pkg_eplot_description = A plot engine written in erlang. -pkg_eplot_homepage = https://github.com/psyeugenic/eplot -pkg_eplot_fetch = git -pkg_eplot_repo = https://github.com/psyeugenic/eplot -pkg_eplot_commit = master - -PACKAGES += epocxy -pkg_epocxy_name = epocxy -pkg_epocxy_description = Erlang Patterns of Concurrency -pkg_epocxy_homepage = https://github.com/duomark/epocxy -pkg_epocxy_fetch = git -pkg_epocxy_repo = https://github.com/duomark/epocxy -pkg_epocxy_commit = master - -PACKAGES += epubnub -pkg_epubnub_name = epubnub -pkg_epubnub_description = Erlang PubNub API -pkg_epubnub_homepage = https://github.com/tsloughter/epubnub -pkg_epubnub_fetch = git -pkg_epubnub_repo = https://github.com/tsloughter/epubnub -pkg_epubnub_commit = master - -PACKAGES += eqm -pkg_eqm_name = eqm -pkg_eqm_description = Erlang pub sub with supply-demand channels -pkg_eqm_homepage = https://github.com/loucash/eqm -pkg_eqm_fetch = git -pkg_eqm_repo = https://github.com/loucash/eqm -pkg_eqm_commit = master - -PACKAGES += eredis -pkg_eredis_name = eredis -pkg_eredis_description = Erlang Redis client -pkg_eredis_homepage = https://github.com/wooga/eredis -pkg_eredis_fetch = git -pkg_eredis_repo = https://github.com/wooga/eredis -pkg_eredis_commit = master - -PACKAGES += eredis_pool -pkg_eredis_pool_name = eredis_pool -pkg_eredis_pool_description = eredis_pool is Pool of Redis clients, using eredis and poolboy. -pkg_eredis_pool_homepage = https://github.com/hiroeorz/eredis_pool -pkg_eredis_pool_fetch = git -pkg_eredis_pool_repo = https://github.com/hiroeorz/eredis_pool -pkg_eredis_pool_commit = master - -PACKAGES += erlang_cep -pkg_erlang_cep_name = erlang_cep -pkg_erlang_cep_description = A basic CEP package written in erlang -pkg_erlang_cep_homepage = https://github.com/danmacklin/erlang_cep -pkg_erlang_cep_fetch = git -pkg_erlang_cep_repo = https://github.com/danmacklin/erlang_cep -pkg_erlang_cep_commit = master - -PACKAGES += erlang_js -pkg_erlang_js_name = erlang_js -pkg_erlang_js_description = A linked-in driver for Erlang to Mozilla's Spidermonkey Javascript runtime. -pkg_erlang_js_homepage = https://github.com/basho/erlang_js -pkg_erlang_js_fetch = git -pkg_erlang_js_repo = https://github.com/basho/erlang_js -pkg_erlang_js_commit = master - -PACKAGES += erlang_localtime -pkg_erlang_localtime_name = erlang_localtime -pkg_erlang_localtime_description = Erlang library for conversion from one local time to another -pkg_erlang_localtime_homepage = https://github.com/dmitryme/erlang_localtime -pkg_erlang_localtime_fetch = git -pkg_erlang_localtime_repo = https://github.com/dmitryme/erlang_localtime -pkg_erlang_localtime_commit = master - -PACKAGES += erlang_smtp -pkg_erlang_smtp_name = erlang_smtp -pkg_erlang_smtp_description = Erlang SMTP and POP3 server code. -pkg_erlang_smtp_homepage = https://github.com/tonyg/erlang-smtp -pkg_erlang_smtp_fetch = git -pkg_erlang_smtp_repo = https://github.com/tonyg/erlang-smtp -pkg_erlang_smtp_commit = master - -PACKAGES += erlang_term -pkg_erlang_term_name = erlang_term -pkg_erlang_term_description = Erlang Term Info -pkg_erlang_term_homepage = https://github.com/okeuday/erlang_term -pkg_erlang_term_fetch = git -pkg_erlang_term_repo = https://github.com/okeuday/erlang_term -pkg_erlang_term_commit = master - -PACKAGES += erlastic_search -pkg_erlastic_search_name = erlastic_search -pkg_erlastic_search_description = An Erlang app for communicating with Elastic Search's rest interface. -pkg_erlastic_search_homepage = https://github.com/tsloughter/erlastic_search -pkg_erlastic_search_fetch = git -pkg_erlastic_search_repo = https://github.com/tsloughter/erlastic_search -pkg_erlastic_search_commit = master - -PACKAGES += erlasticsearch -pkg_erlasticsearch_name = erlasticsearch -pkg_erlasticsearch_description = Erlang thrift interface to elastic_search -pkg_erlasticsearch_homepage = https://github.com/dieswaytoofast/erlasticsearch -pkg_erlasticsearch_fetch = git -pkg_erlasticsearch_repo = https://github.com/dieswaytoofast/erlasticsearch -pkg_erlasticsearch_commit = master - -PACKAGES += erlbrake -pkg_erlbrake_name = erlbrake -pkg_erlbrake_description = Erlang Airbrake notification client -pkg_erlbrake_homepage = https://github.com/kenpratt/erlbrake -pkg_erlbrake_fetch = git -pkg_erlbrake_repo = https://github.com/kenpratt/erlbrake -pkg_erlbrake_commit = master - -PACKAGES += erlcloud -pkg_erlcloud_name = erlcloud -pkg_erlcloud_description = Cloud Computing library for erlang (Amazon EC2, S3, SQS, SimpleDB, Mechanical Turk, ELB) -pkg_erlcloud_homepage = https://github.com/gleber/erlcloud -pkg_erlcloud_fetch = git -pkg_erlcloud_repo = https://github.com/gleber/erlcloud -pkg_erlcloud_commit = master - -PACKAGES += erlcron -pkg_erlcron_name = erlcron -pkg_erlcron_description = Erlang cronish system -pkg_erlcron_homepage = https://github.com/erlware/erlcron -pkg_erlcron_fetch = git -pkg_erlcron_repo = https://github.com/erlware/erlcron -pkg_erlcron_commit = master - -PACKAGES += erldb -pkg_erldb_name = erldb -pkg_erldb_description = ORM (Object-relational mapping) application implemented in Erlang -pkg_erldb_homepage = http://erldb.org -pkg_erldb_fetch = git -pkg_erldb_repo = https://github.com/erldb/erldb -pkg_erldb_commit = master - -PACKAGES += erldis -pkg_erldis_name = erldis -pkg_erldis_description = redis erlang client library -pkg_erldis_homepage = https://github.com/cstar/erldis -pkg_erldis_fetch = git -pkg_erldis_repo = https://github.com/cstar/erldis -pkg_erldis_commit = master - -PACKAGES += erldns -pkg_erldns_name = erldns -pkg_erldns_description = DNS server, in erlang. -pkg_erldns_homepage = https://github.com/aetrion/erl-dns -pkg_erldns_fetch = git -pkg_erldns_repo = https://github.com/aetrion/erl-dns -pkg_erldns_commit = master - -PACKAGES += erldocker -pkg_erldocker_name = erldocker -pkg_erldocker_description = Docker Remote API client for Erlang -pkg_erldocker_homepage = https://github.com/proger/erldocker -pkg_erldocker_fetch = git -pkg_erldocker_repo = https://github.com/proger/erldocker -pkg_erldocker_commit = master - -PACKAGES += erlfsmon -pkg_erlfsmon_name = erlfsmon -pkg_erlfsmon_description = Erlang filesystem event watcher for Linux and OSX -pkg_erlfsmon_homepage = https://github.com/proger/erlfsmon -pkg_erlfsmon_fetch = git -pkg_erlfsmon_repo = https://github.com/proger/erlfsmon -pkg_erlfsmon_commit = master - -PACKAGES += erlgit -pkg_erlgit_name = erlgit -pkg_erlgit_description = Erlang convenience wrapper around git executable -pkg_erlgit_homepage = https://github.com/gleber/erlgit -pkg_erlgit_fetch = git -pkg_erlgit_repo = https://github.com/gleber/erlgit -pkg_erlgit_commit = master - -PACKAGES += erlguten -pkg_erlguten_name = erlguten -pkg_erlguten_description = ErlGuten is a system for high-quality typesetting, written purely in Erlang. -pkg_erlguten_homepage = https://github.com/richcarl/erlguten -pkg_erlguten_fetch = git -pkg_erlguten_repo = https://github.com/richcarl/erlguten -pkg_erlguten_commit = master - -PACKAGES += erlmc -pkg_erlmc_name = erlmc -pkg_erlmc_description = Erlang memcached binary protocol client -pkg_erlmc_homepage = https://github.com/jkvor/erlmc -pkg_erlmc_fetch = git -pkg_erlmc_repo = https://github.com/jkvor/erlmc -pkg_erlmc_commit = master - -PACKAGES += erlmongo -pkg_erlmongo_name = erlmongo -pkg_erlmongo_description = Record based Erlang driver for MongoDB with gridfs support -pkg_erlmongo_homepage = https://github.com/SergejJurecko/erlmongo -pkg_erlmongo_fetch = git -pkg_erlmongo_repo = https://github.com/SergejJurecko/erlmongo -pkg_erlmongo_commit = master - -PACKAGES += erlog -pkg_erlog_name = erlog -pkg_erlog_description = Prolog interpreter in and for Erlang -pkg_erlog_homepage = https://github.com/rvirding/erlog -pkg_erlog_fetch = git -pkg_erlog_repo = https://github.com/rvirding/erlog -pkg_erlog_commit = master - -PACKAGES += erlpass -pkg_erlpass_name = erlpass -pkg_erlpass_description = A library to handle password hashing and changing in a safe manner, independent from any kind of storage whatsoever. -pkg_erlpass_homepage = https://github.com/ferd/erlpass -pkg_erlpass_fetch = git -pkg_erlpass_repo = https://github.com/ferd/erlpass -pkg_erlpass_commit = master - -PACKAGES += erlport -pkg_erlport_name = erlport -pkg_erlport_description = ErlPort - connect Erlang to other languages -pkg_erlport_homepage = https://github.com/hdima/erlport -pkg_erlport_fetch = git -pkg_erlport_repo = https://github.com/hdima/erlport -pkg_erlport_commit = master - -PACKAGES += erlsha2 -pkg_erlsha2_name = erlsha2 -pkg_erlsha2_description = SHA-224, SHA-256, SHA-384, SHA-512 implemented in Erlang NIFs. -pkg_erlsha2_homepage = https://github.com/vinoski/erlsha2 -pkg_erlsha2_fetch = git -pkg_erlsha2_repo = https://github.com/vinoski/erlsha2 -pkg_erlsha2_commit = master - -PACKAGES += erlsh -pkg_erlsh_name = erlsh -pkg_erlsh_description = Erlang shell tools -pkg_erlsh_homepage = https://github.com/proger/erlsh -pkg_erlsh_fetch = git -pkg_erlsh_repo = https://github.com/proger/erlsh -pkg_erlsh_commit = master - -PACKAGES += erlsom -pkg_erlsom_name = erlsom -pkg_erlsom_description = XML parser for Erlang -pkg_erlsom_homepage = https://github.com/willemdj/erlsom -pkg_erlsom_fetch = git -pkg_erlsom_repo = https://github.com/willemdj/erlsom -pkg_erlsom_commit = master - -PACKAGES += erl_streams -pkg_erl_streams_name = erl_streams -pkg_erl_streams_description = Streams in Erlang -pkg_erl_streams_homepage = https://github.com/epappas/erl_streams -pkg_erl_streams_fetch = git -pkg_erl_streams_repo = https://github.com/epappas/erl_streams -pkg_erl_streams_commit = master - -PACKAGES += erlubi -pkg_erlubi_name = erlubi -pkg_erlubi_description = Ubigraph Erlang Client (and Process Visualizer) -pkg_erlubi_homepage = https://github.com/krestenkrab/erlubi -pkg_erlubi_fetch = git -pkg_erlubi_repo = https://github.com/krestenkrab/erlubi -pkg_erlubi_commit = master - -PACKAGES += erlvolt -pkg_erlvolt_name = erlvolt -pkg_erlvolt_description = VoltDB Erlang Client Driver -pkg_erlvolt_homepage = https://github.com/VoltDB/voltdb-client-erlang -pkg_erlvolt_fetch = git -pkg_erlvolt_repo = https://github.com/VoltDB/voltdb-client-erlang -pkg_erlvolt_commit = master - -PACKAGES += erlware_commons -pkg_erlware_commons_name = erlware_commons -pkg_erlware_commons_description = Erlware Commons is an Erlware project focused on all aspects of reusable Erlang components. -pkg_erlware_commons_homepage = https://github.com/erlware/erlware_commons -pkg_erlware_commons_fetch = git -pkg_erlware_commons_repo = https://github.com/erlware/erlware_commons -pkg_erlware_commons_commit = master - -PACKAGES += erlydtl -pkg_erlydtl_name = erlydtl -pkg_erlydtl_description = Django Template Language for Erlang. -pkg_erlydtl_homepage = https://github.com/erlydtl/erlydtl -pkg_erlydtl_fetch = git -pkg_erlydtl_repo = https://github.com/erlydtl/erlydtl -pkg_erlydtl_commit = master - -PACKAGES += errd -pkg_errd_name = errd -pkg_errd_description = Erlang RRDTool library -pkg_errd_homepage = https://github.com/archaelus/errd -pkg_errd_fetch = git -pkg_errd_repo = https://github.com/archaelus/errd -pkg_errd_commit = master - -PACKAGES += erserve -pkg_erserve_name = erserve -pkg_erserve_description = Erlang/Rserve communication interface -pkg_erserve_homepage = https://github.com/del/erserve -pkg_erserve_fetch = git -pkg_erserve_repo = https://github.com/del/erserve -pkg_erserve_commit = master - -PACKAGES += erwa -pkg_erwa_name = erwa -pkg_erwa_description = A WAMP router and client written in Erlang. -pkg_erwa_homepage = https://github.com/bwegh/erwa -pkg_erwa_fetch = git -pkg_erwa_repo = https://github.com/bwegh/erwa -pkg_erwa_commit = 0.1.1 - -PACKAGES += espec -pkg_espec_name = espec -pkg_espec_description = ESpec: Behaviour driven development framework for Erlang -pkg_espec_homepage = https://github.com/lucaspiller/espec -pkg_espec_fetch = git -pkg_espec_repo = https://github.com/lucaspiller/espec -pkg_espec_commit = master - -PACKAGES += estatsd -pkg_estatsd_name = estatsd -pkg_estatsd_description = Erlang stats aggregation app that periodically flushes data to graphite -pkg_estatsd_homepage = https://github.com/RJ/estatsd -pkg_estatsd_fetch = git -pkg_estatsd_repo = https://github.com/RJ/estatsd -pkg_estatsd_commit = master - -PACKAGES += etap -pkg_etap_name = etap -pkg_etap_description = etap is a simple erlang testing library that provides TAP compliant output. -pkg_etap_homepage = https://github.com/ngerakines/etap -pkg_etap_fetch = git -pkg_etap_repo = https://github.com/ngerakines/etap -pkg_etap_commit = master - -PACKAGES += etest_http -pkg_etest_http_name = etest_http -pkg_etest_http_description = etest Assertions around HTTP (client-side) -pkg_etest_http_homepage = https://github.com/wooga/etest_http -pkg_etest_http_fetch = git -pkg_etest_http_repo = https://github.com/wooga/etest_http -pkg_etest_http_commit = master - -PACKAGES += etest -pkg_etest_name = etest -pkg_etest_description = A lightweight, convention over configuration test framework for Erlang -pkg_etest_homepage = https://github.com/wooga/etest -pkg_etest_fetch = git -pkg_etest_repo = https://github.com/wooga/etest -pkg_etest_commit = master - -PACKAGES += etoml -pkg_etoml_name = etoml -pkg_etoml_description = TOML language erlang parser -pkg_etoml_homepage = https://github.com/kalta/etoml -pkg_etoml_fetch = git -pkg_etoml_repo = https://github.com/kalta/etoml -pkg_etoml_commit = master - -PACKAGES += eunit_formatters -pkg_eunit_formatters_name = eunit_formatters -pkg_eunit_formatters_description = Because eunit's output sucks. Let's make it better. -pkg_eunit_formatters_homepage = https://github.com/seancribbs/eunit_formatters -pkg_eunit_formatters_fetch = git -pkg_eunit_formatters_repo = https://github.com/seancribbs/eunit_formatters -pkg_eunit_formatters_commit = master - -PACKAGES += eunit -pkg_eunit_name = eunit -pkg_eunit_description = The EUnit lightweight unit testing framework for Erlang - this is the canonical development repository. -pkg_eunit_homepage = https://github.com/richcarl/eunit -pkg_eunit_fetch = git -pkg_eunit_repo = https://github.com/richcarl/eunit -pkg_eunit_commit = master - -PACKAGES += euthanasia -pkg_euthanasia_name = euthanasia -pkg_euthanasia_description = Merciful killer for your Erlang processes -pkg_euthanasia_homepage = https://github.com/doubleyou/euthanasia -pkg_euthanasia_fetch = git -pkg_euthanasia_repo = https://github.com/doubleyou/euthanasia -pkg_euthanasia_commit = master - -PACKAGES += evum -pkg_evum_name = evum -pkg_evum_description = Spawn Linux VMs as Erlang processes in the Erlang VM -pkg_evum_homepage = https://github.com/msantos/evum -pkg_evum_fetch = git -pkg_evum_repo = https://github.com/msantos/evum -pkg_evum_commit = master - -PACKAGES += exec -pkg_exec_name = exec -pkg_exec_description = Execute and control OS processes from Erlang/OTP. -pkg_exec_homepage = http://saleyn.github.com/erlexec -pkg_exec_fetch = git -pkg_exec_repo = https://github.com/saleyn/erlexec -pkg_exec_commit = master - -PACKAGES += exml -pkg_exml_name = exml -pkg_exml_description = XML parsing library in Erlang -pkg_exml_homepage = https://github.com/paulgray/exml -pkg_exml_fetch = git -pkg_exml_repo = https://github.com/paulgray/exml -pkg_exml_commit = master - -PACKAGES += exometer -pkg_exometer_name = exometer -pkg_exometer_description = Basic measurement objects and probe behavior -pkg_exometer_homepage = https://github.com/Feuerlabs/exometer -pkg_exometer_fetch = git -pkg_exometer_repo = https://github.com/Feuerlabs/exometer -pkg_exometer_commit = 1.2 - -PACKAGES += exs1024 -pkg_exs1024_name = exs1024 -pkg_exs1024_description = Xorshift1024star pseudo random number generator for Erlang. -pkg_exs1024_homepage = https://github.com/jj1bdx/exs1024 -pkg_exs1024_fetch = git -pkg_exs1024_repo = https://github.com/jj1bdx/exs1024 -pkg_exs1024_commit = master - -PACKAGES += exs64 -pkg_exs64_name = exs64 -pkg_exs64_description = Xorshift64star pseudo random number generator for Erlang. -pkg_exs64_homepage = https://github.com/jj1bdx/exs64 -pkg_exs64_fetch = git -pkg_exs64_repo = https://github.com/jj1bdx/exs64 -pkg_exs64_commit = master - -PACKAGES += exsplus116 -pkg_exsplus116_name = exsplus116 -pkg_exsplus116_description = Xorshift116plus for Erlang -pkg_exsplus116_homepage = https://github.com/jj1bdx/exsplus116 -pkg_exsplus116_fetch = git -pkg_exsplus116_repo = https://github.com/jj1bdx/exsplus116 -pkg_exsplus116_commit = master - -PACKAGES += exsplus128 -pkg_exsplus128_name = exsplus128 -pkg_exsplus128_description = Xorshift128plus pseudo random number generator for Erlang. -pkg_exsplus128_homepage = https://github.com/jj1bdx/exsplus128 -pkg_exsplus128_fetch = git -pkg_exsplus128_repo = https://github.com/jj1bdx/exsplus128 -pkg_exsplus128_commit = master - -PACKAGES += ezmq -pkg_ezmq_name = ezmq -pkg_ezmq_description = zMQ implemented in Erlang -pkg_ezmq_homepage = https://github.com/RoadRunnr/ezmq -pkg_ezmq_fetch = git -pkg_ezmq_repo = https://github.com/RoadRunnr/ezmq -pkg_ezmq_commit = master - -PACKAGES += ezmtp -pkg_ezmtp_name = ezmtp -pkg_ezmtp_description = ZMTP protocol in pure Erlang. -pkg_ezmtp_homepage = https://github.com/a13x/ezmtp -pkg_ezmtp_fetch = git -pkg_ezmtp_repo = https://github.com/a13x/ezmtp -pkg_ezmtp_commit = master - -PACKAGES += fast_disk_log -pkg_fast_disk_log_name = fast_disk_log -pkg_fast_disk_log_description = Pool-based asynchronous Erlang disk logger -pkg_fast_disk_log_homepage = https://github.com/lpgauth/fast_disk_log -pkg_fast_disk_log_fetch = git -pkg_fast_disk_log_repo = https://github.com/lpgauth/fast_disk_log -pkg_fast_disk_log_commit = master - -PACKAGES += feeder -pkg_feeder_name = feeder -pkg_feeder_description = Stream parse RSS and Atom formatted XML feeds. -pkg_feeder_homepage = https://github.com/michaelnisi/feeder -pkg_feeder_fetch = git -pkg_feeder_repo = https://github.com/michaelnisi/feeder -pkg_feeder_commit = v1.4.6 - -PACKAGES += fix -pkg_fix_name = fix -pkg_fix_description = http://fixprotocol.org/ implementation. -pkg_fix_homepage = https://github.com/maxlapshin/fix -pkg_fix_fetch = git -pkg_fix_repo = https://github.com/maxlapshin/fix -pkg_fix_commit = master - -PACKAGES += flower -pkg_flower_name = flower -pkg_flower_description = FlowER - a Erlang OpenFlow development platform -pkg_flower_homepage = https://github.com/travelping/flower -pkg_flower_fetch = git -pkg_flower_repo = https://github.com/travelping/flower -pkg_flower_commit = master - -PACKAGES += fn -pkg_fn_name = fn -pkg_fn_description = Function utilities for Erlang -pkg_fn_homepage = https://github.com/reiddraper/fn -pkg_fn_fetch = git -pkg_fn_repo = https://github.com/reiddraper/fn -pkg_fn_commit = master - -PACKAGES += folsom_cowboy -pkg_folsom_cowboy_name = folsom_cowboy -pkg_folsom_cowboy_description = A Cowboy based Folsom HTTP Wrapper. -pkg_folsom_cowboy_homepage = https://github.com/boundary/folsom_cowboy -pkg_folsom_cowboy_fetch = git -pkg_folsom_cowboy_repo = https://github.com/boundary/folsom_cowboy -pkg_folsom_cowboy_commit = master - -PACKAGES += folsomite -pkg_folsomite_name = folsomite -pkg_folsomite_description = blow up your graphite / riemann server with folsom metrics -pkg_folsomite_homepage = https://github.com/campanja/folsomite -pkg_folsomite_fetch = git -pkg_folsomite_repo = https://github.com/campanja/folsomite -pkg_folsomite_commit = master - -PACKAGES += folsom -pkg_folsom_name = folsom -pkg_folsom_description = Expose Erlang Events and Metrics -pkg_folsom_homepage = https://github.com/boundary/folsom -pkg_folsom_fetch = git -pkg_folsom_repo = https://github.com/boundary/folsom -pkg_folsom_commit = master - -PACKAGES += fs -pkg_fs_name = fs -pkg_fs_description = Erlang FileSystem Listener -pkg_fs_homepage = https://github.com/synrc/fs -pkg_fs_fetch = git -pkg_fs_repo = https://github.com/synrc/fs -pkg_fs_commit = master - -PACKAGES += fuse -pkg_fuse_name = fuse -pkg_fuse_description = A Circuit Breaker for Erlang -pkg_fuse_homepage = https://github.com/jlouis/fuse -pkg_fuse_fetch = git -pkg_fuse_repo = https://github.com/jlouis/fuse -pkg_fuse_commit = master - -PACKAGES += gcm -pkg_gcm_name = gcm -pkg_gcm_description = An Erlang application for Google Cloud Messaging -pkg_gcm_homepage = https://github.com/pdincau/gcm-erlang -pkg_gcm_fetch = git -pkg_gcm_repo = https://github.com/pdincau/gcm-erlang -pkg_gcm_commit = master - -PACKAGES += gcprof -pkg_gcprof_name = gcprof -pkg_gcprof_description = Garbage Collection profiler for Erlang -pkg_gcprof_homepage = https://github.com/knutin/gcprof -pkg_gcprof_fetch = git -pkg_gcprof_repo = https://github.com/knutin/gcprof -pkg_gcprof_commit = master - -PACKAGES += geas -pkg_geas_name = geas -pkg_geas_description = Guess Erlang Application Scattering -pkg_geas_homepage = https://github.com/crownedgrouse/geas -pkg_geas_fetch = git -pkg_geas_repo = https://github.com/crownedgrouse/geas -pkg_geas_commit = master - -PACKAGES += geef -pkg_geef_name = geef -pkg_geef_description = Git NEEEEF (Erlang NIF) -pkg_geef_homepage = https://github.com/carlosmn/geef -pkg_geef_fetch = git -pkg_geef_repo = https://github.com/carlosmn/geef -pkg_geef_commit = master - -PACKAGES += gen_cycle -pkg_gen_cycle_name = gen_cycle -pkg_gen_cycle_description = Simple, generic OTP behaviour for recurring tasks -pkg_gen_cycle_homepage = https://github.com/aerosol/gen_cycle -pkg_gen_cycle_fetch = git -pkg_gen_cycle_repo = https://github.com/aerosol/gen_cycle -pkg_gen_cycle_commit = develop - -PACKAGES += gen_icmp -pkg_gen_icmp_name = gen_icmp -pkg_gen_icmp_description = Erlang interface to ICMP sockets -pkg_gen_icmp_homepage = https://github.com/msantos/gen_icmp -pkg_gen_icmp_fetch = git -pkg_gen_icmp_repo = https://github.com/msantos/gen_icmp -pkg_gen_icmp_commit = master - -PACKAGES += gen_nb_server -pkg_gen_nb_server_name = gen_nb_server -pkg_gen_nb_server_description = OTP behavior for writing non-blocking servers -pkg_gen_nb_server_homepage = https://github.com/kevsmith/gen_nb_server -pkg_gen_nb_server_fetch = git -pkg_gen_nb_server_repo = https://github.com/kevsmith/gen_nb_server -pkg_gen_nb_server_commit = master - -PACKAGES += gen_paxos -pkg_gen_paxos_name = gen_paxos -pkg_gen_paxos_description = An Erlang/OTP-style implementation of the PAXOS distributed consensus protocol -pkg_gen_paxos_homepage = https://github.com/gburd/gen_paxos -pkg_gen_paxos_fetch = git -pkg_gen_paxos_repo = https://github.com/gburd/gen_paxos -pkg_gen_paxos_commit = master - -PACKAGES += gen_smtp -pkg_gen_smtp_name = gen_smtp -pkg_gen_smtp_description = A generic Erlang SMTP server and client that can be extended via callback modules -pkg_gen_smtp_homepage = https://github.com/Vagabond/gen_smtp -pkg_gen_smtp_fetch = git -pkg_gen_smtp_repo = https://github.com/Vagabond/gen_smtp -pkg_gen_smtp_commit = master - -PACKAGES += gen_tracker -pkg_gen_tracker_name = gen_tracker -pkg_gen_tracker_description = supervisor with ets handling of children and their metadata -pkg_gen_tracker_homepage = https://github.com/erlyvideo/gen_tracker -pkg_gen_tracker_fetch = git -pkg_gen_tracker_repo = https://github.com/erlyvideo/gen_tracker -pkg_gen_tracker_commit = master - -PACKAGES += gen_unix -pkg_gen_unix_name = gen_unix -pkg_gen_unix_description = Erlang Unix socket interface -pkg_gen_unix_homepage = https://github.com/msantos/gen_unix -pkg_gen_unix_fetch = git -pkg_gen_unix_repo = https://github.com/msantos/gen_unix -pkg_gen_unix_commit = master - -PACKAGES += getopt -pkg_getopt_name = getopt -pkg_getopt_description = Module to parse command line arguments using the GNU getopt syntax -pkg_getopt_homepage = https://github.com/jcomellas/getopt -pkg_getopt_fetch = git -pkg_getopt_repo = https://github.com/jcomellas/getopt -pkg_getopt_commit = master - -PACKAGES += gettext -pkg_gettext_name = gettext -pkg_gettext_description = Erlang internationalization library. -pkg_gettext_homepage = https://github.com/etnt/gettext -pkg_gettext_fetch = git -pkg_gettext_repo = https://github.com/etnt/gettext -pkg_gettext_commit = master - -PACKAGES += giallo -pkg_giallo_name = giallo -pkg_giallo_description = Small and flexible web framework on top of Cowboy -pkg_giallo_homepage = https://github.com/kivra/giallo -pkg_giallo_fetch = git -pkg_giallo_repo = https://github.com/kivra/giallo -pkg_giallo_commit = master - -PACKAGES += gin -pkg_gin_name = gin -pkg_gin_description = The guards and for Erlang parse_transform -pkg_gin_homepage = https://github.com/mad-cocktail/gin -pkg_gin_fetch = git -pkg_gin_repo = https://github.com/mad-cocktail/gin -pkg_gin_commit = master - -PACKAGES += gitty -pkg_gitty_name = gitty -pkg_gitty_description = Git access in erlang -pkg_gitty_homepage = https://github.com/maxlapshin/gitty -pkg_gitty_fetch = git -pkg_gitty_repo = https://github.com/maxlapshin/gitty -pkg_gitty_commit = master - -PACKAGES += gold_fever -pkg_gold_fever_name = gold_fever -pkg_gold_fever_description = A Treasure Hunt for Erlangers -pkg_gold_fever_homepage = https://github.com/inaka/gold_fever -pkg_gold_fever_fetch = git -pkg_gold_fever_repo = https://github.com/inaka/gold_fever -pkg_gold_fever_commit = master - -PACKAGES += gossiperl -pkg_gossiperl_name = gossiperl -pkg_gossiperl_description = Gossip middleware in Erlang -pkg_gossiperl_homepage = http://gossiperl.com/ -pkg_gossiperl_fetch = git -pkg_gossiperl_repo = https://github.com/gossiperl/gossiperl -pkg_gossiperl_commit = master - -PACKAGES += gpb -pkg_gpb_name = gpb -pkg_gpb_description = A Google Protobuf implementation for Erlang -pkg_gpb_homepage = https://github.com/tomas-abrahamsson/gpb -pkg_gpb_fetch = git -pkg_gpb_repo = https://github.com/tomas-abrahamsson/gpb -pkg_gpb_commit = master - -PACKAGES += gproc -pkg_gproc_name = gproc -pkg_gproc_description = Extended process registry for Erlang -pkg_gproc_homepage = https://github.com/uwiger/gproc -pkg_gproc_fetch = git -pkg_gproc_repo = https://github.com/uwiger/gproc -pkg_gproc_commit = master - -PACKAGES += grapherl -pkg_grapherl_name = grapherl -pkg_grapherl_description = Create graphs of Erlang systems and programs -pkg_grapherl_homepage = https://github.com/eproxus/grapherl -pkg_grapherl_fetch = git -pkg_grapherl_repo = https://github.com/eproxus/grapherl -pkg_grapherl_commit = master - -PACKAGES += gun -pkg_gun_name = gun -pkg_gun_description = Asynchronous SPDY, HTTP and Websocket client written in Erlang. -pkg_gun_homepage = http//ninenines.eu -pkg_gun_fetch = git -pkg_gun_repo = https://github.com/ninenines/gun -pkg_gun_commit = master - -PACKAGES += gut -pkg_gut_name = gut -pkg_gut_description = gut is a template printing, aka scaffolding, tool for Erlang. Like rails generate or yeoman -pkg_gut_homepage = https://github.com/unbalancedparentheses/gut -pkg_gut_fetch = git -pkg_gut_repo = https://github.com/unbalancedparentheses/gut -pkg_gut_commit = master - -PACKAGES += hackney -pkg_hackney_name = hackney -pkg_hackney_description = simple HTTP client in Erlang -pkg_hackney_homepage = https://github.com/benoitc/hackney -pkg_hackney_fetch = git -pkg_hackney_repo = https://github.com/benoitc/hackney -pkg_hackney_commit = master - -PACKAGES += hamcrest -pkg_hamcrest_name = hamcrest -pkg_hamcrest_description = Erlang port of Hamcrest -pkg_hamcrest_homepage = https://github.com/hyperthunk/hamcrest-erlang -pkg_hamcrest_fetch = git -pkg_hamcrest_repo = https://github.com/hyperthunk/hamcrest-erlang -pkg_hamcrest_commit = master - -PACKAGES += hanoidb -pkg_hanoidb_name = hanoidb -pkg_hanoidb_description = Erlang LSM BTree Storage -pkg_hanoidb_homepage = https://github.com/krestenkrab/hanoidb -pkg_hanoidb_fetch = git -pkg_hanoidb_repo = https://github.com/krestenkrab/hanoidb -pkg_hanoidb_commit = master - -PACKAGES += hottub -pkg_hottub_name = hottub -pkg_hottub_description = Permanent Erlang Worker Pool -pkg_hottub_homepage = https://github.com/bfrog/hottub -pkg_hottub_fetch = git -pkg_hottub_repo = https://github.com/bfrog/hottub -pkg_hottub_commit = master - -PACKAGES += hpack -pkg_hpack_name = hpack -pkg_hpack_description = HPACK Implementation for Erlang -pkg_hpack_homepage = https://github.com/joedevivo/hpack -pkg_hpack_fetch = git -pkg_hpack_repo = https://github.com/joedevivo/hpack -pkg_hpack_commit = master - -PACKAGES += hyper -pkg_hyper_name = hyper -pkg_hyper_description = Erlang implementation of HyperLogLog -pkg_hyper_homepage = https://github.com/GameAnalytics/hyper -pkg_hyper_fetch = git -pkg_hyper_repo = https://github.com/GameAnalytics/hyper -pkg_hyper_commit = master - -PACKAGES += ibrowse -pkg_ibrowse_name = ibrowse -pkg_ibrowse_description = Erlang HTTP client -pkg_ibrowse_homepage = https://github.com/cmullaparthi/ibrowse -pkg_ibrowse_fetch = git -pkg_ibrowse_repo = https://github.com/cmullaparthi/ibrowse -pkg_ibrowse_commit = v4.1.1 - -PACKAGES += ierlang -pkg_ierlang_name = ierlang -pkg_ierlang_description = An Erlang language kernel for IPython. -pkg_ierlang_homepage = https://github.com/robbielynch/ierlang -pkg_ierlang_fetch = git -pkg_ierlang_repo = https://github.com/robbielynch/ierlang -pkg_ierlang_commit = master - -PACKAGES += iota -pkg_iota_name = iota -pkg_iota_description = iota (Inter-dependency Objective Testing Apparatus) - a tool to enforce clean separation of responsibilities in Erlang code -pkg_iota_homepage = https://github.com/jpgneves/iota -pkg_iota_fetch = git -pkg_iota_repo = https://github.com/jpgneves/iota -pkg_iota_commit = master - -PACKAGES += ircd -pkg_ircd_name = ircd -pkg_ircd_description = A pluggable IRC daemon application/library for Erlang. -pkg_ircd_homepage = https://github.com/tonyg/erlang-ircd -pkg_ircd_fetch = git -pkg_ircd_repo = https://github.com/tonyg/erlang-ircd -pkg_ircd_commit = master - -PACKAGES += irc_lib -pkg_irc_lib_name = irc_lib -pkg_irc_lib_description = Erlang irc client library -pkg_irc_lib_homepage = https://github.com/OtpChatBot/irc_lib -pkg_irc_lib_fetch = git -pkg_irc_lib_repo = https://github.com/OtpChatBot/irc_lib -pkg_irc_lib_commit = master - -PACKAGES += iris -pkg_iris_name = iris -pkg_iris_description = Iris Erlang binding -pkg_iris_homepage = https://github.com/project-iris/iris-erl -pkg_iris_fetch = git -pkg_iris_repo = https://github.com/project-iris/iris-erl -pkg_iris_commit = master - -PACKAGES += iso8601 -pkg_iso8601_name = iso8601 -pkg_iso8601_description = Erlang ISO 8601 date formatter/parser -pkg_iso8601_homepage = https://github.com/seansawyer/erlang_iso8601 -pkg_iso8601_fetch = git -pkg_iso8601_repo = https://github.com/seansawyer/erlang_iso8601 -pkg_iso8601_commit = master - -PACKAGES += itweet -pkg_itweet_name = itweet -pkg_itweet_description = Twitter Stream API on ibrowse -pkg_itweet_homepage = http://inaka.github.com/itweet/ -pkg_itweet_fetch = git -pkg_itweet_repo = https://github.com/inaka/itweet -pkg_itweet_commit = v2.0 - -PACKAGES += jerg -pkg_jerg_name = jerg -pkg_jerg_description = JSON Schema to Erlang Records Generator -pkg_jerg_homepage = https://github.com/ddossot/jerg -pkg_jerg_fetch = git -pkg_jerg_repo = https://github.com/ddossot/jerg -pkg_jerg_commit = master - -PACKAGES += jesse -pkg_jesse_name = jesse -pkg_jesse_description = jesse (JSon Schema Erlang) is an implementation of a json schema validator for Erlang. -pkg_jesse_homepage = https://github.com/klarna/jesse -pkg_jesse_fetch = git -pkg_jesse_repo = https://github.com/klarna/jesse -pkg_jesse_commit = master - -PACKAGES += jiffy -pkg_jiffy_name = jiffy -pkg_jiffy_description = JSON NIFs for Erlang. -pkg_jiffy_homepage = https://github.com/davisp/jiffy -pkg_jiffy_fetch = git -pkg_jiffy_repo = https://github.com/davisp/jiffy -pkg_jiffy_commit = master - -PACKAGES += jiffy_v -pkg_jiffy_v_name = jiffy_v -pkg_jiffy_v_description = JSON validation utility -pkg_jiffy_v_homepage = https://github.com/shizzard/jiffy-v -pkg_jiffy_v_fetch = git -pkg_jiffy_v_repo = https://github.com/shizzard/jiffy-v -pkg_jiffy_v_commit = 0.3.3 - -PACKAGES += jobs -pkg_jobs_name = jobs -pkg_jobs_description = a Job scheduler for load regulation -pkg_jobs_homepage = https://github.com/esl/jobs -pkg_jobs_fetch = git -pkg_jobs_repo = https://github.com/esl/jobs -pkg_jobs_commit = 0.3 - -PACKAGES += joxa -pkg_joxa_name = joxa -pkg_joxa_description = A Modern Lisp for the Erlang VM -pkg_joxa_homepage = https://github.com/joxa/joxa -pkg_joxa_fetch = git -pkg_joxa_repo = https://github.com/joxa/joxa -pkg_joxa_commit = master - -PACKAGES += jsonerl -pkg_jsonerl_name = jsonerl -pkg_jsonerl_description = yet another but slightly different erlang <-> json encoder/decoder -pkg_jsonerl_homepage = https://github.com/lambder/jsonerl -pkg_jsonerl_fetch = git -pkg_jsonerl_repo = https://github.com/lambder/jsonerl -pkg_jsonerl_commit = master - -PACKAGES += json -pkg_json_name = json -pkg_json_description = a high level json library for erlang (17.0+) -pkg_json_homepage = https://github.com/talentdeficit/json -pkg_json_fetch = git -pkg_json_repo = https://github.com/talentdeficit/json -pkg_json_commit = master - -PACKAGES += jsonpath -pkg_jsonpath_name = jsonpath -pkg_jsonpath_description = Fast Erlang JSON data retrieval and updates via javascript-like notation -pkg_jsonpath_homepage = https://github.com/GeneStevens/jsonpath -pkg_jsonpath_fetch = git -pkg_jsonpath_repo = https://github.com/GeneStevens/jsonpath -pkg_jsonpath_commit = master - -PACKAGES += json_rec -pkg_json_rec_name = json_rec -pkg_json_rec_description = JSON to erlang record -pkg_json_rec_homepage = https://github.com/justinkirby/json_rec -pkg_json_rec_fetch = git -pkg_json_rec_repo = https://github.com/justinkirby/json_rec -pkg_json_rec_commit = master - -PACKAGES += jsonx -pkg_jsonx_name = jsonx -pkg_jsonx_description = JSONX is an Erlang library for efficient decode and encode JSON, written in C. -pkg_jsonx_homepage = https://github.com/iskra/jsonx -pkg_jsonx_fetch = git -pkg_jsonx_repo = https://github.com/iskra/jsonx -pkg_jsonx_commit = master - -PACKAGES += jsx -pkg_jsx_name = jsx -pkg_jsx_description = An Erlang application for consuming, producing and manipulating JSON. -pkg_jsx_homepage = https://github.com/talentdeficit/jsx -pkg_jsx_fetch = git -pkg_jsx_repo = https://github.com/talentdeficit/jsx -pkg_jsx_commit = master - -PACKAGES += kafka -pkg_kafka_name = kafka -pkg_kafka_description = Kafka consumer and producer in Erlang -pkg_kafka_homepage = https://github.com/wooga/kafka-erlang -pkg_kafka_fetch = git -pkg_kafka_repo = https://github.com/wooga/kafka-erlang -pkg_kafka_commit = master - -PACKAGES += kai -pkg_kai_name = kai -pkg_kai_description = DHT storage by Takeshi Inoue -pkg_kai_homepage = https://github.com/synrc/kai -pkg_kai_fetch = git -pkg_kai_repo = https://github.com/synrc/kai -pkg_kai_commit = master - -PACKAGES += katja -pkg_katja_name = katja -pkg_katja_description = A simple Riemann client written in Erlang. -pkg_katja_homepage = https://github.com/nifoc/katja -pkg_katja_fetch = git -pkg_katja_repo = https://github.com/nifoc/katja -pkg_katja_commit = master - -PACKAGES += kdht -pkg_kdht_name = kdht -pkg_kdht_description = kdht is an erlang DHT implementation -pkg_kdht_homepage = https://github.com/kevinlynx/kdht -pkg_kdht_fetch = git -pkg_kdht_repo = https://github.com/kevinlynx/kdht -pkg_kdht_commit = master - -PACKAGES += key2value -pkg_key2value_name = key2value -pkg_key2value_description = Erlang 2-way map -pkg_key2value_homepage = https://github.com/okeuday/key2value -pkg_key2value_fetch = git -pkg_key2value_repo = https://github.com/okeuday/key2value -pkg_key2value_commit = master - -PACKAGES += keys1value -pkg_keys1value_name = keys1value -pkg_keys1value_description = Erlang set associative map for key lists -pkg_keys1value_homepage = https://github.com/okeuday/keys1value -pkg_keys1value_fetch = git -pkg_keys1value_repo = https://github.com/okeuday/keys1value -pkg_keys1value_commit = master - -PACKAGES += kinetic -pkg_kinetic_name = kinetic -pkg_kinetic_description = Erlang Kinesis Client -pkg_kinetic_homepage = https://github.com/AdRoll/kinetic -pkg_kinetic_fetch = git -pkg_kinetic_repo = https://github.com/AdRoll/kinetic -pkg_kinetic_commit = master - -PACKAGES += kjell -pkg_kjell_name = kjell -pkg_kjell_description = Erlang Shell -pkg_kjell_homepage = https://github.com/karlll/kjell -pkg_kjell_fetch = git -pkg_kjell_repo = https://github.com/karlll/kjell -pkg_kjell_commit = master - -PACKAGES += kraken -pkg_kraken_name = kraken -pkg_kraken_description = Distributed Pubsub Server for Realtime Apps -pkg_kraken_homepage = https://github.com/Asana/kraken -pkg_kraken_fetch = git -pkg_kraken_repo = https://github.com/Asana/kraken -pkg_kraken_commit = master - -PACKAGES += kucumberl -pkg_kucumberl_name = kucumberl -pkg_kucumberl_description = A pure-erlang, open-source, implementation of Cucumber -pkg_kucumberl_homepage = https://github.com/openshine/kucumberl -pkg_kucumberl_fetch = git -pkg_kucumberl_repo = https://github.com/openshine/kucumberl -pkg_kucumberl_commit = master - -PACKAGES += kvc -pkg_kvc_name = kvc -pkg_kvc_description = KVC - Key Value Coding for Erlang data structures -pkg_kvc_homepage = https://github.com/etrepum/kvc -pkg_kvc_fetch = git -pkg_kvc_repo = https://github.com/etrepum/kvc -pkg_kvc_commit = master - -PACKAGES += kvlists -pkg_kvlists_name = kvlists -pkg_kvlists_description = Lists of key-value pairs (decoded JSON) in Erlang -pkg_kvlists_homepage = https://github.com/jcomellas/kvlists -pkg_kvlists_fetch = git -pkg_kvlists_repo = https://github.com/jcomellas/kvlists -pkg_kvlists_commit = master - -PACKAGES += kvs -pkg_kvs_name = kvs -pkg_kvs_description = Container and Iterator -pkg_kvs_homepage = https://github.com/synrc/kvs -pkg_kvs_fetch = git -pkg_kvs_repo = https://github.com/synrc/kvs -pkg_kvs_commit = master - -PACKAGES += lager_amqp_backend -pkg_lager_amqp_backend_name = lager_amqp_backend -pkg_lager_amqp_backend_description = AMQP RabbitMQ Lager backend -pkg_lager_amqp_backend_homepage = https://github.com/jbrisbin/lager_amqp_backend -pkg_lager_amqp_backend_fetch = git -pkg_lager_amqp_backend_repo = https://github.com/jbrisbin/lager_amqp_backend -pkg_lager_amqp_backend_commit = master - -PACKAGES += lager -pkg_lager_name = lager -pkg_lager_description = A logging framework for Erlang/OTP. -pkg_lager_homepage = https://github.com/basho/lager -pkg_lager_fetch = git -pkg_lager_repo = https://github.com/basho/lager -pkg_lager_commit = master - -PACKAGES += lager_syslog -pkg_lager_syslog_name = lager_syslog -pkg_lager_syslog_description = Syslog backend for lager -pkg_lager_syslog_homepage = https://github.com/basho/lager_syslog -pkg_lager_syslog_fetch = git -pkg_lager_syslog_repo = https://github.com/basho/lager_syslog -pkg_lager_syslog_commit = master - -PACKAGES += lambdapad -pkg_lambdapad_name = lambdapad -pkg_lambdapad_description = Static site generator using Erlang. Yes, Erlang. -pkg_lambdapad_homepage = https://github.com/gar1t/lambdapad -pkg_lambdapad_fetch = git -pkg_lambdapad_repo = https://github.com/gar1t/lambdapad -pkg_lambdapad_commit = master - -PACKAGES += lasp -pkg_lasp_name = lasp -pkg_lasp_description = A Language for Distributed, Eventually Consistent Computations -pkg_lasp_homepage = http://lasp-lang.org/ -pkg_lasp_fetch = git -pkg_lasp_repo = https://github.com/lasp-lang/lasp -pkg_lasp_commit = master - -PACKAGES += lasse -pkg_lasse_name = lasse -pkg_lasse_description = SSE handler for Cowboy -pkg_lasse_homepage = https://github.com/inaka/lasse -pkg_lasse_fetch = git -pkg_lasse_repo = https://github.com/inaka/lasse -pkg_lasse_commit = 0.1.0 - -PACKAGES += ldap -pkg_ldap_name = ldap -pkg_ldap_description = LDAP server written in Erlang -pkg_ldap_homepage = https://github.com/spawnproc/ldap -pkg_ldap_fetch = git -pkg_ldap_repo = https://github.com/spawnproc/ldap -pkg_ldap_commit = master - -PACKAGES += lethink -pkg_lethink_name = lethink -pkg_lethink_description = erlang driver for rethinkdb -pkg_lethink_homepage = https://github.com/taybin/lethink -pkg_lethink_fetch = git -pkg_lethink_repo = https://github.com/taybin/lethink -pkg_lethink_commit = master - -PACKAGES += lfe -pkg_lfe_name = lfe -pkg_lfe_description = Lisp Flavoured Erlang (LFE) -pkg_lfe_homepage = https://github.com/rvirding/lfe -pkg_lfe_fetch = git -pkg_lfe_repo = https://github.com/rvirding/lfe -pkg_lfe_commit = master - -PACKAGES += ling -pkg_ling_name = ling -pkg_ling_description = Erlang on Xen -pkg_ling_homepage = https://github.com/cloudozer/ling -pkg_ling_fetch = git -pkg_ling_repo = https://github.com/cloudozer/ling -pkg_ling_commit = master - -PACKAGES += live -pkg_live_name = live -pkg_live_description = Automated module and configuration reloader. -pkg_live_homepage = http://ninenines.eu -pkg_live_fetch = git -pkg_live_repo = https://github.com/ninenines/live -pkg_live_commit = master - -PACKAGES += lmq -pkg_lmq_name = lmq -pkg_lmq_description = Lightweight Message Queue -pkg_lmq_homepage = https://github.com/iij/lmq -pkg_lmq_fetch = git -pkg_lmq_repo = https://github.com/iij/lmq -pkg_lmq_commit = master - -PACKAGES += locker -pkg_locker_name = locker -pkg_locker_description = Atomic distributed 'check and set' for short-lived keys -pkg_locker_homepage = https://github.com/wooga/locker -pkg_locker_fetch = git -pkg_locker_repo = https://github.com/wooga/locker -pkg_locker_commit = master - -PACKAGES += locks -pkg_locks_name = locks -pkg_locks_description = A scalable, deadlock-resolving resource locker -pkg_locks_homepage = https://github.com/uwiger/locks -pkg_locks_fetch = git -pkg_locks_repo = https://github.com/uwiger/locks -pkg_locks_commit = master - -PACKAGES += log4erl -pkg_log4erl_name = log4erl -pkg_log4erl_description = A logger for erlang in the spirit of Log4J. -pkg_log4erl_homepage = https://github.com/ahmednawras/log4erl -pkg_log4erl_fetch = git -pkg_log4erl_repo = https://github.com/ahmednawras/log4erl -pkg_log4erl_commit = master - -PACKAGES += lol -pkg_lol_name = lol -pkg_lol_description = Lisp on erLang, and programming is fun again -pkg_lol_homepage = https://github.com/b0oh/lol -pkg_lol_fetch = git -pkg_lol_repo = https://github.com/b0oh/lol -pkg_lol_commit = master - -PACKAGES += lucid -pkg_lucid_name = lucid -pkg_lucid_description = HTTP/2 server written in Erlang -pkg_lucid_homepage = https://github.com/tatsuhiro-t/lucid -pkg_lucid_fetch = git -pkg_lucid_repo = https://github.com/tatsuhiro-t/lucid -pkg_lucid_commit = master - -PACKAGES += luerl -pkg_luerl_name = luerl -pkg_luerl_description = Lua in Erlang -pkg_luerl_homepage = https://github.com/rvirding/luerl -pkg_luerl_fetch = git -pkg_luerl_repo = https://github.com/rvirding/luerl -pkg_luerl_commit = develop - -PACKAGES += luwak -pkg_luwak_name = luwak -pkg_luwak_description = Large-object storage interface for Riak -pkg_luwak_homepage = https://github.com/basho/luwak -pkg_luwak_fetch = git -pkg_luwak_repo = https://github.com/basho/luwak -pkg_luwak_commit = master - -PACKAGES += lux -pkg_lux_name = lux -pkg_lux_description = Lux (LUcid eXpect scripting) simplifies test automation and provides an Expect-style execution of commands -pkg_lux_homepage = https://github.com/hawk/lux -pkg_lux_fetch = git -pkg_lux_repo = https://github.com/hawk/lux -pkg_lux_commit = master - -PACKAGES += machi -pkg_machi_name = machi -pkg_machi_description = Machi file store -pkg_machi_homepage = https://github.com/basho/machi -pkg_machi_fetch = git -pkg_machi_repo = https://github.com/basho/machi -pkg_machi_commit = master - -PACKAGES += mad -pkg_mad_name = mad -pkg_mad_description = Small and Fast Rebar Replacement -pkg_mad_homepage = https://github.com/synrc/mad -pkg_mad_fetch = git -pkg_mad_repo = https://github.com/synrc/mad -pkg_mad_commit = master - -PACKAGES += marina -pkg_marina_name = marina -pkg_marina_description = Non-blocking Erlang Cassandra CQL3 client -pkg_marina_homepage = https://github.com/lpgauth/marina -pkg_marina_fetch = git -pkg_marina_repo = https://github.com/lpgauth/marina -pkg_marina_commit = master - -PACKAGES += mavg -pkg_mavg_name = mavg -pkg_mavg_description = Erlang :: Exponential moving average library -pkg_mavg_homepage = https://github.com/EchoTeam/mavg -pkg_mavg_fetch = git -pkg_mavg_repo = https://github.com/EchoTeam/mavg -pkg_mavg_commit = master - -PACKAGES += mcd -pkg_mcd_name = mcd -pkg_mcd_description = Fast memcached protocol client in pure Erlang -pkg_mcd_homepage = https://github.com/EchoTeam/mcd -pkg_mcd_fetch = git -pkg_mcd_repo = https://github.com/EchoTeam/mcd -pkg_mcd_commit = master - -PACKAGES += mcerlang -pkg_mcerlang_name = mcerlang -pkg_mcerlang_description = The McErlang model checker for Erlang -pkg_mcerlang_homepage = https://github.com/fredlund/McErlang -pkg_mcerlang_fetch = git -pkg_mcerlang_repo = https://github.com/fredlund/McErlang -pkg_mcerlang_commit = master - -PACKAGES += mc_erl -pkg_mc_erl_name = mc_erl -pkg_mc_erl_description = mc-erl is a server for Minecraft 1.4.7 written in Erlang. -pkg_mc_erl_homepage = https://github.com/clonejo/mc-erl -pkg_mc_erl_fetch = git -pkg_mc_erl_repo = https://github.com/clonejo/mc-erl -pkg_mc_erl_commit = master - -PACKAGES += meck -pkg_meck_name = meck -pkg_meck_description = A mocking library for Erlang -pkg_meck_homepage = https://github.com/eproxus/meck -pkg_meck_fetch = git -pkg_meck_repo = https://github.com/eproxus/meck -pkg_meck_commit = master - -PACKAGES += mekao -pkg_mekao_name = mekao -pkg_mekao_description = SQL constructor -pkg_mekao_homepage = https://github.com/ddosia/mekao -pkg_mekao_fetch = git -pkg_mekao_repo = https://github.com/ddosia/mekao -pkg_mekao_commit = master - -PACKAGES += memo -pkg_memo_name = memo -pkg_memo_description = Erlang memoization server -pkg_memo_homepage = https://github.com/tuncer/memo -pkg_memo_fetch = git -pkg_memo_repo = https://github.com/tuncer/memo -pkg_memo_commit = master - -PACKAGES += merge_index -pkg_merge_index_name = merge_index -pkg_merge_index_description = MergeIndex is an Erlang library for storing ordered sets on disk. It is very similar to an SSTable (in Google's Bigtable) or an HFile (in Hadoop). -pkg_merge_index_homepage = https://github.com/basho/merge_index -pkg_merge_index_fetch = git -pkg_merge_index_repo = https://github.com/basho/merge_index -pkg_merge_index_commit = master - -PACKAGES += merl -pkg_merl_name = merl -pkg_merl_description = Metaprogramming in Erlang -pkg_merl_homepage = https://github.com/richcarl/merl -pkg_merl_fetch = git -pkg_merl_repo = https://github.com/richcarl/merl -pkg_merl_commit = master - -PACKAGES += mimetypes -pkg_mimetypes_name = mimetypes -pkg_mimetypes_description = Erlang MIME types library -pkg_mimetypes_homepage = https://github.com/spawngrid/mimetypes -pkg_mimetypes_fetch = git -pkg_mimetypes_repo = https://github.com/spawngrid/mimetypes -pkg_mimetypes_commit = master - -PACKAGES += mixer -pkg_mixer_name = mixer -pkg_mixer_description = Mix in functions from other modules -pkg_mixer_homepage = https://github.com/chef/mixer -pkg_mixer_fetch = git -pkg_mixer_repo = https://github.com/chef/mixer -pkg_mixer_commit = master - -PACKAGES += mochiweb -pkg_mochiweb_name = mochiweb -pkg_mochiweb_description = MochiWeb is an Erlang library for building lightweight HTTP servers. -pkg_mochiweb_homepage = https://github.com/mochi/mochiweb -pkg_mochiweb_fetch = git -pkg_mochiweb_repo = https://github.com/mochi/mochiweb -pkg_mochiweb_commit = master - -PACKAGES += mochiweb_xpath -pkg_mochiweb_xpath_name = mochiweb_xpath -pkg_mochiweb_xpath_description = XPath support for mochiweb's html parser -pkg_mochiweb_xpath_homepage = https://github.com/retnuh/mochiweb_xpath -pkg_mochiweb_xpath_fetch = git -pkg_mochiweb_xpath_repo = https://github.com/retnuh/mochiweb_xpath -pkg_mochiweb_xpath_commit = master - -PACKAGES += mockgyver -pkg_mockgyver_name = mockgyver -pkg_mockgyver_description = A mocking library for Erlang -pkg_mockgyver_homepage = https://github.com/klajo/mockgyver -pkg_mockgyver_fetch = git -pkg_mockgyver_repo = https://github.com/klajo/mockgyver -pkg_mockgyver_commit = master - -PACKAGES += modlib -pkg_modlib_name = modlib -pkg_modlib_description = Web framework based on Erlang's inets httpd -pkg_modlib_homepage = https://github.com/gar1t/modlib -pkg_modlib_fetch = git -pkg_modlib_repo = https://github.com/gar1t/modlib -pkg_modlib_commit = master - -PACKAGES += mongodb -pkg_mongodb_name = mongodb -pkg_mongodb_description = MongoDB driver for Erlang -pkg_mongodb_homepage = https://github.com/comtihon/mongodb-erlang -pkg_mongodb_fetch = git -pkg_mongodb_repo = https://github.com/comtihon/mongodb-erlang -pkg_mongodb_commit = master - -PACKAGES += mongooseim -pkg_mongooseim_name = mongooseim -pkg_mongooseim_description = Jabber / XMPP server with focus on performance and scalability, by Erlang Solutions -pkg_mongooseim_homepage = https://www.erlang-solutions.com/products/mongooseim-massively-scalable-ejabberd-platform -pkg_mongooseim_fetch = git -pkg_mongooseim_repo = https://github.com/esl/MongooseIM -pkg_mongooseim_commit = master - -PACKAGES += moyo -pkg_moyo_name = moyo -pkg_moyo_description = Erlang utility functions library -pkg_moyo_homepage = https://github.com/dwango/moyo -pkg_moyo_fetch = git -pkg_moyo_repo = https://github.com/dwango/moyo -pkg_moyo_commit = master - -PACKAGES += msgpack -pkg_msgpack_name = msgpack -pkg_msgpack_description = MessagePack (de)serializer implementation for Erlang -pkg_msgpack_homepage = https://github.com/msgpack/msgpack-erlang -pkg_msgpack_fetch = git -pkg_msgpack_repo = https://github.com/msgpack/msgpack-erlang -pkg_msgpack_commit = master - -PACKAGES += mu2 -pkg_mu2_name = mu2 -pkg_mu2_description = Erlang mutation testing tool -pkg_mu2_homepage = https://github.com/ramsay-t/mu2 -pkg_mu2_fetch = git -pkg_mu2_repo = https://github.com/ramsay-t/mu2 -pkg_mu2_commit = master - -PACKAGES += mustache -pkg_mustache_name = mustache -pkg_mustache_description = Mustache template engine for Erlang. -pkg_mustache_homepage = https://github.com/mojombo/mustache.erl -pkg_mustache_fetch = git -pkg_mustache_repo = https://github.com/mojombo/mustache.erl -pkg_mustache_commit = master - -PACKAGES += myproto -pkg_myproto_name = myproto -pkg_myproto_description = MySQL Server Protocol in Erlang -pkg_myproto_homepage = https://github.com/altenwald/myproto -pkg_myproto_fetch = git -pkg_myproto_repo = https://github.com/altenwald/myproto -pkg_myproto_commit = master - -PACKAGES += mysql -pkg_mysql_name = mysql -pkg_mysql_description = Erlang MySQL Driver (from code.google.com) -pkg_mysql_homepage = https://github.com/dizzyd/erlang-mysql-driver -pkg_mysql_fetch = git -pkg_mysql_repo = https://github.com/dizzyd/erlang-mysql-driver -pkg_mysql_commit = master - -PACKAGES += n2o -pkg_n2o_name = n2o -pkg_n2o_description = WebSocket Application Server -pkg_n2o_homepage = https://github.com/5HT/n2o -pkg_n2o_fetch = git -pkg_n2o_repo = https://github.com/5HT/n2o -pkg_n2o_commit = master - -PACKAGES += nat_upnp -pkg_nat_upnp_name = nat_upnp -pkg_nat_upnp_description = Erlang library to map your internal port to an external using UNP IGD -pkg_nat_upnp_homepage = https://github.com/benoitc/nat_upnp -pkg_nat_upnp_fetch = git -pkg_nat_upnp_repo = https://github.com/benoitc/nat_upnp -pkg_nat_upnp_commit = master - -PACKAGES += neo4j -pkg_neo4j_name = neo4j -pkg_neo4j_description = Erlang client library for Neo4J. -pkg_neo4j_homepage = https://github.com/dmitriid/neo4j-erlang -pkg_neo4j_fetch = git -pkg_neo4j_repo = https://github.com/dmitriid/neo4j-erlang -pkg_neo4j_commit = master - -PACKAGES += neotoma -pkg_neotoma_name = neotoma -pkg_neotoma_description = Erlang library and packrat parser-generator for parsing expression grammars. -pkg_neotoma_homepage = https://github.com/seancribbs/neotoma -pkg_neotoma_fetch = git -pkg_neotoma_repo = https://github.com/seancribbs/neotoma -pkg_neotoma_commit = master - -PACKAGES += newrelic -pkg_newrelic_name = newrelic -pkg_newrelic_description = Erlang library for sending metrics to New Relic -pkg_newrelic_homepage = https://github.com/wooga/newrelic-erlang -pkg_newrelic_fetch = git -pkg_newrelic_repo = https://github.com/wooga/newrelic-erlang -pkg_newrelic_commit = master - -PACKAGES += nifty -pkg_nifty_name = nifty -pkg_nifty_description = Erlang NIF wrapper generator -pkg_nifty_homepage = https://github.com/parapluu/nifty -pkg_nifty_fetch = git -pkg_nifty_repo = https://github.com/parapluu/nifty -pkg_nifty_commit = master - -PACKAGES += nitrogen_core -pkg_nitrogen_core_name = nitrogen_core -pkg_nitrogen_core_description = The core Nitrogen library. -pkg_nitrogen_core_homepage = http://nitrogenproject.com/ -pkg_nitrogen_core_fetch = git -pkg_nitrogen_core_repo = https://github.com/nitrogen/nitrogen_core -pkg_nitrogen_core_commit = master - -PACKAGES += nkbase -pkg_nkbase_name = nkbase -pkg_nkbase_description = NkBASE distributed database -pkg_nkbase_homepage = https://github.com/Nekso/nkbase -pkg_nkbase_fetch = git -pkg_nkbase_repo = https://github.com/Nekso/nkbase -pkg_nkbase_commit = develop - -PACKAGES += nkdocker -pkg_nkdocker_name = nkdocker -pkg_nkdocker_description = Erlang Docker client -pkg_nkdocker_homepage = https://github.com/Nekso/nkdocker -pkg_nkdocker_fetch = git -pkg_nkdocker_repo = https://github.com/Nekso/nkdocker -pkg_nkdocker_commit = master - -PACKAGES += nkpacket -pkg_nkpacket_name = nkpacket -pkg_nkpacket_description = Generic Erlang transport layer -pkg_nkpacket_homepage = https://github.com/Nekso/nkpacket -pkg_nkpacket_fetch = git -pkg_nkpacket_repo = https://github.com/Nekso/nkpacket -pkg_nkpacket_commit = master - -PACKAGES += nodefinder -pkg_nodefinder_name = nodefinder -pkg_nodefinder_description = automatic node discovery via UDP multicast -pkg_nodefinder_homepage = https://github.com/erlanger/nodefinder -pkg_nodefinder_fetch = git -pkg_nodefinder_repo = https://github.com/okeuday/nodefinder -pkg_nodefinder_commit = master - -PACKAGES += nprocreg -pkg_nprocreg_name = nprocreg -pkg_nprocreg_description = Minimal Distributed Erlang Process Registry -pkg_nprocreg_homepage = http://nitrogenproject.com/ -pkg_nprocreg_fetch = git -pkg_nprocreg_repo = https://github.com/nitrogen/nprocreg -pkg_nprocreg_commit = master - -PACKAGES += oauth2c -pkg_oauth2c_name = oauth2c -pkg_oauth2c_description = Erlang OAuth2 Client -pkg_oauth2c_homepage = https://github.com/kivra/oauth2_client -pkg_oauth2c_fetch = git -pkg_oauth2c_repo = https://github.com/kivra/oauth2_client -pkg_oauth2c_commit = master - -PACKAGES += oauth2 -pkg_oauth2_name = oauth2 -pkg_oauth2_description = Erlang Oauth2 implementation -pkg_oauth2_homepage = https://github.com/kivra/oauth2 -pkg_oauth2_fetch = git -pkg_oauth2_repo = https://github.com/kivra/oauth2 -pkg_oauth2_commit = master - -PACKAGES += oauth -pkg_oauth_name = oauth -pkg_oauth_description = An Erlang OAuth 1.0 implementation -pkg_oauth_homepage = https://github.com/tim/erlang-oauth -pkg_oauth_fetch = git -pkg_oauth_repo = https://github.com/tim/erlang-oauth -pkg_oauth_commit = master - -PACKAGES += of_protocol -pkg_of_protocol_name = of_protocol -pkg_of_protocol_description = OpenFlow Protocol Library for Erlang -pkg_of_protocol_homepage = https://github.com/FlowForwarding/of_protocol -pkg_of_protocol_fetch = git -pkg_of_protocol_repo = https://github.com/FlowForwarding/of_protocol -pkg_of_protocol_commit = master - -PACKAGES += openflow -pkg_openflow_name = openflow -pkg_openflow_description = An OpenFlow controller written in pure erlang -pkg_openflow_homepage = https://github.com/renatoaguiar/erlang-openflow -pkg_openflow_fetch = git -pkg_openflow_repo = https://github.com/renatoaguiar/erlang-openflow -pkg_openflow_commit = master - -PACKAGES += openid -pkg_openid_name = openid -pkg_openid_description = Erlang OpenID -pkg_openid_homepage = https://github.com/brendonh/erl_openid -pkg_openid_fetch = git -pkg_openid_repo = https://github.com/brendonh/erl_openid -pkg_openid_commit = master - -PACKAGES += openpoker -pkg_openpoker_name = openpoker -pkg_openpoker_description = Genesis Texas hold'em Game Server -pkg_openpoker_homepage = https://github.com/hpyhacking/openpoker -pkg_openpoker_fetch = git -pkg_openpoker_repo = https://github.com/hpyhacking/openpoker -pkg_openpoker_commit = master - -PACKAGES += pal -pkg_pal_name = pal -pkg_pal_description = Pragmatic Authentication Library -pkg_pal_homepage = https://github.com/manifest/pal -pkg_pal_fetch = git -pkg_pal_repo = https://github.com/manifest/pal -pkg_pal_commit = master - -PACKAGES += parse_trans -pkg_parse_trans_name = parse_trans -pkg_parse_trans_description = Parse transform utilities for Erlang -pkg_parse_trans_homepage = https://github.com/uwiger/parse_trans -pkg_parse_trans_fetch = git -pkg_parse_trans_repo = https://github.com/uwiger/parse_trans -pkg_parse_trans_commit = master - -PACKAGES += parsexml -pkg_parsexml_name = parsexml -pkg_parsexml_description = Simple DOM XML parser with convenient and very simple API -pkg_parsexml_homepage = https://github.com/maxlapshin/parsexml -pkg_parsexml_fetch = git -pkg_parsexml_repo = https://github.com/maxlapshin/parsexml -pkg_parsexml_commit = master - -PACKAGES += pegjs -pkg_pegjs_name = pegjs -pkg_pegjs_description = An implementation of PEG.js grammar for Erlang. -pkg_pegjs_homepage = https://github.com/dmitriid/pegjs -pkg_pegjs_fetch = git -pkg_pegjs_repo = https://github.com/dmitriid/pegjs -pkg_pegjs_commit = 0.3 - -PACKAGES += percept2 -pkg_percept2_name = percept2 -pkg_percept2_description = Concurrent profiling tool for Erlang -pkg_percept2_homepage = https://github.com/huiqing/percept2 -pkg_percept2_fetch = git -pkg_percept2_repo = https://github.com/huiqing/percept2 -pkg_percept2_commit = master - -PACKAGES += pgsql -pkg_pgsql_name = pgsql -pkg_pgsql_description = Erlang PostgreSQL driver -pkg_pgsql_homepage = https://github.com/semiocast/pgsql -pkg_pgsql_fetch = git -pkg_pgsql_repo = https://github.com/semiocast/pgsql -pkg_pgsql_commit = master - -PACKAGES += pkgx -pkg_pkgx_name = pkgx -pkg_pkgx_description = Build .deb packages from Erlang releases -pkg_pkgx_homepage = https://github.com/arjan/pkgx -pkg_pkgx_fetch = git -pkg_pkgx_repo = https://github.com/arjan/pkgx -pkg_pkgx_commit = master - -PACKAGES += pkt -pkg_pkt_name = pkt -pkg_pkt_description = Erlang network protocol library -pkg_pkt_homepage = https://github.com/msantos/pkt -pkg_pkt_fetch = git -pkg_pkt_repo = https://github.com/msantos/pkt -pkg_pkt_commit = master - -PACKAGES += plain_fsm -pkg_plain_fsm_name = plain_fsm -pkg_plain_fsm_description = A behaviour/support library for writing plain Erlang FSMs. -pkg_plain_fsm_homepage = https://github.com/uwiger/plain_fsm -pkg_plain_fsm_fetch = git -pkg_plain_fsm_repo = https://github.com/uwiger/plain_fsm -pkg_plain_fsm_commit = master - -PACKAGES += plumtree -pkg_plumtree_name = plumtree -pkg_plumtree_description = Epidemic Broadcast Trees -pkg_plumtree_homepage = https://github.com/helium/plumtree -pkg_plumtree_fetch = git -pkg_plumtree_repo = https://github.com/helium/plumtree -pkg_plumtree_commit = master - -PACKAGES += pmod_transform -pkg_pmod_transform_name = pmod_transform -pkg_pmod_transform_description = Parse transform for parameterized modules -pkg_pmod_transform_homepage = https://github.com/erlang/pmod_transform -pkg_pmod_transform_fetch = git -pkg_pmod_transform_repo = https://github.com/erlang/pmod_transform -pkg_pmod_transform_commit = master - -PACKAGES += pobox -pkg_pobox_name = pobox -pkg_pobox_description = External buffer processes to protect against mailbox overflow in Erlang -pkg_pobox_homepage = https://github.com/ferd/pobox -pkg_pobox_fetch = git -pkg_pobox_repo = https://github.com/ferd/pobox -pkg_pobox_commit = master - -PACKAGES += ponos -pkg_ponos_name = ponos -pkg_ponos_description = ponos is a simple yet powerful load generator written in erlang -pkg_ponos_homepage = https://github.com/klarna/ponos -pkg_ponos_fetch = git -pkg_ponos_repo = https://github.com/klarna/ponos -pkg_ponos_commit = master - -PACKAGES += poolboy -pkg_poolboy_name = poolboy -pkg_poolboy_description = A hunky Erlang worker pool factory -pkg_poolboy_homepage = https://github.com/devinus/poolboy -pkg_poolboy_fetch = git -pkg_poolboy_repo = https://github.com/devinus/poolboy -pkg_poolboy_commit = master - -PACKAGES += pooler -pkg_pooler_name = pooler -pkg_pooler_description = An OTP Process Pool Application -pkg_pooler_homepage = https://github.com/seth/pooler -pkg_pooler_fetch = git -pkg_pooler_repo = https://github.com/seth/pooler -pkg_pooler_commit = master - -PACKAGES += pqueue -pkg_pqueue_name = pqueue -pkg_pqueue_description = Erlang Priority Queues -pkg_pqueue_homepage = https://github.com/okeuday/pqueue -pkg_pqueue_fetch = git -pkg_pqueue_repo = https://github.com/okeuday/pqueue -pkg_pqueue_commit = master - -PACKAGES += procket -pkg_procket_name = procket -pkg_procket_description = Erlang interface to low level socket operations -pkg_procket_homepage = http://blog.listincomprehension.com/search/label/procket -pkg_procket_fetch = git -pkg_procket_repo = https://github.com/msantos/procket -pkg_procket_commit = master - -PACKAGES += proper -pkg_proper_name = proper -pkg_proper_description = PropEr: a QuickCheck-inspired property-based testing tool for Erlang. -pkg_proper_homepage = http://proper.softlab.ntua.gr -pkg_proper_fetch = git -pkg_proper_repo = https://github.com/manopapad/proper -pkg_proper_commit = master - -PACKAGES += prop -pkg_prop_name = prop -pkg_prop_description = An Erlang code scaffolding and generator system. -pkg_prop_homepage = https://github.com/nuex/prop -pkg_prop_fetch = git -pkg_prop_repo = https://github.com/nuex/prop -pkg_prop_commit = master - -PACKAGES += props -pkg_props_name = props -pkg_props_description = Property structure library -pkg_props_homepage = https://github.com/greyarea/props -pkg_props_fetch = git -pkg_props_repo = https://github.com/greyarea/props -pkg_props_commit = master - -PACKAGES += protobuffs -pkg_protobuffs_name = protobuffs -pkg_protobuffs_description = An implementation of Google's Protocol Buffers for Erlang, based on ngerakines/erlang_protobuffs. -pkg_protobuffs_homepage = https://github.com/basho/erlang_protobuffs -pkg_protobuffs_fetch = git -pkg_protobuffs_repo = https://github.com/basho/erlang_protobuffs -pkg_protobuffs_commit = master - -PACKAGES += psycho -pkg_psycho_name = psycho -pkg_psycho_description = HTTP server that provides a WSGI-like interface for applications and middleware. -pkg_psycho_homepage = https://github.com/gar1t/psycho -pkg_psycho_fetch = git -pkg_psycho_repo = https://github.com/gar1t/psycho -pkg_psycho_commit = master - -PACKAGES += ptrackerl -pkg_ptrackerl_name = ptrackerl -pkg_ptrackerl_description = Pivotal Tracker API Client written in Erlang -pkg_ptrackerl_homepage = https://github.com/inaka/ptrackerl -pkg_ptrackerl_fetch = git -pkg_ptrackerl_repo = https://github.com/inaka/ptrackerl -pkg_ptrackerl_commit = master - -PACKAGES += purity -pkg_purity_name = purity -pkg_purity_description = A side-effect analyzer for Erlang -pkg_purity_homepage = https://github.com/mpitid/purity -pkg_purity_fetch = git -pkg_purity_repo = https://github.com/mpitid/purity -pkg_purity_commit = master - -PACKAGES += push_service -pkg_push_service_name = push_service -pkg_push_service_description = Push service -pkg_push_service_homepage = https://github.com/hairyhum/push_service -pkg_push_service_fetch = git -pkg_push_service_repo = https://github.com/hairyhum/push_service -pkg_push_service_commit = master - -PACKAGES += qdate -pkg_qdate_name = qdate -pkg_qdate_description = Date, time, and timezone parsing, formatting, and conversion for Erlang. -pkg_qdate_homepage = https://github.com/choptastic/qdate -pkg_qdate_fetch = git -pkg_qdate_repo = https://github.com/choptastic/qdate -pkg_qdate_commit = 0.4.0 - -PACKAGES += qrcode -pkg_qrcode_name = qrcode -pkg_qrcode_description = QR Code encoder in Erlang -pkg_qrcode_homepage = https://github.com/komone/qrcode -pkg_qrcode_fetch = git -pkg_qrcode_repo = https://github.com/komone/qrcode -pkg_qrcode_commit = master - -PACKAGES += quest -pkg_quest_name = quest -pkg_quest_description = Learn Erlang through this set of challenges. An interactive system for getting to know Erlang. -pkg_quest_homepage = https://github.com/eriksoe/ErlangQuest -pkg_quest_fetch = git -pkg_quest_repo = https://github.com/eriksoe/ErlangQuest -pkg_quest_commit = master - -PACKAGES += quickrand -pkg_quickrand_name = quickrand -pkg_quickrand_description = Quick Erlang Random Number Generation -pkg_quickrand_homepage = https://github.com/okeuday/quickrand -pkg_quickrand_fetch = git -pkg_quickrand_repo = https://github.com/okeuday/quickrand -pkg_quickrand_commit = master - -PACKAGES += rabbit_exchange_type_riak -pkg_rabbit_exchange_type_riak_name = rabbit_exchange_type_riak -pkg_rabbit_exchange_type_riak_description = Custom RabbitMQ exchange type for sticking messages in Riak -pkg_rabbit_exchange_type_riak_homepage = https://github.com/jbrisbin/riak-exchange -pkg_rabbit_exchange_type_riak_fetch = git -pkg_rabbit_exchange_type_riak_repo = https://github.com/jbrisbin/riak-exchange -pkg_rabbit_exchange_type_riak_commit = master - -PACKAGES += rabbit -pkg_rabbit_name = rabbit -pkg_rabbit_description = RabbitMQ Server -pkg_rabbit_homepage = https://www.rabbitmq.com/ -pkg_rabbit_fetch = git -pkg_rabbit_repo = https://github.com/rabbitmq/rabbitmq-server.git -pkg_rabbit_commit = master - -PACKAGES += rack -pkg_rack_name = rack -pkg_rack_description = Rack handler for erlang -pkg_rack_homepage = https://github.com/erlyvideo/rack -pkg_rack_fetch = git -pkg_rack_repo = https://github.com/erlyvideo/rack -pkg_rack_commit = master - -PACKAGES += radierl -pkg_radierl_name = radierl -pkg_radierl_description = RADIUS protocol stack implemented in Erlang. -pkg_radierl_homepage = https://github.com/vances/radierl -pkg_radierl_fetch = git -pkg_radierl_repo = https://github.com/vances/radierl -pkg_radierl_commit = master - -PACKAGES += rafter -pkg_rafter_name = rafter -pkg_rafter_description = An Erlang library application which implements the Raft consensus protocol -pkg_rafter_homepage = https://github.com/andrewjstone/rafter -pkg_rafter_fetch = git -pkg_rafter_repo = https://github.com/andrewjstone/rafter -pkg_rafter_commit = master - -PACKAGES += ranch -pkg_ranch_name = ranch -pkg_ranch_description = Socket acceptor pool for TCP protocols. -pkg_ranch_homepage = http://ninenines.eu -pkg_ranch_fetch = git -pkg_ranch_repo = https://github.com/ninenines/ranch -pkg_ranch_commit = 1.1.0 - -PACKAGES += rbeacon -pkg_rbeacon_name = rbeacon -pkg_rbeacon_description = LAN discovery and presence in Erlang. -pkg_rbeacon_homepage = https://github.com/refuge/rbeacon -pkg_rbeacon_fetch = git -pkg_rbeacon_repo = https://github.com/refuge/rbeacon -pkg_rbeacon_commit = master - -PACKAGES += rebar -pkg_rebar_name = rebar -pkg_rebar_description = Erlang build tool that makes it easy to compile and test Erlang applications, port drivers and releases. -pkg_rebar_homepage = http://www.rebar3.org -pkg_rebar_fetch = git -pkg_rebar_repo = https://github.com/rebar/rebar3 -pkg_rebar_commit = master - -PACKAGES += rebus -pkg_rebus_name = rebus -pkg_rebus_description = A stupid simple, internal, pub/sub event bus written in- and for Erlang. -pkg_rebus_homepage = https://github.com/olle/rebus -pkg_rebus_fetch = git -pkg_rebus_repo = https://github.com/olle/rebus -pkg_rebus_commit = master - -PACKAGES += rec2json -pkg_rec2json_name = rec2json -pkg_rec2json_description = Compile erlang record definitions into modules to convert them to/from json easily. -pkg_rec2json_homepage = https://github.com/lordnull/rec2json -pkg_rec2json_fetch = git -pkg_rec2json_repo = https://github.com/lordnull/rec2json -pkg_rec2json_commit = master - -PACKAGES += recon -pkg_recon_name = recon -pkg_recon_description = Collection of functions and scripts to debug Erlang in production. -pkg_recon_homepage = https://github.com/ferd/recon -pkg_recon_fetch = git -pkg_recon_repo = https://github.com/ferd/recon -pkg_recon_commit = 2.2.1 - -PACKAGES += record_info -pkg_record_info_name = record_info -pkg_record_info_description = Convert between record and proplist -pkg_record_info_homepage = https://github.com/bipthelin/erlang-record_info -pkg_record_info_fetch = git -pkg_record_info_repo = https://github.com/bipthelin/erlang-record_info -pkg_record_info_commit = master - -PACKAGES += redgrid -pkg_redgrid_name = redgrid -pkg_redgrid_description = automatic Erlang node discovery via redis -pkg_redgrid_homepage = https://github.com/jkvor/redgrid -pkg_redgrid_fetch = git -pkg_redgrid_repo = https://github.com/jkvor/redgrid -pkg_redgrid_commit = master - -PACKAGES += redo -pkg_redo_name = redo -pkg_redo_description = pipelined erlang redis client -pkg_redo_homepage = https://github.com/jkvor/redo -pkg_redo_fetch = git -pkg_redo_repo = https://github.com/jkvor/redo -pkg_redo_commit = master - -PACKAGES += reltool_util -pkg_reltool_util_name = reltool_util -pkg_reltool_util_description = Erlang reltool utility functionality application -pkg_reltool_util_homepage = https://github.com/okeuday/reltool_util -pkg_reltool_util_fetch = git -pkg_reltool_util_repo = https://github.com/okeuday/reltool_util -pkg_reltool_util_commit = master - -PACKAGES += relx -pkg_relx_name = relx -pkg_relx_description = Sane, simple release creation for Erlang -pkg_relx_homepage = https://github.com/erlware/relx -pkg_relx_fetch = git -pkg_relx_repo = https://github.com/erlware/relx -pkg_relx_commit = master - -PACKAGES += resource_discovery -pkg_resource_discovery_name = resource_discovery -pkg_resource_discovery_description = An application used to dynamically discover resources present in an Erlang node cluster. -pkg_resource_discovery_homepage = http://erlware.org/ -pkg_resource_discovery_fetch = git -pkg_resource_discovery_repo = https://github.com/erlware/resource_discovery -pkg_resource_discovery_commit = master - -PACKAGES += restc -pkg_restc_name = restc -pkg_restc_description = Erlang Rest Client -pkg_restc_homepage = https://github.com/kivra/restclient -pkg_restc_fetch = git -pkg_restc_repo = https://github.com/kivra/restclient -pkg_restc_commit = master - -PACKAGES += rfc4627_jsonrpc -pkg_rfc4627_jsonrpc_name = rfc4627_jsonrpc -pkg_rfc4627_jsonrpc_description = Erlang RFC4627 (JSON) codec and JSON-RPC server implementation. -pkg_rfc4627_jsonrpc_homepage = https://github.com/tonyg/erlang-rfc4627 -pkg_rfc4627_jsonrpc_fetch = git -pkg_rfc4627_jsonrpc_repo = https://github.com/tonyg/erlang-rfc4627 -pkg_rfc4627_jsonrpc_commit = master - -PACKAGES += riakc -pkg_riakc_name = riakc -pkg_riakc_description = Erlang clients for Riak. -pkg_riakc_homepage = https://github.com/basho/riak-erlang-client -pkg_riakc_fetch = git -pkg_riakc_repo = https://github.com/basho/riak-erlang-client -pkg_riakc_commit = master - -PACKAGES += riak_core -pkg_riak_core_name = riak_core -pkg_riak_core_description = Distributed systems infrastructure used by Riak. -pkg_riak_core_homepage = https://github.com/basho/riak_core -pkg_riak_core_fetch = git -pkg_riak_core_repo = https://github.com/basho/riak_core -pkg_riak_core_commit = master - -PACKAGES += riak_dt -pkg_riak_dt_name = riak_dt -pkg_riak_dt_description = Convergent replicated datatypes in Erlang -pkg_riak_dt_homepage = https://github.com/basho/riak_dt -pkg_riak_dt_fetch = git -pkg_riak_dt_repo = https://github.com/basho/riak_dt -pkg_riak_dt_commit = master - -PACKAGES += riak_ensemble -pkg_riak_ensemble_name = riak_ensemble -pkg_riak_ensemble_description = Multi-Paxos framework in Erlang -pkg_riak_ensemble_homepage = https://github.com/basho/riak_ensemble -pkg_riak_ensemble_fetch = git -pkg_riak_ensemble_repo = https://github.com/basho/riak_ensemble -pkg_riak_ensemble_commit = master - -PACKAGES += riakhttpc -pkg_riakhttpc_name = riakhttpc -pkg_riakhttpc_description = Riak Erlang client using the HTTP interface -pkg_riakhttpc_homepage = https://github.com/basho/riak-erlang-http-client -pkg_riakhttpc_fetch = git -pkg_riakhttpc_repo = https://github.com/basho/riak-erlang-http-client -pkg_riakhttpc_commit = master - -PACKAGES += riak_kv -pkg_riak_kv_name = riak_kv -pkg_riak_kv_description = Riak Key/Value Store -pkg_riak_kv_homepage = https://github.com/basho/riak_kv -pkg_riak_kv_fetch = git -pkg_riak_kv_repo = https://github.com/basho/riak_kv -pkg_riak_kv_commit = master - -PACKAGES += riaknostic -pkg_riaknostic_name = riaknostic -pkg_riaknostic_description = A diagnostic tool for Riak installations, to find common errors asap -pkg_riaknostic_homepage = https://github.com/basho/riaknostic -pkg_riaknostic_fetch = git -pkg_riaknostic_repo = https://github.com/basho/riaknostic -pkg_riaknostic_commit = master - -PACKAGES += riak_pg -pkg_riak_pg_name = riak_pg -pkg_riak_pg_description = Distributed process groups with riak_core. -pkg_riak_pg_homepage = https://github.com/cmeiklejohn/riak_pg -pkg_riak_pg_fetch = git -pkg_riak_pg_repo = https://github.com/cmeiklejohn/riak_pg -pkg_riak_pg_commit = master - -PACKAGES += riak_pipe -pkg_riak_pipe_name = riak_pipe -pkg_riak_pipe_description = Riak Pipelines -pkg_riak_pipe_homepage = https://github.com/basho/riak_pipe -pkg_riak_pipe_fetch = git -pkg_riak_pipe_repo = https://github.com/basho/riak_pipe -pkg_riak_pipe_commit = master - -PACKAGES += riakpool -pkg_riakpool_name = riakpool -pkg_riakpool_description = erlang riak client pool -pkg_riakpool_homepage = https://github.com/dweldon/riakpool -pkg_riakpool_fetch = git -pkg_riakpool_repo = https://github.com/dweldon/riakpool -pkg_riakpool_commit = master - -PACKAGES += riak_sysmon -pkg_riak_sysmon_name = riak_sysmon -pkg_riak_sysmon_description = Simple OTP app for managing Erlang VM system_monitor event messages -pkg_riak_sysmon_homepage = https://github.com/basho/riak_sysmon -pkg_riak_sysmon_fetch = git -pkg_riak_sysmon_repo = https://github.com/basho/riak_sysmon -pkg_riak_sysmon_commit = master - -PACKAGES += riak_test -pkg_riak_test_name = riak_test -pkg_riak_test_description = I'm in your cluster, testing your riaks -pkg_riak_test_homepage = https://github.com/basho/riak_test -pkg_riak_test_fetch = git -pkg_riak_test_repo = https://github.com/basho/riak_test -pkg_riak_test_commit = master - -PACKAGES += rivus_cep -pkg_rivus_cep_name = rivus_cep -pkg_rivus_cep_description = Complex event processing in Erlang -pkg_rivus_cep_homepage = https://github.com/vascokk/rivus_cep -pkg_rivus_cep_fetch = git -pkg_rivus_cep_repo = https://github.com/vascokk/rivus_cep -pkg_rivus_cep_commit = master - -PACKAGES += rlimit -pkg_rlimit_name = rlimit -pkg_rlimit_description = Magnus Klaar's rate limiter code from etorrent -pkg_rlimit_homepage = https://github.com/jlouis/rlimit -pkg_rlimit_fetch = git -pkg_rlimit_repo = https://github.com/jlouis/rlimit -pkg_rlimit_commit = master - -PACKAGES += safetyvalve -pkg_safetyvalve_name = safetyvalve -pkg_safetyvalve_description = A safety valve for your erlang node -pkg_safetyvalve_homepage = https://github.com/jlouis/safetyvalve -pkg_safetyvalve_fetch = git -pkg_safetyvalve_repo = https://github.com/jlouis/safetyvalve -pkg_safetyvalve_commit = master - -PACKAGES += seestar -pkg_seestar_name = seestar -pkg_seestar_description = The Erlang client for Cassandra 1.2+ binary protocol -pkg_seestar_homepage = https://github.com/iamaleksey/seestar -pkg_seestar_fetch = git -pkg_seestar_repo = https://github.com/iamaleksey/seestar -pkg_seestar_commit = master - -PACKAGES += service -pkg_service_name = service -pkg_service_description = A minimal Erlang behavior for creating CloudI internal services -pkg_service_homepage = http://cloudi.org/ -pkg_service_fetch = git -pkg_service_repo = https://github.com/CloudI/service -pkg_service_commit = master - -PACKAGES += setup -pkg_setup_name = setup -pkg_setup_description = Generic setup utility for Erlang-based systems -pkg_setup_homepage = https://github.com/uwiger/setup -pkg_setup_fetch = git -pkg_setup_repo = https://github.com/uwiger/setup -pkg_setup_commit = master - -PACKAGES += sext -pkg_sext_name = sext -pkg_sext_description = Sortable Erlang Term Serialization -pkg_sext_homepage = https://github.com/uwiger/sext -pkg_sext_fetch = git -pkg_sext_repo = https://github.com/uwiger/sext -pkg_sext_commit = master - -PACKAGES += sfmt -pkg_sfmt_name = sfmt -pkg_sfmt_description = SFMT pseudo random number generator for Erlang. -pkg_sfmt_homepage = https://github.com/jj1bdx/sfmt-erlang -pkg_sfmt_fetch = git -pkg_sfmt_repo = https://github.com/jj1bdx/sfmt-erlang -pkg_sfmt_commit = master - -PACKAGES += sgte -pkg_sgte_name = sgte -pkg_sgte_description = A simple Erlang Template Engine -pkg_sgte_homepage = https://github.com/filippo/sgte -pkg_sgte_fetch = git -pkg_sgte_repo = https://github.com/filippo/sgte -pkg_sgte_commit = master - -PACKAGES += sheriff -pkg_sheriff_name = sheriff -pkg_sheriff_description = Parse transform for type based validation. -pkg_sheriff_homepage = http://ninenines.eu -pkg_sheriff_fetch = git -pkg_sheriff_repo = https://github.com/extend/sheriff -pkg_sheriff_commit = master - -PACKAGES += shotgun -pkg_shotgun_name = shotgun -pkg_shotgun_description = better than just a gun -pkg_shotgun_homepage = https://github.com/inaka/shotgun -pkg_shotgun_fetch = git -pkg_shotgun_repo = https://github.com/inaka/shotgun -pkg_shotgun_commit = 0.1.0 - -PACKAGES += sidejob -pkg_sidejob_name = sidejob -pkg_sidejob_description = Parallel worker and capacity limiting library for Erlang -pkg_sidejob_homepage = https://github.com/basho/sidejob -pkg_sidejob_fetch = git -pkg_sidejob_repo = https://github.com/basho/sidejob -pkg_sidejob_commit = master - -PACKAGES += sieve -pkg_sieve_name = sieve -pkg_sieve_description = sieve is a simple TCP routing proxy (layer 7) in erlang -pkg_sieve_homepage = https://github.com/benoitc/sieve -pkg_sieve_fetch = git -pkg_sieve_repo = https://github.com/benoitc/sieve -pkg_sieve_commit = master - -PACKAGES += sighandler -pkg_sighandler_name = sighandler -pkg_sighandler_description = Handle UNIX signals in Er lang -pkg_sighandler_homepage = https://github.com/jkingsbery/sighandler -pkg_sighandler_fetch = git -pkg_sighandler_repo = https://github.com/jkingsbery/sighandler -pkg_sighandler_commit = master - -PACKAGES += simhash -pkg_simhash_name = simhash -pkg_simhash_description = Simhashing for Erlang -- hashing algorithm to find near-duplicates in binary data. -pkg_simhash_homepage = https://github.com/ferd/simhash -pkg_simhash_fetch = git -pkg_simhash_repo = https://github.com/ferd/simhash -pkg_simhash_commit = master - -PACKAGES += simple_bridge -pkg_simple_bridge_name = simple_bridge -pkg_simple_bridge_description = A simple, standardized interface library to Erlang HTTP Servers. -pkg_simple_bridge_homepage = https://github.com/nitrogen/simple_bridge -pkg_simple_bridge_fetch = git -pkg_simple_bridge_repo = https://github.com/nitrogen/simple_bridge -pkg_simple_bridge_commit = master - -PACKAGES += simple_oauth2 -pkg_simple_oauth2_name = simple_oauth2 -pkg_simple_oauth2_description = Simple erlang OAuth2 client module for any http server framework (Google, Facebook, Yandex, Vkontakte are preconfigured) -pkg_simple_oauth2_homepage = https://github.com/virtan/simple_oauth2 -pkg_simple_oauth2_fetch = git -pkg_simple_oauth2_repo = https://github.com/virtan/simple_oauth2 -pkg_simple_oauth2_commit = master - -PACKAGES += skel -pkg_skel_name = skel -pkg_skel_description = A Streaming Process-based Skeleton Library for Erlang -pkg_skel_homepage = https://github.com/ParaPhrase/skel -pkg_skel_fetch = git -pkg_skel_repo = https://github.com/ParaPhrase/skel -pkg_skel_commit = master - -PACKAGES += smother -pkg_smother_name = smother -pkg_smother_description = Extended code coverage metrics for Erlang. -pkg_smother_homepage = https://ramsay-t.github.io/Smother/ -pkg_smother_fetch = git -pkg_smother_repo = https://github.com/ramsay-t/Smother -pkg_smother_commit = master - -PACKAGES += social -pkg_social_name = social -pkg_social_description = Cowboy handler for social login via OAuth2 providers -pkg_social_homepage = https://github.com/dvv/social -pkg_social_fetch = git -pkg_social_repo = https://github.com/dvv/social -pkg_social_commit = master - -PACKAGES += spapi_router -pkg_spapi_router_name = spapi_router -pkg_spapi_router_description = Partially-connected Erlang clustering -pkg_spapi_router_homepage = https://github.com/spilgames/spapi-router -pkg_spapi_router_fetch = git -pkg_spapi_router_repo = https://github.com/spilgames/spapi-router -pkg_spapi_router_commit = master - -PACKAGES += sqerl -pkg_sqerl_name = sqerl -pkg_sqerl_description = An Erlang-flavoured SQL DSL -pkg_sqerl_homepage = https://github.com/hairyhum/sqerl -pkg_sqerl_fetch = git -pkg_sqerl_repo = https://github.com/hairyhum/sqerl -pkg_sqerl_commit = master - -PACKAGES += srly -pkg_srly_name = srly -pkg_srly_description = Native Erlang Unix serial interface -pkg_srly_homepage = https://github.com/msantos/srly -pkg_srly_fetch = git -pkg_srly_repo = https://github.com/msantos/srly -pkg_srly_commit = master - -PACKAGES += sshrpc -pkg_sshrpc_name = sshrpc -pkg_sshrpc_description = Erlang SSH RPC module (experimental) -pkg_sshrpc_homepage = https://github.com/jj1bdx/sshrpc -pkg_sshrpc_fetch = git -pkg_sshrpc_repo = https://github.com/jj1bdx/sshrpc -pkg_sshrpc_commit = master - -PACKAGES += stable -pkg_stable_name = stable -pkg_stable_description = Library of assorted helpers for Cowboy web server. -pkg_stable_homepage = https://github.com/dvv/stable -pkg_stable_fetch = git -pkg_stable_repo = https://github.com/dvv/stable -pkg_stable_commit = master - -PACKAGES += statebox -pkg_statebox_name = statebox -pkg_statebox_description = Erlang state monad with merge/conflict-resolution capabilities. Useful for Riak. -pkg_statebox_homepage = https://github.com/mochi/statebox -pkg_statebox_fetch = git -pkg_statebox_repo = https://github.com/mochi/statebox -pkg_statebox_commit = master - -PACKAGES += statebox_riak -pkg_statebox_riak_name = statebox_riak -pkg_statebox_riak_description = Convenience library that makes it easier to use statebox with riak, extracted from best practices in our production code at Mochi Media. -pkg_statebox_riak_homepage = https://github.com/mochi/statebox_riak -pkg_statebox_riak_fetch = git -pkg_statebox_riak_repo = https://github.com/mochi/statebox_riak -pkg_statebox_riak_commit = master - -PACKAGES += statman -pkg_statman_name = statman -pkg_statman_description = Efficiently collect massive volumes of metrics inside the Erlang VM -pkg_statman_homepage = https://github.com/knutin/statman -pkg_statman_fetch = git -pkg_statman_repo = https://github.com/knutin/statman -pkg_statman_commit = master - -PACKAGES += statsderl -pkg_statsderl_name = statsderl -pkg_statsderl_description = StatsD client (erlang) -pkg_statsderl_homepage = https://github.com/lpgauth/statsderl -pkg_statsderl_fetch = git -pkg_statsderl_repo = https://github.com/lpgauth/statsderl -pkg_statsderl_commit = master - -PACKAGES += stdinout_pool -pkg_stdinout_pool_name = stdinout_pool -pkg_stdinout_pool_description = stdinout_pool : stuff goes in, stuff goes out. there's never any miscommunication. -pkg_stdinout_pool_homepage = https://github.com/mattsta/erlang-stdinout-pool -pkg_stdinout_pool_fetch = git -pkg_stdinout_pool_repo = https://github.com/mattsta/erlang-stdinout-pool -pkg_stdinout_pool_commit = master - -PACKAGES += stockdb -pkg_stockdb_name = stockdb -pkg_stockdb_description = Database for storing Stock Exchange quotes in erlang -pkg_stockdb_homepage = https://github.com/maxlapshin/stockdb -pkg_stockdb_fetch = git -pkg_stockdb_repo = https://github.com/maxlapshin/stockdb -pkg_stockdb_commit = master - -PACKAGES += stripe -pkg_stripe_name = stripe -pkg_stripe_description = Erlang interface to the stripe.com API -pkg_stripe_homepage = https://github.com/mattsta/stripe-erlang -pkg_stripe_fetch = git -pkg_stripe_repo = https://github.com/mattsta/stripe-erlang -pkg_stripe_commit = v1 - -PACKAGES += surrogate -pkg_surrogate_name = surrogate -pkg_surrogate_description = Proxy server written in erlang. Supports reverse proxy load balancing and forward proxy with http (including CONNECT), socks4, socks5, and transparent proxy modes. -pkg_surrogate_homepage = https://github.com/skruger/Surrogate -pkg_surrogate_fetch = git -pkg_surrogate_repo = https://github.com/skruger/Surrogate -pkg_surrogate_commit = master - -PACKAGES += swab -pkg_swab_name = swab -pkg_swab_description = General purpose buffer handling module -pkg_swab_homepage = https://github.com/crownedgrouse/swab -pkg_swab_fetch = git -pkg_swab_repo = https://github.com/crownedgrouse/swab -pkg_swab_commit = master - -PACKAGES += swarm -pkg_swarm_name = swarm -pkg_swarm_description = Fast and simple acceptor pool for Erlang -pkg_swarm_homepage = https://github.com/jeremey/swarm -pkg_swarm_fetch = git -pkg_swarm_repo = https://github.com/jeremey/swarm -pkg_swarm_commit = master - -PACKAGES += switchboard -pkg_switchboard_name = switchboard -pkg_switchboard_description = A framework for processing email using worker plugins. -pkg_switchboard_homepage = https://github.com/thusfresh/switchboard -pkg_switchboard_fetch = git -pkg_switchboard_repo = https://github.com/thusfresh/switchboard -pkg_switchboard_commit = master - -PACKAGES += sync -pkg_sync_name = sync -pkg_sync_description = On-the-fly recompiling and reloading in Erlang. -pkg_sync_homepage = https://github.com/rustyio/sync -pkg_sync_fetch = git -pkg_sync_repo = https://github.com/rustyio/sync -pkg_sync_commit = master - -PACKAGES += syn -pkg_syn_name = syn -pkg_syn_description = A global process registry for Erlang. -pkg_syn_homepage = https://github.com/ostinelli/syn -pkg_syn_fetch = git -pkg_syn_repo = https://github.com/ostinelli/syn -pkg_syn_commit = master - -PACKAGES += syntaxerl -pkg_syntaxerl_name = syntaxerl -pkg_syntaxerl_description = Syntax checker for Erlang -pkg_syntaxerl_homepage = https://github.com/ten0s/syntaxerl -pkg_syntaxerl_fetch = git -pkg_syntaxerl_repo = https://github.com/ten0s/syntaxerl -pkg_syntaxerl_commit = master - -PACKAGES += syslog -pkg_syslog_name = syslog -pkg_syslog_description = Erlang port driver for interacting with syslog via syslog(3) -pkg_syslog_homepage = https://github.com/Vagabond/erlang-syslog -pkg_syslog_fetch = git -pkg_syslog_repo = https://github.com/Vagabond/erlang-syslog -pkg_syslog_commit = master - -PACKAGES += taskforce -pkg_taskforce_name = taskforce -pkg_taskforce_description = Erlang worker pools for controlled parallelisation of arbitrary tasks. -pkg_taskforce_homepage = https://github.com/g-andrade/taskforce -pkg_taskforce_fetch = git -pkg_taskforce_repo = https://github.com/g-andrade/taskforce -pkg_taskforce_commit = master - -PACKAGES += tddreloader -pkg_tddreloader_name = tddreloader -pkg_tddreloader_description = Shell utility for recompiling, reloading, and testing code as it changes -pkg_tddreloader_homepage = https://github.com/version2beta/tddreloader -pkg_tddreloader_fetch = git -pkg_tddreloader_repo = https://github.com/version2beta/tddreloader -pkg_tddreloader_commit = master - -PACKAGES += tempo -pkg_tempo_name = tempo -pkg_tempo_description = NIF-based date and time parsing and formatting for Erlang. -pkg_tempo_homepage = https://github.com/selectel/tempo -pkg_tempo_fetch = git -pkg_tempo_repo = https://github.com/selectel/tempo -pkg_tempo_commit = master - -PACKAGES += ticktick -pkg_ticktick_name = ticktick -pkg_ticktick_description = Ticktick is an id generator for message service. -pkg_ticktick_homepage = https://github.com/ericliang/ticktick -pkg_ticktick_fetch = git -pkg_ticktick_repo = https://github.com/ericliang/ticktick -pkg_ticktick_commit = master - -PACKAGES += tinymq -pkg_tinymq_name = tinymq -pkg_tinymq_description = TinyMQ - a diminutive, in-memory message queue -pkg_tinymq_homepage = https://github.com/ChicagoBoss/tinymq -pkg_tinymq_fetch = git -pkg_tinymq_repo = https://github.com/ChicagoBoss/tinymq -pkg_tinymq_commit = master - -PACKAGES += tinymt -pkg_tinymt_name = tinymt -pkg_tinymt_description = TinyMT pseudo random number generator for Erlang. -pkg_tinymt_homepage = https://github.com/jj1bdx/tinymt-erlang -pkg_tinymt_fetch = git -pkg_tinymt_repo = https://github.com/jj1bdx/tinymt-erlang -pkg_tinymt_commit = master - -PACKAGES += tirerl -pkg_tirerl_name = tirerl -pkg_tirerl_description = Erlang interface to Elastic Search -pkg_tirerl_homepage = https://github.com/inaka/tirerl -pkg_tirerl_fetch = git -pkg_tirerl_repo = https://github.com/inaka/tirerl -pkg_tirerl_commit = master - -PACKAGES += traffic_tools -pkg_traffic_tools_name = traffic_tools -pkg_traffic_tools_description = Simple traffic limiting library -pkg_traffic_tools_homepage = https://github.com/systra/traffic_tools -pkg_traffic_tools_fetch = git -pkg_traffic_tools_repo = https://github.com/systra/traffic_tools -pkg_traffic_tools_commit = master - -PACKAGES += trails -pkg_trails_name = trails -pkg_trails_description = A couple of improvements over Cowboy Routes -pkg_trails_homepage = http://inaka.github.io/cowboy-trails/ -pkg_trails_fetch = git -pkg_trails_repo = https://github.com/inaka/cowboy-trails -pkg_trails_commit = master - -PACKAGES += trane -pkg_trane_name = trane -pkg_trane_description = SAX style broken HTML parser in Erlang -pkg_trane_homepage = https://github.com/massemanet/trane -pkg_trane_fetch = git -pkg_trane_repo = https://github.com/massemanet/trane -pkg_trane_commit = master - -PACKAGES += transit -pkg_transit_name = transit -pkg_transit_description = transit format for erlang -pkg_transit_homepage = https://github.com/isaiah/transit-erlang -pkg_transit_fetch = git -pkg_transit_repo = https://github.com/isaiah/transit-erlang -pkg_transit_commit = master - -PACKAGES += trie -pkg_trie_name = trie -pkg_trie_description = Erlang Trie Implementation -pkg_trie_homepage = https://github.com/okeuday/trie -pkg_trie_fetch = git -pkg_trie_repo = https://github.com/okeuday/trie -pkg_trie_commit = master - -PACKAGES += triq -pkg_triq_name = triq -pkg_triq_description = Trifork QuickCheck -pkg_triq_homepage = https://github.com/krestenkrab/triq -pkg_triq_fetch = git -pkg_triq_repo = https://github.com/krestenkrab/triq -pkg_triq_commit = master - -PACKAGES += tunctl -pkg_tunctl_name = tunctl -pkg_tunctl_description = Erlang TUN/TAP interface -pkg_tunctl_homepage = https://github.com/msantos/tunctl -pkg_tunctl_fetch = git -pkg_tunctl_repo = https://github.com/msantos/tunctl -pkg_tunctl_commit = master - -PACKAGES += twerl -pkg_twerl_name = twerl -pkg_twerl_description = Erlang client for the Twitter Streaming API -pkg_twerl_homepage = https://github.com/lucaspiller/twerl -pkg_twerl_fetch = git -pkg_twerl_repo = https://github.com/lucaspiller/twerl -pkg_twerl_commit = oauth - -PACKAGES += twitter_erlang -pkg_twitter_erlang_name = twitter_erlang -pkg_twitter_erlang_description = An Erlang twitter client -pkg_twitter_erlang_homepage = https://github.com/ngerakines/erlang_twitter -pkg_twitter_erlang_fetch = git -pkg_twitter_erlang_repo = https://github.com/ngerakines/erlang_twitter -pkg_twitter_erlang_commit = master - -PACKAGES += ucol_nif -pkg_ucol_nif_name = ucol_nif -pkg_ucol_nif_description = ICU based collation Erlang module -pkg_ucol_nif_homepage = https://github.com/refuge/ucol_nif -pkg_ucol_nif_fetch = git -pkg_ucol_nif_repo = https://github.com/refuge/ucol_nif -pkg_ucol_nif_commit = master - -PACKAGES += unicorn -pkg_unicorn_name = unicorn -pkg_unicorn_description = Generic configuration server -pkg_unicorn_homepage = https://github.com/shizzard/unicorn -pkg_unicorn_fetch = git -pkg_unicorn_repo = https://github.com/shizzard/unicorn -pkg_unicorn_commit = 0.3.0 - -PACKAGES += unsplit -pkg_unsplit_name = unsplit -pkg_unsplit_description = Resolves conflicts in Mnesia after network splits -pkg_unsplit_homepage = https://github.com/uwiger/unsplit -pkg_unsplit_fetch = git -pkg_unsplit_repo = https://github.com/uwiger/unsplit -pkg_unsplit_commit = master - -PACKAGES += uuid -pkg_uuid_name = uuid -pkg_uuid_description = Erlang UUID Implementation -pkg_uuid_homepage = https://github.com/okeuday/uuid -pkg_uuid_fetch = git -pkg_uuid_repo = https://github.com/okeuday/uuid -pkg_uuid_commit = v1.4.0 - -PACKAGES += ux -pkg_ux_name = ux -pkg_ux_description = Unicode eXtention for Erlang (Strings, Collation) -pkg_ux_homepage = https://github.com/erlang-unicode/ux -pkg_ux_fetch = git -pkg_ux_repo = https://github.com/erlang-unicode/ux -pkg_ux_commit = master - -PACKAGES += vert -pkg_vert_name = vert -pkg_vert_description = Erlang binding to libvirt virtualization API -pkg_vert_homepage = https://github.com/msantos/erlang-libvirt -pkg_vert_fetch = git -pkg_vert_repo = https://github.com/msantos/erlang-libvirt -pkg_vert_commit = master - -PACKAGES += verx -pkg_verx_name = verx -pkg_verx_description = Erlang implementation of the libvirtd remote protocol -pkg_verx_homepage = https://github.com/msantos/verx -pkg_verx_fetch = git -pkg_verx_repo = https://github.com/msantos/verx -pkg_verx_commit = master - -PACKAGES += vmq_acl -pkg_vmq_acl_name = vmq_acl -pkg_vmq_acl_description = Component of VerneMQ: A distributed MQTT message broker -pkg_vmq_acl_homepage = https://verne.mq/ -pkg_vmq_acl_fetch = git -pkg_vmq_acl_repo = https://github.com/erlio/vmq_acl -pkg_vmq_acl_commit = master - -PACKAGES += vmq_bridge -pkg_vmq_bridge_name = vmq_bridge -pkg_vmq_bridge_description = Component of VerneMQ: A distributed MQTT message broker -pkg_vmq_bridge_homepage = https://verne.mq/ -pkg_vmq_bridge_fetch = git -pkg_vmq_bridge_repo = https://github.com/erlio/vmq_bridge -pkg_vmq_bridge_commit = master - -PACKAGES += vmq_graphite -pkg_vmq_graphite_name = vmq_graphite -pkg_vmq_graphite_description = Component of VerneMQ: A distributed MQTT message broker -pkg_vmq_graphite_homepage = https://verne.mq/ -pkg_vmq_graphite_fetch = git -pkg_vmq_graphite_repo = https://github.com/erlio/vmq_graphite -pkg_vmq_graphite_commit = master - -PACKAGES += vmq_passwd -pkg_vmq_passwd_name = vmq_passwd -pkg_vmq_passwd_description = Component of VerneMQ: A distributed MQTT message broker -pkg_vmq_passwd_homepage = https://verne.mq/ -pkg_vmq_passwd_fetch = git -pkg_vmq_passwd_repo = https://github.com/erlio/vmq_passwd -pkg_vmq_passwd_commit = master - -PACKAGES += vmq_server -pkg_vmq_server_name = vmq_server -pkg_vmq_server_description = Component of VerneMQ: A distributed MQTT message broker -pkg_vmq_server_homepage = https://verne.mq/ -pkg_vmq_server_fetch = git -pkg_vmq_server_repo = https://github.com/erlio/vmq_server -pkg_vmq_server_commit = master - -PACKAGES += vmq_snmp -pkg_vmq_snmp_name = vmq_snmp -pkg_vmq_snmp_description = Component of VerneMQ: A distributed MQTT message broker -pkg_vmq_snmp_homepage = https://verne.mq/ -pkg_vmq_snmp_fetch = git -pkg_vmq_snmp_repo = https://github.com/erlio/vmq_snmp -pkg_vmq_snmp_commit = master - -PACKAGES += vmq_systree -pkg_vmq_systree_name = vmq_systree -pkg_vmq_systree_description = Component of VerneMQ: A distributed MQTT message broker -pkg_vmq_systree_homepage = https://verne.mq/ -pkg_vmq_systree_fetch = git -pkg_vmq_systree_repo = https://github.com/erlio/vmq_systree -pkg_vmq_systree_commit = master - -PACKAGES += vmstats -pkg_vmstats_name = vmstats -pkg_vmstats_description = tiny Erlang app that works in conjunction with statsderl in order to generate information on the Erlang VM for graphite logs. -pkg_vmstats_homepage = https://github.com/ferd/vmstats -pkg_vmstats_fetch = git -pkg_vmstats_repo = https://github.com/ferd/vmstats -pkg_vmstats_commit = master - -PACKAGES += walrus -pkg_walrus_name = walrus -pkg_walrus_description = Walrus - Mustache-like Templating -pkg_walrus_homepage = https://github.com/devinus/walrus -pkg_walrus_fetch = git -pkg_walrus_repo = https://github.com/devinus/walrus -pkg_walrus_commit = master - -PACKAGES += webmachine -pkg_webmachine_name = webmachine -pkg_webmachine_description = A REST-based system for building web applications. -pkg_webmachine_homepage = https://github.com/basho/webmachine -pkg_webmachine_fetch = git -pkg_webmachine_repo = https://github.com/basho/webmachine -pkg_webmachine_commit = master - -PACKAGES += websocket_client -pkg_websocket_client_name = websocket_client -pkg_websocket_client_description = Erlang websocket client (ws and wss supported) -pkg_websocket_client_homepage = https://github.com/jeremyong/websocket_client -pkg_websocket_client_fetch = git -pkg_websocket_client_repo = https://github.com/jeremyong/websocket_client -pkg_websocket_client_commit = master - -PACKAGES += worker_pool -pkg_worker_pool_name = worker_pool -pkg_worker_pool_description = a simple erlang worker pool -pkg_worker_pool_homepage = https://github.com/inaka/worker_pool -pkg_worker_pool_fetch = git -pkg_worker_pool_repo = https://github.com/inaka/worker_pool -pkg_worker_pool_commit = 1.0.2 - -PACKAGES += wrangler -pkg_wrangler_name = wrangler -pkg_wrangler_description = Import of the Wrangler svn repository. -pkg_wrangler_homepage = http://www.cs.kent.ac.uk/projects/wrangler/Home.html -pkg_wrangler_fetch = git -pkg_wrangler_repo = https://github.com/RefactoringTools/wrangler -pkg_wrangler_commit = master - -PACKAGES += wsock -pkg_wsock_name = wsock -pkg_wsock_description = Erlang library to build WebSocket clients and servers -pkg_wsock_homepage = https://github.com/madtrick/wsock -pkg_wsock_fetch = git -pkg_wsock_repo = https://github.com/madtrick/wsock -pkg_wsock_commit = master - -PACKAGES += xhttpc -pkg_xhttpc_name = xhttpc -pkg_xhttpc_description = Extensible HTTP Client for Erlang -pkg_xhttpc_homepage = https://github.com/seriyps/xhttpc -pkg_xhttpc_fetch = git -pkg_xhttpc_repo = https://github.com/seriyps/xhttpc -pkg_xhttpc_commit = master - -PACKAGES += xref_runner -pkg_xref_runner_name = xref_runner -pkg_xref_runner_description = Erlang Xref Runner (inspired in rebar xref) -pkg_xref_runner_homepage = https://github.com/inaka/xref_runner -pkg_xref_runner_fetch = git -pkg_xref_runner_repo = https://github.com/inaka/xref_runner -pkg_xref_runner_commit = 0.2.0 - -PACKAGES += yamerl -pkg_yamerl_name = yamerl -pkg_yamerl_description = YAML 1.2 parser in pure Erlang -pkg_yamerl_homepage = https://github.com/yakaz/yamerl -pkg_yamerl_fetch = git -pkg_yamerl_repo = https://github.com/yakaz/yamerl -pkg_yamerl_commit = master - -PACKAGES += yamler -pkg_yamler_name = yamler -pkg_yamler_description = libyaml-based yaml loader for Erlang -pkg_yamler_homepage = https://github.com/goertzenator/yamler -pkg_yamler_fetch = git -pkg_yamler_repo = https://github.com/goertzenator/yamler -pkg_yamler_commit = master - -PACKAGES += yaws -pkg_yaws_name = yaws -pkg_yaws_description = Yaws webserver -pkg_yaws_homepage = http://yaws.hyber.org -pkg_yaws_fetch = git -pkg_yaws_repo = https://github.com/klacke/yaws -pkg_yaws_commit = master - -PACKAGES += zab_engine -pkg_zab_engine_name = zab_engine -pkg_zab_engine_description = zab propotocol implement by erlang -pkg_zab_engine_homepage = https://github.com/xinmingyao/zab_engine -pkg_zab_engine_fetch = git -pkg_zab_engine_repo = https://github.com/xinmingyao/zab_engine -pkg_zab_engine_commit = master - -PACKAGES += zeta -pkg_zeta_name = zeta -pkg_zeta_description = HTTP access log parser in Erlang -pkg_zeta_homepage = https://github.com/s1n4/zeta -pkg_zeta_fetch = git -pkg_zeta_repo = https://github.com/s1n4/zeta -pkg_zeta_commit = - -PACKAGES += zippers -pkg_zippers_name = zippers -pkg_zippers_description = A library for functional zipper data structures in Erlang. Read more on zippers -pkg_zippers_homepage = https://github.com/ferd/zippers -pkg_zippers_fetch = git -pkg_zippers_repo = https://github.com/ferd/zippers -pkg_zippers_commit = master - -PACKAGES += zlists -pkg_zlists_name = zlists -pkg_zlists_description = Erlang lazy lists library. -pkg_zlists_homepage = https://github.com/vjache/erlang-zlists -pkg_zlists_fetch = git -pkg_zlists_repo = https://github.com/vjache/erlang-zlists -pkg_zlists_commit = master - -PACKAGES += zraft_lib -pkg_zraft_lib_name = zraft_lib -pkg_zraft_lib_description = Erlang raft consensus protocol implementation -pkg_zraft_lib_homepage = https://github.com/dreyk/zraft_lib -pkg_zraft_lib_fetch = git -pkg_zraft_lib_repo = https://github.com/dreyk/zraft_lib -pkg_zraft_lib_commit = master - -PACKAGES += zucchini -pkg_zucchini_name = zucchini -pkg_zucchini_description = An Erlang INI parser -pkg_zucchini_homepage = https://github.com/devinus/zucchini -pkg_zucchini_fetch = git -pkg_zucchini_repo = https://github.com/devinus/zucchini -pkg_zucchini_commit = master - -# Copyright (c) 2015, Loïc Hoguin -# This file is part of erlang.mk and subject to the terms of the ISC License. - -.PHONY: search - -define pkg_print - $(verbose) printf "%s\n" \ - $(if $(call core_eq,$(1),$(pkg_$(1)_name)),,"Pkg name: $(1)") \ - "App name: $(pkg_$(1)_name)" \ - "Description: $(pkg_$(1)_description)" \ - "Home page: $(pkg_$(1)_homepage)" \ - "Fetch with: $(pkg_$(1)_fetch)" \ - "Repository: $(pkg_$(1)_repo)" \ - "Commit: $(pkg_$(1)_commit)" \ - "" - -endef - -search: -ifdef q - $(foreach p,$(PACKAGES), \ - $(if $(findstring $(call core_lc,$(q)),$(call core_lc,$(pkg_$(p)_name) $(pkg_$(p)_description))), \ - $(call pkg_print,$(p)))) -else - $(foreach p,$(PACKAGES),$(call pkg_print,$(p))) -endif - -# Copyright (c) 2013-2015, Loïc Hoguin -# This file is part of erlang.mk and subject to the terms of the ISC License. - -.PHONY: distclean-deps distclean-pkg - -# Configuration. - -IGNORE_DEPS ?= - -DEPS_DIR ?= $(CURDIR)/deps -export DEPS_DIR - -REBAR_DEPS_DIR = $(DEPS_DIR) -export REBAR_DEPS_DIR - -ALL_DEPS_DIRS = $(addprefix $(DEPS_DIR)/,$(filter-out $(IGNORE_DEPS),$(DEPS))) - -ifeq ($(filter $(DEPS_DIR),$(subst :, ,$(ERL_LIBS))),) -ifeq ($(ERL_LIBS),) - ERL_LIBS = $(DEPS_DIR) -else - ERL_LIBS := $(ERL_LIBS):$(DEPS_DIR) -endif -endif -export ERL_LIBS - -# Verbosity. - -dep_verbose_0 = @echo " DEP " $(1); -dep_verbose = $(dep_verbose_$(V)) - -# Core targets. - -ifneq ($(SKIP_DEPS),) -deps:: -else -deps:: $(ALL_DEPS_DIRS) -ifneq ($(IS_DEP),1) - $(verbose) rm -f $(ERLANG_MK_TMP)/deps.log -endif - $(verbose) mkdir -p $(ERLANG_MK_TMP) - $(verbose) for dep in $(ALL_DEPS_DIRS) ; do \ - if grep -qs ^$$dep$$ $(ERLANG_MK_TMP)/deps.log; then \ - echo -n; \ - else \ - echo $$dep >> $(ERLANG_MK_TMP)/deps.log; \ - if [ -f $$dep/GNUmakefile ] || [ -f $$dep/makefile ] || [ -f $$dep/Makefile ]; then \ - $(MAKE) -C $$dep IS_DEP=1 || exit $$?; \ - else \ - echo "ERROR: No Makefile to build dependency $$dep."; \ - exit 1; \ - fi \ - fi \ - done -endif - -distclean:: distclean-deps distclean-pkg - -# Deps related targets. - -# @todo rename GNUmakefile and makefile into Makefile first, if they exist -# While Makefile file could be GNUmakefile or makefile, -# in practice only Makefile is needed so far. -define dep_autopatch - if [ -f $(DEPS_DIR)/$(1)/Makefile ]; then \ - if [ 0 != `grep -c "include ../\w*\.mk" $(DEPS_DIR)/$(1)/Makefile` ]; then \ - $(call dep_autopatch2,$(1)); \ - elif [ 0 != `grep -ci rebar $(DEPS_DIR)/$(1)/Makefile` ]; then \ - $(call dep_autopatch2,$(1)); \ - elif [ -n "`find $(DEPS_DIR)/$(1)/ -type f -name \*.mk -not -name erlang.mk | xargs -r grep -i rebar`" ]; then \ - $(call dep_autopatch2,$(1)); \ - else \ - if [ -f $(DEPS_DIR)/$(1)/erlang.mk ]; then \ - $(call erlang,$(call dep_autopatch_appsrc.erl,$(1))); \ - $(call dep_autopatch_erlang_mk,$(1)); \ - else \ - $(call erlang,$(call dep_autopatch_app.erl,$(1))); \ - fi \ - fi \ - else \ - if [ ! -d $(DEPS_DIR)/$(1)/src/ ]; then \ - $(call dep_autopatch_noop,$(1)); \ - else \ - $(call dep_autopatch2,$(1)); \ - fi \ - fi -endef - -define dep_autopatch2 - $(call erlang,$(call dep_autopatch_appsrc.erl,$(1))); \ - if [ -f $(DEPS_DIR)/$(1)/rebar.config -o -f $(DEPS_DIR)/$(1)/rebar.config.script ]; then \ - $(call dep_autopatch_fetch_rebar); \ - $(call dep_autopatch_rebar,$(1)); \ - else \ - $(call dep_autopatch_gen,$(1)); \ - fi -endef - -define dep_autopatch_noop - printf "noop:\n" > $(DEPS_DIR)/$(1)/Makefile -endef - -# Overwrite erlang.mk with the current file by default. -ifeq ($(NO_AUTOPATCH_ERLANG_MK),) -define dep_autopatch_erlang_mk - echo "include $(ERLANG_MK_FILENAME)" > $(DEPS_DIR)/$(1)/erlang.mk -endef -else -define dep_autopatch_erlang_mk - echo -n -endef -endif - -define dep_autopatch_gen - printf "%s\n" \ - "ERLC_OPTS = +debug_info" \ - "include ../../erlang.mk" > $(DEPS_DIR)/$(1)/Makefile -endef - -define dep_autopatch_fetch_rebar - mkdir -p $(ERLANG_MK_TMP); \ - if [ ! -d $(ERLANG_MK_TMP)/rebar ]; then \ - git clone -q -n -- https://github.com/rebar/rebar $(ERLANG_MK_TMP)/rebar; \ - cd $(ERLANG_MK_TMP)/rebar; \ - git checkout -q 791db716b5a3a7671e0b351f95ddf24b848ee173; \ - $(MAKE); \ - cd -; \ - fi -endef - -define dep_autopatch_rebar - if [ -f $(DEPS_DIR)/$(1)/Makefile ]; then \ - mv $(DEPS_DIR)/$(1)/Makefile $(DEPS_DIR)/$(1)/Makefile.orig.mk; \ - fi; \ - $(call erlang,$(call dep_autopatch_rebar.erl,$(1))); \ - rm -f $(DEPS_DIR)/$(1)/ebin/$(1).app -endef - -define dep_autopatch_rebar.erl - application:set_env(rebar, log_level, debug), - Conf1 = case file:consult("$(DEPS_DIR)/$(1)/rebar.config") of - {ok, Conf0} -> Conf0; - _ -> [] - end, - {Conf, OsEnv} = fun() -> - case filelib:is_file("$(DEPS_DIR)/$(1)/rebar.config.script") of - false -> {Conf1, []}; - true -> - Bindings0 = erl_eval:new_bindings(), - Bindings1 = erl_eval:add_binding('CONFIG', Conf1, Bindings0), - Bindings = erl_eval:add_binding('SCRIPT', "$(DEPS_DIR)/$(1)/rebar.config.script", Bindings1), - Before = os:getenv(), - {ok, Conf2} = file:script("$(DEPS_DIR)/$(1)/rebar.config.script", Bindings), - {Conf2, lists:foldl(fun(E, Acc) -> lists:delete(E, Acc) end, os:getenv(), Before)} - end - end(), - Write = fun (Text) -> - file:write_file("$(DEPS_DIR)/$(1)/Makefile", Text, [append]) - end, - Escape = fun (Text) -> - re:replace(Text, "\\\\$$$$", "\$$$$$$$$", [global, {return, list}]) - end, - Write("IGNORE_DEPS = edown eper eunit_formatters meck node_package " - "rebar_lock_deps_plugin rebar_vsn_plugin reltool_util\n"), - Write("C_SRC_DIR = /path/do/not/exist\n"), - Write("DRV_CFLAGS = -fPIC\nexport DRV_CFLAGS\n"), - Write(["ERLANG_ARCH = ", rebar_utils:wordsize(), "\nexport ERLANG_ARCH\n"]), - fun() -> - Write("ERLC_OPTS = +debug_info\nexport ERLC_OPTS\n"), - case lists:keyfind(erl_opts, 1, Conf) of - false -> ok; - {_, ErlOpts} -> - lists:foreach(fun - ({d, D}) -> - Write("ERLC_OPTS += -D" ++ atom_to_list(D) ++ "=1\n"); - ({i, I}) -> - Write(["ERLC_OPTS += -I ", I, "\n"]); - ({platform_define, Regex, D}) -> - case rebar_utils:is_arch(Regex) of - true -> Write("ERLC_OPTS += -D" ++ atom_to_list(D) ++ "=1\n"); - false -> ok - end; - ({parse_transform, PT}) -> - Write("ERLC_OPTS += +'{parse_transform, " ++ atom_to_list(PT) ++ "}'\n"); - (_) -> ok - end, ErlOpts) - end, - Write("\n") - end(), - fun() -> - File = case lists:keyfind(deps, 1, Conf) of - false -> []; - {_, Deps} -> - [begin case case Dep of - {N, S} when is_atom(N), is_list(S) -> {N, {hex, S}}; - {N, S} when is_tuple(S) -> {N, S}; - {N, _, S} -> {N, S}; - {N, _, S, _} -> {N, S}; - _ -> false - end of - false -> ok; - {Name, Source} -> - {Method, Repo, Commit} = case Source of - {hex, V} -> {hex, undefined, V}; - {git, R} -> {git, R, master}; - {M, R, {branch, C}} -> {M, R, C}; - {M, R, {ref, C}} -> {M, R, C}; - {M, R, {tag, C}} -> {M, R, C}; - {M, R, C} -> {M, R, C} - end, - Write(io_lib:format("DEPS += ~s\ndep_~s = ~s ~s ~s~n", [Name, Name, Method, Repo, Commit])) - end end || Dep <- Deps] - end - end(), - fun() -> - case lists:keyfind(erl_first_files, 1, Conf) of - false -> ok; - {_, Files} -> - Names = [[" ", case lists:reverse(F) of - "lre." ++ Elif -> lists:reverse(Elif); - Elif -> lists:reverse(Elif) - end] || "src/" ++ F <- Files], - Write(io_lib:format("COMPILE_FIRST +=~s\n", [Names])) - end - end(), - FindFirst = fun(F, Fd) -> - case io:parse_erl_form(Fd, undefined) of - {ok, {attribute, _, compile, {parse_transform, PT}}, _} -> - [PT, F(F, Fd)]; - {ok, {attribute, _, compile, CompileOpts}, _} when is_list(CompileOpts) -> - case proplists:get_value(parse_transform, CompileOpts) of - undefined -> [F(F, Fd)]; - PT -> [PT, F(F, Fd)] - end; - {ok, {attribute, _, include, Hrl}, _} -> - case file:open("$(DEPS_DIR)/$(1)/include/" ++ Hrl, [read]) of - {ok, HrlFd} -> [F(F, HrlFd), F(F, Fd)]; - _ -> - case file:open("$(DEPS_DIR)/$(1)/src/" ++ Hrl, [read]) of - {ok, HrlFd} -> [F(F, HrlFd), F(F, Fd)]; - _ -> [F(F, Fd)] - end - end; - {ok, {attribute, _, include_lib, "$(1)/include/" ++ Hrl}, _} -> - {ok, HrlFd} = file:open("$(DEPS_DIR)/$(1)/include/" ++ Hrl, [read]), - [F(F, HrlFd), F(F, Fd)]; - {ok, {attribute, _, include_lib, Hrl}, _} -> - case file:open("$(DEPS_DIR)/$(1)/include/" ++ Hrl, [read]) of - {ok, HrlFd} -> [F(F, HrlFd), F(F, Fd)]; - _ -> [F(F, Fd)] - end; - {ok, {attribute, _, import, {Imp, _}}, _} -> - case file:open("$(DEPS_DIR)/$(1)/src/" ++ atom_to_list(Imp) ++ ".erl", [read]) of - {ok, ImpFd} -> [Imp, F(F, ImpFd), F(F, Fd)]; - _ -> [F(F, Fd)] - end; - {eof, _} -> - file:close(Fd), - []; - _ -> - F(F, Fd) - end - end, - fun() -> - ErlFiles = filelib:wildcard("$(DEPS_DIR)/$(1)/src/*.erl"), - First0 = lists:usort(lists:flatten([begin - {ok, Fd} = file:open(F, [read]), - FindFirst(FindFirst, Fd) - end || F <- ErlFiles])), - First = lists:flatten([begin - {ok, Fd} = file:open("$(DEPS_DIR)/$(1)/src/" ++ atom_to_list(M) ++ ".erl", [read]), - FindFirst(FindFirst, Fd) - end || M <- First0, lists:member("$(DEPS_DIR)/$(1)/src/" ++ atom_to_list(M) ++ ".erl", ErlFiles)]) ++ First0, - Write(["COMPILE_FIRST +=", [[" ", atom_to_list(M)] || M <- First, - lists:member("$(DEPS_DIR)/$(1)/src/" ++ atom_to_list(M) ++ ".erl", ErlFiles)], "\n"]) - end(), - Write("\n\nrebar_dep: preprocess pre-deps deps pre-app app\n"), - Write("\npreprocess::\n"), - Write("\npre-deps::\n"), - Write("\npre-app::\n"), - PatchHook = fun(Cmd) -> - case Cmd of - "make -C" ++ Cmd1 -> "$$$$\(MAKE) -C" ++ Escape(Cmd1); - "gmake -C" ++ Cmd1 -> "$$$$\(MAKE) -C" ++ Escape(Cmd1); - "make " ++ Cmd1 -> "$$$$\(MAKE) -f Makefile.orig.mk " ++ Escape(Cmd1); - "gmake " ++ Cmd1 -> "$$$$\(MAKE) -f Makefile.orig.mk " ++ Escape(Cmd1); - _ -> Escape(Cmd) - end - end, - fun() -> - case lists:keyfind(pre_hooks, 1, Conf) of - false -> ok; - {_, Hooks} -> - [case H of - {'get-deps', Cmd} -> - Write("\npre-deps::\n\t" ++ PatchHook(Cmd) ++ "\n"); - {compile, Cmd} -> - Write("\npre-app::\n\tCC=$$$$\(CC) " ++ PatchHook(Cmd) ++ "\n"); - {Regex, compile, Cmd} -> - case rebar_utils:is_arch(Regex) of - true -> Write("\npre-app::\n\tCC=$$$$\(CC) " ++ PatchHook(Cmd) ++ "\n"); - false -> ok - end; - _ -> ok - end || H <- Hooks] - end - end(), - ShellToMk = fun(V) -> - re:replace(re:replace(V, "(\\\\$$$$)(\\\\w*)", "\\\\1(\\\\2)", [global]), - "-Werror\\\\b", "", [{return, list}, global]) - end, - PortSpecs = fun() -> - case lists:keyfind(port_specs, 1, Conf) of - false -> - case filelib:is_dir("$(DEPS_DIR)/$(1)/c_src") of - false -> []; - true -> - [{"priv/" ++ proplists:get_value(so_name, Conf, "$(1)_drv.so"), - proplists:get_value(port_sources, Conf, ["c_src/*.c"]), []}] - end; - {_, Specs} -> - lists:flatten([case S of - {Output, Input} -> {ShellToMk(Output), Input, []}; - {Regex, Output, Input} -> - case rebar_utils:is_arch(Regex) of - true -> {ShellToMk(Output), Input, []}; - false -> [] - end; - {Regex, Output, Input, [{env, Env}]} -> - case rebar_utils:is_arch(Regex) of - true -> {ShellToMk(Output), Input, Env}; - false -> [] - end - end || S <- Specs]) - end - end(), - PortSpecWrite = fun (Text) -> - file:write_file("$(DEPS_DIR)/$(1)/c_src/Makefile.erlang.mk", Text, [append]) - end, - case PortSpecs of - [] -> ok; - _ -> - Write("\npre-app::\n\t$$$$\(MAKE) -f c_src/Makefile.erlang.mk\n"), - PortSpecWrite(io_lib:format("ERL_CFLAGS = -finline-functions -Wall -fPIC -I ~s/erts-~s/include -I ~s\n", - [code:root_dir(), erlang:system_info(version), code:lib_dir(erl_interface, include)])), - PortSpecWrite(io_lib:format("ERL_LDFLAGS = -L ~s -lerl_interface -lei\n", - [code:lib_dir(erl_interface, lib)])), - [PortSpecWrite(["\n", E, "\n"]) || E <- OsEnv], - FilterEnv = fun(Env) -> - lists:flatten([case E of - {_, _} -> E; - {Regex, K, V} -> - case rebar_utils:is_arch(Regex) of - true -> {K, V}; - false -> [] - end - end || E <- Env]) - end, - MergeEnv = fun(Env) -> - lists:foldl(fun ({K, V}, Acc) -> - case lists:keyfind(K, 1, Acc) of - false -> [{K, rebar_utils:expand_env_variable(V, K, "")}|Acc]; - {_, V0} -> [{K, rebar_utils:expand_env_variable(V, K, V0)}|Acc] - end - end, [], Env) - end, - PortEnv = case lists:keyfind(port_env, 1, Conf) of - false -> []; - {_, PortEnv0} -> FilterEnv(PortEnv0) - end, - PortSpec = fun ({Output, Input0, Env}) -> - filelib:ensure_dir("$(DEPS_DIR)/$(1)/" ++ Output), - Input = [[" ", I] || I <- Input0], - PortSpecWrite([ - [["\n", K, " = ", ShellToMk(V)] || {K, V} <- lists:reverse(MergeEnv(PortEnv))], - case $(PLATFORM) of - darwin -> "\n\nLDFLAGS += -flat_namespace -undefined suppress"; - _ -> "" - end, - "\n\nall:: ", Output, "\n\n", - "%.o: %.c\n\t$$$$\(CC) -c -o $$$$\@ $$$$\< $$$$\(CFLAGS) $$$$\(ERL_CFLAGS) $$$$\(DRV_CFLAGS) $$$$\(EXE_CFLAGS)\n\n", - "%.o: %.C\n\t$$$$\(CXX) -c -o $$$$\@ $$$$\< $$$$\(CXXFLAGS) $$$$\(ERL_CFLAGS) $$$$\(DRV_CFLAGS) $$$$\(EXE_CFLAGS)\n\n", - "%.o: %.cc\n\t$$$$\(CXX) -c -o $$$$\@ $$$$\< $$$$\(CXXFLAGS) $$$$\(ERL_CFLAGS) $$$$\(DRV_CFLAGS) $$$$\(EXE_CFLAGS)\n\n", - "%.o: %.cpp\n\t$$$$\(CXX) -c -o $$$$\@ $$$$\< $$$$\(CXXFLAGS) $$$$\(ERL_CFLAGS) $$$$\(DRV_CFLAGS) $$$$\(EXE_CFLAGS)\n\n", - [[Output, ": ", K, " = ", ShellToMk(V), "\n"] || {K, V} <- lists:reverse(MergeEnv(FilterEnv(Env)))], - Output, ": $$$$\(foreach ext,.c .C .cc .cpp,", - "$$$$\(patsubst %$$$$\(ext),%.o,$$$$\(filter %$$$$\(ext),$$$$\(wildcard", Input, "))))\n", - "\t$$$$\(CC) -o $$$$\@ $$$$\? $$$$\(LDFLAGS) $$$$\(ERL_LDFLAGS) $$$$\(DRV_LDFLAGS) $$$$\(EXE_LDFLAGS)", - case filename:extension(Output) of - [] -> "\n"; - _ -> " -shared\n" - end]) - end, - [PortSpec(S) || S <- PortSpecs] - end, - Write("\ninclude $(ERLANG_MK_FILENAME)"), - RunPlugin = fun(Plugin, Step) -> - case erlang:function_exported(Plugin, Step, 2) of - false -> ok; - true -> - c:cd("$(DEPS_DIR)/$(1)/"), - Ret = Plugin:Step({config, "", Conf, dict:new(), dict:new(), dict:new(), - dict:store(base_dir, "", dict:new())}, undefined), - io:format("rebar plugin ~p step ~p ret ~p~n", [Plugin, Step, Ret]) - end - end, - fun() -> - case lists:keyfind(plugins, 1, Conf) of - false -> ok; - {_, Plugins} -> - [begin - case lists:keyfind(deps, 1, Conf) of - false -> ok; - {_, Deps} -> - case lists:keyfind(P, 1, Deps) of - false -> ok; - _ -> - Path = "$(DEPS_DIR)/" ++ atom_to_list(P), - io:format("~s", [os:cmd("$(MAKE) -C $(DEPS_DIR)/$(1) " ++ Path)]), - io:format("~s", [os:cmd("$(MAKE) -C " ++ Path ++ " IS_DEP=1")]), - code:add_patha(Path ++ "/ebin") - end - end - end || P <- Plugins], - [case code:load_file(P) of - {module, P} -> ok; - _ -> - case lists:keyfind(plugin_dir, 1, Conf) of - false -> ok; - {_, PluginsDir} -> - ErlFile = "$(DEPS_DIR)/$(1)/" ++ PluginsDir ++ "/" ++ atom_to_list(P) ++ ".erl", - {ok, P, Bin} = compile:file(ErlFile, [binary]), - {module, P} = code:load_binary(P, ErlFile, Bin) - end - end || P <- Plugins], - [RunPlugin(P, preprocess) || P <- Plugins], - [RunPlugin(P, pre_compile) || P <- Plugins] - end - end(), - halt() -endef - -define dep_autopatch_app.erl - UpdateModules = fun(App) -> - case filelib:is_regular(App) of - false -> ok; - true -> - {ok, [{application, $(1), L0}]} = file:consult(App), - Mods = filelib:fold_files("$(DEPS_DIR)/$(1)/src", "\\\\.erl$$$$", true, - fun (F, Acc) -> [list_to_atom(filename:rootname(filename:basename(F)))|Acc] end, []), - L = lists:keystore(modules, 1, L0, {modules, Mods}), - ok = file:write_file(App, io_lib:format("~p.~n", [{application, $(1), L}])) - end - end, - UpdateModules("$(DEPS_DIR)/$(1)/ebin/$(1).app"), - halt() -endef - -define dep_autopatch_appsrc.erl - AppSrcOut = "$(DEPS_DIR)/$(1)/src/$(1).app.src", - AppSrcIn = case filelib:is_regular(AppSrcOut) of false -> "$(DEPS_DIR)/$(1)/ebin/$(1).app"; true -> AppSrcOut end, - case filelib:is_regular(AppSrcIn) of - false -> ok; - true -> - {ok, [{application, $(1), L0}]} = file:consult(AppSrcIn), - L1 = lists:keystore(modules, 1, L0, {modules, []}), - L2 = case lists:keyfind(vsn, 1, L1) of {_, git} -> lists:keyreplace(vsn, 1, L1, {vsn, "git"}); _ -> L1 end, - L3 = case lists:keyfind(registered, 1, L2) of false -> [{registered, []}|L2]; _ -> L2 end, - ok = file:write_file(AppSrcOut, io_lib:format("~p.~n", [{application, $(1), L3}])), - case AppSrcOut of AppSrcIn -> ok; _ -> ok = file:delete(AppSrcIn) end - end, - halt() -endef - -define hex_fetch.erl - ssl:start(), - inets:start(), - {ok, {{_, 200, _}, _, Body}} = httpc:request(get, - {"https://s3.amazonaws.com/s3.hex.pm/tarballs/$(1)-$(2).tar", []}, - [], [{body_format, binary}]), - {ok, Files} = erl_tar:extract({binary, Body}, [memory]), - {_, Source} = lists:keyfind("contents.tar.gz", 1, Files), - ok = erl_tar:extract({binary, Source}, [{cwd, "$(DEPS_DIR)/$(1)"}, compressed]), - halt() -endef - -define dep_fetch - if [ "$(2)" = "git" ]; then \ - git clone -q -n -- $(3) $(DEPS_DIR)/$(1); \ - cd $(DEPS_DIR)/$(1) && git checkout -q $(4); \ - elif [ "$(2)" = "hg" ]; then \ - hg clone -q -U $(3) $(DEPS_DIR)/$(1); \ - cd $(DEPS_DIR)/$(1) && hg update -q $(4); \ - elif [ "$(2)" = "svn" ]; then \ - svn checkout -q $(3) $(DEPS_DIR)/$(1); \ - elif [ "$(2)" = "cp" ]; then \ - cp -R $(3) $(DEPS_DIR)/$(1); \ - elif [ "$(2)" = "hex" ]; then \ - $(call erlang,$(call hex_fetch.erl,$(1),$(strip $(4)))); \ - else \ - echo "Unknown or invalid dependency: $(1). Please consult the erlang.mk README for instructions." >&2; \ - exit 78; \ - fi -endef - -define dep_target -$(DEPS_DIR)/$(1): - $(verbose) mkdir -p $(DEPS_DIR) -ifeq (,$(dep_$(1))) - $(dep_verbose) $(call dep_fetch,$(pkg_$(1)_name),$(pkg_$(1)_fetch), \ - $(patsubst git://github.com/%,https://github.com/%,$(pkg_$(1)_repo)), \ - $(pkg_$(1)_commit)) -else -ifeq (1,$(words $(dep_$(1)))) - $(dep_verbose) $(call dep_fetch,$(1),git, \ - $(patsubst git://github.com/%,https://github.com/%,$(dep_$(1))), \ - master) -else -ifeq (2,$(words $(dep_$(1)))) - $(dep_verbose) $(call dep_fetch,$(1),git, \ - $(patsubst git://github.com/%,https://github.com/%,$(word 1,$(dep_$(1)))), \ - $(word 2,$(dep_$(1)))) -else - $(dep_verbose) $(call dep_fetch,$(1),$(word 1,$(dep_$(1))), \ - $(patsubst git://github.com/%,https://github.com/%,$(word 2,$(dep_$(1)))), \ - $(word 3,$(dep_$(1)))) -endif -endif -endif - $(verbose) if [ -f $(DEPS_DIR)/$(1)/configure.ac -o -f $(DEPS_DIR)/$(1)/configure.in ]; then \ - echo " AUTO " $(1); \ - cd $(DEPS_DIR)/$(1) && autoreconf -Wall -vif -I m4; \ - fi - - $(verbose) if [ -f $(DEPS_DIR)/$(1)/configure ]; then \ - echo " CONF " $(1); \ - cd $(DEPS_DIR)/$(1) && ./configure; \ - fi -ifeq ($(filter $(1),$(NO_AUTOPATCH)),) - $(verbose) if [ "$(1)" = "amqp_client" -a "$(RABBITMQ_CLIENT_PATCH)" ]; then \ - if [ ! -d $(DEPS_DIR)/rabbitmq-codegen ]; then \ - echo " PATCH Downloading rabbitmq-codegen"; \ - git clone https://github.com/rabbitmq/rabbitmq-codegen.git $(DEPS_DIR)/rabbitmq-codegen; \ - fi; \ - if [ ! -d $(DEPS_DIR)/rabbitmq-server ]; then \ - echo " PATCH Downloading rabbitmq-server"; \ - git clone https://github.com/rabbitmq/rabbitmq-server.git $(DEPS_DIR)/rabbitmq-server; \ - fi; \ - ln -s $(DEPS_DIR)/amqp_client/deps/rabbit_common-0.0.0 $(DEPS_DIR)/rabbit_common; \ - elif [ "$(1)" = "rabbit" -a "$(RABBITMQ_SERVER_PATCH)" ]; then \ - if [ ! -d $(DEPS_DIR)/rabbitmq-codegen ]; then \ - echo " PATCH Downloading rabbitmq-codegen"; \ - git clone https://github.com/rabbitmq/rabbitmq-codegen.git $(DEPS_DIR)/rabbitmq-codegen; \ - fi \ - else \ - $(call dep_autopatch,$(1)) \ - fi -endif -endef - -$(foreach dep,$(DEPS),$(eval $(call dep_target,$(dep)))) - -distclean-deps: - $(gen_verbose) rm -rf $(DEPS_DIR) - -# Copyright (c) 2015, Loïc Hoguin -# This file is part of erlang.mk and subject to the terms of the ISC License. - -# Verbosity. - -proto_verbose_0 = @echo " PROTO " $(filter %.proto,$(?F)); -proto_verbose = $(proto_verbose_$(V)) - -# Core targets. - -define compile_proto - $(verbose) mkdir -p ebin/ include/ - $(proto_verbose) $(call erlang,$(call compile_proto.erl,$(1))) - $(proto_verbose) erlc +debug_info -o ebin/ ebin/*.erl - $(verbose) rm ebin/*.erl -endef - -define compile_proto.erl - [begin - Dir = filename:dirname(filename:dirname(F)), - protobuffs_compile:generate_source(F, - [{output_include_dir, Dir ++ "/include"}, - {output_src_dir, Dir ++ "/ebin"}]) - end || F <- string:tokens("$(1)", " ")], - halt(). -endef - -ifneq ($(wildcard src/),) -ebin/$(PROJECT).app:: $(sort $(call core_find,src/,*.proto)) - $(if $(strip $?),$(call compile_proto,$?)) -endif - -# Copyright (c) 2013-2015, Loïc Hoguin -# This file is part of erlang.mk and subject to the terms of the ISC License. - -.PHONY: clean-app - -# Configuration. - -ERLC_OPTS ?= -Werror +debug_info +warn_export_vars +warn_shadow_vars \ - +warn_obsolete_guard # +bin_opt_info +warn_export_all +warn_missing_spec -COMPILE_FIRST ?= -COMPILE_FIRST_PATHS = $(addprefix src/,$(addsuffix .erl,$(COMPILE_FIRST))) -ERLC_EXCLUDE ?= -ERLC_EXCLUDE_PATHS = $(addprefix src/,$(addsuffix .erl,$(ERLC_EXCLUDE))) - -ERLC_MIB_OPTS ?= -COMPILE_MIB_FIRST ?= -COMPILE_MIB_FIRST_PATHS = $(addprefix mibs/,$(addsuffix .mib,$(COMPILE_MIB_FIRST))) - -# Verbosity. - -app_verbose_0 = @echo " APP " $(PROJECT); -app_verbose = $(app_verbose_$(V)) - -appsrc_verbose_0 = @echo " APP " $(PROJECT).app.src; -appsrc_verbose = $(appsrc_verbose_$(V)) - -erlc_verbose_0 = @echo " ERLC " $(filter-out $(patsubst %,%.erl,$(ERLC_EXCLUDE)),\ - $(filter %.erl %.core,$(?F))); -erlc_verbose = $(erlc_verbose_$(V)) - -xyrl_verbose_0 = @echo " XYRL " $(filter %.xrl %.yrl,$(?F)); -xyrl_verbose = $(xyrl_verbose_$(V)) - -asn1_verbose_0 = @echo " ASN1 " $(filter %.asn1,$(?F)); -asn1_verbose = $(asn1_verbose_$(V)) - -mib_verbose_0 = @echo " MIB " $(filter %.bin %.mib,$(?F)); -mib_verbose = $(mib_verbose_$(V)) - -# Targets. - -ifeq ($(wildcard ebin/test),) -app:: app-build -else -app:: clean app-build -endif - -ifeq ($(wildcard src/$(PROJECT)_app.erl),) -define app_file -{application, $(PROJECT), [ - {description, "$(PROJECT_DESCRIPTION)"}, - {vsn, "$(PROJECT_VERSION)"}, - {id, "$(1)"}, - {modules, [$(call comma_list,$(2))]}, - {registered, []}, - {applications, [$(call comma_list,kernel stdlib $(OTP_DEPS) $(DEPS))]} -]}. -endef -else -define app_file -{application, $(PROJECT), [ - {description, "$(PROJECT_DESCRIPTION)"}, - {vsn, "$(PROJECT_VERSION)"}, - {id, "$(1)"}, - {modules, [$(call comma_list,$(2))]}, - {registered, [$(call comma_list,$(PROJECT)_sup $(PROJECT_REGISTERED))]}, - {applications, [$(call comma_list,kernel stdlib $(OTP_DEPS) $(DEPS))]}, - {mod, {$(PROJECT)_app, []}} -]}. -endef -endif - -app-build: erlc-include ebin/$(PROJECT).app - $(eval GITDESCRIBE := $(shell git describe --dirty --abbrev=7 --tags --always --first-parent 2>/dev/null || true)) - $(eval MODULES := $(patsubst %,'%',$(sort $(notdir $(basename $(wildcard ebin/*.beam)))))) -ifeq ($(wildcard src/$(PROJECT).app.src),) - $(app_verbose) echo $(subst $(newline),,$(subst ",\",$(call app_file,$(GITDESCRIBE),$(MODULES)))) \ - > ebin/$(PROJECT).app -else - $(verbose) if [ -z "$$(grep -E '^[^%]*{\s*modules\s*,' src/$(PROJECT).app.src)" ]; then \ - echo "Empty modules entry not found in $(PROJECT).app.src. Please consult the erlang.mk README for instructions." >&2; \ - exit 1; \ - fi - $(appsrc_verbose) cat src/$(PROJECT).app.src \ - | sed "s/{[[:space:]]*modules[[:space:]]*,[[:space:]]*\[\]}/{modules, \[$(call comma_list,$(MODULES))\]}/" \ - | sed "s/{id,[[:space:]]*\"git\"}/{id, \"$(GITDESCRIBE)\"}/" \ - > ebin/$(PROJECT).app -endif - -erlc-include: - - $(verbose) if [ -d ebin/ ]; then \ - find include/ src/ -type f -name \*.hrl -newer ebin -exec touch $(shell find src/ -type f -name "*.erl") \; 2>/dev/null || printf ''; \ - fi - -define compile_erl - $(erlc_verbose) erlc -v $(if $(IS_DEP),$(filter-out -Werror,$(ERLC_OPTS)),$(ERLC_OPTS)) -o ebin/ \ - -pa ebin/ -I include/ $(filter-out $(ERLC_EXCLUDE_PATHS),\ - $(COMPILE_FIRST_PATHS) $(1)) -endef - -define compile_xyrl - $(xyrl_verbose) erlc -v -o ebin/ $(1) - $(xyrl_verbose) erlc $(ERLC_OPTS) -o ebin/ ebin/*.erl - $(verbose) rm ebin/*.erl -endef - -define compile_asn1 - $(asn1_verbose) erlc -v -I include/ -o ebin/ $(1) - $(verbose) mv ebin/*.hrl include/ - $(verbose) mv ebin/*.asn1db include/ - $(verbose) rm ebin/*.erl -endef - -define compile_mib - $(mib_verbose) erlc -v $(ERLC_MIB_OPTS) -o priv/mibs/ \ - -I priv/mibs/ $(COMPILE_MIB_FIRST_PATHS) $(1) - $(mib_verbose) erlc -o include/ -- priv/mibs/*.bin -endef - -ifneq ($(wildcard src/),) -ebin/$(PROJECT).app:: - $(verbose) mkdir -p ebin/ - -ifneq ($(wildcard asn1/),) -ebin/$(PROJECT).app:: $(sort $(call core_find,asn1/,*.asn1)) - $(verbose) mkdir -p include - $(if $(strip $?),$(call compile_asn1,$?)) -endif - -ifneq ($(wildcard mibs/),) -ebin/$(PROJECT).app:: $(sort $(call core_find,mibs/,*.mib)) - $(verbose) mkdir -p priv/mibs/ include - $(if $(strip $?),$(call compile_mib,$?)) -endif - -ebin/$(PROJECT).app:: $(sort $(call core_find,src/,*.erl *.core)) - $(if $(strip $?),$(call compile_erl,$?)) - -ebin/$(PROJECT).app:: $(sort $(call core_find,src/,*.xrl *.yrl)) - $(if $(strip $?),$(call compile_xyrl,$?)) -endif - -clean:: clean-app - -clean-app: - $(gen_verbose) rm -rf ebin/ priv/mibs/ \ - $(addprefix include/,$(addsuffix .hrl,$(notdir $(basename $(call core_find,mibs/,*.mib))))) - -# Copyright (c) 2015, Viktor Söderqvist -# This file is part of erlang.mk and subject to the terms of the ISC License. - -.PHONY: docs-deps - -# Configuration. - -ALL_DOC_DEPS_DIRS = $(addprefix $(DEPS_DIR)/,$(DOC_DEPS)) - -# Targets. - -$(foreach dep,$(DOC_DEPS),$(eval $(call dep_target,$(dep)))) - -ifneq ($(SKIP_DEPS),) -doc-deps: -else -doc-deps: $(ALL_DOC_DEPS_DIRS) - $(verbose) for dep in $(ALL_DOC_DEPS_DIRS) ; do $(MAKE) -C $$dep; done -endif - -# Copyright (c) 2015, Loïc Hoguin -# This file is part of erlang.mk and subject to the terms of the ISC License. - -.PHONY: test-deps test-dir test-build clean-test-dir - -# Configuration. - -TEST_DIR ?= $(CURDIR)/test - -ALL_TEST_DEPS_DIRS = $(addprefix $(DEPS_DIR)/,$(TEST_DEPS)) - -TEST_ERLC_OPTS ?= +debug_info +warn_export_vars +warn_shadow_vars +warn_obsolete_guard -TEST_ERLC_OPTS += -DTEST=1 - -# Targets. - -$(foreach dep,$(TEST_DEPS),$(eval $(call dep_target,$(dep)))) - -ifneq ($(SKIP_DEPS),) -test-deps: -else -test-deps: $(ALL_TEST_DEPS_DIRS) - $(verbose) for dep in $(ALL_TEST_DEPS_DIRS) ; do $(MAKE) -C $$dep IS_DEP=1; done -endif - -ifneq ($(wildcard $(TEST_DIR)),) -test-dir: - $(gen_verbose) erlc -v $(TEST_ERLC_OPTS) -I include/ -o $(TEST_DIR) \ - $(call core_find,$(TEST_DIR)/,*.erl) -pa ebin/ -endif - -ifeq ($(wildcard ebin/test),) -test-build:: ERLC_OPTS=$(TEST_ERLC_OPTS) -test-build:: clean deps test-deps - $(verbose) $(MAKE) --no-print-directory app-build test-dir ERLC_OPTS="$(TEST_ERLC_OPTS)" - $(gen_verbose) touch ebin/test -else -test-build:: ERLC_OPTS=$(TEST_ERLC_OPTS) -test-build:: deps test-deps - $(verbose) $(MAKE) --no-print-directory app-build test-dir ERLC_OPTS="$(TEST_ERLC_OPTS)" -endif - -clean:: clean-test-dir - -clean-test-dir: -ifneq ($(wildcard $(TEST_DIR)/*.beam),) - $(gen_verbose) rm -f $(TEST_DIR)/*.beam -endif - -# Copyright (c) 2015, Loïc Hoguin -# This file is part of erlang.mk and subject to the terms of the ISC License. - -.PHONY: asciidoc asciidoc-guide asciidoc-manual install-asciidoc distclean-asciidoc - -MAN_INSTALL_PATH ?= /usr/local/share/man -MAN_SECTIONS ?= 3 7 - -docs:: asciidoc - -asciidoc: distclean-asciidoc doc-deps asciidoc-guide asciidoc-manual - -ifeq ($(wildcard doc/src/guide/book.asciidoc),) -asciidoc-guide: -else -asciidoc-guide: - a2x -v -f pdf doc/src/guide/book.asciidoc && mv doc/src/guide/book.pdf doc/guide.pdf - a2x -v -f chunked doc/src/guide/book.asciidoc && mv doc/src/guide/book.chunked/ doc/html/ -endif - -ifeq ($(wildcard doc/src/manual/*.asciidoc),) -asciidoc-manual: -else -asciidoc-manual: - for f in doc/src/manual/*.asciidoc ; do \ - a2x -v -f manpage $$f ; \ - done - for s in $(MAN_SECTIONS); do \ - mkdir -p doc/man$$s/ ; \ - mv doc/src/manual/*.$$s doc/man$$s/ ; \ - gzip doc/man$$s/*.$$s ; \ - done - -install-docs:: install-asciidoc - -install-asciidoc: asciidoc-manual - for s in $(MAN_SECTIONS); do \ - mkdir -p $(MAN_INSTALL_PATH)/man$$s/ ; \ - install -g 0 -o 0 -m 0644 doc/man$$s/*.gz $(MAN_INSTALL_PATH)/man$$s/ ; \ - done -endif - -distclean:: distclean-asciidoc - -distclean-asciidoc: - $(gen_verbose) rm -rf doc/html/ doc/guide.pdf doc/man3/ doc/man7/ - -# Copyright (c) 2014-2015, Loïc Hoguin -# This file is part of erlang.mk and subject to the terms of the ISC License. - -.PHONY: bootstrap bootstrap-lib bootstrap-rel new list-templates - -# Core targets. - -help:: - $(verbose) printf "%s\n" "" \ - "Bootstrap targets:" \ - " bootstrap Generate a skeleton of an OTP application" \ - " bootstrap-lib Generate a skeleton of an OTP library" \ - " bootstrap-rel Generate the files needed to build a release" \ - " new t=TPL n=NAME Generate a module NAME based on the template TPL" \ - " list-templates List available templates" - -# Bootstrap templates. - -define bs_appsrc -{application, $(PROJECT), [ - {description, ""}, - {vsn, "0.1.0"}, - {id, "git"}, - {modules, []}, - {registered, []}, - {applications, [ - kernel, - stdlib - ]}, - {mod, {$(PROJECT)_app, []}}, - {env, []} -]}. -endef - -define bs_appsrc_lib -{application, $(PROJECT), [ - {description, ""}, - {vsn, "0.1.0"}, - {id, "git"}, - {modules, []}, - {registered, []}, - {applications, [ - kernel, - stdlib - ]} -]}. -endef - -ifdef SP -define bs_Makefile -PROJECT = $(PROJECT) - -# Whitespace to be used when creating files from templates. -SP = $(SP) - -include erlang.mk -endef -else -define bs_Makefile -PROJECT = $(PROJECT) -include erlang.mk -endef -endif - -define bs_app --module($(PROJECT)_app). --behaviour(application). - --export([start/2]). --export([stop/1]). - -start(_Type, _Args) -> - $(PROJECT)_sup:start_link(). - -stop(_State) -> - ok. -endef - -define bs_relx_config -{release, {$(PROJECT)_release, "1"}, [$(PROJECT)]}. -{extended_start_script, true}. -{sys_config, "rel/sys.config"}. -{vm_args, "rel/vm.args"}. -endef - -define bs_sys_config -[ -]. -endef - -define bs_vm_args --name $(PROJECT)@127.0.0.1 --setcookie $(PROJECT) --heart -endef - -# Normal templates. - -define tpl_supervisor --module($(n)). --behaviour(supervisor). - --export([start_link/0]). --export([init/1]). - -start_link() -> - supervisor:start_link({local, ?MODULE}, ?MODULE, []). - -init([]) -> - Procs = [], - {ok, {{one_for_one, 1, 5}, Procs}}. -endef - -define tpl_gen_server --module($(n)). --behaviour(gen_server). - -%% API. --export([start_link/0]). - -%% gen_server. --export([init/1]). --export([handle_call/3]). --export([handle_cast/2]). --export([handle_info/2]). --export([terminate/2]). --export([code_change/3]). - --record(state, { -}). - -%% API. - --spec start_link() -> {ok, pid()}. -start_link() -> - gen_server:start_link(?MODULE, [], []). - -%% gen_server. - -init([]) -> - {ok, #state{}}. - -handle_call(_Request, _From, State) -> - {reply, ignored, State}. - -handle_cast(_Msg, State) -> - {noreply, State}. - -handle_info(_Info, State) -> - {noreply, State}. - -terminate(_Reason, _State) -> - ok. - -code_change(_OldVsn, State, _Extra) -> - {ok, State}. -endef - -define tpl_cowboy_http --module($(n)). --behaviour(cowboy_http_handler). - --export([init/3]). --export([handle/2]). --export([terminate/3]). - --record(state, { -}). - -init(_, Req, _Opts) -> - {ok, Req, #state{}}. - -handle(Req, State=#state{}) -> - {ok, Req2} = cowboy_req:reply(200, Req), - {ok, Req2, State}. - -terminate(_Reason, _Req, _State) -> - ok. -endef - -define tpl_gen_fsm --module($(n)). --behaviour(gen_fsm). - -%% API. --export([start_link/0]). - -%% gen_fsm. --export([init/1]). --export([state_name/2]). --export([handle_event/3]). --export([state_name/3]). --export([handle_sync_event/4]). --export([handle_info/3]). --export([terminate/3]). --export([code_change/4]). - --record(state, { -}). - -%% API. - --spec start_link() -> {ok, pid()}. -start_link() -> - gen_fsm:start_link(?MODULE, [], []). - -%% gen_fsm. - -init([]) -> - {ok, state_name, #state{}}. - -state_name(_Event, StateData) -> - {next_state, state_name, StateData}. - -handle_event(_Event, StateName, StateData) -> - {next_state, StateName, StateData}. - -state_name(_Event, _From, StateData) -> - {reply, ignored, state_name, StateData}. - -handle_sync_event(_Event, _From, StateName, StateData) -> - {reply, ignored, StateName, StateData}. - -handle_info(_Info, StateName, StateData) -> - {next_state, StateName, StateData}. - -terminate(_Reason, _StateName, _StateData) -> - ok. - -code_change(_OldVsn, StateName, StateData, _Extra) -> - {ok, StateName, StateData}. -endef - -define tpl_cowboy_loop --module($(n)). --behaviour(cowboy_loop_handler). - --export([init/3]). --export([info/3]). --export([terminate/3]). - --record(state, { -}). - -init(_, Req, _Opts) -> - {loop, Req, #state{}, 5000, hibernate}. - -info(_Info, Req, State) -> - {loop, Req, State, hibernate}. - -terminate(_Reason, _Req, _State) -> - ok. -endef - -define tpl_cowboy_rest --module($(n)). - --export([init/3]). --export([content_types_provided/2]). --export([get_html/2]). - -init(_, _Req, _Opts) -> - {upgrade, protocol, cowboy_rest}. - -content_types_provided(Req, State) -> - {[{{<<"text">>, <<"html">>, '*'}, get_html}], Req, State}. - -get_html(Req, State) -> - {<<"This is REST!">>, Req, State}. -endef - -define tpl_cowboy_ws --module($(n)). --behaviour(cowboy_websocket_handler). - --export([init/3]). --export([websocket_init/3]). --export([websocket_handle/3]). --export([websocket_info/3]). --export([websocket_terminate/3]). - --record(state, { -}). - -init(_, _, _) -> - {upgrade, protocol, cowboy_websocket}. - -websocket_init(_, Req, _Opts) -> - Req2 = cowboy_req:compact(Req), - {ok, Req2, #state{}}. - -websocket_handle({text, Data}, Req, State) -> - {reply, {text, Data}, Req, State}; -websocket_handle({binary, Data}, Req, State) -> - {reply, {binary, Data}, Req, State}; -websocket_handle(_Frame, Req, State) -> - {ok, Req, State}. - -websocket_info(_Info, Req, State) -> - {ok, Req, State}. - -websocket_terminate(_Reason, _Req, _State) -> - ok. -endef - -define tpl_ranch_protocol --module($(n)). --behaviour(ranch_protocol). - --export([start_link/4]). --export([init/4]). - --type opts() :: []. --export_type([opts/0]). - --record(state, { - socket :: inet:socket(), - transport :: module() -}). - -start_link(Ref, Socket, Transport, Opts) -> - Pid = spawn_link(?MODULE, init, [Ref, Socket, Transport, Opts]), - {ok, Pid}. - --spec init(ranch:ref(), inet:socket(), module(), opts()) -> ok. -init(Ref, Socket, Transport, _Opts) -> - ok = ranch:accept_ack(Ref), - loop(#state{socket=Socket, transport=Transport}). - -loop(State) -> - loop(State). -endef - -# Plugin-specific targets. - -define render_template - $(verbose) echo "$${_$(1)}" > $(2) -endef - -ifndef WS -ifdef SP -WS = $(subst a,,a $(wordlist 1,$(SP),a a a a a a a a a a a a a a a a a a a a)) -else -WS = $(tab) -endif -endif - -$(foreach template,$(filter bs_% tpl_%,$(.VARIABLES)), \ - $(eval _$(template) = $$(subst $$(tab),$$(WS),$$($(template)))) \ - $(eval export _$(template))) - -bootstrap: -ifneq ($(wildcard src/),) - $(error Error: src/ directory already exists) -endif - $(call render_template,bs_Makefile,Makefile) - $(verbose) mkdir src/ - $(call render_template,bs_appsrc,src/$(PROJECT).app.src) - $(call render_template,bs_app,src/$(PROJECT)_app.erl) - $(eval n := $(PROJECT)_sup) - $(call render_template,tpl_supervisor,src/$(PROJECT)_sup.erl) - -bootstrap-lib: -ifneq ($(wildcard src/),) - $(error Error: src/ directory already exists) -endif - $(call render_template,bs_Makefile,Makefile) - $(verbose) mkdir src/ - $(call render_template,bs_appsrc_lib,src/$(PROJECT).app.src) - -bootstrap-rel: -ifneq ($(wildcard relx.config),) - $(error Error: relx.config already exists) -endif -ifneq ($(wildcard rel/),) - $(error Error: rel/ directory already exists) -endif - $(call render_template,bs_relx_config,relx.config) - $(verbose) mkdir rel/ - $(call render_template,bs_sys_config,rel/sys.config) - $(call render_template,bs_vm_args,rel/vm.args) - -new: -ifeq ($(wildcard src/),) - $(error Error: src/ directory does not exist) -endif -ifndef t - $(error Usage: $(MAKE) new t=TEMPLATE n=NAME) -endif -ifndef tpl_$(t) - $(error Unknown template) -endif -ifndef n - $(error Usage: $(MAKE) new t=TEMPLATE n=NAME) -endif - $(call render_template,tpl_$(t),src/$(n).erl) - -list-templates: - $(verbose) echo Available templates: $(sort $(patsubst tpl_%,%,$(filter tpl_%,$(.VARIABLES)))) - -# Copyright (c) 2014-2015, Loïc Hoguin -# This file is part of erlang.mk and subject to the terms of the ISC License. - -.PHONY: clean-c_src distclean-c_src-env - -# Configuration. - -C_SRC_DIR ?= $(CURDIR)/c_src -C_SRC_ENV ?= $(C_SRC_DIR)/env.mk -C_SRC_OUTPUT ?= $(CURDIR)/priv/$(PROJECT).so -C_SRC_TYPE ?= shared - -# System type and C compiler/flags. - -ifeq ($(PLATFORM),darwin) - CC ?= cc - CFLAGS ?= -O3 -std=c99 -arch x86_64 -finline-functions -Wall -Wmissing-prototypes - CXXFLAGS ?= -O3 -arch x86_64 -finline-functions -Wall - LDFLAGS ?= -arch x86_64 -flat_namespace -undefined suppress -else ifeq ($(PLATFORM),freebsd) - CC ?= cc - CFLAGS ?= -O3 -std=c99 -finline-functions -Wall -Wmissing-prototypes - CXXFLAGS ?= -O3 -finline-functions -Wall -else ifeq ($(PLATFORM),linux) - CC ?= gcc - CFLAGS ?= -O3 -std=c99 -finline-functions -Wall -Wmissing-prototypes - CXXFLAGS ?= -O3 -finline-functions -Wall -endif - -CFLAGS += -fPIC -I $(ERTS_INCLUDE_DIR) -I $(ERL_INTERFACE_INCLUDE_DIR) -CXXFLAGS += -fPIC -I $(ERTS_INCLUDE_DIR) -I $(ERL_INTERFACE_INCLUDE_DIR) - -LDLIBS += -L $(ERL_INTERFACE_LIB_DIR) -lerl_interface -lei - -ifeq ($(C_SRC_TYPE),shared) -LDFLAGS += -shared -endif - -# Verbosity. - -c_verbose_0 = @echo " C " $(?F); -c_verbose = $(c_verbose_$(V)) - -cpp_verbose_0 = @echo " CPP " $(?F); -cpp_verbose = $(cpp_verbose_$(V)) - -link_verbose_0 = @echo " LD " $(@F); -link_verbose = $(link_verbose_$(V)) - -# Targets. - -ifeq ($(wildcard $(C_SRC_DIR)),) -else ifneq ($(wildcard $(C_SRC_DIR)/Makefile),) -app:: app-c_src - -test-build:: app-c_src - -app-c_src: - $(MAKE) -C $(C_SRC_DIR) - -clean:: - $(MAKE) -C $(C_SRC_DIR) clean - -else - -ifeq ($(SOURCES),) -SOURCES := $(sort $(call core_find,$(C_SRC_DIR)/,*.c *.C *.cc *.cpp)) -endif -OBJECTS = $(addsuffix .o, $(basename $(SOURCES))) - -COMPILE_C = $(c_verbose) $(CC) $(CFLAGS) $(CPPFLAGS) -c -COMPILE_CPP = $(cpp_verbose) $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c - -app:: $(C_SRC_ENV) $(C_SRC_OUTPUT) - -test-build:: $(C_SRC_ENV) $(C_SRC_OUTPUT) - -$(C_SRC_OUTPUT): $(OBJECTS) - $(verbose) mkdir -p priv/ - $(link_verbose) $(CC) $(OBJECTS) $(LDFLAGS) $(LDLIBS) -o $(C_SRC_OUTPUT) - -%.o: %.c - $(COMPILE_C) $(OUTPUT_OPTION) $< - -%.o: %.cc - $(COMPILE_CPP) $(OUTPUT_OPTION) $< - -%.o: %.C - $(COMPILE_CPP) $(OUTPUT_OPTION) $< - -%.o: %.cpp - $(COMPILE_CPP) $(OUTPUT_OPTION) $< - -clean:: clean-c_src - -clean-c_src: - $(gen_verbose) rm -f $(C_SRC_OUTPUT) $(OBJECTS) - -endif - -ifneq ($(wildcard $(C_SRC_DIR)),) -$(C_SRC_ENV): - $(verbose) $(ERL) -eval "file:write_file(\"$(C_SRC_ENV)\", \ - io_lib:format( \ - \"ERTS_INCLUDE_DIR ?= ~s/erts-~s/include/~n\" \ - \"ERL_INTERFACE_INCLUDE_DIR ?= ~s~n\" \ - \"ERL_INTERFACE_LIB_DIR ?= ~s~n\", \ - [code:root_dir(), erlang:system_info(version), \ - code:lib_dir(erl_interface, include), \ - code:lib_dir(erl_interface, lib)])), \ - halt()." - -distclean:: distclean-c_src-env - -distclean-c_src-env: - $(gen_verbose) rm -f $(C_SRC_ENV) - --include $(C_SRC_ENV) -endif - -# Copyright (c) 2015, Loïc Hoguin -# This file is part of erlang.mk and subject to the terms of the ISC License. - -.PHONY: ci ci-setup distclean-kerl - -KERL ?= $(CURDIR)/kerl -export KERL - -KERL_URL ?= https://raw.githubusercontent.com/yrashk/kerl/master/kerl - -OTP_GIT ?= https://github.com/erlang/otp - -CI_INSTALL_DIR ?= $(HOME)/erlang -CI_OTP ?= - -ifeq ($(strip $(CI_OTP)),) -ci:: -else -ci:: $(addprefix ci-,$(CI_OTP)) - -ci-prepare: $(addprefix $(CI_INSTALL_DIR)/,$(CI_OTP)) - -ci-setup:: - -ci_verbose_0 = @echo " CI " $(1); -ci_verbose = $(ci_verbose_$(V)) - -define ci_target -ci-$(1): $(CI_INSTALL_DIR)/$(1) - $(ci_verbose) \ - PATH="$(CI_INSTALL_DIR)/$(1)/bin:$(PATH)" \ - CI_OTP_RELEASE="$(1)" \ - CT_OPTS="-label $(1)" \ - $(MAKE) clean ci-setup tests -endef - -$(foreach otp,$(CI_OTP),$(eval $(call ci_target,$(otp)))) - -define ci_otp_target -ifeq ($(wildcard $(CI_INSTALL_DIR)/$(1)),) -$(CI_INSTALL_DIR)/$(1): $(KERL) - $(KERL) build git $(OTP_GIT) $(1) $(1) - $(KERL) install $(1) $(CI_INSTALL_DIR)/$(1) -endif -endef - -$(foreach otp,$(CI_OTP),$(eval $(call ci_otp_target,$(otp)))) - -$(KERL): - $(gen_verbose) $(call core_http_get,$(KERL),$(KERL_URL)) - $(verbose) chmod +x $(KERL) - -help:: - $(verbose) printf "%s\n" "" \ - "Continuous Integration targets:" \ - " ci Run '$(MAKE) tests' on all configured Erlang versions." \ - "" \ - "The CI_OTP variable must be defined with the Erlang versions" \ - "that must be tested. For example: CI_OTP = OTP-17.3.4 OTP-17.5.3" - -distclean:: distclean-kerl - -distclean-kerl: - $(gen_verbose) rm -rf $(KERL) -endif - -# Copyright (c) 2013-2015, Loïc Hoguin -# This file is part of erlang.mk and subject to the terms of the ISC License. - -.PHONY: ct distclean-ct - -# Configuration. - -CT_OPTS ?= -ifneq ($(wildcard $(TEST_DIR)),) - CT_SUITES ?= $(sort $(subst _SUITE.erl,,$(notdir $(call core_find,$(TEST_DIR)/,*_SUITE.erl)))) -else - CT_SUITES ?= -endif - -# Core targets. - -tests:: ct - -distclean:: distclean-ct - -help:: - $(verbose) printf "%s\n" "" \ - "Common_test targets:" \ - " ct Run all the common_test suites for this project" \ - "" \ - "All your common_test suites have their associated targets." \ - "A suite named http_SUITE can be ran using the ct-http target." - -# Plugin-specific targets. - -CT_RUN = ct_run \ - -no_auto_compile \ - -noinput \ - -pa $(CURDIR)/ebin $(DEPS_DIR)/*/ebin $(TEST_DIR) \ - -dir $(TEST_DIR) \ - -logdir $(CURDIR)/logs - -ifeq ($(CT_SUITES),) -ct: -else -ct: test-build - $(verbose) mkdir -p $(CURDIR)/logs/ - $(gen_verbose) $(CT_RUN) -suite $(addsuffix _SUITE,$(CT_SUITES)) $(CT_OPTS) -endif - -define ct_suite_target -ct-$(1): test-build - $(verbose) mkdir -p $(CURDIR)/logs/ - $(gen_verbose) $(CT_RUN) -suite $(addsuffix _SUITE,$(1)) $(CT_OPTS) -endef - -$(foreach test,$(CT_SUITES),$(eval $(call ct_suite_target,$(test)))) - -distclean-ct: - $(gen_verbose) rm -rf $(CURDIR)/logs/ - -# Copyright (c) 2013-2015, Loïc Hoguin -# This file is part of erlang.mk and subject to the terms of the ISC License. - -.PHONY: plt distclean-plt dialyze - -# Configuration. - -DIALYZER_PLT ?= $(CURDIR)/.$(PROJECT).plt -export DIALYZER_PLT - -PLT_APPS ?= -DIALYZER_DIRS ?= --src -r src -DIALYZER_OPTS ?= -Werror_handling -Wrace_conditions \ - -Wunmatched_returns # -Wunderspecs - -# Core targets. - -check:: dialyze - -distclean:: distclean-plt - -help:: - $(verbose) printf "%s\n" "" \ - "Dialyzer targets:" \ - " plt Build a PLT file for this project" \ - " dialyze Analyze the project using Dialyzer" - -# Plugin-specific targets. - -$(DIALYZER_PLT): deps app - $(verbose) dialyzer --build_plt --apps erts kernel stdlib $(PLT_APPS) $(OTP_DEPS) $(ALL_DEPS_DIRS) - -plt: $(DIALYZER_PLT) - -distclean-plt: - $(gen_verbose) rm -f $(DIALYZER_PLT) - -ifneq ($(wildcard $(DIALYZER_PLT)),) -dialyze: -else -dialyze: $(DIALYZER_PLT) -endif - $(verbose) dialyzer --no_native $(DIALYZER_DIRS) $(DIALYZER_OPTS) - -# Copyright (c) 2013-2015, Loïc Hoguin -# This file is part of erlang.mk and subject to the terms of the ISC License. - -.PHONY: distclean-edoc edoc - -# Configuration. - -EDOC_OPTS ?= - -# Core targets. - -docs:: distclean-edoc edoc - -distclean:: distclean-edoc - -# Plugin-specific targets. - -edoc: doc-deps - $(gen_verbose) $(ERL) -eval 'edoc:application($(PROJECT), ".", [$(EDOC_OPTS)]), halt().' - -distclean-edoc: - $(gen_verbose) rm -f doc/*.css doc/*.html doc/*.png doc/edoc-info - -# Copyright (c) 2015, Erlang Solutions Ltd. -# This file is part of erlang.mk and subject to the terms of the ISC License. - -.PHONY: elvis distclean-elvis - -# Configuration. - -ELVIS_CONFIG ?= $(CURDIR)/elvis.config - -ELVIS ?= $(CURDIR)/elvis -export ELVIS - -ELVIS_URL ?= https://github.com/inaka/elvis/releases/download/0.2.5-beta2/elvis -ELVIS_CONFIG_URL ?= https://github.com/inaka/elvis/releases/download/0.2.5-beta2/elvis.config -ELVIS_OPTS ?= - -# Core targets. - -help:: - $(verbose) printf "%s\n" "" \ - "Elvis targets:" \ - " elvis Run Elvis using the local elvis.config or download the default otherwise" - -distclean:: distclean-elvis - -# Plugin-specific targets. - -$(ELVIS): - $(gen_verbose) $(call core_http_get,$(ELVIS),$(ELVIS_URL)) - $(verbose) chmod +x $(ELVIS) - -$(ELVIS_CONFIG): - $(verbose) $(call core_http_get,$(ELVIS_CONFIG),$(ELVIS_CONFIG_URL)) - -elvis: $(ELVIS) $(ELVIS_CONFIG) - $(verbose) $(ELVIS) rock -c $(ELVIS_CONFIG) $(ELVIS_OPTS) - -distclean-elvis: - $(gen_verbose) rm -rf $(ELVIS) - -# Copyright (c) 2013-2015, Loïc Hoguin -# This file is part of erlang.mk and subject to the terms of the ISC License. - -# Configuration. - -DTL_FULL_PATH ?= 0 - -# Verbosity. - -dtl_verbose_0 = @echo " DTL " $(filter %.dtl,$(?F)); -dtl_verbose = $(dtl_verbose_$(V)) - -# Core targets. - -define compile_erlydtl - $(dtl_verbose) $(ERL) -pa ebin/ $(DEPS_DIR)/erlydtl/ebin/ -eval ' \ - Compile = fun(F) -> \ - S = fun (1) -> re:replace(filename:rootname(string:sub_string(F, 11), ".dtl"), "/", "_", [{return, list}, global]); \ - (0) -> filename:basename(F, ".dtl") \ - end, \ - Module = list_to_atom(string:to_lower(S($(DTL_FULL_PATH))) ++ "_dtl"), \ - {ok, _} = erlydtl:compile(F, Module, [{out_dir, "ebin/"}, return_errors, {doc_root, "templates"}]) \ - end, \ - _ = [Compile(F) || F <- string:tokens("$(1)", " ")], \ - halt().' -endef - -ifneq ($(wildcard src/),) -ebin/$(PROJECT).app:: $(sort $(call core_find,templates/,*.dtl)) - $(if $(strip $?),$(call compile_erlydtl,$?)) -endif - -# Copyright (c) 2014 Dave Cottlehuber -# This file is part of erlang.mk and subject to the terms of the ISC License. - -.PHONY: distclean-escript escript - -# Configuration. - -ESCRIPT_NAME ?= $(PROJECT) -ESCRIPT_COMMENT ?= This is an -*- erlang -*- file - -ESCRIPT_BEAMS ?= "ebin/*", "deps/*/ebin/*" -ESCRIPT_SYS_CONFIG ?= "rel/sys.config" -ESCRIPT_EMU_ARGS ?= -pa . \ - -sasl errlog_type error \ - -escript main $(ESCRIPT_NAME) -ESCRIPT_SHEBANG ?= /usr/bin/env escript -ESCRIPT_STATIC ?= "deps/*/priv/**", "priv/**" - -# Core targets. - -distclean:: distclean-escript - -help:: - $(verbose) printf "%s\n" "" \ - "Escript targets:" \ - " escript Build an executable escript archive" \ - -# Plugin-specific targets. - -# Based on https://github.com/synrc/mad/blob/master/src/mad_bundle.erl -# Copyright (c) 2013 Maxim Sokhatsky, Synrc Research Center -# Modified MIT License, https://github.com/synrc/mad/blob/master/LICENSE : -# Software may only be used for the great good and the true happiness of all -# sentient beings. - -define ESCRIPT_RAW -'Read = fun(F) -> {ok, B} = file:read_file(filename:absname(F)), B end,'\ -'Files = fun(L) -> A = lists:concat([filelib:wildcard(X)||X<- L ]),'\ -' [F || F <- A, not filelib:is_dir(F) ] end,'\ -'Squash = fun(L) -> [{filename:basename(F), Read(F) } || F <- L ] end,'\ -'Zip = fun(A, L) -> {ok,{_,Z}} = zip:create(A, L, [{compress,all},memory]), Z end,'\ -'Ez = fun(Escript) ->'\ -' Static = Files([$(ESCRIPT_STATIC)]),'\ -' Beams = Squash(Files([$(ESCRIPT_BEAMS), $(ESCRIPT_SYS_CONFIG)])),'\ -' Archive = Beams ++ [{ "static.gz", Zip("static.gz", Static)}],'\ -' escript:create(Escript, [ $(ESCRIPT_OPTIONS)'\ -' {archive, Archive, [memory]},'\ -' {shebang, "$(ESCRIPT_SHEBANG)"},'\ -' {comment, "$(ESCRIPT_COMMENT)"},'\ -' {emu_args, " $(ESCRIPT_EMU_ARGS)"}'\ -' ]),'\ -' file:change_mode(Escript, 8#755)'\ -'end,'\ -'Ez("$(ESCRIPT_NAME)"),'\ -'halt().' -endef - -ESCRIPT_COMMAND = $(subst ' ',,$(ESCRIPT_RAW)) - -escript:: distclean-escript deps app - $(gen_verbose) $(ERL) -eval $(ESCRIPT_COMMAND) - -distclean-escript: - $(gen_verbose) rm -f $(ESCRIPT_NAME) - -# Copyright (c) 2014, Enrique Fernandez -# Copyright (c) 2015, Loïc Hoguin -# This file is contributed to erlang.mk and subject to the terms of the ISC License. - -.PHONY: eunit - -# Configuration - -EUNIT_OPTS ?= - -# Core targets. - -tests:: eunit - -help:: - $(verbose) printf "%s\n" "" \ - "EUnit targets:" \ - " eunit Run all the EUnit tests for this project" - -# Plugin-specific targets. - -define eunit.erl - case "$(COVER)" of - "" -> ok; - _ -> - case cover:compile_beam_directory("ebin") of - {error, _} -> halt(1); - _ -> ok - end - end, - case eunit:test([$(call comma_list,$(1))], [$(EUNIT_OPTS)]) of - ok -> ok; - error -> halt(2) - end, - case "$(COVER)" of - "" -> ok; - _ -> - cover:export("eunit.coverdata") - end, - halt() -endef - -EUNIT_EBIN_MODS = $(notdir $(basename $(call core_find,ebin/,*.beam))) -EUNIT_TEST_MODS = $(notdir $(basename $(call core_find,$(TEST_DIR)/,*.beam))) -EUNIT_MODS = $(foreach mod,$(EUNIT_EBIN_MODS) $(filter-out \ - $(patsubst %,%_tests,$(EUNIT_EBIN_MODS)),$(EUNIT_TEST_MODS)),{module,'$(mod)'}) - -eunit: test-build - $(gen_verbose) $(ERL) -pa $(TEST_DIR) $(DEPS_DIR)/*/ebin ebin \ - -eval "$(subst $(newline),,$(subst ",\",$(call eunit.erl,$(EUNIT_MODS))))" - -# Copyright (c) 2013-2015, Loïc Hoguin -# This file is part of erlang.mk and subject to the terms of the ISC License. - -.PHONY: relx-rel distclean-relx-rel distclean-relx run - -# Configuration. - -RELX_CONFIG ?= $(CURDIR)/relx.config - -RELX ?= $(CURDIR)/relx -export RELX - -RELX_URL ?= https://github.com/erlware/relx/releases/download/v2.0.0/relx -RELX_OPTS ?= -RELX_OUTPUT_DIR ?= _rel - -ifeq ($(firstword $(RELX_OPTS)),-o) - RELX_OUTPUT_DIR = $(word 2,$(RELX_OPTS)) -else - RELX_OPTS += -o $(RELX_OUTPUT_DIR) -endif - -# Core targets. - -ifeq ($(IS_DEP),) -ifneq ($(wildcard $(RELX_CONFIG)),) -rel:: distclean-relx-rel relx-rel -endif -endif - -distclean:: distclean-relx-rel distclean-relx - -# Plugin-specific targets. - -$(RELX): - $(gen_verbose) $(call core_http_get,$(RELX),$(RELX_URL)) - $(verbose) chmod +x $(RELX) - -relx-rel: $(RELX) - $(verbose) $(RELX) -c $(RELX_CONFIG) $(RELX_OPTS) - -distclean-relx-rel: - $(gen_verbose) rm -rf $(RELX_OUTPUT_DIR) - -distclean-relx: - $(gen_verbose) rm -rf $(RELX) - -# Run target. - -ifeq ($(wildcard $(RELX_CONFIG)),) -run: -else - -define get_relx_release.erl - {ok, Config} = file:consult("$(RELX_CONFIG)"), - {release, {Name, _}, _} = lists:keyfind(release, 1, Config), - io:format("~s", [Name]), - halt(0). -endef - -RELX_RELEASE = `$(call erlang,$(get_relx_release.erl))` - -run: all - $(verbose) $(RELX_OUTPUT_DIR)/$(RELX_RELEASE)/bin/$(RELX_RELEASE) console - -help:: - $(verbose) printf "%s\n" "" \ - "Relx targets:" \ - " run Compile the project, build the release and run it" - -endif - -# Copyright (c) 2014, M Robert Martin -# This file is contributed to erlang.mk and subject to the terms of the ISC License. - -.PHONY: shell - -# Configuration. - -SHELL_PATH ?= -pa $(CURDIR)/ebin $(DEPS_DIR)/*/ebin -SHELL_OPTS ?= - -ALL_SHELL_DEPS_DIRS = $(addprefix $(DEPS_DIR)/,$(SHELL_DEPS)) - -# Core targets - -help:: - $(verbose) printf "%s\n" "" \ - "Shell targets:" \ - " shell Run an erlang shell with SHELL_OPTS or reasonable default" - -# Plugin-specific targets. - -$(foreach dep,$(SHELL_DEPS),$(eval $(call dep_target,$(dep)))) - -build-shell-deps: $(ALL_SHELL_DEPS_DIRS) - $(verbose) for dep in $(ALL_SHELL_DEPS_DIRS) ; do $(MAKE) -C $$dep ; done - -shell: build-shell-deps - $(gen_verbose) erl $(SHELL_PATH) $(SHELL_OPTS) - -# Copyright (c) 2015, Loïc Hoguin -# This file is part of erlang.mk and subject to the terms of the ISC License. - -ifneq ($(wildcard $(DEPS_DIR)/triq),) -.PHONY: triq - -# Targets. - -tests:: triq - -define triq_check.erl - code:add_pathsa(["$(CURDIR)/ebin", "$(DEPS_DIR)/*/ebin"]), - try - case $(1) of - all -> [true] =:= lists:usort([triq:check(M) || M <- [$(call comma_list,$(3))]]); - module -> triq:check($(2)); - function -> triq:check($(2)) - end - of - true -> halt(0); - _ -> halt(1) - catch error:undef -> - io:format("Undefined property or module~n"), - halt(0) - end. -endef - -ifdef t -ifeq (,$(findstring :,$(t))) -triq: test-build - $(verbose) $(call erlang,$(call triq_check.erl,module,$(t))) -else -triq: test-build - $(verbose) echo Testing $(t)/0 - $(verbose) $(call erlang,$(call triq_check.erl,function,$(t)())) -endif -else -triq: test-build - $(eval MODULES := $(patsubst %,'%',$(sort $(notdir $(basename $(wildcard ebin/*.beam)))))) - $(gen_verbose) $(call erlang,$(call triq_check.erl,all,undefined,$(MODULES))) -endif -endif - -# Copyright (c) 2015, Erlang Solutions Ltd. -# This file is part of erlang.mk and subject to the terms of the ISC License. - -.PHONY: xref distclean-xref - -# Configuration. - -ifeq ($(XREF_CONFIG),) - XREF_ARGS := -else - XREF_ARGS := -c $(XREF_CONFIG) -endif - -XREFR ?= $(CURDIR)/xrefr -export XREFR - -XREFR_URL ?= https://github.com/inaka/xref_runner/releases/download/0.2.2/xrefr - -# Core targets. - -help:: - $(verbose) printf "%s\n" "" \ - "Xref targets:" \ - " xref Run Xrefr using $XREF_CONFIG as config file if defined" - -distclean:: distclean-xref - -# Plugin-specific targets. - -$(XREFR): - $(gen_verbose) $(call core_http_get,$(XREFR),$(XREFR_URL)) - $(verbose) chmod +x $(XREFR) - -xref: deps app $(XREFR) - $(gen_verbose) $(XREFR) $(XREFR_ARGS) - -distclean-xref: - $(gen_verbose) rm -rf $(XREFR) - -# Copyright 2015, Viktor Söderqvist -# This file is part of erlang.mk and subject to the terms of the ISC License. - -COVER_REPORT_DIR = cover - -# Hook in coverage to ct - -ifdef COVER -ifdef CT_RUN -# All modules in 'ebin' -COVER_MODS = $(notdir $(basename $(call core_ls,ebin/*.beam))) - -test-build:: $(TEST_DIR)/ct.cover.spec - -$(TEST_DIR)/ct.cover.spec: - $(verbose) echo Cover mods: $(COVER_MODS) - $(gen_verbose) printf "%s\n" \ - '{incl_mods,[$(subst $(space),$(comma),$(COVER_MODS))]}.' \ - '{export,"$(CURDIR)/ct.coverdata"}.' > $@ - -CT_RUN += -cover $(TEST_DIR)/ct.cover.spec -endif -endif - -# Core targets - -ifdef COVER -ifneq ($(COVER_REPORT_DIR),) -tests:: - $(verbose) $(MAKE) --no-print-directory cover-report -endif -endif - -clean:: coverdata-clean - -ifneq ($(COVER_REPORT_DIR),) -distclean:: cover-report-clean -endif - -help:: - $(verbose) printf "%s\n" "" \ - "Cover targets:" \ - " cover-report Generate a HTML coverage report from previously collected" \ - " cover data." \ - " all.coverdata Merge {eunit,ct}.coverdata into one coverdata file." \ - "" \ - "If COVER=1 is set, coverage data is generated by the targets eunit and ct. The" \ - "target tests additionally generates a HTML coverage report from the combined" \ - "coverdata files from each of these testing tools. HTML reports can be disabled" \ - "by setting COVER_REPORT_DIR to empty." - -# Plugin specific targets - -COVERDATA = $(filter-out all.coverdata,$(wildcard *.coverdata)) - -.PHONY: coverdata-clean -coverdata-clean: - $(gen_verbose) rm -f *.coverdata ct.cover.spec - -# Merge all coverdata files into one. -all.coverdata: $(COVERDATA) - $(gen_verbose) $(ERL) -eval ' \ - $(foreach f,$(COVERDATA),cover:import("$(f)") == ok orelse halt(1),) \ - cover:export("$@"), halt(0).' - -# These are only defined if COVER_REPORT_DIR is non-empty. Set COVER_REPORT_DIR to -# empty if you want the coverdata files but not the HTML report. -ifneq ($(COVER_REPORT_DIR),) - -.PHONY: cover-report-clean cover-report - -cover-report-clean: - $(gen_verbose) rm -rf $(COVER_REPORT_DIR) - -ifeq ($(COVERDATA),) -cover-report: -else - -# Modules which include eunit.hrl always contain one line without coverage -# because eunit defines test/0 which is never called. We compensate for this. -EUNIT_HRL_MODS = $(subst $(space),$(comma),$(shell \ - grep -e '^\s*-include.*include/eunit\.hrl"' src/*.erl \ - | sed "s/^src\/\(.*\)\.erl:.*/'\1'/" | uniq)) - -define cover_report.erl - $(foreach f,$(COVERDATA),cover:import("$(f)") == ok orelse halt(1),) - Ms = cover:imported_modules(), - [cover:analyse_to_file(M, "$(COVER_REPORT_DIR)/" ++ atom_to_list(M) - ++ ".COVER.html", [html]) || M <- Ms], - Report = [begin {ok, R} = cover:analyse(M, module), R end || M <- Ms], - EunitHrlMods = [$(EUNIT_HRL_MODS)], - Report1 = [{M, {Y, case lists:member(M, EunitHrlMods) of - true -> N - 1; false -> N end}} || {M, {Y, N}} <- Report], - TotalY = lists:sum([Y || {_, {Y, _}} <- Report1]), - TotalN = lists:sum([N || {_, {_, N}} <- Report1]), - TotalPerc = round(100 * TotalY / (TotalY + TotalN)), - {ok, F} = file:open("$(COVER_REPORT_DIR)/index.html", [write]), - io:format(F, "~n" - "~n" - "Coverage report~n" - "~n", []), - io:format(F, "

Coverage

~n

Total: ~p%

~n", [TotalPerc]), - io:format(F, "~n", []), - [io:format(F, "" - "~n", - [M, M, round(100 * Y / (Y + N))]) || {M, {Y, N}} <- Report1], - How = "$(subst $(space),$(comma)$(space),$(basename $(COVERDATA)))", - Date = "$(shell date -u "+%Y-%m-%dT%H:%M:%SZ")", - io:format(F, "
ModuleCoverage
~p~p%
~n" - "

Generated using ~s and erlang.mk on ~s.

~n" - "", [How, Date]), - halt(). -endef - -cover-report: - $(gen_verbose) mkdir -p $(COVER_REPORT_DIR) - $(gen_verbose) $(call erlang,$(cover_report.erl)) - -endif -endif # ifneq ($(COVER_REPORT_DIR),) DELETED deps/ranch/src/ranch.app.src Index: deps/ranch/src/ranch.app.src ================================================================== --- deps/ranch/src/ranch.app.src +++ /dev/null @@ -1,27 +0,0 @@ -%% Copyright (c) 2011-2015, Loïc Hoguin -%% -%% Permission to use, copy, modify, and/or distribute this software for any -%% purpose with or without fee is hereby granted, provided that the above -%% copyright notice and this permission notice appear in all copies. -%% -%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -{application, ranch, [ - {description, "Socket acceptor pool for TCP protocols."}, - {vsn, "1.2.0"}, - {id, "git"}, - {modules, []}, - {registered, [ranch_sup, ranch_server]}, - {applications, [ - kernel, - stdlib - ]}, - {mod, {ranch_app, []}}, - {env, []} -]}. DELETED deps/ranch/src/ranch.erl Index: deps/ranch/src/ranch.erl ================================================================== --- deps/ranch/src/ranch.erl +++ /dev/null @@ -1,186 +0,0 @@ -%% Copyright (c) 2011-2015, Loïc Hoguin -%% -%% Permission to use, copy, modify, and/or distribute this software for any -%% purpose with or without fee is hereby granted, provided that the above -%% copyright notice and this permission notice appear in all copies. -%% -%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - --module(ranch). - --export([start_listener/6]). --export([stop_listener/1]). --export([child_spec/6]). --export([accept_ack/1]). --export([remove_connection/1]). --export([get_addr/1]). --export([get_port/1]). --export([get_max_connections/1]). --export([set_max_connections/2]). --export([get_protocol_options/1]). --export([set_protocol_options/2]). --export([filter_options/3]). --export([set_option_default/3]). --export([require/1]). - --type max_conns() :: non_neg_integer() | infinity. --export_type([max_conns/0]). - --type opt() :: {ack_timeout, timeout()} - | {connection_type, worker | supervisor} - | {max_connections, max_conns()} - | {shutdown, timeout() | brutal_kill} - | {socket, any()}. --export_type([opt/0]). - --type ref() :: any(). --export_type([ref/0]). - --spec start_listener(ref(), non_neg_integer(), module(), any(), module(), any()) - -> supervisor:startchild_ret(). -start_listener(Ref, NbAcceptors, Transport, TransOpts, Protocol, ProtoOpts) - when is_integer(NbAcceptors) andalso is_atom(Transport) - andalso is_atom(Protocol) -> - _ = code:ensure_loaded(Transport), - case erlang:function_exported(Transport, name, 0) of - false -> - {error, badarg}; - true -> - Res = supervisor:start_child(ranch_sup, child_spec(Ref, NbAcceptors, - Transport, TransOpts, Protocol, ProtoOpts)), - Socket = proplists:get_value(socket, TransOpts), - case Res of - {ok, Pid} when Socket =/= undefined -> - %% Give ownership of the socket to ranch_acceptors_sup - %% to make sure the socket stays open as long as the - %% listener is alive. If the socket closes however there - %% will be no way to recover because we don't know how - %% to open it again. - Children = supervisor:which_children(Pid), - {_, AcceptorsSup, _, _} - = lists:keyfind(ranch_acceptors_sup, 1, Children), - %%% Note: the catch is here because SSL crashes when you change - %%% the controlling process of a listen socket because of a bug. - %%% The bug will be fixed in R16. - catch Transport:controlling_process(Socket, AcceptorsSup); - _ -> - ok - end, - Res - end. - --spec stop_listener(ref()) -> ok | {error, not_found}. -stop_listener(Ref) -> - case supervisor:terminate_child(ranch_sup, {ranch_listener_sup, Ref}) of - ok -> - _ = supervisor:delete_child(ranch_sup, {ranch_listener_sup, Ref}), - ranch_server:cleanup_listener_opts(Ref); - {error, Reason} -> - {error, Reason} - end. - --spec child_spec(ref(), non_neg_integer(), module(), any(), module(), any()) - -> supervisor:child_spec(). -child_spec(Ref, NbAcceptors, Transport, TransOpts, Protocol, ProtoOpts) - when is_integer(NbAcceptors) andalso is_atom(Transport) - andalso is_atom(Protocol) -> - {{ranch_listener_sup, Ref}, {ranch_listener_sup, start_link, [ - Ref, NbAcceptors, Transport, TransOpts, Protocol, ProtoOpts - ]}, permanent, infinity, supervisor, [ranch_listener_sup]}. - --spec accept_ack(ref()) -> ok. -accept_ack(Ref) -> - receive {shoot, Ref, Transport, Socket, AckTimeout} -> - Transport:accept_ack(Socket, AckTimeout) - end. - --spec remove_connection(ref()) -> ok. -remove_connection(Ref) -> - ConnsSup = ranch_server:get_connections_sup(Ref), - ConnsSup ! {remove_connection, Ref}, - ok. - --spec get_addr(ref()) -> {inet:ip_address(), inet:port_number()}. -get_addr(Ref) -> - ranch_server:get_addr(Ref). - --spec get_port(ref()) -> inet:port_number(). -get_port(Ref) -> - {_, Port} = get_addr(Ref), - Port. - --spec get_max_connections(ref()) -> max_conns(). -get_max_connections(Ref) -> - ranch_server:get_max_connections(Ref). - --spec set_max_connections(ref(), max_conns()) -> ok. -set_max_connections(Ref, MaxConnections) -> - ranch_server:set_max_connections(Ref, MaxConnections). - --spec get_protocol_options(ref()) -> any(). -get_protocol_options(Ref) -> - ranch_server:get_protocol_options(Ref). - --spec set_protocol_options(ref(), any()) -> ok. -set_protocol_options(Ref, Opts) -> - ranch_server:set_protocol_options(Ref, Opts). - --spec filter_options([inet | inet6 | {atom(), any()} | {raw, any(), any(), any()}], - [atom()], Acc) -> Acc when Acc :: [any()]. -filter_options(UserOptions, AllowedKeys, DefaultOptions) -> - AllowedOptions = filter_user_options(UserOptions, AllowedKeys), - lists:foldl(fun merge_options/2, DefaultOptions, AllowedOptions). - -%% 2-tuple options. -filter_user_options([Opt = {Key, _}|Tail], AllowedKeys) -> - case lists:member(Key, AllowedKeys) of - true -> - [Opt|filter_user_options(Tail, AllowedKeys)]; - false -> - filter_options_warning(Opt), - filter_user_options(Tail, AllowedKeys) - end; -%% Special option forms. -filter_user_options([inet|Tail], AllowedKeys) -> - [inet|filter_user_options(Tail, AllowedKeys)]; -filter_user_options([inet6|Tail], AllowedKeys) -> - [inet6|filter_user_options(Tail, AllowedKeys)]; -filter_user_options([Opt = {raw, _, _, _}|Tail], AllowedKeys) -> - [Opt|filter_user_options(Tail, AllowedKeys)]; -filter_user_options([Opt|Tail], AllowedKeys) -> - filter_options_warning(Opt), - filter_user_options(Tail, AllowedKeys); -filter_user_options([], _) -> - []. - -filter_options_warning(Opt) -> - error_logger:warning_msg("Transport option ~p unknown or invalid.~n", [Opt]). - -merge_options({Key, _} = Option, OptionList) -> - lists:keystore(Key, 1, OptionList, Option); -merge_options(Option, OptionList) -> - [Option|OptionList]. - --spec set_option_default(Opts, atom(), any()) - -> Opts when Opts :: [{atom(), any()}]. -set_option_default(Opts, Key, Value) -> - case lists:keymember(Key, 1, Opts) of - true -> Opts; - false -> [{Key, Value}|Opts] - end. - --spec require([atom()]) -> ok. -require([]) -> - ok; -require([App|Tail]) -> - case application:start(App) of - ok -> ok; - {error, {already_started, App}} -> ok - end, - require(Tail). DELETED deps/ranch/src/ranch_acceptor.erl Index: deps/ranch/src/ranch_acceptor.erl ================================================================== --- deps/ranch/src/ranch_acceptor.erl +++ /dev/null @@ -1,58 +0,0 @@ -%% Copyright (c) 2011-2015, Loïc Hoguin -%% -%% Permission to use, copy, modify, and/or distribute this software for any -%% purpose with or without fee is hereby granted, provided that the above -%% copyright notice and this permission notice appear in all copies. -%% -%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - --module(ranch_acceptor). - --export([start_link/3]). --export([loop/3]). - --spec start_link(inet:socket(), module(), pid()) - -> {ok, pid()}. -start_link(LSocket, Transport, ConnsSup) -> - Pid = spawn_link(?MODULE, loop, [LSocket, Transport, ConnsSup]), - {ok, Pid}. - --spec loop(inet:socket(), module(), pid()) -> no_return(). -loop(LSocket, Transport, ConnsSup) -> - _ = case Transport:accept(LSocket, infinity) of - {ok, CSocket} -> - case Transport:controlling_process(CSocket, ConnsSup) of - ok -> - %% This call will not return until process has been started - %% AND we are below the maximum number of connections. - ranch_conns_sup:start_protocol(ConnsSup, CSocket); - {error, _} -> - Transport:close(CSocket) - end; - %% Reduce the accept rate if we run out of file descriptors. - %% We can't accept anymore anyway, so we might as well wait - %% a little for the situation to resolve itself. - {error, emfile} -> - receive after 100 -> ok end; - %% We want to crash if the listening socket got closed. - {error, Reason} when Reason =/= closed -> - ok - end, - flush(), - ?MODULE:loop(LSocket, Transport, ConnsSup). - -flush() -> - receive Msg -> - error_logger:error_msg( - "Ranch acceptor received unexpected message: ~p~n", - [Msg]), - flush() - after 0 -> - ok - end. DELETED deps/ranch/src/ranch_acceptors_sup.erl Index: deps/ranch/src/ranch_acceptors_sup.erl ================================================================== --- deps/ranch/src/ranch_acceptors_sup.erl +++ /dev/null @@ -1,56 +0,0 @@ -%% Copyright (c) 2011-2015, Loïc Hoguin -%% -%% Permission to use, copy, modify, and/or distribute this software for any -%% purpose with or without fee is hereby granted, provided that the above -%% copyright notice and this permission notice appear in all copies. -%% -%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - --module(ranch_acceptors_sup). --behaviour(supervisor). - --export([start_link/4]). --export([init/1]). - --spec start_link(ranch:ref(), non_neg_integer(), module(), any()) - -> {ok, pid()}. -start_link(Ref, NbAcceptors, Transport, TransOpts) -> - supervisor:start_link(?MODULE, [Ref, NbAcceptors, Transport, TransOpts]). - -init([Ref, NbAcceptors, Transport, TransOpts]) -> - ConnsSup = ranch_server:get_connections_sup(Ref), - LSocket = case proplists:get_value(socket, TransOpts) of - undefined -> - TransOpts2 = proplists:delete(ack_timeout, - proplists:delete(connection_type, - proplists:delete(max_connections, - proplists:delete(shutdown, - proplists:delete(socket, TransOpts))))), - case Transport:listen(TransOpts2) of - {ok, Socket} -> Socket; - {error, Reason} -> listen_error(Ref, Transport, TransOpts2, Reason) - end; - Socket -> - Socket - end, - {ok, Addr} = Transport:sockname(LSocket), - ranch_server:set_addr(Ref, Addr), - Procs = [ - {{acceptor, self(), N}, {ranch_acceptor, start_link, [ - LSocket, Transport, ConnsSup - ]}, permanent, brutal_kill, worker, []} - || N <- lists:seq(1, NbAcceptors)], - {ok, {{one_for_one, 10, 10}, Procs}}. - --spec listen_error(any(), module(), any(), atom()) -> no_return(). -listen_error(Ref, Transport, TransOpts2, Reason) -> - error_logger:error_msg( - "Failed to start Ranch listener ~p in ~p:listen(~p) for reason ~p (~s)~n", - [Ref, Transport, TransOpts2, Reason, inet:format_error(Reason)]), - exit({listen_error, Ref, Reason}). DELETED deps/ranch/src/ranch_app.erl Index: deps/ranch/src/ranch_app.erl ================================================================== --- deps/ranch/src/ranch_app.erl +++ /dev/null @@ -1,44 +0,0 @@ -%% Copyright (c) 2011-2015, Loïc Hoguin -%% -%% Permission to use, copy, modify, and/or distribute this software for any -%% purpose with or without fee is hereby granted, provided that the above -%% copyright notice and this permission notice appear in all copies. -%% -%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - --module(ranch_app). --behaviour(application). - --export([start/2]). --export([stop/1]). --export([profile_output/0]). - -start(_, _) -> - _ = consider_profiling(), - ranch_sup:start_link(). - -stop(_) -> - ok. - --spec profile_output() -> ok. -profile_output() -> - eprof:stop_profiling(), - eprof:log("procs.profile"), - eprof:analyze(procs), - eprof:log("total.profile"), - eprof:analyze(total). - -consider_profiling() -> - case application:get_env(profile) of - {ok, true} -> - {ok, _Pid} = eprof:start(), - eprof:start_profiling([self()]); - _ -> - not_profiling - end. DELETED deps/ranch/src/ranch_conns_sup.erl Index: deps/ranch/src/ranch_conns_sup.erl ================================================================== --- deps/ranch/src/ranch_conns_sup.erl +++ /dev/null @@ -1,284 +0,0 @@ -%% Copyright (c) 2011-2015, Loïc Hoguin -%% -%% Permission to use, copy, modify, and/or distribute this software for any -%% purpose with or without fee is hereby granted, provided that the above -%% copyright notice and this permission notice appear in all copies. -%% -%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -%% Make sure to never reload this module outside a release upgrade, -%% as calling l(ranch_conns_sup) twice will kill the process and all -%% the currently open connections. --module(ranch_conns_sup). - -%% API. --export([start_link/6]). --export([start_protocol/2]). --export([active_connections/1]). - -%% Supervisor internals. --export([init/7]). --export([system_continue/3]). --export([system_terminate/4]). --export([system_code_change/4]). - --type conn_type() :: worker | supervisor. --type shutdown() :: brutal_kill | timeout(). - --record(state, { - parent = undefined :: pid(), - ref :: ranch:ref(), - conn_type :: conn_type(), - shutdown :: shutdown(), - transport = undefined :: module(), - protocol = undefined :: module(), - opts :: any(), - ack_timeout :: timeout(), - max_conns = undefined :: ranch:max_conns() -}). - -%% API. - --spec start_link(ranch:ref(), conn_type(), shutdown(), module(), - timeout(), module()) -> {ok, pid()}. -start_link(Ref, ConnType, Shutdown, Transport, AckTimeout, Protocol) -> - proc_lib:start_link(?MODULE, init, - [self(), Ref, ConnType, Shutdown, Transport, AckTimeout, Protocol]). - -%% We can safely assume we are on the same node as the supervisor. -%% -%% We can also safely avoid having a monitor and a timeout here -%% because only three things can happen: -%% * The supervisor died; rest_for_one strategy killed all acceptors -%% so this very calling process is going to di-- -%% * There's too many connections, the supervisor will resume the -%% acceptor only when we get below the limit again. -%% * The supervisor is overloaded, there's either too many acceptors -%% or the max_connections limit is too large. It's better if we -%% don't keep accepting connections because this leaves -%% more room for the situation to be resolved. -%% -%% We do not need the reply, we only need the ok from the supervisor -%% to continue. The supervisor sends its own pid when the acceptor can -%% continue. --spec start_protocol(pid(), inet:socket()) -> ok. -start_protocol(SupPid, Socket) -> - SupPid ! {?MODULE, start_protocol, self(), Socket}, - receive SupPid -> ok end. - -%% We can't make the above assumptions here. This function might be -%% called from anywhere. --spec active_connections(pid()) -> non_neg_integer(). -active_connections(SupPid) -> - Tag = erlang:monitor(process, SupPid), - catch erlang:send(SupPid, {?MODULE, active_connections, self(), Tag}, - [noconnect]), - receive - {Tag, Ret} -> - erlang:demonitor(Tag, [flush]), - Ret; - {'DOWN', Tag, _, _, noconnection} -> - exit({nodedown, node(SupPid)}); - {'DOWN', Tag, _, _, Reason} -> - exit(Reason) - after 5000 -> - erlang:demonitor(Tag, [flush]), - exit(timeout) - end. - -%% Supervisor internals. - --spec init(pid(), ranch:ref(), conn_type(), shutdown(), - module(), timeout(), module()) -> no_return(). -init(Parent, Ref, ConnType, Shutdown, Transport, AckTimeout, Protocol) -> - process_flag(trap_exit, true), - ok = ranch_server:set_connections_sup(Ref, self()), - MaxConns = ranch_server:get_max_connections(Ref), - Opts = ranch_server:get_protocol_options(Ref), - ok = proc_lib:init_ack(Parent, {ok, self()}), - loop(#state{parent=Parent, ref=Ref, conn_type=ConnType, - shutdown=Shutdown, transport=Transport, protocol=Protocol, - opts=Opts, ack_timeout=AckTimeout, max_conns=MaxConns}, 0, 0, []). - -loop(State=#state{parent=Parent, ref=Ref, conn_type=ConnType, - transport=Transport, protocol=Protocol, opts=Opts, - max_conns=MaxConns}, CurConns, NbChildren, Sleepers) -> - receive - {?MODULE, start_protocol, To, Socket} -> - try Protocol:start_link(Ref, Socket, Transport, Opts) of - {ok, Pid} -> - shoot(State, CurConns, NbChildren, Sleepers, To, Socket, Pid, Pid); - {ok, SupPid, ProtocolPid} when ConnType =:= supervisor -> - shoot(State, CurConns, NbChildren, Sleepers, To, Socket, SupPid, ProtocolPid); - Ret -> - To ! self(), - error_logger:error_msg( - "Ranch listener ~p connection process start failure; " - "~p:start_link/4 returned: ~999999p~n", - [Ref, Protocol, Ret]), - Transport:close(Socket), - loop(State, CurConns, NbChildren, Sleepers) - catch Class:Reason -> - To ! self(), - error_logger:error_msg( - "Ranch listener ~p connection process start failure; " - "~p:start_link/4 crashed with reason: ~p:~999999p~n", - [Ref, Protocol, Class, Reason]), - loop(State, CurConns, NbChildren, Sleepers) - end; - {?MODULE, active_connections, To, Tag} -> - To ! {Tag, CurConns}, - loop(State, CurConns, NbChildren, Sleepers); - %% Remove a connection from the count of connections. - {remove_connection, Ref} -> - loop(State, CurConns - 1, NbChildren, Sleepers); - %% Upgrade the max number of connections allowed concurrently. - %% We resume all sleeping acceptors if this number increases. - {set_max_conns, MaxConns2} when MaxConns2 > MaxConns -> - _ = [To ! self() || To <- Sleepers], - loop(State#state{max_conns=MaxConns2}, - CurConns, NbChildren, []); - {set_max_conns, MaxConns2} -> - loop(State#state{max_conns=MaxConns2}, - CurConns, NbChildren, Sleepers); - %% Upgrade the protocol options. - {set_opts, Opts2} -> - loop(State#state{opts=Opts2}, - CurConns, NbChildren, Sleepers); - {'EXIT', Parent, Reason} -> - terminate(State, Reason, NbChildren); - {'EXIT', Pid, Reason} when Sleepers =:= [] -> - report_error(Ref, Protocol, Pid, Reason), - erase(Pid), - loop(State, CurConns - 1, NbChildren - 1, Sleepers); - %% Resume a sleeping acceptor if needed. - {'EXIT', Pid, Reason} -> - report_error(Ref, Protocol, Pid, Reason), - erase(Pid), - [To|Sleepers2] = Sleepers, - To ! self(), - loop(State, CurConns - 1, NbChildren - 1, Sleepers2); - {system, From, Request} -> - sys:handle_system_msg(Request, From, Parent, ?MODULE, [], - {State, CurConns, NbChildren, Sleepers}); - %% Calls from the supervisor module. - {'$gen_call', {To, Tag}, which_children} -> - Pids = get_keys(true), - Children = [{Protocol, Pid, ConnType, [Protocol]} - || Pid <- Pids, is_pid(Pid)], - To ! {Tag, Children}, - loop(State, CurConns, NbChildren, Sleepers); - {'$gen_call', {To, Tag}, count_children} -> - Counts = case ConnType of - worker -> [{supervisors, 0}, {workers, NbChildren}]; - supervisor -> [{supervisors, NbChildren}, {workers, 0}] - end, - Counts2 = [{specs, 1}, {active, NbChildren}|Counts], - To ! {Tag, Counts2}, - loop(State, CurConns, NbChildren, Sleepers); - {'$gen_call', {To, Tag}, _} -> - To ! {Tag, {error, ?MODULE}}, - loop(State, CurConns, NbChildren, Sleepers); - Msg -> - error_logger:error_msg( - "Ranch listener ~p received unexpected message ~p~n", - [Ref, Msg]) - end. - -shoot(State=#state{ref=Ref, transport=Transport, ack_timeout=AckTimeout, max_conns=MaxConns}, - CurConns, NbChildren, Sleepers, To, Socket, SupPid, ProtocolPid) -> - case Transport:controlling_process(Socket, ProtocolPid) of - ok -> - ProtocolPid ! {shoot, Ref, Transport, Socket, AckTimeout}, - put(SupPid, true), - CurConns2 = CurConns + 1, - if CurConns2 < MaxConns -> - To ! self(), - loop(State, CurConns2, NbChildren + 1, Sleepers); - true -> - loop(State, CurConns2, NbChildren + 1, [To|Sleepers]) - end; - {error, _} -> - Transport:close(Socket), - %% Only kill the supervised pid, because the connection's pid, - %% when different, is supposed to be sitting under it and linked. - exit(SupPid, kill), - loop(State, CurConns, NbChildren, Sleepers) - end. - --spec terminate(#state{}, any(), non_neg_integer()) -> no_return(). -%% Kill all children and then exit. We unlink first to avoid -%% getting a message for each child getting killed. -terminate(#state{shutdown=brutal_kill}, Reason, _) -> - Pids = get_keys(true), - _ = [begin - unlink(P), - exit(P, kill) - end || P <- Pids], - exit(Reason); -%% Attempt to gracefully shutdown all children. -terminate(#state{shutdown=Shutdown}, Reason, NbChildren) -> - shutdown_children(), - _ = if - Shutdown =:= infinity -> - ok; - true -> - erlang:send_after(Shutdown, self(), kill) - end, - wait_children(NbChildren), - exit(Reason). - -%% Monitor processes so we can know which ones have shutdown -%% before the timeout. Unlink so we avoid receiving an extra -%% message. Then send a shutdown exit signal. -shutdown_children() -> - Pids = get_keys(true), - _ = [begin - monitor(process, P), - unlink(P), - exit(P, shutdown) - end || P <- Pids], - ok. - -wait_children(0) -> - ok; -wait_children(NbChildren) -> - receive - {'DOWN', _, process, Pid, _} -> - _ = erase(Pid), - wait_children(NbChildren - 1); - kill -> - Pids = get_keys(true), - _ = [exit(P, kill) || P <- Pids], - ok - end. - -system_continue(_, _, {State, CurConns, NbChildren, Sleepers}) -> - loop(State, CurConns, NbChildren, Sleepers). - --spec system_terminate(any(), _, _, _) -> no_return(). -system_terminate(Reason, _, _, {State, _, NbChildren, _}) -> - terminate(State, Reason, NbChildren). - -system_code_change(Misc, _, _, _) -> - {ok, Misc}. - -%% We use ~999999p here instead of ~w because the latter doesn't -%% support printable strings. -report_error(_, _, _, normal) -> - ok; -report_error(_, _, _, shutdown) -> - ok; -report_error(_, _, _, {shutdown, _}) -> - ok; -report_error(Ref, Protocol, Pid, Reason) -> - error_logger:error_msg( - "Ranch listener ~p had connection process started with " - "~p:start_link/4 at ~p exit with reason: ~999999p~n", - [Ref, Protocol, Pid, Reason]). DELETED deps/ranch/src/ranch_listener_sup.erl Index: deps/ranch/src/ranch_listener_sup.erl ================================================================== --- deps/ranch/src/ranch_listener_sup.erl +++ /dev/null @@ -1,42 +0,0 @@ -%% Copyright (c) 2011-2015, Loïc Hoguin -%% -%% Permission to use, copy, modify, and/or distribute this software for any -%% purpose with or without fee is hereby granted, provided that the above -%% copyright notice and this permission notice appear in all copies. -%% -%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - --module(ranch_listener_sup). --behaviour(supervisor). - --export([start_link/6]). --export([init/1]). - --spec start_link(ranch:ref(), non_neg_integer(), module(), any(), module(), any()) - -> {ok, pid()}. -start_link(Ref, NbAcceptors, Transport, TransOpts, Protocol, ProtoOpts) -> - MaxConns = proplists:get_value(max_connections, TransOpts, 1024), - ranch_server:set_new_listener_opts(Ref, MaxConns, ProtoOpts), - supervisor:start_link(?MODULE, { - Ref, NbAcceptors, Transport, TransOpts, Protocol - }). - -init({Ref, NbAcceptors, Transport, TransOpts, Protocol}) -> - AckTimeout = proplists:get_value(ack_timeout, TransOpts, 5000), - ConnType = proplists:get_value(connection_type, TransOpts, worker), - Shutdown = proplists:get_value(shutdown, TransOpts, 5000), - ChildSpecs = [ - {ranch_conns_sup, {ranch_conns_sup, start_link, - [Ref, ConnType, Shutdown, Transport, AckTimeout, Protocol]}, - permanent, infinity, supervisor, [ranch_conns_sup]}, - {ranch_acceptors_sup, {ranch_acceptors_sup, start_link, - [Ref, NbAcceptors, Transport, TransOpts]}, - permanent, infinity, supervisor, [ranch_acceptors_sup]} - ], - {ok, {{rest_for_one, 10, 10}, ChildSpecs}}. DELETED deps/ranch/src/ranch_protocol.erl Index: deps/ranch/src/ranch_protocol.erl ================================================================== --- deps/ranch/src/ranch_protocol.erl +++ /dev/null @@ -1,24 +0,0 @@ -%% Copyright (c) 2012-2015, Loïc Hoguin -%% -%% Permission to use, copy, modify, and/or distribute this software for any -%% purpose with or without fee is hereby granted, provided that the above -%% copyright notice and this permission notice appear in all copies. -%% -%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - --module(ranch_protocol). - -%% Start a new connection process for the given socket. --callback start_link( - Ref::ranch:ref(), - Socket::any(), - Transport::module(), - ProtocolOptions::any()) - -> {ok, ConnectionPid::pid()} - | {ok, SupPid::pid(), ConnectionPid::pid()}. DELETED deps/ranch/src/ranch_server.erl Index: deps/ranch/src/ranch_server.erl ================================================================== --- deps/ranch/src/ranch_server.erl +++ /dev/null @@ -1,154 +0,0 @@ -%% Copyright (c) 2012-2015, Loïc Hoguin -%% -%% Permission to use, copy, modify, and/or distribute this software for any -%% purpose with or without fee is hereby granted, provided that the above -%% copyright notice and this permission notice appear in all copies. -%% -%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - --module(ranch_server). --behaviour(gen_server). - -%% API. --export([start_link/0]). --export([set_new_listener_opts/3]). --export([cleanup_listener_opts/1]). --export([set_connections_sup/2]). --export([get_connections_sup/1]). --export([set_addr/2]). --export([get_addr/1]). --export([set_max_connections/2]). --export([get_max_connections/1]). --export([set_protocol_options/2]). --export([get_protocol_options/1]). --export([count_connections/1]). - -%% gen_server. --export([init/1]). --export([handle_call/3]). --export([handle_cast/2]). --export([handle_info/2]). --export([terminate/2]). --export([code_change/3]). - --define(TAB, ?MODULE). - --type monitors() :: [{{reference(), pid()}, any()}]. --record(state, { - monitors = [] :: monitors() -}). - -%% API. - --spec start_link() -> {ok, pid()}. -start_link() -> - gen_server:start_link({local, ?MODULE}, ?MODULE, [], []). - --spec set_new_listener_opts(ranch:ref(), ranch:max_conns(), any()) -> ok. -set_new_listener_opts(Ref, MaxConns, Opts) -> - gen_server:call(?MODULE, {set_new_listener_opts, Ref, MaxConns, Opts}). - --spec cleanup_listener_opts(ranch:ref()) -> ok. -cleanup_listener_opts(Ref) -> - _ = ets:delete(?TAB, {addr, Ref}), - _ = ets:delete(?TAB, {max_conns, Ref}), - _ = ets:delete(?TAB, {opts, Ref}), - ok. - --spec set_connections_sup(ranch:ref(), pid()) -> ok. -set_connections_sup(Ref, Pid) -> - true = gen_server:call(?MODULE, {set_connections_sup, Ref, Pid}), - ok. - --spec get_connections_sup(ranch:ref()) -> pid(). -get_connections_sup(Ref) -> - ets:lookup_element(?TAB, {conns_sup, Ref}, 2). - --spec set_addr(ranch:ref(), {inet:ip_address(), inet:port_number()}) -> ok. -set_addr(Ref, Addr) -> - gen_server:call(?MODULE, {set_addr, Ref, Addr}). - --spec get_addr(ranch:ref()) -> {inet:ip_address(), inet:port_number()}. -get_addr(Ref) -> - ets:lookup_element(?TAB, {addr, Ref}, 2). - --spec set_max_connections(ranch:ref(), ranch:max_conns()) -> ok. -set_max_connections(Ref, MaxConnections) -> - gen_server:call(?MODULE, {set_max_conns, Ref, MaxConnections}). - --spec get_max_connections(ranch:ref()) -> ranch:max_conns(). -get_max_connections(Ref) -> - ets:lookup_element(?TAB, {max_conns, Ref}, 2). - --spec set_protocol_options(ranch:ref(), any()) -> ok. -set_protocol_options(Ref, ProtoOpts) -> - gen_server:call(?MODULE, {set_opts, Ref, ProtoOpts}). - --spec get_protocol_options(ranch:ref()) -> any(). -get_protocol_options(Ref) -> - ets:lookup_element(?TAB, {opts, Ref}, 2). - --spec count_connections(ranch:ref()) -> non_neg_integer(). -count_connections(Ref) -> - ranch_conns_sup:active_connections(get_connections_sup(Ref)). - -%% gen_server. - -init([]) -> - Monitors = [{{erlang:monitor(process, Pid), Pid}, Ref} || - [Ref, Pid] <- ets:match(?TAB, {{conns_sup, '$1'}, '$2'})], - {ok, #state{monitors=Monitors}}. - -handle_call({set_new_listener_opts, Ref, MaxConns, Opts}, _, State) -> - ets:insert(?TAB, {{max_conns, Ref}, MaxConns}), - ets:insert(?TAB, {{opts, Ref}, Opts}), - {reply, ok, State}; -handle_call({set_connections_sup, Ref, Pid}, _, - State=#state{monitors=Monitors}) -> - case ets:insert_new(?TAB, {{conns_sup, Ref}, Pid}) of - true -> - MonitorRef = erlang:monitor(process, Pid), - {reply, true, - State#state{monitors=[{{MonitorRef, Pid}, Ref}|Monitors]}}; - false -> - {reply, false, State} - end; -handle_call({set_addr, Ref, Addr}, _, State) -> - true = ets:insert(?TAB, {{addr, Ref}, Addr}), - {reply, ok, State}; -handle_call({set_max_conns, Ref, MaxConns}, _, State) -> - ets:insert(?TAB, {{max_conns, Ref}, MaxConns}), - ConnsSup = get_connections_sup(Ref), - ConnsSup ! {set_max_conns, MaxConns}, - {reply, ok, State}; -handle_call({set_opts, Ref, Opts}, _, State) -> - ets:insert(?TAB, {{opts, Ref}, Opts}), - ConnsSup = get_connections_sup(Ref), - ConnsSup ! {set_opts, Opts}, - {reply, ok, State}; -handle_call(_Request, _From, State) -> - {reply, ignore, State}. - -handle_cast(_Request, State) -> - {noreply, State}. - -handle_info({'DOWN', MonitorRef, process, Pid, _}, - State=#state{monitors=Monitors}) -> - {_, Ref} = lists:keyfind({MonitorRef, Pid}, 1, Monitors), - true = ets:delete(?TAB, {conns_sup, Ref}), - Monitors2 = lists:keydelete({MonitorRef, Pid}, 1, Monitors), - {noreply, State#state{monitors=Monitors2}}; -handle_info(_Info, State) -> - {noreply, State}. - -terminate(_Reason, _State) -> - ok. - -code_change(_OldVsn, State, _Extra) -> - {ok, State}. DELETED deps/ranch/src/ranch_ssl.erl Index: deps/ranch/src/ranch_ssl.erl ================================================================== --- deps/ranch/src/ranch_ssl.erl +++ /dev/null @@ -1,227 +0,0 @@ -%% Copyright (c) 2011-2015, Loïc Hoguin -%% -%% Permission to use, copy, modify, and/or distribute this software for any -%% purpose with or without fee is hereby granted, provided that the above -%% copyright notice and this permission notice appear in all copies. -%% -%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - --module(ranch_ssl). --behaviour(ranch_transport). - --export([name/0]). --export([secure/0]). --export([messages/0]). --export([listen/1]). --export([listen_options/0]). --export([accept/2]). --export([accept_ack/2]). --export([connect/3]). --export([connect/4]). --export([recv/3]). --export([send/2]). --export([sendfile/2]). --export([sendfile/4]). --export([sendfile/5]). --export([setopts/2]). --export([controlling_process/2]). --export([peername/1]). --export([sockname/1]). --export([shutdown/2]). --export([close/1]). - --type ssl_opt() :: {alpn_preferred_protocols, [binary()]} - | {cacertfile, string()} - | {cacerts, [public_key:der_encoded()]} - | {cert, public_key:der_encoded()} - | {certfile, string()} - | {ciphers, [ssl:erl_cipher_suite()] | string()} - | {client_renegotiation, boolean()} - | {crl_cache, {module(), {internal | any(), list()}}} - | {crl_check, boolean() | peer | best_effort} - | {depth, 0..255} - | {dh, public_key:der_encoded()} - | {dhfile, string()} - | {fail_if_no_peer_cert, boolean()} - | {hibernate_after, integer() | undefined} - | {honor_cipher_order, boolean()} - | {key, {'RSAPrivateKey' | 'DSAPrivateKey' | 'PrivateKeyInfo', public_key:der_encoded()}} - | {keyfile, string()} - | {log_alert, boolean()} - | {next_protocols_advertised, [binary()]} - | {partial_chain, fun(([public_key:der_encoded()]) -> {trusted_ca, public_key:der_encoded()} | unknown_ca)} - | {password, string()} - | {psk_identity, string()} - | {reuse_session, fun()} - | {reuse_sessions, boolean()} - | {secure_renegotiate, boolean()} - | {sni_fun, fun()} - | {sni_hosts, [{string(), ssl_opt()}]} - | {user_lookup_fun, {fun(), any()}} - | {verify, ssl:verify_type()} - | {verify_fun, {fun(), any()}} - | {versions, [atom()]}. --export_type([ssl_opt/0]). - --type opt() :: ranch_tcp:opt() | ssl_opt(). --export_type([opt/0]). - --type opts() :: [opt()]. --export_type([opts/0]). - -name() -> ssl. - --spec secure() -> boolean(). -secure() -> - true. - -messages() -> {ssl, ssl_closed, ssl_error}. - --spec listen(opts()) -> {ok, ssl:sslsocket()} | {error, atom()}. -listen(Opts) -> - ranch:require([crypto, asn1, public_key, ssl]), - true = lists:keymember(cert, 1, Opts) - orelse lists:keymember(certfile, 1, Opts), - Opts2 = ranch:set_option_default(Opts, backlog, 1024), - Opts3 = ranch:set_option_default(Opts2, ciphers, unbroken_cipher_suites()), - Opts4 = ranch:set_option_default(Opts3, nodelay, true), - Opts5 = ranch:set_option_default(Opts4, send_timeout, 30000), - Opts6 = ranch:set_option_default(Opts5, send_timeout_close, true), - %% We set the port to 0 because it is given in the Opts directly. - %% The port in the options takes precedence over the one in the - %% first argument. - ssl:listen(0, ranch:filter_options(Opts6, listen_options(), - [binary, {active, false}, {packet, raw}, - {reuseaddr, true}, {nodelay, true}])). - -listen_options() -> - [alpn_preferred_protocols, cacertfile, cacerts, cert, certfile, - ciphers, client_renegotiation, crl_cache, crl_check, depth, - dh, dhfile, fail_if_no_peer_cert, hibernate_after, honor_cipher_order, - key, keyfile, log_alert, next_protocols_advertised, partial_chain, - password, psk_identity, reuse_session, reuse_sessions, secure_renegotiate, - sni_fun, sni_hosts, user_lookup_fun, verify, verify_fun, versions - |ranch_tcp:listen_options()]. - --spec accept(ssl:sslsocket(), timeout()) - -> {ok, ssl:sslsocket()} | {error, closed | timeout | atom()}. -accept(LSocket, Timeout) -> - ssl:transport_accept(LSocket, Timeout). - --spec accept_ack(ssl:sslsocket(), timeout()) -> ok. -accept_ack(CSocket, Timeout) -> - case ssl:ssl_accept(CSocket, Timeout) of - ok -> - ok; - %% Garbage was most likely sent to the socket, don't error out. - {error, {tls_alert, _}} -> - ok = close(CSocket), - exit(normal); - %% Socket most likely stopped responding, don't error out. - {error, Reason} when Reason =:= timeout; Reason =:= closed -> - ok = close(CSocket), - exit(normal); - {error, Reason} -> - ok = close(CSocket), - error(Reason) - end. - -%% @todo Probably filter Opts? --spec connect(inet:ip_address() | inet:hostname(), - inet:port_number(), any()) - -> {ok, inet:socket()} | {error, atom()}. -connect(Host, Port, Opts) when is_integer(Port) -> - ssl:connect(Host, Port, - Opts ++ [binary, {active, false}, {packet, raw}]). - -%% @todo Probably filter Opts? --spec connect(inet:ip_address() | inet:hostname(), - inet:port_number(), any(), timeout()) - -> {ok, inet:socket()} | {error, atom()}. -connect(Host, Port, Opts, Timeout) when is_integer(Port) -> - ssl:connect(Host, Port, - Opts ++ [binary, {active, false}, {packet, raw}], - Timeout). - --spec recv(ssl:sslsocket(), non_neg_integer(), timeout()) - -> {ok, any()} | {error, closed | atom()}. -recv(Socket, Length, Timeout) -> - ssl:recv(Socket, Length, Timeout). - --spec send(ssl:sslsocket(), iodata()) -> ok | {error, atom()}. -send(Socket, Packet) -> - ssl:send(Socket, Packet). - --spec sendfile(ssl:sslsocket(), file:name_all() | file:fd()) - -> {ok, non_neg_integer()} | {error, atom()}. -sendfile(Socket, Filename) -> - sendfile(Socket, Filename, 0, 0, []). - --spec sendfile(ssl:sslsocket(), file:name_all() | file:fd(), - non_neg_integer(), non_neg_integer()) - -> {ok, non_neg_integer()} | {error, atom()}. -sendfile(Socket, File, Offset, Bytes) -> - sendfile(Socket, File, Offset, Bytes, []). - -%% Unlike with TCP, no syscall can be used here, so sending files -%% through SSL will be much slower in comparison. Note that unlike -%% file:sendfile/5 this function accepts either a file or a file name. --spec sendfile(ssl:sslsocket(), file:name_all() | file:fd(), - non_neg_integer(), non_neg_integer(), ranch_transport:sendfile_opts()) - -> {ok, non_neg_integer()} | {error, atom()}. -sendfile(Socket, File, Offset, Bytes, Opts) -> - ranch_transport:sendfile(?MODULE, Socket, File, Offset, Bytes, Opts). - -%% @todo Probably filter Opts? --spec setopts(ssl:sslsocket(), list()) -> ok | {error, atom()}. -setopts(Socket, Opts) -> - ssl:setopts(Socket, Opts). - --spec controlling_process(ssl:sslsocket(), pid()) - -> ok | {error, closed | not_owner | atom()}. -controlling_process(Socket, Pid) -> - ssl:controlling_process(Socket, Pid). - --spec peername(ssl:sslsocket()) - -> {ok, {inet:ip_address(), inet:port_number()}} | {error, atom()}. -peername(Socket) -> - ssl:peername(Socket). - --spec sockname(ssl:sslsocket()) - -> {ok, {inet:ip_address(), inet:port_number()}} | {error, atom()}. -sockname(Socket) -> - ssl:sockname(Socket). - --spec shutdown(ssl:sslsocket(), read | write | read_write) - -> ok | {error, atom()}. -shutdown(Socket, How) -> - ssl:shutdown(Socket, How). - --spec close(ssl:sslsocket()) -> ok. -close(Socket) -> - ssl:close(Socket). - -%% Internal. - -%% Unfortunately the implementation of elliptic-curve ciphers that has -%% been introduced in R16B01 is incomplete. Depending on the particular -%% client, this can cause the TLS handshake to break during key -%% agreement. Depending on the ssl application version, this function -%% returns a list of all cipher suites that are supported by default, -%% minus the elliptic-curve ones. --spec unbroken_cipher_suites() -> [ssl:erl_cipher_suite()]. -unbroken_cipher_suites() -> - case proplists:get_value(ssl_app, ssl:versions()) of - Version when Version =:= "5.3"; Version =:= "5.3.1" -> - lists:filter(fun(Suite) -> - string:left(atom_to_list(element(1, Suite)), 4) =/= "ecdh" - end, ssl:cipher_suites()); - _ -> - ssl:cipher_suites() - end. DELETED deps/ranch/src/ranch_sup.erl Index: deps/ranch/src/ranch_sup.erl ================================================================== --- deps/ranch/src/ranch_sup.erl +++ /dev/null @@ -1,32 +0,0 @@ -%% Copyright (c) 2011-2015, Loïc Hoguin -%% -%% Permission to use, copy, modify, and/or distribute this software for any -%% purpose with or without fee is hereby granted, provided that the above -%% copyright notice and this permission notice appear in all copies. -%% -%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - --module(ranch_sup). --behaviour(supervisor). - --export([start_link/0]). --export([init/1]). - --spec start_link() -> {ok, pid()}. -start_link() -> - supervisor:start_link({local, ?MODULE}, ?MODULE, []). - -init([]) -> - ranch_server = ets:new(ranch_server, [ - ordered_set, public, named_table]), - Procs = [ - {ranch_server, {ranch_server, start_link, []}, - permanent, 5000, worker, [ranch_server]} - ], - {ok, {{one_for_one, 10, 10}, Procs}}. DELETED deps/ranch/src/ranch_tcp.erl Index: deps/ranch/src/ranch_tcp.erl ================================================================== --- deps/ranch/src/ranch_tcp.erl +++ /dev/null @@ -1,204 +0,0 @@ -%% Copyright (c) 2011-2015, Loïc Hoguin -%% -%% Permission to use, copy, modify, and/or distribute this software for any -%% purpose with or without fee is hereby granted, provided that the above -%% copyright notice and this permission notice appear in all copies. -%% -%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - --module(ranch_tcp). --behaviour(ranch_transport). - --export([name/0]). --export([secure/0]). --export([messages/0]). --export([listen/1]). --export([listen_options/0]). --export([accept/2]). --export([accept_ack/2]). --export([connect/3]). --export([connect/4]). --export([recv/3]). --export([send/2]). --export([sendfile/2]). --export([sendfile/4]). --export([sendfile/5]). --export([setopts/2]). --export([controlling_process/2]). --export([peername/1]). --export([sockname/1]). --export([shutdown/2]). --export([close/1]). - --type opt() :: {backlog, non_neg_integer()} - | {buffer, non_neg_integer()} - | {delay_send, boolean()} - | {dontroute, boolean()} - | {exit_on_close, boolean()} - | {fd, non_neg_integer()} - | {high_msgq_watermark, non_neg_integer()} - | {high_watermark, non_neg_integer()} - | inet - | inet6 - | {ip, inet:ip_address()} - | {keepalive, boolean()} - | {linger, {boolean(), non_neg_integer()}} - | {low_msgq_watermark, non_neg_integer()} - | {low_watermark, non_neg_integer()} - | {nodelay, boolean()} - | {port, inet:port_number()} - | {priority, integer()} - | {raw, non_neg_integer(), non_neg_integer(), binary()} - | {recbuf, non_neg_integer()} - | {send_timeout, timeout()} - | {send_timeout_close, boolean()} - | {sndbuf, non_neg_integer()} - | {tos, integer()}. --export_type([opt/0]). - --type opts() :: [opt()]. --export_type([opts/0]). - -name() -> tcp. - --spec secure() -> boolean(). -secure() -> - false. - -messages() -> {tcp, tcp_closed, tcp_error}. - --spec listen(opts()) -> {ok, inet:socket()} | {error, atom()}. -listen(Opts) -> - Opts2 = ranch:set_option_default(Opts, backlog, 1024), - Opts3 = ranch:set_option_default(Opts2, nodelay, true), - Opts4 = ranch:set_option_default(Opts3, send_timeout, 30000), - Opts5 = ranch:set_option_default(Opts4, send_timeout_close, true), - %% We set the port to 0 because it is given in the Opts directly. - %% The port in the options takes precedence over the one in the - %% first argument. - gen_tcp:listen(0, ranch:filter_options(Opts5, listen_options(), - [binary, {active, false}, {packet, raw}, {reuseaddr, true}])). - -%% 'inet' and 'inet6' are also allowed but they are handled -%% specifically as they do not have 2-tuple equivalents. -%% -%% The 4-tuple 'raw' option is also handled specifically. -listen_options() -> - [backlog, buffer, delay_send, dontroute, exit_on_close, fd, - high_msgq_watermark, high_watermark, ip, - keepalive, linger, low_msgq_watermark, - low_watermark, nodelay, port, priority, recbuf, - send_timeout, send_timeout_close, sndbuf, tos]. - --spec accept(inet:socket(), timeout()) - -> {ok, inet:socket()} | {error, closed | timeout | atom()}. -accept(LSocket, Timeout) -> - gen_tcp:accept(LSocket, Timeout). - --spec accept_ack(inet:socket(), timeout()) -> ok. -accept_ack(_, _) -> - ok. - -%% @todo Probably filter Opts? --spec connect(inet:ip_address() | inet:hostname(), - inet:port_number(), any()) - -> {ok, inet:socket()} | {error, atom()}. -connect(Host, Port, Opts) when is_integer(Port) -> - gen_tcp:connect(Host, Port, - Opts ++ [binary, {active, false}, {packet, raw}]). - -%% @todo Probably filter Opts? --spec connect(inet:ip_address() | inet:hostname(), - inet:port_number(), any(), timeout()) - -> {ok, inet:socket()} | {error, atom()}. -connect(Host, Port, Opts, Timeout) when is_integer(Port) -> - gen_tcp:connect(Host, Port, - Opts ++ [binary, {active, false}, {packet, raw}], - Timeout). - --spec recv(inet:socket(), non_neg_integer(), timeout()) - -> {ok, any()} | {error, closed | atom()}. -recv(Socket, Length, Timeout) -> - gen_tcp:recv(Socket, Length, Timeout). - --spec send(inet:socket(), iodata()) -> ok | {error, atom()}. -send(Socket, Packet) -> - gen_tcp:send(Socket, Packet). - --spec sendfile(inet:socket(), file:name_all() | file:fd()) - -> {ok, non_neg_integer()} | {error, atom()}. -sendfile(Socket, Filename) -> - sendfile(Socket, Filename, 0, 0, []). - --spec sendfile(inet:socket(), file:name_all() | file:fd(), non_neg_integer(), - non_neg_integer()) - -> {ok, non_neg_integer()} | {error, atom()}. -sendfile(Socket, File, Offset, Bytes) -> - sendfile(Socket, File, Offset, Bytes, []). - --spec sendfile(inet:socket(), file:name_all() | file:fd(), non_neg_integer(), - non_neg_integer(), [{chunk_size, non_neg_integer()}]) - -> {ok, non_neg_integer()} | {error, atom()}. -sendfile(Socket, Filename, Offset, Bytes, Opts) - when is_list(Filename) orelse is_atom(Filename) - orelse is_binary(Filename) -> - case file:open(Filename, [read, raw, binary]) of - {ok, RawFile} -> - try sendfile(Socket, RawFile, Offset, Bytes, Opts) of - Result -> Result - after - ok = file:close(RawFile) - end; - {error, _} = Error -> - Error - end; -sendfile(Socket, RawFile, Offset, Bytes, Opts) -> - Opts2 = case Opts of - [] -> [{chunk_size, 16#1FFF}]; - _ -> Opts - end, - try file:sendfile(RawFile, Socket, Offset, Bytes, Opts2) of - Result -> Result - catch - error:{badmatch, {error, enotconn}} -> - %% file:sendfile/5 might fail by throwing a - %% {badmatch, {error, enotconn}}. This is because its - %% implementation fails with a badmatch in - %% prim_file:sendfile/10 if the socket is not connected. - {error, closed} - end. - -%% @todo Probably filter Opts? --spec setopts(inet:socket(), list()) -> ok | {error, atom()}. -setopts(Socket, Opts) -> - inet:setopts(Socket, Opts). - --spec controlling_process(inet:socket(), pid()) - -> ok | {error, closed | not_owner | atom()}. -controlling_process(Socket, Pid) -> - gen_tcp:controlling_process(Socket, Pid). - --spec peername(inet:socket()) - -> {ok, {inet:ip_address(), inet:port_number()}} | {error, atom()}. -peername(Socket) -> - inet:peername(Socket). - --spec sockname(inet:socket()) - -> {ok, {inet:ip_address(), inet:port_number()}} | {error, atom()}. -sockname(Socket) -> - inet:sockname(Socket). - --spec shutdown(inet:socket(), read | write | read_write) - -> ok | {error, atom()}. -shutdown(Socket, How) -> - gen_tcp:shutdown(Socket, How). - --spec close(inet:socket()) -> ok. -close(Socket) -> - gen_tcp:close(Socket). DELETED deps/ranch/src/ranch_transport.erl Index: deps/ranch/src/ranch_transport.erl ================================================================== --- deps/ranch/src/ranch_transport.erl +++ /dev/null @@ -1,141 +0,0 @@ -%% Copyright (c) 2012-2015, Loïc Hoguin -%% -%% Permission to use, copy, modify, and/or distribute this software for any -%% purpose with or without fee is hereby granted, provided that the above -%% copyright notice and this permission notice appear in all copies. -%% -%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - --module(ranch_transport). - --export([sendfile/6]). - --type socket() :: any(). --type opts() :: any(). --type sendfile_opts() :: [{chunk_size, non_neg_integer()}]. --export_type([sendfile_opts/0]). - --callback name() -> atom(). --callback secure() -> boolean(). --callback messages() -> {OK::atom(), Closed::atom(), Error::atom()}. --callback listen(opts()) -> {ok, socket()} | {error, atom()}. --callback accept(socket(), timeout()) - -> {ok, socket()} | {error, closed | timeout | atom()}. --callback accept_ack(socket(), timeout()) -> ok. --callback connect(string(), inet:port_number(), opts()) - -> {ok, socket()} | {error, atom()}. --callback connect(string(), inet:port_number(), opts(), timeout()) - -> {ok, socket()} | {error, atom()}. --callback recv(socket(), non_neg_integer(), timeout()) - -> {ok, any()} | {error, closed | timeout | atom()}. --callback send(socket(), iodata()) -> ok | {error, atom()}. --callback sendfile(socket(), file:name() | file:fd()) - -> {ok, non_neg_integer()} | {error, atom()}. --callback sendfile(socket(), file:name() | file:fd(), non_neg_integer(), - non_neg_integer()) -> {ok, non_neg_integer()} | {error, atom()}. --callback sendfile(socket(), file:name() | file:fd(), non_neg_integer(), - non_neg_integer(), sendfile_opts()) - -> {ok, non_neg_integer()} | {error, atom()}. --callback setopts(socket(), opts()) -> ok | {error, atom()}. --callback controlling_process(socket(), pid()) - -> ok | {error, closed | not_owner | atom()}. --callback peername(socket()) - -> {ok, {inet:ip_address(), inet:port_number()}} | {error, atom()}. --callback sockname(socket()) - -> {ok, {inet:ip_address(), inet:port_number()}} | {error, atom()}. --callback shutdown(socket(), read | write | read_write) - -> ok | {error, atom()}. --callback close(socket()) -> ok. - -%% A fallback for transports that don't have a native sendfile implementation. -%% Note that the ordering of arguments is different from file:sendfile/5 and -%% that this function accepts either a raw file or a file name. --spec sendfile(module(), socket(), file:filename_all() | file:fd(), - non_neg_integer(), non_neg_integer(), sendfile_opts()) - -> {ok, non_neg_integer()} | {error, atom()}. -sendfile(Transport, Socket, Filename, Offset, Bytes, Opts) - when is_list(Filename) orelse is_atom(Filename) - orelse is_binary(Filename) -> - ChunkSize = chunk_size(Opts), - case file:open(Filename, [read, raw, binary]) of - {ok, RawFile} -> - _ = case Offset of - 0 -> - ok; - _ -> - {ok, _} = file:position(RawFile, {bof, Offset}) - end, - try - sendfile_loop(Transport, Socket, RawFile, Bytes, 0, ChunkSize) - after - ok = file:close(RawFile) - end; - {error, _Reason} = Error -> - Error - end; -sendfile(Transport, Socket, RawFile, Offset, Bytes, Opts) -> - ChunkSize = chunk_size(Opts), - Initial2 = case file:position(RawFile, {cur, 0}) of - {ok, Offset} -> - Offset; - {ok, Initial} -> - {ok, _} = file:position(RawFile, {bof, Offset}), - Initial - end, - case sendfile_loop(Transport, Socket, RawFile, Bytes, 0, ChunkSize) of - {ok, _Sent} = Result -> - {ok, _} = file:position(RawFile, {bof, Initial2}), - Result; - {error, _Reason} = Error -> - Error - end. - --spec chunk_size(sendfile_opts()) -> pos_integer(). -chunk_size(Opts) -> - case lists:keyfind(chunk_size, 1, Opts) of - {chunk_size, ChunkSize} - when is_integer(ChunkSize) andalso ChunkSize > 0 -> - ChunkSize; - {chunk_size, 0} -> - 16#1FFF; - false -> - 16#1FFF - end. - --spec sendfile_loop(module(), socket(), file:fd(), non_neg_integer(), - non_neg_integer(), pos_integer()) - -> {ok, non_neg_integer()} | {error, term()}. -sendfile_loop(_Transport, _Socket, _RawFile, Sent, Sent, _ChunkSize) - when Sent =/= 0 -> - %% All requested data has been read and sent, return number of bytes sent. - {ok, Sent}; -sendfile_loop(Transport, Socket, RawFile, Bytes, Sent, ChunkSize) -> - ReadSize = read_size(Bytes, Sent, ChunkSize), - case file:read(RawFile, ReadSize) of - {ok, IoData} -> - case Transport:send(Socket, IoData) of - ok -> - Sent2 = iolist_size(IoData) + Sent, - sendfile_loop(Transport, Socket, RawFile, Bytes, Sent2, - ChunkSize); - {error, _Reason} = Error -> - Error - end; - eof -> - {ok, Sent}; - {error, _Reason} = Error -> - Error - end. - --spec read_size(non_neg_integer(), non_neg_integer(), non_neg_integer()) -> - non_neg_integer(). -read_size(0, _Sent, ChunkSize) -> - ChunkSize; -read_size(Bytes, Sent, ChunkSize) -> - min(Bytes - Sent, ChunkSize). DELETED lib/antigone.ex Index: lib/antigone.ex ================================================================== --- lib/antigone.ex +++ /dev/null @@ -1,18 +0,0 @@ -defmodule Antigone do - use Application - - def start(_type, _args) do - import Supervisor.Spec, warn: false - - children = [ - worker(__MODULE__, [], function: :serve), - ] - - opts = [strategy: :one_for_one, name: Antigone.Supervisor] - Supervisor.start_link(children, opts) - end - - def serve do - {:ok,_} = Plug.Adapters.Cowboy.http Router, [] - end -end DELETED lib/router.ex Index: lib/router.ex ================================================================== --- lib/router.ex +++ /dev/null @@ -1,14 +0,0 @@ -defmodule Router do - use Plug.Builder - - if Mix.env == :dev do - use Plug.Debugger - end - - plug Plug.Static, at: "/", from: "www" - plug :not_found - - def not_found(conn, _) do - send_file(conn, 404, "www/404.html") - end -end DELETED mix.exs Index: mix.exs ================================================================== --- mix.exs +++ /dev/null @@ -1,24 +0,0 @@ -defmodule Antigone.Mixfile do - use Mix.Project - - def project do - [app: :antigone, - version: "0.0.1", - elixir: "~> 1.1", - build_embedded: Mix.env == :prod, - start_permanent: Mix.env == :prod, - deps: deps] - end - - def application do - [applications: [:logger, :cowboy, :plug], - mod: {Antigone, []}] - end - - defp deps do - [ - {:cowboy, "~> 1.0.4"}, - {:plug, "~> 1.0.3"} - ] - end -end DELETED mix.lock Index: mix.lock ================================================================== --- mix.lock +++ /dev/null @@ -1,4 +0,0 @@ -%{"cowboy": {:hex, :cowboy, "1.0.4"}, - "cowlib": {:hex, :cowlib, "1.0.2"}, - "plug": {:hex, :plug, "1.0.3"}, - "ranch": {:hex, :ranch, "1.2.0"}} DELETED test/antigone_test.exs Index: test/antigone_test.exs ================================================================== --- test/antigone_test.exs +++ /dev/null @@ -1,8 +0,0 @@ -defmodule AntigoneTest do - use ExUnit.Case - doctest Antigone - - test "the truth" do - assert 1 + 1 == 2 - end -end DELETED test/test_helper.exs Index: test/test_helper.exs ================================================================== --- test/test_helper.exs +++ /dev/null @@ -1,1 +0,0 @@ -ExUnit.start() DELETED www/404.html Index: www/404.html ================================================================== --- www/404.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - Error: 404 - - -
-

Error

-
-
-

404: File Not Found

-

We could not find the content you requested.

-

Please check your URL and try again.

-
- - -