m06_task3.js 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (204) hide show
  1. package/.idea/.name +1 -0
  2. package/.idea/inspectionProfiles/Project_Default.xml +10 -0
  3. package/.idea/jsLibraryMappings.xml +6 -0
  4. package/.idea/modules.xml +8 -0
  5. package/.idea/node_lab_6.iml +12 -0
  6. package/06_task2.html +73 -0
  7. package/06_task2.js +52 -0
  8. package/06_task3.js +3 -0
  9. package/06_task4.js +3 -0
  10. package/m06_task3.js +28 -0
  11. package/package/index.js +28 -0
  12. package/package/node_modules/.package-lock.json +31 -0
  13. package/package/node_modules/@types/node/LICENSE +21 -0
  14. package/package/node_modules/@types/node/README.md +16 -0
  15. package/package/node_modules/@types/node/assert/strict.d.ts +8 -0
  16. package/package/node_modules/@types/node/assert.d.ts +961 -0
  17. package/package/node_modules/@types/node/async_hooks.d.ts +501 -0
  18. package/package/node_modules/@types/node/buffer.d.ts +2258 -0
  19. package/package/node_modules/@types/node/child_process.d.ts +1369 -0
  20. package/package/node_modules/@types/node/cluster.d.ts +410 -0
  21. package/package/node_modules/@types/node/console.d.ts +412 -0
  22. package/package/node_modules/@types/node/constants.d.ts +18 -0
  23. package/package/node_modules/@types/node/crypto.d.ts +3964 -0
  24. package/package/node_modules/@types/node/dgram.d.ts +545 -0
  25. package/package/node_modules/@types/node/diagnostics_channel.d.ts +153 -0
  26. package/package/node_modules/@types/node/dns/promises.d.ts +370 -0
  27. package/package/node_modules/@types/node/dns.d.ts +659 -0
  28. package/package/node_modules/@types/node/dom-events.d.ts +126 -0
  29. package/package/node_modules/@types/node/domain.d.ts +170 -0
  30. package/package/node_modules/@types/node/events.d.ts +678 -0
  31. package/package/node_modules/@types/node/fs/promises.d.ts +1138 -0
  32. package/package/node_modules/@types/node/fs.d.ts +3872 -0
  33. package/package/node_modules/@types/node/globals.d.ts +300 -0
  34. package/package/node_modules/@types/node/globals.global.d.ts +1 -0
  35. package/package/node_modules/@types/node/http.d.ts +1614 -0
  36. package/package/node_modules/@types/node/http2.d.ts +2134 -0
  37. package/package/node_modules/@types/node/https.d.ts +541 -0
  38. package/package/node_modules/@types/node/index.d.ts +133 -0
  39. package/package/node_modules/@types/node/inspector.d.ts +2741 -0
  40. package/package/node_modules/@types/node/module.d.ts +114 -0
  41. package/package/node_modules/@types/node/net.d.ts +869 -0
  42. package/package/node_modules/@types/node/os.d.ts +466 -0
  43. package/package/node_modules/@types/node/package.json +232 -0
  44. package/package/node_modules/@types/node/path.d.ts +191 -0
  45. package/package/node_modules/@types/node/perf_hooks.d.ts +625 -0
  46. package/package/node_modules/@types/node/process.d.ts +1482 -0
  47. package/package/node_modules/@types/node/punycode.d.ts +117 -0
  48. package/package/node_modules/@types/node/querystring.d.ts +131 -0
  49. package/package/node_modules/@types/node/readline/promises.d.ts +143 -0
  50. package/package/node_modules/@types/node/readline.d.ts +653 -0
  51. package/package/node_modules/@types/node/repl.d.ts +424 -0
  52. package/package/node_modules/@types/node/stream/consumers.d.ts +12 -0
  53. package/package/node_modules/@types/node/stream/promises.d.ts +42 -0
  54. package/package/node_modules/@types/node/stream/web.d.ts +330 -0
  55. package/package/node_modules/@types/node/stream.d.ts +1340 -0
  56. package/package/node_modules/@types/node/string_decoder.d.ts +67 -0
  57. package/package/node_modules/@types/node/test.d.ts +314 -0
  58. package/package/node_modules/@types/node/timers/promises.d.ts +68 -0
  59. package/package/node_modules/@types/node/timers.d.ts +94 -0
  60. package/package/node_modules/@types/node/tls.d.ts +1028 -0
  61. package/package/node_modules/@types/node/trace_events.d.ts +171 -0
  62. package/package/node_modules/@types/node/ts4.8/assert/strict.d.ts +8 -0
  63. package/package/node_modules/@types/node/ts4.8/assert.d.ts +961 -0
  64. package/package/node_modules/@types/node/ts4.8/async_hooks.d.ts +501 -0
  65. package/package/node_modules/@types/node/ts4.8/buffer.d.ts +2259 -0
  66. package/package/node_modules/@types/node/ts4.8/child_process.d.ts +1369 -0
  67. package/package/node_modules/@types/node/ts4.8/cluster.d.ts +410 -0
  68. package/package/node_modules/@types/node/ts4.8/console.d.ts +412 -0
  69. package/package/node_modules/@types/node/ts4.8/constants.d.ts +18 -0
  70. package/package/node_modules/@types/node/ts4.8/crypto.d.ts +3964 -0
  71. package/package/node_modules/@types/node/ts4.8/dgram.d.ts +545 -0
  72. package/package/node_modules/@types/node/ts4.8/diagnostics_channel.d.ts +153 -0
  73. package/package/node_modules/@types/node/ts4.8/dns/promises.d.ts +370 -0
  74. package/package/node_modules/@types/node/ts4.8/dns.d.ts +659 -0
  75. package/package/node_modules/@types/node/ts4.8/dom-events.d.ts +126 -0
  76. package/package/node_modules/@types/node/ts4.8/domain.d.ts +170 -0
  77. package/package/node_modules/@types/node/ts4.8/events.d.ts +678 -0
  78. package/package/node_modules/@types/node/ts4.8/fs/promises.d.ts +1138 -0
  79. package/package/node_modules/@types/node/ts4.8/fs.d.ts +3872 -0
  80. package/package/node_modules/@types/node/ts4.8/globals.d.ts +294 -0
  81. package/package/node_modules/@types/node/ts4.8/globals.global.d.ts +1 -0
  82. package/package/node_modules/@types/node/ts4.8/http.d.ts +1614 -0
  83. package/package/node_modules/@types/node/ts4.8/http2.d.ts +2134 -0
  84. package/package/node_modules/@types/node/ts4.8/https.d.ts +541 -0
  85. package/package/node_modules/@types/node/ts4.8/index.d.ts +88 -0
  86. package/package/node_modules/@types/node/ts4.8/inspector.d.ts +2741 -0
  87. package/package/node_modules/@types/node/ts4.8/module.d.ts +114 -0
  88. package/package/node_modules/@types/node/ts4.8/net.d.ts +869 -0
  89. package/package/node_modules/@types/node/ts4.8/os.d.ts +466 -0
  90. package/package/node_modules/@types/node/ts4.8/path.d.ts +191 -0
  91. package/package/node_modules/@types/node/ts4.8/perf_hooks.d.ts +625 -0
  92. package/package/node_modules/@types/node/ts4.8/process.d.ts +1482 -0
  93. package/package/node_modules/@types/node/ts4.8/punycode.d.ts +117 -0
  94. package/package/node_modules/@types/node/ts4.8/querystring.d.ts +131 -0
  95. package/package/node_modules/@types/node/ts4.8/readline/promises.d.ts +143 -0
  96. package/package/node_modules/@types/node/ts4.8/readline.d.ts +653 -0
  97. package/package/node_modules/@types/node/ts4.8/repl.d.ts +424 -0
  98. package/package/node_modules/@types/node/ts4.8/stream/consumers.d.ts +12 -0
  99. package/package/node_modules/@types/node/ts4.8/stream/promises.d.ts +42 -0
  100. package/package/node_modules/@types/node/ts4.8/stream/web.d.ts +330 -0
  101. package/package/node_modules/@types/node/ts4.8/stream.d.ts +1340 -0
  102. package/package/node_modules/@types/node/ts4.8/string_decoder.d.ts +67 -0
  103. package/package/node_modules/@types/node/ts4.8/test.d.ts +314 -0
  104. package/package/node_modules/@types/node/ts4.8/timers/promises.d.ts +68 -0
  105. package/package/node_modules/@types/node/ts4.8/timers.d.ts +94 -0
  106. package/package/node_modules/@types/node/ts4.8/tls.d.ts +1028 -0
  107. package/package/node_modules/@types/node/ts4.8/trace_events.d.ts +171 -0
  108. package/package/node_modules/@types/node/ts4.8/tty.d.ts +206 -0
  109. package/package/node_modules/@types/node/ts4.8/url.d.ts +897 -0
  110. package/package/node_modules/@types/node/ts4.8/util.d.ts +1850 -0
  111. package/package/node_modules/@types/node/ts4.8/v8.d.ts +396 -0
  112. package/package/node_modules/@types/node/ts4.8/vm.d.ts +509 -0
  113. package/package/node_modules/@types/node/ts4.8/wasi.d.ts +158 -0
  114. package/package/node_modules/@types/node/ts4.8/worker_threads.d.ts +689 -0
  115. package/package/node_modules/@types/node/ts4.8/zlib.d.ts +517 -0
  116. package/package/node_modules/@types/node/tty.d.ts +206 -0
  117. package/package/node_modules/@types/node/url.d.ts +897 -0
  118. package/package/node_modules/@types/node/util.d.ts +1850 -0
  119. package/package/node_modules/@types/node/v8.d.ts +396 -0
  120. package/package/node_modules/@types/node/vm.d.ts +509 -0
  121. package/package/node_modules/@types/node/wasi.d.ts +158 -0
  122. package/package/node_modules/@types/node/worker_threads.d.ts +689 -0
  123. package/package/node_modules/@types/node/zlib.d.ts +517 -0
  124. package/package/node_modules/@types/nodemailer/LICENSE +21 -0
  125. package/package/node_modules/@types/nodemailer/README.md +16 -0
  126. package/package/node_modules/@types/nodemailer/index.d.ts +83 -0
  127. package/package/node_modules/@types/nodemailer/lib/addressparser/index.d.ts +31 -0
  128. package/package/node_modules/@types/nodemailer/lib/base64/index.d.ts +22 -0
  129. package/package/node_modules/@types/nodemailer/lib/dkim/index.d.ts +45 -0
  130. package/package/node_modules/@types/nodemailer/lib/dkim/message-parser.d.ts +75 -0
  131. package/package/node_modules/@types/nodemailer/lib/dkim/relaxed-body.d.ts +75 -0
  132. package/package/node_modules/@types/nodemailer/lib/dkim/sign.d.ts +11 -0
  133. package/package/node_modules/@types/nodemailer/lib/fetch/cookies.d.ts +54 -0
  134. package/package/node_modules/@types/nodemailer/lib/fetch/index.d.ts +38 -0
  135. package/package/node_modules/@types/nodemailer/lib/json-transport/index.d.ts +50 -0
  136. package/package/node_modules/@types/nodemailer/lib/mail-composer/index.d.ts +25 -0
  137. package/package/node_modules/@types/nodemailer/lib/mailer/index.d.ts +230 -0
  138. package/package/node_modules/@types/nodemailer/lib/mailer/mail-message.d.ts +28 -0
  139. package/package/node_modules/@types/nodemailer/lib/mime-funcs/index.d.ts +87 -0
  140. package/package/node_modules/@types/nodemailer/lib/mime-funcs/mime-types.d.ts +2 -0
  141. package/package/node_modules/@types/nodemailer/lib/mime-node/index.d.ts +137 -0
  142. package/package/node_modules/@types/nodemailer/lib/mime-node/last-newline.d.ts +9 -0
  143. package/package/node_modules/@types/nodemailer/lib/qp/index.d.ts +23 -0
  144. package/package/node_modules/@types/nodemailer/lib/sendmail-transport/index.d.ts +53 -0
  145. package/package/node_modules/@types/nodemailer/lib/sendmail-transport/le-unix.d.ts +7 -0
  146. package/package/node_modules/@types/nodemailer/lib/sendmail-transport/le-windows.d.ts +7 -0
  147. package/package/node_modules/@types/nodemailer/lib/ses-transport/index.d.ts +136 -0
  148. package/package/node_modules/@types/nodemailer/lib/shared/index.d.ts +51 -0
  149. package/package/node_modules/@types/nodemailer/lib/smtp-connection/data-stream.d.ts +11 -0
  150. package/package/node_modules/@types/nodemailer/lib/smtp-connection/http-proxy-client.d.ts +11 -0
  151. package/package/node_modules/@types/nodemailer/lib/smtp-connection/index.d.ts +254 -0
  152. package/package/node_modules/@types/nodemailer/lib/smtp-pool/index.d.ts +90 -0
  153. package/package/node_modules/@types/nodemailer/lib/smtp-pool/pool-resource.d.ts +66 -0
  154. package/package/node_modules/@types/nodemailer/lib/smtp-transport/index.d.ts +115 -0
  155. package/package/node_modules/@types/nodemailer/lib/stream-transport/index.d.ts +56 -0
  156. package/package/node_modules/@types/nodemailer/lib/well-known/index.d.ts +6 -0
  157. package/package/node_modules/@types/nodemailer/lib/xoauth2/index.d.ts +110 -0
  158. package/package/node_modules/@types/nodemailer/package.json +37 -0
  159. package/package/node_modules/nodemailer/.gitattributes +6 -0
  160. package/package/node_modules/nodemailer/.prettierrc.js +8 -0
  161. package/package/node_modules/nodemailer/CHANGELOG.md +715 -0
  162. package/package/node_modules/nodemailer/CODE_OF_CONDUCT.md +76 -0
  163. package/package/node_modules/nodemailer/CONTRIBUTING.md +67 -0
  164. package/package/node_modules/nodemailer/LICENSE +16 -0
  165. package/package/node_modules/nodemailer/README.md +93 -0
  166. package/package/node_modules/nodemailer/SECURITY.txt +22 -0
  167. package/package/node_modules/nodemailer/lib/addressparser/index.js +313 -0
  168. package/package/node_modules/nodemailer/lib/base64/index.js +142 -0
  169. package/package/node_modules/nodemailer/lib/dkim/index.js +251 -0
  170. package/package/node_modules/nodemailer/lib/dkim/message-parser.js +155 -0
  171. package/package/node_modules/nodemailer/lib/dkim/relaxed-body.js +154 -0
  172. package/package/node_modules/nodemailer/lib/dkim/sign.js +117 -0
  173. package/package/node_modules/nodemailer/lib/fetch/cookies.js +281 -0
  174. package/package/node_modules/nodemailer/lib/fetch/index.js +269 -0
  175. package/package/node_modules/nodemailer/lib/json-transport/index.js +82 -0
  176. package/package/node_modules/nodemailer/lib/mail-composer/index.js +558 -0
  177. package/package/node_modules/nodemailer/lib/mailer/index.js +427 -0
  178. package/package/node_modules/nodemailer/lib/mailer/mail-message.js +315 -0
  179. package/package/node_modules/nodemailer/lib/mime-funcs/index.js +619 -0
  180. package/package/node_modules/nodemailer/lib/mime-funcs/mime-types.js +2102 -0
  181. package/package/node_modules/nodemailer/lib/mime-node/index.js +1290 -0
  182. package/package/node_modules/nodemailer/lib/mime-node/last-newline.js +33 -0
  183. package/package/node_modules/nodemailer/lib/mime-node/le-unix.js +43 -0
  184. package/package/node_modules/nodemailer/lib/mime-node/le-windows.js +52 -0
  185. package/package/node_modules/nodemailer/lib/nodemailer.js +143 -0
  186. package/package/node_modules/nodemailer/lib/qp/index.js +219 -0
  187. package/package/node_modules/nodemailer/lib/sendmail-transport/index.js +210 -0
  188. package/package/node_modules/nodemailer/lib/ses-transport/index.js +349 -0
  189. package/package/node_modules/nodemailer/lib/shared/index.js +639 -0
  190. package/package/node_modules/nodemailer/lib/smtp-connection/data-stream.js +108 -0
  191. package/package/node_modules/nodemailer/lib/smtp-connection/http-proxy-client.js +143 -0
  192. package/package/node_modules/nodemailer/lib/smtp-connection/index.js +1786 -0
  193. package/package/node_modules/nodemailer/lib/smtp-pool/index.js +648 -0
  194. package/package/node_modules/nodemailer/lib/smtp-pool/pool-resource.js +253 -0
  195. package/package/node_modules/nodemailer/lib/smtp-transport/index.js +416 -0
  196. package/package/node_modules/nodemailer/lib/stream-transport/index.js +135 -0
  197. package/package/node_modules/nodemailer/lib/well-known/index.js +47 -0
  198. package/package/node_modules/nodemailer/lib/well-known/services.json +286 -0
  199. package/package/node_modules/nodemailer/lib/xoauth2/index.js +376 -0
  200. package/package/node_modules/nodemailer/package.json +46 -0
  201. package/package/node_modules/nodemailer/postinstall.js +101 -0
  202. package/package/package-lock.json +60 -0
  203. package/package/package.json +6 -0
  204. package/package.json +19 -0
