Add ISC license and Cowboy based web service template
This commit is contained in:
parent
7ce93df72e
commit
312db0e63c
@ -332,7 +332,12 @@ done({error, Info, Code}) ->
|
||||
ok = zx_daemon:idle(),
|
||||
Message = "Operation failed with: ~160tp",
|
||||
ok = tell(error, Message, [Info]),
|
||||
init:stop(Code).
|
||||
init:stop(Code);
|
||||
done({error, Class, Error, Stacktrace}) ->
|
||||
ok = zx_daemon:idle(),
|
||||
Message = "Execution failed with: ~tp: ~tp~nStacktrace:~n~tp",
|
||||
ok = tell(error, Message, [Class, Error, Stacktrace]),
|
||||
init:stop(1).
|
||||
|
||||
|
||||
-spec not_done(outcome()) -> ok | no_return().
|
||||
@ -442,7 +447,10 @@ start(LogPath) ->
|
||||
overload_kill_qlen => 20000,
|
||||
overload_kill_restart_after => 5000,
|
||||
sync_mode_qlen => 10,
|
||||
type => {file, LogPath}},
|
||||
type => file,
|
||||
file => LogPath,
|
||||
max_no_bytes => 10000000,
|
||||
max_no_files => 10},
|
||||
filter_default =>
|
||||
stop,
|
||||
filters =>
|
||||
@ -468,8 +476,8 @@ trim_logs(LogDir) ->
|
||||
{ok, Origin} = file:get_cwd(),
|
||||
ok = file:set_cwd(LogDir),
|
||||
{ok, Files} = file:list_dir("."),
|
||||
Desc = fun(A, B) -> A > B end,
|
||||
Sorted = lists:sort(Desc, Files),
|
||||
Descending = fun(A, B) -> A > B end,
|
||||
Sorted = lists:sort(Descending, Files),
|
||||
ok =
|
||||
case length(Sorted) =< 10 of
|
||||
true -> ok;
|
||||
@ -873,6 +881,11 @@ search_xdg([]) ->
|
||||
%% procedure the runtime will halt with an error message.
|
||||
|
||||
run(PackageString, RunArgs) ->
|
||||
try run1(PackageString, RunArgs)
|
||||
catch C:E:S -> {error, C, E, S}
|
||||
end.
|
||||
|
||||
run1(PackageString, RunArgs) ->
|
||||
case zx_lib:package_id(PackageString) of
|
||||
{ok, {"otpr", "zomp", Version}} -> run2_maybe(Version, RunArgs);
|
||||
{ok, FuzzyID} -> run2(FuzzyID, RunArgs);
|
||||
@ -969,6 +982,11 @@ resolve_version(PackageID = {Realm, Name, _}) ->
|
||||
%% and use zx commands to add or drop dependencies made available via zomp.
|
||||
|
||||
run_local(RunArgs) ->
|
||||
try run_local1(RunArgs)
|
||||
catch C:E:S -> {error, C, E, S}
|
||||
end.
|
||||
|
||||
run_local1(RunArgs) ->
|
||||
{ok, ProjectDir} = file:get_cwd(),
|
||||
run_project(ProjectDir, ProjectDir, RunArgs).
|
||||
|
||||
@ -978,6 +996,11 @@ run_local(RunArgs) ->
|
||||
RunArgs :: [string()].
|
||||
|
||||
run_dir(TargetDir, RunArgs) ->
|
||||
try run_dir1(TargetDir, RunArgs)
|
||||
catch C:E:S -> {error, C, E, S}
|
||||
end.
|
||||
|
||||
run_dir1(TargetDir, RunArgs) ->
|
||||
{ok, ExecDir} = file:get_cwd(),
|
||||
case file:set_cwd(TargetDir) of
|
||||
ok ->
|
||||
@ -1009,9 +1032,13 @@ run_project(ProjectDir, ExecDir, RunArgs, Meta) ->
|
||||
case prepare(Deps) of
|
||||
ok ->
|
||||
ok = file:set_cwd(ProjectDir),
|
||||
ok = zx_lib:build(),
|
||||
case zx_lib:build() of
|
||||
ok ->
|
||||
ok = file:set_cwd(ExecDir),
|
||||
execute(Type, PackageID, Meta, ProjectDir, NewArgs);
|
||||
error ->
|
||||
{error, build_failed}
|
||||
end;
|
||||
Error ->
|
||||
Error
|
||||
end;
|
||||
@ -1077,8 +1104,10 @@ is_local(_, []) -> false.
|
||||
%% Execution prep common to all packages.
|
||||
|
||||
prepare(Deps) ->
|
||||
ok = ensure(Deps),
|
||||
make(Deps).
|
||||
case ensure(Deps) of
|
||||
ok -> make(Deps);
|
||||
Error -> Error
|
||||
end.
|
||||
|
||||
ensure([{fetch, Dep} | Rest]) ->
|
||||
case filelib:is_dir(zx_lib:ppath(lib, Dep)) of
|
||||
@ -1115,9 +1144,13 @@ make([{local, _, Dir} | Rest]) ->
|
||||
{ok, WorkingDir} = file:get_cwd(),
|
||||
case file:set_cwd(Dir) of
|
||||
ok ->
|
||||
ok = zx_lib:build(),
|
||||
case zx_lib:build() of
|
||||
ok ->
|
||||
ok = file:set_cwd(WorkingDir),
|
||||
make(Rest);
|
||||
error ->
|
||||
{error, build_failed}
|
||||
end;
|
||||
Error = {error, enoent} ->
|
||||
ok = tell(error, "Dir ~p does not exist!", [Dir]),
|
||||
Error
|
||||
|
||||
@ -92,10 +92,14 @@ initialize(P = #project{id = none}) ->
|
||||
initialize(P#project{id = ID, appmod = Name});
|
||||
initialize(P = #project{type = app, id = {_, Name, _}, prefix = none}) ->
|
||||
initialize(P#project{prefix = ask_prefix(Name)});
|
||||
initialize(P = #project{type = web, id = {_, Name, _}, prefix = none}) ->
|
||||
initialize(P#project{prefix = ask_prefix(Name)});
|
||||
initialize(P = #project{type = gui, id = {_, Name, _}, prefix = none}) ->
|
||||
initialize(P#project{prefix = ask_prefix(Name)});
|
||||
initialize(P = #project{type = app, appmod = none}) ->
|
||||
initialize(P#project{appmod = ask_appmod()});
|
||||
initialize(P = #project{type = web, appmod = none}) ->
|
||||
initialize(P#project{appmod = ask_appmod()});
|
||||
initialize(P = #project{type = cli, appmod = none}) ->
|
||||
initialize(P#project{appmod = ask_appmod()});
|
||||
initialize(P = #project{type = gui, appmod = none}) ->
|
||||
@ -190,6 +194,7 @@ initialize(P = #project{type = Type,
|
||||
TS =
|
||||
case Type of
|
||||
app -> "Erlang application";
|
||||
web -> "Web service";
|
||||
cli -> "CLI/terminal program";
|
||||
gui -> "GUI application"
|
||||
end,
|
||||
@ -304,9 +309,10 @@ zompify(P = #project{type = Type,
|
||||
prefix => Prefix,
|
||||
tags => []},
|
||||
Data =
|
||||
case Type == cli of
|
||||
true -> maps:put(mod, Module, Simple);
|
||||
false -> Simple
|
||||
case Type of
|
||||
cli -> maps:put(mod, Module, Simple);
|
||||
web -> Simple#{type := app, deps => cowboy_deps()};
|
||||
_ -> Simple
|
||||
end,
|
||||
ok = zx_lib:write_project_meta(Data),
|
||||
ok = ensure_emakefile(),
|
||||
@ -315,6 +321,17 @@ zompify(P = #project{type = Type,
|
||||
{ok, PackageString} = zx_lib:package_string(ID),
|
||||
tell("Project ~ts initialized.", [PackageString]).
|
||||
|
||||
cowboy_deps() ->
|
||||
Apps = [{"otpr", N} || N <- ["cowboy", "ranch", "cowlib"]],
|
||||
cowboy_deps(Apps).
|
||||
|
||||
cowboy_deps([App = {Realm, Name} | Apps]) ->
|
||||
{ok, Ref} = zx_daemon:latest(App),
|
||||
{ok, Ver} = zx_daemon:wait_result(Ref),
|
||||
[{Realm, Name, Ver} | cowboy_deps(Apps)];
|
||||
cowboy_deps([]) ->
|
||||
[].
|
||||
|
||||
|
||||
-spec ensure_emakefile() -> ok.
|
||||
|
||||
@ -347,6 +364,7 @@ ensure_license(#project{name = Name,
|
||||
"LGPL-3.0-only" -> "lgpl3.txt";
|
||||
"LGPL-3.0-or-later" -> "lgpl3.txt";
|
||||
"MIT" -> "mit.txt";
|
||||
"ISC" -> "isc.txt";
|
||||
"MPL-2.0" -> "mpl2.txt";
|
||||
"CC0" -> "cc0.txt"
|
||||
end,
|
||||
@ -1210,10 +1228,14 @@ create(P = #project{id = none}) ->
|
||||
create(P#project{id = ID, appmod = AppMod});
|
||||
create(P = #project{type = app, id = {_, Name, _}, prefix = none}) ->
|
||||
create(P#project{prefix = ask_prefix(Name)});
|
||||
create(P = #project{type = web, id = {_, Name, _}, prefix = none}) ->
|
||||
create(P#project{prefix = ask_prefix(Name)});
|
||||
create(P = #project{type = gui, id = {_, Name, _}, prefix = none}) ->
|
||||
create(P#project{prefix = ask_prefix(Name)});
|
||||
create(P = #project{type = app, appmod = none}) ->
|
||||
create(P#project{appmod = ask_appmod()});
|
||||
create(P = #project{type = web, appmod = none}) ->
|
||||
create(P#project{appmod = ask_appmod()});
|
||||
create(P = #project{type = gui, appmod = none}) ->
|
||||
create(P#project{appmod = ask_appmod()});
|
||||
create(P = #project{type = cli, module = none}) ->
|
||||
@ -1402,6 +1424,7 @@ create(P = #project{type = Type,
|
||||
TS =
|
||||
case Type of
|
||||
app -> "Erlang application";
|
||||
web -> "Web service";
|
||||
gui -> "GUI application"
|
||||
end,
|
||||
Instructions =
|
||||
@ -1648,6 +1671,7 @@ munge_sources(#project{type = Type,
|
||||
Template =
|
||||
case Type of
|
||||
app -> "example_server";
|
||||
web -> "cowboy_example";
|
||||
gui -> "hellowx"
|
||||
end,
|
||||
TemplateDir = filename:join([os:getenv("ZX_DIR"), "templates", Template]),
|
||||
@ -1716,17 +1740,19 @@ ask_project_type() ->
|
||||
"to work, even if it acts in a supporting role.~n"
|
||||
"(Note that escripts cannot be packaged.)~n"
|
||||
"[1] Traditional Erlang service application~n"
|
||||
"[2] Library~n"
|
||||
"[3] End-user GUI application~n"
|
||||
"[4] End-user CLI application~n"
|
||||
"[5] Escript~n",
|
||||
"[2] Cowboy-based web service~n"
|
||||
"[3] Library~n"
|
||||
"[4] End-user GUI application~n"
|
||||
"[5] End-user CLI application~n"
|
||||
"[6] Escript~n",
|
||||
ok = io:format(Instructions),
|
||||
case zx_tty:get_input() of
|
||||
"1" -> app;
|
||||
"2" -> lib;
|
||||
"3" -> gui;
|
||||
"4" -> cli;
|
||||
"5" -> escript;
|
||||
"2" -> web;
|
||||
"3" -> lib;
|
||||
"4" -> gui;
|
||||
"5" -> cli;
|
||||
"6" -> escript;
|
||||
_ ->
|
||||
ok = zx_tty:derp(),
|
||||
ask_project_type()
|
||||
@ -2551,6 +2577,7 @@ ask_license() ->
|
||||
{"GNU Library (LGPL) v3.0 only", "LGPL-3.0-only"},
|
||||
{"GNU Library (LGPL) v3.0 or later", "LGPL-3.0-or-later"},
|
||||
{"MIT license", "MIT"},
|
||||
{"ISC license", "ISC"},
|
||||
{"Mozilla Public License 2.0", "MPL-2.0"},
|
||||
{"Public Domain/Creative Commons Zero notice", "CC0"},
|
||||
{"[proprietary]", proprietary},
|
||||
|
||||
59
zomp/lib/otpr/zx/0.13.0/templates/cowboy_example/appmod.erl
Normal file
59
zomp/lib/otpr/zx/0.13.0/templates/cowboy_example/appmod.erl
Normal file
@ -0,0 +1,59 @@
|
||||
%%% @doc
|
||||
%%% 〘*PROJECT NAME*〙
|
||||
%%% @end
|
||||
|
||||
-module(〘*APP MOD*〙).
|
||||
-vsn("〘*VERSION*〙").
|
||||
〘*AUTHOR*〙
|
||||
〘*COPYRIGHT*〙
|
||||
〘*LICENSE*〙
|
||||
|
||||
-export([start/0, start/1]).
|
||||
-export([start/2, stop/1]).
|
||||
|
||||
|
||||
|
||||
-spec start() -> ok.
|
||||
%% @doc
|
||||
%% Start the server in an "ignore" state.
|
||||
|
||||
start() ->
|
||||
ok = application:start(hello_web),
|
||||
io:format("Starting...").
|
||||
|
||||
|
||||
-spec start(PortNum) -> ok
|
||||
when PortNum :: inet:port_number().
|
||||
%% @doc
|
||||
%% Start the server and begin listening immediately. Slightly more convenient when
|
||||
%% playing around in the shell.
|
||||
|
||||
start(PortNum) ->
|
||||
ok = start(),
|
||||
io:format("Startup complete, listening on ~w~n", [PortNum]).
|
||||
|
||||
|
||||
-spec start(normal, term()) -> {ok, pid()}.
|
||||
%% @private
|
||||
%% Called by OTP to kick things off. This is for the use of the "application" part of
|
||||
%% OTP, not to be called by user code.
|
||||
%% See: http://erlang.org/doc/apps/kernel/application.html
|
||||
|
||||
start(normal, _Args) ->
|
||||
ok = application:ensure_started(sasl),
|
||||
{ok, Started} = application:ensure_all_started(cowboy),
|
||||
ok = io:format("Started: ~p~n", [Started]),
|
||||
Routes = [{'_', [{"/", 〘*PREFIX*〙_top, []}]}],
|
||||
Dispatch = cowboy_router:compile(Routes),
|
||||
Env = #{env => #{dispatch => Dispatch}},
|
||||
{ok, _} = cowboy:start_clear(〘*PREFIX*〙_listener, [{port, 8080}], Env),
|
||||
〘*PREFIX*〙_sup:start_link().
|
||||
|
||||
|
||||
-spec stop(term()) -> ok.
|
||||
%% @private
|
||||
%% Similar to start/2 above, this is to be called by the "application" part of OTP,
|
||||
%% not client code. Causes a (hopefully graceful) shutdown of the application.
|
||||
|
||||
stop(_State) ->
|
||||
ok.
|
||||
119
zomp/lib/otpr/zx/0.13.0/templates/cowboy_example/src/_state.erl
Normal file
119
zomp/lib/otpr/zx/0.13.0/templates/cowboy_example/src/_state.erl
Normal file
@ -0,0 +1,119 @@
|
||||
%%% @doc
|
||||
%%% 〘*PROJECT NAME*〙 State
|
||||
%%%
|
||||
%%% This template has been generated by the `zx create project' command and is
|
||||
%%% dead simple. You can have it save a value and you can read that value back out.
|
||||
%%% Obviously you will probably want more from a web server than this,
|
||||
%%% so make it your own.
|
||||
%%% @end
|
||||
|
||||
-module(〘*PREFIX*〙_state).
|
||||
-vsn("〘*VERSION*〙").
|
||||
-behavior(gen_server).
|
||||
〘*AUTHOR*〙
|
||||
〘*COPYRIGHT*〙
|
||||
〘*LICENSE*〙
|
||||
|
||||
-export([save/2, read/1]).
|
||||
-export([start_link/0]).
|
||||
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
|
||||
code_change/3, terminate/2]).
|
||||
|
||||
|
||||
%%% Type and Record Definitions
|
||||
|
||||
-record(s,
|
||||
{data = #{} :: #{Key :: term() := Value :: term()}}).
|
||||
|
||||
-type state() :: #s{}.
|
||||
|
||||
|
||||
|
||||
%%% Service Interface
|
||||
|
||||
-spec save(Key, Value) -> ok
|
||||
when Key :: term(),
|
||||
Value :: term().
|
||||
%% @doc
|
||||
%% Save a value.
|
||||
|
||||
save(Key, Value) ->
|
||||
gen_server:cast(?MODULE, {save, Key, Value}).
|
||||
|
||||
|
||||
-spec read(Key) -> {ok, Value} | error
|
||||
when Key :: term(),
|
||||
Value :: term().
|
||||
%% @doc
|
||||
%% Read a value.
|
||||
|
||||
read(ConfKey) ->
|
||||
gen_server:call(?MODULE, {read, ConfKey}).
|
||||
|
||||
|
||||
|
||||
%%% Startup Functions
|
||||
|
||||
-spec start_link() -> Result
|
||||
when Result :: {ok, pid()}
|
||||
| {error, Reason :: term()}.
|
||||
%% @private
|
||||
%% This should only ever be called by hw_sup (the service-level supervisor).
|
||||
|
||||
start_link() ->
|
||||
gen_server:start_link({local, ?MODULE}, ?MODULE, none, []).
|
||||
|
||||
|
||||
-spec init(none) -> {ok, state()}.
|
||||
%% @private
|
||||
%% Called by the supervisor process to give the process a chance to perform any
|
||||
%% preparatory work necessary for proper function.
|
||||
|
||||
init(none) ->
|
||||
State = #s{},
|
||||
{ok, State}.
|
||||
|
||||
|
||||
|
||||
%%% gen_server Message Handling Callbacks
|
||||
|
||||
handle_call({read, ConfKey}, _, State) ->
|
||||
Value = do_read(ConfKey, State),
|
||||
{reply, Value, State};
|
||||
handle_call(Unexpected, From, State) ->
|
||||
ok = io:format("~p Unexpected call from ~tp: ~tp~n", [self(), From, Unexpected]),
|
||||
{noreply, State}.
|
||||
|
||||
handle_cast({save, ConfKey, Value}, State) ->
|
||||
NewState = do_save(ConfKey, Value, State),
|
||||
{noreply, NewState};
|
||||
handle_cast(Unexpected, State) ->
|
||||
ok = io:format("~p Unexpected cast: ~tp~n", [self(), Unexpected]),
|
||||
{noreply, State}.
|
||||
|
||||
handle_info(Unexpected, State) ->
|
||||
ok = io:format("~p Unexpected info: ~tp~n", [self(), Unexpected]),
|
||||
{noreply, State}.
|
||||
|
||||
|
||||
|
||||
%%% OTP Service Functions
|
||||
|
||||
code_change(_, State, _) ->
|
||||
{ok, State}.
|
||||
|
||||
|
||||
terminate(_, _) ->
|
||||
ok.
|
||||
|
||||
|
||||
|
||||
%%% Doer Functions
|
||||
|
||||
do_save(Key, Value, State = #s{data = Data}) ->
|
||||
NewData = maps:put(Key, Value, Data),
|
||||
State#s{data = NewData}.
|
||||
|
||||
|
||||
do_read(Key, #s{data = Data}) ->
|
||||
maps:find(Key, Data).
|
||||
@ -0,0 +1,44 @@
|
||||
%%% @doc
|
||||
%%% 〘*PROJECT NAME*〙 Top-level Supervisor
|
||||
%%%
|
||||
%%% The very top level supervisor in the system.
|
||||
%%% There is only one stateful worker defined by default here, simple
|
||||
%%% called [project]_state. Make it yours.
|
||||
%%%
|
||||
%%% See: http://erlang.org/doc/design_principles/applications.html
|
||||
%%% See: http://zxq9.com/archives/1311
|
||||
%%% @end
|
||||
|
||||
-module(〘*PREFIX*〙_sup).
|
||||
-vsn("〘*VERSION*〙").
|
||||
-behaviour(supervisor).
|
||||
〘*AUTHOR*〙
|
||||
〘*COPYRIGHT*〙
|
||||
〘*LICENSE*〙
|
||||
|
||||
-export([start_link/0]).
|
||||
-export([init/1]).
|
||||
|
||||
|
||||
-spec start_link() -> {ok, pid()}.
|
||||
%% @private
|
||||
%% This supervisor's own start function.
|
||||
|
||||
start_link() ->
|
||||
supervisor:start_link({local, ?MODULE}, ?MODULE, []).
|
||||
|
||||
|
||||
-spec init([]) -> {ok, {supervisor:sup_flags(), [supervisor:child_spec()]}}.
|
||||
%% @private
|
||||
%% The OTP init/1 function.
|
||||
|
||||
init([]) ->
|
||||
RestartStrategy = {one_for_one, 1, 60},
|
||||
State = {〘*PREFIX*〙_state,
|
||||
{〘*PREFIX*〙_state, start_link, []},
|
||||
permanent,
|
||||
5000,
|
||||
worker,
|
||||
[〘*PREFIX*〙_state]},
|
||||
Children = [State],
|
||||
{ok, {RestartStrategy, Children}}.
|
||||
@ -0,0 +1,38 @@
|
||||
%%% @doc
|
||||
%%% 〘*PROJECT NAME*〙 top-level HTTP request handler.
|
||||
%%% @end
|
||||
|
||||
-module(〘*PREFIX*〙_top).
|
||||
-vsn("〘*VERSION*〙").
|
||||
-behavior(cowboy_handler).
|
||||
〘*AUTHOR*〙
|
||||
〘*COPYRIGHT*〙
|
||||
〘*LICENSE*〙
|
||||
|
||||
-export([init/2]).
|
||||
|
||||
|
||||
-spec init(Req, State) -> Result
|
||||
when Req :: cowboy_req:req(),
|
||||
State :: any(),
|
||||
Result :: {ok, Reply, NewState}
|
||||
| {module(), Reply, NewState, Options},
|
||||
Reply :: cowboy_req:req(),
|
||||
NewState :: any(),
|
||||
Options :: any().
|
||||
|
||||
init(Req, State) ->
|
||||
Hits =
|
||||
case 〘*PREFIX*〙_state:read(hits) of
|
||||
{ok, N} -> N;
|
||||
error -> 1
|
||||
end,
|
||||
ok = 〘*PREFIX*〙_state:save(hits, Hits + 1),
|
||||
Code = 200,
|
||||
Headers = #{<<"content-type">> => <<"text/plain">>},
|
||||
TextHits = integer_to_binary(Hits),
|
||||
Body =
|
||||
<<"Hello, World!\r\n",
|
||||
"We've had ", TextHits/binary, " hits so far.">>,
|
||||
Reply = cowboy_req:reply(Code, Headers, Body, Req),
|
||||
{ok, Reply, State}.
|
||||
@ -1,4 +1,4 @@
|
||||
To the extent possible under law, 〘\*COPYRIGHT HOLDER\*〙 has waived all copyright and related or neighboring rights to 〘\*PROJECT NAME\*〙.
|
||||
To the extent possible under law, 〘*COPYRIGHT HOLDER*〙 has waived all copyright and related or neighboring rights to 〘*PROJECT NAME*〙.
|
||||
|
||||
A more complete reference for the reasoning and formulation of this waiver of property rights is available at the Creative Commons Zero ("CC0") page:
|
||||
https://creativecommons.org/share-your-work/public-domain/cc0/
|
||||
|
||||
14
zomp/lib/otpr/zx/0.13.0/templates/licenses/isc.txt
Normal file
14
zomp/lib/otpr/zx/0.13.0/templates/licenses/isc.txt
Normal file
@ -0,0 +1,14 @@
|
||||
Copyright 〘*YEAR*〙 〘*COPYRIGHT HOLDER*〙
|
||||
|
||||
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.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user