capricorn 0.2.25 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (139) hide show
  1. data/LICENSE +19 -0
  2. data/README.md +1 -0
  3. data/bin/capricorn-app-scaffolder +27 -0
  4. data/bin/capricorn-gem-spec +33 -0
  5. data/bin/capricornctl +12 -0
  6. data/bin/capricornd +31 -0
  7. data/erlang/lib/bert/doc/overview.edoc +4 -0
  8. data/erlang/lib/bert/ebin/bert.app +9 -0
  9. data/erlang/lib/bert/rebar.config +3 -0
  10. data/erlang/lib/bert/src/bert.erl +69 -0
  11. data/erlang/lib/bertio/doc/overview.edoc +4 -0
  12. data/erlang/lib/bertio/ebin/bertio.app +9 -0
  13. data/erlang/lib/bertio/rebar.config +3 -0
  14. data/erlang/lib/bertio/src/bertio.erl +28 -0
  15. data/erlang/lib/bertrpc/doc/overview.edoc +4 -0
  16. data/erlang/lib/bertrpc/ebin/bertrpc.app +12 -0
  17. data/erlang/lib/bertrpc/include/bertrpc.hrl +1 -0
  18. data/erlang/lib/bertrpc/rebar.config +5 -0
  19. data/erlang/lib/bertrpc/src/bertrpc.erl +471 -0
  20. data/erlang/lib/bertrpc/src/bertrpc_hello_world.erl +148 -0
  21. data/erlang/lib/bertrpc/src/fd_tcp.erl +376 -0
  22. data/erlang/lib/capricorn/doc/overview.edoc +4 -0
  23. data/erlang/lib/capricorn/ebin/capricorn.app +56 -0
  24. data/erlang/lib/capricorn/include/capricorn.hrl +76 -0
  25. data/erlang/lib/capricorn/rebar.config +3 -0
  26. data/erlang/lib/capricorn/src/cap_application.erl +170 -0
  27. data/erlang/lib/capricorn/src/cap_cluster.erl +121 -0
  28. data/erlang/lib/capricorn/src/cap_cluster_gems.erl +422 -0
  29. data/erlang/lib/capricorn/src/cap_config.erl +25 -0
  30. data/erlang/lib/capricorn/src/cap_dets_updater.erl +26 -0
  31. data/erlang/lib/capricorn/src/cap_event_sup.erl +35 -0
  32. data/erlang/lib/capricorn/src/cap_events.erl +24 -0
  33. data/erlang/lib/capricorn/src/cap_external_api.erl +87 -0
  34. data/erlang/lib/capricorn/src/cap_external_apps_api.erl +125 -0
  35. data/erlang/lib/capricorn/src/cap_external_gems_api.erl +85 -0
  36. data/erlang/lib/capricorn/src/cap_external_machines_api.erl +18 -0
  37. data/erlang/lib/capricorn/src/cap_gem_utils.erl +111 -0
  38. data/erlang/lib/capricorn/src/cap_internal_api.erl +69 -0
  39. data/erlang/lib/capricorn/src/cap_internal_apps_api.erl +38 -0
  40. data/erlang/lib/capricorn/src/cap_log.erl +113 -0
  41. data/erlang/lib/capricorn/src/cap_machine.erl +338 -0
  42. data/erlang/lib/capricorn/src/cap_machine_apps.erl +410 -0
  43. data/erlang/lib/capricorn/src/cap_machine_apps_sup.erl +57 -0
  44. data/erlang/lib/capricorn/src/cap_sup.erl +200 -0
  45. data/erlang/lib/capricorn/src/cap_util.erl +278 -0
  46. data/erlang/lib/capricorn/src/capricorn.erl +45 -0
  47. data/erlang/lib/capricorn/src/capricorn_app.erl +36 -0
  48. data/erlang/lib/emq/ebin/emq.app +17 -0
  49. data/erlang/lib/emq/src/emq.erl +261 -0
  50. data/erlang/lib/emq/src/emq_app.erl +11 -0
  51. data/erlang/lib/emq/src/emq_pool.erl +178 -0
  52. data/erlang/lib/emq/src/emq_queue.erl +332 -0
  53. data/erlang/lib/emq/src/emq_status.erl +148 -0
  54. data/erlang/lib/emq/src/emq_sup.erl +132 -0
  55. data/erlang/lib/gcd/ebin/gcd.app +18 -0
  56. data/erlang/lib/gcd/include/gcd.hrl +5 -0
  57. data/erlang/lib/gcd/rebar.config +3 -0
  58. data/erlang/lib/gcd/src/gcd.erl +51 -0
  59. data/erlang/lib/gcd/src/gcd_app.erl +13 -0
  60. data/erlang/lib/gcd/src/gcd_event.erl +39 -0
  61. data/erlang/lib/gcd/src/gcd_server.erl +30 -0
  62. data/erlang/lib/gcd/src/gcd_srv.erl +186 -0
  63. data/erlang/lib/gcd/src/gcd_sup.erl +18 -0
  64. data/erlang/rebar +0 -0
  65. data/erlang/rebar.config +9 -0
  66. data/erlang/rel/overlay/bin/capricornd +146 -0
  67. data/erlang/rel/overlay/erts-vsn/bin/erl +34 -0
  68. data/erlang/rel/overlay/erts-vsn/bin/nodetool +80 -0
  69. data/erlang/rel/overlay/etc/capricorn/app.config +59 -0
  70. data/erlang/rel/overlay/etc/capricorn/cluster-vm.args +21 -0
  71. data/erlang/rel/overlay/etc/capricorn/machine-vm.args +21 -0
  72. data/erlang/rel/reltool.config +43 -0
  73. data/ext/Makefile +2 -0
  74. data/ext/extconf.rb +1 -0
  75. data/lib/capricorn-client.rb +86 -0
  76. data/lib/capricorn-client/cli/applications.rb +256 -0
  77. data/lib/capricorn-client/cli/gems.rb +57 -0
  78. data/lib/capricorn-client/cli/machines.rb +9 -0
  79. data/lib/capricorn-client/helpers.rb +62 -0
  80. data/lib/capricorn.rb +5 -99
  81. data/lib/capricorn/driver.rb +86 -0
  82. data/lib/capricorn/recipes/apache-debian.rb +112 -0
  83. data/lib/capricorn/recipes/centos-plesk.rb +162 -0
  84. data/lib/capricorn/recipes/macports.rb +54 -0
  85. data/lib/capricorn/system_context.rb +49 -0
  86. data/lib/capricorn/version.rb +5 -0
  87. metadata +233 -74
  88. data/app_generators/engine/engine_generator.rb +0 -40
  89. data/app_generators/engine/templates/Gmfile +0 -20
  90. data/app_generators/engine/templates/MIT-LICENSE.txt +0 -20
  91. data/app_generators/engine/templates/README.rdoc +0 -7
  92. data/app_generators/engine/templates/config/initializers/rails_init.rb +0 -1
  93. data/app_generators/engine/templates/config/routes.rb +0 -2
  94. data/app_generators/engine/templates/gitignore +0 -9
  95. data/app_generators/engine/templates/init.rb +0 -1
  96. data/app_generators/engine/templates/lib/engine.rb +0 -4
  97. data/app_generators/engine/templates/rails/init.rb +0 -1
  98. data/app_generators/engine/templates/tasks/engine_tasks.rake +0 -4
  99. data/bin/capricorn +0 -20
  100. data/lib/capricorn/actor.rb +0 -23
  101. data/lib/capricorn/actor/actions.rb +0 -76
  102. data/lib/capricorn/actors/apache_actor.rb +0 -56
  103. data/lib/capricorn/actors/base_actor.rb +0 -335
  104. data/lib/capricorn/actors/host_file_actor.rb +0 -77
  105. data/lib/capricorn/actors/mysql_actor.rb +0 -20
  106. data/lib/capricorn/actors/passenger_actor.rb +0 -28
  107. data/lib/capricorn/actors/plesk_actor.rb +0 -228
  108. data/lib/capricorn/actors/sqlite3_actor.rb +0 -44
  109. data/lib/capricorn/app_runner.rb +0 -108
  110. data/lib/capricorn/apps/dev.rb +0 -15
  111. data/lib/capricorn/apps/engines.rb +0 -33
  112. data/lib/capricorn/apps/jobs.rb +0 -35
  113. data/lib/capricorn/apps/satellite.rb +0 -68
  114. data/lib/capricorn/apps/server.rb +0 -73
  115. data/lib/capricorn/client.rb +0 -48
  116. data/lib/capricorn/client/auth_token.rb +0 -98
  117. data/lib/capricorn/daemon.rb +0 -81
  118. data/lib/capricorn/exception_handler.rb +0 -79
  119. data/lib/capricorn/extentions/rubygems_plugin.rb +0 -27
  120. data/lib/capricorn/extentions/thor_extentions.rb +0 -32
  121. data/lib/capricorn/job_queue.rb +0 -203
  122. data/lib/capricorn/satellite.rb +0 -52
  123. data/lib/capricorn/satellite/actions.rb +0 -55
  124. data/lib/capricorn/satellite/dependency_loader.rb +0 -82
  125. data/lib/capricorn/satellite/persistence.rb +0 -50
  126. data/lib/capricorn/server.rb +0 -144
  127. data/lib/capricorn/server/daemon.rb +0 -83
  128. data/lib/capricorn/server/proxy.rb +0 -25
  129. data/lib/capricorn/server/security.rb +0 -120
  130. data/lib/capricorn/system.rb +0 -218
  131. data/lib/capricorn/system/config.rb +0 -49
  132. data/lib/capricorn/system/helper.rb +0 -21
  133. data/lib/capricorn/system/options.rb +0 -79
  134. data/lib/capricorn/system/process_user.rb +0 -73
  135. data/lib/capricorn/system/satellites.rb +0 -44
  136. data/lib/capricorn/system/shell.rb +0 -80
  137. data/lib/rubygems_plugin.rb +0 -1
  138. data/spec/actor/actions_spec.rb +0 -13
  139. data/spec/spec_helper.rb +0 -1