@@ -0,0 +1,639 @@
1
+ /* eslint no-console: 0 */
2
+
3
+ 'use strict';
4
+
5
+ const urllib = require('url');
6
+ const util = require('util');
7
+ const fs = require('fs');
8
+ const nmfetch = require('../fetch');
9
+ const dns = require('dns');
10
+ const net = require('net');
11
+ const os = require('os');
12
+
13
+ const DNS_TTL = 5 * 60 * 1000;
14
+
15
+ let networkInterfaces;
16
+ try {
17
+ networkInterfaces = os.networkInterfaces();
18
+ } catch (err) {
19
+ // fails on some systems
20
+ }
21
+
22
+ module.exports.networkInterfaces = networkInterfaces;
23
+
24
+ const isFamilySupported = (family, allowInternal) => {
25
+ let networkInterfaces = module.exports.networkInterfaces;
26
+ if (!networkInterfaces) {
27
+ // hope for the best
28
+ return true;
29
+ }
30
+
31
+ const familySupported =
32
+ // crux that replaces Object.values(networkInterfaces) as Object.values is not supported in nodejs v6
33
+ Object.keys(networkInterfaces)
34
+ .map(key => networkInterfaces[key])
35
+ // crux that replaces .flat() as it is not supported in older Node versions (v10 and older)
36
+ .reduce((acc, val) => acc.concat(val), [])
37
+ .filter(i => !i.internal || allowInternal)
38
+ .filter(i => i.family === 'IPv' + family || i.family === family).length > 0;
39
+
40
+ return familySupported;
41
+ };
42
+
43
+ const resolver = (family, hostname, options, callback) => {
44
+ options = options || {};
45
+ const familySupported = isFamilySupported(family, options.allowInternalNetworkInterfaces);
46
+
47
+ if (!familySupported) {
48
+ return callback(null, []);
49
+ }
50
+
51
+ const resolver = dns.Resolver ? new dns.Resolver(options) : dns;
52
+ resolver['resolve' + family](hostname, (err, addresses) => {
53
+ if (err) {
54
+ switch (err.code) {
55
+ case dns.NODATA:
56
+ case dns.NOTFOUND:
57
+ case dns.NOTIMP:
58
+ case dns.SERVFAIL:
59
+ case dns.CONNREFUSED:
60
+ case dns.REFUSED:
61
+ case 'EAI_AGAIN':
62
+ return callback(null, []);
63
+ }
64
+ return callback(err);
65
+ }
66
+ return callback(null, Array.isArray(addresses) ? addresses : [].concat(addresses || []));
67
+ });
68
+ };
69
+
70
+ const dnsCache = (module.exports.dnsCache = new Map());
71
+
72
+ const formatDNSValue = (value, extra) => {
73
+ if (!value) {
74
+ return Object.assign({}, extra || {});
75
+ }
76
+
77
+ return Object.assign(
78
+ {
79
+ servername: value.servername,
80
+ host:
81
+ !value.addresses || !value.addresses.length
82
+ ? null
83
+ : value.addresses.length === 1
84
+ ? value.addresses[0]
85
+ : value.addresses[Math.floor(Math.random() * value.addresses.length)]
86
+ },
87
+ extra || {}
88
+ );
89
+ };
90
+
91
+ module.exports.resolveHostname = (options, callback) => {
92
+ options = options || {};
93
+
94
+ if (!options.host && options.servername) {
95
+ options.host = options.servername;
96
+ }
97
+
98
+ if (!options.host || net.isIP(options.host)) {
99
+ // nothing to do here
100
+ let value = {
101
+ addresses: [options.host],
102
+ servername: options.servername || false
103
+ };
104
+ return callback(
105
+ null,
106
+ formatDNSValue(value, {
107
+ cached: false
108
+ })
109
+ );
110
+ }
111
+
112
+ let cached;
113
+ if (dnsCache.has(options.host)) {
114
+ cached = dnsCache.get(options.host);
115
+
116
+ if (!cached.expires || cached.expires >= Date.now()) {
117
+ return callback(
118
+ null,
119
+ formatDNSValue(cached.value, {
120
+ cached: true
121
+ })
122
+ );
123
+ }
124
+ }
125
+
126
+ resolver(4, options.host, options, (err, addresses) => {
127
+ if (err) {
128
+ if (cached) {
129
+ // ignore error, use expired value
130
+ return callback(
131
+ null,
132
+ formatDNSValue(cached.value, {
133
+ cached: true,
134
+ error: err
135
+ })
136
+ );
137
+ }
138
+ return callback(err);
139
+ }
140
+
141
+ if (addresses && addresses.length) {
142
+ let value = {
143
+ addresses,
144
+ servername: options.servername || options.host
145
+ };
146
+
147
+ dnsCache.set(options.host, {
148
+ value,
149
+ expires: Date.now() + (options.dnsTtl || DNS_TTL)
150
+ });
151
+
152
+ return callback(
153
+ null,
154
+ formatDNSValue(value, {
155
+ cached: false
156
+ })
157
+ );
158
+ }
159
+
160
+ resolver(6, options.host, options, (err, addresses) => {
161
+ if (err) {
162
+ if (cached) {
163
+ // ignore error, use expired value
164
+ return callback(
165
+ null,
166
+ formatDNSValue(cached.value, {
167
+ cached: true,
168
+ error: err
169
+ })
170
+ );
171
+ }
172
+ return callback(err);
173
+ }
174
+
175
+ if (addresses && addresses.length) {
176
+ let value = {
177
+ addresses,
178
+ servername: options.servername || options.host
179
+ };
180
+
181
+ dnsCache.set(options.host, {
182
+ value,
183
+ expires: Date.now() + (options.dnsTtl || DNS_TTL)
184
+ });
185
+
186
+ return callback(
187
+ null,
188
+ formatDNSValue(value, {
189
+ cached: false
190
+ })
191
+ );
192
+ }
193
+
194
+ try {
195
+ dns.lookup(options.host, { all: true }, (err, addresses) => {
196
+ if (err) {
197
+ if (cached) {
198
+ // ignore error, use expired value
199
+ return callback(
200
+ null,
201
+ formatDNSValue(cached.value, {
202
+ cached: true,
203
+ error: err
204
+ })
205
+ );
206
+ }
207
+ return callback(err);
208
+ }
209
+
210
+ let address = addresses
211
+ ? addresses
212
+ .filter(addr => isFamilySupported(addr.family))
213
+ .map(addr => addr.address)
214
+ .shift()
215
+ : false;
216
+
217
+ if (addresses && addresses.length && !address) {
218
+ // there are addresses but none can be used
219
+ let err = new Error(`Can not use IPv${addresses[0].family} addresses with current network`);
220
+ return callback(err);
221
+ }
222
+
223
+ if (!address && cached) {
224
+ // nothing was found, fallback to cached value
225
+ return callback(
226
+ null,
227
+ formatDNSValue(cached.value, {
228
+ cached: true
229
+ })
230
+ );
231
+ }
232
+
233
+ let value = {
234
+ addresses: address ? [address] : [options.host],
235
+ servername: options.servername || options.host
236
+ };
237
+
238
+ dnsCache.set(options.host, {
239
+ value,
240
+ expires: Date.now() + (options.dnsTtl || DNS_TTL)
241
+ });
242
+
243
+ return callback(
244
+ null,
245
+ formatDNSValue(value, {
246
+ cached: false
247
+ })
248
+ );
249
+ });
250
+ } catch (err) {
251
+ if (cached) {
252
+ // ignore error, use expired value
253
+ return callback(
254
+ null,
255
+ formatDNSValue(cached.value, {
256
+ cached: true,
257
+ error: err
258
+ })
259
+ );
260
+ }
261
+ return callback(err);
262
+ }
263
+ });
264
+ });
265
+ };
266
+ /**
267
+ * Parses connection url to a structured configuration object
268
+ *
269
+ * @param {String} str Connection url
270
+ * @return {Object} Configuration object
271
+ */
272
+ module.exports.parseConnectionUrl = str => {
273
+ str = str || '';
274
+ let options = {};
275
+
276
+ [urllib.parse(str, true)].forEach(url => {
277
+ let auth;
278
+
279
+ switch (url.protocol) {
280
+ case 'smtp:':
281
+ options.secure = false;
282
+ break;
283
+ case 'smtps:':
284
+ options.secure = true;
285
+ break;
286
+ case 'direct:':
287
+ options.direct = true;
288
+ break;
289
+ }
290
+
291
+ if (!isNaN(url.port) && Number(url.port)) {
292
+ options.port = Number(url.port);
293
+ }
294
+
295
+ if (url.hostname) {
296
+ options.host = url.hostname;
297
+ }
298
+
299
+ if (url.auth) {
300
+ auth = url.auth.split(':');
301
+
302
+ if (!options.auth) {
303
+ options.auth = {};
304
+ }
305
+
306
+ options.auth.user = auth.shift();
307
+ options.auth.pass = auth.join(':');
308
+ }
309
+
310
+ Object.keys(url.query || {}).forEach(key => {
311
+ let obj = options;
312
+ let lKey = key;
313
+ let value = url.query[key];
314
+
315
+ if (!isNaN(value)) {
316
+ value = Number(value);
317
+ }
318
+
319
+ switch (value) {
320
+ case 'true':
321
+ value = true;
322
+ break;
323
+ case 'false':
324
+ value = false;
325
+ break;
326
+ }
327
+
328
+ // tls is nested object
329
+ if (key.indexOf('tls.') === 0) {
330
+ lKey = key.substr(4);
331
+ if (!options.tls) {
332
+ options.tls = {};
333
+ }
334
+ obj = options.tls;
335
+ } else if (key.indexOf('.') >= 0) {
336
+ // ignore nested properties besides tls
337
+ return;
338
+ }
339
+
340
+ if (!(lKey in obj)) {
341
+ obj[lKey] = value;
342
+ }
343
+ });
344
+ });
345
+
346
+ return options;
347
+ };
348
+
349
+ module.exports._logFunc = (logger, level, defaults, data, message, ...args) => {
350
+ let entry = {};
351
+
352
+ Object.keys(defaults || {}).forEach(key => {
353
+ if (key !== 'level') {
354
+ entry[key] = defaults[key];
355
+ }
356
+ });
357
+
358
+ Object.keys(data || {}).forEach(key => {
359
+ if (key !== 'level') {
360
+ entry[key] = data[key];
361
+ }
362
+ });
363
+
364
+ logger[level](entry, message, ...args);
365
+ };
366
+
367
+ /**
368
+ * Returns a bunyan-compatible logger interface. Uses either provided logger or
369
+ * creates a default console logger
370
+ *
371
+ * @param {Object} [options] Options object that might include 'logger' value
372
+ * @return {Object} bunyan compatible logger
373
+ */
374
+ module.exports.getLogger = (options, defaults) => {
375
+ options = options || {};
376
+
377
+ let response = {};
378
+ let levels = ['trace', 'debug', 'info', 'warn', 'error', 'fatal'];
379
+
380
+ if (!options.logger) {
381
+ // use vanity logger
382
+ levels.forEach(level => {
383
+ response[level] = () => false;
384
+ });
385
+ return response;
386
+ }
387
+
388
+ let logger = options.logger;
389
+
390
+ if (options.logger === true) {
391
+ // create console logger
392
+ logger = createDefaultLogger(levels);
393
+ }
394
+
395
+ levels.forEach(level => {
396
+ response[level] = (data, message, ...args) => {
397
+ module.exports._logFunc(logger, level, defaults, data, message, ...args);
398
+ };
399
+ });
400
+
401
+ return response;
402
+ };
403
+
404
+ /**
405
+ * Wrapper for creating a callback that either resolves or rejects a promise
406
+ * based on input
407
+ *
408
+ * @param {Function} resolve Function to run if callback is called
409
+ * @param {Function} reject Function to run if callback ends with an error
410
+ */
411
+ module.exports.callbackPromise = (resolve, reject) =>
412
+ function () {
413
+ let args = Array.from(arguments);
414
+ let err = args.shift();
415
+ if (err) {
416
+ reject(err);
417
+ } else {
418
+ resolve(...args);
419
+ }
420
+ };
421
+
422
+ /**
423
+ * Resolves a String or a Buffer value for content value. Useful if the value
424
+ * is a Stream or a file or an URL. If the value is a Stream, overwrites
425
+ * the stream object with the resolved value (you can't stream a value twice).
426
+ *
427
+ * This is useful when you want to create a plugin that needs a content value,
428
+ * for example the `html` or `text` value as a String or a Buffer but not as
429
+ * a file path or an URL.
430
+ *
431
+ * @param {Object} data An object or an Array you want to resolve an element for
432
+ * @param {String|Number} key Property name or an Array index
433
+ * @param {Function} callback Callback function with (err, value)
434
+ */
435
+ module.exports.resolveContent = (data, key, callback) => {
436
+ let promise;
437
+
438
+ if (!callback) {
439
+ promise = new Promise((resolve, reject) => {
440
+ callback = module.exports.callbackPromise(resolve, reject);
441
+ });
442
+ }
443
+
444
+ let content = (data && data[key] && data[key].content) || data[key];
445
+ let contentStream;
446
+ let encoding = ((typeof data[key] === 'object' && data[key].encoding) || 'utf8')
447
+ .toString()
448
+ .toLowerCase()
449
+ .replace(/[-_\s]/g, '');
450
+
451
+ if (!content) {
452
+ return callback(null, content);
453
+ }
454
+
455
+ if (typeof content === 'object') {
456
+ if (typeof content.pipe === 'function') {
457
+ return resolveStream(content, (err, value) => {
458
+ if (err) {
459
+ return callback(err);
460
+ }
461
+ // we can't stream twice the same content, so we need
462
+ // to replace the stream object with the streaming result
463
+ if (data[key].content) {
464
+ data[key].content = value;
465
+ } else {
466
+ data[key] = value;
467
+ }
468
+ callback(null, value);
469
+ });
470
+ } else if (/^https?:\/\//i.test(content.path || content.href)) {
471
+ contentStream = nmfetch(content.path || content.href);
472
+ return resolveStream(contentStream, callback);
473
+ } else if (/^data:/i.test(content.path || content.href)) {
474
+ let parts = (content.path || content.href).match(/^data:((?:[^;]*;)*(?:[^,]*)),(.*)$/i);
475
+ if (!parts) {
476
+ return callback(null, Buffer.from(0));
477
+ }
478
+ return callback(null, /\bbase64$/i.test(parts[1]) ? Buffer.from(parts[2], 'base64') : Buffer.from(decodeURIComponent(parts[2])));
479
+ } else if (content.path) {
480
+ return resolveStream(fs.createReadStream(content.path), callback);
481
+ }
482
+ }
483
+
484
+ if (typeof data[key].content === 'string' && !['utf8', 'usascii', 'ascii'].includes(encoding)) {
485
+ content = Buffer.from(data[key].content, encoding);
486
+ }
487
+
488
+ // default action, return as is
489
+ setImmediate(() => callback(null, content));
490
+
491
+ return promise;
492
+ };
493
+
494
+ /**
495
+ * Copies properties from source objects to target objects
496
+ */
497
+ module.exports.assign = function (/* target, ... sources */) {
498
+ let args = Array.from(arguments);
499
+ let target = args.shift() || {};
500
+
501
+ args.forEach(source => {
502
+ Object.keys(source || {}).forEach(key => {
503
+ if (['tls', 'auth'].includes(key) && source[key] && typeof source[key] === 'object') {
504
+ // tls and auth are special keys that need to be enumerated separately
505
+ // other objects are passed as is
506
+ if (!target[key]) {
507
+ // ensure that target has this key
508
+ target[key] = {};
509
+ }
510
+ Object.keys(source[key]).forEach(subKey => {
511
+ target[key][subKey] = source[key][subKey];
512
+ });
513
+ } else {
514
+ target[key] = source[key];
515
+ }
516
+ });
517
+ });
518
+ return target;
519
+ };
520
+
521
+ module.exports.encodeXText = str => {
522
+ // ! 0x21
523
+ // + 0x2B
524
+ // = 0x3D
525
+ // ~ 0x7E
526
+ if (!/[^\x21-\x2A\x2C-\x3C\x3E-\x7E]/.test(str)) {
527
+ return str;
528
+ }
529
+ let buf = Buffer.from(str);
530
+ let result = '';
531
+ for (let i = 0, len = buf.length; i < len; i++) {
532
+ let c = buf[i];
533
+ if (c < 0x21 || c > 0x7e || c === 0x2b || c === 0x3d) {
534
+ result += '+' + (c < 0x10 ? '0' : '') + c.toString(16).toUpperCase();
535
+ } else {
536
+ result += String.fromCharCode(c);
537
+ }
538
+ }
539
+ return result;
540
+ };
541
+
542
+ /**
543
+ * Streams a stream value into a Buffer
544
+ *
545
+ * @param {Object} stream Readable stream
546
+ * @param {Function} callback Callback function with (err, value)
547
+ */
548
+ function resolveStream(stream, callback) {
549
+ let responded = false;
550
+ let chunks = [];
551
+ let chunklen = 0;
552
+
553
+ stream.on('error', err => {
554
+ if (responded) {
555
+ return;
556
+ }
557
+
558
+ responded = true;
559
+ callback(err);
560
+ });
561
+
562
+ stream.on('readable', () => {
563
+ let chunk;
564
+ while ((chunk = stream.read()) !== null) {
565
+ chunks.push(chunk);
566
+ chunklen += chunk.length;
567
+ }
568
+ });
569
+
570
+ stream.on('end', () => {
571
+ if (responded) {
572
+ return;
573
+ }
574
+ responded = true;
575
+
576
+ let value;
577
+
578
+ try {
579
+ value = Buffer.concat(chunks, chunklen);
580
+ } catch (E) {
581
+ return callback(E);
582
+ }
583
+ callback(null, value);
584
+ });
585
+ }
586
+
587
+ /**
588
+ * Generates a bunyan-like logger that prints to console
589
+ *
590
+ * @returns {Object} Bunyan logger instance
591
+ */
592
+ function createDefaultLogger(levels) {
593
+ let levelMaxLen = 0;
594
+ let levelNames = new Map();
595
+ levels.forEach(level => {
596
+ if (level.length > levelMaxLen) {
597
+ levelMaxLen = level.length;
598
+ }
599
+ });
600
+
601
+ levels.forEach(level => {
602
+ let levelName = level.toUpperCase();
603
+ if (levelName.length < levelMaxLen) {
604
+ levelName += ' '.repeat(levelMaxLen - levelName.length);
605
+ }
606
+ levelNames.set(level, levelName);
607
+ });
608
+
609
+ let print = (level, entry, message, ...args) => {
610
+ let prefix = '';
611
+ if (entry) {
612
+ if (entry.tnx === 'server') {
613
+ prefix = 'S: ';
614
+ } else if (entry.tnx === 'client') {
615
+ prefix = 'C: ';
616
+ }
617
+
618
+ if (entry.sid) {
619
+ prefix = '[' + entry.sid + '] ' + prefix;
620
+ }
621
+
622
+ if (entry.cid) {
623
+ prefix = '[#' + entry.cid + '] ' + prefix;
624
+ }
625
+ }
626
+
627
+ message = util.format(message, ...args);
628
+ message.split(/\r?\n/).forEach(line => {
629
+ console.log('[%s] %s %s', new Date().toISOString().substr(0, 19).replace(/T/, ' '), levelNames.get(level), prefix + line);
630
+ });
631
+ };
632
+
633
+ let logger = {};
634
+ levels.forEach(level => {
635
+ logger[level] = print.bind(null, level);
636
+ });
637
+
638
+ return logger;
639
+ }