@@ -0,0 +1,200 @@
1
+ %%
2
+ %% Supervisor module
3
+ %%
4
+ %% File : cap_sup.erl
5
+ %% Created: 2010-01-04
6
+ %%
7
+ %% @author simonmenke <simon.menke@gmail.com>
8
+ %% @copyright 2010 simonmenke
9
+ %%
10
+ %% @doc TODO make nice description
11
+ %%
12
+
13
+ -module(cap_sup).
14
+ -author('simonmenke <simon.menke@gmail.com>').
15
+ -include("capricorn.hrl").
16
+ -behaviour(supervisor).
17
+
18
+ %% operation & maintenance api
19
+ % -export([start_link/0]).
20
+ -export([start_link/1,stop/0,
21
+ start_primary_services/1,start_secondary_services/1,
22
+ restart_core_server/0]).
23
+
24
+ %% supervisor callback
25
+ -export([init/1]).
26
+
27
+
28
+ -define(SERVER, ?MODULE).
29
+
30
+ %%
31
+ %% Operation & Maintenance API
32
+ %%
33
+
34
+
35
+ start_link(NodeType) ->
36
+ case whereis(cap_sup) of
37
+ undefined ->
38
+ start_server(NodeType);
39
+ _Else ->
40
+ {error, already_started}
41
+ end.
42
+
43
+ restart_core_server() ->
44
+ NodeType = cap_config:get(node_type),
45
+ restart_core_server(NodeType).
46
+ restart_core_server(cluster) ->
47
+ supervisor:terminate_child(cap_primary_services, cap_cluster),
48
+ supervisor:restart_child(cap_primary_services, cap_cluster),
49
+ ok;
50
+ restart_core_server(machine) ->
51
+ supervisor:terminate_child(cap_primary_services, cap_machine),
52
+ supervisor:restart_child(cap_primary_services, cap_machine),
53
+ ok.
54
+
55
+
56
+
57
+ start_server(NodeType) ->
58
+ LogLevel = cap_config:get(log, level, info),
59
+
60
+ % announce startup
61
+ io:format("Capricorn (LogLevel=~s, Node=~s, Type=~s) is starting.~n", [
62
+ LogLevel,
63
+ atom_to_list(node()),
64
+ atom_to_list(NodeType)
65
+ ]),
66
+
67
+ BaseChildSpecs =
68
+ {{one_for_all, 10, 3600},[
69
+ {cap_primary_services,
70
+ {cap_sup, start_primary_services, [NodeType]},
71
+ permanent,
72
+ infinity,
73
+ supervisor,
74
+ [cap_sup]},
75
+ {cap_secondary_services,
76
+ {cap_sup, start_secondary_services, [NodeType]},
77
+ permanent,
78
+ infinity,
79
+ supervisor,
80
+ [cap_sup]}
81
+ ]},
82
+
83
+ {ok, Pid} = supervisor:start_link({local, cap_sup}, cap_sup, BaseChildSpecs),
84
+
85
+ io:format("Capricorn has started. Time to relax.~n"),
86
+
87
+ {ok, Pid}.
88
+
89
+ start_primary_services(cluster) ->
90
+ ExternalApi = cap_config:get(cluster, api),
91
+
92
+ supervisor:start_link({local, cap_primary_services}, cap_sup,
93
+ {{one_for_one, 10, 3600},[
94
+ {cap_log,
95
+ {cap_log, start_link, []},
96
+ permanent,
97
+ brutal_kill,
98
+ worker,
99
+ [cap_log]},
100
+ {cap_cluster,
101
+ {cap_cluster, start_link, []},
102
+ permanent,
103
+ 1000,
104
+ worker,
105
+ [cap_cluster]},
106
+ {cap_cluster_gems,
107
+ {cap_cluster_gems, start_link, []},
108
+ permanent,
109
+ 1000,
110
+ worker,
111
+ [cap_cluster_gems]},
112
+ {cap_events,
113
+ {cap_events, start_link, []},
114
+ permanent,
115
+ brutal_kill,
116
+ worker,
117
+ [cap_events]},
118
+ {cap_external_api,
119
+ {cap_external_api, start_link, [ExternalApi]},
120
+ permanent,
121
+ 1000,
122
+ worker,
123
+ [cap_external_api]}
124
+ ]});
125
+ start_primary_services(machine) ->
126
+ InternalApi = cap_config:get(machine, api),
127
+
128
+ supervisor:start_link({local, cap_primary_services}, cap_sup,
129
+ {{one_for_one, 10, 3600},[
130
+ {cap_log,
131
+ {cap_log, start_link, []},
132
+ permanent,
133
+ brutal_kill,
134
+ worker,
135
+ [cap_log]},
136
+ {cap_machine,
137
+ {cap_machine, start_link, []},
138
+ permanent,
139
+ 1000,
140
+ worker,
141
+ [cap_machine]},
142
+ {cap_machine_apps,
143
+ {cap_machine_apps, start_link, []},
144
+ permanent,
145
+ 1000,
146
+ worker,
147
+ [cap_machine_apps]},
148
+ {cap_internal_api,
149
+ {cap_internal_api, start_link, [InternalApi]},
150
+ permanent,
151
+ 1000,
152
+ worker,
153
+ [cap_internal_api]},
154
+ {cap_events,
155
+ {cap_events, start_link, []},
156
+ permanent,
157
+ brutal_kill,
158
+ worker,
159
+ [cap_events]},
160
+ {cap_machine_apps_sup,
161
+ {cap_machine_apps_sup, start_link, []},
162
+ permanent,
163
+ infinity,
164
+ supervisor,
165
+ [cap_machine_apps_sup]}
166
+ ]}).
167
+
168
+ start_secondary_services(NodeType) ->
169
+ DaemonChildSpecs = [
170
+ begin
171
+ {Name,
172
+ {Module, Fun, Args},
173
+ permanent,
174
+ brutal_kill,
175
+ worker,
176
+ [Module]}
177
+ end
178
+ || {Name, {Module, Fun, Args}}
179
+ <- cap_config:get(NodeType, daemons, [])],
180
+
181
+ EventHandlerSpecs = [
182
+ begin
183
+ {Name,
184
+ {cap_event_sup, start_link, [cap_events, Module, Args]},
185
+ permanent,
186
+ brutal_kill,
187
+ worker,
188
+ [Module]}
189
+ end
190
+ || {Name, {Module, Args}}
191
+ <- cap_config:get(NodeType, event_handlers, [])],
192
+
193
+ supervisor:start_link({local, cap_secondary_services}, cap_sup,
194
+ {{one_for_one, 10, 3600}, DaemonChildSpecs++EventHandlerSpecs}).
195
+
196
+ stop() ->
197
+ catch exit(whereis(cap_sup), normal).
198
+
199
+ init(ChildSpecs) ->
200
+ {ok, ChildSpecs}.
@@ -0,0 +1,278 @@
1
+ % Licensed under the Apache License, Version 2.0 (the "License"); you may not
2
+ % use this file except in compliance with the License. You may obtain a copy of
3
+ % the License at
4
+ %
5
+ % http://www.apache.org/licenses/LICENSE-2.0
6
+ %
7
+ % Unless required by applicable law or agreed to in writing, software
8
+ % distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9
+ % WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10
+ % License for the specific language governing permissions and limitations under
11
+ % the License.
12
+
13
+ -module(cap_util).
14
+
15
+ -export([implode/2]).
16
+ -export([abs_pathname/1,abs_pathname/2, trim/1, ascii_lower/1]).
17
+ -export([encodeBase64/1, decodeBase64/1, encodeBase64Url/1, decodeBase64Url/1,
18
+ to_hex/1,parse_term/1, dict_find/3]).
19
+ -export([file_read_size/1]).
20
+ -export([to_binary/1, to_integer/1, to_list/1]).
21
+
22
+ -include("capricorn.hrl").
23
+ -include_lib("kernel/include/file.hrl").
24
+
25
+ to_hex([]) ->
26
+ [];
27
+ to_hex(Bin) when is_binary(Bin) ->
28
+ to_hex(binary_to_list(Bin));
29
+ to_hex([H|T]) ->
30
+ [to_digit(H div 16), to_digit(H rem 16) | to_hex(T)].
31
+
32
+ to_digit(N) when N < 10 -> $0 + N;
33
+ to_digit(N) -> $a + N-10.
34
+
35
+
36
+ parse_term(Bin) when is_binary(Bin) ->
37
+ parse_term(binary_to_list(Bin));
38
+ parse_term(List) ->
39
+ {ok, Tokens, _} = erl_scan:string(List ++ "."),
40
+ erl_parse:parse_term(Tokens).
41
+
42
+ % given a pathname "../foo/bar/" it gives back the fully qualified
43
+ % absolute pathname.
44
+ abs_pathname(" " ++ Filename) ->
45
+ % strip leading whitspace
46
+ abs_pathname(Filename);
47
+ abs_pathname([$/ |_]=Filename) ->
48
+ Filename;
49
+ abs_pathname(Filename) ->
50
+ {ok, Cwd} = file:get_cwd(),
51
+ {Filename2, Args} = separate_cmd_args(Filename, ""),
52
+ abs_pathname(Filename2, Cwd) ++ Args.
53
+
54
+ abs_pathname(Filename, Dir) ->
55
+ Name = filename:absname(Filename, Dir ++ "/"),
56
+ OutFilename = filename:join(fix_path_list(filename:split(Name), [])),
57
+ % If the filename is a dir (last char slash, put back end slash
58
+ case string:right(Filename,1) of
59
+ "/" ->
60
+ OutFilename ++ "/";
61
+ "\\" ->
62
+ OutFilename ++ "/";
63
+ _Else->
64
+ OutFilename
65
+ end.
66
+
67
+ % if this as an executable with arguments, seperate out the arguments
68
+ % ""./foo\ bar.sh -baz=blah" -> {"./foo\ bar.sh", " -baz=blah"}
69
+ separate_cmd_args("", CmdAcc) ->
70
+ {lists:reverse(CmdAcc), ""};
71
+ separate_cmd_args("\\ " ++ Rest, CmdAcc) -> % handle skipped value
72
+ separate_cmd_args(Rest, " \\" ++ CmdAcc);
73
+ separate_cmd_args(" " ++ Rest, CmdAcc) ->
74
+ {lists:reverse(CmdAcc), " " ++ Rest};
75
+ separate_cmd_args([Char|Rest], CmdAcc) ->
76
+ separate_cmd_args(Rest, [Char | CmdAcc]).
77
+
78
+ % lowercases string bytes that are the ascii characters A-Z.
79
+ % All other characters/bytes are ignored.
80
+ ascii_lower(String) ->
81
+ ascii_lower(String, []).
82
+
83
+ ascii_lower([], Acc) ->
84
+ lists:reverse(Acc);
85
+ ascii_lower([Char | RestString], Acc) when Char >= $A, Char =< $B ->
86
+ ascii_lower(RestString, [Char + ($a-$A) | Acc]);
87
+ ascii_lower([Char | RestString], Acc) ->
88
+ ascii_lower(RestString, [Char | Acc]).
89
+
90
+ % Is a character whitespace?
91
+ is_whitespace($\s) -> true;
92
+ is_whitespace($\t) -> true;
93
+ is_whitespace($\n) -> true;
94
+ is_whitespace($\r) -> true;
95
+ is_whitespace(_Else) -> false.
96
+
97
+
98
+ % removes leading and trailing whitespace from a string
99
+ trim(String) ->
100
+ String2 = lists:dropwhile(fun is_whitespace/1, String),
101
+ lists:reverse(lists:dropwhile(fun is_whitespace/1, lists:reverse(String2))).
102
+
103
+ % takes a heirarchical list of dirs and removes the dots ".", double dots
104
+ % ".." and the corresponding parent dirs.
105
+ fix_path_list([], Acc) ->
106
+ lists:reverse(Acc);
107
+ fix_path_list([".."|Rest], [_PrevAcc|RestAcc]) ->
108
+ fix_path_list(Rest, RestAcc);
109
+ fix_path_list(["."|Rest], Acc) ->
110
+ fix_path_list(Rest, Acc);
111
+ fix_path_list([Dir | Rest], Acc) ->
112
+ fix_path_list(Rest, [Dir | Acc]).
113
+
114
+
115
+ implode(List, Sep) ->
116
+ implode(List, Sep, []).
117
+
118
+ implode([], _Sep, Acc) ->
119
+ lists:flatten(lists:reverse(Acc));
120
+ implode([H], Sep, Acc) ->
121
+ implode([], Sep, [H|Acc]);
122
+ implode([H|T], Sep, Acc) ->
123
+ implode(T, Sep, [Sep,H|Acc]).
124
+
125
+
126
+ %%% Purpose : Base 64 encoding and decoding.
127
+ %%% Copied from ssl_base_64 to avoid using the
128
+ %%% erlang ssl library
129
+
130
+ -define(st(X,A), ((X-A+256) div 256)).
131
+
132
+ %% A PEM encoding consists of characters A-Z, a-z, 0-9, +, / and
133
+ %% =. Each character encodes a 6 bits value from 0 to 63 (A = 0, / =
134
+ %% 63); = is a padding character.
135
+ %%
136
+
137
+ %%
138
+ %% encode64(Bytes|Binary) -> binary
139
+ %%
140
+ %% Take 3 bytes a time (3 x 8 = 24 bits), and make 4 characters out of
141
+ %% them (4 x 6 = 24 bits).
142
+ %%
143
+ encodeBase64(Bs) when is_list(Bs) ->
144
+ encodeBase64(iolist_to_binary(Bs), <<>>);
145
+ encodeBase64(Bs) ->
146
+ encodeBase64(Bs, <<>>).
147
+
148
+ encodeBase64(<<B:3/binary, Bs/binary>>, Acc) ->
149
+ <<C1:6, C2:6, C3:6, C4:6>> = B,
150
+ encodeBase64(Bs, <<Acc/binary, (enc(C1)), (enc(C2)), (enc(C3)), (enc(C4))>>);
151
+ encodeBase64(<<B:2/binary>>, Acc) ->
152
+ <<C1:6, C2:6, C3:6, _:6>> = <<B/binary, 0>>,
153
+ <<Acc/binary, (enc(C1)), (enc(C2)), (enc(C3)), $=>>;
154
+ encodeBase64(<<B:1/binary>>, Acc) ->
155
+ <<C1:6, C2:6, _:12>> = <<B/binary, 0, 0>>,
156
+ <<Acc/binary, (enc(C1)), (enc(C2)), $=, $=>>;
157
+ encodeBase64(<<>>, Acc) ->
158
+ Acc.
159
+
160
+ encodeBase64Url(Bs) when is_list(Bs) ->
161
+ encodeBase64Url(list_to_binary(Bs), <<>>);
162
+ encodeBase64Url(Bs) ->
163
+ encodeBase64Url(Bs, <<>>).
164
+
165
+ encodeBase64Url(<<B:3/binary, Bs/binary>>, Acc) ->
166
+ <<C1:6, C2:6, C3:6, C4:6>> = B,
167
+ encodeBase64Url(Bs, <<Acc/binary, (encUrl(C1)), (encUrl(C2)), (encUrl(C3)), (encUrl(C4))>>);
168
+ encodeBase64Url(<<B:2/binary>>, Acc) ->
169
+ <<C1:6, C2:6, C3:6, _:6>> = <<B/binary, 0>>,
170
+ <<Acc/binary, (encUrl(C1)), (encUrl(C2)), (encUrl(C3))>>;
171
+ encodeBase64Url(<<B:1/binary>>, Acc) ->
172
+ <<C1:6, C2:6, _:12>> = <<B/binary, 0, 0>>,
173
+ <<Acc/binary, (encUrl(C1)), (encUrl(C2))>>;
174
+ encodeBase64Url(<<>>, Acc) ->
175
+ Acc.
176
+
177
+ %%
178
+ %% decodeBase64(BinaryChars) -> Binary
179
+ %%
180
+ decodeBase64(Cs) when is_list(Cs) ->
181
+ decodeBase64(list_to_binary(Cs));
182
+ decodeBase64(Cs) ->
183
+ decode1(Cs, <<>>).
184
+
185
+ decode1(<<C1, C2, $=, $=>>, Acc) ->
186
+ <<B1, _:16>> = <<(dec(C1)):6, (dec(C2)):6, 0:12>>,
187
+ <<Acc/binary, B1>>;
188
+ decode1(<<C1, C2, C3, $=>>, Acc) ->
189
+ <<B1, B2, _:8>> = <<(dec(C1)):6, (dec(C2)):6, (dec(C3)):6, (dec(0)):6>>,
190
+ <<Acc/binary, B1, B2>>;
191
+ decode1(<<C1, C2, C3, C4, Cs/binary>>, Acc) ->
192
+ Bin = <<Acc/binary, (dec(C1)):6, (dec(C2)):6, (dec(C3)):6, (dec(C4)):6>>,
193
+ decode1(Cs, Bin);
194
+ decode1(<<>>, Acc) ->
195
+ Acc.
196
+
197
+ decodeBase64Url(Cs) when is_list(Cs) ->
198
+ decodeBase64Url(list_to_binary(Cs));
199
+ decodeBase64Url(Cs) ->
200
+ decode1Url(Cs, <<>>).
201
+
202
+ decode1Url(<<C1, C2>>, Acc) ->
203
+ <<B1, _:16>> = <<(decUrl(C1)):6, (decUrl(C2)):6, 0:12>>,
204
+ <<Acc/binary, B1>>;
205
+ decode1Url(<<C1, C2, C3>>, Acc) ->
206
+ <<B1, B2, _:8>> = <<(decUrl(C1)):6, (decUrl(C2)):6, (decUrl(C3)):6, (decUrl(0)):6>>,
207
+ <<Acc/binary, B1, B2>>;
208
+ decode1Url(<<C1, C2, C3, C4, Cs/binary>>, Acc) ->
209
+ Bin = <<Acc/binary, (decUrl(C1)):6, (decUrl(C2)):6, (decUrl(C3)):6, (decUrl(C4)):6>>,
210
+ decode1Url(Cs, Bin);
211
+ decode1Url(<<>>, Acc) ->
212
+ Acc.
213
+
214
+ %% enc/1 and dec/1
215
+ %%
216
+ %% Mapping: 0-25 -> A-Z, 26-51 -> a-z, 52-61 -> 0-9, 62 -> +, 63 -> /
217
+ %%
218
+ enc(C) ->
219
+ 65 + C + 6*?st(C,26) - 75*?st(C,52) -15*?st(C,62) + 3*?st(C,63).
220
+
221
+ dec(C) ->
222
+ 62*?st(C,43) + ?st(C,47) + (C-59)*?st(C,48) - 69*?st(C,65) - 6*?st(C,97).
223
+
224
+ %% encUrl/1 and decUrl/1
225
+ %%
226
+ %% Mapping: 0-25 -> A-Z, 26-51 -> a-z, 52-61 -> 0-9, 62 -> -, 63 -> _
227
+ %%
228
+ encUrl(C) ->
229
+ 65 + C + 6*?st(C,26) - 75*?st(C,52) -13*?st(C,62) + 49*?st(C,63).
230
+
231
+ decUrl(C) ->
232
+ 62*?st(C,45) + (C-58)*?st(C,48) - 69*?st(C,65) + 33*?st(C,95) - 39*?st(C,97).
233
+
234
+ dict_find(Key, Dict, DefaultValue) ->
235
+ case dict:find(Key, Dict) of
236
+ {ok, Value} ->
237
+ Value;
238
+ error ->
239
+ DefaultValue
240
+ end.
241
+
242
+
243
+ file_read_size(FileName) ->
244
+ case file:read_file_info(FileName) of
245
+ {ok, FileInfo} ->
246
+ FileInfo#file_info.size;
247
+ Error -> Error
248
+ end.
249
+
250
+ to_binary(V) when is_binary(V) ->
251
+ V;
252
+ to_binary(V) when is_list(V) ->
253
+ try
254
+ list_to_binary(V)
255
+ catch
256
+ _ ->
257
+ list_to_binary(io_lib:format("~p", [V]))
258
+ end;
259
+ to_binary(V) when is_atom(V) ->
260
+ list_to_binary(atom_to_list(V));
261
+ to_binary(V) ->
262
+ list_to_binary(io_lib:format("~p", [V])).
263
+
264
+ to_integer(V) when is_integer(V) ->
265
+ V;
266
+ to_integer(V) when is_list(V) ->
267
+ erlang:list_to_integer(V);
268
+ to_integer(V) when is_binary(V) ->
269
+ erlang:list_to_integer(binary_to_list(V)).
270
+
271
+ to_list(V) when is_list(V) ->
272
+ V;
273
+ to_list(V) when is_binary(V) ->
274
+ binary_to_list(V);
275
+ to_list(V) when is_atom(V) ->
276
+ atom_to_list(V);
277
+ to_list(V) ->
278
+ lists:flatten(io_lib:format("~p", [V])).