Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8e52075636 | ||
|
|
7200f079bf | ||
|
|
d155db81de | ||
|
|
25e3bbf039 | ||
|
|
eecf3d854b | ||
|
|
7c2499fc06 | ||
|
|
1aa605c620 | ||
|
|
66287ad6c1 | ||
|
|
9a19485454 | ||
|
|
7d67d578fd | ||
|
|
960d3c7880 | ||
|
|
9eabf3fa81 | ||
|
|
89beadd2ce | ||
|
|
6ecb6c1500 | ||
|
|
51bc5f70c5 | ||
|
|
be62ac9c14 | ||
|
|
161c34384d | ||
|
|
89784ab90a | ||
|
|
d83e547fa9 | ||
|
|
30d86928d5 | ||
|
|
12c32d09fb | ||
|
|
ae6fd6aa35 | ||
|
|
72d3a49352 | ||
|
|
87b62390b7 | ||
|
|
6c93446a1f | ||
|
|
83c106a857 | ||
|
|
facb2846fd | ||
|
|
596c70d3dc | ||
|
|
7beff0201d | ||
|
|
a4c9d1ecb7 | ||
|
|
b7a79a556a | ||
|
|
03ab9e4e0d | ||
|
|
7e855f5c8f | ||
|
|
9e510d5831 | ||
|
|
1689a0d56b | ||
|
|
9ff774e7df | ||
|
|
c78ad0b574 | ||
|
|
117aeaa15d | ||
|
|
e135743efa | ||
|
|
2c1324dc0a | ||
|
|
c7e09bd7b4 | ||
|
|
86824795a0 | ||
|
|
1b0636c2d2 | ||
|
|
2f9d2bbdf6 | ||
|
|
21a1b2c15c | ||
|
|
bdef3d6afd | ||
|
|
a882aab30e | ||
|
|
788b577d65 | ||
|
|
71a22adc06 | ||
|
|
7d1ef2ffe8 | ||
|
|
55f5f74658 | ||
|
|
e1fd82bc46 | ||
|
|
49b8480bfb | ||
|
|
b2ab484883 | ||
|
|
4c3b97be7d | ||
|
|
60e1b64455 | ||
|
|
6bcd02bb1c | ||
|
|
66f302a613 | ||
|
|
1716af6c72 | ||
|
|
749326c83a | ||
|
|
9657577c00 | ||
|
|
9f5216d259 | ||
|
|
c8826e8f9c | ||
|
|
25bc13ef1e | ||
|
|
4d123a15f9 | ||
|
|
2cf1b09767 | ||
|
|
abfd81cb9d | ||
|
|
3895678bee | ||
|
|
e0a1feafe0 | ||
|
|
c75eb24eb8 | ||
|
|
c3aae185df | ||
|
|
2e87783246 | ||
|
|
fbab767b9f | ||
|
|
7bc38b5eaa | ||
|
|
b93456f512 | ||
|
|
ddb700eee5 | ||
|
|
1052ee0766 | ||
|
|
29534218d7 | ||
|
|
d7abd53062 | ||
|
|
aede72fa37 | ||
|
|
b0a5165b44 | ||
|
|
4919f792f2 | ||
|
|
d5927f5d50 | ||
|
|
e68330e045 | ||
|
|
b5d5b3763f | ||
|
|
b6a6687c1e | ||
|
|
3843b670a5 | ||
|
|
249efdd378 | ||
|
|
18ce1669fc | ||
|
|
e8d3b8030e | ||
|
|
a752abf318 | ||
|
|
d3ebcaf5d2 | ||
|
|
0abb8322d9 | ||
|
|
99ed58ec4d | ||
|
|
04450ec659 | ||
|
|
82a378e519 | ||
|
|
29d31ba919 | ||
|
|
4519ea568d | ||
|
|
9f88f31f01 | ||
|
|
4bdea2b467 | ||
|
|
2252a74cd7 | ||
|
|
d1fa7b88e0 | ||
|
|
9ecf42578c | ||
|
|
754fc25924 | ||
|
|
d9551c75b1 | ||
|
|
8d45cf6972 | ||
|
|
f176e1ae59 | ||
|
|
fa8f62fb5d | ||
|
|
0c142f20d7 | ||
|
|
b641fc6b79 | ||
|
|
1252a61479 | ||
|
|
5f631c0b96 | ||
|
|
348c579521 | ||
|
|
7ce9cdf0b9 | ||
|
|
09beadb98a | ||
|
|
5b265a76bd | ||
|
|
c5a4a1c6f2 | ||
|
|
88ada54045 | ||
|
|
c5b1c08d05 | ||
|
|
a0765ade6b | ||
|
|
54250f5fbf | ||
|
|
f3f397f31e | ||
|
|
d806ed5d5f | ||
|
|
37e9a2ee95 | ||
|
|
7ad6a08002 | ||
|
|
90686ee5c9 | ||
|
|
85c5577955 | ||
|
|
30d4a1ad0f | ||
|
|
1b551741b8 | ||
|
|
369f44adfa | ||
|
|
763f4551d5 | ||
|
|
42d7865e14 | ||
|
|
cf62702f08 | ||
|
|
14ccd78782 | ||
|
|
6c4b5efd98 | ||
|
|
05a43c563c | ||
|
|
94d2e86b60 | ||
|
|
d1b8f9e01f | ||
|
|
228acefa36 | ||
|
|
d1d8a77bf6 | ||
|
|
7ea3293aba | ||
|
|
082a498afd | ||
|
|
866c987409 | ||
|
|
1d0e65d17a | ||
|
|
136a37ef73 | ||
|
|
0ce49b5c71 | ||
|
|
490ad3834b | ||
|
|
bcc62c96c8 | ||
|
|
15d6cb3065 | ||
|
|
a490660b38 | ||
|
|
72019b7427 | ||
|
|
21c0024a2f | ||
|
|
d7a02d13e4 | ||
|
|
cb220837b9 | ||
|
|
ddaae51d42 | ||
|
|
629e55f97d | ||
|
|
909ebad276 | ||
|
|
cb7743fa39 | ||
|
|
6197842bca | ||
|
|
77d461dcbf | ||
|
|
47b6060910 | ||
|
|
47d3fe5af6 | ||
|
|
6691a2fdad | ||
|
|
746f56f42a | ||
|
|
87de05881c | ||
|
|
f2fba1d200 | ||
|
|
34d4fb8cf0 | ||
|
|
be64f81eee | ||
|
|
9fe1c93c9b | ||
|
|
a4b6d58b24 | ||
|
|
86f391c701 | ||
|
|
36de38bd11 | ||
|
|
a308872c88 | ||
|
|
a369160296 | ||
|
|
0a09b46c94 | ||
|
|
b0a1cd7b0d | ||
|
|
73a2b92278 | ||
|
|
c3bb5bd89e | ||
|
|
d22ff2fce7 | ||
|
|
fee2980d95 | ||
|
|
d6693ed360 | ||
|
|
4880069775 | ||
|
|
5d217a1262 | ||
|
|
f778d22eac | ||
|
|
3aa76dcaec | ||
|
|
4680573a6b | ||
|
|
95fcb261eb | ||
|
|
5867c67da2 | ||
|
|
80d74e9e34 | ||
|
|
43a0b500f5 | ||
|
|
3d53ed17fb | ||
|
|
4ea452307e | ||
|
|
e61f20f1ed | ||
|
|
ca11f5ab49 | ||
|
|
000d24d31a | ||
|
|
ef92f2e9c5 | ||
|
|
4e89eac8dd | ||
|
|
b015e33ea5 | ||
|
|
96e762d4a1 | ||
|
|
359060a151 | ||
|
|
af1aff7fbb | ||
|
|
517ef216c1 | ||
|
|
734c13cdf5 | ||
|
|
1bf3ad2426 | ||
|
|
884b9a4813 | ||
|
|
7153690016 | ||
|
|
f00b3a2b3a | ||
|
|
c2b5e4f3b8 | ||
|
|
bc15e9ce9a | ||
|
|
70dc6d8dc9 | ||
|
|
10b11b03a8 | ||
|
|
cb602f178c | ||
|
|
464113c5ae | ||
|
|
c34f6c54e7 | ||
|
|
8fb58ebbca | ||
|
|
dce60c6dbb | ||
|
|
f668d08804 | ||
|
|
c41a22195c | ||
|
|
900c05213b | ||
|
|
c5850e4b05 | ||
|
|
ff4649fe42 | ||
|
|
1a38e91042 | ||
|
|
b6196371bb | ||
|
|
d5beb7ba3f | ||
|
|
19acf23c49 | ||
|
|
5cd3291fec | ||
|
|
b3e0f780c3 | ||
|
|
2bdbfc27f6 | ||
|
|
3fc61a3edc | ||
|
|
12339bbf4c | ||
|
|
1fb9f922b0 | ||
|
|
b93bc02ab0 | ||
|
|
747e393a54 | ||
|
|
4e8660a21f | ||
|
|
3fe77fa9a6 | ||
|
|
b4fbaf7c13 | ||
|
|
9884241df8 | ||
|
|
63d7a4fa45 | ||
|
|
8f4b6c41a2 | ||
|
|
4493d65ec9 | ||
|
|
e5910da300 | ||
|
|
c277a1d878 | ||
|
|
7820ad3a59 | ||
|
|
23533b83a4 | ||
|
|
ab650ec5c9 | ||
|
|
8f36597048 | ||
|
|
d0213ee90a | ||
|
|
1e9fabe1ca | ||
|
|
148d3f0562 | ||
|
|
c3057df3f5 | ||
|
|
0b2e474d52 | ||
|
|
95a36b1759 | ||
|
|
86ffa3a3ea | ||
|
|
69e2b2985d | ||
|
|
c431904b56 | ||
|
|
c2a10601b9 | ||
|
|
e9a8e5468d | ||
|
|
22e602debb | ||
|
|
455cec67a5 | ||
|
|
e2dfac946d | ||
|
|
c198d2e5f1 | ||
|
|
9a70abef24 | ||
|
|
53e1c469a2 | ||
|
|
139c2061a8 | ||
|
|
15b361fbac | ||
|
|
3130e59244 | ||
|
|
93286836f9 | ||
|
|
91b57aa9a8 | ||
|
|
220231e647 | ||
|
|
c438bb0bc5 | ||
|
|
95afa323c0 | ||
|
|
bc56353a79 | ||
|
|
1ffccdb7b2 | ||
|
|
e79fe4b8f0 | ||
|
|
aaf1fc3a4a | ||
|
|
8b42353039 | ||
|
|
05c687e251 | ||
|
|
492b8f6950 | ||
|
|
8ccee82059 | ||
|
|
b99a94a652 | ||
|
|
41e5d7e471 | ||
|
|
1adea37c45 | ||
|
|
98f6c8aa4f | ||
|
|
341ae53e85 | ||
|
|
291fc024cd | ||
|
|
f63d833a33 | ||
|
|
ab035901f8 | ||
|
|
20f54059ad | ||
|
|
563c31303e | ||
|
|
421e099f2b | ||
|
|
955d4a3129 | ||
|
|
b84981ad03 | ||
|
|
777b8e94e2 | ||
|
|
6df642623a | ||
|
|
0a3e186f11 | ||
|
|
c2d83a9db0 | ||
|
|
f33d3a4e02 | ||
|
|
86b8a56b05 | ||
|
|
ac6ec15aed | ||
|
|
31632c6361 | ||
|
|
98c99279c3 | ||
|
|
cdb8d7b692 | ||
|
|
93ac3e19f0 | ||
|
|
6a51af9efe | ||
|
|
9d73b3470b | ||
|
|
1c8449cea6 | ||
|
|
3bbbd41196 | ||
|
|
339bbee0df | ||
|
|
9ba6eb716d | ||
|
|
d949c19c7e | ||
|
|
1299d6118f | ||
|
|
244ff92e78 | ||
|
|
53f34dea04 | ||
|
|
1f5c3fac31 | ||
|
|
7014258c8d | ||
|
|
1614e7ba8d | ||
|
|
43b5a4e735 | ||
|
|
43191db63e | ||
|
|
e89be2e944 | ||
|
|
c2fbff6d0e | ||
|
|
b8eca17c55 | ||
|
|
4650e491df | ||
|
|
3e33e57707 | ||
|
|
c80f4c5313 | ||
|
|
132ecbec2f | ||
|
|
0a90cab44a | ||
|
|
d16dbc197f | ||
|
|
127f27e375 | ||
|
|
6523cc4da0 | ||
|
|
2516da1c89 | ||
|
|
0ae2b82b60 | ||
|
|
dab526936f | ||
|
|
780077d118 | ||
|
|
ad8f1d88d4 | ||
|
|
a3c4a48ef7 | ||
|
|
84a11fe3b1 | ||
|
|
2a3cfc9858 | ||
|
|
b9b20c6494 | ||
|
|
a8a7d2cf7e | ||
|
|
50ecc30b4d | ||
|
|
cd89db5c2f | ||
|
|
1ed99999bd | ||
|
|
4afebdcb2b | ||
|
|
c3d9d17e34 | ||
|
|
7bf5144e62 | ||
|
|
3eb4eb8074 | ||
|
|
ab000c684a | ||
|
|
aba60dadec | ||
|
|
f29457e967 | ||
|
|
8742fac5d8 | ||
|
|
0ab1c7ef76 | ||
|
|
47abc641f1 | ||
|
|
7519b2ef3a | ||
|
|
ce8657f12f | ||
|
|
8e366916d5 | ||
|
|
33f53ab000 | ||
|
|
bd15ad4301 | ||
|
|
e5b3b8ad32 | ||
|
|
e116c48bef | ||
|
|
7d7bb3b388 | ||
|
|
0b4bf13335 | ||
|
|
228984a3fc | ||
|
|
f084ad8008 | ||
|
|
255da78bed | ||
|
|
5d5badfcee | ||
|
|
4cf9f99ae9 | ||
|
|
673f25f75a | ||
|
|
961fb96bb7 | ||
|
|
d6475fcd19 | ||
|
|
ac538f755f | ||
|
|
5b2eb4f0e1 | ||
|
|
10c274c774 | ||
|
|
eb3b81297d | ||
|
|
80f4133bbf | ||
|
|
d10fb9451c | ||
|
|
88ae2ecadb | ||
|
|
85d19dad47 | ||
|
|
c5cc414181 | ||
|
|
17703fe3e8 | ||
|
|
04aeeba2fa | ||
|
|
4e11d5cdbf | ||
|
|
be63c0dc89 | ||
|
|
987bc1d580 | ||
|
|
ddd35c0cba | ||
|
|
c97b615785 | ||
|
|
9ab6d084df | ||
|
|
cf8d0a25aa | ||
|
|
0a0852b576 | ||
|
|
90716417c9 | ||
|
|
101afbc9b8 | ||
|
|
a197646867 | ||
|
|
00d1d2c0e7 | ||
|
|
6e50fe4475 | ||
|
|
7942803a75 | ||
|
|
a8b74a9021 | ||
|
|
27a9a62843 | ||
|
|
9b268b6c77 | ||
|
|
3b3ac48edd | ||
|
|
598e96a0cc | ||
|
|
b5dd0e8093 | ||
|
|
9b24fdfd1d | ||
|
|
8313896a85 | ||
|
|
8193302162 | ||
|
|
6e3e5560d0 | ||
|
|
f0c6630a16 | ||
|
|
1db747da29 | ||
|
|
8065439f96 | ||
|
|
62c896a872 | ||
|
|
2db07dfc3b | ||
|
|
34eb3f1e66 | ||
|
|
9d30e892e9 | ||
|
|
0aaba7a461 | ||
|
|
3d6b568c6e | ||
|
|
2b2816cfe4 | ||
|
|
2fa18b47db | ||
|
|
c8af7cdd27 | ||
|
|
f857f6394f | ||
|
|
97d733e129 | ||
|
|
77e44c7c0e | ||
|
|
abf89d32d9 | ||
|
|
177e05deb2 | ||
|
|
eb5645241c | ||
|
|
202300952c | ||
|
|
c7bea65ae7 | ||
|
|
d5a9000d46 | ||
|
|
f62018451f | ||
|
|
0a93e301c9 | ||
|
|
6fe9cae62a | ||
|
|
38e984a008 | ||
|
|
09e4254718 | ||
|
|
d4b55c4ceb | ||
|
|
7d5479985d | ||
|
|
6517af3dea | ||
|
|
7632a5e4af | ||
|
|
7f20c41dd5 | ||
|
|
66b23b11b0 | ||
|
|
448b44094a | ||
|
|
8bbb44f90c | ||
|
|
0fba87c755 | ||
|
|
fea648496c | ||
|
|
944a6b761c | ||
|
|
f1ae183752 | ||
|
|
a0ece4e969 | ||
|
|
0bb14abbdd | ||
|
|
4c37e49274 | ||
|
|
2a2bc33a89 | ||
|
|
41558bbf64 | ||
|
|
4d0cc95ff4 | ||
|
|
cfd28a4f7a | ||
|
|
5a0b6fc35a | ||
|
|
3e59e1c465 | ||
|
|
ae611a6e55 | ||
|
|
a7a2e3deb1 | ||
|
|
cae0a1cbc0 | ||
|
|
244e5f67d3 | ||
|
|
ff078882d5 | ||
|
|
8d76733fad | ||
|
|
fb3a5a7d90 | ||
|
|
f374ac5f9a | ||
|
|
02707364f0 | ||
|
|
104106b9cf | ||
|
|
474e065a30 | ||
|
|
27094896b1 | ||
|
|
cd48bcfd7d | ||
|
|
5baeba53d7 | ||
|
|
3a3b433849 | ||
|
|
a2192ae483 | ||
|
|
023b55f2e5 | ||
|
|
e4309d472b | ||
|
|
c5452fc2ec | ||
|
|
f78ee9d42e | ||
|
|
c8416cc17d | ||
|
|
cf0a969a65 | ||
|
|
06670d3401 | ||
|
|
acfc66cd60 | ||
|
|
6f140202ad | ||
|
|
cfe77a3d58 | ||
|
|
a0527a7f0e | ||
|
|
c90cffa688 | ||
|
|
d7a633bfa3 | ||
|
|
0ea3cdd228 | ||
|
|
ddef065493 | ||
|
|
ac857d18db | ||
|
|
663e928d65 | ||
|
|
189cd8c5f6 | ||
|
|
692f436b3d | ||
|
|
2e65ce8272 | ||
|
|
a35e5bd966 | ||
|
|
83fe5a17f3 | ||
|
|
49bbfaf130 | ||
|
|
cd9c7dcbec | ||
|
|
f868fc861b | ||
|
|
84907d5bc4 | ||
|
|
1cee8a16b9 | ||
|
|
57e32b87c7 | ||
|
|
6926655513 | ||
|
|
8354319e72 | ||
|
|
f9596cc1db | ||
|
|
b2e2ad9a45 | ||
|
|
a07fb2be51 | ||
|
|
7f259f2a79 | ||
|
|
7c0493071f | ||
|
|
c60fe0c6f6 | ||
|
|
8ce34af9f3 | ||
|
|
82761bb875 | ||
|
|
08a10a8af5 | ||
|
|
bd130136bc | ||
|
|
fb04203b72 | ||
|
|
4172c190e5 | ||
|
|
920abd627b | ||
|
|
02b7399f9a | ||
|
|
b8402ed073 | ||
|
|
06c5c4d2a4 | ||
|
|
57a4ec31d1 | ||
|
|
511c9a6d4a | ||
|
|
8ec47111d5 | ||
|
|
8b67274cc0 | ||
|
|
af22fb7a06 | ||
|
|
df5fff5e72 | ||
|
|
d9243d1c0b | ||
|
|
2fb145d39d | ||
|
|
14094aaef7 | ||
|
|
ec752645ee | ||
|
|
ceb2f1da41 | ||
|
|
aab857a66e | ||
|
|
066be0fe30 | ||
|
|
380e87ddfa | ||
|
|
e9a7a2af18 | ||
|
|
a83e7d8c42 | ||
|
|
bf7dd7ac63 | ||
|
|
0fc3370859 | ||
|
|
c416012f97 | ||
|
|
d3a8862bd8 | ||
|
|
08353731ef | ||
|
|
16700244b0 | ||
|
|
49ca223e9c | ||
|
|
38efe632ae | ||
|
|
39a3bb7e44 | ||
|
|
920e8d9145 | ||
|
|
aed6d05d8c | ||
|
|
d85d95a40b | ||
|
|
b5dd54a404 | ||
|
|
f7c0a2ee15 | ||
|
|
874b5bfdbf | ||
|
|
71d09722be | ||
|
|
349d25dccf | ||
|
|
3942914945 | ||
|
|
60c16bbb5d | ||
|
|
70b5f4130e | ||
|
|
17cfecc5c3 | ||
|
|
ebdd18769b | ||
|
|
f974fddd2a | ||
|
|
b1a46da309 | ||
|
|
81879be4be | ||
|
|
0a094d4c1f | ||
|
|
66a96410d4 | ||
|
|
d4b23f08b6 | ||
|
|
d6d956b9d8 | ||
|
|
383b2a48c5 | ||
|
|
ab1c464950 | ||
|
|
f20b5191f2 | ||
|
|
fc113d64f5 | ||
|
|
6f6b12bee7 | ||
|
|
4e6c2867da | ||
|
|
54989e819a | ||
|
|
bf505bb68d | ||
|
|
4072062b72 | ||
|
|
d6ba37dc3c | ||
|
|
a58d21aa28 | ||
|
|
6e8d4129b2 | ||
|
|
2485a8f8d9 | ||
|
|
1ae908f6d5 | ||
|
|
6b923bdff1 | ||
|
|
d39969d1e6 | ||
|
|
eaef5bd133 | ||
|
|
7cc7df8c0e | ||
|
|
551f393da7 | ||
|
|
e81f8373a2 | ||
|
|
dfa83f2c85 | ||
|
|
91bdbc5193 | ||
|
|
707b9ed2d6 | ||
|
|
cd6b846e22 | ||
|
|
807e4ea6ec | ||
|
|
507e8bfac9 | ||
|
|
2ea63a0ea6 | ||
|
|
7988acbff4 | ||
|
|
b8c3740446 | ||
|
|
7bdbd80552 | ||
|
|
577ad2599c | ||
|
|
4d9f8168b8 | ||
|
|
f1d0b451b1 | ||
|
|
ac921d4657 | ||
|
|
f046434f3b | ||
|
|
58b9ee41fa | ||
|
|
d28d7a67f2 | ||
|
|
20370e65d6 | ||
|
|
67626d49c9 | ||
|
|
cd9e179fcb | ||
|
|
0ba28e6153 | ||
|
|
de791765b2 | ||
|
|
e79121acb7 | ||
|
|
4bdec5c1c1 | ||
|
|
fa39d2f2fa | ||
|
|
c55d06ed57 | ||
|
|
3829873552 | ||
|
|
54ebcc5bd8 | ||
|
|
7782500dbb | ||
|
|
86ec6bb2f8 | ||
|
|
02499d672b | ||
|
|
8c2e641ed7 | ||
|
|
29c53082eb | ||
|
|
2fa988fc7b | ||
|
|
72f1d444d3 | ||
|
|
7dcc94202d | ||
|
|
a447ae5eab | ||
|
|
54ad1e4e47 | ||
|
|
39ea91cfc2 | ||
|
|
5ebff5d15e | ||
|
|
731512a947 | ||
|
|
304dbca63d | ||
|
|
18ff0fafe0 | ||
|
|
25de791424 | ||
|
|
6e88c9cfd1 | ||
|
|
9937e88985 | ||
|
|
57f964a139 | ||
|
|
cbd5835112 | ||
|
|
fba32acb73 | ||
|
|
2fdb1f78a2 | ||
|
|
ea2069df51 | ||
|
|
7267fc757d | ||
|
|
ea7d69060d | ||
|
|
6e5e2eb694 | ||
|
|
51466df7b9 | ||
|
|
d6259332d4 | ||
|
|
260229a4d1 | ||
|
|
7776df241c | ||
|
|
e17fdcb077 | ||
|
|
d96629cdf4 | ||
|
|
0c79fcfbd0 | ||
|
|
9125830de6 | ||
|
|
55963d0c9a | ||
|
|
44f7b91826 | ||
|
|
731ea5d50d | ||
|
|
9e517fde00 | ||
|
|
1ff61837ac | ||
|
|
3a8464e4b8 | ||
|
|
39b0b8e2fd | ||
|
|
3a61186491 | ||
|
|
2180e1786c | ||
|
|
8fb5e8ef19 | ||
|
|
a8f54d1851 | ||
|
|
c9721d4d7f | ||
|
|
c848372bbe | ||
|
|
a23daa1547 | ||
|
|
9dba6c806b | ||
|
|
fc635a9340 | ||
|
|
81f738af3f | ||
|
|
f6165d23e4 | ||
|
|
e4a4b6f260 | ||
|
|
0ceee1dc05 | ||
|
|
8a6cf95fad | ||
|
|
37a7031f4e | ||
|
|
8874f3de9d | ||
|
|
3c5d48ea13 | ||
|
|
a0d98b7a39 | ||
|
|
74b75899d3 | ||
|
|
240eca0b68 | ||
|
|
cd54b18de3 | ||
|
|
65e01dbabc | ||
|
|
62276ce63e | ||
|
|
f67fe352cf | ||
|
|
4805797752 | ||
|
|
4c038508f2 | ||
|
|
15db11c0e6 | ||
|
|
97fe505bb4 | ||
|
|
fd45a6d31b | ||
|
|
e1a9ad7f82 | ||
|
|
296affc6e4 | ||
|
|
1889e12b54 | ||
|
|
5e91d919e0 | ||
|
|
5934846852 | ||
|
|
5045dfab74 | ||
|
|
499a7d6a37 | ||
|
|
f72c3fa9a7 | ||
|
|
d0c50632cd | ||
|
|
fffb54e2c6 | ||
|
|
8bf3bd48a6 | ||
|
|
dbe976ad3e | ||
|
|
9a8a6b53ae | ||
|
|
84132b7b2a | ||
|
|
e69a7a1b25 | ||
|
|
7f2bdc217a | ||
|
|
76bb35d5db | ||
|
|
0187f297d1 | ||
|
|
6ff49dc196 | ||
|
|
cd778396ff | ||
|
|
0dcb50d39c | ||
|
|
fd763846e5 | ||
|
|
f4f310cf51 | ||
|
|
0798b72470 | ||
|
|
39a17f8a72 | ||
|
|
78454da3b3 | ||
|
|
e62dc8f3b2 | ||
|
|
e99088348d | ||
|
|
6a12bd7abc | ||
|
|
b39e30fb0c | ||
|
|
92b15395a4 | ||
|
|
7411ff1fca | ||
|
|
f2e7facbc3 | ||
|
|
f1b4f0c463 | ||
|
|
c04e3f80b9 | ||
|
|
717e872fdd | ||
|
|
dbff932d8b | ||
|
|
5c9f463cab | ||
|
|
3a8f47befd | ||
|
|
a3e2a41834 | ||
|
|
b667bd709d | ||
|
|
a4c668e37a | ||
|
|
900bbe724a | ||
|
|
f5a2857620 | ||
|
|
2ef6f7248d | ||
|
|
06b430e57f | ||
|
|
f061dcf8b6 | ||
|
|
99377bdd30 | ||
|
|
c6b5343c9b | ||
|
|
7f4e2a93d0 | ||
|
|
c151f9bc59 | ||
|
|
204bf9acec | ||
|
|
e3bac87016 | ||
|
|
1f09505248 | ||
|
|
7f99013179 | ||
|
|
8d72c2a7b2 | ||
|
|
c722cfec18 | ||
|
|
835af2cae1 | ||
|
|
bd2a4097b2 | ||
|
|
fcc75c6a3f | ||
|
|
e08b234326 | ||
|
|
5bd3df7a0f | ||
|
|
5bbf24bf41 | ||
|
|
ace1dc53b2 | ||
|
|
100480a1d5 | ||
|
|
a89a2df603 | ||
|
|
988ad66a12 | ||
|
|
85d6292b8f | ||
|
|
98ab0950c9 | ||
|
|
a7f9043072 | ||
|
|
6d8b747ff2 | ||
|
|
a17eae4142 | ||
|
|
7b05d70042 | ||
|
|
f328907da4 | ||
|
|
1cea7ba487 | ||
|
|
6848452149 | ||
|
|
f9a1d47f13 | ||
|
|
492dcdca8d | ||
|
|
4ef3a778c1 | ||
|
|
31c5ef1bc3 | ||
|
|
4656e7b0dd | ||
|
|
4216cf2ac1 | ||
|
|
37e4f51668 | ||
|
|
1dae0373c8 | ||
|
|
e928f36456 | ||
|
|
fcb94a1742 | ||
|
|
8ff010ca0f | ||
|
|
241090a82b | ||
|
|
618bef0eb2 | ||
|
|
3b69f5d500 | ||
|
|
b298d46a40 | ||
|
|
75059d1bdc | ||
|
|
15e9a92798 | ||
|
|
bafc30bec6 | ||
|
|
0a8f839281 | ||
|
|
ab48174bac | ||
|
|
4439251f17 | ||
|
|
f9a6403b11 | ||
|
|
786f46c655 | ||
|
|
5ebd9fe7a5 | ||
|
|
2302ae5e88 | ||
|
|
8b12263dbc | ||
|
|
376d2666a5 | ||
|
|
d90622630f | ||
|
|
da447b1067 | ||
|
|
460d95afc5 | ||
|
|
8f522048d8 | ||
|
|
147c095105 | ||
|
|
fecb11f2fa | ||
|
|
56e50c2dbe | ||
|
|
c1b5e9b260 | ||
|
|
286fa90ee9 | ||
|
|
d63fb70c69 | ||
|
|
4d76a3be4c | ||
|
|
d9c612ef2b | ||
|
|
3b3ca1c1b3 | ||
|
|
2e748fdbf1 | ||
|
|
6c99691d1c | ||
|
|
fd067c8077 | ||
|
|
04012760d1 | ||
|
|
0ec1a141f1 | ||
|
|
7414a4fb06 | ||
|
|
abbd44e276 | ||
|
|
13e80e6bd5 | ||
|
|
ffa981d172 | ||
|
|
806f07db67 | ||
|
|
6746933a3d | ||
|
|
8cb2833fa7 | ||
|
|
1730f3c0c9 | ||
|
|
d6dda04f4f | ||
|
|
1b0825ef4b | ||
|
|
7249b2bd5f | ||
|
|
238bf1a29e | ||
|
|
4cbf81da59 | ||
|
|
d9b7ec18e7 | ||
|
|
ffed9c4d8c | ||
|
|
0dc0c5a0e0 | ||
|
|
57f826ece1 | ||
|
|
729bdebc50 | ||
|
|
2a541175b5 | ||
|
|
5f93f7162f | ||
|
|
3640554503 | ||
|
|
12437fd7fe | ||
|
|
4120f953c7 | ||
|
|
844c7787f9 | ||
|
|
0fe9ec1499 | ||
|
|
b3fb21dacc | ||
|
|
2deaf084e4 | ||
|
|
1b324510cc | ||
|
|
fd839f1827 | ||
|
|
f149f4aab1 | ||
|
|
af6fc64ab9 | ||
|
|
ff159bf30a | ||
|
|
8cdd19bcae | ||
|
|
2efc859829 | ||
|
|
d4a8351464 | ||
|
|
5fa544fc78 | ||
|
|
1070dd2d87 | ||
|
|
af98854ce4 | ||
|
|
7cace648c0 | ||
|
|
447bf4adb0 | ||
|
|
6572c1c692 | ||
|
|
7b48859f8d | ||
|
|
a6230bafe7 | ||
|
|
cc8f1466c7 | ||
|
|
69f810febc | ||
|
|
e5da7440d7 | ||
|
|
849ec1684a | ||
|
|
4f210cd8eb | ||
|
|
285f75764c | ||
|
|
3586203753 | ||
|
|
e406de7e00 | ||
|
|
53ed8502c9 | ||
|
|
ac8c756879 | ||
|
|
07faacdaf9 | ||
|
|
8464844518 | ||
|
|
fe2d1ff027 | ||
|
|
8d129e359e | ||
|
|
39aa56457b | ||
|
|
8491d5da8b | ||
|
|
681196e2c8 | ||
|
|
836ad5ebab | ||
|
|
a3ea1eddfb | ||
|
|
a2c06ac6ba | ||
|
|
a5c697fa2d | ||
|
|
be199b4fe9 | ||
|
|
cc15320cfe | ||
|
|
70bae59ec6 | ||
|
|
d4f3361805 | ||
|
|
332c855d40 | ||
|
|
01e3fa4d13 | ||
|
|
15a0f7a00a | ||
|
|
a751adba2a | ||
|
|
10eed010df | ||
|
|
033ca26216 | ||
|
|
40793cbdce | ||
|
|
48a1b2ec75 | ||
|
|
1a55556c66 | ||
|
|
3edd3ccbe6 | ||
|
|
194933e037 | ||
|
|
38deaedaef | ||
|
|
fc3dd5900c | ||
|
|
b1213425d0 | ||
|
|
40f0b450a8 | ||
|
|
0bab3977a8 | ||
|
|
2c46760b77 | ||
|
|
878c9ae5ae | ||
|
|
c8553de09e | ||
|
|
6738858e11 | ||
|
|
61cd6ab86e | ||
|
|
77704b669a | ||
|
|
770be613d7 | ||
|
|
9790366449 | ||
|
|
89f0a8c530 | ||
|
|
f72a06e25a | ||
|
|
8b975533e5 | ||
|
|
b32f7a9b57 | ||
|
|
e1e0083897 | ||
|
|
ca08ac0e3c | ||
|
|
a5b85b4462 | ||
|
|
3feab3a16d | ||
|
|
5d76e57b81 | ||
|
|
9101cd0339 | ||
|
|
4b2d3f5f5b | ||
|
|
482a471abb | ||
|
|
4d90bb0d02 | ||
|
|
202dfc18be | ||
|
|
13f4742699 | ||
|
|
33e769bd75 | ||
|
|
992f3000ef | ||
|
|
7ea4adae5e | ||
|
|
5ed9991135 | ||
|
|
dc2527c11f | ||
|
|
bee95654f3 | ||
|
|
48296bb1cf | ||
|
|
1ee9735354 | ||
|
|
f8da303ca1 | ||
|
|
6ae6ee9fd2 | ||
|
|
a11eafc5b3 | ||
|
|
efe53b57e4 | ||
|
|
e2330944d4 | ||
|
|
1c18906db7 | ||
|
|
873ceb48bd | ||
|
|
a48b955d89 | ||
|
|
b92fae2bfb | ||
|
|
156be17191 | ||
|
|
92290cfe81 | ||
|
|
29725c97f1 | ||
|
|
56b9cd14cb | ||
|
|
3550cc8f48 | ||
|
|
6a3d01ee6b | ||
|
|
27986213aa | ||
|
|
a2d07ef983 | ||
|
|
3cf4e32d9f | ||
|
|
a54584b716 | ||
|
|
51907e2642 | ||
|
|
5dd9d37ef2 | ||
|
|
f900854e0d | ||
|
|
d20e94f763 | ||
|
|
58de2ad2d7 | ||
|
|
f30c7b75d0 | ||
|
|
c5b8e55e12 | ||
|
|
559874fce7 | ||
|
|
1875653b34 | ||
|
|
6df770e72d | ||
|
|
51d415c8dd | ||
|
|
63bf428c34 | ||
|
|
a5d2772082 | ||
|
|
43c317ef4c | ||
|
|
01ffdb69d0 | ||
|
|
a78f346ac6 | ||
|
|
4ae88c859e | ||
|
|
e8a97f12d7 | ||
|
|
06aabdefbe | ||
|
|
15643f8e67 | ||
|
|
b987df1974 | ||
|
|
cbe63d43df | ||
|
|
e91a7c9599 | ||
|
|
3054952a5e | ||
|
|
3244df9cd1 | ||
|
|
1f75081f6e | ||
|
|
2c83a50a8a | ||
|
|
1c80fc28ee | ||
|
|
810eab9a58 | ||
|
|
256aa0296d | ||
|
|
2eb506c5e0 | ||
|
|
9f78a2902b | ||
|
|
613ae4ee34 | ||
|
|
ab208b71c4 | ||
|
|
68dd8d277d | ||
|
|
36a1927915 | ||
|
|
68437de416 | ||
|
|
459cd1b095 | ||
|
|
6f7f774080 | ||
|
|
fc0bf1953a | ||
|
|
c907e6c5fb | ||
|
|
29b3950ee7 | ||
|
|
0e0c6b8357 | ||
|
|
6f17f3e2c2 | ||
|
|
df107a272e | ||
|
|
b7a0748312 | ||
|
|
421b420a0c | ||
|
|
a478dc5935 | ||
|
|
4d65cb1c0f | ||
|
|
ced823cd95 | ||
|
|
79325bd219 | ||
|
|
5a19135c35 | ||
|
|
290e5f83d4 | ||
|
|
b535cb319a | ||
|
|
e3a9c6afb4 | ||
|
|
3f1a33e4b4 | ||
|
|
441eaa7f6c | ||
|
|
632153a1b4 | ||
|
|
f9d0ad9dc3 | ||
|
|
a67323fc12 | ||
|
|
1daa5e69b1 | ||
|
|
1718490982 | ||
|
|
1d4f97bb4c | ||
|
|
183fc7ced9 | ||
|
|
dcf1cedec9 | ||
|
|
845e608280 | ||
|
|
d6ecfe7f24 | ||
|
|
06b6bf6185 | ||
|
|
04a38b446f | ||
|
|
dfde5785a6 | ||
|
|
1a61455eef | ||
|
|
9f2ecb0144 | ||
|
|
3265060dc8 | ||
|
|
58b8acd68a | ||
|
|
3ec09ceedf | ||
|
|
1ce4aa81ee | ||
|
|
177e829f4b | ||
|
|
b5b672ec89 | ||
|
|
d41419c8d3 | ||
|
|
5e4d9dc17a | ||
|
|
4ac688e560 | ||
|
|
5d0a5cfe72 | ||
|
|
d4b81bb911 | ||
|
|
23122b327c | ||
|
|
f443c64341 | ||
|
|
c84af7d1e2 | ||
|
|
19a28b3c81 | ||
|
|
69944c1d3a | ||
|
|
81bf4921d4 | ||
|
|
91f6eedb24 | ||
|
|
dae150a3a5 | ||
|
|
8a81dce0c1 | ||
|
|
203d4a79e2 | ||
|
|
b04d47c3a9 | ||
|
|
8fcd1906a2 | ||
|
|
9939212379 | ||
|
|
38752f1327 | ||
|
|
6b51ec3371 | ||
|
|
5714056f9f | ||
|
|
21665e367c | ||
|
|
dff844b40a | ||
|
|
54403dfcbc | ||
|
|
61672c7805 | ||
|
|
69bb96113b | ||
|
|
51328efb22 | ||
|
|
f159666ae3 | ||
|
|
7fdb50807c | ||
|
|
890c7b42dc | ||
|
|
55398684cc | ||
|
|
c85edc38aa | ||
|
|
fa368b56ba | ||
|
|
41d7520585 | ||
|
|
0f23618324 | ||
|
|
bf9a2b45ef | ||
|
|
063c017bb7 | ||
|
|
7519a3765b | ||
|
|
56c687b39b | ||
|
|
083d398631 | ||
|
|
466183113f | ||
|
|
923c432977 | ||
|
|
e433ba8d7b | ||
|
|
848c884fff | ||
|
|
0769bbb7ff | ||
|
|
7054b09584 | ||
|
|
2633628ad1 | ||
|
|
e5ae1c2ea3 | ||
|
|
d2844580a1 | ||
|
|
42f5a3e2f7 | ||
|
|
8a62005a2d | ||
|
|
616f54c4a2 | ||
|
|
2140e5992a | ||
|
|
cd38c62430 | ||
|
|
67ac6ae191 | ||
|
|
7addae0fdd | ||
|
|
a3e8ba5506 | ||
|
|
6a302c38ab | ||
|
|
129bb6b1c3 | ||
|
|
c8b09c2238 | ||
|
|
76364af243 | ||
|
|
0efa8f9d3f | ||
|
|
f36b452f00 | ||
|
|
0be132f3b5 | ||
|
|
d31d8a764b | ||
|
|
68b29b683d | ||
|
|
eee293518c | ||
|
|
c4adc86f5e | ||
|
|
3ebda76def | ||
|
|
7564623d46 | ||
|
|
dc6b44571f | ||
|
|
ccd0167e40 | ||
|
|
7dd1004b93 | ||
|
|
19dd02acfd | ||
|
|
5e31914dc1 | ||
|
|
8296e0f485 | ||
|
|
afa5e3f469 | ||
|
|
f57fcbcb50 | ||
|
|
ce53e9dd2b | ||
|
|
55c2634416 | ||
|
|
fe0d340c03 | ||
|
|
5a02c9dbed | ||
|
|
2c4ffcf70d | ||
|
|
53c3e1338f | ||
|
|
79454a9072 | ||
|
|
21c2c5650b | ||
|
|
81ee559905 | ||
|
|
4a637a6e9a | ||
|
|
aaf4802d80 | ||
|
|
96310d761b | ||
|
|
96150bf568 | ||
|
|
f49df51544 | ||
|
|
673796fb3a | ||
|
|
482ab33c03 | ||
|
|
fb53cd37e7 | ||
|
|
c9fc7a1320 | ||
|
|
5f59b7e747 | ||
|
|
024b24932c | ||
|
|
604c0b189f | ||
|
|
356f1f5119 | ||
|
|
06659844b6 | ||
|
|
57cf363be9 | ||
|
|
2fc1ff68cf | ||
|
|
6c4fecc4f7 | ||
|
|
0991ad7cc8 | ||
|
|
d03b96b699 | ||
|
|
a690c1442f | ||
|
|
d742b67878 | ||
|
|
41971a95b2 | ||
|
|
b6d700077a | ||
|
|
c091e6910b | ||
|
|
35f633b533 | ||
|
|
85e4ed7c25 | ||
|
|
3b345a81c4 | ||
|
|
a55c48a4ce | ||
|
|
6f4c21c218 | ||
|
|
5060640408 | ||
|
|
f1cc8379e7 | ||
|
|
4f9627c612 | ||
|
|
012f241005 | ||
|
|
ccf67dbf05 | ||
|
|
a43709b4a8 | ||
|
|
e95c074965 | ||
|
|
4ca73566b6 | ||
|
|
d0b347517c | ||
|
|
7bed7ff482 | ||
|
|
d38b0dbf5b | ||
|
|
29d6c4ac04 | ||
|
|
8148b6d037 | ||
|
|
3327e0e871 | ||
|
|
0456f0f59b | ||
|
|
72cf78de2c | ||
|
|
1d0a89879c | ||
|
|
d1cc952859 | ||
|
|
f56c5b201d | ||
|
|
077b9eb7a4 | ||
|
|
15c333feb0 | ||
|
|
31c20ab32c | ||
|
|
69215cf9eb | ||
|
|
f89b51eace | ||
|
|
c581b5e532 | ||
|
|
df311203dc | ||
|
|
4927195ee4 | ||
|
|
63be1ebd38 | ||
|
|
796dc18cfb | ||
|
|
14e116553f | ||
|
|
c82ccd6cf7 | ||
|
|
0adb080319 | ||
|
|
dbb38fffae | ||
|
|
672a68219a | ||
|
|
22cb0efd00 | ||
|
|
a68d3d63b2 | ||
|
|
cf48c7280a | ||
|
|
1295973028 | ||
|
|
d5b9eda0f2 | ||
|
|
41c078d25c | ||
|
|
5614224e7d | ||
|
|
9ba44cb0d5 | ||
|
|
c18828af7b | ||
|
|
8a5f8439b4 | ||
|
|
8f0374569e | ||
|
|
09dde636d2 | ||
|
|
d347247bf3 | ||
|
|
a6c66fb669 | ||
|
|
b4dbc825b1 | ||
|
|
4a0cc8223e | ||
|
|
7db10857b3 | ||
|
|
7e927b43ad | ||
|
|
9eea072f2a | ||
|
|
aa2ff674db | ||
|
|
de24bfdf2f | ||
|
|
2a084c3d98 | ||
|
|
db8df41396 | ||
|
|
bda05d9372 | ||
|
|
59bc2af4d6 | ||
|
|
00a23ee330 | ||
|
|
51ad50a641 | ||
|
|
148e1926e8 | ||
|
|
96c023df41 | ||
|
|
44f37f49a1 | ||
|
|
a8a30f6d3f | ||
|
|
ba80b1cd55 | ||
|
|
b56e985ccc | ||
|
|
67521fd9f6 | ||
|
|
8c394f44b8 | ||
|
|
77b4fff268 | ||
|
|
f56a0c6075 | ||
|
|
9ce8486059 | ||
|
|
04a321150a | ||
|
|
d333c3c09e | ||
|
|
81d977c720 | ||
|
|
f477898c7c | ||
|
|
566193a1eb | ||
|
|
5d6eeb5d1d | ||
|
|
d9b9d71b2d | ||
|
|
643ee1df14 | ||
|
|
6c4d37ee68 | ||
|
|
97b79cd04a | ||
|
|
56c6229dd6 | ||
|
|
0fe2dd9b48 | ||
|
|
910aee7f7b | ||
|
|
97063937ff | ||
|
|
7e68b097d1 | ||
|
|
4d41dff4fd | ||
|
|
05082cec88 | ||
|
|
f05733da69 | ||
|
|
3c53909e82 | ||
|
|
1e53ec47a9 | ||
|
|
17802735d7 | ||
|
|
d2eb67a1ae | ||
|
|
3f254dd3fc | ||
|
|
e139bde6ae | ||
|
|
5f62951143 | ||
|
|
2207e87c8f | ||
|
|
5bd59c7b70 | ||
|
|
02f6867a2f | ||
|
|
b93fa3144a | ||
|
|
a68e0d9a3f | ||
|
|
cfe80ba9b7 | ||
|
|
35abfd44dd | ||
|
|
e98b5a691e | ||
|
|
ed24afd172 | ||
|
|
714556de65 | ||
|
|
547ec85b58 | ||
|
|
845d751e87 | ||
|
|
518a7f8a71 | ||
|
|
31323b01bc | ||
|
|
3a138ecc83 | ||
|
|
7294674a8b | ||
|
|
423b978395 | ||
|
|
ecf20ec7b8 | ||
|
|
c948a509fb | ||
|
|
f5ad19d76b | ||
|
|
d665d9e90e | ||
|
|
a5e10450dd | ||
|
|
e9d79b130d | ||
|
|
7951dac9d5 | ||
|
|
6c77351c58 | ||
|
|
7c4cda622f | ||
|
|
d8f8c1cb99 | ||
|
|
d2b9ad570f | ||
|
|
5b36f32996 | ||
|
|
3298030b8e | ||
|
|
6cfc696439 | ||
|
|
a93b3a06dd | ||
|
|
79e8d77ea0 | ||
|
|
d68fab9ee5 | ||
|
|
bda470245e | ||
|
|
0c95290f93 | ||
|
|
8989739d32 | ||
|
|
1112981e6e | ||
|
|
0cf82744ce | ||
|
|
5cdf838325 | ||
|
|
6418cad39f | ||
|
|
46529fd51e | ||
|
|
c09ba40a48 | ||
|
|
47d52896a1 | ||
|
|
d60c99b01c | ||
|
|
b8aeba06a2 | ||
|
|
8a0bc2d614 | ||
|
|
e34747d1ad | ||
|
|
1a6bc7c514 | ||
|
|
ffa0ddfdbf | ||
|
|
ca55bff1cf | ||
|
|
cfee5c4fdb | ||
|
|
e46185068b | ||
|
|
6ef2fea45e | ||
|
|
e244dd84a9 | ||
|
|
5034937a15 | ||
|
|
060045be65 | ||
|
|
9adfe8d484 | ||
|
|
799cc369e0 | ||
|
|
b97d3fea4b | ||
|
|
2a4ca9d5c3 | ||
|
|
747e40e74e | ||
|
|
cf279e7885 | ||
|
|
cbf968735a | ||
|
|
57b35e6007 | ||
|
|
1eaabdd8e5 | ||
|
|
dcd4e660a3 | ||
|
|
96409e74e5 | ||
|
|
e28ee097a1 | ||
|
|
2b4e544867 | ||
|
|
ee042a3481 | ||
|
|
63075f6846 | ||
|
|
7f2e42a06d | ||
|
|
3fbfa33b9a | ||
|
|
179aa75047 | ||
|
|
4658194d08 | ||
|
|
b35657814c | ||
|
|
a2322c77c6 | ||
|
|
b50c183c19 | ||
|
|
a941687db0 | ||
|
|
c2eef52b65 | ||
|
|
3e6cbbde04 | ||
|
|
6400536282 | ||
|
|
776103068f | ||
|
|
93beff3b65 | ||
|
|
22f8d86b05 | ||
|
|
3a9a9c7ad0 | ||
|
|
13238b1ad2 | ||
|
|
56f661e9c6 | ||
|
|
5351f46efb | ||
|
|
0cd3335b78 | ||
|
|
0611627448 | ||
|
|
f014918435 | ||
|
|
51e016089e |
No files matched your search
@@ -0,0 +1,6 @@
|
|||||||
|
BasedOnStyle: Google
|
||||||
|
AllowShortFunctionsOnASingleLine: false
|
||||||
|
SpaceAfterCStyleCast: true
|
||||||
|
PointerBindsToType: false
|
||||||
|
DerivePointerBinding: false
|
||||||
|
IncludeBlocks: Preserve
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
name: build
|
||||||
|
on: [push, pull_request]
|
||||||
|
jobs:
|
||||||
|
linux:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Install packages
|
||||||
|
run: sudo apt-get install libmbedtls-dev
|
||||||
|
- name: make
|
||||||
|
run: make test test++ IPV6=0
|
||||||
|
- name: openssl
|
||||||
|
run: make test SSL=OPENSSL IPV6=0
|
||||||
|
- name: examples
|
||||||
|
run: make ex
|
||||||
|
macos:
|
||||||
|
runs-on: macos-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Install packages
|
||||||
|
run: HOMEBREW_NO_AUTO_UPDATE=1 brew install jq mbedtls openssl
|
||||||
|
- name: make
|
||||||
|
run: make test++ upload-coverage IPV6=0
|
||||||
|
- name: openssl
|
||||||
|
run: make test SSL=OPENSSL IPV6=0
|
||||||
|
- name: exports
|
||||||
|
run: make mg_prefix
|
||||||
|
windows:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: vc98
|
||||||
|
run: make vc98
|
||||||
|
- name: vc2017
|
||||||
|
run: make vc2017
|
||||||
|
- name: mingw
|
||||||
|
run: make mingw
|
||||||
|
- name: mingw++
|
||||||
|
run: make mingw++
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
Copyright (c) 2004-2013 Sergey Lyubka <valenok@gmail.com>
|
Copyright (c) 2004-2013 Sergey Lyubka
|
||||||
Copyright (c) 2013-2015 Cesanta Software Limited
|
Copyright (c) 2013-2020 Cesanta Software Limited
|
||||||
All rights reserved
|
All rights reserved
|
||||||
|
|
||||||
This software is dual-licensed: you can redistribute it and/or modify
|
This software is dual-licensed: you can redistribute it and/or modify
|
||||||
|
|||||||
@@ -0,0 +1,106 @@
|
|||||||
|
SRCS = $(wildcard src/*.c)
|
||||||
|
HDRS = $(wildcard src/*.h)
|
||||||
|
DEFS ?= -DMG_MAX_HTTP_HEADERS=5 -DMG_ENABLE_LINES -DMG_ENABLE_HTTP_DEBUG_ENDPOINT=1 -DMG_ENABLE_DIRECTORY_LISTING=1 -DMG_ENABLE_SSI=1
|
||||||
|
CFLAGS ?= -W -Wall -Werror -Isrc -I. -O0 -g $(DEFS) $(TFLAGS) $(EXTRA)
|
||||||
|
SSL ?= MBEDTLS
|
||||||
|
CDIR ?= $(realpath $(CURDIR))
|
||||||
|
VC98 = docker run --rm -e WINEDEBUG=-all -v $(CDIR):$(CDIR) -w $(CDIR) docker.io/mdashnet/vc98
|
||||||
|
VC2017 = docker run --rm -e WINEDEBUG=-all -v $(CDIR):$(CDIR) -w $(CDIR) docker.io/mdashnet/vc2017
|
||||||
|
MINGW = docker run --rm -v $(CDIR):$(CDIR) -w $(CDIR) docker.io/mdashnet/mingw
|
||||||
|
GCC = docker run --rm -v $(CDIR):$(CDIR) -w $(CDIR) mdashnet/cc2
|
||||||
|
VCFLAGS = /nologo /W3 /O2 /I. $(DEFS) $(TFLAGS)
|
||||||
|
CLANG ?= clang # /usr/local/opt/llvm\@9/bin/clang
|
||||||
|
IPV6 ?= 1
|
||||||
|
ASAN_OPTIONS ?=
|
||||||
|
EXAMPLES := $(wildcard examples/*)
|
||||||
|
EXAMPLE_TARGET ?= example
|
||||||
|
.PHONY: ex test
|
||||||
|
|
||||||
|
ifeq "$(SSL)" "MBEDTLS"
|
||||||
|
MBEDTLS_DIR ?= $(shell brew --cellar mbedtls)
|
||||||
|
MBEDTLS_VER ?= $(shell brew info mbedtls --json | jq -j .[0].installed[0].version)
|
||||||
|
MBEDTLS ?= $(MBEDTLS_DIR)/$(MBEDTLS_VER)
|
||||||
|
CFLAGS += -DMG_ENABLE_MBEDTLS=1 -I$(MBEDTLS)/include -I/usr/include
|
||||||
|
LDFLAGS ?= -L$(MBEDTLS)/lib -lmbedtls -lmbedcrypto -lmbedx509
|
||||||
|
endif
|
||||||
|
ifeq "$(SSL)" "OPENSSL"
|
||||||
|
OPENSSL_DIR ?= $(shell brew --cellar openssl)
|
||||||
|
OPENSSL_VER ?= $(shell brew info openssl --json | jq -j .[0].installed[0].version)
|
||||||
|
OPENSSL ?= $(OPENSSL_DIR)/$(OPENSSL_VER)
|
||||||
|
CFLAGS += -DMG_ENABLE_OPENSSL=1 -I$(OPENSSL)/include
|
||||||
|
LDFLAGS ?= -L$(OPENSSL)/lib -lssl -lcrypto
|
||||||
|
endif
|
||||||
|
|
||||||
|
all: mg_prefix test test++ ex vc98 vc2017 mingw mingw++ linux linux++ infer fuzz
|
||||||
|
|
||||||
|
ex:
|
||||||
|
@for X in $(EXAMPLES); do $(MAKE) -C $$X $(EXAMPLE_TARGET); done
|
||||||
|
|
||||||
|
# Check that all external (exported) symbols have "mg_" prefix
|
||||||
|
mg_prefix: mongoose.c mongoose.h
|
||||||
|
$(CLANG) mongoose.c $(CFLAGS) -c -o /tmp/x.o && nm /tmp/x.o | grep ' T' | grep -v 'mg_' ; test $$? = 1
|
||||||
|
|
||||||
|
# C++ build
|
||||||
|
test++: CLANG = g++ -Wno-deprecated -Wno-missing-field-initializers
|
||||||
|
test++: unamalgamated
|
||||||
|
|
||||||
|
# Make sure we can build from an unamalgamated sources
|
||||||
|
unamalgamated: $(SRCS) $(HDRS) Makefile
|
||||||
|
$(CLANG) src/*.c test/unit_test.c $(CFLAGS) $(LDFLAGS) -g -o unit_test
|
||||||
|
|
||||||
|
fuzz: mongoose.c mongoose.h Makefile test/fuzz.c
|
||||||
|
$(CLANG) mongoose.c test/fuzz.c $(CFLAGS) -DMG_ENABLE_LINES -DMG_ENABLE_LOG=0 -fsanitize=fuzzer,signed-integer-overflow,address $(LDFLAGS) -g -o fuzzer
|
||||||
|
$(DEBUGGER) ./fuzzer
|
||||||
|
|
||||||
|
# make CLANG=/usr/local/opt/llvm\@8/bin/clang ASAN_OPTIONS=detect_leaks=1
|
||||||
|
test: CFLAGS += -DMG_ENABLE_IPV6=$(IPV6) -fsanitize=address#,undefined
|
||||||
|
test: mongoose.c mongoose.h Makefile test/unit_test.c
|
||||||
|
$(CLANG) mongoose.c test/unit_test.c $(CFLAGS) -coverage $(LDFLAGS) -g -o unit_test
|
||||||
|
ASAN_OPTIONS=$(ASAN_OPTIONS) $(DEBUGGER) ./unit_test
|
||||||
|
|
||||||
|
coverage: test
|
||||||
|
gcov -l -n *.gcno | sed '/^$$/d' | sed 'N;s/\n/ /'
|
||||||
|
gcov mongoose.gcno >/dev/null
|
||||||
|
|
||||||
|
upload-coverage: coverage
|
||||||
|
curl -s https://codecov.io/bash | /bin/bash
|
||||||
|
|
||||||
|
infer:
|
||||||
|
infer run -- cc test/unit_test.c -c -W -Wall -Werror -Isrc -I. -O2 -DMG_ENABLE_MBEDTLS=1 -DMG_ENABLE_LINES -I/usr/local/Cellar/mbedtls/2.23.0/include -DMG_ENABLE_IPV6=1 -g -o /dev/null
|
||||||
|
|
||||||
|
#vc98: VCFLAGS += -DMG_ENABLE_IPV6=1
|
||||||
|
vc98: Makefile mongoose.c mongoose.h test/unit_test.c
|
||||||
|
$(VC98) wine cl mongoose.c test/unit_test.c $(VCFLAGS) ws2_32.lib /Fe$@.exe
|
||||||
|
$(VC98) wine $@.exe
|
||||||
|
|
||||||
|
#vc2017: VCFLAGS += -DMG_ENABLE_IPV6=1
|
||||||
|
vc2017: Makefile mongoose.c mongoose.h test/unit_test.c
|
||||||
|
$(VC2017) wine64 cl mongoose.c test/unit_test.c $(VCFLAGS) ws2_32.lib /Fe$@.exe
|
||||||
|
$(VC2017) wine64 $@.exe
|
||||||
|
|
||||||
|
mingw: Makefile mongoose.c mongoose.h test/unit_test.c
|
||||||
|
$(MINGW) i686-w64-mingw32-gcc mongoose.c test/unit_test.c -W -Wall -Werror -I. $(DEFS) -lwsock32 -o test.exe
|
||||||
|
$(VC98) wine test.exe
|
||||||
|
|
||||||
|
mingw++: Makefile mongoose.c mongoose.h test/unit_test.c
|
||||||
|
$(MINGW) i686-w64-mingw32-g++ mongoose.c test/unit_test.c -W -Wall -Werror -I. $(DEFS) -lwsock32 -o test.exe
|
||||||
|
# Note: for some reason, a binary built with mingw g++, fails to run
|
||||||
|
|
||||||
|
#linux: CFLAGS += -DMG_ENABLE_IPV6=$(IPV6)
|
||||||
|
linux: CFLAGS += -fsanitize=address,undefined
|
||||||
|
linux: Makefile mongoose.c mongoose.h test/unit_test.c
|
||||||
|
$(GCC) $(CC) mongoose.c test/unit_test.c $(CFLAGS) $(LDFLAGS) -o unit_test_gcc
|
||||||
|
$(GCC) ./unit_test_gcc
|
||||||
|
|
||||||
|
linux++: CC = g++ -Wno-missing-field-initializers
|
||||||
|
linux++: linux
|
||||||
|
|
||||||
|
mongoose.c: $(SRCS) Makefile
|
||||||
|
(cat src/license.h; echo; echo '#include "mongoose.h"' ; (for F in src/private.h src/*.c ; do echo; echo '#ifdef MG_ENABLE_LINES'; echo "#line 1 \"$$F\""; echo '#endif'; cat $$F | sed -e 's,#include ".*,,'; done))> $@
|
||||||
|
|
||||||
|
mongoose.h: $(HDRS) Makefile
|
||||||
|
(cat src/license.h src/version.h ; cat src/arch.h src/arch_*.h src/config.h src/str.h src/log.h src/timer.h src/util.h src/url.h src/iobuf.h src/base64.h src/md5.h src/sha1.h src/event.h src/net.h src/http.h src/ssi.h src/tls.h src/ws.h src/sntp.h src/mqtt.h src/dns.h | sed -e 's,#include ".*,,' -e 's,^#pragma once,,')> $@
|
||||||
|
|
||||||
|
clean: EXAMPLE_TARGET = clean
|
||||||
|
clean: ex
|
||||||
|
rm -rf $(PROG) *.o *.dSYM unit_test* ut fuzzer *.gcov *.gcno *.gcda *.obj *.exe *.ilk *.pdb slow-unit* _CL_* infer-out data.txt crash-*
|
||||||
@@ -1,53 +1,56 @@
|
|||||||
# <img src="http://www.cesanta.com/hubfs/www.cesanta.com/Images/mongoose_library.png" width="64" height="64"> Mongoose - Embedded Web Server
|
# Mongoose - Embedded Web Server / Embedded Networking Library
|
||||||
|
|
||||||
[](https://gitter.im/cesanta/mongoose?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|

|
||||||
|
[](https://github.com/cesanta/mongoose/actions)
|
||||||
|
[](https://codecov.io/gh/cesanta/mongoose)
|
||||||
|
[](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:mongoose)
|
||||||
|
|
||||||

|
Mongoose is a networking library for C/C++. It implements event-driven
|
||||||
|
non-blocking APIs for TCP, UDP, HTTP, WebSocket, MQTT. It has been designed
|
||||||
|
for connecting devices and bringing them online. On the market since 2004, used
|
||||||
|
by vast number of open source and commercial products - it even runs on the
|
||||||
|
International Space Station! Mongoose makes embedded network programming fast,
|
||||||
|
robust, and easy.
|
||||||
|
|
||||||
|
- [Download Mongoose Source Code here](https://www.cesanta.com/download.html)
|
||||||
|
- [Read Mongoose documentation](https://cesanta.com/docs/)
|
||||||
|
|
||||||
Mongoose is ideal for embedded environments, it has been designed as an open
|
Connectivity is vital for software and embedded devices, but there are many
|
||||||
source platform for connecting devices and bringing them online.
|
pitfalls to consider when embedding a web server. This white paper breaks down
|
||||||
[Mongoose](https://www.cesanta.com/products)
|
on the top 9 things to avoid when embedding a web server.
|
||||||
has been on the market since 2004 and attracted
|
|
||||||
over 1 million cumulative downloads.
|
|
||||||
|
|
||||||
It provides easy to use event-driven interface that allows to implement
|
- [Download “9 Things NOT to do when embedding a web server” white paper here](https://www.cesanta.com/whitepaper.html)
|
||||||
network protocols or scalable network applications with little effort.
|
|
||||||
Mongoose helps developers to manage the complexity of network programming
|
|
||||||
and let them concentrate on the logic, saving time and money.
|
|
||||||
|
|
||||||
[Download Mongoose Source Code here](http://hubs.ly/H0150FK0)
|
Looking for a complete IoT solution? Check out
|
||||||
|
- [VCON](https://vcon.io) - Arduino compatible MCU modules with built-in firmware OTA updates
|
||||||
> Nothing overdone. Nothing less. So unbelievably easy to use.
|
- [Mongoose OS](https://mongoose-os.com) - open source embedded operating system for low-power connected microcontrollers. Secure, designed for commercial Internet of Things products
|
||||||
> Just how good software should be!
|
|
||||||
> - Pritin Tyagaraj, SAP
|
|
||||||
|
|
||||||
|
# Support
|
||||||
|
- [Study Mongoose examples](https://github.com/cesanta/mongoose/tree/master/examples)
|
||||||
|
- [Support Forum - ask your technical questions here](https://forum.cesanta.com/c/mongoose-library/6)
|
||||||
|
- [Commercial licensing and support available](https://www.cesanta.com/licensing.html)
|
||||||
|
- [Check out latest releases](https://github.com/cesanta/mongoose/releases)
|
||||||
|
|
||||||
# Features
|
# Features
|
||||||
|
|
||||||
* Cross-platform: works on Linux/UNIX, QNX, eCos, Windows, Android, iPhone, etc
|
* Cross-platform: works on Linux/UNIX, MacOS, QNX, eCos, Windows, Android,
|
||||||
* Single-threaded, asynchronous, non-blocking core with simple event-based API
|
iPhone, FreeRTOS, etc
|
||||||
* Builtin protocols:
|
* Supported embedded architectures: ESP32, ESP8266, TI CC3200, TI MSP432, NRF52, STM32, PIC32, NXP, and more
|
||||||
- plain TCP, plain UDP, SSL/TLS (over TCP, one-way or two-way)
|
* Builtin protocols: plain TCP/UDP, HTTP, MQTT, Websocket
|
||||||
- HTTP client, HTTP server
|
* SSL/TLS support: mbedTLS, OpenSSL or custom via API
|
||||||
- Websocket client, Websocket server
|
* Asynchronous DNS resolver
|
||||||
- JSON-RPC client, JSON-RPC server
|
|
||||||
- MQTT client, MQTT broker
|
|
||||||
- CoAP client, CoAP server
|
|
||||||
- DNS client, DNS server, async DNS resolver
|
|
||||||
* Tiny static and run-time footprint
|
* Tiny static and run-time footprint
|
||||||
* Source code is both ISO C and ISO C++ compliant
|
* Source code is both ISO C and ISO C++ compliant
|
||||||
* Very easy to integrate: just copy
|
* Very easy to integrate: just copy
|
||||||
[mongoose.c](https://raw.githubusercontent.com/cesanta/mongoose/master/mongoose.c) and
|
[mongoose.c](https://raw.githubusercontent.com/cesanta/mongoose/master/mongoose.c) and
|
||||||
[mongoose.h](https://raw.githubusercontent.com/cesanta/mongoose/master/mongoose.h)
|
[mongoose.h](https://raw.githubusercontent.com/cesanta/mongoose/master/mongoose.h)
|
||||||
files to your build tree
|
files to your build tree
|
||||||
* Extensively tested and production-ready, trusted by many blue chip businesses
|
|
||||||
|
|
||||||
# Examples & Documentation
|
# Licensing
|
||||||
|
|
||||||
- [User Guide](https://docs.cesanta.com/mongoose) - Detailed User Guide and API reference
|
Mongoose is released under Commercial and [GNU GPL v.2](http://www.gnu.org/licenses/old-licenses/gpl-2.0.html) open source licenses.
|
||||||
- [examples](examples) - Collection of well-commented examples. To build any example,
|
|
||||||
go into respective directory and type `make`
|
Commercial Projects: [Contact us for commercial license.](https://www.cesanta.com/contact.html)
|
||||||
|
|
||||||
# Dashboard Example
|
# Dashboard Example
|
||||||
|
|
||||||
@@ -55,47 +58,17 @@ Mongoose is often used to implement device dashboards and real-time
|
|||||||
data exchange over Websocket. Here is a dashboard example that illustrates
|
data exchange over Websocket. Here is a dashboard example that illustrates
|
||||||
the functionality:
|
the functionality:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
[Developing a new product? Contact us today to discuss how Mongoose can help
|
[Developing a new product? Contact us today to discuss how Mongoose can help.](https://www.cesanta.com/contact.html)
|
||||||
](https://www.cesanta.com/contact)
|
|
||||||
|
|
||||||
|
# Contributions
|
||||||
|
|
||||||
# Licensing
|
Contributions are welcome! Please follow the guidelines below:
|
||||||
|
|
||||||
You are using Mongoose under
|
- Sign [Cesanta CLA](https://cesanta.com/cla.html) and send GitHub pull request
|
||||||
[GPLv2](http://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)
|
- When making pull requests, please make sure that it has only one commit,
|
||||||
and until you commercialize your
|
and imlements/fixes only one piece of functionality
|
||||||
application, can continue to use Mongoose free of charge.
|
|
||||||
|
|
||||||
Once you commercialize your product, in order to comply with GPLv2
|
# Looking for a pre-compiled Mongoose web server Windows or Mac binary?
|
||||||
you need to either open the source code of your product fully or
|
- [Download pre-compiled Mongoose web server binary.](https://www.cesanta.com/binary.html)
|
||||||
alternatively purchase a commercial license.
|
|
||||||
We offer [three levels of commercial licensing](https://www.cesanta.com/products):
|
|
||||||
|
|
||||||
- Mongoose Lite: cross platform integration, SSL/TLS, HTTP support
|
|
||||||
- Mongoose: Mongoose Lite + HTTP CGI, HTTP SSI, HTTP Digest Auth,
|
|
||||||
WebSocket support
|
|
||||||
- Mongoose Premium: Mongoose + Plain TCP, UDP, JSON-RPC, MQTT, DNS,
|
|
||||||
CoAP support
|
|
||||||
|
|
||||||
|
|
||||||
[Enquire about commercial licensing here](https://www.cesanta.com/contact)
|
|
||||||
|
|
||||||
# Mongoose Binary
|
|
||||||
|
|
||||||
This is our easy to use web server for web developers (PHP, Ruby, Python, etc)
|
|
||||||
and web designers. Available in three editions to suit your needs: free, pro
|
|
||||||
(USD 5) and dev edition (from USD 8). To install, simply download, double-click
|
|
||||||
to start and run browser - that's all!
|
|
||||||
|
|
||||||
[Download Mongoose Binary here](https://www.cesanta.com/mongoose)
|
|
||||||
|
|
||||||
# Other products by Cesanta
|
|
||||||
|
|
||||||
- [Smart.js](https://github.com/cesanta/smart.js) -
|
|
||||||
Generic, hardware independent, full-stack IoT software platform
|
|
||||||
- [V7](https://github.com/cesanta/v7) - Embedded JavaScript engine
|
|
||||||
- [Frozen](https://github.com/cesanta/frozen) - JSON parser and generator
|
|
||||||
- [SLRE](https://github.com/cesanta/slre) - Super Light Regular Expression
|
|
||||||
library
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
*.exe
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
# Copyright (c) 2014 Cesanta Software
|
|
||||||
# All rights reserved
|
|
||||||
|
|
||||||
SUBDIRS = $(sort $(dir $(wildcard */)))
|
|
||||||
X = $(SUBDIRS)
|
|
||||||
|
|
||||||
.PHONY: $(SUBDIRS)
|
|
||||||
|
|
||||||
all: $(SUBDIRS)
|
|
||||||
|
|
||||||
$(SUBDIRS):
|
|
||||||
@$(MAKE) -C $@
|
|
||||||
|
|
||||||
clean:
|
|
||||||
for d in $(SUBDIRS) ; do $(MAKE) -C $$d clean ; done
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
PROG = api_server
|
|
||||||
SOURCES = $(PROG).c sqlite3.c db_plugin_sqlite.c ../../mongoose.c
|
|
||||||
CFLAGS = -W -Wall -pthread $(CFLAGS_EXTRA)
|
|
||||||
|
|
||||||
ifeq ($(OS), Windows_NT)
|
|
||||||
else
|
|
||||||
UNAME_S := $(shell uname -s)
|
|
||||||
ifeq ($(UNAME_S), Linux)
|
|
||||||
CFLAGS += -ldl -lm
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
|
|
||||||
all: $(PROG)
|
|
||||||
|
|
||||||
$(PROG): $(SOURCES)
|
|
||||||
$(CC) $(SOURCES) -o $@ $(CFLAGS)
|
|
||||||
|
|
||||||
$(PROG).exe: $(SOURCES)
|
|
||||||
cl $(SOURCES) /I.. /MD /Fe$@
|
|
||||||
|
|
||||||
test: $(PROG)
|
|
||||||
sh unit_test.sh $$(pwd)/$(PROG)
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -rf *.gc* *.dSYM *.exe *.obj *.o a.out $(PROG)
|
|
||||||
@@ -1,104 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2014 Cesanta Software Limited
|
|
||||||
* All rights reserved
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "db_plugin.h"
|
|
||||||
|
|
||||||
static const char *s_http_port = "8000";
|
|
||||||
static struct mg_serve_http_opts s_http_server_opts;
|
|
||||||
static int s_sig_num = 0;
|
|
||||||
static void *s_db_handle = NULL;
|
|
||||||
static const char *s_db_path = "api_server.db";
|
|
||||||
static const struct mg_str s_get_method = MG_STR("GET");
|
|
||||||
static const struct mg_str s_put_method = MG_STR("PUT");
|
|
||||||
static const struct mg_str s_delele_method = MG_STR("DELETE");
|
|
||||||
|
|
||||||
static void signal_handler(int sig_num) {
|
|
||||||
signal(sig_num, signal_handler);
|
|
||||||
s_sig_num = sig_num;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int has_prefix(const struct mg_str *uri, const struct mg_str *prefix) {
|
|
||||||
return uri->len > prefix->len && memcmp(uri->p, prefix->p, prefix->len) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int is_equal(const struct mg_str *s1, const struct mg_str *s2) {
|
|
||||||
return s1->len == s2->len && memcmp(s1->p, s2->p, s2->len) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
|
|
||||||
static const struct mg_str api_prefix = MG_STR("/api/v1");
|
|
||||||
struct http_message *hm = (struct http_message *) ev_data;
|
|
||||||
struct mg_str key;
|
|
||||||
|
|
||||||
switch (ev) {
|
|
||||||
case MG_EV_HTTP_REQUEST:
|
|
||||||
if (has_prefix(&hm->uri, &api_prefix)) {
|
|
||||||
key.p = hm->uri.p + api_prefix.len;
|
|
||||||
key.len = hm->uri.len - api_prefix.len;
|
|
||||||
if (is_equal(&hm->method, &s_get_method)) {
|
|
||||||
db_op(nc, hm, &key, s_db_handle, API_OP_GET);
|
|
||||||
} else if (is_equal(&hm->method, &s_put_method)) {
|
|
||||||
db_op(nc, hm, &key, s_db_handle, API_OP_SET);
|
|
||||||
} else if (is_equal(&hm->method, &s_delele_method)) {
|
|
||||||
db_op(nc, hm, &key, s_db_handle, API_OP_DEL);
|
|
||||||
} else {
|
|
||||||
mg_printf(nc, "%s",
|
|
||||||
"HTTP/1.0 501 Not Implemented\r\n"
|
|
||||||
"Content-Length: 0\r\n\r\n");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
mg_serve_http(nc, hm, s_http_server_opts); /* Serve static content */
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
|
||||||
struct mg_mgr mgr;
|
|
||||||
struct mg_connection *nc;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
/* Open listening socket */
|
|
||||||
mg_mgr_init(&mgr, NULL);
|
|
||||||
nc = mg_bind(&mgr, s_http_port, ev_handler);
|
|
||||||
mg_set_protocol_http_websocket(nc);
|
|
||||||
s_http_server_opts.document_root = "web_root";
|
|
||||||
|
|
||||||
/* Parse command line arguments */
|
|
||||||
for (i = 1; i < argc; i++) {
|
|
||||||
if (strcmp(argv[i], "-D") == 0) {
|
|
||||||
mgr.hexdump_file = argv[++i];
|
|
||||||
} else if (strcmp(argv[i], "-f") == 0) {
|
|
||||||
s_db_path = argv[++i];
|
|
||||||
} else if (strcmp(argv[i], "-r") == 0) {
|
|
||||||
s_http_server_opts.document_root = argv[++i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
signal(SIGINT, signal_handler);
|
|
||||||
signal(SIGTERM, signal_handler);
|
|
||||||
|
|
||||||
/* Open database */
|
|
||||||
if ((s_db_handle = db_open(s_db_path)) == NULL) {
|
|
||||||
fprintf(stderr, "Cannot open DB [%s]\n", s_db_path);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Run event loop until signal is received */
|
|
||||||
printf("Starting RESTful server on port %s\n", s_http_port);
|
|
||||||
while (s_sig_num == 0) {
|
|
||||||
mg_mgr_poll(&mgr, 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Cleanup */
|
|
||||||
mg_mgr_free(&mgr);
|
|
||||||
db_close(&s_db_handle);
|
|
||||||
|
|
||||||
printf("Exiting on signal %d\n", s_sig_num);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2014 Cesanta Software Limited
|
|
||||||
* All rights reserved
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef DB_PLUGIN_HEADER_DEFINED
|
|
||||||
#define DB_PLUGIN_HEADER_DEFINED
|
|
||||||
|
|
||||||
#include "../../mongoose.h"
|
|
||||||
|
|
||||||
void *db_open(const char *db_path);
|
|
||||||
void db_close(void **db_handle);
|
|
||||||
|
|
||||||
enum { API_OP_GET, API_OP_SET, API_OP_DEL };
|
|
||||||
|
|
||||||
void db_op(struct mg_connection *nc, const struct http_message *hm,
|
|
||||||
const struct mg_str *key, void *db, int op);
|
|
||||||
|
|
||||||
#endif /* DB_PLUGIN_HEADER_DEFINED */
|
|
||||||
@@ -1,107 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2014 Cesanta Software Limited
|
|
||||||
* All rights reserved
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "db_plugin.h"
|
|
||||||
#include "sqlite3.h"
|
|
||||||
|
|
||||||
void *db_open(const char *db_path) {
|
|
||||||
sqlite3 *db = NULL;
|
|
||||||
if (sqlite3_open_v2(db_path, &db, SQLITE_OPEN_READWRITE |
|
|
||||||
SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX, NULL) == SQLITE_OK) {
|
|
||||||
sqlite3_exec(db, "CREATE TABLE IF NOT EXISTS kv(key PRIMARY KEY, val);",
|
|
||||||
0, 0, 0);
|
|
||||||
}
|
|
||||||
return db;
|
|
||||||
}
|
|
||||||
|
|
||||||
void db_close(void **db_handle) {
|
|
||||||
if (db_handle != NULL && *db_handle != NULL) {
|
|
||||||
sqlite3_close(*db_handle);
|
|
||||||
*db_handle = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void op_set(struct mg_connection *nc, const struct http_message *hm,
|
|
||||||
const struct mg_str *key, void *db) {
|
|
||||||
sqlite3_stmt *stmt = NULL;
|
|
||||||
char value[200];
|
|
||||||
const struct mg_str *body = hm->query_string.len > 0 ?
|
|
||||||
&hm->query_string : &hm->body;
|
|
||||||
|
|
||||||
mg_get_http_var(body, "value", value, sizeof(value));
|
|
||||||
if (sqlite3_prepare_v2(db, "INSERT OR REPLACE INTO kv VALUES (?, ?);",
|
|
||||||
-1, &stmt, NULL) == SQLITE_OK) {
|
|
||||||
sqlite3_bind_text(stmt, 1, key->p, key->len, SQLITE_STATIC);
|
|
||||||
sqlite3_bind_text(stmt, 2, value, strlen(value), SQLITE_STATIC);
|
|
||||||
sqlite3_step(stmt);
|
|
||||||
sqlite3_finalize(stmt);
|
|
||||||
}
|
|
||||||
mg_printf(nc, "%s", "HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void op_get(struct mg_connection *nc, const struct http_message *hm,
|
|
||||||
const struct mg_str *key, void *db) {
|
|
||||||
sqlite3_stmt *stmt = NULL;
|
|
||||||
const char *data = NULL;
|
|
||||||
int result;
|
|
||||||
(void) hm;
|
|
||||||
|
|
||||||
if (sqlite3_prepare_v2(db, "SELECT val FROM kv WHERE key = ?;",
|
|
||||||
-1, &stmt, NULL) == SQLITE_OK) {
|
|
||||||
sqlite3_bind_text(stmt, 1, key->p, key->len, SQLITE_STATIC);
|
|
||||||
result = sqlite3_step(stmt);
|
|
||||||
data = (char *) sqlite3_column_text(stmt, 0);
|
|
||||||
if ((result == SQLITE_OK || result == SQLITE_ROW) && data != NULL) {
|
|
||||||
mg_printf(nc, "HTTP/1.1 200 OK\r\n"
|
|
||||||
"Content-Type: text/plain\r\n"
|
|
||||||
"Content-Length: %d\r\n\r\n%s",
|
|
||||||
(int) strlen(data), data);
|
|
||||||
} else {
|
|
||||||
mg_printf(nc, "%s", "HTTP/1.1 404 Not Found\r\n"
|
|
||||||
"Content-Length: 0\r\n\r\n");
|
|
||||||
}
|
|
||||||
sqlite3_finalize(stmt);
|
|
||||||
} else {
|
|
||||||
mg_printf(nc, "%s", "HTTP/1.1 500 Server Error\r\n"
|
|
||||||
"Content-Length: 0\r\n\r\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void op_del(struct mg_connection *nc, const struct http_message *hm,
|
|
||||||
const struct mg_str *key, void *db) {
|
|
||||||
sqlite3_stmt *stmt = NULL;
|
|
||||||
int result;
|
|
||||||
(void) hm;
|
|
||||||
|
|
||||||
if (sqlite3_prepare_v2(db, "DELETE FROM kv WHERE key = ?;",
|
|
||||||
-1, &stmt, NULL) == SQLITE_OK) {
|
|
||||||
sqlite3_bind_text(stmt, 1, key->p, key->len, SQLITE_STATIC);
|
|
||||||
result = sqlite3_step(stmt);
|
|
||||||
if (result == SQLITE_OK || result == SQLITE_ROW) {
|
|
||||||
mg_printf(nc, "%s", "HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n");
|
|
||||||
} else {
|
|
||||||
mg_printf(nc, "%s", "HTTP/1.1 404 Not Found\r\n"
|
|
||||||
"Content-Length: 0\r\n\r\n");
|
|
||||||
}
|
|
||||||
sqlite3_finalize(stmt);
|
|
||||||
} else {
|
|
||||||
mg_printf(nc, "%s", "HTTP/1.1 500 Server Error\r\n"
|
|
||||||
"Content-Length: 0\r\n\r\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void db_op(struct mg_connection *nc, const struct http_message *hm,
|
|
||||||
const struct mg_str *key, void *db, int op) {
|
|
||||||
switch (op) {
|
|
||||||
case API_OP_GET: op_get(nc, hm, key, db); break;
|
|
||||||
case API_OP_SET: op_set(nc, hm, key, db); break;
|
|
||||||
case API_OP_DEL: op_del(nc, hm, key, db); break;
|
|
||||||
default:
|
|
||||||
mg_printf(nc, "%s", "HTTP/1.0 501 Not Implemented\r\n"
|
|
||||||
"Content-Length: 0\r\n\r\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
PROG=$1
|
|
||||||
PORT=${2:-8000} # If second param is given, this is load balancer port
|
|
||||||
DB_FILE=/tmp/_$$.db
|
|
||||||
URL=http://127.0.0.1:$PORT/api/v1
|
|
||||||
|
|
||||||
cleanup() {
|
|
||||||
rm -rf $DB_FILE
|
|
||||||
kill -9 $PID >/dev/null 2>&1
|
|
||||||
}
|
|
||||||
|
|
||||||
#set -x
|
|
||||||
trap cleanup EXIT
|
|
||||||
|
|
||||||
cleanup
|
|
||||||
$PROG -f $DB_FILE &
|
|
||||||
PID=$!
|
|
||||||
|
|
||||||
#sleep 1
|
|
||||||
curl -s -X PUT -d 'value=123' $URL/foo
|
|
||||||
curl -s -X PUT -d 'value=success' $URL/bar/baz
|
|
||||||
|
|
||||||
# Fetch existing key
|
|
||||||
RESULT=$(curl -s $URL/bar/baz)
|
|
||||||
test "$RESULT" = "success" || exit 1
|
|
||||||
|
|
||||||
# Delete it
|
|
||||||
curl -s -X DELETE $URL/bar/baz
|
|
||||||
|
|
||||||
# Make sure it's deleted - GET must result in 404
|
|
||||||
RESULT=$(curl -s -i $URL/bar/baz | head -1 | tr -d '\r')
|
|
||||||
test "$RESULT" = "HTTP/1.1 404 Not Found" || exit 1
|
|
||||||
|
|
||||||
exit 0
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8" />
|
|
||||||
<title>RESTful API demo</title>
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
||||||
<style type="text/css">
|
|
||||||
* { outline: none; }
|
|
||||||
body {
|
|
||||||
background-color: #789; margin: 0;
|
|
||||||
padding: 0; font: 16px/1.4 Helvetica, Arial, sans-serif;
|
|
||||||
font: 16px/1.4 Helvetica, Arial, sans-serif;
|
|
||||||
}
|
|
||||||
div.content {
|
|
||||||
width: 800px; margin: 2em auto; padding: 20px 50px;
|
|
||||||
background-color: #fff; border-radius: 1em;
|
|
||||||
}
|
|
||||||
label { display: inline-block; min-width: 7em; }
|
|
||||||
input { border: 1px solid #ccc; padding: 0.2em; }
|
|
||||||
a:link, a:visited { color: #69c; text-decoration: none; }
|
|
||||||
@media (max-width: 700px) {
|
|
||||||
body { background-color: #fff; }
|
|
||||||
div.content { width: auto; margin: 0 auto; padding: 1em; }
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
|
|
||||||
<script language="javascript" type="text/javascript">
|
|
||||||
jQuery(function() {
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="content">
|
|
||||||
<h1>API server</h1>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
# This "makefile" is only intended to prevent errors during main makefile execution
|
|
||||||
all:
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
# Arduino Restful Client
|
|
||||||
|
|
||||||
This example demonstrates how to use [Mongoose](https://www.cesanta.com/mongoose) to send HTTP commands from Arduino.
|
|
||||||
|
|
||||||
Example sends free memory size and current board uptime, but it can be modified to send any user-specific data.
|
|
||||||
|
|
||||||
At the moment this example supports [Arduino Mega 2560](http://arduino.cc/en/Main/ArduinoBoardMega2560) board (and compatible) with either W5100-based
|
|
||||||
network shield (like [Arduino Ethernet Shield](http://arduino.cc/en/Main/ArduinoEthernetShield)) or [CC3000](http://www.ti.com/product/cc3000)-based WIFI Shield.
|
|
||||||
|
|
||||||
## Build and run instructions:
|
|
||||||
|
|
||||||
###To run with Arduino Ethernet (W5100) shield:
|
|
||||||
1. Add (Sketch->Add file...) the following files to sketch:
|
|
||||||
- /mongoose/mongoose.h
|
|
||||||
- /mongoose/mongoose.c
|
|
||||||
- /mongoose/platforms/arduino_ethernet_W5100/avrsupport.h
|
|
||||||
- /mongoose/platforms/arduino_ethernet_W5100/avrsupport.cpp
|
|
||||||
3. Buils and start (in console) /Users/alex/Projects/mongoose/examples/restful_server example
|
|
||||||
4. Make `board_ip` and `board_mac` variables suitable for your network and board
|
|
||||||
5. Change IP address in `s_target_address` variable to IP address of host running restful_server
|
|
||||||
6. Uncomment line `#include <Ethernet.h>`
|
|
||||||
7. Compile and flash sketch
|
|
||||||
8. restful_server will start to show current uptime and free memory size (with 5 seconds interval)
|
|
||||||
|
|
||||||
###To run with Adafruit WiFi (CC3000) shield:
|
|
||||||
1. Add (Sketch->Add files...) the following files to sketch:
|
|
||||||
- /mongoose/mongoose.h
|
|
||||||
- /mongoose/mongoose.c
|
|
||||||
- /mongoose/platforms/arduino_ethernet_W5100/avrsupport.h
|
|
||||||
- /mongoose/platforms/arduino_ethernet_W5100/avrsupport.cpp
|
|
||||||
2. Import Adafruit CC3000 library for mongoose
|
|
||||||
(select Sketch->Import Library...->Add library... and point
|
|
||||||
/mongoose/platforms/arduino_wifi_CC3000/adafruit_CC3000_lib_mongoose folder)
|
|
||||||
3. Buils and start (in console) /Users/alex/Projects/mongoose/examples/restful_server example
|
|
||||||
4. Make the following variables suitable for your network
|
|
||||||
- `board_ip`
|
|
||||||
- `subnet_mask`
|
|
||||||
- `gateway`
|
|
||||||
- `dns`
|
|
||||||
- `wlan_ssid`
|
|
||||||
- `wlan_pwd`
|
|
||||||
- `wlan_security`
|
|
||||||
5. Change IP address in `s_target_address` variable to IP address of host running restful_server
|
|
||||||
6. Uncomment line `#include <Adafruit_CC3000.h>`
|
|
||||||
8. Compile and flash sketch
|
|
||||||
9. restful_server will start to show current uptime and free memory size (with 5 seconds interval)
|
|
||||||
@@ -1,141 +0,0 @@
|
|||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2015 Cesanta Software Limited
|
|
||||||
* All rights reserved
|
|
||||||
*
|
|
||||||
* Build and run instructions:
|
|
||||||
* To run with Arduino Ethernet (W5100) shield:
|
|
||||||
* -----------------------------------------------------------
|
|
||||||
* 1. Add (Sketch->Add file...) the following files to sketch:
|
|
||||||
* - /mongoose/mongoose.h
|
|
||||||
* - /mongoose/mongoose.c
|
|
||||||
* - /mongoose/platforms/arduino_ethernet_W5100/avrsupport.h
|
|
||||||
* - /mongoose/platforms/arduino_ethernet_W5100/avrsupport.cpp
|
|
||||||
* 2. Buils and run in console /Users/alex/Projects/mongoose/examples/restful_server example
|
|
||||||
* 3. Make board_ip and board_mac variables suitable for your network and board
|
|
||||||
* 4. Uncomment line #include <Ethernet.h>
|
|
||||||
* 5. Change IP address in s_target_address variable to IP address of host running restful_server
|
|
||||||
* 6. Compile & flash sketch
|
|
||||||
* 7. restful_server server will start to show current uptime and free memory size (with 5 second interval)
|
|
||||||
*
|
|
||||||
* To run with Adafruit WiFi (CC3000) shield:
|
|
||||||
* -----------------------------------------------------------
|
|
||||||
* 1. Add (Sketch->Add files...) the following files to sketch:
|
|
||||||
* - /mongoose/mongoose.h
|
|
||||||
* - /mongoose/mongoose.c
|
|
||||||
* - /mongoose/platforms/arduino_ethernet_W5100/avrsupport.h
|
|
||||||
* - /mongoose/platforms/arduino_ethernet_W5100/avrsupport.cpp
|
|
||||||
* 2. Import Adafruit CC3000 library for mongoose (select Sketch->Import Library...->Add library... and point
|
|
||||||
* /mongoose/platforms/arduino_wifi_CC3000/adafruit_CC3000_lib_mongoose folder
|
|
||||||
* 3. Buils and run in console /Users/alex/Projects/mongoose/examples/restful_server example
|
|
||||||
* 4. Make the following variables suitable for your network
|
|
||||||
* - board_ip
|
|
||||||
* - subnet_mask
|
|
||||||
* - gateway
|
|
||||||
* - dns
|
|
||||||
* - wlan_ssid
|
|
||||||
* - wlan_pwd
|
|
||||||
* - wlan_security
|
|
||||||
* 5. Uncomment line #include <Adafruit_CC3000.h>
|
|
||||||
* 6. Compile & flash sketch
|
|
||||||
* 7. restful_server server will start to show current uptime and free memory size (with 5 second interval) *
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
//#include <Ethernet.h>
|
|
||||||
//#include <Adafruit_CC3000.h>
|
|
||||||
#include <SPI.h>
|
|
||||||
#include "mongoose.h"
|
|
||||||
|
|
||||||
// CHANGE THESE VARIABLES
|
|
||||||
// NB: Devices with the same address must not end up on the same network.
|
|
||||||
// Use MAC address provided by device manufacturer (e.g. on a sticker).
|
|
||||||
// If there isn't one, use a random one from the locally administered range.
|
|
||||||
// See http://en.wikipedia.org/wiki/MAC_address for details.
|
|
||||||
static uint8_t board_mac[] = {
|
|
||||||
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
|
|
||||||
};
|
|
||||||
static uint8_t board_ip[] = {192, 168, 10, 177};
|
|
||||||
|
|
||||||
#ifdef WIFI_CC3000
|
|
||||||
static uint8_t subnet_mask[] = {255, 255, 255, 0};
|
|
||||||
static uint8_t gateway[] = {192, 168, 10, 254};
|
|
||||||
static uint8_t dmg_ip[] = {192, 168, 10, 254};
|
|
||||||
|
|
||||||
static const char *wlan_ssid = "mynetwork";
|
|
||||||
static const char *wlan_pwd = "mypassword";
|
|
||||||
static int wlan_security = WLAN_SEC_WPA2;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static const char *s_target_address = "192.168.10.3:8000";
|
|
||||||
|
|
||||||
/////////////////////////////////////////////
|
|
||||||
|
|
||||||
static const char *s_request = "/printcontent";
|
|
||||||
|
|
||||||
static uint32_t IP2U32(uint8_t* iparr) {
|
|
||||||
return ((uint32_t)iparr[0] << 24) | ((uint32_t)iparr[1] << 16) | (iparr[2] << 8) | (iparr[3]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int get_data_to_send(char* buf, int buf_size) {
|
|
||||||
// Adding data to send
|
|
||||||
// It could be any sensor data, now just put uptime & free memory size here
|
|
||||||
return snprintf(buf, buf_size, "Uptime: %lus Free memory: %db",
|
|
||||||
millis()/1000, get_freememsize());
|
|
||||||
}
|
|
||||||
static void rfc_ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
|
|
||||||
int connect_status;
|
|
||||||
|
|
||||||
switch (ev) {
|
|
||||||
case NS_CONNECT:
|
|
||||||
connect_status = * (int *) ev_data;
|
|
||||||
|
|
||||||
if (connect_status == 0) {
|
|
||||||
char buf[100];
|
|
||||||
int len = get_data_to_send(buf, sizeof(buf));
|
|
||||||
mg_printf(nc, "POST %s HTTP/1.0\r\nHost: %s\r\nContent-Lenght: %d"
|
|
||||||
"\r\n\r\n%s", s_request, s_target_address, len, buf);
|
|
||||||
nc->flags |= MG_F_SEND_AND_CLOSE;
|
|
||||||
} else {
|
|
||||||
nc->flags |= MG_F_CLOSE_IMMEDIATELY;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct mg_mgr mgr;
|
|
||||||
static struct mg_connection *nc;
|
|
||||||
|
|
||||||
void setup()
|
|
||||||
{
|
|
||||||
Serial.begin(9600);
|
|
||||||
Serial.println("Initialization...");
|
|
||||||
#if defined(ETHERNET_W5100)
|
|
||||||
avr_netinit(board_mac, board_ip);
|
|
||||||
#elif defined(WIFI_CC3000)
|
|
||||||
if (avr_netinit(wlan_ssid, wlan_pwd, wlan_security, IP2U32(board_ip),
|
|
||||||
IP2U32(subnet_mask), IP2U32(gateway), IP2U32(dmg_ip)) != 0) {
|
|
||||||
Serial.println("Initialization error, check network settings");
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
mg_mgr_init(&mgr, NULL);
|
|
||||||
Serial.println("Initialization done");
|
|
||||||
}
|
|
||||||
|
|
||||||
void loop() {
|
|
||||||
nc = mg_connect(&mgr, s_target_address, rfc_ev_handler);
|
|
||||||
if (nc != NULL) {
|
|
||||||
mg_set_protocol_http_websocket(nc);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t time_to_finish = millis() + 5000;
|
|
||||||
while (millis() < time_to_finish) {
|
|
||||||
mg_mgr_poll(&mgr, 1000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
# This "makefile" is only intended to prevent errors during main makefile execution
|
|
||||||
all:
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
# Arduino Restful Server
|
|
||||||
|
|
||||||
This example demonstrates how to use [Mongoose](https://www.cesanta.com/mongoose) to control Arduino
|
|
||||||
using HTTP requests.
|
|
||||||
Example just blinks by LED when Mongoose receives HTTP command, but it can be modified to execute any user-specific code.
|
|
||||||
|
|
||||||
At the moment this example supports [Arduino Mega 2560](http://arduino.cc/en/Main/ArduinoBoardMega2560) board (and compatible) with either W5100-based
|
|
||||||
network shield (like [Arduino Ethernet Shield](http://arduino.cc/en/Main/ArduinoEthernetShield)) or [CC3000](http://www.ti.com/product/cc3000)-based WIFI Shield.
|
|
||||||
|
|
||||||
## Build and run instructions:
|
|
||||||
|
|
||||||
###To run with Arduino Ethernet (W5100) shield:
|
|
||||||
1. Add (Sketch->Add file...) the following files to sketch:
|
|
||||||
- /mongoose/mongoose.h
|
|
||||||
- /mongoose/mongoose.c
|
|
||||||
- /mongoose/platforms/arduino_ethernet_W5100/avrsupport.h
|
|
||||||
- /mongoose/platforms/arduino_ethernet_W5100/avrsupport.cpp
|
|
||||||
2. Make `board_ip` and `board_mac` variables suitable for your network and board
|
|
||||||
3. Uncomment line `#include <Ethernet.h>`
|
|
||||||
4. Compile and flash sketch
|
|
||||||
5. Run `curl http://<board_ip/blink`
|
|
||||||
LED attached to PIN 13 will blink and board free memory size and board uptime will be displayed.
|
|
||||||
|
|
||||||
|
|
||||||
###To run with Adafruit WiFi (CC3000) shield:
|
|
||||||
1. Add (Sketch->Add files...) the following files to sketch:
|
|
||||||
- /mongoose/mongoose.h
|
|
||||||
- /mongoose/mongoose.c
|
|
||||||
- /mongoose/platforms/arduino_ethernet_W5100/avrsupport.h
|
|
||||||
- /mongoose/platforms/arduino_ethernet_W5100/avrsupport.cpp
|
|
||||||
2. Import Adafruit CC3000 library for mongoose
|
|
||||||
(select Sketch->Import Library...->Add library... and point
|
|
||||||
/mongoose/platforms/arduino_wifi_CC3000/adafruit_CC3000_lib_mongoose folder)
|
|
||||||
3. Make the following variables suitable for your network
|
|
||||||
- `board_ip`
|
|
||||||
- `subnet_mask`
|
|
||||||
- `gateway`
|
|
||||||
- `dns`
|
|
||||||
- `wlan_ssid`
|
|
||||||
- `wlan_pwd`
|
|
||||||
- `wlan_security`
|
|
||||||
5. Uncomment line `#include <Adafruit_CC3000.h>`
|
|
||||||
4. Compile and flash sketch
|
|
||||||
5. Run curl `http://<board_ip/blink`
|
|
||||||
LED attached to PIN 13 will blink and board free memory size and board uptime will be displayed.
|
|
||||||
@@ -1,133 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2015 Cesanta Software Limited
|
|
||||||
* All rights reserved
|
|
||||||
*
|
|
||||||
* Build and run instructions:
|
|
||||||
* To run with Arduino Ethernet (W5100) shield:
|
|
||||||
* -----------------------------------------------------------
|
|
||||||
* 1. Add (Sketch->Add file...) the following files to sketch:
|
|
||||||
* - /mongoose/mongoose.h
|
|
||||||
* - /mongoose/mongoose.c
|
|
||||||
* - /mongoose/platforms/arduino_ethernet_W5100/avrsupport.h
|
|
||||||
* - /mongoose/platforms/arduino_ethernet_W5100/avrsupport.cpp
|
|
||||||
* 2. Make board_ip and board_mac variables suitable for your network and board
|
|
||||||
* 3. Uncomment line #include <Ethernet.h>
|
|
||||||
* 4. Compile & flash sketch
|
|
||||||
* 5. Run curl http://<board_ip/blink
|
|
||||||
* LED attached to PIN 13 will blink and board free memory size and uptime will responsed
|
|
||||||
*
|
|
||||||
* To run with Adafruit WiFi (CC3000) shield:
|
|
||||||
* -----------------------------------------------------------
|
|
||||||
* 1. Add (Sketch->Add files...) the following files to sketch:
|
|
||||||
* - /mongoose/mongoose.h
|
|
||||||
* - /mongoose/mongoose.c
|
|
||||||
* - /mongoose/platforms/arduino_ethernet_W5100/avrsupport.h
|
|
||||||
* - /mongoose/platforms/arduino_ethernet_W5100/avrsupport.cpp
|
|
||||||
* 2. Import Adafruit CC3000 library for mongoose (select Sketch->Import Library...->Add library... and point
|
|
||||||
* /mongoose/platforms/arduino_wifi_CC3000/adafruit_CC3000_lib_mongoose folder
|
|
||||||
* 3. Make the following variables suitable for your network
|
|
||||||
* - board_ip
|
|
||||||
* - subnet_mask
|
|
||||||
* - gateway
|
|
||||||
* - dns
|
|
||||||
* - wlan_ssid
|
|
||||||
* - wlan_pwd
|
|
||||||
* - wlan_security
|
|
||||||
* 5. Uncomment line #include <Adafruit_CC3000.h>
|
|
||||||
* 4. Compile & flash sketch
|
|
||||||
* 5. Run curl http://<board_ip/blink
|
|
||||||
* LED attached to PIN 13 will blink and board free memory size and uptime will responsed
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
//#include <Ethernet.h>
|
|
||||||
//#include <Adafruit_CC3000.h>
|
|
||||||
#include <SPI.h>
|
|
||||||
#include "mongoose.h"
|
|
||||||
|
|
||||||
// CHANGE THESE VARIABLES
|
|
||||||
// NB: Devices with the same address must not end up on the same network.
|
|
||||||
// Use MAC address provided by device manufacturer (e.g. on a sticker).
|
|
||||||
// If there isn't one, use a random one from the locally administered range.
|
|
||||||
// See http://en.wikipedia.org/wiki/MAC_address for details.
|
|
||||||
static uint8_t board_mac[] = {
|
|
||||||
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
|
|
||||||
};
|
|
||||||
|
|
||||||
static uint8_t board_ip[] = {192, 168, 10, 8};
|
|
||||||
|
|
||||||
#ifdef WIFI_CC3000
|
|
||||||
static uint8_t subnet_mask[] = {255, 255, 255, 0};
|
|
||||||
static uint8_t gateway[] = {192, 168, 10, 254};
|
|
||||||
static uint8_t dmg_ip[] = {192, 168, 10, 254};
|
|
||||||
|
|
||||||
static const char *wlan_ssid = "mynetwork";
|
|
||||||
static const char *wlan_pwd = "mypassword";
|
|
||||||
static int wlan_security = WLAN_SEC_WPA2;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
///////////////////////////////////////////////
|
|
||||||
|
|
||||||
static const char *s_http_port = "60000";
|
|
||||||
|
|
||||||
static uint32_t IP2U32(uint8_t* iparr) {
|
|
||||||
return ((uint32_t)iparr[0] << 24) | ((uint32_t)iparr[1] << 16) | (iparr[2] << 8) | (iparr[3]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void rfs_ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
|
|
||||||
struct http_message *hm = (struct http_message *) ev_data;
|
|
||||||
char buf[100];
|
|
||||||
int clen;
|
|
||||||
|
|
||||||
switch (ev) {
|
|
||||||
case NS_HTTP_REQUEST:
|
|
||||||
if (mg_vcmp(&hm->uri, "/blink") == 0) {
|
|
||||||
blink(1, 500);
|
|
||||||
}
|
|
||||||
|
|
||||||
clen = snprintf(buf, sizeof(buf),
|
|
||||||
"Free memory size: %d Uptime: %d",
|
|
||||||
(int)get_freememsize(), (int)time(NULL));
|
|
||||||
|
|
||||||
mg_printf_http_chunk(nc, "HTTP/1.1 200 OK\r\n"
|
|
||||||
"Content-Length: %d\r\n"
|
|
||||||
"Transfer-Encoding: chunked\r\n\r\n"
|
|
||||||
"%s",
|
|
||||||
clen, buf);
|
|
||||||
|
|
||||||
mg_send_http_chunk(nc, "", 0);
|
|
||||||
break;
|
|
||||||
case NS_SEND:
|
|
||||||
nc->flags |= MG_F_CLOSE_IMMEDIATELY;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct mg_connection *nc;
|
|
||||||
static struct mg_mgr mgr;
|
|
||||||
|
|
||||||
void setup() {
|
|
||||||
Serial.begin(9600);
|
|
||||||
Serial.println("Initialization...");
|
|
||||||
#if defined(ETHERNET_W5100)
|
|
||||||
avr_netinit(board_mac, board_ip);
|
|
||||||
#elif defined(WIFI_CC3000)
|
|
||||||
if (avr_netinit(wlan_ssid, wlan_pwd, wlan_security, IP2U32(board_ip),
|
|
||||||
IP2U32(subnet_mask), IP2U32(gateway), IP2U32(dmg_ip)) != 0) {
|
|
||||||
Serial.println("Initialization error, check network settings");
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
mg_mgr_init(&mgr, NULL);
|
|
||||||
nc = mg_bind(&mgr, s_http_port, rfs_ev_handler);
|
|
||||||
mg_set_protocol_http_websocket(nc);
|
|
||||||
Serial.println("Initialization done");
|
|
||||||
}
|
|
||||||
|
|
||||||
void loop() {
|
|
||||||
mg_mgr_poll(&mgr, 1000);
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
PROG ?= example
|
||||||
|
CFLAGS ?= -DMG_IO_SIZE=8192 -DMG_ENABLE_LINES
|
||||||
|
|
||||||
|
all: $(PROG)
|
||||||
|
$(DEBUGGER) ./$(PROG) $(ARGS)
|
||||||
|
|
||||||
|
$(PROG): main.c
|
||||||
|
$(CC) ../../mongoose.c -I../.. -W -Wall $(CFLAGS) -o $(PROG) main.c
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf $(PROG) *.o *.dSYM *.gcov *.gcno *.gcda *.obj *.exe *.ilk *.pdb
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
// Copyright (c) 2020 Cesanta Software Limited
|
||||||
|
// All rights reserved
|
||||||
|
//
|
||||||
|
// Example captive DNS server (captive portal).
|
||||||
|
// 1. Run `make`. This builds and starts a server on port 5533
|
||||||
|
// 2. Run `dig -t A www.google.com -4 @localhost -p 5533`
|
||||||
|
|
||||||
|
#include "mongoose.h"
|
||||||
|
|
||||||
|
static const char *s_listen_url = "udp://0.0.0.0:5533";
|
||||||
|
|
||||||
|
// DNS answer section. We response with IP 1.2.3.4 - you can change it
|
||||||
|
// in the last 4 bytes of this array
|
||||||
|
uint8_t answer[] = {
|
||||||
|
0xc0, 0x0c, // Point to the name in the DNS question
|
||||||
|
0, 1, // 2 bytes - record type, A
|
||||||
|
0, 1, // 2 bytes - address class, INET
|
||||||
|
0, 0, 0, 120, // 4 bytes - TTL
|
||||||
|
0, 4, // 2 bytes - address length
|
||||||
|
1, 2, 3, 4 // 4 bytes - IP address
|
||||||
|
};
|
||||||
|
|
||||||
|
static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
|
||||||
|
if (ev == MG_EV_READ) {
|
||||||
|
struct mg_dns_rr rr; // Parse first question, offset 12 is header size
|
||||||
|
size_t n = mg_dns_parse_rr(c->recv.buf, c->recv.len, 12, true, &rr);
|
||||||
|
if (n > 0) {
|
||||||
|
char buf[12 + n + sizeof(answer)];
|
||||||
|
struct mg_dns_header *h = (struct mg_dns_header *) buf;
|
||||||
|
memset(buf, 0, sizeof(buf)); // Clear the whole datagram
|
||||||
|
h->txnid = ((struct mg_dns_header *) c->recv.buf)->txnid; // Copy tnxid
|
||||||
|
h->num_questions = mg_htons(1); // We use only the 1st question
|
||||||
|
h->num_answers = mg_htons(1); // And only one answer
|
||||||
|
h->flags = mg_htons(0x8400); // Authoritative response
|
||||||
|
memcpy(buf + sizeof(*h), c->recv.buf + sizeof(*h), n); // Copy question
|
||||||
|
memcpy(buf + sizeof(*h) + n, answer, sizeof(answer)); // And answer
|
||||||
|
mg_send(c, buf, sizeof(buf)); // And send it!
|
||||||
|
}
|
||||||
|
mg_iobuf_delete(&c->recv, c->recv.len);
|
||||||
|
}
|
||||||
|
(void) fn_data;
|
||||||
|
(void) ev_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
struct mg_mgr mgr;
|
||||||
|
|
||||||
|
mg_log_set("3"); // Set log level
|
||||||
|
mg_mgr_init(&mgr); // Initialise event manager
|
||||||
|
mg_listen(&mgr, s_listen_url, fn, NULL); // Start DNS server
|
||||||
|
for (;;) mg_mgr_poll(&mgr, 1000); // Event loop
|
||||||
|
mg_mgr_free(&mgr);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
PROG = captive_dns_server
|
|
||||||
MODULE_CFLAGS=-DMG_ENABLE_DNS_SERVER
|
|
||||||
|
|
||||||
include ../rules.mk
|
|
||||||
@@ -1,82 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2014 Cesanta Software Limited
|
|
||||||
* All rights reserved
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Try it out with:
|
|
||||||
* $ dig -t A www.google.com -4 @localhost -p 5533
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "../../mongoose.h"
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
static int s_exit_flag = 0;
|
|
||||||
static in_addr_t s_our_ip_addr;
|
|
||||||
static const char *s_listening_addr = "udp://:5533";
|
|
||||||
|
|
||||||
static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
|
|
||||||
struct mg_dmg_message *msg;
|
|
||||||
struct mg_dmg_resource_record *rr;
|
|
||||||
struct mg_dmg_reply reply;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
switch (ev) {
|
|
||||||
case MG_DNS_MESSAGE:
|
|
||||||
msg = (struct mg_dmg_message *) ev_data;
|
|
||||||
reply = mg_dmg_create_reply(&nc->send_mbuf, msg);
|
|
||||||
|
|
||||||
for (i = 0; i < msg->num_questions; i++) {
|
|
||||||
rr = &msg->questions[i];
|
|
||||||
if (rr->rtype == MG_DNS_A_RECORD) {
|
|
||||||
mg_dmg_reply_record(&reply, rr, NULL, rr->rtype, 3600,
|
|
||||||
&s_our_ip_addr, 4);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We don't set the error flag even if there were no answers
|
|
||||||
* maching the MG_DNS_A_RECORD query type.
|
|
||||||
* This indicates that we have (syntetic) answers for MG_DNS_A_RECORD.
|
|
||||||
* See http://goo.gl/QWvufr for a distinction between NXDOMAIN and NODATA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
mg_dmg_send_reply(nc, &reply);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
|
||||||
struct mg_mgr mgr;
|
|
||||||
struct mg_connection *nc;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
mg_mgr_init(&mgr, NULL);
|
|
||||||
s_our_ip_addr = inet_addr("127.0.0.1");
|
|
||||||
|
|
||||||
/* Parse command line arguments */
|
|
||||||
for (i = 1; i < argc; i++) {
|
|
||||||
if (strcmp(argv[i], "-D") == 0) {
|
|
||||||
mgr.hexdump_file = argv[++i];
|
|
||||||
} else if (strcmp(argv[i], "-l") == 0 && i + 1 < argc) {
|
|
||||||
s_listening_addr = argv[++i];
|
|
||||||
} else {
|
|
||||||
s_our_ip_addr = inet_addr(argv[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(stderr, "Listening on '%s'\n", s_listening_addr);
|
|
||||||
if ((nc = mg_bind(&mgr, s_listening_addr, ev_handler)) == NULL) {
|
|
||||||
fprintf(stderr, "cannot bind to socket\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
mg_set_protocol_dns(nc);
|
|
||||||
|
|
||||||
while (s_exit_flag == 0) {
|
|
||||||
mg_mgr_poll(&mgr, 1000);
|
|
||||||
}
|
|
||||||
mg_mgr_free(&mgr);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
PROG = coap_client
|
|
||||||
SOURCES = $(PROG).c ../../mongoose.c
|
|
||||||
CFLAGS = -W -Wall -I../.. $(CFLAGS_EXTRA) -DMG_ENABLE_COAP
|
|
||||||
|
|
||||||
all: $(PROG)
|
|
||||||
|
|
||||||
$(PROG): $(SOURCES)
|
|
||||||
$(CC) $(SOURCES) -o $@ $(CFLAGS)
|
|
||||||
|
|
||||||
$(PROG).exe: $(SOURCES)
|
|
||||||
cl $(SOURCES) /I../.. /MD /Fe$@
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -rf *.gc* *.dSYM *.exe *.obj *.o a.out $(PROG)
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2015 Cesanta Software Limited
|
|
||||||
* All rights reserved
|
|
||||||
*
|
|
||||||
* This program sends CoAP CON-message to server (coap.me by default)
|
|
||||||
* and waits for answer.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "mongoose.h"
|
|
||||||
|
|
||||||
static int s_time_to_exit = 0;
|
|
||||||
static char* s_default_address = "udp://coap.me:5683";
|
|
||||||
|
|
||||||
static void coap_handler(struct mg_connection *nc, int ev, void *p) {
|
|
||||||
switch (ev) {
|
|
||||||
case MG_EV_CONNECT: {
|
|
||||||
struct mg_coap_message cm;
|
|
||||||
uint32_t res;
|
|
||||||
|
|
||||||
memset(&cm, 0, sizeof(cm));
|
|
||||||
cm.msg_id = 1;
|
|
||||||
cm.msg_type = MG_COAP_MSG_CON;
|
|
||||||
printf("Sending CON...\n");
|
|
||||||
res = mg_coap_send_message(nc, &cm);
|
|
||||||
if (res == 0) {
|
|
||||||
printf("Sent CON with msg_id = %d\n", cm.msg_id);
|
|
||||||
} else {
|
|
||||||
printf("Error: %d\n", res);
|
|
||||||
s_time_to_exit = 1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MG_EV_COAP_ACK:
|
|
||||||
case MG_EV_COAP_RST: {
|
|
||||||
struct mg_coap_message *cm = (struct mg_coap_message *)p;
|
|
||||||
printf("ACK/RST for message with msg_id = %d received\n",
|
|
||||||
cm->msg_id);
|
|
||||||
s_time_to_exit = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
|
||||||
struct mg_mgr mgr;
|
|
||||||
struct mg_connection *nc;
|
|
||||||
char *address = s_default_address;
|
|
||||||
|
|
||||||
if (argc > 1) {
|
|
||||||
address = argv[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("Using %s as CoAP server\n", address);
|
|
||||||
|
|
||||||
mg_mgr_init(&mgr, 0);
|
|
||||||
|
|
||||||
nc = mg_connect(&mgr, address, coap_handler);
|
|
||||||
if (nc == NULL) {
|
|
||||||
printf("Unable to connect to %s\n", address);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
mg_set_protocol_coap(nc);
|
|
||||||
|
|
||||||
while (!s_time_to_exit) {
|
|
||||||
mg_mgr_poll(&mgr, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
mg_mgr_free(&mgr);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
PROG = coap_server
|
|
||||||
SOURCES = $(PROG).c ../../mongoose.c
|
|
||||||
CFLAGS = -W -Wall -I../.. $(CFLAGS_EXTRA) -DMG_ENABLE_COAP
|
|
||||||
|
|
||||||
all: $(PROG)
|
|
||||||
|
|
||||||
$(PROG): $(SOURCES)
|
|
||||||
$(CC) $(SOURCES) -o $@ $(CFLAGS)
|
|
||||||
|
|
||||||
$(PROG).exe: $(SOURCES)
|
|
||||||
cl $(SOURCES) /I../.. /MD /Fe$@
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -rf *.gc* *.dSYM *.exe *.obj *.o a.out $(PROG)
|
|
||||||
@@ -1,73 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2015 Cesanta Software Limited
|
|
||||||
* All rights reserved
|
|
||||||
*
|
|
||||||
* This program listens on 5683 for CoAP messages,
|
|
||||||
* sends ACK is nessesary and dump everything received.
|
|
||||||
* It is possible to use ../coap_client to send message.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "mongoose.h"
|
|
||||||
|
|
||||||
static char* s_default_address = "udp://:5683";
|
|
||||||
static int s_sig_received = 0;
|
|
||||||
|
|
||||||
static void signal_handler(int sig_num) {
|
|
||||||
signal(sig_num, signal_handler);
|
|
||||||
s_sig_received = sig_num;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void coap_handler(struct mg_connection *nc, int ev, void *p) {
|
|
||||||
switch (ev) {
|
|
||||||
case MG_EV_COAP_CON: {
|
|
||||||
uint32_t res;
|
|
||||||
struct mg_coap_message *cm = (struct mg_coap_message *)p;
|
|
||||||
printf("CON with msg_id = %d received\n", cm->msg_id);
|
|
||||||
res = mg_coap_send_ack(nc, cm->msg_id);
|
|
||||||
if (res == 0) {
|
|
||||||
printf("Successfully sent ACK for message with msg_id = %d\n",
|
|
||||||
cm->msg_id);
|
|
||||||
} else {
|
|
||||||
printf("Error: %d\n", res);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MG_EV_COAP_NOC:
|
|
||||||
case MG_EV_COAP_ACK:
|
|
||||||
case MG_EV_COAP_RST: {
|
|
||||||
struct mg_coap_message *cm = (struct mg_coap_message *)p;
|
|
||||||
printf("ACK/RST/NOC with msg_id = %d received\n",
|
|
||||||
cm->msg_id);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
struct mg_mgr mgr;
|
|
||||||
struct mg_connection *nc;
|
|
||||||
|
|
||||||
signal(SIGTERM, signal_handler);
|
|
||||||
signal(SIGINT, signal_handler);
|
|
||||||
|
|
||||||
mg_mgr_init(&mgr, 0);
|
|
||||||
|
|
||||||
nc = mg_bind(&mgr, s_default_address, coap_handler);
|
|
||||||
if (nc == NULL) {
|
|
||||||
printf("Unable to start listener at %s\n", s_default_address);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("Listening for CoAP messages at %s\n", s_default_address);
|
|
||||||
|
|
||||||
mg_set_protocol_coap(nc);
|
|
||||||
|
|
||||||
while (!s_sig_received) {
|
|
||||||
mg_mgr_poll(&mgr, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("Exiting on signal %d\n", s_sig_received);
|
|
||||||
|
|
||||||
mg_mgr_free(&mgr);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
PROG ?= example
|
||||||
|
|
||||||
|
all: $(PROG)
|
||||||
|
$(DEBUGGER) ./$(PROG)
|
||||||
|
|
||||||
|
$(PROG):
|
||||||
|
$(CC) ../../mongoose.c -I../.. $(CFLAGS) $(EXTRA) -o $(PROG) main.c mjson.c
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf $(PROG) *.o *.dSYM *.gcov *.gcno *.gcda *.obj *.exe *.ilk *.pdb log.txt
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
# A complete device dashboard
|
||||||
|
|
||||||
|
This example is a demonstration of how Mongoose Library could be integrated
|
||||||
|
into an embedded device and provide a complete device dashbord with the
|
||||||
|
following features:
|
||||||
|
|
||||||
|
- Multiple logins with different permissions (admin and user)
|
||||||
|
- Login screen for non-authenticated connections
|
||||||
|
- A [preact](https://preactjs.com/)-based dashboard with multiple pages
|
||||||
|
- Internal variables
|
||||||
|
- A form that changes those variables
|
||||||
|
- All changes are propagates to all connected clients
|
||||||
|
- Live log stream
|
||||||
|
- Live video stream
|
||||||
|
|
||||||
|
|
||||||
|
In essense, this example is a combination of several other examples
|
||||||
|
pulled together (multiple-logins, dashboard, live-log, video-stream).
|
||||||
|
|
||||||
|
# Screenshots
|
||||||
|
|
||||||
|
This is a login screen that prompts for user/password
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
# Main dashboard
|
||||||
|
|
||||||
|
A main dashboard page shows internal data, live video stream, and a form
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
A live log page shows live log stream coming from device
|
||||||
|
|
||||||
|

|
||||||
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 9.8 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 9.7 KiB |
|
After Width: | Height: | Size: 10 KiB |
@@ -0,0 +1,204 @@
|
|||||||
|
// Copyright (c) 2020 Cesanta Software Limited
|
||||||
|
// All rights reserved
|
||||||
|
|
||||||
|
#include "mjson.h"
|
||||||
|
#include "mongoose.h"
|
||||||
|
|
||||||
|
// Authenticated user.
|
||||||
|
// A user can be authenticated by:
|
||||||
|
// - a name:pass pair
|
||||||
|
// - a token
|
||||||
|
// When a user is shown a login screen, she enters a user:pass. If successful,
|
||||||
|
// a server returns user info which includes token. From that point on,
|
||||||
|
// client can use token for authentication. Tokens could be refreshed/changed
|
||||||
|
// on a server side, forcing clients to re-login.
|
||||||
|
struct user {
|
||||||
|
const char *name, *pass, *token;
|
||||||
|
};
|
||||||
|
|
||||||
|
// This is a configuration structure we're going to show on a dashboard
|
||||||
|
static struct config {
|
||||||
|
int value1;
|
||||||
|
char *value2;
|
||||||
|
} s_config = {123, NULL};
|
||||||
|
|
||||||
|
// Stringifies the config. A caller must free() it.
|
||||||
|
static char *stringify_config(struct config *cfg) {
|
||||||
|
char *s = NULL;
|
||||||
|
mjson_printf(mjson_print_dynamic_buf, &s, "{%Q:%d,%Q:%Q}", "value1",
|
||||||
|
cfg->value1, "value2", cfg->value2);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update config structure. Return true if changed, false otherwise
|
||||||
|
static bool update_config(struct mg_http_message *hm, struct config *cfg) {
|
||||||
|
bool changed = false;
|
||||||
|
char buf[256];
|
||||||
|
double dv;
|
||||||
|
if (mjson_get_number(hm->body.ptr, hm->body.len, "$.value1", &dv)) {
|
||||||
|
s_config.value1 = dv;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
if (mjson_get_string(hm->body.ptr, hm->body.len, "$.value2", buf,
|
||||||
|
sizeof(buf)) > 0) {
|
||||||
|
free(s_config.value2);
|
||||||
|
s_config.value2 = strdup(buf);
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse HTTP requests, return authenticated user or NULL
|
||||||
|
static struct user *getuser(struct mg_http_message *hm) {
|
||||||
|
// In production, make passwords strong and tokens randomly generated
|
||||||
|
// In this example, user list is kept in RAM. In production, it can
|
||||||
|
// be backed by file, database, or some other method.
|
||||||
|
static struct user users[] = {
|
||||||
|
{"admin", "admin", "admin_token"},
|
||||||
|
{"user1", "pass1", "user1_token"},
|
||||||
|
{"user2", "pass2", "user2_token"},
|
||||||
|
{NULL, NULL, NULL},
|
||||||
|
};
|
||||||
|
char user[256], pass[256];
|
||||||
|
struct user *u;
|
||||||
|
mg_http_creds(hm, user, sizeof(user), pass, sizeof(pass));
|
||||||
|
if (user[0] != '\0' && pass[0] != '\0') {
|
||||||
|
// Both user and password is set, search by user/password
|
||||||
|
for (u = users; u->name != NULL; u++)
|
||||||
|
if (strcmp(user, u->name) == 0 && strcmp(pass, u->pass) == 0) return u;
|
||||||
|
} else if (user[0] == '\0') {
|
||||||
|
// Only password is set, search by token
|
||||||
|
for (u = users; u->name != NULL; u++)
|
||||||
|
if (strcmp(pass, u->token) == 0) return u;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Notify all config watchers about the config change
|
||||||
|
static void notify_config_change(struct mg_mgr *mgr) {
|
||||||
|
struct mg_connection *c;
|
||||||
|
char *s = stringify_config(&s_config);
|
||||||
|
for (c = mgr->conns; c != NULL; c = c->next) {
|
||||||
|
if (c->label[0] == 'W') mg_http_printf_chunk(c, "%s\n", s);
|
||||||
|
}
|
||||||
|
free(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
// HTTP request handler function
|
||||||
|
static void cb(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
|
||||||
|
if (ev == MG_EV_HTTP_MSG) {
|
||||||
|
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||||
|
struct user *u = getuser(hm);
|
||||||
|
// LOG(LL_INFO, ("%p [%.*s] auth %s", c->fd, (int) hm->uri.len, hm->uri.ptr,
|
||||||
|
// u ? u->name : "NULL"));
|
||||||
|
if (u == NULL && mg_http_match_uri(hm, "/api/#")) {
|
||||||
|
// All URIs starting with /api/ must be authenticated
|
||||||
|
mg_printf(c, "%s", "HTTP/1.1 403 Denied\r\nContent-Length: 0\r\n\r\n");
|
||||||
|
} else if (mg_http_match_uri(hm, "/api/config/get")) {
|
||||||
|
char *s = stringify_config(&s_config);
|
||||||
|
mg_printf(c, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\n\r\n%s\n",
|
||||||
|
(int) strlen(s) + 1, s);
|
||||||
|
free(s);
|
||||||
|
} else if (mg_http_match_uri(hm, "/api/config/set")) {
|
||||||
|
// Admins only
|
||||||
|
if (strcmp(u->name, "admin") == 0) {
|
||||||
|
if (update_config(hm, &s_config)) notify_config_change(fn_data);
|
||||||
|
mg_printf(c, "HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n");
|
||||||
|
} else {
|
||||||
|
mg_printf(c, "%s", "HTTP/1.1 403 Denied\r\nContent-Length: 0\r\n\r\n");
|
||||||
|
}
|
||||||
|
} else if (mg_http_match_uri(hm, "/api/config/watch")) {
|
||||||
|
c->label[0] = 'W'; // Mark ourselves as a config watcher
|
||||||
|
mg_printf(c, "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n");
|
||||||
|
} else if (mg_http_match_uri(hm, "/api/video1")) {
|
||||||
|
c->label[0] = 'S'; // Mark that connection as live streamer
|
||||||
|
mg_printf(
|
||||||
|
c, "%s",
|
||||||
|
"HTTP/1.0 200 OK\r\n"
|
||||||
|
"Cache-Control: no-cache\r\n"
|
||||||
|
"Pragma: no-cache\r\nExpires: Thu, 01 Dec 1994 16:00:00 GMT\r\n"
|
||||||
|
"Content-Type: multipart/x-mixed-replace; boundary=--foo\r\n\r\n");
|
||||||
|
} else if (mg_http_match_uri(hm, "/api/log/static")) {
|
||||||
|
mg_http_serve_file(c, hm, "log.txt", "text/plain", "");
|
||||||
|
} else if (mg_http_match_uri(hm, "/api/log/live")) {
|
||||||
|
c->label[0] = 'L'; // Mark that connection as live log listener
|
||||||
|
mg_printf(c, "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n");
|
||||||
|
} else if (mg_http_match_uri(hm, "/api/login")) {
|
||||||
|
mg_printf(c, "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n");
|
||||||
|
mg_http_printf_chunk(c, "{\"user\":\"%s\",\"token\":\"%s\"}\n", u->name,
|
||||||
|
u->token);
|
||||||
|
mg_http_printf_chunk(c, "");
|
||||||
|
} else {
|
||||||
|
struct mg_http_serve_opts opts = {.root_dir = "web_root"};
|
||||||
|
mg_http_serve_dir(c, ev_data, &opts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The image stream is simulated by sending MJPEG frames specified by the
|
||||||
|
// "files" array of file names.
|
||||||
|
static void broadcast_mjpeg_frame(struct mg_mgr *mgr) {
|
||||||
|
const char *files[] = {"images/1.jpg", "images/2.jpg", "images/3.jpg",
|
||||||
|
"images/4.jpg", "images/5.jpg", "images/6.jpg"};
|
||||||
|
size_t nfiles = sizeof(files) / sizeof(files[0]);
|
||||||
|
static size_t i;
|
||||||
|
const char *path = files[i++ % nfiles];
|
||||||
|
size_t size = mg_file_size(path);
|
||||||
|
char *data = mg_file_read(path); // Read next file
|
||||||
|
struct mg_connection *c;
|
||||||
|
for (c = mgr->conns; c != NULL; c = c->next) {
|
||||||
|
if (c->label[0] != 'S') continue; // Skip non-stream connections
|
||||||
|
if (data == NULL || size == 0) continue; // Skip on file read error
|
||||||
|
mg_printf(c,
|
||||||
|
"--foo\r\nContent-Type: image/jpeg\r\n"
|
||||||
|
"Content-Length: %lu\r\n\r\n",
|
||||||
|
(unsigned long) size);
|
||||||
|
mg_send(c, data, size);
|
||||||
|
mg_send(c, "\r\n", 2);
|
||||||
|
}
|
||||||
|
free(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mjpeg_cb(void *arg) {
|
||||||
|
broadcast_mjpeg_frame(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void log_message(const char *filename, const char *message) {
|
||||||
|
FILE *fp = fopen(filename, "a");
|
||||||
|
if (fp != NULL) {
|
||||||
|
fprintf(fp, "%s", message);
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void broadcast_message(struct mg_mgr *mgr, const char *message) {
|
||||||
|
struct mg_connection *c;
|
||||||
|
for (c = mgr->conns; c != NULL; c = c->next) {
|
||||||
|
if (c->label[0] == 'L') mg_http_printf_chunk(c, "%s", message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Timer function - called periodically.
|
||||||
|
// Prepare log message. Save it to a file, and broadcast.
|
||||||
|
static void log_cb(void *arg) {
|
||||||
|
char buf[64];
|
||||||
|
snprintf(buf, sizeof(buf), "Time is: %lu\n", (unsigned long) time(NULL));
|
||||||
|
log_message("log.txt", buf);
|
||||||
|
broadcast_message(arg, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
struct mg_mgr mgr;
|
||||||
|
struct mg_timer t1, t2;
|
||||||
|
|
||||||
|
mg_mgr_init(&mgr);
|
||||||
|
mg_http_listen(&mgr, "http://localhost:8000", cb, &mgr);
|
||||||
|
mg_timer_init(&t1, 500, MG_TIMER_REPEAT, mjpeg_cb, &mgr);
|
||||||
|
mg_timer_init(&t2, 1000, MG_TIMER_REPEAT, log_cb, &mgr);
|
||||||
|
for (;;) mg_mgr_poll(&mgr, 50);
|
||||||
|
mg_timer_free(&t1);
|
||||||
|
mg_timer_free(&t2);
|
||||||
|
mg_mgr_free(&mgr);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,981 @@
|
|||||||
|
// Copyright (c) 2018-2020 Cesanta Software Limited
|
||||||
|
// All rights reserved
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
#include "mjson.h"
|
||||||
|
|
||||||
|
#if !defined(_MSC_VER) || _MSC_VER >= 1700
|
||||||
|
#else
|
||||||
|
#define va_copy(x, y) (x) = (y)
|
||||||
|
#define snprintf _snprintf
|
||||||
|
#define alloca _alloca
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int mjson_esc(int c, int esc) {
|
||||||
|
const char *p, *esc1 = "\b\f\n\r\t\\\"", *esc2 = "bfnrt\\\"";
|
||||||
|
for (p = esc ? esc1 : esc2; *p != '\0'; p++) {
|
||||||
|
if (*p == c) return esc ? esc2[p - esc1] : esc1[p - esc2];
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mjson_pass_string(const char *s, int len) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
if (s[i] == '\\' && i + 1 < len && mjson_esc(s[i + 1], 1)) {
|
||||||
|
i++;
|
||||||
|
} else if (s[i] == '\0') {
|
||||||
|
return MJSON_ERROR_INVALID_INPUT;
|
||||||
|
} else if (s[i] == '"') {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return MJSON_ERROR_INVALID_INPUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mjson(const char *s, int len, mjson_cb_t cb, void *ud) {
|
||||||
|
enum { S_VALUE, S_KEY, S_COLON, S_COMMA_OR_EOO } expecting = S_VALUE;
|
||||||
|
unsigned char nesting[MJSON_MAX_DEPTH];
|
||||||
|
int i, depth = 0;
|
||||||
|
#define MJSONCALL(ev) \
|
||||||
|
if (cb != NULL && cb(ev, s, start, i - start + 1, ud)) return i + 1;
|
||||||
|
|
||||||
|
// In the ascii table, the distance between `[` and `]` is 2.
|
||||||
|
// Ditto for `{` and `}`. Hence +2 in the code below.
|
||||||
|
#define MJSONEOO() \
|
||||||
|
do { \
|
||||||
|
if (c != nesting[depth - 1] + 2) return MJSON_ERROR_INVALID_INPUT; \
|
||||||
|
depth--; \
|
||||||
|
if (depth == 0) { \
|
||||||
|
MJSONCALL(tok); \
|
||||||
|
return i + 1; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
int start = i;
|
||||||
|
unsigned char c = ((unsigned char *) s)[i];
|
||||||
|
int tok = c;
|
||||||
|
if (c == ' ' || c == '\t' || c == '\n' || c == '\r') continue;
|
||||||
|
// printf("- %c [%.*s] %d %d\n", c, i, s, depth, expecting);
|
||||||
|
switch (expecting) {
|
||||||
|
case S_VALUE:
|
||||||
|
if (c == '{') {
|
||||||
|
if (depth >= (int) sizeof(nesting)) return MJSON_ERROR_TOO_DEEP;
|
||||||
|
nesting[depth++] = c;
|
||||||
|
expecting = S_KEY;
|
||||||
|
break;
|
||||||
|
} else if (c == '[') {
|
||||||
|
if (depth >= (int) sizeof(nesting)) return MJSON_ERROR_TOO_DEEP;
|
||||||
|
nesting[depth++] = c;
|
||||||
|
break;
|
||||||
|
} else if (c == ']' && depth > 0) { // Empty array
|
||||||
|
MJSONEOO();
|
||||||
|
} else if (c == 't' && i + 3 < len && memcmp(&s[i], "true", 4) == 0) {
|
||||||
|
i += 3;
|
||||||
|
tok = MJSON_TOK_TRUE;
|
||||||
|
} else if (c == 'n' && i + 3 < len && memcmp(&s[i], "null", 4) == 0) {
|
||||||
|
i += 3;
|
||||||
|
tok = MJSON_TOK_NULL;
|
||||||
|
} else if (c == 'f' && i + 4 < len && memcmp(&s[i], "false", 5) == 0) {
|
||||||
|
i += 4;
|
||||||
|
tok = MJSON_TOK_FALSE;
|
||||||
|
} else if (c == '-' || ((c >= '0' && c <= '9'))) {
|
||||||
|
char *end = NULL;
|
||||||
|
strtod(&s[i], &end);
|
||||||
|
if (end != NULL) i += end - &s[i] - 1;
|
||||||
|
tok = MJSON_TOK_NUMBER;
|
||||||
|
} else if (c == '"') {
|
||||||
|
int n = mjson_pass_string(&s[i + 1], len - i - 1);
|
||||||
|
if (n < 0) return n;
|
||||||
|
i += n + 1;
|
||||||
|
tok = MJSON_TOK_STRING;
|
||||||
|
} else {
|
||||||
|
return MJSON_ERROR_INVALID_INPUT;
|
||||||
|
}
|
||||||
|
if (depth == 0) {
|
||||||
|
MJSONCALL(tok);
|
||||||
|
return i + 1;
|
||||||
|
}
|
||||||
|
expecting = S_COMMA_OR_EOO;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case S_KEY:
|
||||||
|
if (c == '"') {
|
||||||
|
int n = mjson_pass_string(&s[i + 1], len - i - 1);
|
||||||
|
if (n < 0) return n;
|
||||||
|
i += n + 1;
|
||||||
|
tok = MJSON_TOK_KEY;
|
||||||
|
expecting = S_COLON;
|
||||||
|
} else if (c == '}') { // Empty object
|
||||||
|
MJSONEOO();
|
||||||
|
expecting = S_COMMA_OR_EOO;
|
||||||
|
} else {
|
||||||
|
return MJSON_ERROR_INVALID_INPUT;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case S_COLON:
|
||||||
|
if (c == ':') {
|
||||||
|
expecting = S_VALUE;
|
||||||
|
} else {
|
||||||
|
return MJSON_ERROR_INVALID_INPUT;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case S_COMMA_OR_EOO:
|
||||||
|
if (depth <= 0) return MJSON_ERROR_INVALID_INPUT;
|
||||||
|
if (c == ',') {
|
||||||
|
expecting = (nesting[depth - 1] == '{') ? S_KEY : S_VALUE;
|
||||||
|
} else if (c == ']' || c == '}') {
|
||||||
|
MJSONEOO();
|
||||||
|
} else {
|
||||||
|
return MJSON_ERROR_INVALID_INPUT;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
MJSONCALL(tok);
|
||||||
|
}
|
||||||
|
return MJSON_ERROR_INVALID_INPUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct msjon_get_data {
|
||||||
|
const char *path; // Lookup json path
|
||||||
|
int pos; // Current path index
|
||||||
|
int d1; // Current depth of traversal
|
||||||
|
int d2; // Expected depth of traversal
|
||||||
|
int i1; // Index in an array
|
||||||
|
int i2; // Expected index in an array
|
||||||
|
int obj; // If the value is array/object, offset where it starts
|
||||||
|
const char **tokptr; // Destination
|
||||||
|
int *toklen; // Destination length
|
||||||
|
int tok; // Returned token
|
||||||
|
};
|
||||||
|
|
||||||
|
static int mjson_plen(const char *s) {
|
||||||
|
int i = 0;
|
||||||
|
while (s[i] != '\0' && s[i] != '.' && s[i] != '[') i++;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mjson_get_cb(int tok, const char *s, int off, int len, void *ud) {
|
||||||
|
struct msjon_get_data *data = (struct msjon_get_data *) ud;
|
||||||
|
// printf("--> %2x %2d %2d %2d %2d\t'%s'\t'%.*s'\t\t'%.*s'\n", tok, data->d1,
|
||||||
|
// data->d2, data->i1, data->i2, data->path + data->pos, off, s, len,
|
||||||
|
// s + off);
|
||||||
|
if (data->tok != MJSON_TOK_INVALID) return 1; // Found
|
||||||
|
|
||||||
|
if (tok == '{') {
|
||||||
|
if (!data->path[data->pos] && data->d1 == data->d2) data->obj = off;
|
||||||
|
data->d1++;
|
||||||
|
} else if (tok == '[') {
|
||||||
|
if (data->d1 == data->d2 && data->path[data->pos] == '[') {
|
||||||
|
data->i1 = 0;
|
||||||
|
data->i2 = (int) strtod(&data->path[data->pos + 1], NULL);
|
||||||
|
if (data->i1 == data->i2) {
|
||||||
|
data->d2++;
|
||||||
|
data->pos += 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!data->path[data->pos] && data->d1 == data->d2) data->obj = off;
|
||||||
|
data->d1++;
|
||||||
|
} else if (tok == ',') {
|
||||||
|
if (data->d1 == data->d2 + 1) {
|
||||||
|
data->i1++;
|
||||||
|
if (data->i1 == data->i2) {
|
||||||
|
while (data->path[data->pos] != ']') data->pos++;
|
||||||
|
data->pos++;
|
||||||
|
data->d2++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (tok == MJSON_TOK_KEY && data->d1 == data->d2 + 1 &&
|
||||||
|
data->path[data->pos] == '.' && s[off] == '"' &&
|
||||||
|
s[off + len - 1] == '"' &&
|
||||||
|
mjson_plen(&data->path[data->pos + 1]) == len - 2 &&
|
||||||
|
!memcmp(s + off + 1, &data->path[data->pos + 1], len - 2)) {
|
||||||
|
data->d2++;
|
||||||
|
data->pos += len - 1;
|
||||||
|
} else if (tok == MJSON_TOK_KEY && data->d1 == data->d2) {
|
||||||
|
return 1; // Exhausted path, not found
|
||||||
|
} else if (tok == '}' || tok == ']') {
|
||||||
|
data->d1--;
|
||||||
|
// data->d2--;
|
||||||
|
if (!data->path[data->pos] && data->d1 == data->d2 && data->obj != -1) {
|
||||||
|
data->tok = tok - 2;
|
||||||
|
if (data->tokptr) *data->tokptr = s + data->obj;
|
||||||
|
if (data->toklen) *data->toklen = off - data->obj + 1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} else if (MJSON_TOK_IS_VALUE(tok)) {
|
||||||
|
// printf("TOK --> %d\n", tok);
|
||||||
|
if (data->d1 == data->d2 && !data->path[data->pos]) {
|
||||||
|
data->tok = tok;
|
||||||
|
if (data->tokptr) *data->tokptr = s + off;
|
||||||
|
if (data->toklen) *data->toklen = len;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum mjson_tok mjson_find(const char *s, int len, const char *jp,
|
||||||
|
const char **tokptr, int *toklen) {
|
||||||
|
struct msjon_get_data data = {jp, 1, 0, 0, 0,
|
||||||
|
0, -1, tokptr, toklen, MJSON_TOK_INVALID};
|
||||||
|
if (jp[0] != '$') return MJSON_TOK_INVALID;
|
||||||
|
if (mjson(s, len, mjson_get_cb, &data) < 0) return MJSON_TOK_INVALID;
|
||||||
|
return (enum mjson_tok) data.tok;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mjson_get_number(const char *s, int len, const char *path, double *v) {
|
||||||
|
const char *p;
|
||||||
|
int tok, n;
|
||||||
|
if ((tok = mjson_find(s, len, path, &p, &n)) == MJSON_TOK_NUMBER) {
|
||||||
|
if (v != NULL) *v = strtod(p, NULL);
|
||||||
|
}
|
||||||
|
return tok == MJSON_TOK_NUMBER ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mjson_get_bool(const char *s, int len, const char *path, int *v) {
|
||||||
|
int tok = mjson_find(s, len, path, NULL, NULL);
|
||||||
|
if (tok == MJSON_TOK_TRUE && v != NULL) *v = 1;
|
||||||
|
if (tok == MJSON_TOK_FALSE && v != NULL) *v = 0;
|
||||||
|
return tok == MJSON_TOK_TRUE || tok == MJSON_TOK_FALSE ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mjson_unescape(const char *s, int len, char *to, int n) {
|
||||||
|
int i, j;
|
||||||
|
for (i = 0, j = 0; i < len && j < n; i++, j++) {
|
||||||
|
if (s[i] == '\\' && i + 1 < len) {
|
||||||
|
int c = mjson_esc(s[i + 1], 0);
|
||||||
|
if (c == 0) return -1;
|
||||||
|
to[j] = c;
|
||||||
|
i++;
|
||||||
|
} else {
|
||||||
|
to[j] = s[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (j >= n) return -1;
|
||||||
|
if (n > 0) to[j] = '\0';
|
||||||
|
return j;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mjson_get_string(const char *s, int len, const char *path, char *to,
|
||||||
|
int n) {
|
||||||
|
const char *p;
|
||||||
|
int sz;
|
||||||
|
if (mjson_find(s, len, path, &p, &sz) != MJSON_TOK_STRING) return -1;
|
||||||
|
return mjson_unescape(p + 1, sz - 2, to, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
int mjson_get_hex(const char *s, int len, const char *x, char *to, int n) {
|
||||||
|
const char *p;
|
||||||
|
int i, j, sz;
|
||||||
|
if (mjson_find(s, len, x, &p, &sz) != MJSON_TOK_STRING) return -1;
|
||||||
|
for (i = j = 0; i < sz - 3 && j < n; i += 2, j++) {
|
||||||
|
#define HEXTOI(x) (x >= '0' && x <= '9' ? x - '0' : x - 'W')
|
||||||
|
unsigned char a = *(const unsigned char *) (p + i + 1);
|
||||||
|
unsigned char b = *(const unsigned char *) (p + i + 2);
|
||||||
|
((unsigned char *) to)[j] = (HEXTOI(a) << 4) | HEXTOI(b);
|
||||||
|
}
|
||||||
|
if (j < n) to[j] = '\0';
|
||||||
|
return j;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if MJSON_ENABLE_BASE64
|
||||||
|
static int mjson_base64rev(int c) {
|
||||||
|
if (c >= 'A' && c <= 'Z') {
|
||||||
|
return c - 'A';
|
||||||
|
} else if (c >= 'a' && c <= 'z') {
|
||||||
|
return c + 26 - 'a';
|
||||||
|
} else if (c >= '0' && c <= '9') {
|
||||||
|
return c + 52 - '0';
|
||||||
|
} else if (c == '+') {
|
||||||
|
return 62;
|
||||||
|
} else if (c == '/') {
|
||||||
|
return 63;
|
||||||
|
} else {
|
||||||
|
return 64;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int mjson_base64_dec(const char *src, int n, char *dst, int dlen) {
|
||||||
|
const char *end = src + n;
|
||||||
|
int len = 0;
|
||||||
|
while (src + 3 < end && len < dlen) {
|
||||||
|
int a = mjson_base64rev(src[0]), b = mjson_base64rev(src[1]),
|
||||||
|
c = mjson_base64rev(src[2]), d = mjson_base64rev(src[3]);
|
||||||
|
dst[len++] = (a << 2) | (b >> 4);
|
||||||
|
if (src[2] != '=' && len < dlen) {
|
||||||
|
dst[len++] = (b << 4) | (c >> 2);
|
||||||
|
if (src[3] != '=' && len < dlen) {
|
||||||
|
dst[len++] = (c << 6) | d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
src += 4;
|
||||||
|
}
|
||||||
|
if (len < dlen) dst[len] = '\0';
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mjson_get_base64(const char *s, int len, const char *path, char *to,
|
||||||
|
int n) {
|
||||||
|
const char *p;
|
||||||
|
int sz;
|
||||||
|
if (mjson_find(s, len, path, &p, &sz) != MJSON_TOK_STRING) return 0;
|
||||||
|
return mjson_base64_dec(p + 1, sz - 2, to, n);
|
||||||
|
}
|
||||||
|
#endif // MJSON_ENABLE_BASE64
|
||||||
|
|
||||||
|
#if MJSON_ENABLE_NEXT
|
||||||
|
struct nextdata {
|
||||||
|
int off, len, depth, t, vo, arrayindex;
|
||||||
|
int *koff, *klen, *voff, *vlen, *vtype;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int next_cb(int tok, const char *s, int off, int len, void *ud) {
|
||||||
|
struct nextdata *d = (struct nextdata *) ud;
|
||||||
|
// int i;
|
||||||
|
switch (tok) {
|
||||||
|
case '{':
|
||||||
|
case '[':
|
||||||
|
if (d->depth == 0 && tok == '[') d->arrayindex = 0;
|
||||||
|
if (d->depth == 1 && off > d->off) {
|
||||||
|
d->vo = off;
|
||||||
|
d->t = tok == '{' ? MJSON_TOK_OBJECT : MJSON_TOK_ARRAY;
|
||||||
|
if (d->voff) *d->voff = off;
|
||||||
|
if (d->vtype) *d->vtype = d->t;
|
||||||
|
}
|
||||||
|
d->depth++;
|
||||||
|
break;
|
||||||
|
case '}':
|
||||||
|
case ']':
|
||||||
|
d->depth--;
|
||||||
|
if (d->depth == 1 && d->vo) {
|
||||||
|
d->len = off + len;
|
||||||
|
if (d->vlen) *d->vlen = d->len - d->vo;
|
||||||
|
if (d->arrayindex >= 0) {
|
||||||
|
if (d->koff) *d->koff = d->arrayindex; // koff holds array index
|
||||||
|
if (d->klen) *d->klen = 0; // klen holds 0
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (d->depth == 1 && d->arrayindex >= 0) d->arrayindex++;
|
||||||
|
break;
|
||||||
|
case ',':
|
||||||
|
case ':':
|
||||||
|
break;
|
||||||
|
case MJSON_TOK_KEY:
|
||||||
|
if (d->depth == 1 && d->off < off) {
|
||||||
|
if (d->koff) *d->koff = off; // And report back to the user
|
||||||
|
if (d->klen) *d->klen = len; // If we have to
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (d->depth != 1) break;
|
||||||
|
// If we're iterating over the array
|
||||||
|
if (off > d->off) {
|
||||||
|
d->len = off + len;
|
||||||
|
if (d->vlen) *d->vlen = len; // value length
|
||||||
|
if (d->voff) *d->voff = off; // value offset
|
||||||
|
if (d->vtype) *d->vtype = tok; // value type
|
||||||
|
if (d->arrayindex >= 0) {
|
||||||
|
if (d->koff) *d->koff = d->arrayindex; // koff holds array index
|
||||||
|
if (d->klen) *d->klen = 0; // klen holds 0
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (d->arrayindex >= 0) d->arrayindex++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
(void) s;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mjson_next(const char *s, int n, int off, int *koff, int *klen, int *voff,
|
||||||
|
int *vlen, int *vtype) {
|
||||||
|
struct nextdata d = {off, 0, 0, 0, 0, -1, koff, klen, voff, vlen, vtype};
|
||||||
|
mjson(s, n, next_cb, &d);
|
||||||
|
return d.len;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MJSON_ENABLE_PRINT
|
||||||
|
int mjson_print_fixed_buf(const char *ptr, int len, void *fndata) {
|
||||||
|
struct mjson_fixedbuf *fb = (struct mjson_fixedbuf *) fndata;
|
||||||
|
int i, left = fb->size - 1 - fb->len;
|
||||||
|
if (left < len) len = left;
|
||||||
|
for (i = 0; i < len; i++) fb->ptr[fb->len + i] = ptr[i];
|
||||||
|
fb->len += len;
|
||||||
|
fb->ptr[fb->len] = '\0';
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mjson_print_dynamic_buf(const char *ptr, int len, void *fndata) {
|
||||||
|
char *s, *buf = *(char **) fndata;
|
||||||
|
int curlen = buf == NULL ? 0 : strlen(buf);
|
||||||
|
if ((s = (char *) realloc(buf, curlen + len + 1)) == NULL) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
memcpy(s + curlen, ptr, len);
|
||||||
|
s[curlen + len] = '\0';
|
||||||
|
*(char **) fndata = s;
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int mjson_print_null(const char *ptr, int len, void *userdata) {
|
||||||
|
(void) ptr;
|
||||||
|
(void) userdata;
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mjson_print_file(const char *ptr, int len, void *userdata) {
|
||||||
|
return fwrite(ptr, 1, len, (FILE *) userdata);
|
||||||
|
}
|
||||||
|
|
||||||
|
int mjson_print_buf(mjson_print_fn_t fn, void *fndata, const char *buf,
|
||||||
|
int len) {
|
||||||
|
return fn(buf, len, fndata);
|
||||||
|
}
|
||||||
|
|
||||||
|
int mjson_print_int(mjson_print_fn_t fn, void *fndata, int value,
|
||||||
|
int is_signed) {
|
||||||
|
char buf[20];
|
||||||
|
int len = snprintf(buf, sizeof(buf), is_signed ? "%d" : "%u", value);
|
||||||
|
return fn(buf, len, fndata);
|
||||||
|
}
|
||||||
|
|
||||||
|
int mjson_print_long(mjson_print_fn_t fn, void *fndata, long value,
|
||||||
|
int is_signed) {
|
||||||
|
char buf[20];
|
||||||
|
const char *fmt = (is_signed ? "%ld" : "%lu");
|
||||||
|
int len = snprintf(buf, sizeof(buf), fmt, value);
|
||||||
|
return fn(buf, len, fndata);
|
||||||
|
}
|
||||||
|
|
||||||
|
int mjson_print_dbl(mjson_print_fn_t fn, void *fndata, double d,
|
||||||
|
const char *fmt) {
|
||||||
|
char buf[40];
|
||||||
|
int n = snprintf(buf, sizeof(buf), fmt, d);
|
||||||
|
return fn(buf, n, fndata);
|
||||||
|
}
|
||||||
|
|
||||||
|
int mjson_print_str(mjson_print_fn_t fn, void *fndata, const char *s, int len) {
|
||||||
|
int i, n = fn("\"", 1, fndata);
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
char c = mjson_esc(s[i], 1);
|
||||||
|
if (c) {
|
||||||
|
n += fn("\\", 1, fndata);
|
||||||
|
n += fn(&c, 1, fndata);
|
||||||
|
} else {
|
||||||
|
n += fn(&s[i], 1, fndata);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return n + fn("\"", 1, fndata);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if MJSON_ENABLE_BASE64
|
||||||
|
int mjson_print_b64(mjson_print_fn_t fn, void *fndata, const unsigned char *s,
|
||||||
|
int n) {
|
||||||
|
const char *t =
|
||||||
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||||
|
int i, len = fn("\"", 1, fndata);
|
||||||
|
for (i = 0; i < n; i += 3) {
|
||||||
|
int a = s[i], b = i + 1 < n ? s[i + 1] : 0, c = i + 2 < n ? s[i + 2] : 0;
|
||||||
|
char buf[4] = {t[a >> 2], t[(a & 3) << 4 | (b >> 4)], '=', '='};
|
||||||
|
if (i + 1 < n) buf[2] = t[(b & 15) << 2 | (c >> 6)];
|
||||||
|
if (i + 2 < n) buf[3] = t[c & 63];
|
||||||
|
len += fn(buf, sizeof(buf), fndata);
|
||||||
|
}
|
||||||
|
return len + fn("\"", 1, fndata);
|
||||||
|
}
|
||||||
|
#endif /* MJSON_ENABLE_BASE64 */
|
||||||
|
|
||||||
|
int mjson_vprintf(mjson_print_fn_t fn, void *fndata, const char *fmt,
|
||||||
|
va_list xap) {
|
||||||
|
int i = 0, n = 0;
|
||||||
|
va_list ap;
|
||||||
|
va_copy(ap, xap);
|
||||||
|
while (fmt[i] != '\0') {
|
||||||
|
if (fmt[i] == '%') {
|
||||||
|
char fc = fmt[++i];
|
||||||
|
int is_long = 0;
|
||||||
|
if (fc == 'l') {
|
||||||
|
is_long = 1;
|
||||||
|
fc = fmt[i + 1];
|
||||||
|
}
|
||||||
|
if (fc == 'Q') {
|
||||||
|
char *buf = va_arg(ap, char *);
|
||||||
|
n += mjson_print_str(fn, fndata, buf ? buf : "", buf ? strlen(buf) : 0);
|
||||||
|
} else if (strncmp(&fmt[i], ".*Q", 3) == 0) {
|
||||||
|
int len = va_arg(ap, int);
|
||||||
|
char *buf = va_arg(ap, char *);
|
||||||
|
n += mjson_print_str(fn, fndata, buf, len);
|
||||||
|
i += 2;
|
||||||
|
} else if (fc == 'd' || fc == 'u') {
|
||||||
|
int is_signed = (fc == 'd');
|
||||||
|
if (is_long) {
|
||||||
|
long val = va_arg(ap, long);
|
||||||
|
n += mjson_print_long(fn, fndata, val, is_signed);
|
||||||
|
i++;
|
||||||
|
} else {
|
||||||
|
int val = va_arg(ap, int);
|
||||||
|
n += mjson_print_int(fn, fndata, val, is_signed);
|
||||||
|
}
|
||||||
|
} else if (fc == 'B') {
|
||||||
|
const char *s = va_arg(ap, int) ? "true" : "false";
|
||||||
|
n += mjson_print_buf(fn, fndata, s, strlen(s));
|
||||||
|
} else if (fc == 's') {
|
||||||
|
char *buf = va_arg(ap, char *);
|
||||||
|
n += mjson_print_buf(fn, fndata, buf, strlen(buf));
|
||||||
|
} else if (strncmp(&fmt[i], ".*s", 3) == 0) {
|
||||||
|
int len = va_arg(ap, int);
|
||||||
|
char *buf = va_arg(ap, char *);
|
||||||
|
n += mjson_print_buf(fn, fndata, buf, len);
|
||||||
|
i += 2;
|
||||||
|
} else if (fc == 'g') {
|
||||||
|
n += mjson_print_dbl(fn, fndata, va_arg(ap, double), "%g");
|
||||||
|
} else if (fc == 'f') {
|
||||||
|
n += mjson_print_dbl(fn, fndata, va_arg(ap, double), "%f");
|
||||||
|
#if MJSON_ENABLE_BASE64
|
||||||
|
} else if (fc == 'V') {
|
||||||
|
int len = va_arg(ap, int);
|
||||||
|
const char *buf = va_arg(ap, const char *);
|
||||||
|
n += mjson_print_b64(fn, fndata, (unsigned char *) buf, len);
|
||||||
|
#endif
|
||||||
|
} else if (fc == 'H') {
|
||||||
|
const char *hex = "0123456789abcdef";
|
||||||
|
int i, len = va_arg(ap, int);
|
||||||
|
const unsigned char *p = va_arg(ap, const unsigned char *);
|
||||||
|
n += fn("\"", 1, fndata);
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
n += fn(&hex[(p[i] >> 4) & 15], 1, fndata);
|
||||||
|
n += fn(&hex[p[i] & 15], 1, fndata);
|
||||||
|
}
|
||||||
|
n += fn("\"", 1, fndata);
|
||||||
|
} else if (fc == 'M') {
|
||||||
|
mjson_vprint_fn_t vfn = va_arg(ap, mjson_vprint_fn_t);
|
||||||
|
n += vfn(fn, fndata, &ap);
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
} else {
|
||||||
|
n += mjson_print_buf(fn, fndata, &fmt[i++], 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
va_end(xap);
|
||||||
|
va_end(ap);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mjson_printf(mjson_print_fn_t fn, void *fndata, const char *fmt, ...) {
|
||||||
|
va_list ap;
|
||||||
|
int len;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
len = mjson_vprintf(fn, fndata, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
#endif /* MJSON_ENABLE_PRINT */
|
||||||
|
|
||||||
|
#if MJSON_IMPLEMENT_STRTOD
|
||||||
|
static inline int is_digit(int c) {
|
||||||
|
return c >= '0' && c <= '9';
|
||||||
|
}
|
||||||
|
|
||||||
|
/* NOTE: strtod() implementation by Yasuhiro Matsumoto. */
|
||||||
|
double strtod(const char *str, char **end) {
|
||||||
|
double d = 0.0;
|
||||||
|
int sign = 1, n = 0;
|
||||||
|
const char *p = str, *a = str;
|
||||||
|
|
||||||
|
/* decimal part */
|
||||||
|
if (*p == '-') {
|
||||||
|
sign = -1;
|
||||||
|
++p;
|
||||||
|
} else if (*p == '+')
|
||||||
|
++p;
|
||||||
|
if (is_digit(*p)) {
|
||||||
|
d = (double) (*p++ - '0');
|
||||||
|
while (*p && is_digit(*p)) {
|
||||||
|
d = d * 10.0 + (double) (*p - '0');
|
||||||
|
++p;
|
||||||
|
++n;
|
||||||
|
}
|
||||||
|
a = p;
|
||||||
|
} else if (*p != '.')
|
||||||
|
goto done;
|
||||||
|
d *= sign;
|
||||||
|
|
||||||
|
/* fraction part */
|
||||||
|
if (*p == '.') {
|
||||||
|
double f = 0.0;
|
||||||
|
double base = 0.1;
|
||||||
|
++p;
|
||||||
|
|
||||||
|
if (is_digit(*p)) {
|
||||||
|
while (*p && is_digit(*p)) {
|
||||||
|
f += base * (*p - '0');
|
||||||
|
base /= 10.0;
|
||||||
|
++p;
|
||||||
|
++n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
d += f * sign;
|
||||||
|
a = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* exponential part */
|
||||||
|
if ((*p == 'E') || (*p == 'e')) {
|
||||||
|
int e = 0;
|
||||||
|
++p;
|
||||||
|
|
||||||
|
sign = 1;
|
||||||
|
if (*p == '-') {
|
||||||
|
sign = -1;
|
||||||
|
++p;
|
||||||
|
} else if (*p == '+')
|
||||||
|
++p;
|
||||||
|
|
||||||
|
if (is_digit(*p)) {
|
||||||
|
while (*p == '0') ++p;
|
||||||
|
e = (int) (*p++ - '0');
|
||||||
|
while (*p && is_digit(*p)) {
|
||||||
|
e = e * 10 + (int) (*p - '0');
|
||||||
|
++p;
|
||||||
|
}
|
||||||
|
e *= sign;
|
||||||
|
} else if (!is_digit(*(a - 1))) {
|
||||||
|
a = str;
|
||||||
|
goto done;
|
||||||
|
} else if (*p == 0)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
if (d == 2.2250738585072011 && e == -308) {
|
||||||
|
d = 0.0;
|
||||||
|
a = p;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (d == 2.2250738585072012 && e <= -308) {
|
||||||
|
d *= 1.0e-308;
|
||||||
|
a = p;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < 10; i++) d *= 10;
|
||||||
|
}
|
||||||
|
a = p;
|
||||||
|
} else if (p > str && !is_digit(*(p - 1))) {
|
||||||
|
a = str;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
if (end) *end = (char *) a;
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MJSON_ENABLE_MERGE
|
||||||
|
int mjson_merge(const char *s, int n, const char *s2, int n2,
|
||||||
|
mjson_print_fn_t fn, void *userdata) {
|
||||||
|
int koff, klen, voff, vlen, t, t2, k, off = 0, len = 0, comma = 0;
|
||||||
|
if (n < 2) return len;
|
||||||
|
len += fn("{", 1, userdata);
|
||||||
|
while ((off = mjson_next(s, n, off, &koff, &klen, &voff, &vlen, &t)) != 0) {
|
||||||
|
#if !defined(_MSC_VER) || _MSC_VER >= 1700
|
||||||
|
char path[klen + 1];
|
||||||
|
#else
|
||||||
|
char *path = (char *) alloca(klen + 1);
|
||||||
|
#endif
|
||||||
|
const char *val;
|
||||||
|
memcpy(path, "$.", 2);
|
||||||
|
memcpy(path + 2, s + koff + 1, klen - 2);
|
||||||
|
path[klen] = '\0';
|
||||||
|
if ((t2 = mjson_find(s2, n2, path, &val, &k)) != MJSON_TOK_INVALID) {
|
||||||
|
if (t2 == MJSON_TOK_NULL) continue; // null deletes the key
|
||||||
|
} else {
|
||||||
|
val = s + voff; // Key is not found in the update. Copy the old value.
|
||||||
|
}
|
||||||
|
if (comma) len += fn(",", 1, userdata);
|
||||||
|
len += fn(s + koff, klen, userdata);
|
||||||
|
len += fn(":", 1, userdata);
|
||||||
|
if (t == MJSON_TOK_OBJECT && t2 == MJSON_TOK_OBJECT) {
|
||||||
|
len += mjson_merge(s + voff, vlen, val, k, fn, userdata);
|
||||||
|
} else {
|
||||||
|
if (t2 != MJSON_TOK_INVALID) vlen = k;
|
||||||
|
len += fn(val, vlen, userdata);
|
||||||
|
}
|
||||||
|
comma = 1;
|
||||||
|
}
|
||||||
|
// Add missing keys
|
||||||
|
off = 0;
|
||||||
|
while ((off = mjson_next(s2, n2, off, &koff, &klen, &voff, &vlen, &t)) != 0) {
|
||||||
|
#if !defined(_MSC_VER) || _MSC_VER >= 1700
|
||||||
|
char path[klen + 1];
|
||||||
|
#else
|
||||||
|
char *path = (char *) alloca(klen + 1);
|
||||||
|
#endif
|
||||||
|
const char *val;
|
||||||
|
if (t == MJSON_TOK_NULL) continue;
|
||||||
|
memcpy(path, "$.", 2);
|
||||||
|
memcpy(path + 2, s2 + koff + 1, klen - 2);
|
||||||
|
path[klen] = '\0';
|
||||||
|
if (mjson_find(s, n, path, &val, &vlen) != MJSON_TOK_INVALID) continue;
|
||||||
|
if (comma) len += fn(",", 1, userdata);
|
||||||
|
len += fn(s2 + koff, klen, userdata);
|
||||||
|
len += fn(":", 1, userdata);
|
||||||
|
len += fn(s2 + voff, vlen, userdata);
|
||||||
|
comma = 1;
|
||||||
|
}
|
||||||
|
len += fn("}", 1, userdata);
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
#endif // MJSON_ENABLE_MERGE
|
||||||
|
|
||||||
|
#if MJSON_ENABLE_PRETTY
|
||||||
|
struct prettydata {
|
||||||
|
int level;
|
||||||
|
int len;
|
||||||
|
int prev;
|
||||||
|
const char *pad;
|
||||||
|
int padlen;
|
||||||
|
mjson_print_fn_t fn;
|
||||||
|
void *userdata;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int pretty_cb(int ev, const char *s, int off, int len, void *ud) {
|
||||||
|
struct prettydata *d = (struct prettydata *) ud;
|
||||||
|
int i;
|
||||||
|
switch (ev) {
|
||||||
|
case '{':
|
||||||
|
case '[':
|
||||||
|
d->level++;
|
||||||
|
d->len += d->fn(s + off, len, d->userdata);
|
||||||
|
break;
|
||||||
|
case '}':
|
||||||
|
case ']':
|
||||||
|
d->level--;
|
||||||
|
if (d->prev != '[' && d->prev != '{' && d->padlen > 0) {
|
||||||
|
d->len += d->fn("\n", 1, d->userdata);
|
||||||
|
for (i = 0; i < d->level; i++)
|
||||||
|
d->len += d->fn(d->pad, d->padlen, d->userdata);
|
||||||
|
}
|
||||||
|
d->len += d->fn(s + off, len, d->userdata);
|
||||||
|
break;
|
||||||
|
case ',':
|
||||||
|
d->len += d->fn(s + off, len, d->userdata);
|
||||||
|
if (d->padlen > 0) {
|
||||||
|
d->len += d->fn("\n", 1, d->userdata);
|
||||||
|
for (i = 0; i < d->level; i++)
|
||||||
|
d->len += d->fn(d->pad, d->padlen, d->userdata);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ':':
|
||||||
|
d->len += d->fn(s + off, len, d->userdata);
|
||||||
|
if (d->padlen > 0) d->len += d->fn(" ", 1, d->userdata);
|
||||||
|
break;
|
||||||
|
case MJSON_TOK_KEY:
|
||||||
|
if (d->prev == '{' && d->padlen > 0) {
|
||||||
|
d->len += d->fn("\n", 1, d->userdata);
|
||||||
|
for (i = 0; i < d->level; i++)
|
||||||
|
d->len += d->fn(d->pad, d->padlen, d->userdata);
|
||||||
|
}
|
||||||
|
d->len += d->fn(s + off, len, d->userdata);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (d->prev == '[' && d->padlen > 0) {
|
||||||
|
d->len += d->fn("\n", 1, d->userdata);
|
||||||
|
for (i = 0; i < d->level; i++)
|
||||||
|
d->len += d->fn(d->pad, d->padlen, d->userdata);
|
||||||
|
}
|
||||||
|
d->len += d->fn(s + off, len, d->userdata);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
d->prev = ev;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mjson_pretty(const char *s, int n, const char *pad, mjson_print_fn_t fn,
|
||||||
|
void *userdata) {
|
||||||
|
struct prettydata d = {0, 0, 0, pad, strlen(pad), fn, userdata};
|
||||||
|
if (mjson(s, n, pretty_cb, &d) < 0) return -1;
|
||||||
|
return d.len;
|
||||||
|
}
|
||||||
|
#endif // MJSON_ENABLE_PRETTY
|
||||||
|
|
||||||
|
#if MJSON_ENABLE_RPC
|
||||||
|
struct jsonrpc_ctx jsonrpc_default_context;
|
||||||
|
struct jsonrpc_userdata {
|
||||||
|
mjson_print_fn_t fn;
|
||||||
|
void *fndata;
|
||||||
|
};
|
||||||
|
|
||||||
|
int mjson_globmatch(const char *s1, int n1, const char *s2, int n2) {
|
||||||
|
int i = 0, j = 0, ni = 0, nj = 0;
|
||||||
|
while (i < n1 || j < n2) {
|
||||||
|
if (i < n1 && j < n2 && (s1[i] == '?' || s2[j] == s1[i])) {
|
||||||
|
i++, j++;
|
||||||
|
} else if (i < n1 && (s1[i] == '*' || s1[i] == '#')) {
|
||||||
|
ni = i, nj = j + 1, i++;
|
||||||
|
} else if (nj > 0 && nj <= n2 && (s1[i - 1] == '#' || s2[j] != '/')) {
|
||||||
|
i = ni, j = nj;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int jsonrpc_printer(const char *buf, int len, void *userdata) {
|
||||||
|
struct jsonrpc_userdata *u = (struct jsonrpc_userdata *) userdata;
|
||||||
|
return u->fn(buf, len, u->fndata);
|
||||||
|
}
|
||||||
|
|
||||||
|
void jsonrpc_return_errorv(struct jsonrpc_request *r, int code,
|
||||||
|
const char *message, const char *data_fmt,
|
||||||
|
va_list ap) {
|
||||||
|
if (r->id_len == 0) return;
|
||||||
|
mjson_printf(r->fn, r->fndata,
|
||||||
|
"{\"id\":%.*s,\"error\":{\"code\":%d,\"message\":%Q", r->id_len,
|
||||||
|
r->id, code, message == NULL ? "" : message);
|
||||||
|
if (data_fmt != NULL) {
|
||||||
|
mjson_printf(r->fn, r->fndata, ",\"data\":");
|
||||||
|
mjson_vprintf(r->fn, r->fndata, data_fmt, ap);
|
||||||
|
}
|
||||||
|
mjson_printf(r->fn, r->fndata, "}}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void jsonrpc_return_error(struct jsonrpc_request *r, int code,
|
||||||
|
const char *message, const char *data_fmt, ...) {
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, data_fmt);
|
||||||
|
jsonrpc_return_errorv(r, code, message, data_fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
void jsonrpc_return_successv(struct jsonrpc_request *r, const char *result_fmt,
|
||||||
|
va_list ap) {
|
||||||
|
if (r->id_len == 0) return;
|
||||||
|
mjson_printf(r->fn, r->fndata, "{\"id\":%.*s,\"result\":", r->id_len, r->id);
|
||||||
|
if (result_fmt != NULL) {
|
||||||
|
mjson_vprintf(r->fn, r->fndata, result_fmt, ap);
|
||||||
|
} else {
|
||||||
|
mjson_printf(r->fn, r->fndata, "%s", "null");
|
||||||
|
}
|
||||||
|
mjson_printf(r->fn, r->fndata, "}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void jsonrpc_return_success(struct jsonrpc_request *r, const char *result_fmt,
|
||||||
|
...) {
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, result_fmt);
|
||||||
|
jsonrpc_return_successv(r, result_fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
void jsonrpc_ctx_process(struct jsonrpc_ctx *ctx, const char *req, int req_sz,
|
||||||
|
mjson_print_fn_t fn, void *fndata) {
|
||||||
|
const char *result = NULL, *error = NULL;
|
||||||
|
int result_sz = 0, error_sz = 0;
|
||||||
|
struct jsonrpc_method *m = NULL;
|
||||||
|
struct jsonrpc_userdata d;
|
||||||
|
struct jsonrpc_request r = {req, req_sz, 0, 0, 0, 0, 0,
|
||||||
|
0, &jsonrpc_printer, NULL, NULL};
|
||||||
|
|
||||||
|
d.fn = fn;
|
||||||
|
d.fndata = fndata;
|
||||||
|
r.fndata = &d;
|
||||||
|
|
||||||
|
// Is is a response frame?
|
||||||
|
mjson_find(req, req_sz, "$.result", &result, &result_sz);
|
||||||
|
if (result == NULL) mjson_find(req, req_sz, "$.error", &error, &error_sz);
|
||||||
|
if (result_sz > 0 || error_sz > 0) {
|
||||||
|
if (ctx->response_cb != NULL) ctx->response_cb(req, req_sz, ctx->userdata);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method must exist and must be a string
|
||||||
|
if (mjson_find(req, req_sz, "$.method", &r.method, &r.method_len) !=
|
||||||
|
MJSON_TOK_STRING) {
|
||||||
|
mjson_printf(fn, fndata, "{\"error\":{\"code\":-32700,\"message\":%.*Q}}\n",
|
||||||
|
req_sz, req);
|
||||||
|
ctx->in_len = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// id and params are optional
|
||||||
|
mjson_find(req, req_sz, "$.id", &r.id, &r.id_len);
|
||||||
|
mjson_find(req, req_sz, "$.params", &r.params, &r.params_len);
|
||||||
|
|
||||||
|
for (m = ctx->methods; m != NULL; m = m->next) {
|
||||||
|
if (mjson_globmatch(m->method, m->method_sz, r.method + 1,
|
||||||
|
r.method_len - 2) > 0) {
|
||||||
|
if (r.params == NULL) r.params = "";
|
||||||
|
r.userdata = m->cbdata;
|
||||||
|
m->cb(&r);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (m == NULL) {
|
||||||
|
jsonrpc_return_error(&r, JSONRPC_ERROR_NOT_FOUND, "method not found", NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int jsonrpc_print_methods(mjson_print_fn_t fn, void *fndata,
|
||||||
|
va_list *ap) {
|
||||||
|
struct jsonrpc_ctx *ctx = va_arg(*ap, struct jsonrpc_ctx *);
|
||||||
|
struct jsonrpc_method *m;
|
||||||
|
int len = 0;
|
||||||
|
for (m = ctx->methods; m != NULL; m = m->next) {
|
||||||
|
if (m != ctx->methods) len += mjson_print_buf(fn, fndata, ",", 1);
|
||||||
|
len += mjson_print_str(fn, fndata, m->method, strlen(m->method));
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rpclist(struct jsonrpc_request *r) {
|
||||||
|
jsonrpc_return_success(r, "[%M]", jsonrpc_print_methods, r->userdata);
|
||||||
|
}
|
||||||
|
|
||||||
|
void jsonrpc_ctx_init(struct jsonrpc_ctx *ctx, mjson_print_fn_t response_cb,
|
||||||
|
void *userdata) {
|
||||||
|
ctx->response_cb = response_cb;
|
||||||
|
ctx->userdata = userdata;
|
||||||
|
jsonrpc_ctx_export(ctx, MJSON_RPC_LIST_NAME, rpclist, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void jsonrpc_ctx_process_byte(struct jsonrpc_ctx *ctx, unsigned char ch,
|
||||||
|
mjson_print_fn_t fn, void *p) {
|
||||||
|
if (ctx->in_len >= (int) sizeof(ctx->in)) ctx->in_len = 0; // Overflow
|
||||||
|
if (ch == '\n') { // If new line, parse frame
|
||||||
|
if (ctx->in_len > 1) jsonrpc_ctx_process(ctx, ctx->in, ctx->in_len, fn, p);
|
||||||
|
ctx->in_len = 0;
|
||||||
|
} else {
|
||||||
|
ctx->in[ctx->in_len] = ch; // Append to the buffer
|
||||||
|
ctx->in_len++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void jsonrpc_init(mjson_print_fn_t response_cb, void *userdata) {
|
||||||
|
jsonrpc_ctx_init(&jsonrpc_default_context, response_cb, userdata);
|
||||||
|
}
|
||||||
|
#endif // MJSON_ENABLE_RPC
|
||||||
@@ -0,0 +1,220 @@
|
|||||||
|
// Copyright (c) 2018-2020 Cesanta Software Limited
|
||||||
|
// All rights reserved
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
#ifndef MJSON_H
|
||||||
|
#define MJSON_H
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifndef MJSON_ENABLE_PRINT
|
||||||
|
#define MJSON_ENABLE_PRINT 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MJSON_ENABLE_RPC
|
||||||
|
#define MJSON_ENABLE_RPC 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MJSON_ENABLE_BASE64
|
||||||
|
#define MJSON_ENABLE_BASE64 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MJSON_ENABLE_MERGE
|
||||||
|
#define MJSON_ENABLE_MERGE 0
|
||||||
|
#elif MJSON_ENABLE_MERGE
|
||||||
|
#define MJSON_ENABLE_NEXT 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MJSON_ENABLE_PRETTY
|
||||||
|
#define MJSON_ENABLE_PRETTY 0
|
||||||
|
#elif MJSON_ENABLE_PRETTY
|
||||||
|
#define MJSON_ENABLE_NEXT 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MJSON_ENABLE_NEXT
|
||||||
|
#define MJSON_ENABLE_NEXT 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef MJSON_RPC_IN_BUF_SIZE
|
||||||
|
#define MJSON_RPC_IN_BUF_SIZE 256
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MJSON_RPC_LIST_NAME
|
||||||
|
#define MJSON_RPC_LIST_NAME "rpc.list"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
enum {
|
||||||
|
MJSON_ERROR_INVALID_INPUT = -1,
|
||||||
|
MJSON_ERROR_TOO_DEEP = -2,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum mjson_tok {
|
||||||
|
MJSON_TOK_INVALID = 0,
|
||||||
|
MJSON_TOK_KEY = 1,
|
||||||
|
MJSON_TOK_STRING = 11,
|
||||||
|
MJSON_TOK_NUMBER = 12,
|
||||||
|
MJSON_TOK_TRUE = 13,
|
||||||
|
MJSON_TOK_FALSE = 14,
|
||||||
|
MJSON_TOK_NULL = 15,
|
||||||
|
MJSON_TOK_ARRAY = 91,
|
||||||
|
MJSON_TOK_OBJECT = 123,
|
||||||
|
};
|
||||||
|
#define MJSON_TOK_IS_VALUE(t) ((t) > 10 && (t) < 20)
|
||||||
|
|
||||||
|
typedef int (*mjson_cb_t)(int ev, const char *s, int off, int len, void *ud);
|
||||||
|
|
||||||
|
#ifndef MJSON_MAX_DEPTH
|
||||||
|
#define MJSON_MAX_DEPTH 20
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int mjson(const char *s, int len, mjson_cb_t cb, void *ud);
|
||||||
|
enum mjson_tok mjson_find(const char *s, int len, const char *jp,
|
||||||
|
const char **tokptr, int *toklen);
|
||||||
|
int mjson_get_number(const char *s, int len, const char *path, double *v);
|
||||||
|
int mjson_get_bool(const char *s, int len, const char *path, int *v);
|
||||||
|
int mjson_get_string(const char *s, int len, const char *path, char *to, int n);
|
||||||
|
int mjson_get_hex(const char *s, int len, const char *path, char *to, int n);
|
||||||
|
|
||||||
|
#if MJSON_ENABLE_NEXT
|
||||||
|
int mjson_next(const char *s, int n, int off, int *koff, int *klen, int *voff,
|
||||||
|
int *vlen, int *vtype);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MJSON_ENABLE_BASE64
|
||||||
|
int mjson_get_base64(const char *s, int len, const char *path, char *to, int n);
|
||||||
|
int mjson_base64_dec(const char *src, int n, char *dst, int dlen);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MJSON_ENABLE_PRINT
|
||||||
|
typedef int (*mjson_print_fn_t)(const char *buf, int len, void *userdata);
|
||||||
|
typedef int (*mjson_vprint_fn_t)(mjson_print_fn_t, void *, va_list *);
|
||||||
|
|
||||||
|
struct mjson_fixedbuf {
|
||||||
|
char *ptr;
|
||||||
|
int size, len;
|
||||||
|
};
|
||||||
|
|
||||||
|
int mjson_printf(mjson_print_fn_t, void *, const char *fmt, ...);
|
||||||
|
int mjson_vprintf(mjson_print_fn_t, void *, const char *fmt, va_list ap);
|
||||||
|
int mjson_print_str(mjson_print_fn_t, void *, const char *s, int len);
|
||||||
|
int mjson_print_int(mjson_print_fn_t, void *, int value, int is_signed);
|
||||||
|
int mjson_print_long(mjson_print_fn_t, void *, long value, int is_signed);
|
||||||
|
int mjson_print_buf(mjson_print_fn_t fn, void *, const char *buf, int len);
|
||||||
|
|
||||||
|
int mjson_print_null(const char *ptr, int len, void *userdata);
|
||||||
|
int mjson_print_file(const char *ptr, int len, void *userdata);
|
||||||
|
int mjson_print_fixed_buf(const char *ptr, int len, void *userdata);
|
||||||
|
int mjson_print_dynamic_buf(const char *ptr, int len, void *userdata);
|
||||||
|
|
||||||
|
#if MJSON_ENABLE_PRETTY
|
||||||
|
int mjson_pretty(const char *, int, const char *, mjson_print_fn_t, void *);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MJSON_ENABLE_MERGE
|
||||||
|
int mjson_merge(const char *, int, const char *, int, mjson_print_fn_t, void *);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // MJSON_ENABLE_PRINT
|
||||||
|
|
||||||
|
#if MJSON_ENABLE_RPC
|
||||||
|
|
||||||
|
void jsonrpc_init(mjson_print_fn_t, void *userdata);
|
||||||
|
int mjson_globmatch(const char *s1, int n1, const char *s2, int n2);
|
||||||
|
|
||||||
|
struct jsonrpc_request {
|
||||||
|
const char *frame; // Points to the whole frame
|
||||||
|
int frame_len; // Frame length
|
||||||
|
const char *params; // Points to the "params" in the request frame
|
||||||
|
int params_len; // Length of the "params"
|
||||||
|
const char *id; // Points to the "id" in the request frame
|
||||||
|
int id_len; // Length of the "id"
|
||||||
|
const char *method; // Points to the "method" in the request frame
|
||||||
|
int method_len; // Length of the "method"
|
||||||
|
mjson_print_fn_t fn; // Printer function
|
||||||
|
void *fndata; // Printer function data
|
||||||
|
void *userdata; // Callback's user data as specified at export time
|
||||||
|
};
|
||||||
|
|
||||||
|
struct jsonrpc_method {
|
||||||
|
const char *method;
|
||||||
|
int method_sz;
|
||||||
|
void (*cb)(struct jsonrpc_request *);
|
||||||
|
void *cbdata;
|
||||||
|
struct jsonrpc_method *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Main RPC context, stores current request information and a list of
|
||||||
|
// exported RPC methods.
|
||||||
|
struct jsonrpc_ctx {
|
||||||
|
struct jsonrpc_method *methods;
|
||||||
|
void *userdata;
|
||||||
|
mjson_print_fn_t response_cb;
|
||||||
|
int in_len;
|
||||||
|
char in[MJSON_RPC_IN_BUF_SIZE];
|
||||||
|
};
|
||||||
|
|
||||||
|
// Registers function fn under the given name within the given RPC context
|
||||||
|
#define jsonrpc_ctx_export(ctx, name, fn, ud) \
|
||||||
|
do { \
|
||||||
|
static struct jsonrpc_method m = {(name), sizeof(name) - 1, (fn), 0, 0}; \
|
||||||
|
m.cbdata = (ud); \
|
||||||
|
m.next = (ctx)->methods; \
|
||||||
|
(ctx)->methods = &m; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
void jsonrpc_ctx_init(struct jsonrpc_ctx *ctx, mjson_print_fn_t, void *);
|
||||||
|
void jsonrpc_return_error(struct jsonrpc_request *r, int code,
|
||||||
|
const char *message, const char *data_fmt, ...);
|
||||||
|
void jsonrpc_return_success(struct jsonrpc_request *r, const char *result_fmt,
|
||||||
|
...);
|
||||||
|
void jsonrpc_ctx_process(struct jsonrpc_ctx *ctx, const char *req, int req_sz,
|
||||||
|
mjson_print_fn_t fn, void *fndata);
|
||||||
|
void jsonrpc_ctx_process_byte(struct jsonrpc_ctx *ctx, unsigned char ch,
|
||||||
|
mjson_print_fn_t fn, void *fndata);
|
||||||
|
|
||||||
|
extern struct jsonrpc_ctx jsonrpc_default_context;
|
||||||
|
|
||||||
|
#define jsonrpc_export(name, fn, ud) \
|
||||||
|
jsonrpc_ctx_export(&jsonrpc_default_context, (name), (fn), (ud))
|
||||||
|
|
||||||
|
#define jsonrpc_process(buf, len, fn, data) \
|
||||||
|
jsonrpc_ctx_process(&jsonrpc_default_context, (buf), (len), (fn), (data))
|
||||||
|
|
||||||
|
#define jsonrpc_process_byte(x, fn, data) \
|
||||||
|
jsonrpc_ctx_process_byte(&jsonrpc_default_context, (x), (fn), (data))
|
||||||
|
|
||||||
|
#define JSONRPC_ERROR_INVALID -32700 /* Invalid JSON was received */
|
||||||
|
#define JSONRPC_ERROR_NOT_FOUND -32601 /* The method does not exist */
|
||||||
|
#define JSONRPC_ERROR_BAD_PARAMS -32602 /* Invalid params passed */
|
||||||
|
#define JSONRPC_ERROR_INTERNAL -32603 /* Internal JSON-RPC error */
|
||||||
|
|
||||||
|
#endif // MJSON_ENABLE_RPC
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif // MJSON_H
|
||||||
|
After Width: | Height: | Size: 134 KiB |
|
After Width: | Height: | Size: 52 KiB |
|
After Width: | Height: | Size: 122 KiB |
@@ -0,0 +1,312 @@
|
|||||||
|
const {h, render, Component} = preact;
|
||||||
|
const html = htm.bind(h);
|
||||||
|
|
||||||
|
class Login extends Component {
|
||||||
|
state = {user: '', pass: ''};
|
||||||
|
onclick = (app) => {
|
||||||
|
const authhdr = 'Basic ' + btoa(this.state.user + ':' + this.state.pass);
|
||||||
|
const headers = {Authorization: authhdr};
|
||||||
|
return axios.get('/api/login', {headers})
|
||||||
|
.then(res => app.setUser(res.data.token))
|
||||||
|
.catch(err => alert('Login failed'));
|
||||||
|
};
|
||||||
|
onpassinput = (ev) => this.setState({pass: ev.target.value});
|
||||||
|
onuserinput = (ev) => this.setState({user: ev.target.value});
|
||||||
|
render({app}, {user, pass, signup}) {
|
||||||
|
return html`
|
||||||
|
<div class='mx-auto bg-light rounded border my-5' style='max-width: 480px;'>
|
||||||
|
<div class='form p-5 rounded form-sm'>
|
||||||
|
<h4 class="text-muted mb-4">Login </h4>
|
||||||
|
<input type='email' placeholder='Email' class='my-2 form-control'
|
||||||
|
oninput=${this.onuserinput} value=${user} />
|
||||||
|
<input type="password" placeholder="Password" class="my-2 form-control"
|
||||||
|
oninput=${this.onpassinput} value=${pass}
|
||||||
|
onchange=${ev => this.onclick(app)} />
|
||||||
|
<div class="mb-4">
|
||||||
|
<button class="btn btn-info btn-block"
|
||||||
|
disabled=${!user || !pass} onclick="${ev => this.onclick(app)}"
|
||||||
|
> Login </button>
|
||||||
|
</div>
|
||||||
|
<div class="text-muted small">
|
||||||
|
Valid logins: admin:admin, user1:pass1, user2:pass2
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class Dropdown extends Component {
|
||||||
|
state = {show: false};
|
||||||
|
render(props, state) {
|
||||||
|
const onclick = x => this.setState({show: x});
|
||||||
|
const show = state.show ? 'show' : '';
|
||||||
|
return html`
|
||||||
|
<div class="dropdown autoexpand ${props.cls}">
|
||||||
|
<div type="buttonx" onclick=${() => onclick(!state.show)}
|
||||||
|
class="dropdown-toggle my-0 ${props.bcls}"
|
||||||
|
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||||
|
${props.title}
|
||||||
|
</div>
|
||||||
|
<div onclick=${() => onclick(false)} style=${props.dstyle}
|
||||||
|
class="dropdown-menu ${props.dcls} ${show}">
|
||||||
|
${props.children}
|
||||||
|
</div>
|
||||||
|
</div>`;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const NavLink = ({href, title, url}) => html`<a class="nav-item nav-link
|
||||||
|
${url == href ? 'active' : ''}"
|
||||||
|
target=${href.match(/^http/) ? '_blank' : ''}
|
||||||
|
href="${href.match(/^http/) ? '' : '#'}${href}">${title}</a>`;
|
||||||
|
|
||||||
|
class Header extends Component {
|
||||||
|
state = {expanded: false};
|
||||||
|
ontoggle = () => this.setState({expanded: !this.state.expanded});
|
||||||
|
render(props, state) {
|
||||||
|
const u = props.app.state.user || {};
|
||||||
|
return html`
|
||||||
|
<nav class="navbar navbar-expand-md navbar-dark bg-dark">
|
||||||
|
<a class="navbar-brand" href="#">
|
||||||
|
<img src="images/logo.png" width="26" height="26" alt="" class="mr-2" />
|
||||||
|
MyProduct
|
||||||
|
</a>
|
||||||
|
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation"
|
||||||
|
onclick=${() => this.ontoggle()} >
|
||||||
|
<span class="navbar-toggler-icon"></span>
|
||||||
|
</button>
|
||||||
|
<div class="navbar-collapse ${state.expanded ? '' : 'collapse'}"
|
||||||
|
id="navbarNav">
|
||||||
|
<div class="nav navbar-nav mr-auto">
|
||||||
|
<${NavLink} href="/" title="Dashboard" url=${props.url} />
|
||||||
|
<${NavLink} href="/logs" title="Logs" url=${props.url} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<form class="form-inline">
|
||||||
|
<${Dropdown} title="${u.user}" cls="mr-2"
|
||||||
|
bcls="btn btn-sm btn-outline-light pointer" dcls="m-0 dropdown-menu-right">
|
||||||
|
<div onclick=${() => props.app.setUser('')}
|
||||||
|
class="dropdown-item small pointer text-center">logout</div>
|
||||||
|
</${Dropdown}>
|
||||||
|
<img src="images/user.png" class="rounded-circle nav-item mr-2" width="30" />
|
||||||
|
</form>
|
||||||
|
</nav>
|
||||||
|
`
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const Info = () => html`<div class="alert alert-secondary my-3">
|
||||||
|
This dashboard shows values kept in server memory. Many clients
|
||||||
|
can open this page. As soon as any client changes any value,
|
||||||
|
all clients update automatically.
|
||||||
|
The JS code that watches state changes, reconnects on network failures.
|
||||||
|
That means if server restarts, dashboard on all connected clients
|
||||||
|
refresh automatically.
|
||||||
|
You can use <code>curl</code> command-line utility:
|
||||||
|
<br/><code>curl localhost:8000/api/config/get</code>
|
||||||
|
<br/><code>curl localhost:8000/api/config/watch</code>
|
||||||
|
<br/><code>curl localhost:8000/api/config/set -d '{"a":123}'</code>
|
||||||
|
<br/><span class="badge badge-danger">NOTE:</span> administrators
|
||||||
|
can change settings values, whilst users cannot.
|
||||||
|
</div>`;
|
||||||
|
|
||||||
|
class DashVideo extends Component {
|
||||||
|
render(props, state) {
|
||||||
|
const onclick = ev => axios.post(
|
||||||
|
'/api/config/set', {value1: +state.value1, value2: state.value2});
|
||||||
|
// alert(JSON.stringify(state));
|
||||||
|
return html`<div id="form">
|
||||||
|
<div><b>Change values</b></div>
|
||||||
|
<table>
|
||||||
|
<tr><td>Value 1 (number):</td><td><input value=${state.value1}
|
||||||
|
onInput=${linkState(this, 'value1')} /></td></tr>
|
||||||
|
<tr><td>Value 2 (string):</td><td><input value=${state.value2}
|
||||||
|
onInput=${linkState(this, 'value2')}/></td></tr>
|
||||||
|
<tr><td></td>
|
||||||
|
<td><button onClick=${onclick}>Save values</button></td></tr>
|
||||||
|
</table>
|
||||||
|
</div>`
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class DashForm extends Component {
|
||||||
|
render(props, state) {
|
||||||
|
const onclick = ev => axios.post(
|
||||||
|
'/api/config/set', {value1: +state.value1, value2: state.value2});
|
||||||
|
// alert(JSON.stringify(state));
|
||||||
|
return html`<div id="form">
|
||||||
|
<div><b>Change values</b></div>
|
||||||
|
<table>
|
||||||
|
<tr><td>Value 1 (number):</td><td><input class="form-control form-control-sm"
|
||||||
|
value=${state.value1}
|
||||||
|
onInput=${linkState(this, 'value1')} /></td></tr>
|
||||||
|
<tr><td>Value 2 (string):</td><td><input class="form-control form-control-sm"
|
||||||
|
value=${state.value2}
|
||||||
|
onInput=${linkState(this, 'value2')}/></td></tr>
|
||||||
|
<tr><td></td>
|
||||||
|
<td><button class="btn btn-primary btn-block"
|
||||||
|
onClick=${onclick}>Save values</button></td></tr>
|
||||||
|
</table>
|
||||||
|
</div>`
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class DashSettings extends Component {
|
||||||
|
state = {value1: null, value2: null};
|
||||||
|
componentDidMount() {
|
||||||
|
axios.get('/api/config/get')
|
||||||
|
.then(r => this.setState(r.data))
|
||||||
|
.catch(e => console.log(e));
|
||||||
|
var self = this;
|
||||||
|
var f = function(reader) {
|
||||||
|
return reader.read().then(function(result) {
|
||||||
|
var data = String.fromCharCode.apply(null, result.value);
|
||||||
|
self.setState(JSON.parse(data));
|
||||||
|
// console.log(JSON.parse(data));
|
||||||
|
if (!result.done) return f(reader);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
fetch('/api/config/watch')
|
||||||
|
.then(r => r.body.getReader())
|
||||||
|
.then(f)
|
||||||
|
.catch(e => setTimeout(x => self.componentDidMount(), 1000));
|
||||||
|
}
|
||||||
|
render(props, state) {
|
||||||
|
return html
|
||||||
|
`<div id="dashboard" style="display: flex; justify-content: flex-evenly;">
|
||||||
|
<div style="width:50%;text-align:center;">Value 1 (number):
|
||||||
|
<div style="font-size:140%;"><b>${state.value1}</b></div></div>
|
||||||
|
<div style="width:50%;text-align:center;">Value 2 (string):
|
||||||
|
<div style="font-size:140%;"><b>${state.value2}</b></div></div>
|
||||||
|
</div>`
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class AdminDashboard extends Component {
|
||||||
|
render(props, state) {
|
||||||
|
return html`<div class="container-fluid">
|
||||||
|
<${Info} />
|
||||||
|
<div class="card-deck">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">Settings</div>
|
||||||
|
<div class="card-body"><${DashSettings} /></div>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">Video stream</div>
|
||||||
|
<div class="card-body"><img src="/api/video1" class="mw-100" /></div>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">Change settings</div>
|
||||||
|
<div class="card-body"><${DashForm} /></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class UserDashboard extends Component {
|
||||||
|
render(props, state) {
|
||||||
|
return html`<div class="container-fluid">
|
||||||
|
<${Info} />
|
||||||
|
<div class="card-deck">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">Settings</div>
|
||||||
|
<div class="card-body"><${DashSettings} /></div>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">Video stream</div>
|
||||||
|
<div class="card-body"><img src="/api/video1" class="mw-100" /></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Logs extends Component {
|
||||||
|
state = {live: '', static: ''};
|
||||||
|
componentDidMount() {
|
||||||
|
var self = this;
|
||||||
|
var f = function(r) {
|
||||||
|
return r.read().then(function(result) {
|
||||||
|
var data = String.fromCharCode.apply(null, result.value);
|
||||||
|
var live = self.state.live + data;
|
||||||
|
self.setState({live}); // Append live log
|
||||||
|
if (!result.done) f(r); // Read next chunk
|
||||||
|
});
|
||||||
|
};
|
||||||
|
fetch('/api/log/static')
|
||||||
|
.then(r => r.text())
|
||||||
|
.then(r => {
|
||||||
|
self.setState({static: r});
|
||||||
|
})
|
||||||
|
.then(r => fetch('/api/log/live'))
|
||||||
|
.then(r => r.body.getReader())
|
||||||
|
.then(f);
|
||||||
|
}
|
||||||
|
render(props, state) {
|
||||||
|
return html`<div class="container-fluid">
|
||||||
|
<div class="alert alert-secondary my-3">
|
||||||
|
A div below shows file log.txt, which is produced by the server.
|
||||||
|
The server appends a new log message to that file every second,
|
||||||
|
and a div below also shows that, implementing a "live log" feature.
|
||||||
|
JS code on this page first fetches /api/log/static that returns
|
||||||
|
log.txt contents, then fetches /api/log/live that does not return,
|
||||||
|
but feeds chunks of data as they arrive (live log).
|
||||||
|
<br/><br/>
|
||||||
|
You can also use <code>curl</code> command-line utility to see
|
||||||
|
live logs:
|
||||||
|
<br/><code>curl localhost:8000/api/log/live</code>
|
||||||
|
</div>
|
||||||
|
<div class="card-deck">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">Static</div>
|
||||||
|
<div class="card-body"><pre class="log">${state.static}</pre></div>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">Live</div>
|
||||||
|
<div class="card-body"><pre class="log">${state.live}</pre></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class App extends Component {
|
||||||
|
state = {user: null, url: '/'};
|
||||||
|
setUser(token) {
|
||||||
|
const maxAge = token ? 86400 : 0;
|
||||||
|
document.cookie = `access_token=${token};path=/;max-age=${maxAge}`;
|
||||||
|
// this.setState({token});
|
||||||
|
return axios.get('/api/login')
|
||||||
|
.then(res => this.setState({user: res.data}))
|
||||||
|
.catch(err => this.setState({user: {}}));
|
||||||
|
}
|
||||||
|
componentDidMount() {
|
||||||
|
const getCookie = name => {
|
||||||
|
var v = document.cookie.match('(^|;) ?' + name + '=([^;]*)(;|$)');
|
||||||
|
return v ? v[2] : '';
|
||||||
|
};
|
||||||
|
this.setUser(getCookie('access_token')); // Move from state1 to 2 or 3
|
||||||
|
}
|
||||||
|
render(props, state) {
|
||||||
|
// We have three states:
|
||||||
|
// 1. Beginning. We don't know if we have a valid auth token or not
|
||||||
|
// 2. We sent an /api/login request, and failed to login
|
||||||
|
// 3. We sent an /api/login request, and succeeded to login
|
||||||
|
|
||||||
|
if (!state.user) return ''; // State 1
|
||||||
|
if (!state.user.user) return h(Login, {app: this}); // State 2
|
||||||
|
return h( // State 3
|
||||||
|
'div', {}, h(Header, {url: state.url, app: this}),
|
||||||
|
h(preactRouter.Router, {
|
||||||
|
history: History.createHashHistory(),
|
||||||
|
onChange: ev => this.setState({url: ev.url}),
|
||||||
|
},
|
||||||
|
h(state.user.user == 'admin' ? AdminDashboard : UserDashboard,
|
||||||
|
{default: true, app: this}),
|
||||||
|
h(Logs, {path: 'logs', app: this})));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
window.onload = () => render(h(App), document.body);
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
/* axios v0.21.1 | (c) 2020 by Matt Zabriskie */
|
||||||
|
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.axios=t():e.axios=t()}(this,function(){return function(e){function t(r){if(n[r])return n[r].exports;var o=n[r]={exports:{},id:r,loaded:!1};return e[r].call(o.exports,o,o.exports,t),o.loaded=!0,o.exports}var n={};return t.m=e,t.c=n,t.p="",t(0)}([function(e,t,n){e.exports=n(1)},function(e,t,n){"use strict";function r(e){var t=new i(e),n=s(i.prototype.request,t);return o.extend(n,i.prototype,t),o.extend(n,t),n}var o=n(2),s=n(3),i=n(4),a=n(22),u=n(10),c=r(u);c.Axios=i,c.create=function(e){return r(a(c.defaults,e))},c.Cancel=n(23),c.CancelToken=n(24),c.isCancel=n(9),c.all=function(e){return Promise.all(e)},c.spread=n(25),c.isAxiosError=n(26),e.exports=c,e.exports.default=c},function(e,t,n){"use strict";function r(e){return"[object Array]"===R.call(e)}function o(e){return"undefined"==typeof e}function s(e){return null!==e&&!o(e)&&null!==e.constructor&&!o(e.constructor)&&"function"==typeof e.constructor.isBuffer&&e.constructor.isBuffer(e)}function i(e){return"[object ArrayBuffer]"===R.call(e)}function a(e){return"undefined"!=typeof FormData&&e instanceof FormData}function u(e){var t;return t="undefined"!=typeof ArrayBuffer&&ArrayBuffer.isView?ArrayBuffer.isView(e):e&&e.buffer&&e.buffer instanceof ArrayBuffer}function c(e){return"string"==typeof e}function f(e){return"number"==typeof e}function p(e){return null!==e&&"object"==typeof e}function d(e){if("[object Object]"!==R.call(e))return!1;var t=Object.getPrototypeOf(e);return null===t||t===Object.prototype}function l(e){return"[object Date]"===R.call(e)}function h(e){return"[object File]"===R.call(e)}function m(e){return"[object Blob]"===R.call(e)}function y(e){return"[object Function]"===R.call(e)}function g(e){return p(e)&&y(e.pipe)}function v(e){return"undefined"!=typeof URLSearchParams&&e instanceof URLSearchParams}function x(e){return e.replace(/^\s*/,"").replace(/\s*$/,"")}function w(){return("undefined"==typeof navigator||"ReactNative"!==navigator.product&&"NativeScript"!==navigator.product&&"NS"!==navigator.product)&&("undefined"!=typeof window&&"undefined"!=typeof document)}function b(e,t){if(null!==e&&"undefined"!=typeof e)if("object"!=typeof e&&(e=[e]),r(e))for(var n=0,o=e.length;n<o;n++)t.call(null,e[n],n,e);else for(var s in e)Object.prototype.hasOwnProperty.call(e,s)&&t.call(null,e[s],s,e)}function E(){function e(e,n){d(t[n])&&d(e)?t[n]=E(t[n],e):d(e)?t[n]=E({},e):r(e)?t[n]=e.slice():t[n]=e}for(var t={},n=0,o=arguments.length;n<o;n++)b(arguments[n],e);return t}function j(e,t,n){return b(t,function(t,r){n&&"function"==typeof t?e[r]=S(t,n):e[r]=t}),e}function C(e){return 65279===e.charCodeAt(0)&&(e=e.slice(1)),e}var S=n(3),R=Object.prototype.toString;e.exports={isArray:r,isArrayBuffer:i,isBuffer:s,isFormData:a,isArrayBufferView:u,isString:c,isNumber:f,isObject:p,isPlainObject:d,isUndefined:o,isDate:l,isFile:h,isBlob:m,isFunction:y,isStream:g,isURLSearchParams:v,isStandardBrowserEnv:w,forEach:b,merge:E,extend:j,trim:x,stripBOM:C}},function(e,t){"use strict";e.exports=function(e,t){return function(){for(var n=new Array(arguments.length),r=0;r<n.length;r++)n[r]=arguments[r];return e.apply(t,n)}}},function(e,t,n){"use strict";function r(e){this.defaults=e,this.interceptors={request:new i,response:new i}}var o=n(2),s=n(5),i=n(6),a=n(7),u=n(22);r.prototype.request=function(e){"string"==typeof e?(e=arguments[1]||{},e.url=arguments[0]):e=e||{},e=u(this.defaults,e),e.method?e.method=e.method.toLowerCase():this.defaults.method?e.method=this.defaults.method.toLowerCase():e.method="get";var t=[a,void 0],n=Promise.resolve(e);for(this.interceptors.request.forEach(function(e){t.unshift(e.fulfilled,e.rejected)}),this.interceptors.response.forEach(function(e){t.push(e.fulfilled,e.rejected)});t.length;)n=n.then(t.shift(),t.shift());return n},r.prototype.getUri=function(e){return e=u(this.defaults,e),s(e.url,e.params,e.paramsSerializer).replace(/^\?/,"")},o.forEach(["delete","get","head","options"],function(e){r.prototype[e]=function(t,n){return this.request(u(n||{},{method:e,url:t,data:(n||{}).data}))}}),o.forEach(["post","put","patch"],function(e){r.prototype[e]=function(t,n,r){return this.request(u(r||{},{method:e,url:t,data:n}))}}),e.exports=r},function(e,t,n){"use strict";function r(e){return encodeURIComponent(e).replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%20/g,"+").replace(/%5B/gi,"[").replace(/%5D/gi,"]")}var o=n(2);e.exports=function(e,t,n){if(!t)return e;var s;if(n)s=n(t);else if(o.isURLSearchParams(t))s=t.toString();else{var i=[];o.forEach(t,function(e,t){null!==e&&"undefined"!=typeof e&&(o.isArray(e)?t+="[]":e=[e],o.forEach(e,function(e){o.isDate(e)?e=e.toISOString():o.isObject(e)&&(e=JSON.stringify(e)),i.push(r(t)+"="+r(e))}))}),s=i.join("&")}if(s){var a=e.indexOf("#");a!==-1&&(e=e.slice(0,a)),e+=(e.indexOf("?")===-1?"?":"&")+s}return e}},function(e,t,n){"use stricLine truncated
|
||||||
|
//# sourceMappingURL=axios.min.map
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
/*!
|
||||||
|
* Bootstrap v4.3.1 (https://getbootstrap.com/)
|
||||||
|
* Copyright 2011-2019 The Bootstrap Authors
|
||||||
|
* Copyright 2011-2019 Twitter, Inc.
|
||||||
|
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||||
|
*/:root{--blue:#007bff;--indigo:#6610f2;--purple:#6f42c1;--pink:#e83e8c;--red:#dc3545;--orange:#fd7e14;--yellow:#ffc107;--green:#28a745;--teal:#20c997;--cyan:#17a2b8;--white:#fff;--gray:#6c757d;--gray-dark:#343a40;--primary:#007bff;--secondary:#6c757d;--success:#28a745;--info:#17a2b8;--warning:#ffc107;--danger:#dc3545;--light:#f8f9fa;--dark:#343a40;--breakpoint-xs:0;--breakpoint-sm:576px;--breakpoint-md:768px;--breakpoint-lg:992px;--breakpoint-xl:1200px;--font-family-sans-serif:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-family-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace}*,::after,::before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}[tabindex="-1"]:focus{outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;text-decoration:none;background-color:transparent}a:hover{color:#0056b3;text-decoration:underline}a:not([href]):not([tabindex]){color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus,a:not([href]):not([tabindex]):hover{color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus{outline:0}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg{overflow:hidden;vertical-align:middle}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}select{word-wrap:normal}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=date],input[type=datetime-local],input[type=month],input[type=time]{-webkit-appearance:listbox}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none!important}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{margin-bottom:.5rem;font-weight:500;line-height:1.2}.h1,h1{font-size:2.5rem}.h2,h2{font-size:2rem}.h3,h3{font-size:1.75rem}.h4,h4{font-size:1.5rem}.h5,h5{font-size:1.25rem}.h6,h6{font-size:1rem}.lead{font-size:1.25rem;font-weight:300}.display-1{font-size:6rem;font-weight:300;line-height:1.2}.display-2{font-size:5.5rem;font-weight:300;line-height:1.2}.display-3{font-size:4.5rem;font-weight:300;line-height:1.2}.display-4{font-size:3.5rem;font-weight:300;line-height:1.2}hr{margin-top:1rem;margin-bottom:1rem;border:0;border-top:1px solid rgba(0,0,0,.1)}.small,Line truncated
|
||||||
|
/*# sourceMappingURL=bootstrap.min.css.map */
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
!function(t,n){"object"==typeof exports&&"object"==typeof module?module.exports=n():"function"==typeof define&&define.amd?define([],n):"object"==typeof exports?exports.History=n():t.History=n()}(this,function(){return function(t){function n(o){if(e[o])return e[o].exports;var r=e[o]={exports:{},id:o,loaded:!1};return t[o].call(r.exports,r,r.exports,n),r.loaded=!0,r.exports}var e={};return n.m=t,n.c=e,n.p="",n(0)}([function(t,n,e){"use strict";function o(t){return t&&t.__esModule?t:{default:t}}n.__esModule=!0,n.createPath=n.parsePath=n.locationsAreEqual=n.createLocation=n.createMemoryHistory=n.createHashHistory=n.createBrowserHistory=void 0;var r=e(2);Object.defineProperty(n,"createLocation",{enumerable:!0,get:function(){return r.createLocation}}),Object.defineProperty(n,"locationsAreEqual",{enumerable:!0,get:function(){return r.locationsAreEqual}});var i=e(1);Object.defineProperty(n,"parsePath",{enumerable:!0,get:function(){return i.parsePath}}),Object.defineProperty(n,"createPath",{enumerable:!0,get:function(){return i.createPath}});var a=e(7),c=o(a),u=e(8),s=o(u),f=e(9),l=o(f);n.createBrowserHistory=c.default,n.createHashHistory=s.default,n.createMemoryHistory=l.default},function(t,n){"use strict";n.__esModule=!0;n.addLeadingSlash=function(t){return"/"===t.charAt(0)?t:"/"+t},n.stripLeadingSlash=function(t){return"/"===t.charAt(0)?t.substr(1):t},n.stripPrefix=function(t,n){return 0===t.indexOf(n)?t.substr(n.length):t},n.stripTrailingSlash=function(t){return"/"===t.charAt(t.length-1)?t.slice(0,-1):t},n.parsePath=function(t){var n=t||"/",e="",o="",r=n.indexOf("#");r!==-1&&(o=n.substr(r),n=n.substr(0,r));var i=n.indexOf("?");return i!==-1&&(e=n.substr(i),n=n.substr(0,i)),n=decodeURI(n),{pathname:n,search:"?"===e?"":e,hash:"#"===o?"":o}},n.createPath=function(t){var n=t.pathname,e=t.search,o=t.hash,r=encodeURI(n||"/");return e&&"?"!==e&&(r+="?"===e.charAt(0)?e:"?"+e),o&&"#"!==o&&(r+="#"===o.charAt(0)?o:"#"+o),r}},function(t,n,e){"use strict";function o(t){return t&&t.__esModule?t:{default:t}}n.__esModule=!0,n.locationsAreEqual=n.createLocation=void 0;var r=Object.assign||function(t){for(var n=1;n<arguments.length;n++){var e=arguments[n];for(var o in e)Object.prototype.hasOwnProperty.call(e,o)&&(t[o]=e[o])}return t},i=e(10),a=o(i),c=e(11),u=o(c),s=e(1);n.createLocation=function(t,n,e,o){var i=void 0;return"string"==typeof t?(i=(0,s.parsePath)(t),i.state=n):(i=r({},t),void 0===i.pathname&&(i.pathname=""),i.search?"?"!==i.search.charAt(0)&&(i.search="?"+i.search):i.search="",i.hash?"#"!==i.hash.charAt(0)&&(i.hash="#"+i.hash):i.hash="",void 0!==n&&void 0===i.state&&(i.state=n)),i.key=e,o&&(i.pathname?"/"!==i.pathname.charAt(0)&&(i.pathname=(0,a.default)(i.pathname,o.pathname)):i.pathname=o.pathname),i},n.locationsAreEqual=function(t,n){return t.pathname===n.pathname&&t.search===n.search&&t.hash===n.hash&&t.key===n.key&&(0,u.default)(t.state,n.state)}},function(t,n,e){"use strict";var o=function(){};t.exports=o},function(t,n,e){"use strict";function o(t){return t&&t.__esModule?t:{default:t}}n.__esModule=!0;var r=e(3),i=(o(r),function(){var t=null,n=function(n){return t=n,function(){t===n&&(t=null)}},e=function(n,e,o,r){if(null!=t){var i="function"==typeof t?t(n,e):t;"string"==typeof i?"function"==typeof o?o(i,r):r(!0):r(i!==!1)}else r(!0)},o=[],r=function(t){var n=!0,e=function(){n&&t.apply(void 0,arguments)};return o.push(e),function(){n=!1,o=o.filter(function(t){return t!==e})}},i=function(){for(var t=arguments.length,n=Array(t),e=0;e<t;e++)n[e]=arguments[e];o.forEach(function(t){return t.apply(void 0,n)})};return{setPrompt:n,confirmTransitionTo:e,appendListener:r,notifyListeners:i}});n.default=i},function(t,n){"use strict";n.__esModule=!0;n.canUseDOM=!("undefined"==typeof window||!window.document||!window.document.createElement),n.addEventListener=function(t,n,e){return t.addEventListener?t.addEventListener(n,e,!1):t.attachEvent("on"+n,e)},n.removeEventListener=function(t,n,e){return t.removeEventListener?t.removeEventListener(n,e,!1):t.detachEvent("on"+n,e)},n.getConfirmation=function(t,n){return n(window.confirm(t))},n.supportsHistory=function(){var t=window.navigator.userAgent;return(t.indexOf("Android 2.")===-1&&t.indexOf("Android 4.0")===-1||t.indexOf("Mobile Safari")===-1||t.indexOf("Chrome")!==-1||t.indexOf("Windows Phone")!==-1)&&(window.history&&"pushState"in window.history)},n.supportsPopStateOnHashChange=function(){return window.navigator.userAgent.indexOf("Trident")===-1},n.supportsGoWithoutReloadUsingHash=function(){return window.navigator.userAgent.indexOf("Firefox")===-1},n.isExtraneousPopstateEvent=function(t){return void 0===t.state&&navigator.userAgent.indexOf("CriOS")===-1}},function(t,n,e){"use strict";var o=function(t,n,e,o,r,i,a,c){if(!t){var u;if(void 0===n)u=new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.");else{var s=[e,o,r,i,a,c],f=0;u=new Error(n.replace(/%s/g,function(){return s[f++]})),u.name="InLine truncated
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
!function(){function n(n){var t=e.get(this);return t||(t=new Map,e.set(this,t)),1<(t=a(this,t.get(n)||(t.set(n,t=function(n){function t(n){1===u&&(n||(r=r.replace(/^\s*\n\s*|\s*\n\s*$/g,"")))?p.push(0,n,r):3===u&&(n||r)?(p.push(3,n,r),u=2):2===u&&"..."===r&&n?p.push(4,n,0):2===u&&r&&!n?p.push(5,0,!0,r):5<=u&&((r||!n&&5===u)&&(p.push(u,0,r,s),u=6),n&&(p.push(u,n,0,s),u=6)),r=""}for(var e,s,u=1,r="",h="",p=[0],a=0;a<n.length;a++){a&&(1===u&&t(),t(a));for(var o=0;o<n[a].length;o++)e=n[a][o],1===u?"<"===e?(t(),p=[p],u=3):r+=e:4===u?r="--"===r&&">"===e?(u=1,""):e+r[0]:h?e===h?h="":r+=e:'"'===e||"'"===e?h=e:">"===e?(t(),u=1):u&&("="===e?(u=5,s=r,r=""):"/"===e&&(u<5||">"===n[a][o+1])?(t(),3===u&&(p=p[0]),(p=(u=p)[0]).push(2,0,u),u=0):" "===e||"\t"===e||"\n"===e||"\r"===e?(t(),u=2):r+=e),3===u&&"!--"===r&&(u=4,p=p[0])}return t(),p}(n)),t),arguments,[])).length?t:t[0]}var a=function(n,t,e,s){var u;t[0]=0;for(var r=1;r<t.length;r++){var h=t[r++],p=t[r]?(t[0]|=h?1:2,e[t[r++]]):t[++r];3===h?s[0]=p:4===h?s[1]=Object.assign(s[1]||{},p):5===h?(s[1]=s[1]||{})[t[++r]]=p:6===h?s[1][t[++r]]+=p+"":h?(u=n.apply(p,a(n,p,e,["",null])),s.push(u),p[0]?t[0]|=2:(t[r-2]=0,t[r]=u)):s.push(p)}return s},e=new Map;"undefined"!=typeof module?module.exports=n:self.htm=n}();
|
||||||
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 3.8 KiB |
@@ -0,0 +1,19 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<title>example</title>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<link rel="stylesheet" href="bootstrap.min.css" />
|
||||||
|
<link rel="stylesheet" href="style.css" />
|
||||||
|
<script src="preact.min.js"></script>
|
||||||
|
<script src="preact-router.min.js"></script>
|
||||||
|
<script src="htm.min.js"></script>
|
||||||
|
<script src="history.min.js"></script>
|
||||||
|
<script src="linkstate.min.js"></script>
|
||||||
|
<script src="axios.min.js"></script>
|
||||||
|
<script src="app.js"></script>
|
||||||
|
</head>
|
||||||
|
<body></body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
function linkState(component, key, eventPath) {
|
||||||
|
let path = key.split('.'), cache = component.__lsc || (component.__lsc = {});
|
||||||
|
|
||||||
|
return cache[key + eventPath] || (cache[key + eventPath] = function(e) {
|
||||||
|
let t = e && e.target || this, state = {}, obj = state,
|
||||||
|
v = typeof eventPath === 'string' ?
|
||||||
|
delve(e, eventPath) :
|
||||||
|
t.nodeName ? (t.type.match(/^che|rad/) ? t.checked : t.value) :
|
||||||
|
e,
|
||||||
|
i = 0;
|
||||||
|
for (; i < path.length - 1; i++) {
|
||||||
|
obj = obj[path[i]] ||
|
||||||
|
(obj[path[i]] = !i && component.state[path[i]] || {});
|
||||||
|
}
|
||||||
|
obj[path[i]] = v;
|
||||||
|
component.setState(state);
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e(require("preact")):"function"==typeof define&&define.amd?define(["preact"],e):t.preactRouter=e(t.preact)}(this,function(p){function i(t,e){for(var n in e)t[n]=e[n];return t}function u(t,e,n){var r,o=/(?:\?([^#]*))?(#.*)?$/,i=t.match(o),u={};if(i&&i[1])for(var a=i[1].split("&"),p=0;p<a.length;p++){var c=a[p].split("=");u[decodeURIComponent(c[0])]=decodeURIComponent(c.slice(1).join("="))}t=y(t.replace(o,"")),e=y(e||"");for(var f=Math.max(t.length,e.length),l=0;l<f;l++)if(e[l]&&":"===e[l].charAt(0)){var s=e[l].replace(/(^:|[+*?]+$)/g,""),h=(e[l].match(/[+*?]+$/)||v)[0]||"",d=~h.indexOf("+"),g=~h.indexOf("*"),m=t[l]||"";if(!m&&!g&&(h.indexOf("?")<0||d)){r=!1;break}if(u[s]=decodeURIComponent(m),d||g){u[s]=t.slice(l).map(decodeURIComponent).join("/");break}}else if(e[l]!==t[l]){r=!1;break}return(!0===n.default||!1!==r)&&u}function e(t,e){return t.rank<e.rank?1:t.rank>e.rank?-1:t.index-e.index}function n(t,e){return t.index=e,t.rank=(n=t).props.default?0:function(t){return y(t).map(r).join("")}(n.props.path),t.props;var n}function y(t){return t.replace(/(^\/+|\/+$)/g,"").split("/")}function r(t){return":"==t.charAt(0)?1+"*+?".indexOf(t.charAt(t.length-1))||4:5}function o(){var t;return""+((t=g&&g.location?g.location:g&&g.getCurrentLocation?g.getCurrentLocation():"undefined"!=typeof location?location:b).pathname||"")+(t.search||"")}function a(t,e){return void 0===e&&(e=!1),"string"!=typeof t&&t.url&&(e=t.replace,t=t.url),function(t){for(var e=m.length;e--;)if(m[e].canRoute(t))return 1;return}(t)&&(n=t,void 0===(r=e?"replace":"push")&&(r="push"),g&&g[r]?g[r](n):"undefined"!=typeof history&&history[r+"State"]&&history[r+"State"](null,null,n)),c(t);var n,r}function c(t){for(var e=!1,n=0;n<m.length;n++)!0===m[n].routeTo(t)&&(e=!0);for(var r=C.length;r--;)C[r](t);return e}function f(t){if(t&&t.getAttribute){var e=t.getAttribute("href"),n=t.getAttribute("target");if(e&&e.match(/^\//g)&&(!n||n.match(/^_?self$/i)))return a(e)}}function l(t){if(!(t.ctrlKey||t.metaKey||t.altKey||t.shiftKey||0!==t.button))return f(t.currentTarget||t.target||this),s(t)}function s(t){return t&&(t.stopImmediatePropagation&&t.stopImmediatePropagation(),t.stopPropagation&&t.stopPropagation(),t.preventDefault()),!1}function h(t){if(!(t.ctrlKey||t.metaKey||t.altKey||t.shiftKey||0!==t.button)){var e=t.target;do{if("A"===(e.nodeName+"").toUpperCase()&&e.getAttribute("href")){if(e.hasAttribute("native"))return;if(f(e))return s(t)}}while(e=e.parentNode)}}var d,v={},g=null,m=[],C=[],b={},U=!1,t=((d=p.Component)&&(k.__proto__=d),((k.prototype=Object.create(d&&d.prototype)).constructor=k).prototype.shouldComponentUpdate=function(t){return!0!==t.static||t.url!==this.props.url||t.onChange!==this.props.onChange},k.prototype.canRoute=function(t){return 0<this.getMatchingChildren(p.toChildArray(this.props.children),t,!1).length},k.prototype.routeTo=function(t){this.setState({url:t});var e=this.canRoute(t);return this.updating||this.forceUpdate(),e},k.prototype.componentWillMount=function(){m.push(this),this.updating=!0},k.prototype.componentDidMount=function(){var e=this;g&&(this.unlisten=g.listen(function(t){e.routeTo(""+(t.pathname||"")+(t.search||""))})),this.updating=!1},k.prototype.componentWillUnmount=function(){"function"==typeof this.unlisten&&this.unlisten(),m.splice(m.indexOf(this),1)},k.prototype.componentWillUpdate=function(){this.updating=!0},k.prototype.componentDidUpdate=function(){this.updating=!1},k.prototype.getMatchingChildren=function(t,r,o){return t.filter(n).sort(e).map(function(t){var e=u(r,t.props.path,t.props);if(e){if(!1===o)return t;var n={url:r,matches:e};return i(n,e),delete n.ref,delete n.key,p.cloneElement(t,n)}}).filter(Boolean)},k.prototype.render=function(t,e){var n=t.children,r=t.onChange,o=e.url,i=this.getMatchingChildren(p.toChildArray(n),o,!0),u=i[0]||null,a=this.previousUrl;return o!==a&&(this.previousUrl=o,"function"==typeof r&&r({router:this,url:o,previous:a,active:i,current:u})),u},k);function k(t){d.call(this,t),t.history&&(g=t.history),this.state={url:t.url||o()},U||("function"==typeof addEventListener&&(g||addEventListener("popstate",function(){c(o())}),addEventListener("click",h)),U=!0)}return t.subscribers=C,t.getCurrentUrl=o,t.route=a,(t.Router=t).Route=function(t){return p.createElement(t.component,t)},t.Link=function(t){return p.createElement("a",i({onClick:l},t))},t.exec=u,t});
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
!function(){var n,l,u,t,i,o,r,e,f={},c=[],a=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i;function s(n,l){for(var u in l)n[u]=l[u];return n}function v(n){var l=n.parentNode;l&&l.removeChild(n)}function h(n,l,u){var t,i=arguments,o={};for(t in l)"key"!==t&&"ref"!==t&&(o[t]=l[t]);if(arguments.length>3)for(u=[u],t=3;t<arguments.length;t++)u.push(i[t]);if(null!=u&&(o.children=u),"function"==typeof n&&null!=n.defaultProps)for(t in n.defaultProps)void 0===o[t]&&(o[t]=n.defaultProps[t]);return y(n,o,l&&l.key,l&&l.ref,null)}function y(l,u,t,i,o){var r={type:l,props:u,key:t,ref:i,__k:null,__:null,__b:0,__e:null,__d:void 0,__c:null,constructor:void 0,__v:o};return null==o&&(r.__v=r),n.vnode&&n.vnode(r),r}function p(n){return n.children}function d(n,l){this.props=n,this.context=l}function _(n,l){if(null==l)return n.__?_(n.__,n.__.__k.indexOf(n)+1):null;for(var u;l<n.__k.length;l++)if(null!=(u=n.__k[l])&&null!=u.__e)return u.__e;return"function"==typeof n.type?_(n):null}function m(n){var l,u;if(null!=(n=n.__)&&null!=n.__c){for(n.__e=n.__c.base=null,l=0;l<n.__k.length;l++)if(null!=(u=n.__k[l])&&null!=u.__e){n.__e=n.__c.base=u.__e;break}return m(n)}}function k(l){(!l.__d&&(l.__d=!0)&&u.push(l)&&!w.__r++||i!==n.debounceRendering)&&((i=n.debounceRendering)||t)(w)}function w(){for(var n;w.__r=u.length;)n=u.sort(function(n,l){return n.__v.__b-l.__v.__b}),u=[],n.some(function(n){var l,u,t,i,o,r,e;n.__d&&(r=(o=(l=n).__v).__e,(e=l.__P)&&(u=[],(t=s({},o)).__v=t,i=N(e,o,t,l.__n,void 0!==e.ownerSVGElement,null,u,null==r?_(o):r),z(u,o),i!=r&&m(o)))})}function g(n,l,u,t,i,o,r,e,a,s){var h,d,m,k,w,g,x,C=t&&t.__k||c,A=C.length;for(a==f&&(a=null!=r?r[0]:A?_(t,0):null),u.__k=[],h=0;h<l.length;h++)if(null!=(k=u.__k[h]=null==(k=l[h])||"boolean"==typeof k?null:"string"==typeof k||"number"==typeof k?y(null,k,null,null,k):Array.isArray(k)?y(p,{children:k},null,null,null):null!=k.__e||null!=k.__c?y(k.type,k.props,k.key,null,k.__v):k)){if(k.__=u,k.__b=u.__b+1,null===(m=C[h])||m&&k.key==m.key&&k.type===m.type)C[h]=void 0;else for(d=0;d<A;d++){if((m=C[d])&&k.key==m.key&&k.type===m.type){C[d]=void 0;break}m=null}w=N(n,k,m=m||f,i,o,r,e,a,s),(d=k.ref)&&m.ref!=d&&(x||(x=[]),m.ref&&x.push(m.ref,null,k),x.push(d,k.__c||w,k)),null!=w?(null==g&&(g=w),a=b(n,k,m,C,r,w,a),"option"==u.type?n.value="":"function"==typeof u.type&&(u.__d=a)):a&&m.__e==a&&a.parentNode!=n&&(a=_(m))}if(u.__e=g,null!=r&&"function"!=typeof u.type)for(h=r.length;h--;)null!=r[h]&&v(r[h]);for(h=A;h--;)null!=C[h]&&j(C[h],C[h]);if(x)for(h=0;h<x.length;h++)$(x[h],x[++h],x[++h])}function b(n,l,u,t,i,o,r){var e,f,c;if(void 0!==l.__d)e=l.__d,l.__d=void 0;else if(i==u||o!=r||null==o.parentNode)n:if(null==r||r.parentNode!==n)n.appendChild(o),e=null;else{for(f=r,c=0;(f=f.nextSibling)&&c<t.length;c+=2)if(f==o)break n;n.insertBefore(o,r),e=r}return void 0!==e?e:o.nextSibling}function x(n,l,u,t,i){var o;for(o in u)"children"===o||"key"===o||o in l||A(n,o,null,u[o],t);for(o in l)i&&"function"!=typeof l[o]||"children"===o||"key"===o||"value"===o||"checked"===o||u[o]===l[o]||A(n,o,l[o],u[o],t)}function C(n,l,u){"-"===l[0]?n.setProperty(l,u):n[l]="number"==typeof u&&!1===a.test(l)?u+"px":null==u?"":u}function A(n,l,u,t,i){var o,r,e,f,c;if(i?"className"===l&&(l="class"):"class"===l&&(l="className"),"style"===l)if(o=n.style,"string"==typeof u)o.cssText=u;else{if("string"==typeof t&&(o.cssText="",t=null),t)for(f in t)u&&f in u||C(o,f,"");if(u)for(c in u)t&&u[c]===t[c]||C(o,c,u[c])}else"o"===l[0]&&"n"===l[1]?(r=l!==(l=l.replace(/Capture$/,"")),e=l.toLowerCase(),l=(e in n?e:l).slice(2),u?(t||n.addEventListener(l,P,r),(n.l||(n.l={}))[l]=u):n.removeEventListener(l,P,r)):"list"!==l&&"tagName"!==l&&"form"!==l&&"type"!==l&&"size"!==l&&!i&&l in n?n[l]=null==u?"":u:"function"!=typeof u&&"dangerouslySetInnerHTML"!==l&&(l!==(l=l.replace(/^xlink:?/,""))?null==u||!1===u?n.removeAttributeNS("http://www.w3.org/1999/xlink",l.toLowerCase()):n.setAttributeNS("http://www.w3.org/1999/xlink",l.toLowerCase(),u):null==u||!1===u&&!/^ar/.test(l)?n.removeAttribute(l):n.setAttribute(l,u))}function P(l){this.l[l.type](n.event?n.event(l):l)}function E(n,l,u){var t,i;for(t=0;t<n.__k.length;t++)(i=n.__k[t])&&(i.__=n,i.__e&&("function"==typeof i.type&&i.__k.length>1&&E(i,l,u),l=b(u,i,i,n.__k,null,i.__e,l),"function"==typeof n.type&&(n.__d=l)))}function N(l,u,t,i,o,r,e,f,c){var a,v,h,y,_,m,k,w,b,x,C,A=u.type;if(void 0!==u.constructor)return null;(a=n.__b)&&a(u);try{n:if("function"==typeof A){if(w=u.props,b=(a=A.contextType)&&i[a.__c],x=a?b?b.props.value:a.__:i,t.__c?k=(v=u.__c=t.__c).__=v.__E:("prototype"in A&&A.prototype.render?u.__c=v=new A(w,x):(u.__c=v=new d(w,x),v.constructor=A,v.render=F),b&&b.sub(v),v.props=w,v.state||(v.state={}),v.context=x,v.__n=i,h=v.__d=!0,v.__h=[]),null==v.__s&&(v.__s=v.state),null!=A.getDerivedStateFromProps&&(v.__s==v.state&&(v.__s=s({},v.__s)),s(v.__s,A.getDerivedStateFromProps(w,v.__s))),y=v.props,_=v.state,h)null==A.getDerivedStateFromProps&&null!=v.componentWillMount&&v.componenLine truncated
|
||||||
|
//# sourceMappingURL=preact.min.js.map
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
html, body { margin: 0; padding: 0; height: 100%; }
|
||||||
|
select, input, label::before, textarea { outline: none; box-shadow:none !important; border: 1px solid #ccc !important; }
|
||||||
|
.btn:focus,.btn:active:focus,.btn.active:focus,
|
||||||
|
.btn.focus,.btn:active.focus,.btn.active.focus { outline: none; box-shadow:none !important; }
|
||||||
|
.dropdown.autoexpand:hover>.dropdown-menu { display: block; }
|
||||||
|
.pointer { cursor: pointer; }
|
||||||
|
.log { max-height: 10em; overflow: auto; height: 100%; }
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
PROG ?= example
|
||||||
|
|
||||||
|
all: $(PROG)
|
||||||
|
$(DEBUGGER) ./$(PROG)
|
||||||
|
|
||||||
|
$(PROG):
|
||||||
|
$(CC) ../../mongoose.c -I../.. $(CFLAGS) $(EXTRA) -o $(PROG) main.c mjson.c
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf $(PROG) *.o *.dSYM *.gcov *.gcno *.gcda *.obj *.exe *.ilk *.pdb log.txt
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
// Copyright (c) 2020 Cesanta Software Limited
|
||||||
|
// All rights reserved
|
||||||
|
|
||||||
|
#include "mjson.h" // JSON parsing and printing
|
||||||
|
#include "mongoose.h"
|
||||||
|
|
||||||
|
// This is a configuration structure we're going to show on a dashboard
|
||||||
|
static struct config {
|
||||||
|
int value1;
|
||||||
|
char *value2;
|
||||||
|
} s_config = {123, NULL};
|
||||||
|
|
||||||
|
// Stringifies the config. A caller must free() it.
|
||||||
|
static char *stringify_config(struct config *cfg) {
|
||||||
|
char *s = NULL;
|
||||||
|
mjson_printf(mjson_print_dynamic_buf, &s, "{%Q:%d,%Q:%Q}", "value1",
|
||||||
|
cfg->value1, "value2", cfg->value2);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update config structure. Return true if changed, false otherwise
|
||||||
|
static bool update_config(struct mg_http_message *hm, struct config *cfg) {
|
||||||
|
bool changed = false;
|
||||||
|
char buf[256];
|
||||||
|
double dv;
|
||||||
|
if (mjson_get_number(hm->body.ptr, hm->body.len, "$.value1", &dv)) {
|
||||||
|
s_config.value1 = dv;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
if (mjson_get_string(hm->body.ptr, hm->body.len, "$.value2", buf,
|
||||||
|
sizeof(buf)) > 0) {
|
||||||
|
free(s_config.value2);
|
||||||
|
s_config.value2 = strdup(buf);
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Notify all config watchers about the config change
|
||||||
|
static void notify_config_change(struct mg_mgr *mgr) {
|
||||||
|
struct mg_connection *c;
|
||||||
|
char *s = stringify_config(&s_config);
|
||||||
|
for (c = mgr->conns; c != NULL; c = c->next) {
|
||||||
|
if (c->label[0] == 'W') mg_http_printf_chunk(c, "%s\n", s);
|
||||||
|
}
|
||||||
|
free(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
// HTTP request handler function. It implements the following endpoints:
|
||||||
|
// /api/config/get - returns current config
|
||||||
|
// /api/config/set - updates current config
|
||||||
|
// /api/config/watch - does not return. Sends config as it changes in
|
||||||
|
// chunks all other URI - serves web_root/ directory
|
||||||
|
static void cb(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
|
||||||
|
if (ev == MG_EV_HTTP_MSG) {
|
||||||
|
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||||
|
if (mg_http_match_uri(hm, "/api/config/get")) {
|
||||||
|
char *s = stringify_config(&s_config);
|
||||||
|
mg_printf(c, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\n\r\n%s\n",
|
||||||
|
(int) strlen(s) + 1, s);
|
||||||
|
free(s);
|
||||||
|
} else if (mg_http_match_uri(hm, "/api/config/set")) {
|
||||||
|
if (update_config(hm, &s_config)) notify_config_change(fn_data);
|
||||||
|
mg_printf(c, "HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n");
|
||||||
|
} else if (mg_http_match_uri(hm, "/api/config/watch")) {
|
||||||
|
c->label[0] = 'W'; // Mark ourselves as a config watcher
|
||||||
|
mg_printf(c, "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n");
|
||||||
|
} else {
|
||||||
|
struct mg_http_serve_opts opts = {.root_dir = "web_root"};
|
||||||
|
mg_http_serve_dir(c, ev_data, &opts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
struct mg_mgr mgr;
|
||||||
|
mg_mgr_init(&mgr);
|
||||||
|
mg_http_listen(&mgr, "http://localhost:8000", cb, &mgr);
|
||||||
|
for (;;) mg_mgr_poll(&mgr, 1000);
|
||||||
|
mg_mgr_free(&mgr);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,981 @@
|
|||||||
|
// Copyright (c) 2018-2020 Cesanta Software Limited
|
||||||
|
// All rights reserved
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
#include "mjson.h"
|
||||||
|
|
||||||
|
#if !defined(_MSC_VER) || _MSC_VER >= 1700
|
||||||
|
#else
|
||||||
|
#define va_copy(x, y) (x) = (y)
|
||||||
|
#define snprintf _snprintf
|
||||||
|
#define alloca _alloca
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int mjson_esc(int c, int esc) {
|
||||||
|
const char *p, *esc1 = "\b\f\n\r\t\\\"", *esc2 = "bfnrt\\\"";
|
||||||
|
for (p = esc ? esc1 : esc2; *p != '\0'; p++) {
|
||||||
|
if (*p == c) return esc ? esc2[p - esc1] : esc1[p - esc2];
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mjson_pass_string(const char *s, int len) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
if (s[i] == '\\' && i + 1 < len && mjson_esc(s[i + 1], 1)) {
|
||||||
|
i++;
|
||||||
|
} else if (s[i] == '\0') {
|
||||||
|
return MJSON_ERROR_INVALID_INPUT;
|
||||||
|
} else if (s[i] == '"') {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return MJSON_ERROR_INVALID_INPUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mjson(const char *s, int len, mjson_cb_t cb, void *ud) {
|
||||||
|
enum { S_VALUE, S_KEY, S_COLON, S_COMMA_OR_EOO } expecting = S_VALUE;
|
||||||
|
unsigned char nesting[MJSON_MAX_DEPTH];
|
||||||
|
int i, depth = 0;
|
||||||
|
#define MJSONCALL(ev) \
|
||||||
|
if (cb != NULL && cb(ev, s, start, i - start + 1, ud)) return i + 1;
|
||||||
|
|
||||||
|
// In the ascii table, the distance between `[` and `]` is 2.
|
||||||
|
// Ditto for `{` and `}`. Hence +2 in the code below.
|
||||||
|
#define MJSONEOO() \
|
||||||
|
do { \
|
||||||
|
if (c != nesting[depth - 1] + 2) return MJSON_ERROR_INVALID_INPUT; \
|
||||||
|
depth--; \
|
||||||
|
if (depth == 0) { \
|
||||||
|
MJSONCALL(tok); \
|
||||||
|
return i + 1; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
int start = i;
|
||||||
|
unsigned char c = ((unsigned char *) s)[i];
|
||||||
|
int tok = c;
|
||||||
|
if (c == ' ' || c == '\t' || c == '\n' || c == '\r') continue;
|
||||||
|
// printf("- %c [%.*s] %d %d\n", c, i, s, depth, expecting);
|
||||||
|
switch (expecting) {
|
||||||
|
case S_VALUE:
|
||||||
|
if (c == '{') {
|
||||||
|
if (depth >= (int) sizeof(nesting)) return MJSON_ERROR_TOO_DEEP;
|
||||||
|
nesting[depth++] = c;
|
||||||
|
expecting = S_KEY;
|
||||||
|
break;
|
||||||
|
} else if (c == '[') {
|
||||||
|
if (depth >= (int) sizeof(nesting)) return MJSON_ERROR_TOO_DEEP;
|
||||||
|
nesting[depth++] = c;
|
||||||
|
break;
|
||||||
|
} else if (c == ']' && depth > 0) { // Empty array
|
||||||
|
MJSONEOO();
|
||||||
|
} else if (c == 't' && i + 3 < len && memcmp(&s[i], "true", 4) == 0) {
|
||||||
|
i += 3;
|
||||||
|
tok = MJSON_TOK_TRUE;
|
||||||
|
} else if (c == 'n' && i + 3 < len && memcmp(&s[i], "null", 4) == 0) {
|
||||||
|
i += 3;
|
||||||
|
tok = MJSON_TOK_NULL;
|
||||||
|
} else if (c == 'f' && i + 4 < len && memcmp(&s[i], "false", 5) == 0) {
|
||||||
|
i += 4;
|
||||||
|
tok = MJSON_TOK_FALSE;
|
||||||
|
} else if (c == '-' || ((c >= '0' && c <= '9'))) {
|
||||||
|
char *end = NULL;
|
||||||
|
strtod(&s[i], &end);
|
||||||
|
if (end != NULL) i += end - &s[i] - 1;
|
||||||
|
tok = MJSON_TOK_NUMBER;
|
||||||
|
} else if (c == '"') {
|
||||||
|
int n = mjson_pass_string(&s[i + 1], len - i - 1);
|
||||||
|
if (n < 0) return n;
|
||||||
|
i += n + 1;
|
||||||
|
tok = MJSON_TOK_STRING;
|
||||||
|
} else {
|
||||||
|
return MJSON_ERROR_INVALID_INPUT;
|
||||||
|
}
|
||||||
|
if (depth == 0) {
|
||||||
|
MJSONCALL(tok);
|
||||||
|
return i + 1;
|
||||||
|
}
|
||||||
|
expecting = S_COMMA_OR_EOO;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case S_KEY:
|
||||||
|
if (c == '"') {
|
||||||
|
int n = mjson_pass_string(&s[i + 1], len - i - 1);
|
||||||
|
if (n < 0) return n;
|
||||||
|
i += n + 1;
|
||||||
|
tok = MJSON_TOK_KEY;
|
||||||
|
expecting = S_COLON;
|
||||||
|
} else if (c == '}') { // Empty object
|
||||||
|
MJSONEOO();
|
||||||
|
expecting = S_COMMA_OR_EOO;
|
||||||
|
} else {
|
||||||
|
return MJSON_ERROR_INVALID_INPUT;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case S_COLON:
|
||||||
|
if (c == ':') {
|
||||||
|
expecting = S_VALUE;
|
||||||
|
} else {
|
||||||
|
return MJSON_ERROR_INVALID_INPUT;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case S_COMMA_OR_EOO:
|
||||||
|
if (depth <= 0) return MJSON_ERROR_INVALID_INPUT;
|
||||||
|
if (c == ',') {
|
||||||
|
expecting = (nesting[depth - 1] == '{') ? S_KEY : S_VALUE;
|
||||||
|
} else if (c == ']' || c == '}') {
|
||||||
|
MJSONEOO();
|
||||||
|
} else {
|
||||||
|
return MJSON_ERROR_INVALID_INPUT;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
MJSONCALL(tok);
|
||||||
|
}
|
||||||
|
return MJSON_ERROR_INVALID_INPUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct msjon_get_data {
|
||||||
|
const char *path; // Lookup json path
|
||||||
|
int pos; // Current path index
|
||||||
|
int d1; // Current depth of traversal
|
||||||
|
int d2; // Expected depth of traversal
|
||||||
|
int i1; // Index in an array
|
||||||
|
int i2; // Expected index in an array
|
||||||
|
int obj; // If the value is array/object, offset where it starts
|
||||||
|
const char **tokptr; // Destination
|
||||||
|
int *toklen; // Destination length
|
||||||
|
int tok; // Returned token
|
||||||
|
};
|
||||||
|
|
||||||
|
static int mjson_plen(const char *s) {
|
||||||
|
int i = 0;
|
||||||
|
while (s[i] != '\0' && s[i] != '.' && s[i] != '[') i++;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mjson_get_cb(int tok, const char *s, int off, int len, void *ud) {
|
||||||
|
struct msjon_get_data *data = (struct msjon_get_data *) ud;
|
||||||
|
// printf("--> %2x %2d %2d %2d %2d\t'%s'\t'%.*s'\t\t'%.*s'\n", tok, data->d1,
|
||||||
|
// data->d2, data->i1, data->i2, data->path + data->pos, off, s, len,
|
||||||
|
// s + off);
|
||||||
|
if (data->tok != MJSON_TOK_INVALID) return 1; // Found
|
||||||
|
|
||||||
|
if (tok == '{') {
|
||||||
|
if (!data->path[data->pos] && data->d1 == data->d2) data->obj = off;
|
||||||
|
data->d1++;
|
||||||
|
} else if (tok == '[') {
|
||||||
|
if (data->d1 == data->d2 && data->path[data->pos] == '[') {
|
||||||
|
data->i1 = 0;
|
||||||
|
data->i2 = (int) strtod(&data->path[data->pos + 1], NULL);
|
||||||
|
if (data->i1 == data->i2) {
|
||||||
|
data->d2++;
|
||||||
|
data->pos += 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!data->path[data->pos] && data->d1 == data->d2) data->obj = off;
|
||||||
|
data->d1++;
|
||||||
|
} else if (tok == ',') {
|
||||||
|
if (data->d1 == data->d2 + 1) {
|
||||||
|
data->i1++;
|
||||||
|
if (data->i1 == data->i2) {
|
||||||
|
while (data->path[data->pos] != ']') data->pos++;
|
||||||
|
data->pos++;
|
||||||
|
data->d2++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (tok == MJSON_TOK_KEY && data->d1 == data->d2 + 1 &&
|
||||||
|
data->path[data->pos] == '.' && s[off] == '"' &&
|
||||||
|
s[off + len - 1] == '"' &&
|
||||||
|
mjson_plen(&data->path[data->pos + 1]) == len - 2 &&
|
||||||
|
!memcmp(s + off + 1, &data->path[data->pos + 1], len - 2)) {
|
||||||
|
data->d2++;
|
||||||
|
data->pos += len - 1;
|
||||||
|
} else if (tok == MJSON_TOK_KEY && data->d1 == data->d2) {
|
||||||
|
return 1; // Exhausted path, not found
|
||||||
|
} else if (tok == '}' || tok == ']') {
|
||||||
|
data->d1--;
|
||||||
|
// data->d2--;
|
||||||
|
if (!data->path[data->pos] && data->d1 == data->d2 && data->obj != -1) {
|
||||||
|
data->tok = tok - 2;
|
||||||
|
if (data->tokptr) *data->tokptr = s + data->obj;
|
||||||
|
if (data->toklen) *data->toklen = off - data->obj + 1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} else if (MJSON_TOK_IS_VALUE(tok)) {
|
||||||
|
// printf("TOK --> %d\n", tok);
|
||||||
|
if (data->d1 == data->d2 && !data->path[data->pos]) {
|
||||||
|
data->tok = tok;
|
||||||
|
if (data->tokptr) *data->tokptr = s + off;
|
||||||
|
if (data->toklen) *data->toklen = len;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum mjson_tok mjson_find(const char *s, int len, const char *jp,
|
||||||
|
const char **tokptr, int *toklen) {
|
||||||
|
struct msjon_get_data data = {jp, 1, 0, 0, 0,
|
||||||
|
0, -1, tokptr, toklen, MJSON_TOK_INVALID};
|
||||||
|
if (jp[0] != '$') return MJSON_TOK_INVALID;
|
||||||
|
if (mjson(s, len, mjson_get_cb, &data) < 0) return MJSON_TOK_INVALID;
|
||||||
|
return (enum mjson_tok) data.tok;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mjson_get_number(const char *s, int len, const char *path, double *v) {
|
||||||
|
const char *p;
|
||||||
|
int tok, n;
|
||||||
|
if ((tok = mjson_find(s, len, path, &p, &n)) == MJSON_TOK_NUMBER) {
|
||||||
|
if (v != NULL) *v = strtod(p, NULL);
|
||||||
|
}
|
||||||
|
return tok == MJSON_TOK_NUMBER ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mjson_get_bool(const char *s, int len, const char *path, int *v) {
|
||||||
|
int tok = mjson_find(s, len, path, NULL, NULL);
|
||||||
|
if (tok == MJSON_TOK_TRUE && v != NULL) *v = 1;
|
||||||
|
if (tok == MJSON_TOK_FALSE && v != NULL) *v = 0;
|
||||||
|
return tok == MJSON_TOK_TRUE || tok == MJSON_TOK_FALSE ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mjson_unescape(const char *s, int len, char *to, int n) {
|
||||||
|
int i, j;
|
||||||
|
for (i = 0, j = 0; i < len && j < n; i++, j++) {
|
||||||
|
if (s[i] == '\\' && i + 1 < len) {
|
||||||
|
int c = mjson_esc(s[i + 1], 0);
|
||||||
|
if (c == 0) return -1;
|
||||||
|
to[j] = c;
|
||||||
|
i++;
|
||||||
|
} else {
|
||||||
|
to[j] = s[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (j >= n) return -1;
|
||||||
|
if (n > 0) to[j] = '\0';
|
||||||
|
return j;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mjson_get_string(const char *s, int len, const char *path, char *to,
|
||||||
|
int n) {
|
||||||
|
const char *p;
|
||||||
|
int sz;
|
||||||
|
if (mjson_find(s, len, path, &p, &sz) != MJSON_TOK_STRING) return -1;
|
||||||
|
return mjson_unescape(p + 1, sz - 2, to, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
int mjson_get_hex(const char *s, int len, const char *x, char *to, int n) {
|
||||||
|
const char *p;
|
||||||
|
int i, j, sz;
|
||||||
|
if (mjson_find(s, len, x, &p, &sz) != MJSON_TOK_STRING) return -1;
|
||||||
|
for (i = j = 0; i < sz - 3 && j < n; i += 2, j++) {
|
||||||
|
#define HEXTOI(x) (x >= '0' && x <= '9' ? x - '0' : x - 'W')
|
||||||
|
unsigned char a = *(const unsigned char *) (p + i + 1);
|
||||||
|
unsigned char b = *(const unsigned char *) (p + i + 2);
|
||||||
|
((unsigned char *) to)[j] = (HEXTOI(a) << 4) | HEXTOI(b);
|
||||||
|
}
|
||||||
|
if (j < n) to[j] = '\0';
|
||||||
|
return j;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if MJSON_ENABLE_BASE64
|
||||||
|
static int mjson_base64rev(int c) {
|
||||||
|
if (c >= 'A' && c <= 'Z') {
|
||||||
|
return c - 'A';
|
||||||
|
} else if (c >= 'a' && c <= 'z') {
|
||||||
|
return c + 26 - 'a';
|
||||||
|
} else if (c >= '0' && c <= '9') {
|
||||||
|
return c + 52 - '0';
|
||||||
|
} else if (c == '+') {
|
||||||
|
return 62;
|
||||||
|
} else if (c == '/') {
|
||||||
|
return 63;
|
||||||
|
} else {
|
||||||
|
return 64;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int mjson_base64_dec(const char *src, int n, char *dst, int dlen) {
|
||||||
|
const char *end = src + n;
|
||||||
|
int len = 0;
|
||||||
|
while (src + 3 < end && len < dlen) {
|
||||||
|
int a = mjson_base64rev(src[0]), b = mjson_base64rev(src[1]),
|
||||||
|
c = mjson_base64rev(src[2]), d = mjson_base64rev(src[3]);
|
||||||
|
dst[len++] = (a << 2) | (b >> 4);
|
||||||
|
if (src[2] != '=' && len < dlen) {
|
||||||
|
dst[len++] = (b << 4) | (c >> 2);
|
||||||
|
if (src[3] != '=' && len < dlen) {
|
||||||
|
dst[len++] = (c << 6) | d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
src += 4;
|
||||||
|
}
|
||||||
|
if (len < dlen) dst[len] = '\0';
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mjson_get_base64(const char *s, int len, const char *path, char *to,
|
||||||
|
int n) {
|
||||||
|
const char *p;
|
||||||
|
int sz;
|
||||||
|
if (mjson_find(s, len, path, &p, &sz) != MJSON_TOK_STRING) return 0;
|
||||||
|
return mjson_base64_dec(p + 1, sz - 2, to, n);
|
||||||
|
}
|
||||||
|
#endif // MJSON_ENABLE_BASE64
|
||||||
|
|
||||||
|
#if MJSON_ENABLE_NEXT
|
||||||
|
struct nextdata {
|
||||||
|
int off, len, depth, t, vo, arrayindex;
|
||||||
|
int *koff, *klen, *voff, *vlen, *vtype;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int next_cb(int tok, const char *s, int off, int len, void *ud) {
|
||||||
|
struct nextdata *d = (struct nextdata *) ud;
|
||||||
|
// int i;
|
||||||
|
switch (tok) {
|
||||||
|
case '{':
|
||||||
|
case '[':
|
||||||
|
if (d->depth == 0 && tok == '[') d->arrayindex = 0;
|
||||||
|
if (d->depth == 1 && off > d->off) {
|
||||||
|
d->vo = off;
|
||||||
|
d->t = tok == '{' ? MJSON_TOK_OBJECT : MJSON_TOK_ARRAY;
|
||||||
|
if (d->voff) *d->voff = off;
|
||||||
|
if (d->vtype) *d->vtype = d->t;
|
||||||
|
}
|
||||||
|
d->depth++;
|
||||||
|
break;
|
||||||
|
case '}':
|
||||||
|
case ']':
|
||||||
|
d->depth--;
|
||||||
|
if (d->depth == 1 && d->vo) {
|
||||||
|
d->len = off + len;
|
||||||
|
if (d->vlen) *d->vlen = d->len - d->vo;
|
||||||
|
if (d->arrayindex >= 0) {
|
||||||
|
if (d->koff) *d->koff = d->arrayindex; // koff holds array index
|
||||||
|
if (d->klen) *d->klen = 0; // klen holds 0
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (d->depth == 1 && d->arrayindex >= 0) d->arrayindex++;
|
||||||
|
break;
|
||||||
|
case ',':
|
||||||
|
case ':':
|
||||||
|
break;
|
||||||
|
case MJSON_TOK_KEY:
|
||||||
|
if (d->depth == 1 && d->off < off) {
|
||||||
|
if (d->koff) *d->koff = off; // And report back to the user
|
||||||
|
if (d->klen) *d->klen = len; // If we have to
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (d->depth != 1) break;
|
||||||
|
// If we're iterating over the array
|
||||||
|
if (off > d->off) {
|
||||||
|
d->len = off + len;
|
||||||
|
if (d->vlen) *d->vlen = len; // value length
|
||||||
|
if (d->voff) *d->voff = off; // value offset
|
||||||
|
if (d->vtype) *d->vtype = tok; // value type
|
||||||
|
if (d->arrayindex >= 0) {
|
||||||
|
if (d->koff) *d->koff = d->arrayindex; // koff holds array index
|
||||||
|
if (d->klen) *d->klen = 0; // klen holds 0
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (d->arrayindex >= 0) d->arrayindex++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
(void) s;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mjson_next(const char *s, int n, int off, int *koff, int *klen, int *voff,
|
||||||
|
int *vlen, int *vtype) {
|
||||||
|
struct nextdata d = {off, 0, 0, 0, 0, -1, koff, klen, voff, vlen, vtype};
|
||||||
|
mjson(s, n, next_cb, &d);
|
||||||
|
return d.len;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MJSON_ENABLE_PRINT
|
||||||
|
int mjson_print_fixed_buf(const char *ptr, int len, void *fndata) {
|
||||||
|
struct mjson_fixedbuf *fb = (struct mjson_fixedbuf *) fndata;
|
||||||
|
int i, left = fb->size - 1 - fb->len;
|
||||||
|
if (left < len) len = left;
|
||||||
|
for (i = 0; i < len; i++) fb->ptr[fb->len + i] = ptr[i];
|
||||||
|
fb->len += len;
|
||||||
|
fb->ptr[fb->len] = '\0';
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mjson_print_dynamic_buf(const char *ptr, int len, void *fndata) {
|
||||||
|
char *s, *buf = *(char **) fndata;
|
||||||
|
int curlen = buf == NULL ? 0 : strlen(buf);
|
||||||
|
if ((s = (char *) realloc(buf, curlen + len + 1)) == NULL) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
memcpy(s + curlen, ptr, len);
|
||||||
|
s[curlen + len] = '\0';
|
||||||
|
*(char **) fndata = s;
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int mjson_print_null(const char *ptr, int len, void *userdata) {
|
||||||
|
(void) ptr;
|
||||||
|
(void) userdata;
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mjson_print_file(const char *ptr, int len, void *userdata) {
|
||||||
|
return fwrite(ptr, 1, len, (FILE *) userdata);
|
||||||
|
}
|
||||||
|
|
||||||
|
int mjson_print_buf(mjson_print_fn_t fn, void *fndata, const char *buf,
|
||||||
|
int len) {
|
||||||
|
return fn(buf, len, fndata);
|
||||||
|
}
|
||||||
|
|
||||||
|
int mjson_print_int(mjson_print_fn_t fn, void *fndata, int value,
|
||||||
|
int is_signed) {
|
||||||
|
char buf[20];
|
||||||
|
int len = snprintf(buf, sizeof(buf), is_signed ? "%d" : "%u", value);
|
||||||
|
return fn(buf, len, fndata);
|
||||||
|
}
|
||||||
|
|
||||||
|
int mjson_print_long(mjson_print_fn_t fn, void *fndata, long value,
|
||||||
|
int is_signed) {
|
||||||
|
char buf[20];
|
||||||
|
const char *fmt = (is_signed ? "%ld" : "%lu");
|
||||||
|
int len = snprintf(buf, sizeof(buf), fmt, value);
|
||||||
|
return fn(buf, len, fndata);
|
||||||
|
}
|
||||||
|
|
||||||
|
int mjson_print_dbl(mjson_print_fn_t fn, void *fndata, double d,
|
||||||
|
const char *fmt) {
|
||||||
|
char buf[40];
|
||||||
|
int n = snprintf(buf, sizeof(buf), fmt, d);
|
||||||
|
return fn(buf, n, fndata);
|
||||||
|
}
|
||||||
|
|
||||||
|
int mjson_print_str(mjson_print_fn_t fn, void *fndata, const char *s, int len) {
|
||||||
|
int i, n = fn("\"", 1, fndata);
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
char c = mjson_esc(s[i], 1);
|
||||||
|
if (c) {
|
||||||
|
n += fn("\\", 1, fndata);
|
||||||
|
n += fn(&c, 1, fndata);
|
||||||
|
} else {
|
||||||
|
n += fn(&s[i], 1, fndata);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return n + fn("\"", 1, fndata);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if MJSON_ENABLE_BASE64
|
||||||
|
int mjson_print_b64(mjson_print_fn_t fn, void *fndata, const unsigned char *s,
|
||||||
|
int n) {
|
||||||
|
const char *t =
|
||||||
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||||
|
int i, len = fn("\"", 1, fndata);
|
||||||
|
for (i = 0; i < n; i += 3) {
|
||||||
|
int a = s[i], b = i + 1 < n ? s[i + 1] : 0, c = i + 2 < n ? s[i + 2] : 0;
|
||||||
|
char buf[4] = {t[a >> 2], t[(a & 3) << 4 | (b >> 4)], '=', '='};
|
||||||
|
if (i + 1 < n) buf[2] = t[(b & 15) << 2 | (c >> 6)];
|
||||||
|
if (i + 2 < n) buf[3] = t[c & 63];
|
||||||
|
len += fn(buf, sizeof(buf), fndata);
|
||||||
|
}
|
||||||
|
return len + fn("\"", 1, fndata);
|
||||||
|
}
|
||||||
|
#endif /* MJSON_ENABLE_BASE64 */
|
||||||
|
|
||||||
|
int mjson_vprintf(mjson_print_fn_t fn, void *fndata, const char *fmt,
|
||||||
|
va_list xap) {
|
||||||
|
int i = 0, n = 0;
|
||||||
|
va_list ap;
|
||||||
|
va_copy(ap, xap);
|
||||||
|
while (fmt[i] != '\0') {
|
||||||
|
if (fmt[i] == '%') {
|
||||||
|
char fc = fmt[++i];
|
||||||
|
int is_long = 0;
|
||||||
|
if (fc == 'l') {
|
||||||
|
is_long = 1;
|
||||||
|
fc = fmt[i + 1];
|
||||||
|
}
|
||||||
|
if (fc == 'Q') {
|
||||||
|
char *buf = va_arg(ap, char *);
|
||||||
|
n += mjson_print_str(fn, fndata, buf ? buf : "", buf ? strlen(buf) : 0);
|
||||||
|
} else if (strncmp(&fmt[i], ".*Q", 3) == 0) {
|
||||||
|
int len = va_arg(ap, int);
|
||||||
|
char *buf = va_arg(ap, char *);
|
||||||
|
n += mjson_print_str(fn, fndata, buf, len);
|
||||||
|
i += 2;
|
||||||
|
} else if (fc == 'd' || fc == 'u') {
|
||||||
|
int is_signed = (fc == 'd');
|
||||||
|
if (is_long) {
|
||||||
|
long val = va_arg(ap, long);
|
||||||
|
n += mjson_print_long(fn, fndata, val, is_signed);
|
||||||
|
i++;
|
||||||
|
} else {
|
||||||
|
int val = va_arg(ap, int);
|
||||||
|
n += mjson_print_int(fn, fndata, val, is_signed);
|
||||||
|
}
|
||||||
|
} else if (fc == 'B') {
|
||||||
|
const char *s = va_arg(ap, int) ? "true" : "false";
|
||||||
|
n += mjson_print_buf(fn, fndata, s, strlen(s));
|
||||||
|
} else if (fc == 's') {
|
||||||
|
char *buf = va_arg(ap, char *);
|
||||||
|
n += mjson_print_buf(fn, fndata, buf, strlen(buf));
|
||||||
|
} else if (strncmp(&fmt[i], ".*s", 3) == 0) {
|
||||||
|
int len = va_arg(ap, int);
|
||||||
|
char *buf = va_arg(ap, char *);
|
||||||
|
n += mjson_print_buf(fn, fndata, buf, len);
|
||||||
|
i += 2;
|
||||||
|
} else if (fc == 'g') {
|
||||||
|
n += mjson_print_dbl(fn, fndata, va_arg(ap, double), "%g");
|
||||||
|
} else if (fc == 'f') {
|
||||||
|
n += mjson_print_dbl(fn, fndata, va_arg(ap, double), "%f");
|
||||||
|
#if MJSON_ENABLE_BASE64
|
||||||
|
} else if (fc == 'V') {
|
||||||
|
int len = va_arg(ap, int);
|
||||||
|
const char *buf = va_arg(ap, const char *);
|
||||||
|
n += mjson_print_b64(fn, fndata, (unsigned char *) buf, len);
|
||||||
|
#endif
|
||||||
|
} else if (fc == 'H') {
|
||||||
|
const char *hex = "0123456789abcdef";
|
||||||
|
int i, len = va_arg(ap, int);
|
||||||
|
const unsigned char *p = va_arg(ap, const unsigned char *);
|
||||||
|
n += fn("\"", 1, fndata);
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
n += fn(&hex[(p[i] >> 4) & 15], 1, fndata);
|
||||||
|
n += fn(&hex[p[i] & 15], 1, fndata);
|
||||||
|
}
|
||||||
|
n += fn("\"", 1, fndata);
|
||||||
|
} else if (fc == 'M') {
|
||||||
|
mjson_vprint_fn_t vfn = va_arg(ap, mjson_vprint_fn_t);
|
||||||
|
n += vfn(fn, fndata, &ap);
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
} else {
|
||||||
|
n += mjson_print_buf(fn, fndata, &fmt[i++], 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
va_end(xap);
|
||||||
|
va_end(ap);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mjson_printf(mjson_print_fn_t fn, void *fndata, const char *fmt, ...) {
|
||||||
|
va_list ap;
|
||||||
|
int len;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
len = mjson_vprintf(fn, fndata, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
#endif /* MJSON_ENABLE_PRINT */
|
||||||
|
|
||||||
|
#if MJSON_IMPLEMENT_STRTOD
|
||||||
|
static inline int is_digit(int c) {
|
||||||
|
return c >= '0' && c <= '9';
|
||||||
|
}
|
||||||
|
|
||||||
|
/* NOTE: strtod() implementation by Yasuhiro Matsumoto. */
|
||||||
|
double strtod(const char *str, char **end) {
|
||||||
|
double d = 0.0;
|
||||||
|
int sign = 1, n = 0;
|
||||||
|
const char *p = str, *a = str;
|
||||||
|
|
||||||
|
/* decimal part */
|
||||||
|
if (*p == '-') {
|
||||||
|
sign = -1;
|
||||||
|
++p;
|
||||||
|
} else if (*p == '+')
|
||||||
|
++p;
|
||||||
|
if (is_digit(*p)) {
|
||||||
|
d = (double) (*p++ - '0');
|
||||||
|
while (*p && is_digit(*p)) {
|
||||||
|
d = d * 10.0 + (double) (*p - '0');
|
||||||
|
++p;
|
||||||
|
++n;
|
||||||
|
}
|
||||||
|
a = p;
|
||||||
|
} else if (*p != '.')
|
||||||
|
goto done;
|
||||||
|
d *= sign;
|
||||||
|
|
||||||
|
/* fraction part */
|
||||||
|
if (*p == '.') {
|
||||||
|
double f = 0.0;
|
||||||
|
double base = 0.1;
|
||||||
|
++p;
|
||||||
|
|
||||||
|
if (is_digit(*p)) {
|
||||||
|
while (*p && is_digit(*p)) {
|
||||||
|
f += base * (*p - '0');
|
||||||
|
base /= 10.0;
|
||||||
|
++p;
|
||||||
|
++n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
d += f * sign;
|
||||||
|
a = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* exponential part */
|
||||||
|
if ((*p == 'E') || (*p == 'e')) {
|
||||||
|
int e = 0;
|
||||||
|
++p;
|
||||||
|
|
||||||
|
sign = 1;
|
||||||
|
if (*p == '-') {
|
||||||
|
sign = -1;
|
||||||
|
++p;
|
||||||
|
} else if (*p == '+')
|
||||||
|
++p;
|
||||||
|
|
||||||
|
if (is_digit(*p)) {
|
||||||
|
while (*p == '0') ++p;
|
||||||
|
e = (int) (*p++ - '0');
|
||||||
|
while (*p && is_digit(*p)) {
|
||||||
|
e = e * 10 + (int) (*p - '0');
|
||||||
|
++p;
|
||||||
|
}
|
||||||
|
e *= sign;
|
||||||
|
} else if (!is_digit(*(a - 1))) {
|
||||||
|
a = str;
|
||||||
|
goto done;
|
||||||
|
} else if (*p == 0)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
if (d == 2.2250738585072011 && e == -308) {
|
||||||
|
d = 0.0;
|
||||||
|
a = p;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (d == 2.2250738585072012 && e <= -308) {
|
||||||
|
d *= 1.0e-308;
|
||||||
|
a = p;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < 10; i++) d *= 10;
|
||||||
|
}
|
||||||
|
a = p;
|
||||||
|
} else if (p > str && !is_digit(*(p - 1))) {
|
||||||
|
a = str;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
if (end) *end = (char *) a;
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MJSON_ENABLE_MERGE
|
||||||
|
int mjson_merge(const char *s, int n, const char *s2, int n2,
|
||||||
|
mjson_print_fn_t fn, void *userdata) {
|
||||||
|
int koff, klen, voff, vlen, t, t2, k, off = 0, len = 0, comma = 0;
|
||||||
|
if (n < 2) return len;
|
||||||
|
len += fn("{", 1, userdata);
|
||||||
|
while ((off = mjson_next(s, n, off, &koff, &klen, &voff, &vlen, &t)) != 0) {
|
||||||
|
#if !defined(_MSC_VER) || _MSC_VER >= 1700
|
||||||
|
char path[klen + 1];
|
||||||
|
#else
|
||||||
|
char *path = (char *) alloca(klen + 1);
|
||||||
|
#endif
|
||||||
|
const char *val;
|
||||||
|
memcpy(path, "$.", 2);
|
||||||
|
memcpy(path + 2, s + koff + 1, klen - 2);
|
||||||
|
path[klen] = '\0';
|
||||||
|
if ((t2 = mjson_find(s2, n2, path, &val, &k)) != MJSON_TOK_INVALID) {
|
||||||
|
if (t2 == MJSON_TOK_NULL) continue; // null deletes the key
|
||||||
|
} else {
|
||||||
|
val = s + voff; // Key is not found in the update. Copy the old value.
|
||||||
|
}
|
||||||
|
if (comma) len += fn(",", 1, userdata);
|
||||||
|
len += fn(s + koff, klen, userdata);
|
||||||
|
len += fn(":", 1, userdata);
|
||||||
|
if (t == MJSON_TOK_OBJECT && t2 == MJSON_TOK_OBJECT) {
|
||||||
|
len += mjson_merge(s + voff, vlen, val, k, fn, userdata);
|
||||||
|
} else {
|
||||||
|
if (t2 != MJSON_TOK_INVALID) vlen = k;
|
||||||
|
len += fn(val, vlen, userdata);
|
||||||
|
}
|
||||||
|
comma = 1;
|
||||||
|
}
|
||||||
|
// Add missing keys
|
||||||
|
off = 0;
|
||||||
|
while ((off = mjson_next(s2, n2, off, &koff, &klen, &voff, &vlen, &t)) != 0) {
|
||||||
|
#if !defined(_MSC_VER) || _MSC_VER >= 1700
|
||||||
|
char path[klen + 1];
|
||||||
|
#else
|
||||||
|
char *path = (char *) alloca(klen + 1);
|
||||||
|
#endif
|
||||||
|
const char *val;
|
||||||
|
if (t == MJSON_TOK_NULL) continue;
|
||||||
|
memcpy(path, "$.", 2);
|
||||||
|
memcpy(path + 2, s2 + koff + 1, klen - 2);
|
||||||
|
path[klen] = '\0';
|
||||||
|
if (mjson_find(s, n, path, &val, &vlen) != MJSON_TOK_INVALID) continue;
|
||||||
|
if (comma) len += fn(",", 1, userdata);
|
||||||
|
len += fn(s2 + koff, klen, userdata);
|
||||||
|
len += fn(":", 1, userdata);
|
||||||
|
len += fn(s2 + voff, vlen, userdata);
|
||||||
|
comma = 1;
|
||||||
|
}
|
||||||
|
len += fn("}", 1, userdata);
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
#endif // MJSON_ENABLE_MERGE
|
||||||
|
|
||||||
|
#if MJSON_ENABLE_PRETTY
|
||||||
|
struct prettydata {
|
||||||
|
int level;
|
||||||
|
int len;
|
||||||
|
int prev;
|
||||||
|
const char *pad;
|
||||||
|
int padlen;
|
||||||
|
mjson_print_fn_t fn;
|
||||||
|
void *userdata;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int pretty_cb(int ev, const char *s, int off, int len, void *ud) {
|
||||||
|
struct prettydata *d = (struct prettydata *) ud;
|
||||||
|
int i;
|
||||||
|
switch (ev) {
|
||||||
|
case '{':
|
||||||
|
case '[':
|
||||||
|
d->level++;
|
||||||
|
d->len += d->fn(s + off, len, d->userdata);
|
||||||
|
break;
|
||||||
|
case '}':
|
||||||
|
case ']':
|
||||||
|
d->level--;
|
||||||
|
if (d->prev != '[' && d->prev != '{' && d->padlen > 0) {
|
||||||
|
d->len += d->fn("\n", 1, d->userdata);
|
||||||
|
for (i = 0; i < d->level; i++)
|
||||||
|
d->len += d->fn(d->pad, d->padlen, d->userdata);
|
||||||
|
}
|
||||||
|
d->len += d->fn(s + off, len, d->userdata);
|
||||||
|
break;
|
||||||
|
case ',':
|
||||||
|
d->len += d->fn(s + off, len, d->userdata);
|
||||||
|
if (d->padlen > 0) {
|
||||||
|
d->len += d->fn("\n", 1, d->userdata);
|
||||||
|
for (i = 0; i < d->level; i++)
|
||||||
|
d->len += d->fn(d->pad, d->padlen, d->userdata);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ':':
|
||||||
|
d->len += d->fn(s + off, len, d->userdata);
|
||||||
|
if (d->padlen > 0) d->len += d->fn(" ", 1, d->userdata);
|
||||||
|
break;
|
||||||
|
case MJSON_TOK_KEY:
|
||||||
|
if (d->prev == '{' && d->padlen > 0) {
|
||||||
|
d->len += d->fn("\n", 1, d->userdata);
|
||||||
|
for (i = 0; i < d->level; i++)
|
||||||
|
d->len += d->fn(d->pad, d->padlen, d->userdata);
|
||||||
|
}
|
||||||
|
d->len += d->fn(s + off, len, d->userdata);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (d->prev == '[' && d->padlen > 0) {
|
||||||
|
d->len += d->fn("\n", 1, d->userdata);
|
||||||
|
for (i = 0; i < d->level; i++)
|
||||||
|
d->len += d->fn(d->pad, d->padlen, d->userdata);
|
||||||
|
}
|
||||||
|
d->len += d->fn(s + off, len, d->userdata);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
d->prev = ev;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mjson_pretty(const char *s, int n, const char *pad, mjson_print_fn_t fn,
|
||||||
|
void *userdata) {
|
||||||
|
struct prettydata d = {0, 0, 0, pad, strlen(pad), fn, userdata};
|
||||||
|
if (mjson(s, n, pretty_cb, &d) < 0) return -1;
|
||||||
|
return d.len;
|
||||||
|
}
|
||||||
|
#endif // MJSON_ENABLE_PRETTY
|
||||||
|
|
||||||
|
#if MJSON_ENABLE_RPC
|
||||||
|
struct jsonrpc_ctx jsonrpc_default_context;
|
||||||
|
struct jsonrpc_userdata {
|
||||||
|
mjson_print_fn_t fn;
|
||||||
|
void *fndata;
|
||||||
|
};
|
||||||
|
|
||||||
|
int mjson_globmatch(const char *s1, int n1, const char *s2, int n2) {
|
||||||
|
int i = 0, j = 0, ni = 0, nj = 0;
|
||||||
|
while (i < n1 || j < n2) {
|
||||||
|
if (i < n1 && j < n2 && (s1[i] == '?' || s2[j] == s1[i])) {
|
||||||
|
i++, j++;
|
||||||
|
} else if (i < n1 && (s1[i] == '*' || s1[i] == '#')) {
|
||||||
|
ni = i, nj = j + 1, i++;
|
||||||
|
} else if (nj > 0 && nj <= n2 && (s1[i - 1] == '#' || s2[j] != '/')) {
|
||||||
|
i = ni, j = nj;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int jsonrpc_printer(const char *buf, int len, void *userdata) {
|
||||||
|
struct jsonrpc_userdata *u = (struct jsonrpc_userdata *) userdata;
|
||||||
|
return u->fn(buf, len, u->fndata);
|
||||||
|
}
|
||||||
|
|
||||||
|
void jsonrpc_return_errorv(struct jsonrpc_request *r, int code,
|
||||||
|
const char *message, const char *data_fmt,
|
||||||
|
va_list ap) {
|
||||||
|
if (r->id_len == 0) return;
|
||||||
|
mjson_printf(r->fn, r->fndata,
|
||||||
|
"{\"id\":%.*s,\"error\":{\"code\":%d,\"message\":%Q", r->id_len,
|
||||||
|
r->id, code, message == NULL ? "" : message);
|
||||||
|
if (data_fmt != NULL) {
|
||||||
|
mjson_printf(r->fn, r->fndata, ",\"data\":");
|
||||||
|
mjson_vprintf(r->fn, r->fndata, data_fmt, ap);
|
||||||
|
}
|
||||||
|
mjson_printf(r->fn, r->fndata, "}}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void jsonrpc_return_error(struct jsonrpc_request *r, int code,
|
||||||
|
const char *message, const char *data_fmt, ...) {
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, data_fmt);
|
||||||
|
jsonrpc_return_errorv(r, code, message, data_fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
void jsonrpc_return_successv(struct jsonrpc_request *r, const char *result_fmt,
|
||||||
|
va_list ap) {
|
||||||
|
if (r->id_len == 0) return;
|
||||||
|
mjson_printf(r->fn, r->fndata, "{\"id\":%.*s,\"result\":", r->id_len, r->id);
|
||||||
|
if (result_fmt != NULL) {
|
||||||
|
mjson_vprintf(r->fn, r->fndata, result_fmt, ap);
|
||||||
|
} else {
|
||||||
|
mjson_printf(r->fn, r->fndata, "%s", "null");
|
||||||
|
}
|
||||||
|
mjson_printf(r->fn, r->fndata, "}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void jsonrpc_return_success(struct jsonrpc_request *r, const char *result_fmt,
|
||||||
|
...) {
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, result_fmt);
|
||||||
|
jsonrpc_return_successv(r, result_fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
void jsonrpc_ctx_process(struct jsonrpc_ctx *ctx, const char *req, int req_sz,
|
||||||
|
mjson_print_fn_t fn, void *fndata) {
|
||||||
|
const char *result = NULL, *error = NULL;
|
||||||
|
int result_sz = 0, error_sz = 0;
|
||||||
|
struct jsonrpc_method *m = NULL;
|
||||||
|
struct jsonrpc_userdata d;
|
||||||
|
struct jsonrpc_request r = {req, req_sz, 0, 0, 0, 0, 0,
|
||||||
|
0, &jsonrpc_printer, NULL, NULL};
|
||||||
|
|
||||||
|
d.fn = fn;
|
||||||
|
d.fndata = fndata;
|
||||||
|
r.fndata = &d;
|
||||||
|
|
||||||
|
// Is is a response frame?
|
||||||
|
mjson_find(req, req_sz, "$.result", &result, &result_sz);
|
||||||
|
if (result == NULL) mjson_find(req, req_sz, "$.error", &error, &error_sz);
|
||||||
|
if (result_sz > 0 || error_sz > 0) {
|
||||||
|
if (ctx->response_cb != NULL) ctx->response_cb(req, req_sz, ctx->userdata);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method must exist and must be a string
|
||||||
|
if (mjson_find(req, req_sz, "$.method", &r.method, &r.method_len) !=
|
||||||
|
MJSON_TOK_STRING) {
|
||||||
|
mjson_printf(fn, fndata, "{\"error\":{\"code\":-32700,\"message\":%.*Q}}\n",
|
||||||
|
req_sz, req);
|
||||||
|
ctx->in_len = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// id and params are optional
|
||||||
|
mjson_find(req, req_sz, "$.id", &r.id, &r.id_len);
|
||||||
|
mjson_find(req, req_sz, "$.params", &r.params, &r.params_len);
|
||||||
|
|
||||||
|
for (m = ctx->methods; m != NULL; m = m->next) {
|
||||||
|
if (mjson_globmatch(m->method, m->method_sz, r.method + 1,
|
||||||
|
r.method_len - 2) > 0) {
|
||||||
|
if (r.params == NULL) r.params = "";
|
||||||
|
r.userdata = m->cbdata;
|
||||||
|
m->cb(&r);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (m == NULL) {
|
||||||
|
jsonrpc_return_error(&r, JSONRPC_ERROR_NOT_FOUND, "method not found", NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int jsonrpc_print_methods(mjson_print_fn_t fn, void *fndata,
|
||||||
|
va_list *ap) {
|
||||||
|
struct jsonrpc_ctx *ctx = va_arg(*ap, struct jsonrpc_ctx *);
|
||||||
|
struct jsonrpc_method *m;
|
||||||
|
int len = 0;
|
||||||
|
for (m = ctx->methods; m != NULL; m = m->next) {
|
||||||
|
if (m != ctx->methods) len += mjson_print_buf(fn, fndata, ",", 1);
|
||||||
|
len += mjson_print_str(fn, fndata, m->method, strlen(m->method));
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rpclist(struct jsonrpc_request *r) {
|
||||||
|
jsonrpc_return_success(r, "[%M]", jsonrpc_print_methods, r->userdata);
|
||||||
|
}
|
||||||
|
|
||||||
|
void jsonrpc_ctx_init(struct jsonrpc_ctx *ctx, mjson_print_fn_t response_cb,
|
||||||
|
void *userdata) {
|
||||||
|
ctx->response_cb = response_cb;
|
||||||
|
ctx->userdata = userdata;
|
||||||
|
jsonrpc_ctx_export(ctx, MJSON_RPC_LIST_NAME, rpclist, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void jsonrpc_ctx_process_byte(struct jsonrpc_ctx *ctx, unsigned char ch,
|
||||||
|
mjson_print_fn_t fn, void *p) {
|
||||||
|
if (ctx->in_len >= (int) sizeof(ctx->in)) ctx->in_len = 0; // Overflow
|
||||||
|
if (ch == '\n') { // If new line, parse frame
|
||||||
|
if (ctx->in_len > 1) jsonrpc_ctx_process(ctx, ctx->in, ctx->in_len, fn, p);
|
||||||
|
ctx->in_len = 0;
|
||||||
|
} else {
|
||||||
|
ctx->in[ctx->in_len] = ch; // Append to the buffer
|
||||||
|
ctx->in_len++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void jsonrpc_init(mjson_print_fn_t response_cb, void *userdata) {
|
||||||
|
jsonrpc_ctx_init(&jsonrpc_default_context, response_cb, userdata);
|
||||||
|
}
|
||||||
|
#endif // MJSON_ENABLE_RPC
|
||||||
@@ -0,0 +1,220 @@
|
|||||||
|
// Copyright (c) 2018-2020 Cesanta Software Limited
|
||||||
|
// All rights reserved
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
#ifndef MJSON_H
|
||||||
|
#define MJSON_H
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifndef MJSON_ENABLE_PRINT
|
||||||
|
#define MJSON_ENABLE_PRINT 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MJSON_ENABLE_RPC
|
||||||
|
#define MJSON_ENABLE_RPC 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MJSON_ENABLE_BASE64
|
||||||
|
#define MJSON_ENABLE_BASE64 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MJSON_ENABLE_MERGE
|
||||||
|
#define MJSON_ENABLE_MERGE 0
|
||||||
|
#elif MJSON_ENABLE_MERGE
|
||||||
|
#define MJSON_ENABLE_NEXT 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MJSON_ENABLE_PRETTY
|
||||||
|
#define MJSON_ENABLE_PRETTY 0
|
||||||
|
#elif MJSON_ENABLE_PRETTY
|
||||||
|
#define MJSON_ENABLE_NEXT 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MJSON_ENABLE_NEXT
|
||||||
|
#define MJSON_ENABLE_NEXT 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef MJSON_RPC_IN_BUF_SIZE
|
||||||
|
#define MJSON_RPC_IN_BUF_SIZE 256
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MJSON_RPC_LIST_NAME
|
||||||
|
#define MJSON_RPC_LIST_NAME "rpc.list"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
enum {
|
||||||
|
MJSON_ERROR_INVALID_INPUT = -1,
|
||||||
|
MJSON_ERROR_TOO_DEEP = -2,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum mjson_tok {
|
||||||
|
MJSON_TOK_INVALID = 0,
|
||||||
|
MJSON_TOK_KEY = 1,
|
||||||
|
MJSON_TOK_STRING = 11,
|
||||||
|
MJSON_TOK_NUMBER = 12,
|
||||||
|
MJSON_TOK_TRUE = 13,
|
||||||
|
MJSON_TOK_FALSE = 14,
|
||||||
|
MJSON_TOK_NULL = 15,
|
||||||
|
MJSON_TOK_ARRAY = 91,
|
||||||
|
MJSON_TOK_OBJECT = 123,
|
||||||
|
};
|
||||||
|
#define MJSON_TOK_IS_VALUE(t) ((t) > 10 && (t) < 20)
|
||||||
|
|
||||||
|
typedef int (*mjson_cb_t)(int ev, const char *s, int off, int len, void *ud);
|
||||||
|
|
||||||
|
#ifndef MJSON_MAX_DEPTH
|
||||||
|
#define MJSON_MAX_DEPTH 20
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int mjson(const char *s, int len, mjson_cb_t cb, void *ud);
|
||||||
|
enum mjson_tok mjson_find(const char *s, int len, const char *jp,
|
||||||
|
const char **tokptr, int *toklen);
|
||||||
|
int mjson_get_number(const char *s, int len, const char *path, double *v);
|
||||||
|
int mjson_get_bool(const char *s, int len, const char *path, int *v);
|
||||||
|
int mjson_get_string(const char *s, int len, const char *path, char *to, int n);
|
||||||
|
int mjson_get_hex(const char *s, int len, const char *path, char *to, int n);
|
||||||
|
|
||||||
|
#if MJSON_ENABLE_NEXT
|
||||||
|
int mjson_next(const char *s, int n, int off, int *koff, int *klen, int *voff,
|
||||||
|
int *vlen, int *vtype);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MJSON_ENABLE_BASE64
|
||||||
|
int mjson_get_base64(const char *s, int len, const char *path, char *to, int n);
|
||||||
|
int mjson_base64_dec(const char *src, int n, char *dst, int dlen);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MJSON_ENABLE_PRINT
|
||||||
|
typedef int (*mjson_print_fn_t)(const char *buf, int len, void *userdata);
|
||||||
|
typedef int (*mjson_vprint_fn_t)(mjson_print_fn_t, void *, va_list *);
|
||||||
|
|
||||||
|
struct mjson_fixedbuf {
|
||||||
|
char *ptr;
|
||||||
|
int size, len;
|
||||||
|
};
|
||||||
|
|
||||||
|
int mjson_printf(mjson_print_fn_t, void *, const char *fmt, ...);
|
||||||
|
int mjson_vprintf(mjson_print_fn_t, void *, const char *fmt, va_list ap);
|
||||||
|
int mjson_print_str(mjson_print_fn_t, void *, const char *s, int len);
|
||||||
|
int mjson_print_int(mjson_print_fn_t, void *, int value, int is_signed);
|
||||||
|
int mjson_print_long(mjson_print_fn_t, void *, long value, int is_signed);
|
||||||
|
int mjson_print_buf(mjson_print_fn_t fn, void *, const char *buf, int len);
|
||||||
|
|
||||||
|
int mjson_print_null(const char *ptr, int len, void *userdata);
|
||||||
|
int mjson_print_file(const char *ptr, int len, void *userdata);
|
||||||
|
int mjson_print_fixed_buf(const char *ptr, int len, void *userdata);
|
||||||
|
int mjson_print_dynamic_buf(const char *ptr, int len, void *userdata);
|
||||||
|
|
||||||
|
#if MJSON_ENABLE_PRETTY
|
||||||
|
int mjson_pretty(const char *, int, const char *, mjson_print_fn_t, void *);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MJSON_ENABLE_MERGE
|
||||||
|
int mjson_merge(const char *, int, const char *, int, mjson_print_fn_t, void *);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // MJSON_ENABLE_PRINT
|
||||||
|
|
||||||
|
#if MJSON_ENABLE_RPC
|
||||||
|
|
||||||
|
void jsonrpc_init(mjson_print_fn_t, void *userdata);
|
||||||
|
int mjson_globmatch(const char *s1, int n1, const char *s2, int n2);
|
||||||
|
|
||||||
|
struct jsonrpc_request {
|
||||||
|
const char *frame; // Points to the whole frame
|
||||||
|
int frame_len; // Frame length
|
||||||
|
const char *params; // Points to the "params" in the request frame
|
||||||
|
int params_len; // Length of the "params"
|
||||||
|
const char *id; // Points to the "id" in the request frame
|
||||||
|
int id_len; // Length of the "id"
|
||||||
|
const char *method; // Points to the "method" in the request frame
|
||||||
|
int method_len; // Length of the "method"
|
||||||
|
mjson_print_fn_t fn; // Printer function
|
||||||
|
void *fndata; // Printer function data
|
||||||
|
void *userdata; // Callback's user data as specified at export time
|
||||||
|
};
|
||||||
|
|
||||||
|
struct jsonrpc_method {
|
||||||
|
const char *method;
|
||||||
|
int method_sz;
|
||||||
|
void (*cb)(struct jsonrpc_request *);
|
||||||
|
void *cbdata;
|
||||||
|
struct jsonrpc_method *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Main RPC context, stores current request information and a list of
|
||||||
|
// exported RPC methods.
|
||||||
|
struct jsonrpc_ctx {
|
||||||
|
struct jsonrpc_method *methods;
|
||||||
|
void *userdata;
|
||||||
|
mjson_print_fn_t response_cb;
|
||||||
|
int in_len;
|
||||||
|
char in[MJSON_RPC_IN_BUF_SIZE];
|
||||||
|
};
|
||||||
|
|
||||||
|
// Registers function fn under the given name within the given RPC context
|
||||||
|
#define jsonrpc_ctx_export(ctx, name, fn, ud) \
|
||||||
|
do { \
|
||||||
|
static struct jsonrpc_method m = {(name), sizeof(name) - 1, (fn), 0, 0}; \
|
||||||
|
m.cbdata = (ud); \
|
||||||
|
m.next = (ctx)->methods; \
|
||||||
|
(ctx)->methods = &m; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
void jsonrpc_ctx_init(struct jsonrpc_ctx *ctx, mjson_print_fn_t, void *);
|
||||||
|
void jsonrpc_return_error(struct jsonrpc_request *r, int code,
|
||||||
|
const char *message, const char *data_fmt, ...);
|
||||||
|
void jsonrpc_return_success(struct jsonrpc_request *r, const char *result_fmt,
|
||||||
|
...);
|
||||||
|
void jsonrpc_ctx_process(struct jsonrpc_ctx *ctx, const char *req, int req_sz,
|
||||||
|
mjson_print_fn_t fn, void *fndata);
|
||||||
|
void jsonrpc_ctx_process_byte(struct jsonrpc_ctx *ctx, unsigned char ch,
|
||||||
|
mjson_print_fn_t fn, void *fndata);
|
||||||
|
|
||||||
|
extern struct jsonrpc_ctx jsonrpc_default_context;
|
||||||
|
|
||||||
|
#define jsonrpc_export(name, fn, ud) \
|
||||||
|
jsonrpc_ctx_export(&jsonrpc_default_context, (name), (fn), (ud))
|
||||||
|
|
||||||
|
#define jsonrpc_process(buf, len, fn, data) \
|
||||||
|
jsonrpc_ctx_process(&jsonrpc_default_context, (buf), (len), (fn), (data))
|
||||||
|
|
||||||
|
#define jsonrpc_process_byte(x, fn, data) \
|
||||||
|
jsonrpc_ctx_process_byte(&jsonrpc_default_context, (x), (fn), (data))
|
||||||
|
|
||||||
|
#define JSONRPC_ERROR_INVALID -32700 /* Invalid JSON was received */
|
||||||
|
#define JSONRPC_ERROR_NOT_FOUND -32601 /* The method does not exist */
|
||||||
|
#define JSONRPC_ERROR_BAD_PARAMS -32602 /* Invalid params passed */
|
||||||
|
#define JSONRPC_ERROR_INTERNAL -32603 /* Internal JSON-RPC error */
|
||||||
|
|
||||||
|
#endif // MJSON_ENABLE_RPC
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif // MJSON_H
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
const {h, render, Component} = preact;
|
||||||
|
const html = htm.bind(h);
|
||||||
|
|
||||||
|
const Info = () => html`<div id="info">
|
||||||
|
This dashboard shows values kept in server memory. Many clients
|
||||||
|
can open this page. As soon as any client changes any value,
|
||||||
|
all clients update automatically.
|
||||||
|
<br/><br/>
|
||||||
|
The JS code that watches state changes, reconnects on network failures.
|
||||||
|
That means if server restarts, dashboard on all connected clients
|
||||||
|
refresh automatically.
|
||||||
|
<br/><br/>
|
||||||
|
|
||||||
|
You can use <code>curl</code> command-line utility:
|
||||||
|
<br/><code>curl localhost:8000/api/config/get</code>
|
||||||
|
<br/><code>curl localhost:8000/api/config/watch</code>
|
||||||
|
<br/><code>curl localhost:8000/api/config/set -d '{"a":123}'</code>
|
||||||
|
</div>`;
|
||||||
|
|
||||||
|
class Dashboard extends Component {
|
||||||
|
state = {value1: null, value2: null};
|
||||||
|
componentDidMount() {
|
||||||
|
axios.get('/api/config/get')
|
||||||
|
.then(r => this.setState(r.data))
|
||||||
|
.catch(e => console.log(e));
|
||||||
|
var self = this;
|
||||||
|
var f = function(reader) {
|
||||||
|
return reader.read().then(function(result) {
|
||||||
|
var data = String.fromCharCode.apply(null, result.value);
|
||||||
|
self.setState(JSON.parse(data));
|
||||||
|
// console.log(JSON.parse(data));
|
||||||
|
if (!result.done) return f(reader);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
fetch('/api/config/watch')
|
||||||
|
.then(r => r.body.getReader())
|
||||||
|
.then(f)
|
||||||
|
.catch(e => setTimeout(x => self.componentDidMount(), 1000));
|
||||||
|
}
|
||||||
|
render(props, state) {
|
||||||
|
return html
|
||||||
|
`<div id="dashboard" style="display: flex; justify-content: flex-evenly;">
|
||||||
|
<div style="width:50%;text-align:center;">Value 1 (number):
|
||||||
|
<div style="font-size:140%;"><b>${state.value1}</b></div></div>
|
||||||
|
<div style="width:50%;text-align:center;">Value 2 (string):
|
||||||
|
<div style="font-size:140%;"><b>${state.value2}</b></div></div>
|
||||||
|
</div>`
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class Form extends Component {
|
||||||
|
render(props, state) {
|
||||||
|
const onclick = ev => axios.post(
|
||||||
|
'/api/config/set', {value1: +state.value1, value2: state.value2});
|
||||||
|
// alert(JSON.stringify(state));
|
||||||
|
return html`<div id="form">
|
||||||
|
<div><b>Change values</b></div>
|
||||||
|
<table>
|
||||||
|
<tr><td>Value 1 (number):</td><td><input value=${state.value1}
|
||||||
|
onInput=${linkState(this, 'value1')} /></td></tr>
|
||||||
|
<tr><td>Value 2 (string):</td><td><input value=${state.value2}
|
||||||
|
onInput=${linkState(this, 'value2')}/></td></tr>
|
||||||
|
<tr><td></td>
|
||||||
|
<td><button onClick=${onclick}>Save values</button></td></tr>
|
||||||
|
</table>
|
||||||
|
</div>`
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const App = () => html`<div id="container">
|
||||||
|
<${Info} />
|
||||||
|
<${Dashboard} />
|
||||||
|
<${Form} />
|
||||||
|
</div>`;
|
||||||
|
|
||||||
|
window.onload = () => render(h(App), document.body);
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
/* axios v0.21.1 | (c) 2020 by Matt Zabriskie */
|
||||||
|
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.axios=t():e.axios=t()}(this,function(){return function(e){function t(r){if(n[r])return n[r].exports;var o=n[r]={exports:{},id:r,loaded:!1};return e[r].call(o.exports,o,o.exports,t),o.loaded=!0,o.exports}var n={};return t.m=e,t.c=n,t.p="",t(0)}([function(e,t,n){e.exports=n(1)},function(e,t,n){"use strict";function r(e){var t=new i(e),n=s(i.prototype.request,t);return o.extend(n,i.prototype,t),o.extend(n,t),n}var o=n(2),s=n(3),i=n(4),a=n(22),u=n(10),c=r(u);c.Axios=i,c.create=function(e){return r(a(c.defaults,e))},c.Cancel=n(23),c.CancelToken=n(24),c.isCancel=n(9),c.all=function(e){return Promise.all(e)},c.spread=n(25),c.isAxiosError=n(26),e.exports=c,e.exports.default=c},function(e,t,n){"use strict";function r(e){return"[object Array]"===R.call(e)}function o(e){return"undefined"==typeof e}function s(e){return null!==e&&!o(e)&&null!==e.constructor&&!o(e.constructor)&&"function"==typeof e.constructor.isBuffer&&e.constructor.isBuffer(e)}function i(e){return"[object ArrayBuffer]"===R.call(e)}function a(e){return"undefined"!=typeof FormData&&e instanceof FormData}function u(e){var t;return t="undefined"!=typeof ArrayBuffer&&ArrayBuffer.isView?ArrayBuffer.isView(e):e&&e.buffer&&e.buffer instanceof ArrayBuffer}function c(e){return"string"==typeof e}function f(e){return"number"==typeof e}function p(e){return null!==e&&"object"==typeof e}function d(e){if("[object Object]"!==R.call(e))return!1;var t=Object.getPrototypeOf(e);return null===t||t===Object.prototype}function l(e){return"[object Date]"===R.call(e)}function h(e){return"[object File]"===R.call(e)}function m(e){return"[object Blob]"===R.call(e)}function y(e){return"[object Function]"===R.call(e)}function g(e){return p(e)&&y(e.pipe)}function v(e){return"undefined"!=typeof URLSearchParams&&e instanceof URLSearchParams}function x(e){return e.replace(/^\s*/,"").replace(/\s*$/,"")}function w(){return("undefined"==typeof navigator||"ReactNative"!==navigator.product&&"NativeScript"!==navigator.product&&"NS"!==navigator.product)&&("undefined"!=typeof window&&"undefined"!=typeof document)}function b(e,t){if(null!==e&&"undefined"!=typeof e)if("object"!=typeof e&&(e=[e]),r(e))for(var n=0,o=e.length;n<o;n++)t.call(null,e[n],n,e);else for(var s in e)Object.prototype.hasOwnProperty.call(e,s)&&t.call(null,e[s],s,e)}function E(){function e(e,n){d(t[n])&&d(e)?t[n]=E(t[n],e):d(e)?t[n]=E({},e):r(e)?t[n]=e.slice():t[n]=e}for(var t={},n=0,o=arguments.length;n<o;n++)b(arguments[n],e);return t}function j(e,t,n){return b(t,function(t,r){n&&"function"==typeof t?e[r]=S(t,n):e[r]=t}),e}function C(e){return 65279===e.charCodeAt(0)&&(e=e.slice(1)),e}var S=n(3),R=Object.prototype.toString;e.exports={isArray:r,isArrayBuffer:i,isBuffer:s,isFormData:a,isArrayBufferView:u,isString:c,isNumber:f,isObject:p,isPlainObject:d,isUndefined:o,isDate:l,isFile:h,isBlob:m,isFunction:y,isStream:g,isURLSearchParams:v,isStandardBrowserEnv:w,forEach:b,merge:E,extend:j,trim:x,stripBOM:C}},function(e,t){"use strict";e.exports=function(e,t){return function(){for(var n=new Array(arguments.length),r=0;r<n.length;r++)n[r]=arguments[r];return e.apply(t,n)}}},function(e,t,n){"use strict";function r(e){this.defaults=e,this.interceptors={request:new i,response:new i}}var o=n(2),s=n(5),i=n(6),a=n(7),u=n(22);r.prototype.request=function(e){"string"==typeof e?(e=arguments[1]||{},e.url=arguments[0]):e=e||{},e=u(this.defaults,e),e.method?e.method=e.method.toLowerCase():this.defaults.method?e.method=this.defaults.method.toLowerCase():e.method="get";var t=[a,void 0],n=Promise.resolve(e);for(this.interceptors.request.forEach(function(e){t.unshift(e.fulfilled,e.rejected)}),this.interceptors.response.forEach(function(e){t.push(e.fulfilled,e.rejected)});t.length;)n=n.then(t.shift(),t.shift());return n},r.prototype.getUri=function(e){return e=u(this.defaults,e),s(e.url,e.params,e.paramsSerializer).replace(/^\?/,"")},o.forEach(["delete","get","head","options"],function(e){r.prototype[e]=function(t,n){return this.request(u(n||{},{method:e,url:t,data:(n||{}).data}))}}),o.forEach(["post","put","patch"],function(e){r.prototype[e]=function(t,n,r){return this.request(u(r||{},{method:e,url:t,data:n}))}}),e.exports=r},function(e,t,n){"use strict";function r(e){return encodeURIComponent(e).replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%20/g,"+").replace(/%5B/gi,"[").replace(/%5D/gi,"]")}var o=n(2);e.exports=function(e,t,n){if(!t)return e;var s;if(n)s=n(t);else if(o.isURLSearchParams(t))s=t.toString();else{var i=[];o.forEach(t,function(e,t){null!==e&&"undefined"!=typeof e&&(o.isArray(e)?t+="[]":e=[e],o.forEach(e,function(e){o.isDate(e)?e=e.toISOString():o.isObject(e)&&(e=JSON.stringify(e)),i.push(r(t)+"="+r(e))}))}),s=i.join("&")}if(s){var a=e.indexOf("#");a!==-1&&(e=e.slice(0,a)),e+=(e.indexOf("?")===-1?"?":"&")+s}return e}},function(e,t,n){"use stricLine truncated
|
||||||
|
//# sourceMappingURL=axios.min.map
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
!function(){function n(n){var t=e.get(this);return t||(t=new Map,e.set(this,t)),1<(t=a(this,t.get(n)||(t.set(n,t=function(n){function t(n){1===u&&(n||(r=r.replace(/^\s*\n\s*|\s*\n\s*$/g,"")))?p.push(0,n,r):3===u&&(n||r)?(p.push(3,n,r),u=2):2===u&&"..."===r&&n?p.push(4,n,0):2===u&&r&&!n?p.push(5,0,!0,r):5<=u&&((r||!n&&5===u)&&(p.push(u,0,r,s),u=6),n&&(p.push(u,n,0,s),u=6)),r=""}for(var e,s,u=1,r="",h="",p=[0],a=0;a<n.length;a++){a&&(1===u&&t(),t(a));for(var o=0;o<n[a].length;o++)e=n[a][o],1===u?"<"===e?(t(),p=[p],u=3):r+=e:4===u?r="--"===r&&">"===e?(u=1,""):e+r[0]:h?e===h?h="":r+=e:'"'===e||"'"===e?h=e:">"===e?(t(),u=1):u&&("="===e?(u=5,s=r,r=""):"/"===e&&(u<5||">"===n[a][o+1])?(t(),3===u&&(p=p[0]),(p=(u=p)[0]).push(2,0,u),u=0):" "===e||"\t"===e||"\n"===e||"\r"===e?(t(),u=2):r+=e),3===u&&"!--"===r&&(u=4,p=p[0])}return t(),p}(n)),t),arguments,[])).length?t:t[0]}var a=function(n,t,e,s){var u;t[0]=0;for(var r=1;r<t.length;r++){var h=t[r++],p=t[r]?(t[0]|=h?1:2,e[t[r++]]):t[++r];3===h?s[0]=p:4===h?s[1]=Object.assign(s[1]||{},p):5===h?(s[1]=s[1]||{})[t[++r]]=p:6===h?s[1][t[++r]]+=p+"":h?(u=n.apply(p,a(n,p,e,["",null])),s.push(u),p[0]?t[0]|=2:(t[r-2]=0,t[r]=u)):s.push(p)}return s},e=new Map;"undefined"!=typeof module?module.exports=n:self.htm=n}();
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<title>example</title>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<link rel="stylesheet" href="style.css" />
|
||||||
|
<script src="preact.min.js"></script>
|
||||||
|
<script src="htm.min.js"></script>
|
||||||
|
<script src="linkstate.min.js"></script>
|
||||||
|
<script src="axios.min.js"></script>
|
||||||
|
<script src="app.js"></script>
|
||||||
|
</head>
|
||||||
|
<body></body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
function linkState(component, key, eventPath) {
|
||||||
|
let path = key.split('.'), cache = component.__lsc || (component.__lsc = {});
|
||||||
|
|
||||||
|
return cache[key + eventPath] || (cache[key + eventPath] = function(e) {
|
||||||
|
let t = e && e.target || this, state = {}, obj = state,
|
||||||
|
v = typeof eventPath === 'string' ?
|
||||||
|
delve(e, eventPath) :
|
||||||
|
t.nodeName ? (t.type.match(/^che|rad/) ? t.checked : t.value) :
|
||||||
|
e,
|
||||||
|
i = 0;
|
||||||
|
for (; i < path.length - 1; i++) {
|
||||||
|
obj = obj[path[i]] ||
|
||||||
|
(obj[path[i]] = !i && component.state[path[i]] || {});
|
||||||
|
}
|
||||||
|
obj[path[i]] = v;
|
||||||
|
component.setState(state);
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
!function(){var n,l,u,t,i,o,r,e,f={},c=[],a=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i;function s(n,l){for(var u in l)n[u]=l[u];return n}function v(n){var l=n.parentNode;l&&l.removeChild(n)}function h(n,l,u){var t,i=arguments,o={};for(t in l)"key"!==t&&"ref"!==t&&(o[t]=l[t]);if(arguments.length>3)for(u=[u],t=3;t<arguments.length;t++)u.push(i[t]);if(null!=u&&(o.children=u),"function"==typeof n&&null!=n.defaultProps)for(t in n.defaultProps)void 0===o[t]&&(o[t]=n.defaultProps[t]);return y(n,o,l&&l.key,l&&l.ref,null)}function y(l,u,t,i,o){var r={type:l,props:u,key:t,ref:i,__k:null,__:null,__b:0,__e:null,__d:void 0,__c:null,constructor:void 0,__v:o};return null==o&&(r.__v=r),n.vnode&&n.vnode(r),r}function p(n){return n.children}function d(n,l){this.props=n,this.context=l}function _(n,l){if(null==l)return n.__?_(n.__,n.__.__k.indexOf(n)+1):null;for(var u;l<n.__k.length;l++)if(null!=(u=n.__k[l])&&null!=u.__e)return u.__e;return"function"==typeof n.type?_(n):null}function m(n){var l,u;if(null!=(n=n.__)&&null!=n.__c){for(n.__e=n.__c.base=null,l=0;l<n.__k.length;l++)if(null!=(u=n.__k[l])&&null!=u.__e){n.__e=n.__c.base=u.__e;break}return m(n)}}function k(l){(!l.__d&&(l.__d=!0)&&u.push(l)&&!w.__r++||i!==n.debounceRendering)&&((i=n.debounceRendering)||t)(w)}function w(){for(var n;w.__r=u.length;)n=u.sort(function(n,l){return n.__v.__b-l.__v.__b}),u=[],n.some(function(n){var l,u,t,i,o,r,e;n.__d&&(r=(o=(l=n).__v).__e,(e=l.__P)&&(u=[],(t=s({},o)).__v=t,i=N(e,o,t,l.__n,void 0!==e.ownerSVGElement,null,u,null==r?_(o):r),z(u,o),i!=r&&m(o)))})}function g(n,l,u,t,i,o,r,e,a,s){var h,d,m,k,w,g,x,C=t&&t.__k||c,A=C.length;for(a==f&&(a=null!=r?r[0]:A?_(t,0):null),u.__k=[],h=0;h<l.length;h++)if(null!=(k=u.__k[h]=null==(k=l[h])||"boolean"==typeof k?null:"string"==typeof k||"number"==typeof k?y(null,k,null,null,k):Array.isArray(k)?y(p,{children:k},null,null,null):null!=k.__e||null!=k.__c?y(k.type,k.props,k.key,null,k.__v):k)){if(k.__=u,k.__b=u.__b+1,null===(m=C[h])||m&&k.key==m.key&&k.type===m.type)C[h]=void 0;else for(d=0;d<A;d++){if((m=C[d])&&k.key==m.key&&k.type===m.type){C[d]=void 0;break}m=null}w=N(n,k,m=m||f,i,o,r,e,a,s),(d=k.ref)&&m.ref!=d&&(x||(x=[]),m.ref&&x.push(m.ref,null,k),x.push(d,k.__c||w,k)),null!=w?(null==g&&(g=w),a=b(n,k,m,C,r,w,a),"option"==u.type?n.value="":"function"==typeof u.type&&(u.__d=a)):a&&m.__e==a&&a.parentNode!=n&&(a=_(m))}if(u.__e=g,null!=r&&"function"!=typeof u.type)for(h=r.length;h--;)null!=r[h]&&v(r[h]);for(h=A;h--;)null!=C[h]&&j(C[h],C[h]);if(x)for(h=0;h<x.length;h++)$(x[h],x[++h],x[++h])}function b(n,l,u,t,i,o,r){var e,f,c;if(void 0!==l.__d)e=l.__d,l.__d=void 0;else if(i==u||o!=r||null==o.parentNode)n:if(null==r||r.parentNode!==n)n.appendChild(o),e=null;else{for(f=r,c=0;(f=f.nextSibling)&&c<t.length;c+=2)if(f==o)break n;n.insertBefore(o,r),e=r}return void 0!==e?e:o.nextSibling}function x(n,l,u,t,i){var o;for(o in u)"children"===o||"key"===o||o in l||A(n,o,null,u[o],t);for(o in l)i&&"function"!=typeof l[o]||"children"===o||"key"===o||"value"===o||"checked"===o||u[o]===l[o]||A(n,o,l[o],u[o],t)}function C(n,l,u){"-"===l[0]?n.setProperty(l,u):n[l]="number"==typeof u&&!1===a.test(l)?u+"px":null==u?"":u}function A(n,l,u,t,i){var o,r,e,f,c;if(i?"className"===l&&(l="class"):"class"===l&&(l="className"),"style"===l)if(o=n.style,"string"==typeof u)o.cssText=u;else{if("string"==typeof t&&(o.cssText="",t=null),t)for(f in t)u&&f in u||C(o,f,"");if(u)for(c in u)t&&u[c]===t[c]||C(o,c,u[c])}else"o"===l[0]&&"n"===l[1]?(r=l!==(l=l.replace(/Capture$/,"")),e=l.toLowerCase(),l=(e in n?e:l).slice(2),u?(t||n.addEventListener(l,P,r),(n.l||(n.l={}))[l]=u):n.removeEventListener(l,P,r)):"list"!==l&&"tagName"!==l&&"form"!==l&&"type"!==l&&"size"!==l&&!i&&l in n?n[l]=null==u?"":u:"function"!=typeof u&&"dangerouslySetInnerHTML"!==l&&(l!==(l=l.replace(/^xlink:?/,""))?null==u||!1===u?n.removeAttributeNS("http://www.w3.org/1999/xlink",l.toLowerCase()):n.setAttributeNS("http://www.w3.org/1999/xlink",l.toLowerCase(),u):null==u||!1===u&&!/^ar/.test(l)?n.removeAttribute(l):n.setAttribute(l,u))}function P(l){this.l[l.type](n.event?n.event(l):l)}function E(n,l,u){var t,i;for(t=0;t<n.__k.length;t++)(i=n.__k[t])&&(i.__=n,i.__e&&("function"==typeof i.type&&i.__k.length>1&&E(i,l,u),l=b(u,i,i,n.__k,null,i.__e,l),"function"==typeof n.type&&(n.__d=l)))}function N(l,u,t,i,o,r,e,f,c){var a,v,h,y,_,m,k,w,b,x,C,A=u.type;if(void 0!==u.constructor)return null;(a=n.__b)&&a(u);try{n:if("function"==typeof A){if(w=u.props,b=(a=A.contextType)&&i[a.__c],x=a?b?b.props.value:a.__:i,t.__c?k=(v=u.__c=t.__c).__=v.__E:("prototype"in A&&A.prototype.render?u.__c=v=new A(w,x):(u.__c=v=new d(w,x),v.constructor=A,v.render=F),b&&b.sub(v),v.props=w,v.state||(v.state={}),v.context=x,v.__n=i,h=v.__d=!0,v.__h=[]),null==v.__s&&(v.__s=v.state),null!=A.getDerivedStateFromProps&&(v.__s==v.state&&(v.__s=s({},v.__s)),s(v.__s,A.getDerivedStateFromProps(w,v.__s))),y=v.props,_=v.state,h)null==A.getDerivedStateFromProps&&null!=v.componentWillMount&&v.componenLine truncated
|
||||||
|
//# sourceMappingURL=preact.min.js.map
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
#container { margin-right: auto; margin-left: auto; max-width: 480px; }
|
||||||
|
#info { background: #d0f0f0; border-radius: .5em; padding: 2em; }
|
||||||
|
#dashboard { background: #f0f0f0; border-radius: .5em; padding: 0.5em; max-height: 10em; overflow: auto; height: 100%; margin-top: 1em; }
|
||||||
|
#form { background: #d0c0f0; border-radius: .5em; padding: 0.5em; max-height: 10em; overflow: auto; height: 100%; margin-top: 1em; }
|
||||||
|
button { width: 100%; }
|
||||||
|
button, select, input, label::before, textarea { outline: none; box-shadow:none !important; border: 1px solid #ccc !important; }
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
# The following lines of boilerplate have to be in your project's
|
||||||
|
# CMakeLists in this exact order for cmake to work correctly
|
||||||
|
cmake_minimum_required(VERSION 3.5)
|
||||||
|
|
||||||
|
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||||
|
project(mongoose-esp32-example)
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
THISDIR = $(realpath $(CURDIR))
|
||||||
|
ROOTDIR = $(realpath $(CURDIR)/../..)
|
||||||
|
|
||||||
|
all: example
|
||||||
|
|
||||||
|
example: main/main.c Makefile
|
||||||
|
docker run --rm -v $(ROOTDIR):$(ROOTDIR) -w $(THISDIR) espressif/idf idf.py build
|
||||||
|
|
||||||
|
COMPORT ?= /dev/cu.SLAB_USBtoUART
|
||||||
|
ESPTOOL ?= esptool.py
|
||||||
|
flash:
|
||||||
|
cd build && $(ESPTOOL) --chip esp32 -p $(COMPORT) -b 460800 --before=default_reset --after=hard_reset write_flash --flash_mode dio --flash_freq 40m --flash_size 2MB 0x8000 partition_table/partition-table.bin 0x1000 bootloader/bootloader.bin 0x10000 mongoose-esp32-example.bin
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf $(PROG) *.o *.dSYM *.gcov *.gcno *.gcda *.obj *.exe *.ilk *.pdb mongoose mongoose_* mongoose.* build sdkconfig
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
# An example ESP32 application
|
||||||
|
|
||||||
|
To build this application, follow these steps:
|
||||||
|
|
||||||
|
1. Make sure you have Docker installed
|
||||||
|
2. Clone whole mongoose repository on your machine:
|
||||||
|
```sh
|
||||||
|
git clone --depth 1 https://github.com/cesanta/mongoose.git
|
||||||
|
```
|
||||||
|
3. Start command line or terminal, and go into the example's directory:
|
||||||
|
```sh
|
||||||
|
cd mongoose/examples/esp32
|
||||||
|
```
|
||||||
|
4. Run `make`. This invokes a Docker-based build. A firmware will be built
|
||||||
|
in the `build/` directory:
|
||||||
|
```sh
|
||||||
|
make
|
||||||
|
```
|
||||||
|
|
||||||
|
# Flashing built firmware
|
||||||
|
|
||||||
|
If you have a real board to flash to, you can flash a built firmware.
|
||||||
|
First, make sure to have `esptool.py` script installed on your workstation.
|
||||||
|
Then, connect the board to your workstation and run the following command:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
make flash COMPORT=YOUR_USB_PORT
|
||||||
|
```
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
idf_component_register(SRCS "main.c"
|
||||||
|
"wifi.c"
|
||||||
|
"../../../mongoose.c"
|
||||||
|
INCLUDE_DIRS "../../..")
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
// Copyright (c) 2020 Cesanta Software Limited
|
||||||
|
// All rights reserved
|
||||||
|
|
||||||
|
#include "mongoose.h"
|
||||||
|
|
||||||
|
#define WIFI_SSID "WIFI_NETWORK" // SET THIS!
|
||||||
|
#define WIFI_PASS "WIFI_PASSWORD" // SET THIS!
|
||||||
|
|
||||||
|
#define SERVER_URL "http://0.0.0.0:80"
|
||||||
|
#define CLIENT_URL "http://info.cern.ch"
|
||||||
|
|
||||||
|
// Event handler for an server (accepted) connection
|
||||||
|
static void cb(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
|
||||||
|
if (ev == MG_EV_HTTP_MSG) {
|
||||||
|
mg_http_reply(c, 200, "", "Hello from ESP!\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Event handler for a client connection - fetch the first web page in history
|
||||||
|
// To enable TLS for HTTP,
|
||||||
|
// 1. Copy "ca.pem" file to the ESP32 flash FS
|
||||||
|
// 2. Add TLS init snippet for the connection, see examples/http-client
|
||||||
|
static void cb2(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
|
||||||
|
if (ev == MG_EV_CONNECT) {
|
||||||
|
struct mg_str s = mg_url_host(CLIENT_URL);
|
||||||
|
mg_printf(c, "GET / HTTP/1.0\r\nHost: %.*s\r\n\r\n", (int) s.len, s.ptr);
|
||||||
|
} else if (ev == MG_EV_HTTP_MSG) {
|
||||||
|
struct mg_http_message *hm = ev_data; // Print HTTP response
|
||||||
|
LOG(LL_INFO, ("Fetched:\n%.*s", (int) hm->message.len, hm->message.ptr));
|
||||||
|
c->is_closing = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called after we're connected to WiFi network
|
||||||
|
static void run_mongoose(void) {
|
||||||
|
struct mg_mgr mgr;
|
||||||
|
mg_log_set("3");
|
||||||
|
mg_mgr_init(&mgr);
|
||||||
|
mg_http_listen(&mgr, SERVER_URL, cb, &mgr); // Listening server
|
||||||
|
mg_http_connect(&mgr, CLIENT_URL, cb2, &mgr); // Example client
|
||||||
|
LOG(LL_INFO, ("Starting Mongoose web server v%s", MG_VERSION));
|
||||||
|
for (;;) mg_mgr_poll(&mgr, 1000);
|
||||||
|
mg_mgr_free(&mgr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void app_main(void) {
|
||||||
|
// Setup wifi. This function is implemented in wifi.c
|
||||||
|
// It blocks until connected to the configured WiFi network
|
||||||
|
void wifi_init(const char *ssid, const char *pass);
|
||||||
|
wifi_init(WIFI_SSID, WIFI_PASS);
|
||||||
|
|
||||||
|
// Done connecting to WiFi, now start HTTP server
|
||||||
|
run_mongoose();
|
||||||
|
}
|
||||||
@@ -0,0 +1,104 @@
|
|||||||
|
// Code taken from the ESP32 IDF WiFi station Example
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "esp_event.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "esp_system.h"
|
||||||
|
#include "esp_wifi.h"
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/event_groups.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
|
#include "nvs_flash.h"
|
||||||
|
|
||||||
|
#include "lwip/err.h"
|
||||||
|
#include "lwip/sys.h"
|
||||||
|
|
||||||
|
#include "mongoose.h"
|
||||||
|
|
||||||
|
static EventGroupHandle_t s_wifi_event_group;
|
||||||
|
|
||||||
|
/* The event group allows multiple bits for each event, but we only care about
|
||||||
|
* two events:
|
||||||
|
* - we are connected to the AP with an IP
|
||||||
|
* - we failed to connect after the maximum amount of retries */
|
||||||
|
#define WIFI_CONNECTED_BIT BIT0
|
||||||
|
#define WIFI_FAIL_BIT BIT1
|
||||||
|
|
||||||
|
static int s_retry_num = 0;
|
||||||
|
|
||||||
|
static void event_handler(void *arg, esp_event_base_t event_base,
|
||||||
|
int32_t event_id, void *event_data) {
|
||||||
|
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
|
||||||
|
esp_wifi_connect();
|
||||||
|
} else if (event_base == WIFI_EVENT &&
|
||||||
|
event_id == WIFI_EVENT_STA_DISCONNECTED) {
|
||||||
|
if (s_retry_num < 3) {
|
||||||
|
esp_wifi_connect();
|
||||||
|
s_retry_num++;
|
||||||
|
LOG(LL_INFO, ("retry to connect to the AP"));
|
||||||
|
} else {
|
||||||
|
xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT);
|
||||||
|
}
|
||||||
|
LOG(LL_ERROR, ("connect to the AP fail"));
|
||||||
|
} else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
|
||||||
|
ip_event_got_ip_t *event = (ip_event_got_ip_t *) event_data;
|
||||||
|
LOG(LL_INFO, ("got ip:" IPSTR, IP2STR(&event->ip_info.ip)));
|
||||||
|
s_retry_num = 0;
|
||||||
|
xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void wifi_init(const char *ssid, const char *pass) {
|
||||||
|
esp_err_t ret = nvs_flash_init();
|
||||||
|
if (ret == ESP_ERR_NVS_NO_FREE_PAGES ||
|
||||||
|
ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
|
||||||
|
ESP_ERROR_CHECK(nvs_flash_erase());
|
||||||
|
ret = nvs_flash_init();
|
||||||
|
}
|
||||||
|
ESP_ERROR_CHECK(ret);
|
||||||
|
|
||||||
|
s_wifi_event_group = xEventGroupCreate();
|
||||||
|
|
||||||
|
ESP_ERROR_CHECK(esp_netif_init());
|
||||||
|
|
||||||
|
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||||
|
esp_netif_create_default_wifi_sta();
|
||||||
|
|
||||||
|
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
||||||
|
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
|
||||||
|
|
||||||
|
esp_event_handler_instance_t instance_any_id;
|
||||||
|
esp_event_handler_instance_t instance_got_ip;
|
||||||
|
ESP_ERROR_CHECK(esp_event_handler_instance_register(
|
||||||
|
WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL, &instance_any_id));
|
||||||
|
ESP_ERROR_CHECK(esp_event_handler_instance_register(
|
||||||
|
IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL, &instance_got_ip));
|
||||||
|
|
||||||
|
wifi_config_t c = {.sta = {.threshold = {.authmode = WIFI_AUTH_WPA2_PSK},
|
||||||
|
.pmf_cfg = {.capable = true, .required = false}}};
|
||||||
|
snprintf((char *) c.sta.ssid, sizeof(c.sta.ssid), "%s", ssid);
|
||||||
|
snprintf((char *) c.sta.password, sizeof(c.sta.password), "%s", pass);
|
||||||
|
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
|
||||||
|
ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &c));
|
||||||
|
ESP_ERROR_CHECK(esp_wifi_start());
|
||||||
|
LOG(LL_DEBUG, ("wifi_init_sta finished."));
|
||||||
|
|
||||||
|
EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group,
|
||||||
|
WIFI_CONNECTED_BIT | WIFI_FAIL_BIT,
|
||||||
|
pdFALSE, pdFALSE, portMAX_DELAY);
|
||||||
|
|
||||||
|
if (bits & WIFI_CONNECTED_BIT) {
|
||||||
|
LOG(LL_INFO, ("connected to ap SSID:%s password:%s", ssid, pass));
|
||||||
|
} else if (bits & WIFI_FAIL_BIT) {
|
||||||
|
LOG(LL_ERROR, ("Failed to connect to SSID:%s, password:%s", ssid, pass));
|
||||||
|
} else {
|
||||||
|
LOG(LL_ERROR, ("UNEXPECTED EVENT"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The event will not be processed after unregister */
|
||||||
|
ESP_ERROR_CHECK(esp_event_handler_instance_unregister(
|
||||||
|
IP_EVENT, IP_EVENT_STA_GOT_IP, instance_got_ip));
|
||||||
|
ESP_ERROR_CHECK(esp_event_handler_instance_unregister(
|
||||||
|
WIFI_EVENT, ESP_EVENT_ANY_ID, instance_any_id));
|
||||||
|
vEventGroupDelete(s_wifi_event_group);
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
THISDIR = $(realpath $(CURDIR))
|
||||||
|
ROOTDIR = $(realpath $(CURDIR)/../..)
|
||||||
|
|
||||||
|
all: example
|
||||||
|
|
||||||
|
example: src/main/main.c src/main/wifi.c Makefile
|
||||||
|
docker run --rm -v $(ROOTDIR):$(ROOTDIR) -w $(THISDIR) docker.io/mdashnet/8266 make -C src defconfig app
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf $(PROG) *.o *.dSYM *.gcov *.gcno *.gcda *.obj *.exe *.ilk *.pdb mongoose mongoose_* mongoose.* src/build src/sdkconfig
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# An example ESP8266 application
|
||||||
|
|
||||||
|
To build this application, follow these steps:
|
||||||
|
|
||||||
|
1. Make sure you have Docker installed
|
||||||
|
2. Clone whole mongoose repository on your machine:
|
||||||
|
```sh
|
||||||
|
git clone https://github.com/cesanta/mongoose.git
|
||||||
|
```
|
||||||
|
3. Start command line or terminal, and go into the example's directory:
|
||||||
|
```sh
|
||||||
|
cd mongoose/examples/esp8266
|
||||||
|
```
|
||||||
|
4. Run `make`. This invokes a Docker-based build. A firmware will be built
|
||||||
|
in the `src/build/` directory:
|
||||||
|
```sh
|
||||||
|
make example
|
||||||
|
```
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
#
|
||||||
|
# This is a project Makefile. It is assumed the directory this Makefile resides in is a
|
||||||
|
# project subdirectory.
|
||||||
|
#
|
||||||
|
|
||||||
|
PROJECT_NAME := mongoose-example
|
||||||
|
|
||||||
|
include $(IDF_PATH)/make/project.mk
|
||||||
|
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
#
|
||||||
|
# Main component makefile.
|
||||||
|
#
|
||||||
|
# This Makefile can be left empty. By default, it will take the sources in the
|
||||||
|
# src/ directory, compile them and link them into lib(subdirectory_name).a
|
||||||
|
# in the build directory. This behaviour is entirely configurable,
|
||||||
|
# please read the ESP-IDF documents if you need to do this.
|
||||||
|
#
|
||||||
|
|
||||||
|
COMPONENT_INCLUDES += ../../../../..
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
// Copyright (c) 2020 Cesanta Software Limited
|
||||||
|
// All rights reserved
|
||||||
|
|
||||||
|
#include "mongoose.h"
|
||||||
|
|
||||||
|
#define WIFI_SSID "WIFI_NETWORK" // SET THIS!
|
||||||
|
#define WIFI_PASS "WIFI_PASSWORD" // SET THIS!
|
||||||
|
|
||||||
|
#define SERVER_URL "http://0.0.0.0:80"
|
||||||
|
#define CLIENT_URL "http://info.cern.ch"
|
||||||
|
|
||||||
|
// Event handler for an server (accepted) connection
|
||||||
|
static void cb(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
|
||||||
|
if (ev == MG_EV_HTTP_MSG) {
|
||||||
|
mg_http_reply(c, 200, "", "Hello from ESP!\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Event handler for a client connection - fetch the first web page in history
|
||||||
|
// To enable TLS for HTTP,
|
||||||
|
// 1. Copy "ca.pem" file to the ESP32 flash FS
|
||||||
|
// 2. Add TLS init snippet for the connection, see examples/http-client
|
||||||
|
static void cb2(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
|
||||||
|
if (ev == MG_EV_CONNECT) {
|
||||||
|
struct mg_str s = mg_url_host(CLIENT_URL);
|
||||||
|
mg_printf(c, "GET / HTTP/1.0\r\nHost: %.*s\r\n\r\n", (int) s.len, s.ptr);
|
||||||
|
} else if (ev == MG_EV_HTTP_MSG) {
|
||||||
|
struct mg_http_message *hm = ev_data; // Print HTTP response
|
||||||
|
LOG(LL_INFO, ("Fetched:\n%.*s", (int) hm->message.len, hm->message.ptr));
|
||||||
|
c->is_closing = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called after we're connected to WiFi network
|
||||||
|
static void run_mongoose(void) {
|
||||||
|
struct mg_mgr mgr;
|
||||||
|
mg_log_set("3");
|
||||||
|
mg_mgr_init(&mgr);
|
||||||
|
mg_http_listen(&mgr, SERVER_URL, cb, &mgr); // Listening server
|
||||||
|
mg_http_connect(&mgr, CLIENT_URL, cb2, &mgr); // Example client
|
||||||
|
LOG(LL_INFO, ("Starting Mongoose web server v%s", MG_VERSION));
|
||||||
|
for (;;) mg_mgr_poll(&mgr, 1000);
|
||||||
|
mg_mgr_free(&mgr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void app_main(void) {
|
||||||
|
// Setup wifi. This function is implemented in wifi.c
|
||||||
|
// It blocks until connected to the configured WiFi network
|
||||||
|
void wifi_init(const char *ssid, const char *pass);
|
||||||
|
wifi_init(WIFI_SSID, WIFI_PASS);
|
||||||
|
|
||||||
|
// Done connecting to WiFi, now start HTTP server
|
||||||
|
run_mongoose();
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
../../../../mongoose.c
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
#include <string.h>
|
||||||
|
#include "esp_event.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "esp_system.h"
|
||||||
|
#include "esp_wifi.h"
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/event_groups.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
|
#include "nvs_flash.h"
|
||||||
|
|
||||||
|
#include "lwip/err.h"
|
||||||
|
#include "lwip/sys.h"
|
||||||
|
|
||||||
|
#include "mongoose.h"
|
||||||
|
|
||||||
|
static EventGroupHandle_t s_wifi_event_group;
|
||||||
|
|
||||||
|
/* The event group allows multiple bits for each event, but we only care about
|
||||||
|
* two events:
|
||||||
|
* - we are connected to the AP with an IP
|
||||||
|
* - we failed to connect after the maximum amount of retries */
|
||||||
|
#define WIFI_CONNECTED_BIT BIT0
|
||||||
|
#define WIFI_FAIL_BIT BIT1
|
||||||
|
|
||||||
|
static int s_retry_num = 0;
|
||||||
|
|
||||||
|
static void event_handler(void *arg, esp_event_base_t event_base,
|
||||||
|
int32_t event_id, void *event_data) {
|
||||||
|
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
|
||||||
|
esp_wifi_connect();
|
||||||
|
} else if (event_base == WIFI_EVENT &&
|
||||||
|
event_id == WIFI_EVENT_STA_DISCONNECTED) {
|
||||||
|
if (s_retry_num < 3) {
|
||||||
|
esp_wifi_connect();
|
||||||
|
s_retry_num++;
|
||||||
|
LOG(LL_DEBUG, ("retry to connect to the AP"));
|
||||||
|
} else {
|
||||||
|
xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT);
|
||||||
|
}
|
||||||
|
LOG(LL_ERROR, ("connect to the AP fail"));
|
||||||
|
} else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
|
||||||
|
ip_event_got_ip_t *event = (ip_event_got_ip_t *) event_data;
|
||||||
|
LOG(LL_INFO, ("got ip:%s", ip4addr_ntoa(&event->ip_info.ip)));
|
||||||
|
s_retry_num = 0;
|
||||||
|
xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void wifi_init(const char *ssid, const char *pass) {
|
||||||
|
s_wifi_event_group = xEventGroupCreate();
|
||||||
|
tcpip_adapter_init();
|
||||||
|
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||||
|
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
||||||
|
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
|
||||||
|
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID,
|
||||||
|
&event_handler, NULL));
|
||||||
|
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP,
|
||||||
|
&event_handler, NULL));
|
||||||
|
|
||||||
|
wifi_config_t c = {};
|
||||||
|
snprintf((char *) c.sta.ssid, sizeof(c.sta.ssid), "%s", ssid);
|
||||||
|
snprintf((char *) c.sta.password, sizeof(c.sta.password), "%s", pass);
|
||||||
|
if (pass != NULL && pass[0] != '\0') {
|
||||||
|
c.sta.threshold.authmode = WIFI_AUTH_WPA2_PSK;
|
||||||
|
}
|
||||||
|
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
|
||||||
|
ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &c));
|
||||||
|
ESP_ERROR_CHECK(esp_wifi_start());
|
||||||
|
EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group,
|
||||||
|
WIFI_CONNECTED_BIT | WIFI_FAIL_BIT,
|
||||||
|
pdFALSE, pdFALSE, portMAX_DELAY);
|
||||||
|
|
||||||
|
if (bits & WIFI_CONNECTED_BIT) {
|
||||||
|
LOG(LL_INFO, ("connected to ap SSID:%s password:%s", ssid, pass));
|
||||||
|
} else if (bits & WIFI_FAIL_BIT) {
|
||||||
|
LOG(LL_ERROR, ("Failed to connect to SSID:%s, password:%s", ssid, pass));
|
||||||
|
} else {
|
||||||
|
LOG(LL_ERROR, ("UNEXPECTED EVENT"));
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_ERROR_CHECK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP,
|
||||||
|
&event_handler));
|
||||||
|
ESP_ERROR_CHECK(esp_event_handler_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID,
|
||||||
|
&event_handler));
|
||||||
|
vEventGroupDelete(s_wifi_event_group);
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
PROG ?= example
|
||||||
|
|
||||||
|
all: $(PROG)
|
||||||
|
$(DEBUGGER) ./$(PROG)
|
||||||
|
|
||||||
|
$(PROG):
|
||||||
|
$(CC) ../../mongoose.c -I../.. $(CFLAGS) $(EXTRA) -o $(PROG) main.c
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf $(PROG) *.o *.dSYM *.gcov *.gcno *.gcda *.obj *.exe *.ilk *.pdb log.txt
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
// Copyright (c) 2020 Cesanta Software Limited
|
||||||
|
// All rights reserved
|
||||||
|
|
||||||
|
#include "mongoose.h"
|
||||||
|
|
||||||
|
// HTTP request handler function. It implements the following endpoints:
|
||||||
|
// /upload - Saves the next file chunk
|
||||||
|
// all other URI - serves web_root/ directory
|
||||||
|
static void cb(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
|
||||||
|
if (ev == MG_EV_HTTP_MSG) {
|
||||||
|
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||||
|
if (mg_http_match_uri(hm, "/upload")) {
|
||||||
|
mg_http_upload(c, hm, "/tmp");
|
||||||
|
} else {
|
||||||
|
struct mg_http_serve_opts opts = {.root_dir = "web_root"};
|
||||||
|
mg_http_serve_dir(c, ev_data, &opts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
struct mg_mgr mgr;
|
||||||
|
struct mg_timer t1;
|
||||||
|
|
||||||
|
mg_mgr_init(&mgr);
|
||||||
|
mg_log_set("3");
|
||||||
|
mg_http_listen(&mgr, "http://localhost:8000", cb, NULL);
|
||||||
|
|
||||||
|
for (;;) mg_mgr_poll(&mgr, 50);
|
||||||
|
mg_mgr_free(&mgr);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
// Copyright (c) 2020 Cesanta Software Limited
|
||||||
|
// All rights reserved
|
||||||
|
|
||||||
|
// Helper function to display upload status
|
||||||
|
var setStatus = function(text) {
|
||||||
|
document.getElementById('el3').innerText = text;
|
||||||
|
};
|
||||||
|
|
||||||
|
// When user clicks on a button, trigger file selection dialog
|
||||||
|
var button = document.getElementById('el2');
|
||||||
|
button.onclick = function(ev) {
|
||||||
|
input.click();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Send a large blob of data chunk by chunk
|
||||||
|
var sendFileData = function(name, data, chunkSize) {
|
||||||
|
var sendChunk = function(offset) {
|
||||||
|
var chunk = data.subarray(offset, offset + chunkSize) || '';
|
||||||
|
var opts = {method: 'POST', body: chunk};
|
||||||
|
var url = '/upload?offset=' + offset + '&name=' + encodeURIComponent(name);
|
||||||
|
setStatus(
|
||||||
|
'sending bytes ' + offset + '..' + (offset + chunk.length) + ' of ' +
|
||||||
|
data.length);
|
||||||
|
fetch(url, opts).then(function(res) {
|
||||||
|
if (chunk.length > 0) sendChunk(offset + chunk.length);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
sendChunk(0);
|
||||||
|
};
|
||||||
|
|
||||||
|
// If user selected a file, read it into memory and trigger sendFileData()
|
||||||
|
var input = document.getElementById('el1');
|
||||||
|
input.onchange = function(ev) {
|
||||||
|
if (!ev.target.files[0]) return;
|
||||||
|
var f = ev.target.files[0], r = new FileReader();
|
||||||
|
r.readAsArrayBuffer(f);
|
||||||
|
r.onload = function() {
|
||||||
|
ev.target.value = '';
|
||||||
|
sendFileData(f.name, new Uint8Array(r.result), 4096);
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<title>example</title>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<style>
|
||||||
|
#container { margin-right: auto; margin-left: auto; max-width: 480px; }
|
||||||
|
#info { background: #e0f0f0; border-radius: .5em; padding: 2em; }
|
||||||
|
#wrapper { margin-top: 1em; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="container">
|
||||||
|
<div id="info">
|
||||||
|
Mongoose always buffers a full HTTP message before invoking
|
||||||
|
MG_EV_HTTP_MSG event. Big POST request require of lot
|
||||||
|
of RAM to buffer everything. Therefore, in order to upload large
|
||||||
|
files on memory-constrained system, a large file should be send
|
||||||
|
in small chunks.
|
||||||
|
<br/><br/>
|
||||||
|
In this example, JavaScript code on this page sends uploaded
|
||||||
|
file in 2k chunks using an <code>/upload</code> endpoint.
|
||||||
|
Uploaded file is stored in <code>/tmp</code> directory by the helper
|
||||||
|
API function <code>mg_http_upload()</code>
|
||||||
|
</div>
|
||||||
|
<div id="wrapper">
|
||||||
|
<input type="file" id="el1" style="display: none"/>
|
||||||
|
<button id="el2">choose file...</button>
|
||||||
|
<div id="el3"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
<script src="app.js"></script>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
PROG ?= example
|
||||||
|
CFLAGS ?= -DMG_ENABLE_LINES $(CFLAGS_EXTRA)
|
||||||
|
MBEDTLS_DIR ?=
|
||||||
|
|
||||||
|
ifeq "$(MBEDTLS_DIR)" ""
|
||||||
|
else
|
||||||
|
CFLAGS += -DMG_ENABLE_MBEDTLS=1 -I$(MBEDTLS_DIR)/include -I/usr/include
|
||||||
|
CFLAGS += -L$(MBEDTLS_DIR)/lib -lmbedtls -lmbedcrypto -lmbedx509
|
||||||
|
endif
|
||||||
|
|
||||||
|
all: $(PROG)
|
||||||
|
$(DEBUGGER) ./$(PROG) $(ARGS)
|
||||||
|
|
||||||
|
|
||||||
|
$(PROG): main.c
|
||||||
|
$(CC) ../../mongoose.c -I../.. -W -Wall $(CFLAGS) -o $(PROG) main.c
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf $(PROG) *.o *.dSYM *.gcov *.gcno *.gcda *.obj *.exe *.ilk *.pdb
|
||||||
@@ -0,0 +1,507 @@
|
|||||||
|
Subject: O=Digital Signature Trust Co., CN=DST Root CA X3
|
||||||
|
Not Before: Sep 30 21:12:19 2000 GMT
|
||||||
|
Not After : Sep 30 14:01:15 2021 GMT
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/
|
||||||
|
MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
|
||||||
|
DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow
|
||||||
|
PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD
|
||||||
|
Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
|
||||||
|
AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O
|
||||||
|
rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq
|
||||||
|
OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b
|
||||||
|
xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw
|
||||||
|
7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD
|
||||||
|
aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV
|
||||||
|
HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG
|
||||||
|
SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69
|
||||||
|
ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr
|
||||||
|
AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz
|
||||||
|
R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5
|
||||||
|
JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo
|
||||||
|
Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
Subject: C=IE, O=Baltimore, OU=CyberTrust, CN=Baltimore CyberTrust Root
|
||||||
|
Not Before: May 12 18:46:00 2000 GMT
|
||||||
|
Not After : May 12 23:59:00 2025 GMT
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ
|
||||||
|
RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD
|
||||||
|
VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX
|
||||||
|
DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y
|
||||||
|
ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy
|
||||||
|
VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr
|
||||||
|
mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr
|
||||||
|
IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK
|
||||||
|
mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu
|
||||||
|
XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy
|
||||||
|
dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye
|
||||||
|
jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1
|
||||||
|
BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3
|
||||||
|
DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92
|
||||||
|
9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx
|
||||||
|
jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0
|
||||||
|
Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz
|
||||||
|
ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS
|
||||||
|
R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
Subject: C=US, O=GeoTrust Inc., CN=GeoTrust Global CA
|
||||||
|
Not Before: May 21 04:00:00 2002 GMT
|
||||||
|
Not After : May 21 04:00:00 2022 GMT
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT
|
||||||
|
MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i
|
||||||
|
YWwgQ0EwHhcNMDIwNTIxMDQwMDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQG
|
||||||
|
EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMSR2VvVHJ1c3Qg
|
||||||
|
R2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2swYYzD9
|
||||||
|
9BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjoBbdq
|
||||||
|
fnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDv
|
||||||
|
iS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU
|
||||||
|
1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+
|
||||||
|
bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5aszPeE4uwc2hGKceeoW
|
||||||
|
MPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTA
|
||||||
|
ephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVkDBF9qn1l
|
||||||
|
uMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKIn
|
||||||
|
Z57QzxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfS
|
||||||
|
tQWVYrmm3ok9Nns4d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcF
|
||||||
|
PseKUgzbFbS9bZvlxrFUaKnjaZC2mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Un
|
||||||
|
hw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6pXE0zX5IJL4hmXXeXxx12E6nV
|
||||||
|
5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvmMw==
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
Subject: C=US, O=Symantec Corporation, OU=Symantec Trust Network, CN=Symantec Class 3 ECC 256 bit SSL CA - G2
|
||||||
|
Not Before: May 12 00:00:00 2015 GMT
|
||||||
|
Not After : May 11 23:59:59 2025 GMT
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIEajCCA1KgAwIBAgIQP5KHvp0dpKN6nfYoLndaxDANBgkqhkiG9w0BAQsFADCB
|
||||||
|
yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL
|
||||||
|
ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp
|
||||||
|
U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW
|
||||||
|
ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0
|
||||||
|
aG9yaXR5IC0gRzUwHhcNMTUwNTEyMDAwMDAwWhcNMjUwNTExMjM1OTU5WjCBgDEL
|
||||||
|
MAkGA1UEBhMCVVMxHTAbBgNVBAoTFFN5bWFudGVjIENvcnBvcmF0aW9uMR8wHQYD
|
||||||
|
VQQLExZTeW1hbnRlYyBUcnVzdCBOZXR3b3JrMTEwLwYDVQQDEyhTeW1hbnRlYyBD
|
||||||
|
bGFzcyAzIEVDQyAyNTYgYml0IFNTTCBDQSAtIEcyMFkwEwYHKoZIzj0CAQYIKoZI
|
||||||
|
zj0DAQcDQgAEDxukkdfnrOfRTk63ZFvhj39uBNOrONtEt0Bcbb2WljffeYmGZ/ex
|
||||||
|
Hwie/WM7RoyfvVPoFdyXPiuBRq2Gfw4BOaOCAV0wggFZMC4GCCsGAQUFBwEBBCIw
|
||||||
|
IDAeBggrBgEFBQcwAYYSaHR0cDovL3Muc3ltY2QuY29tMBIGA1UdEwEB/wQIMAYB
|
||||||
|
Af8CAQAwZQYDVR0gBF4wXDBaBgpghkgBhvhFAQc2MEwwIwYIKwYBBQUHAgEWF2h0
|
||||||
|
dHBzOi8vZC5zeW1jYi5jb20vY3BzMCUGCCsGAQUFBwICMBkaF2h0dHBzOi8vZC5z
|
||||||
|
eW1jYi5jb20vcnBhMC8GA1UdHwQoMCYwJKAioCCGHmh0dHA6Ly9zLnN5bWNiLmNv
|
||||||
|
bS9wY2EzLWc1LmNybDAOBgNVHQ8BAf8EBAMCAQYwKwYDVR0RBCQwIqQgMB4xHDAa
|
||||||
|
BgNVBAMTE1NZTUMtRUNDLUNBLXAyNTYtMjIwHQYDVR0OBBYEFCXwiuFLetkBlQrt
|
||||||
|
xlPxjHgf2fP4MB8GA1UdIwQYMBaAFH/TZafC3ey78DAJ80M5+gKvMzEzMA0GCSqG
|
||||||
|
SIb3DQEBCwUAA4IBAQAMMGUXBaWTdaLxsTGtcB/naqjIQrLvoV9NG+7MoHpGd/69
|
||||||
|
dZ/h2zOy7sGFUHoG/0HGRA9rxT/5w5GkEVIVkxtWyIWWq6rs4CTZt8Bej/KHYRbo
|
||||||
|
jtEDUkCTZSTLiCvguPyvinXgxy+LHT+PmdtEfXsvcdbeBSWUYpOsDYvD2hNtz9dw
|
||||||
|
Od5nBosMApmdxt+z7LQyZu8wMnfI1U6IMO+RWowxZ8uy0oswdFYd32l9xe+aAE/k
|
||||||
|
y9alLu/M9pvxiUKufqHJRgDBKA6uDjHLMPX+/nxXaNCPX3SI4KVZ1stHQ/U5oNlM
|
||||||
|
dHN9umAvlU313g0IgJrjsQ2nIdf9dsdP+6lrmP7s
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
Subject: C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, OU=(c) 2006 VeriSign, Inc. - For authorized use only, CN=VeriSign Class 3 Public Primary Certification Authority - G5
|
||||||
|
Not Before: Nov 8 00:00:00 2006 GMT
|
||||||
|
Not After : Jul 16 23:59:59 2036 GMT
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCB
|
||||||
|
yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL
|
||||||
|
ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp
|
||||||
|
U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW
|
||||||
|
ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0
|
||||||
|
aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCByjEL
|
||||||
|
MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW
|
||||||
|
ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2ln
|
||||||
|
biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp
|
||||||
|
U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y
|
||||||
|
aXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvJAgIKXo1
|
||||||
|
nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKzj/i5Vbex
|
||||||
|
t0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIz
|
||||||
|
SdhDY2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQG
|
||||||
|
BO+QueQA5N06tRn/Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+
|
||||||
|
rCpSx4/VBEnkjWNHiDxpg8v+R70rfk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/
|
||||||
|
NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E
|
||||||
|
BAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEwHzAH
|
||||||
|
BgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy
|
||||||
|
aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKv
|
||||||
|
MzEzMA0GCSqGSIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzE
|
||||||
|
p6B4Eq1iDkVwZMXnl2YtmAl+X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y
|
||||||
|
5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKEKQsTb47bDN0lAtukixlE0kF6BWlK
|
||||||
|
WE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiCKm0oHw0LxOXnGiYZ
|
||||||
|
4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vEZV8N
|
||||||
|
hnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
Subject: C=US, O=The Go Daddy Group, Inc., OU=Go Daddy Class 2 Certification Authority
|
||||||
|
Not Before: Jun 29 17:06:20 2004 GMT
|
||||||
|
Not After : Jun 29 17:06:20 2034 GMT
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEh
|
||||||
|
MB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBE
|
||||||
|
YWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3
|
||||||
|
MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRo
|
||||||
|
ZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3Mg
|
||||||
|
MiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggEN
|
||||||
|
ADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCA
|
||||||
|
PVYYYwhv2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6w
|
||||||
|
wdhFJ2+qN1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXi
|
||||||
|
EqITLdiOr18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMY
|
||||||
|
avx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+
|
||||||
|
YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0OBBYEFNLE
|
||||||
|
sNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h
|
||||||
|
/t2oatTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5
|
||||||
|
IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmlj
|
||||||
|
YXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD
|
||||||
|
ggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wimPQoZ+YeAEW5p5JYXMP80kWNy
|
||||||
|
OO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKtI3lpjbi2Tc7P
|
||||||
|
TMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ
|
||||||
|
HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mER
|
||||||
|
dEr/VxqHD3VILs9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5Cuf
|
||||||
|
ReYNnyicsbkqWletNw+vHX/bvZ8=
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
# Note: Amazon ATS endpoint uses this (2018/12/18)
|
||||||
|
Subject: C=US, O=Starfield Technologies, Inc., OU=Starfield Class 2 Certification Authority
|
||||||
|
Not Before: Jun 29 17:39:16 2004 GMT
|
||||||
|
Not After : Jun 29 17:39:16 2034 GMT
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzEl
|
||||||
|
MCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMp
|
||||||
|
U3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQw
|
||||||
|
NjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBoMQswCQYDVQQGEwJVUzElMCMGA1UE
|
||||||
|
ChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZp
|
||||||
|
ZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqGSIb3
|
||||||
|
DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf
|
||||||
|
8MOh2tTYbitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN
|
||||||
|
+lq2cwQlZut3f+dZxkqZJRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0
|
||||||
|
X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVmepsZGD3/cVE8MC5fvj13c7JdBmzDI1aa
|
||||||
|
K4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSNF4Azbl5KXZnJHoe0nRrA
|
||||||
|
1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HFMIHCMB0G
|
||||||
|
A1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fR
|
||||||
|
zt0fhvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0
|
||||||
|
YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBD
|
||||||
|
bGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8w
|
||||||
|
DQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGsafPzWdqbAYcaT1epoXkJKtv3
|
||||||
|
L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLMPUxA2IGvd56D
|
||||||
|
eruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl
|
||||||
|
xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynp
|
||||||
|
VSJYACPq4xJDKVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEY
|
||||||
|
WQPJIrSPnNVeKtelttQKbfi3QBFGmh95DmK/D5fs4C8fF5Q=
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
Not Before: Sep 1 00:00:00 2009 GMT
|
||||||
|
Not After : Dec 31 23:59:59 2037 GMT
|
||||||
|
Subject: C=US, ST=Arizona, L=Scottsdale, O=Starfield Technologies, Inc., CN=Starfield Root Certificate Authority - G2
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMx
|
||||||
|
EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT
|
||||||
|
HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVs
|
||||||
|
ZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAw
|
||||||
|
MFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6
|
||||||
|
b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQgVGVj
|
||||||
|
aG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZp
|
||||||
|
Y2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
|
||||||
|
ggEBAL3twQP89o/8ArFvW59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMg
|
||||||
|
nLRJdzIpVv257IzdIvpy3Cdhl+72WoTsbhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1
|
||||||
|
HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNkN3mSwOxGXn/hbVNMYq/N
|
||||||
|
Hwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7NfZTD4p7dN
|
||||||
|
dloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0
|
||||||
|
HZbUJtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO
|
||||||
|
BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0G
|
||||||
|
CSqGSIb3DQEBCwUAA4IBAQARWfolTwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjU
|
||||||
|
sHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx4mcujJUDJi5DnUox9g61DLu3
|
||||||
|
4jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUwF5okxBDgBPfg
|
||||||
|
8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K
|
||||||
|
pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1
|
||||||
|
mMpYjn0q7pBZc2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
Subject: C=US, ST=Arizona, L=Scottsdale, O=Starfield Technologies, Inc., CN=Starfield Services Root Certificate Authority - G2
|
||||||
|
Not Before: Sep 1 00:00:00 2009 GMT
|
||||||
|
Not After : Dec 31 23:59:59 2037 GMT
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMx
|
||||||
|
EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT
|
||||||
|
HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVs
|
||||||
|
ZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5
|
||||||
|
MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNVBAYTAlVTMRAwDgYD
|
||||||
|
VQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFy
|
||||||
|
ZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2Vy
|
||||||
|
dmljZXMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI
|
||||||
|
hvcNAQEBBQADggEPADCCAQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20p
|
||||||
|
OsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm2
|
||||||
|
8xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4PahHQUw2eeBGg6345AWh1K
|
||||||
|
Ts9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLPLJGmpufe
|
||||||
|
hRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk
|
||||||
|
6mFBrMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAw
|
||||||
|
DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+q
|
||||||
|
AdcwKziIorhtSpzyEZGDMA0GCSqGSIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMI
|
||||||
|
bw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPPE95Dz+I0swSdHynVv/heyNXB
|
||||||
|
ve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTyxQGjhdByPq1z
|
||||||
|
qwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd
|
||||||
|
iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn
|
||||||
|
0q23KXB56jzaYyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCN
|
||||||
|
sSi6
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
Subject: OU=GlobalSign Root CA - R2, O=GlobalSign, CN=GlobalSign
|
||||||
|
Not Before: Dec 15 08:00:00 2006 GMT
|
||||||
|
Not After : Dec 15 08:00:00 2021 GMT
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4G
|
||||||
|
A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNp
|
||||||
|
Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1
|
||||||
|
MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMjETMBEG
|
||||||
|
A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI
|
||||||
|
hvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6ErPL
|
||||||
|
v4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8
|
||||||
|
eoLrvozps6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklq
|
||||||
|
tTleiDTsvHgMCJiEbKjNS7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzd
|
||||||
|
C9XZzPnqJworc5HGnRusyMvo4KD0L5CLTfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pa
|
||||||
|
zq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6CygPCm48CAwEAAaOBnDCB
|
||||||
|
mTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUm+IH
|
||||||
|
V2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5n
|
||||||
|
bG9iYWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG
|
||||||
|
3lm0mi3f3BmGLjANBgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4Gs
|
||||||
|
J0/WwbgcQ3izDJr86iw8bmEbTUsp9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO
|
||||||
|
291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu01yiPqFbQfXf5WRDLenVOavS
|
||||||
|
ot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG79G+dwfCMNYxd
|
||||||
|
AfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7
|
||||||
|
TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg==
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
Subject: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert High Assurance EV Root CA
|
||||||
|
Not Before: Nov 10 00:00:00 2006 GMT
|
||||||
|
Not After : Nov 10 00:00:00 2031 GMT
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs
|
||||||
|
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
|
||||||
|
d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
|
||||||
|
ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL
|
||||||
|
MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
|
||||||
|
LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug
|
||||||
|
RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm
|
||||||
|
+9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW
|
||||||
|
PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM
|
||||||
|
xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB
|
||||||
|
Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3
|
||||||
|
hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg
|
||||||
|
EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF
|
||||||
|
MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA
|
||||||
|
FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec
|
||||||
|
nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z
|
||||||
|
eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF
|
||||||
|
hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2
|
||||||
|
Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe
|
||||||
|
vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep
|
||||||
|
+OkuE6N36B9K
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
Subject: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Global Root CA
|
||||||
|
Not Before: Nov 10 00:00:00 2006 GMT
|
||||||
|
Not After : Nov 10 00:00:00 2031 GMT
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh
|
||||||
|
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
|
||||||
|
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
|
||||||
|
QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT
|
||||||
|
MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
|
||||||
|
b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG
|
||||||
|
9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB
|
||||||
|
CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97
|
||||||
|
nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt
|
||||||
|
43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P
|
||||||
|
T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4
|
||||||
|
gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO
|
||||||
|
BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR
|
||||||
|
TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw
|
||||||
|
DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr
|
||||||
|
hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg
|
||||||
|
06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF
|
||||||
|
PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls
|
||||||
|
YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
|
||||||
|
CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
# *.azure-devices.de use this root.
|
||||||
|
Subject: C = DE, O = D-Trust GmbH, CN = D-TRUST Root Class 3 CA 2 2009
|
||||||
|
Not Before: Nov 5 08:35:58 2009 GMT
|
||||||
|
Not After : Nov 5 08:35:58 2029 GMT
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIEMzCCAxugAwIBAgIDCYPzMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNVBAYTAkRF
|
||||||
|
MRUwEwYDVQQKDAxELVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBD
|
||||||
|
bGFzcyAzIENBIDIgMjAwOTAeFw0wOTExMDUwODM1NThaFw0yOTExMDUwODM1NTha
|
||||||
|
ME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxELVRydXN0IEdtYkgxJzAlBgNVBAMM
|
||||||
|
HkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTCCASIwDQYJKoZIhvcNAQEB
|
||||||
|
BQADggEPADCCAQoCggEBANOySs96R+91myP6Oi/WUEWJNTrGa9v+2wBoqOADER03
|
||||||
|
UAifTUpolDWzU9GUY6cgVq/eUXjsKj3zSEhQPgrfRlWLJ23DEE0NkVJD2IfgXU42
|
||||||
|
tSHKXzlABF9bfsyjxiupQB7ZNoTWSPOSHjRGICTBpFGOShrvUD9pXRl/RcPHAY9R
|
||||||
|
ySPocq60vFYJfxLLHLGvKZAKyVXMD9O0Gu1HNVpK7ZxzBCHQqr0ME7UAyiZsxGsM
|
||||||
|
lFqVlNpQmvH/pStmMaTJOKDfHR+4CS7zp+hnUquVH+BGPtikw8paxTGA6Eian5Rp
|
||||||
|
/hnd2HN8gcqW3o7tszIFZYQ05ub9VxC1X3a/L7AQDcUCAwEAAaOCARowggEWMA8G
|
||||||
|
A1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFP3aFMSfMN4hvR5COfyrYyNJ4PGEMA4G
|
||||||
|
A1UdDwEB/wQEAwIBBjCB0wYDVR0fBIHLMIHIMIGAoH6gfIZ6bGRhcDovL2RpcmVj
|
||||||
|
dG9yeS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwUm9vdCUyMENsYXNzJTIwMyUy
|
||||||
|
MENBJTIwMiUyMDIwMDksTz1ELVRydXN0JTIwR21iSCxDPURFP2NlcnRpZmljYXRl
|
||||||
|
cmV2b2NhdGlvbmxpc3QwQ6BBoD+GPWh0dHA6Ly93d3cuZC10cnVzdC5uZXQvY3Js
|
||||||
|
L2QtdHJ1c3Rfcm9vdF9jbGFzc18zX2NhXzJfMjAwOS5jcmwwDQYJKoZIhvcNAQEL
|
||||||
|
BQADggEBAH+X2zDI36ScfSF6gHDOFBJpiBSVYEQBrLLpME+bUMJm2H6NMLVwMeni
|
||||||
|
acfzcNsgFYbQDfC+rAF1hM5+n02/t2A7nPPKHeJeaNijnZflQGDSNiH+0LS4F9p0
|
||||||
|
o3/U37CYAqxva2ssJSRyoWXuJVrl5jLn8t+rSfrzkGkj2wTZ51xY/GXUl77M/C4K
|
||||||
|
zCUqNQT4YJEVdT1B/yMfGchs64JTBKbkTCJNjYy6zltz7GRUUG3RnFX7acM2w4y8
|
||||||
|
PIWmawomDeCTmGCufsYkl4phX5GOZpIJhzbNi5stPvZR1FDUWSi9g/LMKHtThm3Y
|
||||||
|
Johw1+qRzT65ysCQblrGXnRl11z+o+I=
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
# https://www.amazontrust.com/repository/
|
||||||
|
Subject: C = US, O = Amazon, CN = Amazon Root CA 1
|
||||||
|
Not Before: May 26 00:00:00 2015 GMT
|
||||||
|
Not After : Jan 17 00:00:00 2038 GMT
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF
|
||||||
|
ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6
|
||||||
|
b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL
|
||||||
|
MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv
|
||||||
|
b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj
|
||||||
|
ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM
|
||||||
|
9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw
|
||||||
|
IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6
|
||||||
|
VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L
|
||||||
|
93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm
|
||||||
|
jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
|
||||||
|
AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA
|
||||||
|
A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI
|
||||||
|
U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs
|
||||||
|
N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv
|
||||||
|
o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU
|
||||||
|
5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy
|
||||||
|
rqXRfboQnoZsG4q5WTP468SQvvG5
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
Subject: C = US, O = Amazon, CN = Amazon Root CA 2
|
||||||
|
Not Before: May 26 00:00:00 2015 GMT
|
||||||
|
Not After : May 26 00:00:00 2040 GMT
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIFQTCCAymgAwIBAgITBmyf0pY1hp8KD+WGePhbJruKNzANBgkqhkiG9w0BAQwF
|
||||||
|
ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6
|
||||||
|
b24gUm9vdCBDQSAyMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTEL
|
||||||
|
MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv
|
||||||
|
b3QgQ0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK2Wny2cSkxK
|
||||||
|
gXlRmeyKy2tgURO8TW0G/LAIjd0ZEGrHJgw12MBvIITplLGbhQPDW9tK6Mj4kHbZ
|
||||||
|
W0/jTOgGNk3Mmqw9DJArktQGGWCsN0R5hYGCrVo34A3MnaZMUnbqQ523BNFQ9lXg
|
||||||
|
1dKmSYXpN+nKfq5clU1Imj+uIFptiJXZNLhSGkOQsL9sBbm2eLfq0OQ6PBJTYv9K
|
||||||
|
8nu+NQWpEjTj82R0Yiw9AElaKP4yRLuH3WUnAnE72kr3H9rN9yFVkE8P7K6C4Z9r
|
||||||
|
2UXTu/Bfh+08LDmG2j/e7HJV63mjrdvdfLC6HM783k81ds8P+HgfajZRRidhW+me
|
||||||
|
z/CiVX18JYpvL7TFz4QuK/0NURBs+18bvBt+xa47mAExkv8LV/SasrlX6avvDXbR
|
||||||
|
8O70zoan4G7ptGmh32n2M8ZpLpcTnqWHsFcQgTfJU7O7f/aS0ZzQGPSSbtqDT6Zj
|
||||||
|
mUyl+17vIWR6IF9sZIUVyzfpYgwLKhbcAS4y2j5L9Z469hdAlO+ekQiG+r5jqFoz
|
||||||
|
7Mt0Q5X5bGlSNscpb/xVA1wf+5+9R+vnSUeVC06JIglJ4PVhHvG/LopyboBZ/1c6
|
||||||
|
+XUyo05f7O0oYtlNc/LMgRdg7c3r3NunysV+Ar3yVAhU/bQtCSwXVEqY0VThUWcI
|
||||||
|
0u1ufm8/0i2BWSlmy5A5lREedCf+3euvAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMB
|
||||||
|
Af8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSwDPBMMPQFWAJI/TPlUq9LhONm
|
||||||
|
UjANBgkqhkiG9w0BAQwFAAOCAgEAqqiAjw54o+Ci1M3m9Zh6O+oAA7CXDpO8Wqj2
|
||||||
|
LIxyh6mx/H9z/WNxeKWHWc8w4Q0QshNabYL1auaAn6AFC2jkR2vHat+2/XcycuUY
|
||||||
|
+gn0oJMsXdKMdYV2ZZAMA3m3MSNjrXiDCYZohMr/+c8mmpJ5581LxedhpxfL86kS
|
||||||
|
k5Nrp+gvU5LEYFiwzAJRGFuFjWJZY7attN6a+yb3ACfAXVU3dJnJUH/jWS5E4ywl
|
||||||
|
7uxMMne0nxrpS10gxdr9HIcWxkPo1LsmmkVwXqkLN1PiRnsn/eBG8om3zEK2yygm
|
||||||
|
btmlyTrIQRNg91CMFa6ybRoVGld45pIq2WWQgj9sAq+uEjonljYE1x2igGOpm/Hl
|
||||||
|
urR8FLBOybEfdF849lHqm/osohHUqS0nGkWxr7JOcQ3AWEbWaQbLU8uz/mtBzUF+
|
||||||
|
fUwPfHJ5elnNXkoOrJupmHN5fLT0zLm4BwyydFy4x2+IoZCn9Kr5v2c69BoVYh63
|
||||||
|
n749sSmvZ6ES8lgQGVMDMBu4Gon2nL2XA46jCfMdiyHxtN/kHNGfZQIG6lzWE7OE
|
||||||
|
76KlXIx3KadowGuuQNKotOrN8I1LOJwZmhsoVLiJkO/KdYE+HvJkJMcYr07/R54H
|
||||||
|
9jVlpNMKVv/1F2Rs76giJUmTtt8AF9pYfl3uxRuw0dFfIRDH+fO6AgonB8Xx1sfT
|
||||||
|
4PsJYGw=
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
Not Before: May 26 00:00:00 2015 GMT
|
||||||
|
Not After : May 26 00:00:00 2040 GMT
|
||||||
|
Subject: C = US, O = Amazon, CN = Amazon Root CA 3
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5
|
||||||
|
MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g
|
||||||
|
Um9vdCBDQSAzMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG
|
||||||
|
A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg
|
||||||
|
Q0EgMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCmXp8ZBf8ANm+gBG1bG8lKl
|
||||||
|
ui2yEujSLtf6ycXYqm0fc4E7O5hrOXwzpcVOho6AF2hiRVd9RFgdszflZwjrZt6j
|
||||||
|
QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSr
|
||||||
|
ttvXBp43rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkr
|
||||||
|
BqWTrBqYaGFy+uGh0PsceGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteM
|
||||||
|
YyRIHN8wfdVoOw==
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
Not Before: May 26 00:00:00 2015 GMT
|
||||||
|
Not After : May 26 00:00:00 2040 GMT
|
||||||
|
Subject: C = US, O = Amazon, CN = Amazon Root CA 4
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIB8jCCAXigAwIBAgITBmyf18G7EEwpQ+Vxe3ssyBrBDjAKBggqhkjOPQQDAzA5
|
||||||
|
MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g
|
||||||
|
Um9vdCBDQSA0MB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG
|
||||||
|
A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg
|
||||||
|
Q0EgNDB2MBAGByqGSM49AgEGBSuBBAAiA2IABNKrijdPo1MN/sGKe0uoe0ZLY7Bi
|
||||||
|
9i0b2whxIdIA6GO9mif78DluXeo9pcmBqqNbIJhFXRbb/egQbeOc4OO9X4Ri83Bk
|
||||||
|
M6DLJC9wuoihKqB1+IGuYgbEgds5bimwHvouXKNCMEAwDwYDVR0TAQH/BAUwAwEB
|
||||||
|
/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFNPsxzplbszh2naaVvuc84ZtV+WB
|
||||||
|
MAoGCCqGSM49BAMDA2gAMGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlw
|
||||||
|
CkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1AE47xDqUEpHJWEadIRNyp4iciuRMStuW
|
||||||
|
1KyLa2tJElMzrdfkviT8tQp21KW8EA==
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
Not Before: Nov 10 00:00:00 2006 GMT
|
||||||
|
Not After : Nov 10 00:00:00 2031 GMT
|
||||||
|
Subject: C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert Global Root CA
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh
|
||||||
|
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
|
||||||
|
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
|
||||||
|
QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT
|
||||||
|
MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
|
||||||
|
b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG
|
||||||
|
9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB
|
||||||
|
CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97
|
||||||
|
nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt
|
||||||
|
43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P
|
||||||
|
T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4
|
||||||
|
gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO
|
||||||
|
BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR
|
||||||
|
TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw
|
||||||
|
DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr
|
||||||
|
hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg
|
||||||
|
06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF
|
||||||
|
PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls
|
||||||
|
YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
|
||||||
|
CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
Not Before: Nov 13 00:00:00 2012 GMT
|
||||||
|
Not After : Jan 19 03:14:07 2038 GMT
|
||||||
|
Subject: OU = GlobalSign ECC Root CA - R4, O = GlobalSign, CN = GlobalSign
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIB4TCCAYegAwIBAgIRKjikHJYKBN5CsiilC+g0mAIwCgYIKoZIzj0EAwIwUDEk
|
||||||
|
MCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpH
|
||||||
|
bG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoX
|
||||||
|
DTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBD
|
||||||
|
QSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu
|
||||||
|
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuMZ5049sJQ6fLjkZHAOkrprlOQcJ
|
||||||
|
FspjsbmG+IpXwVfOQvpzofdlQv8ewQCybnMO/8ch5RikqtlxP6jUuc6MHaNCMEAw
|
||||||
|
DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFFSwe61F
|
||||||
|
uOJAf/sKbvu+M8k8o4TVMAoGCCqGSM49BAMCA0gAMEUCIQDckqGgE6bPA7DmxCGX
|
||||||
|
kPoUVy0D7O48027KqGx2vKLeuwIgJ6iFJzWbVsaj8kfSt24bAgAXqmemFZHe+pTs
|
||||||
|
ewv4n4Q=
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
Not Before: Nov 1 00:00:42 2018 GMT
|
||||||
|
Not After : Nov 1 00:00:42 2042 GMT
|
||||||
|
Subject: C = US, O = Google Trust Services LLC, CN = GTS LTSR
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIBxTCCAWugAwIBAgINAfD3nVndblD3QnNxUDAKBggqhkjOPQQDAjBEMQswCQYD
|
||||||
|
VQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzERMA8G
|
||||||
|
A1UEAxMIR1RTIExUU1IwHhcNMTgxMTAxMDAwMDQyWhcNNDIxMTAxMDAwMDQyWjBE
|
||||||
|
MQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExM
|
||||||
|
QzERMA8GA1UEAxMIR1RTIExUU1IwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATN
|
||||||
|
8YyO2u+yCQoZdwAkUNv5c3dokfULfrA6QJgFV2XMuENtQZIG5HUOS6jFn8f0ySlV
|
||||||
|
eORCxqFyjDJyRn86d+Iko0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUw
|
||||||
|
AwEB/zAdBgNVHQ4EFgQUPv7/zFLrvzQ+PfNA0OQlsV+4u1IwCgYIKoZIzj0EAwID
|
||||||
|
SAAwRQIhAPKuf/VtBHqGw3TUwUIq7TfaExp3bH7bjCBmVXJupT9FAiBr0SmCtsuk
|
||||||
|
miGgpajjf/gFigGM34F9021bCWs1MbL0SA==
|
||||||
|
-----END CERTIFICATE-----
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
// Copyright (c) 2020 Cesanta Software Limited
|
||||||
|
// All rights reserved
|
||||||
|
//
|
||||||
|
// Example HTTP client. Connect to `s_url`, send request, wait for a response,
|
||||||
|
// print the response and exit.
|
||||||
|
//
|
||||||
|
// To enable SSL/TLS for this client, build it like this:
|
||||||
|
// make MBEDTLS_DIR=/path/to/your/mbedtls/installation
|
||||||
|
|
||||||
|
#include "mongoose.h"
|
||||||
|
|
||||||
|
// The very first web page in history
|
||||||
|
static const char *s_url = "http://info.cern.ch";
|
||||||
|
|
||||||
|
// Print HTTP response and signal that we're done
|
||||||
|
static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
|
||||||
|
if (ev == MG_EV_CONNECT) {
|
||||||
|
// Connected to server
|
||||||
|
struct mg_str host = mg_url_host(s_url);
|
||||||
|
|
||||||
|
if (mg_url_is_ssl(s_url)) {
|
||||||
|
// If s_url is https://, tell client connection to use TLS
|
||||||
|
struct mg_tls_opts opts = {.ca = "ca.pem"};
|
||||||
|
mg_tls_init(c, &opts);
|
||||||
|
}
|
||||||
|
// Send request
|
||||||
|
mg_printf(c, "GET %s HTTP/1.0\r\nHost: %.*s\r\n\r\n", mg_url_uri(s_url),
|
||||||
|
(int) host.len, host.ptr);
|
||||||
|
} else if (ev == MG_EV_HTTP_MSG) {
|
||||||
|
// Response is received. Print it
|
||||||
|
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||||
|
printf("%.*s", (int) hm->message.len, hm->message.ptr);
|
||||||
|
c->is_closing = 1; // Tell mongoose to close this connection
|
||||||
|
*(bool *) fn_data = true; // Tell event loop to stop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
struct mg_mgr mgr; // Event manager
|
||||||
|
bool done = false; // Event handler flips it to true
|
||||||
|
mg_log_set("3"); // Set to 0 to disable debug
|
||||||
|
mg_mgr_init(&mgr); // Initialise event manager
|
||||||
|
mg_http_connect(&mgr, s_url, fn, &done); // Create client connection
|
||||||
|
while (!done) mg_mgr_poll(&mgr, 1000); // Infinite event loop
|
||||||
|
mg_mgr_free(&mgr); // Free resources
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
PROG ?= example
|
||||||
|
ARGS ?= http://www.ladyada.net/
|
||||||
|
MBEDTLS_DIR ?=
|
||||||
|
|
||||||
|
ifeq "$(MBEDTLS_DIR)" ""
|
||||||
|
else
|
||||||
|
CFLAGS += -DMG_ENABLE_MBEDTLS=1 -I$(MBEDTLS_DIR)/include -I/usr/include
|
||||||
|
CFLAGS += -L$(MBEDTLS_DIR)/lib -lmbedtls -lmbedcrypto -lmbedx509
|
||||||
|
endif
|
||||||
|
|
||||||
|
all: $(PROG)
|
||||||
|
$(DEBUGGER) ./$(PROG) $(ARGS)
|
||||||
|
|
||||||
|
|
||||||
|
$(PROG): main.c
|
||||||
|
$(CC) ../../mongoose.c -I../.. -W -Wall $(CFLAGS) -o $(PROG) main.c
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf $(PROG) *.o *.dSYM *.gcov *.gcno *.gcda *.obj *.exe *.ilk *.pdb
|
||||||
@@ -0,0 +1,507 @@
|
|||||||
|
Subject: O=Digital Signature Trust Co., CN=DST Root CA X3
|
||||||
|
Not Before: Sep 30 21:12:19 2000 GMT
|
||||||
|
Not After : Sep 30 14:01:15 2021 GMT
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/
|
||||||
|
MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
|
||||||
|
DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow
|
||||||
|
PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD
|
||||||
|
Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
|
||||||
|
AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O
|
||||||
|
rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq
|
||||||
|
OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b
|
||||||
|
xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw
|
||||||
|
7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD
|
||||||
|
aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV
|
||||||
|
HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG
|
||||||
|
SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69
|
||||||
|
ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr
|
||||||
|
AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz
|
||||||
|
R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5
|
||||||
|
JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo
|
||||||
|
Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
Subject: C=IE, O=Baltimore, OU=CyberTrust, CN=Baltimore CyberTrust Root
|
||||||
|
Not Before: May 12 18:46:00 2000 GMT
|
||||||
|
Not After : May 12 23:59:00 2025 GMT
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ
|
||||||
|
RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD
|
||||||
|
VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX
|
||||||
|
DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y
|
||||||
|
ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy
|
||||||
|
VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr
|
||||||
|
mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr
|
||||||
|
IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK
|
||||||
|
mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu
|
||||||
|
XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy
|
||||||
|
dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye
|
||||||
|
jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1
|
||||||
|
BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3
|
||||||
|
DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92
|
||||||
|
9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx
|
||||||
|
jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0
|
||||||
|
Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz
|
||||||
|
ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS
|
||||||
|
R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
Subject: C=US, O=GeoTrust Inc., CN=GeoTrust Global CA
|
||||||
|
Not Before: May 21 04:00:00 2002 GMT
|
||||||
|
Not After : May 21 04:00:00 2022 GMT
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT
|
||||||
|
MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i
|
||||||
|
YWwgQ0EwHhcNMDIwNTIxMDQwMDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQG
|
||||||
|
EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMSR2VvVHJ1c3Qg
|
||||||
|
R2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2swYYzD9
|
||||||
|
9BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjoBbdq
|
||||||
|
fnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDv
|
||||||
|
iS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU
|
||||||
|
1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+
|
||||||
|
bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5aszPeE4uwc2hGKceeoW
|
||||||
|
MPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTA
|
||||||
|
ephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVkDBF9qn1l
|
||||||
|
uMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKIn
|
||||||
|
Z57QzxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfS
|
||||||
|
tQWVYrmm3ok9Nns4d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcF
|
||||||
|
PseKUgzbFbS9bZvlxrFUaKnjaZC2mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Un
|
||||||
|
hw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6pXE0zX5IJL4hmXXeXxx12E6nV
|
||||||
|
5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvmMw==
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
Subject: C=US, O=Symantec Corporation, OU=Symantec Trust Network, CN=Symantec Class 3 ECC 256 bit SSL CA - G2
|
||||||
|
Not Before: May 12 00:00:00 2015 GMT
|
||||||
|
Not After : May 11 23:59:59 2025 GMT
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIEajCCA1KgAwIBAgIQP5KHvp0dpKN6nfYoLndaxDANBgkqhkiG9w0BAQsFADCB
|
||||||
|
yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL
|
||||||
|
ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp
|
||||||
|
U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW
|
||||||
|
ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0
|
||||||
|
aG9yaXR5IC0gRzUwHhcNMTUwNTEyMDAwMDAwWhcNMjUwNTExMjM1OTU5WjCBgDEL
|
||||||
|
MAkGA1UEBhMCVVMxHTAbBgNVBAoTFFN5bWFudGVjIENvcnBvcmF0aW9uMR8wHQYD
|
||||||
|
VQQLExZTeW1hbnRlYyBUcnVzdCBOZXR3b3JrMTEwLwYDVQQDEyhTeW1hbnRlYyBD
|
||||||
|
bGFzcyAzIEVDQyAyNTYgYml0IFNTTCBDQSAtIEcyMFkwEwYHKoZIzj0CAQYIKoZI
|
||||||
|
zj0DAQcDQgAEDxukkdfnrOfRTk63ZFvhj39uBNOrONtEt0Bcbb2WljffeYmGZ/ex
|
||||||
|
Hwie/WM7RoyfvVPoFdyXPiuBRq2Gfw4BOaOCAV0wggFZMC4GCCsGAQUFBwEBBCIw
|
||||||
|
IDAeBggrBgEFBQcwAYYSaHR0cDovL3Muc3ltY2QuY29tMBIGA1UdEwEB/wQIMAYB
|
||||||
|
Af8CAQAwZQYDVR0gBF4wXDBaBgpghkgBhvhFAQc2MEwwIwYIKwYBBQUHAgEWF2h0
|
||||||
|
dHBzOi8vZC5zeW1jYi5jb20vY3BzMCUGCCsGAQUFBwICMBkaF2h0dHBzOi8vZC5z
|
||||||
|
eW1jYi5jb20vcnBhMC8GA1UdHwQoMCYwJKAioCCGHmh0dHA6Ly9zLnN5bWNiLmNv
|
||||||
|
bS9wY2EzLWc1LmNybDAOBgNVHQ8BAf8EBAMCAQYwKwYDVR0RBCQwIqQgMB4xHDAa
|
||||||
|
BgNVBAMTE1NZTUMtRUNDLUNBLXAyNTYtMjIwHQYDVR0OBBYEFCXwiuFLetkBlQrt
|
||||||
|
xlPxjHgf2fP4MB8GA1UdIwQYMBaAFH/TZafC3ey78DAJ80M5+gKvMzEzMA0GCSqG
|
||||||
|
SIb3DQEBCwUAA4IBAQAMMGUXBaWTdaLxsTGtcB/naqjIQrLvoV9NG+7MoHpGd/69
|
||||||
|
dZ/h2zOy7sGFUHoG/0HGRA9rxT/5w5GkEVIVkxtWyIWWq6rs4CTZt8Bej/KHYRbo
|
||||||
|
jtEDUkCTZSTLiCvguPyvinXgxy+LHT+PmdtEfXsvcdbeBSWUYpOsDYvD2hNtz9dw
|
||||||
|
Od5nBosMApmdxt+z7LQyZu8wMnfI1U6IMO+RWowxZ8uy0oswdFYd32l9xe+aAE/k
|
||||||
|
y9alLu/M9pvxiUKufqHJRgDBKA6uDjHLMPX+/nxXaNCPX3SI4KVZ1stHQ/U5oNlM
|
||||||
|
dHN9umAvlU313g0IgJrjsQ2nIdf9dsdP+6lrmP7s
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
Subject: C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, OU=(c) 2006 VeriSign, Inc. - For authorized use only, CN=VeriSign Class 3 Public Primary Certification Authority - G5
|
||||||
|
Not Before: Nov 8 00:00:00 2006 GMT
|
||||||
|
Not After : Jul 16 23:59:59 2036 GMT
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCB
|
||||||
|
yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL
|
||||||
|
ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp
|
||||||
|
U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW
|
||||||
|
ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0
|
||||||
|
aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCByjEL
|
||||||
|
MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW
|
||||||
|
ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2ln
|
||||||
|
biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp
|
||||||
|
U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y
|
||||||
|
aXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvJAgIKXo1
|
||||||
|
nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKzj/i5Vbex
|
||||||
|
t0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIz
|
||||||
|
SdhDY2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQG
|
||||||
|
BO+QueQA5N06tRn/Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+
|
||||||
|
rCpSx4/VBEnkjWNHiDxpg8v+R70rfk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/
|
||||||
|
NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E
|
||||||
|
BAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEwHzAH
|
||||||
|
BgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy
|
||||||
|
aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKv
|
||||||
|
MzEzMA0GCSqGSIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzE
|
||||||
|
p6B4Eq1iDkVwZMXnl2YtmAl+X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y
|
||||||
|
5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKEKQsTb47bDN0lAtukixlE0kF6BWlK
|
||||||
|
WE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiCKm0oHw0LxOXnGiYZ
|
||||||
|
4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vEZV8N
|
||||||
|
hnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
Subject: C=US, O=The Go Daddy Group, Inc., OU=Go Daddy Class 2 Certification Authority
|
||||||
|
Not Before: Jun 29 17:06:20 2004 GMT
|
||||||
|
Not After : Jun 29 17:06:20 2034 GMT
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEh
|
||||||
|
MB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBE
|
||||||
|
YWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3
|
||||||
|
MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRo
|
||||||
|
ZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3Mg
|
||||||
|
MiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggEN
|
||||||
|
ADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCA
|
||||||
|
PVYYYwhv2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6w
|
||||||
|
wdhFJ2+qN1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXi
|
||||||
|
EqITLdiOr18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMY
|
||||||
|
avx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+
|
||||||
|
YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0OBBYEFNLE
|
||||||
|
sNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h
|
||||||
|
/t2oatTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5
|
||||||
|
IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmlj
|
||||||
|
YXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD
|
||||||
|
ggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wimPQoZ+YeAEW5p5JYXMP80kWNy
|
||||||
|
OO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKtI3lpjbi2Tc7P
|
||||||
|
TMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ
|
||||||
|
HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mER
|
||||||
|
dEr/VxqHD3VILs9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5Cuf
|
||||||
|
ReYNnyicsbkqWletNw+vHX/bvZ8=
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
# Note: Amazon ATS endpoint uses this (2018/12/18)
|
||||||
|
Subject: C=US, O=Starfield Technologies, Inc., OU=Starfield Class 2 Certification Authority
|
||||||
|
Not Before: Jun 29 17:39:16 2004 GMT
|
||||||
|
Not After : Jun 29 17:39:16 2034 GMT
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzEl
|
||||||
|
MCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMp
|
||||||
|
U3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQw
|
||||||
|
NjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBoMQswCQYDVQQGEwJVUzElMCMGA1UE
|
||||||
|
ChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZp
|
||||||
|
ZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqGSIb3
|
||||||
|
DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf
|
||||||
|
8MOh2tTYbitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN
|
||||||
|
+lq2cwQlZut3f+dZxkqZJRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0
|
||||||
|
X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVmepsZGD3/cVE8MC5fvj13c7JdBmzDI1aa
|
||||||
|
K4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSNF4Azbl5KXZnJHoe0nRrA
|
||||||
|
1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HFMIHCMB0G
|
||||||
|
A1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fR
|
||||||
|
zt0fhvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0
|
||||||
|
YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBD
|
||||||
|
bGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8w
|
||||||
|
DQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGsafPzWdqbAYcaT1epoXkJKtv3
|
||||||
|
L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLMPUxA2IGvd56D
|
||||||
|
eruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl
|
||||||
|
xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynp
|
||||||
|
VSJYACPq4xJDKVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEY
|
||||||
|
WQPJIrSPnNVeKtelttQKbfi3QBFGmh95DmK/D5fs4C8fF5Q=
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
Not Before: Sep 1 00:00:00 2009 GMT
|
||||||
|
Not After : Dec 31 23:59:59 2037 GMT
|
||||||
|
Subject: C=US, ST=Arizona, L=Scottsdale, O=Starfield Technologies, Inc., CN=Starfield Root Certificate Authority - G2
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMx
|
||||||
|
EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT
|
||||||
|
HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVs
|
||||||
|
ZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAw
|
||||||
|
MFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6
|
||||||
|
b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQgVGVj
|
||||||
|
aG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZp
|
||||||
|
Y2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
|
||||||
|
ggEBAL3twQP89o/8ArFvW59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMg
|
||||||
|
nLRJdzIpVv257IzdIvpy3Cdhl+72WoTsbhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1
|
||||||
|
HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNkN3mSwOxGXn/hbVNMYq/N
|
||||||
|
Hwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7NfZTD4p7dN
|
||||||
|
dloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0
|
||||||
|
HZbUJtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO
|
||||||
|
BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0G
|
||||||
|
CSqGSIb3DQEBCwUAA4IBAQARWfolTwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjU
|
||||||
|
sHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx4mcujJUDJi5DnUox9g61DLu3
|
||||||
|
4jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUwF5okxBDgBPfg
|
||||||
|
8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K
|
||||||
|
pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1
|
||||||
|
mMpYjn0q7pBZc2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
Subject: C=US, ST=Arizona, L=Scottsdale, O=Starfield Technologies, Inc., CN=Starfield Services Root Certificate Authority - G2
|
||||||
|
Not Before: Sep 1 00:00:00 2009 GMT
|
||||||
|
Not After : Dec 31 23:59:59 2037 GMT
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMx
|
||||||
|
EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT
|
||||||
|
HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVs
|
||||||
|
ZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5
|
||||||
|
MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNVBAYTAlVTMRAwDgYD
|
||||||
|
VQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFy
|
||||||
|
ZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2Vy
|
||||||
|
dmljZXMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI
|
||||||
|
hvcNAQEBBQADggEPADCCAQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20p
|
||||||
|
OsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm2
|
||||||
|
8xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4PahHQUw2eeBGg6345AWh1K
|
||||||
|
Ts9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLPLJGmpufe
|
||||||
|
hRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk
|
||||||
|
6mFBrMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAw
|
||||||
|
DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+q
|
||||||
|
AdcwKziIorhtSpzyEZGDMA0GCSqGSIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMI
|
||||||
|
bw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPPE95Dz+I0swSdHynVv/heyNXB
|
||||||
|
ve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTyxQGjhdByPq1z
|
||||||
|
qwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd
|
||||||
|
iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn
|
||||||
|
0q23KXB56jzaYyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCN
|
||||||
|
sSi6
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
Subject: OU=GlobalSign Root CA - R2, O=GlobalSign, CN=GlobalSign
|
||||||
|
Not Before: Dec 15 08:00:00 2006 GMT
|
||||||
|
Not After : Dec 15 08:00:00 2021 GMT
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4G
|
||||||
|
A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNp
|
||||||
|
Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1
|
||||||
|
MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMjETMBEG
|
||||||
|
A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI
|
||||||
|
hvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6ErPL
|
||||||
|
v4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8
|
||||||
|
eoLrvozps6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklq
|
||||||
|
tTleiDTsvHgMCJiEbKjNS7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzd
|
||||||
|
C9XZzPnqJworc5HGnRusyMvo4KD0L5CLTfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pa
|
||||||
|
zq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6CygPCm48CAwEAAaOBnDCB
|
||||||
|
mTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUm+IH
|
||||||
|
V2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5n
|
||||||
|
bG9iYWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG
|
||||||
|
3lm0mi3f3BmGLjANBgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4Gs
|
||||||
|
J0/WwbgcQ3izDJr86iw8bmEbTUsp9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO
|
||||||
|
291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu01yiPqFbQfXf5WRDLenVOavS
|
||||||
|
ot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG79G+dwfCMNYxd
|
||||||
|
AfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7
|
||||||
|
TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg==
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
Subject: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert High Assurance EV Root CA
|
||||||
|
Not Before: Nov 10 00:00:00 2006 GMT
|
||||||
|
Not After : Nov 10 00:00:00 2031 GMT
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs
|
||||||
|
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
|
||||||
|
d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
|
||||||
|
ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL
|
||||||
|
MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
|
||||||
|
LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug
|
||||||
|
RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm
|
||||||
|
+9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW
|
||||||
|
PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM
|
||||||
|
xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB
|
||||||
|
Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3
|
||||||
|
hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg
|
||||||
|
EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF
|
||||||
|
MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA
|
||||||
|
FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec
|
||||||
|
nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z
|
||||||
|
eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF
|
||||||
|
hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2
|
||||||
|
Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe
|
||||||
|
vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep
|
||||||
|
+OkuE6N36B9K
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
Subject: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Global Root CA
|
||||||
|
Not Before: Nov 10 00:00:00 2006 GMT
|
||||||
|
Not After : Nov 10 00:00:00 2031 GMT
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh
|
||||||
|
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
|
||||||
|
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
|
||||||
|
QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT
|
||||||
|
MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
|
||||||
|
b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG
|
||||||
|
9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB
|
||||||
|
CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97
|
||||||
|
nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt
|
||||||
|
43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P
|
||||||
|
T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4
|
||||||
|
gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO
|
||||||
|
BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR
|
||||||
|
TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw
|
||||||
|
DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr
|
||||||
|
hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg
|
||||||
|
06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF
|
||||||
|
PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls
|
||||||
|
YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
|
||||||
|
CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
# *.azure-devices.de use this root.
|
||||||
|
Subject: C = DE, O = D-Trust GmbH, CN = D-TRUST Root Class 3 CA 2 2009
|
||||||
|
Not Before: Nov 5 08:35:58 2009 GMT
|
||||||
|
Not After : Nov 5 08:35:58 2029 GMT
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIEMzCCAxugAwIBAgIDCYPzMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNVBAYTAkRF
|
||||||
|
MRUwEwYDVQQKDAxELVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBD
|
||||||
|
bGFzcyAzIENBIDIgMjAwOTAeFw0wOTExMDUwODM1NThaFw0yOTExMDUwODM1NTha
|
||||||
|
ME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxELVRydXN0IEdtYkgxJzAlBgNVBAMM
|
||||||
|
HkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTCCASIwDQYJKoZIhvcNAQEB
|
||||||
|
BQADggEPADCCAQoCggEBANOySs96R+91myP6Oi/WUEWJNTrGa9v+2wBoqOADER03
|
||||||
|
UAifTUpolDWzU9GUY6cgVq/eUXjsKj3zSEhQPgrfRlWLJ23DEE0NkVJD2IfgXU42
|
||||||
|
tSHKXzlABF9bfsyjxiupQB7ZNoTWSPOSHjRGICTBpFGOShrvUD9pXRl/RcPHAY9R
|
||||||
|
ySPocq60vFYJfxLLHLGvKZAKyVXMD9O0Gu1HNVpK7ZxzBCHQqr0ME7UAyiZsxGsM
|
||||||
|
lFqVlNpQmvH/pStmMaTJOKDfHR+4CS7zp+hnUquVH+BGPtikw8paxTGA6Eian5Rp
|
||||||
|
/hnd2HN8gcqW3o7tszIFZYQ05ub9VxC1X3a/L7AQDcUCAwEAAaOCARowggEWMA8G
|
||||||
|
A1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFP3aFMSfMN4hvR5COfyrYyNJ4PGEMA4G
|
||||||
|
A1UdDwEB/wQEAwIBBjCB0wYDVR0fBIHLMIHIMIGAoH6gfIZ6bGRhcDovL2RpcmVj
|
||||||
|
dG9yeS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwUm9vdCUyMENsYXNzJTIwMyUy
|
||||||
|
MENBJTIwMiUyMDIwMDksTz1ELVRydXN0JTIwR21iSCxDPURFP2NlcnRpZmljYXRl
|
||||||
|
cmV2b2NhdGlvbmxpc3QwQ6BBoD+GPWh0dHA6Ly93d3cuZC10cnVzdC5uZXQvY3Js
|
||||||
|
L2QtdHJ1c3Rfcm9vdF9jbGFzc18zX2NhXzJfMjAwOS5jcmwwDQYJKoZIhvcNAQEL
|
||||||
|
BQADggEBAH+X2zDI36ScfSF6gHDOFBJpiBSVYEQBrLLpME+bUMJm2H6NMLVwMeni
|
||||||
|
acfzcNsgFYbQDfC+rAF1hM5+n02/t2A7nPPKHeJeaNijnZflQGDSNiH+0LS4F9p0
|
||||||
|
o3/U37CYAqxva2ssJSRyoWXuJVrl5jLn8t+rSfrzkGkj2wTZ51xY/GXUl77M/C4K
|
||||||
|
zCUqNQT4YJEVdT1B/yMfGchs64JTBKbkTCJNjYy6zltz7GRUUG3RnFX7acM2w4y8
|
||||||
|
PIWmawomDeCTmGCufsYkl4phX5GOZpIJhzbNi5stPvZR1FDUWSi9g/LMKHtThm3Y
|
||||||
|
Johw1+qRzT65ysCQblrGXnRl11z+o+I=
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
# https://www.amazontrust.com/repository/
|
||||||
|
Subject: C = US, O = Amazon, CN = Amazon Root CA 1
|
||||||
|
Not Before: May 26 00:00:00 2015 GMT
|
||||||
|
Not After : Jan 17 00:00:00 2038 GMT
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF
|
||||||
|
ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6
|
||||||
|
b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL
|
||||||
|
MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv
|
||||||
|
b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj
|
||||||
|
ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM
|
||||||
|
9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw
|
||||||
|
IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6
|
||||||
|
VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L
|
||||||
|
93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm
|
||||||
|
jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
|
||||||
|
AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA
|
||||||
|
A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI
|
||||||
|
U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs
|
||||||
|
N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv
|
||||||
|
o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU
|
||||||
|
5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy
|
||||||
|
rqXRfboQnoZsG4q5WTP468SQvvG5
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
Subject: C = US, O = Amazon, CN = Amazon Root CA 2
|
||||||
|
Not Before: May 26 00:00:00 2015 GMT
|
||||||
|
Not After : May 26 00:00:00 2040 GMT
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIFQTCCAymgAwIBAgITBmyf0pY1hp8KD+WGePhbJruKNzANBgkqhkiG9w0BAQwF
|
||||||
|
ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6
|
||||||
|
b24gUm9vdCBDQSAyMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTEL
|
||||||
|
MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv
|
||||||
|
b3QgQ0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK2Wny2cSkxK
|
||||||
|
gXlRmeyKy2tgURO8TW0G/LAIjd0ZEGrHJgw12MBvIITplLGbhQPDW9tK6Mj4kHbZ
|
||||||
|
W0/jTOgGNk3Mmqw9DJArktQGGWCsN0R5hYGCrVo34A3MnaZMUnbqQ523BNFQ9lXg
|
||||||
|
1dKmSYXpN+nKfq5clU1Imj+uIFptiJXZNLhSGkOQsL9sBbm2eLfq0OQ6PBJTYv9K
|
||||||
|
8nu+NQWpEjTj82R0Yiw9AElaKP4yRLuH3WUnAnE72kr3H9rN9yFVkE8P7K6C4Z9r
|
||||||
|
2UXTu/Bfh+08LDmG2j/e7HJV63mjrdvdfLC6HM783k81ds8P+HgfajZRRidhW+me
|
||||||
|
z/CiVX18JYpvL7TFz4QuK/0NURBs+18bvBt+xa47mAExkv8LV/SasrlX6avvDXbR
|
||||||
|
8O70zoan4G7ptGmh32n2M8ZpLpcTnqWHsFcQgTfJU7O7f/aS0ZzQGPSSbtqDT6Zj
|
||||||
|
mUyl+17vIWR6IF9sZIUVyzfpYgwLKhbcAS4y2j5L9Z469hdAlO+ekQiG+r5jqFoz
|
||||||
|
7Mt0Q5X5bGlSNscpb/xVA1wf+5+9R+vnSUeVC06JIglJ4PVhHvG/LopyboBZ/1c6
|
||||||
|
+XUyo05f7O0oYtlNc/LMgRdg7c3r3NunysV+Ar3yVAhU/bQtCSwXVEqY0VThUWcI
|
||||||
|
0u1ufm8/0i2BWSlmy5A5lREedCf+3euvAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMB
|
||||||
|
Af8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSwDPBMMPQFWAJI/TPlUq9LhONm
|
||||||
|
UjANBgkqhkiG9w0BAQwFAAOCAgEAqqiAjw54o+Ci1M3m9Zh6O+oAA7CXDpO8Wqj2
|
||||||
|
LIxyh6mx/H9z/WNxeKWHWc8w4Q0QshNabYL1auaAn6AFC2jkR2vHat+2/XcycuUY
|
||||||
|
+gn0oJMsXdKMdYV2ZZAMA3m3MSNjrXiDCYZohMr/+c8mmpJ5581LxedhpxfL86kS
|
||||||
|
k5Nrp+gvU5LEYFiwzAJRGFuFjWJZY7attN6a+yb3ACfAXVU3dJnJUH/jWS5E4ywl
|
||||||
|
7uxMMne0nxrpS10gxdr9HIcWxkPo1LsmmkVwXqkLN1PiRnsn/eBG8om3zEK2yygm
|
||||||
|
btmlyTrIQRNg91CMFa6ybRoVGld45pIq2WWQgj9sAq+uEjonljYE1x2igGOpm/Hl
|
||||||
|
urR8FLBOybEfdF849lHqm/osohHUqS0nGkWxr7JOcQ3AWEbWaQbLU8uz/mtBzUF+
|
||||||
|
fUwPfHJ5elnNXkoOrJupmHN5fLT0zLm4BwyydFy4x2+IoZCn9Kr5v2c69BoVYh63
|
||||||
|
n749sSmvZ6ES8lgQGVMDMBu4Gon2nL2XA46jCfMdiyHxtN/kHNGfZQIG6lzWE7OE
|
||||||
|
76KlXIx3KadowGuuQNKotOrN8I1LOJwZmhsoVLiJkO/KdYE+HvJkJMcYr07/R54H
|
||||||
|
9jVlpNMKVv/1F2Rs76giJUmTtt8AF9pYfl3uxRuw0dFfIRDH+fO6AgonB8Xx1sfT
|
||||||
|
4PsJYGw=
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
Not Before: May 26 00:00:00 2015 GMT
|
||||||
|
Not After : May 26 00:00:00 2040 GMT
|
||||||
|
Subject: C = US, O = Amazon, CN = Amazon Root CA 3
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5
|
||||||
|
MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g
|
||||||
|
Um9vdCBDQSAzMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG
|
||||||
|
A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg
|
||||||
|
Q0EgMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCmXp8ZBf8ANm+gBG1bG8lKl
|
||||||
|
ui2yEujSLtf6ycXYqm0fc4E7O5hrOXwzpcVOho6AF2hiRVd9RFgdszflZwjrZt6j
|
||||||
|
QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSr
|
||||||
|
ttvXBp43rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkr
|
||||||
|
BqWTrBqYaGFy+uGh0PsceGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteM
|
||||||
|
YyRIHN8wfdVoOw==
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
Not Before: May 26 00:00:00 2015 GMT
|
||||||
|
Not After : May 26 00:00:00 2040 GMT
|
||||||
|
Subject: C = US, O = Amazon, CN = Amazon Root CA 4
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIB8jCCAXigAwIBAgITBmyf18G7EEwpQ+Vxe3ssyBrBDjAKBggqhkjOPQQDAzA5
|
||||||
|
MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g
|
||||||
|
Um9vdCBDQSA0MB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG
|
||||||
|
A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg
|
||||||
|
Q0EgNDB2MBAGByqGSM49AgEGBSuBBAAiA2IABNKrijdPo1MN/sGKe0uoe0ZLY7Bi
|
||||||
|
9i0b2whxIdIA6GO9mif78DluXeo9pcmBqqNbIJhFXRbb/egQbeOc4OO9X4Ri83Bk
|
||||||
|
M6DLJC9wuoihKqB1+IGuYgbEgds5bimwHvouXKNCMEAwDwYDVR0TAQH/BAUwAwEB
|
||||||
|
/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFNPsxzplbszh2naaVvuc84ZtV+WB
|
||||||
|
MAoGCCqGSM49BAMDA2gAMGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlw
|
||||||
|
CkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1AE47xDqUEpHJWEadIRNyp4iciuRMStuW
|
||||||
|
1KyLa2tJElMzrdfkviT8tQp21KW8EA==
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
Not Before: Nov 10 00:00:00 2006 GMT
|
||||||
|
Not After : Nov 10 00:00:00 2031 GMT
|
||||||
|
Subject: C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert Global Root CA
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh
|
||||||
|
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
|
||||||
|
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
|
||||||
|
QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT
|
||||||
|
MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
|
||||||
|
b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG
|
||||||
|
9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB
|
||||||
|
CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97
|
||||||
|
nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt
|
||||||
|
43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P
|
||||||
|
T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4
|
||||||
|
gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO
|
||||||
|
BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR
|
||||||
|
TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw
|
||||||
|
DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr
|
||||||
|
hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg
|
||||||
|
06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF
|
||||||
|
PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls
|
||||||
|
YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
|
||||||
|
CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
Not Before: Nov 13 00:00:00 2012 GMT
|
||||||
|
Not After : Jan 19 03:14:07 2038 GMT
|
||||||
|
Subject: OU = GlobalSign ECC Root CA - R4, O = GlobalSign, CN = GlobalSign
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIB4TCCAYegAwIBAgIRKjikHJYKBN5CsiilC+g0mAIwCgYIKoZIzj0EAwIwUDEk
|
||||||
|
MCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpH
|
||||||
|
bG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoX
|
||||||
|
DTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBD
|
||||||
|
QSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu
|
||||||
|
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuMZ5049sJQ6fLjkZHAOkrprlOQcJ
|
||||||
|
FspjsbmG+IpXwVfOQvpzofdlQv8ewQCybnMO/8ch5RikqtlxP6jUuc6MHaNCMEAw
|
||||||
|
DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFFSwe61F
|
||||||
|
uOJAf/sKbvu+M8k8o4TVMAoGCCqGSM49BAMCA0gAMEUCIQDckqGgE6bPA7DmxCGX
|
||||||
|
kPoUVy0D7O48027KqGx2vKLeuwIgJ6iFJzWbVsaj8kfSt24bAgAXqmemFZHe+pTs
|
||||||
|
ewv4n4Q=
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
Not Before: Nov 1 00:00:42 2018 GMT
|
||||||
|
Not After : Nov 1 00:00:42 2042 GMT
|
||||||
|
Subject: C = US, O = Google Trust Services LLC, CN = GTS LTSR
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIBxTCCAWugAwIBAgINAfD3nVndblD3QnNxUDAKBggqhkjOPQQDAjBEMQswCQYD
|
||||||
|
VQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzERMA8G
|
||||||
|
A1UEAxMIR1RTIExUU1IwHhcNMTgxMTAxMDAwMDQyWhcNNDIxMTAxMDAwMDQyWjBE
|
||||||
|
MQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExM
|
||||||
|
QzERMA8GA1UEAxMIR1RTIExUU1IwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATN
|
||||||
|
8YyO2u+yCQoZdwAkUNv5c3dokfULfrA6QJgFV2XMuENtQZIG5HUOS6jFn8f0ySlV
|
||||||
|
eORCxqFyjDJyRn86d+Iko0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUw
|
||||||
|
AwEB/zAdBgNVHQ4EFgQUPv7/zFLrvzQ+PfNA0OQlsV+4u1IwCgYIKoZIzj0EAwID
|
||||||
|
SAAwRQIhAPKuf/VtBHqGw3TUwUIq7TfaExp3bH7bjCBmVXJupT9FAiBr0SmCtsuk
|
||||||
|
miGgpajjf/gFigGM34F9021bCWs1MbL0SA==
|
||||||
|
-----END CERTIFICATE-----
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
// Copyright (c) 2020 Cesanta Software Limited
|
||||||
|
// All rights reserved
|
||||||
|
//
|
||||||
|
// Example HTTP client that uses a proxy server. Usage:
|
||||||
|
// make
|
||||||
|
// ./example PROXY:PORT http://www.ladyada.net
|
||||||
|
//
|
||||||
|
// To enable SSL/TLS for this client, build it like this:
|
||||||
|
// make MBEDTLS_DIR=/path/to/your/mbedtls/installation
|
||||||
|
|
||||||
|
#include "mongoose.h"
|
||||||
|
|
||||||
|
// Print HTTP response and signal that we're done
|
||||||
|
static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
|
||||||
|
const char *url = fn_data;
|
||||||
|
static bool connected;
|
||||||
|
if (ev == MG_EV_HTTP_MSG) {
|
||||||
|
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||||
|
printf("%.*s", (int) hm->message.len, hm->message.ptr);
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
} else if (ev == MG_EV_CONNECT) {
|
||||||
|
// Proxy TCP connection established. Send CONNECT request
|
||||||
|
struct mg_str host = mg_url_host(url);
|
||||||
|
// c->is_hexdumping = 1;
|
||||||
|
mg_printf(c, "CONNECT %.*s:%hu HTTP/1.1\r\nHost: %.*s:%hu\r\n\r\n",
|
||||||
|
(int) host.len, host.ptr, mg_url_port(url), (int) host.len,
|
||||||
|
host.ptr, mg_url_port(url));
|
||||||
|
// If target URL is SSL/TLS, command client connection to use TLS
|
||||||
|
if (mg_url_is_ssl(url)) {
|
||||||
|
struct mg_tls_opts opts = {.ca = "ca.pem"};
|
||||||
|
mg_tls_init(c, &opts);
|
||||||
|
}
|
||||||
|
} else if (!connected && ev == MG_EV_READ) {
|
||||||
|
struct mg_http_message hm;
|
||||||
|
int n = mg_http_parse((char *) c->recv.buf, c->recv.len, &hm);
|
||||||
|
if (n > 0) {
|
||||||
|
struct mg_str host = mg_url_host(url);
|
||||||
|
// CONNECT response - tunnel is established
|
||||||
|
connected = true;
|
||||||
|
LOG(LL_DEBUG,
|
||||||
|
("Connected to proxy, status: %.*s", (int) hm.uri.len, hm.uri.ptr));
|
||||||
|
mg_iobuf_delete(&c->recv, n);
|
||||||
|
// Send request to the target server
|
||||||
|
mg_printf(c, "GET / HTTP/1.0\r\nHost: %.*s\r\n\r\n", (int) host.len,
|
||||||
|
host.ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
struct mg_mgr mgr;
|
||||||
|
|
||||||
|
if (argc != 3) {
|
||||||
|
fprintf(stderr, "Usage: %s PROXY_URL URL\n", argv[0]);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
mg_mgr_init(&mgr); // Initialise event manager
|
||||||
|
mg_http_connect(&mgr, argv[1], fn, argv[2]); // Connect to the proxy
|
||||||
|
for (;;) mg_mgr_poll(&mgr, 1000); // Event loop
|
||||||
|
mg_mgr_free(&mgr);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
PROG ?= example
|
||||||
|
|
||||||
|
ifeq "$(MBEDTLS_DIR)" ""
|
||||||
|
else
|
||||||
|
CFLAGS += -DMG_ENABLE_MBEDTLS=1 -I$(MBEDTLS_DIR)/include -I/usr/include
|
||||||
|
CFLAGS += -L$(MBEDTLS_DIR)/lib -lmbedtls -lmbedcrypto -lmbedx509
|
||||||
|
endif
|
||||||
|
|
||||||
|
all: $(PROG)
|
||||||
|
$(DEBUGGER) ./$(PROG) $(ARGS)
|
||||||
|
|
||||||
|
$(PROG): main.c
|
||||||
|
$(CC) ../../mongoose.c -I../.. -W -Wall -DMG_ENABLE_LINES=1 -DMG_ENABLE_DIRECTORY_LISTING=1 $(CFLAGS) -o $(PROG) main.c
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf $(PROG) *.o *.dSYM *.gcov *.gcno *.gcda *.obj *.exe *.ilk *.pdb
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
Certificate:
|
||||||
|
Data:
|
||||||
|
Version: 3 (0x2)
|
||||||
|
Serial Number:
|
||||||
|
11:2a:0e:3c:6a:8c:85:ff:6e:6a:bc:db:95:51:70:ce:b4:30:78:c7
|
||||||
|
Signature Algorithm: ecdsa-with-SHA256
|
||||||
|
Issuer: C = IE, L = Dublin, O = Cesanta, CN = Test Root
|
||||||
|
Validity
|
||||||
|
Not Before: May 9 21:51:44 2020 GMT
|
||||||
|
Not After : May 9 21:51:44 2050 GMT
|
||||||
|
Subject: C = IE, L = Dublin, O = Cesanta, CN = Test Root
|
||||||
|
Subject Public Key Info:
|
||||||
|
Public Key Algorithm: id-ecPublicKey
|
||||||
|
Public-Key: (256 bit)
|
||||||
|
pub:
|
||||||
|
04:2c:ab:d1:02:66:24:96:d7:12:3e:09:50:4f:f1:
|
||||||
|
50:ee:51:e8:55:03:5e:ba:b1:1d:98:b2:72:79:27:
|
||||||
|
a8:1b:31:0d:5d:50:21:ff:42:f2:da:74:17:5e:53:
|
||||||
|
b2:65:41:c1:fc:84:de:4a:11:b9:8c:f4:19:d9:c4:
|
||||||
|
ca:2b:ea:eb:2c
|
||||||
|
ASN1 OID: prime256v1
|
||||||
|
NIST CURVE: P-256
|
||||||
|
X509v3 extensions:
|
||||||
|
X509v3 Basic Constraints:
|
||||||
|
CA:TRUE
|
||||||
|
X509v3 Key Usage:
|
||||||
|
Digital Signature, Key Encipherment, Key Agreement, Certificate Sign, CRL Sign
|
||||||
|
Signature Algorithm: ecdsa-with-SHA256
|
||||||
|
30:46:02:21:00:9c:71:6c:00:8c:06:41:0c:91:2f:cd:41:d3:
|
||||||
|
87:47:e9:df:3a:22:ad:25:7c:bf:0e:2b:39:dd:7a:0c:4e:68:
|
||||||
|
1d:02:21:00:8f:c1:22:30:10:61:5d:51:10:ea:08:2d:02:63:
|
||||||
|
67:67:32:b5:06:63:96:57:bb:78:47:0a:88:d9:19:2e:f3:be
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIBqjCCAU+gAwIBAgIUESoOPGqMhf9uarzblVFwzrQweMcwCgYIKoZIzj0EAwIw
|
||||||
|
RDELMAkGA1UEBhMCSUUxDzANBgNVBAcMBkR1YmxpbjEQMA4GA1UECgwHQ2VzYW50
|
||||||
|
YTESMBAGA1UEAwwJVGVzdCBSb290MCAXDTIwMDUwOTIxNTE0NFoYDzIwNTAwNTA5
|
||||||
|
MjE1MTQ0WjBEMQswCQYDVQQGEwJJRTEPMA0GA1UEBwwGRHVibGluMRAwDgYDVQQK
|
||||||
|
DAdDZXNhbnRhMRIwEAYDVQQDDAlUZXN0IFJvb3QwWTATBgcqhkjOPQIBBggqhkjO
|
||||||
|
PQMBBwNCAAQsq9ECZiSW1xI+CVBP8VDuUehVA166sR2YsnJ5J6gbMQ1dUCH/QvLa
|
||||||
|
dBdeU7JlQcH8hN5KEbmM9BnZxMor6ussox0wGzAMBgNVHRMEBTADAQH/MAsGA1Ud
|
||||||
|
DwQEAwIBrjAKBggqhkjOPQQDAgNJADBGAiEAnHFsAIwGQQyRL81B04dH6d86Iq0l
|
||||||
|
fL8OKzndegxOaB0CIQCPwSIwEGFdURDqCC0CY2dnMrUGY5ZXu3hHCojZGS7zvg==
|
||||||
|
-----END CERTIFICATE-----
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
// Copyright (c) 2020 Cesanta Software Limited
|
||||||
|
// All rights reserved
|
||||||
|
//
|
||||||
|
// HTTP server example. This server serves both static and dynamic content.
|
||||||
|
// It implements the following endpoints:
|
||||||
|
// /api/f1 - respond with JSON string {"result": 123}
|
||||||
|
// /api/f2/:id - wildcard example, respond with JSON string {"result": "URI"}
|
||||||
|
// any other URI serves static files from s_web_directory
|
||||||
|
//
|
||||||
|
// To enable SSL/TLS (using self-signed certificates in PEM files),
|
||||||
|
// 1. Change s_listen_on from http:// to https://
|
||||||
|
// 2. make MBEDTLS_DIR=/path/to/your/mbedtls/installation
|
||||||
|
// 3. curl -k https://127.0.0.1:8000
|
||||||
|
|
||||||
|
#include "mongoose.h"
|
||||||
|
|
||||||
|
static const char *s_listen_on = "https://localhost:8000";
|
||||||
|
static const char *s_web_directory = ".";
|
||||||
|
|
||||||
|
static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
|
||||||
|
if (ev == MG_EV_ACCEPT && mg_url_is_ssl(s_listen_on)) {
|
||||||
|
// If s_listen_on URL is https://, tell listening connection to use TLS
|
||||||
|
struct mg_tls_opts opts = {
|
||||||
|
//.ca = "ca.pem", // Uncomment to enable two-way SSL
|
||||||
|
.cert = "server.pem", // Certificate PEM file
|
||||||
|
.certkey = "server.pem", // This pem conains both cert and key
|
||||||
|
};
|
||||||
|
mg_tls_init(c, &opts);
|
||||||
|
} else if (ev == MG_EV_HTTP_MSG) {
|
||||||
|
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||||
|
if (mg_http_match_uri(hm, "/api/f1")) {
|
||||||
|
mg_http_reply(c, 200, "", "{\"result\": %d}\n", 123); // Serve REST
|
||||||
|
} else if (mg_http_match_uri(hm, "/api/f2/*")) {
|
||||||
|
mg_http_reply(c, 200, "", "{\"result\": \"%.*s\"}\n", (int) hm->uri.len,
|
||||||
|
hm->uri.ptr);
|
||||||
|
} else {
|
||||||
|
struct mg_http_serve_opts opts = {.root_dir = s_web_directory};
|
||||||
|
mg_http_serve_dir(c, ev_data, &opts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(void) fn_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
struct mg_mgr mgr; // Event manager
|
||||||
|
mg_log_set("2"); // Set to 3 to enable debug
|
||||||
|
mg_mgr_init(&mgr); // Initialise event manager
|
||||||
|
mg_http_listen(&mgr, s_listen_on, fn, NULL); // Create HTTP listener
|
||||||
|
for (;;) mg_mgr_poll(&mgr, 1000); // Infinite event loop
|
||||||
|
mg_mgr_free(&mgr);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
Certificate:
|
||||||
|
Data:
|
||||||
|
Version: 3 (0x2)
|
||||||
|
Serial Number:
|
||||||
|
6e:73:28:55:df:13:b5:61:f5:4f:4f:5d:00:d9:0a:d8:b5:3a:21:4b
|
||||||
|
Signature Algorithm: ecdsa-with-SHA256
|
||||||
|
Issuer: C = IE, L = Dublin, O = Cesanta, CN = Test Root
|
||||||
|
Validity
|
||||||
|
Not Before: May 9 21:51:49 2020 GMT
|
||||||
|
Not After : May 9 21:51:49 2030 GMT
|
||||||
|
Subject: CN = server
|
||||||
|
Subject Public Key Info:
|
||||||
|
Public Key Algorithm: id-ecPublicKey
|
||||||
|
Public-Key: (256 bit)
|
||||||
|
pub:
|
||||||
|
04:92:e0:46:9c:89:c3:37:a9:74:eb:35:55:43:55:
|
||||||
|
5c:ac:eb:c7:e4:50:ee:f4:c0:ba:17:02:5c:d9:ed:
|
||||||
|
b4:d4:ff:21:12:9a:b4:43:f4:89:4b:69:e4:6d:2b:
|
||||||
|
96:1f:fc:01:4d:30:5a:79:73:76:ba:19:41:cc:c5:
|
||||||
|
16:2b:bf:74:28
|
||||||
|
ASN1 OID: prime256v1
|
||||||
|
NIST CURVE: P-256
|
||||||
|
X509v3 extensions:
|
||||||
|
X509v3 Basic Constraints:
|
||||||
|
CA:FALSE
|
||||||
|
X509v3 Key Usage:
|
||||||
|
Digital Signature, Key Encipherment, Key Agreement
|
||||||
|
X509v3 Extended Key Usage:
|
||||||
|
TLS Web Server Authentication
|
||||||
|
Signature Algorithm: ecdsa-with-SHA256
|
||||||
|
30:46:02:21:00:fa:3a:c7:1e:cb:8c:27:59:41:8d:77:dd:7b:
|
||||||
|
cb:8c:08:15:16:b9:6e:70:e6:47:38:d1:55:42:e0:d7:66:c8:
|
||||||
|
f0:02:21:00:cc:70:4d:96:28:00:d3:c7:39:53:74:b2:49:87:
|
||||||
|
27:92:1b:ab:1a:0e:74:06:59:42:23:47:98:43:d8:20:a7:fa
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIBhzCCASygAwIBAgIUbnMoVd8TtWH1T09dANkK2LU6IUswCgYIKoZIzj0EAwIw
|
||||||
|
RDELMAkGA1UEBhMCSUUxDzANBgNVBAcMBkR1YmxpbjEQMA4GA1UECgwHQ2VzYW50
|
||||||
|
YTESMBAGA1UEAwwJVGVzdCBSb290MB4XDTIwMDUwOTIxNTE0OVoXDTMwMDUwOTIx
|
||||||
|
NTE0OVowETEPMA0GA1UEAwwGc2VydmVyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcD
|
||||||
|
QgAEkuBGnInDN6l06zVVQ1VcrOvH5FDu9MC6FwJc2e201P8hEpq0Q/SJS2nkbSuW
|
||||||
|
H/wBTTBaeXN2uhlBzMUWK790KKMvMC0wCQYDVR0TBAIwADALBgNVHQ8EBAMCA6gw
|
||||||
|
EwYDVR0lBAwwCgYIKwYBBQUHAwEwCgYIKoZIzj0EAwIDSQAwRgIhAPo6xx7LjCdZ
|
||||||
|
QY133XvLjAgVFrlucOZHONFVQuDXZsjwAiEAzHBNligA08c5U3SySYcnkhurGg50
|
||||||
|
BllCI0eYQ9ggp/o=
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
-----BEGIN PRIVATE KEY-----
|
||||||
|
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQglNni0t9Dg9icgG8w
|
||||||
|
kbfxWSS+TuNgbtNybIQXcm3NHpmhRANCAASS4EacicM3qXTrNVVDVVys68fkUO70
|
||||||
|
wLoXAlzZ7bTU/yESmrRD9IlLaeRtK5Yf/AFNMFp5c3a6GUHMxRYrv3Qo
|
||||||
|
-----END PRIVATE KEY-----
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
PROG ?= example
|
||||||
|
CFLAGS ?= -DMG_IO_SIZE=8192
|
||||||
|
MBEDTLS_DIR ?=
|
||||||
|
|
||||||
|
ifeq "$(MBEDTLS_DIR)" ""
|
||||||
|
else
|
||||||
|
CFLAGS += -DMG_ENABLE_MBEDTLS=1 -I$(MBEDTLS_DIR)/include -I/usr/include
|
||||||
|
CFLAGS += -L$(MBEDTLS_DIR)/lib -lmbedtls -lmbedcrypto -lmbedx509
|
||||||
|
endif
|
||||||
|
|
||||||
|
all: $(PROG)
|
||||||
|
$(DEBUGGER) ./$(PROG) $(ARGS)
|
||||||
|
|
||||||
|
|
||||||
|
$(PROG): main.c
|
||||||
|
$(CC) ../../mongoose.c -I../.. -W -Wall $(CFLAGS) -o $(PROG) main.c
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf $(PROG) *.o *.dSYM *.gcov *.gcno *.gcda *.obj *.exe *.ilk *.pdb
|
||||||
@@ -0,0 +1,507 @@
|
|||||||
|
Subject: O=Digital Signature Trust Co., CN=DST Root CA X3
|
||||||
|
Not Before: Sep 30 21:12:19 2000 GMT
|
||||||
|
Not After : Sep 30 14:01:15 2021 GMT
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/
|
||||||
|
MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
|
||||||
|
DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow
|
||||||
|
PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD
|
||||||
|
Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
|
||||||
|
AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O
|
||||||
|
rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq
|
||||||
|
OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b
|
||||||
|
xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw
|
||||||
|
7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD
|
||||||
|
aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV
|
||||||
|
HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG
|
||||||
|
SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69
|
||||||
|
ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr
|
||||||
|
AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz
|
||||||
|
R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5
|
||||||
|
JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo
|
||||||
|
Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
Subject: C=IE, O=Baltimore, OU=CyberTrust, CN=Baltimore CyberTrust Root
|
||||||
|
Not Before: May 12 18:46:00 2000 GMT
|
||||||
|
Not After : May 12 23:59:00 2025 GMT
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ
|
||||||
|
RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD
|
||||||
|
VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX
|
||||||
|
DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y
|
||||||
|
ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy
|
||||||
|
VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr
|
||||||
|
mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr
|
||||||
|
IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK
|
||||||
|
mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu
|
||||||
|
XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy
|
||||||
|
dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye
|
||||||
|
jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1
|
||||||
|
BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3
|
||||||
|
DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92
|
||||||
|
9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx
|
||||||
|
jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0
|
||||||
|
Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz
|
||||||
|
ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS
|
||||||
|
R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
Subject: C=US, O=GeoTrust Inc., CN=GeoTrust Global CA
|
||||||
|
Not Before: May 21 04:00:00 2002 GMT
|
||||||
|
Not After : May 21 04:00:00 2022 GMT
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT
|
||||||
|
MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i
|
||||||
|
YWwgQ0EwHhcNMDIwNTIxMDQwMDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQG
|
||||||
|
EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMSR2VvVHJ1c3Qg
|
||||||
|
R2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2swYYzD9
|
||||||
|
9BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjoBbdq
|
||||||
|
fnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDv
|
||||||
|
iS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU
|
||||||
|
1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+
|
||||||
|
bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5aszPeE4uwc2hGKceeoW
|
||||||
|
MPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTA
|
||||||
|
ephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVkDBF9qn1l
|
||||||
|
uMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKIn
|
||||||
|
Z57QzxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfS
|
||||||
|
tQWVYrmm3ok9Nns4d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcF
|
||||||
|
PseKUgzbFbS9bZvlxrFUaKnjaZC2mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Un
|
||||||
|
hw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6pXE0zX5IJL4hmXXeXxx12E6nV
|
||||||
|
5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvmMw==
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
Subject: C=US, O=Symantec Corporation, OU=Symantec Trust Network, CN=Symantec Class 3 ECC 256 bit SSL CA - G2
|
||||||
|
Not Before: May 12 00:00:00 2015 GMT
|
||||||
|
Not After : May 11 23:59:59 2025 GMT
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIEajCCA1KgAwIBAgIQP5KHvp0dpKN6nfYoLndaxDANBgkqhkiG9w0BAQsFADCB
|
||||||
|
yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL
|
||||||
|
ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp
|
||||||
|
U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW
|
||||||
|
ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0
|
||||||
|
aG9yaXR5IC0gRzUwHhcNMTUwNTEyMDAwMDAwWhcNMjUwNTExMjM1OTU5WjCBgDEL
|
||||||
|
MAkGA1UEBhMCVVMxHTAbBgNVBAoTFFN5bWFudGVjIENvcnBvcmF0aW9uMR8wHQYD
|
||||||
|
VQQLExZTeW1hbnRlYyBUcnVzdCBOZXR3b3JrMTEwLwYDVQQDEyhTeW1hbnRlYyBD
|
||||||
|
bGFzcyAzIEVDQyAyNTYgYml0IFNTTCBDQSAtIEcyMFkwEwYHKoZIzj0CAQYIKoZI
|
||||||
|
zj0DAQcDQgAEDxukkdfnrOfRTk63ZFvhj39uBNOrONtEt0Bcbb2WljffeYmGZ/ex
|
||||||
|
Hwie/WM7RoyfvVPoFdyXPiuBRq2Gfw4BOaOCAV0wggFZMC4GCCsGAQUFBwEBBCIw
|
||||||
|
IDAeBggrBgEFBQcwAYYSaHR0cDovL3Muc3ltY2QuY29tMBIGA1UdEwEB/wQIMAYB
|
||||||
|
Af8CAQAwZQYDVR0gBF4wXDBaBgpghkgBhvhFAQc2MEwwIwYIKwYBBQUHAgEWF2h0
|
||||||
|
dHBzOi8vZC5zeW1jYi5jb20vY3BzMCUGCCsGAQUFBwICMBkaF2h0dHBzOi8vZC5z
|
||||||
|
eW1jYi5jb20vcnBhMC8GA1UdHwQoMCYwJKAioCCGHmh0dHA6Ly9zLnN5bWNiLmNv
|
||||||
|
bS9wY2EzLWc1LmNybDAOBgNVHQ8BAf8EBAMCAQYwKwYDVR0RBCQwIqQgMB4xHDAa
|
||||||
|
BgNVBAMTE1NZTUMtRUNDLUNBLXAyNTYtMjIwHQYDVR0OBBYEFCXwiuFLetkBlQrt
|
||||||
|
xlPxjHgf2fP4MB8GA1UdIwQYMBaAFH/TZafC3ey78DAJ80M5+gKvMzEzMA0GCSqG
|
||||||
|
SIb3DQEBCwUAA4IBAQAMMGUXBaWTdaLxsTGtcB/naqjIQrLvoV9NG+7MoHpGd/69
|
||||||
|
dZ/h2zOy7sGFUHoG/0HGRA9rxT/5w5GkEVIVkxtWyIWWq6rs4CTZt8Bej/KHYRbo
|
||||||
|
jtEDUkCTZSTLiCvguPyvinXgxy+LHT+PmdtEfXsvcdbeBSWUYpOsDYvD2hNtz9dw
|
||||||
|
Od5nBosMApmdxt+z7LQyZu8wMnfI1U6IMO+RWowxZ8uy0oswdFYd32l9xe+aAE/k
|
||||||
|
y9alLu/M9pvxiUKufqHJRgDBKA6uDjHLMPX+/nxXaNCPX3SI4KVZ1stHQ/U5oNlM
|
||||||
|
dHN9umAvlU313g0IgJrjsQ2nIdf9dsdP+6lrmP7s
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
Subject: C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, OU=(c) 2006 VeriSign, Inc. - For authorized use only, CN=VeriSign Class 3 Public Primary Certification Authority - G5
|
||||||
|
Not Before: Nov 8 00:00:00 2006 GMT
|
||||||
|
Not After : Jul 16 23:59:59 2036 GMT
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCB
|
||||||
|
yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL
|
||||||
|
ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp
|
||||||
|
U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW
|
||||||
|
ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0
|
||||||
|
aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCByjEL
|
||||||
|
MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW
|
||||||
|
ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2ln
|
||||||
|
biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp
|
||||||
|
U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y
|
||||||
|
aXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvJAgIKXo1
|
||||||
|
nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKzj/i5Vbex
|
||||||
|
t0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIz
|
||||||
|
SdhDY2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQG
|
||||||
|
BO+QueQA5N06tRn/Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+
|
||||||
|
rCpSx4/VBEnkjWNHiDxpg8v+R70rfk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/
|
||||||
|
NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E
|
||||||
|
BAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEwHzAH
|
||||||
|
BgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy
|
||||||
|
aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKv
|
||||||
|
MzEzMA0GCSqGSIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzE
|
||||||
|
p6B4Eq1iDkVwZMXnl2YtmAl+X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y
|
||||||
|
5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKEKQsTb47bDN0lAtukixlE0kF6BWlK
|
||||||
|
WE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiCKm0oHw0LxOXnGiYZ
|
||||||
|
4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vEZV8N
|
||||||
|
hnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
Subject: C=US, O=The Go Daddy Group, Inc., OU=Go Daddy Class 2 Certification Authority
|
||||||
|
Not Before: Jun 29 17:06:20 2004 GMT
|
||||||
|
Not After : Jun 29 17:06:20 2034 GMT
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEh
|
||||||
|
MB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBE
|
||||||
|
YWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3
|
||||||
|
MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRo
|
||||||
|
ZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3Mg
|
||||||
|
MiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggEN
|
||||||
|
ADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCA
|
||||||
|
PVYYYwhv2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6w
|
||||||
|
wdhFJ2+qN1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXi
|
||||||
|
EqITLdiOr18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMY
|
||||||
|
avx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+
|
||||||
|
YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0OBBYEFNLE
|
||||||
|
sNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h
|
||||||
|
/t2oatTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5
|
||||||
|
IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmlj
|
||||||
|
YXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD
|
||||||
|
ggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wimPQoZ+YeAEW5p5JYXMP80kWNy
|
||||||
|
OO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKtI3lpjbi2Tc7P
|
||||||
|
TMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ
|
||||||
|
HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mER
|
||||||
|
dEr/VxqHD3VILs9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5Cuf
|
||||||
|
ReYNnyicsbkqWletNw+vHX/bvZ8=
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
# Note: Amazon ATS endpoint uses this (2018/12/18)
|
||||||
|
Subject: C=US, O=Starfield Technologies, Inc., OU=Starfield Class 2 Certification Authority
|
||||||
|
Not Before: Jun 29 17:39:16 2004 GMT
|
||||||
|
Not After : Jun 29 17:39:16 2034 GMT
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzEl
|
||||||
|
MCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMp
|
||||||
|
U3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQw
|
||||||
|
NjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBoMQswCQYDVQQGEwJVUzElMCMGA1UE
|
||||||
|
ChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZp
|
||||||
|
ZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqGSIb3
|
||||||
|
DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf
|
||||||
|
8MOh2tTYbitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN
|
||||||
|
+lq2cwQlZut3f+dZxkqZJRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0
|
||||||
|
X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVmepsZGD3/cVE8MC5fvj13c7JdBmzDI1aa
|
||||||
|
K4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSNF4Azbl5KXZnJHoe0nRrA
|
||||||
|
1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HFMIHCMB0G
|
||||||
|
A1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fR
|
||||||
|
zt0fhvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0
|
||||||
|
YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBD
|
||||||
|
bGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8w
|
||||||
|
DQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGsafPzWdqbAYcaT1epoXkJKtv3
|
||||||
|
L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLMPUxA2IGvd56D
|
||||||
|
eruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl
|
||||||
|
xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynp
|
||||||
|
VSJYACPq4xJDKVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEY
|
||||||
|
WQPJIrSPnNVeKtelttQKbfi3QBFGmh95DmK/D5fs4C8fF5Q=
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
Not Before: Sep 1 00:00:00 2009 GMT
|
||||||
|
Not After : Dec 31 23:59:59 2037 GMT
|
||||||
|
Subject: C=US, ST=Arizona, L=Scottsdale, O=Starfield Technologies, Inc., CN=Starfield Root Certificate Authority - G2
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMx
|
||||||
|
EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT
|
||||||
|
HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVs
|
||||||
|
ZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAw
|
||||||
|
MFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6
|
||||||
|
b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQgVGVj
|
||||||
|
aG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZp
|
||||||
|
Y2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
|
||||||
|
ggEBAL3twQP89o/8ArFvW59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMg
|
||||||
|
nLRJdzIpVv257IzdIvpy3Cdhl+72WoTsbhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1
|
||||||
|
HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNkN3mSwOxGXn/hbVNMYq/N
|
||||||
|
Hwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7NfZTD4p7dN
|
||||||
|
dloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0
|
||||||
|
HZbUJtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO
|
||||||
|
BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0G
|
||||||
|
CSqGSIb3DQEBCwUAA4IBAQARWfolTwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjU
|
||||||
|
sHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx4mcujJUDJi5DnUox9g61DLu3
|
||||||
|
4jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUwF5okxBDgBPfg
|
||||||
|
8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K
|
||||||
|
pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1
|
||||||
|
mMpYjn0q7pBZc2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
Subject: C=US, ST=Arizona, L=Scottsdale, O=Starfield Technologies, Inc., CN=Starfield Services Root Certificate Authority - G2
|
||||||
|
Not Before: Sep 1 00:00:00 2009 GMT
|
||||||
|
Not After : Dec 31 23:59:59 2037 GMT
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMx
|
||||||
|
EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT
|
||||||
|
HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVs
|
||||||
|
ZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5
|
||||||
|
MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNVBAYTAlVTMRAwDgYD
|
||||||
|
VQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFy
|
||||||
|
ZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2Vy
|
||||||
|
dmljZXMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI
|
||||||
|
hvcNAQEBBQADggEPADCCAQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20p
|
||||||
|
OsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm2
|
||||||
|
8xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4PahHQUw2eeBGg6345AWh1K
|
||||||
|
Ts9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLPLJGmpufe
|
||||||
|
hRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk
|
||||||
|
6mFBrMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAw
|
||||||
|
DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+q
|
||||||
|
AdcwKziIorhtSpzyEZGDMA0GCSqGSIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMI
|
||||||
|
bw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPPE95Dz+I0swSdHynVv/heyNXB
|
||||||
|
ve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTyxQGjhdByPq1z
|
||||||
|
qwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd
|
||||||
|
iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn
|
||||||
|
0q23KXB56jzaYyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCN
|
||||||
|
sSi6
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
Subject: OU=GlobalSign Root CA - R2, O=GlobalSign, CN=GlobalSign
|
||||||
|
Not Before: Dec 15 08:00:00 2006 GMT
|
||||||
|
Not After : Dec 15 08:00:00 2021 GMT
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4G
|
||||||
|
A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNp
|
||||||
|
Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1
|
||||||
|
MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMjETMBEG
|
||||||
|
A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI
|
||||||
|
hvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6ErPL
|
||||||
|
v4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8
|
||||||
|
eoLrvozps6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklq
|
||||||
|
tTleiDTsvHgMCJiEbKjNS7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzd
|
||||||
|
C9XZzPnqJworc5HGnRusyMvo4KD0L5CLTfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pa
|
||||||
|
zq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6CygPCm48CAwEAAaOBnDCB
|
||||||
|
mTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUm+IH
|
||||||
|
V2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5n
|
||||||
|
bG9iYWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG
|
||||||
|
3lm0mi3f3BmGLjANBgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4Gs
|
||||||
|
J0/WwbgcQ3izDJr86iw8bmEbTUsp9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO
|
||||||
|
291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu01yiPqFbQfXf5WRDLenVOavS
|
||||||
|
ot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG79G+dwfCMNYxd
|
||||||
|
AfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7
|
||||||
|
TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg==
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
Subject: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert High Assurance EV Root CA
|
||||||
|
Not Before: Nov 10 00:00:00 2006 GMT
|
||||||
|
Not After : Nov 10 00:00:00 2031 GMT
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs
|
||||||
|
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
|
||||||
|
d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
|
||||||
|
ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL
|
||||||
|
MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
|
||||||
|
LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug
|
||||||
|
RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm
|
||||||
|
+9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW
|
||||||
|
PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM
|
||||||
|
xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB
|
||||||
|
Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3
|
||||||
|
hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg
|
||||||
|
EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF
|
||||||
|
MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA
|
||||||
|
FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec
|
||||||
|
nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z
|
||||||
|
eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF
|
||||||
|
hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2
|
||||||
|
Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe
|
||||||
|
vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep
|
||||||
|
+OkuE6N36B9K
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
Subject: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Global Root CA
|
||||||
|
Not Before: Nov 10 00:00:00 2006 GMT
|
||||||
|
Not After : Nov 10 00:00:00 2031 GMT
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh
|
||||||
|
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
|
||||||
|
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
|
||||||
|
QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT
|
||||||
|
MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
|
||||||
|
b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG
|
||||||
|
9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB
|
||||||
|
CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97
|
||||||
|
nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt
|
||||||
|
43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P
|
||||||
|
T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4
|
||||||
|
gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO
|
||||||
|
BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR
|
||||||
|
TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw
|
||||||
|
DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr
|
||||||
|
hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg
|
||||||
|
06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF
|
||||||
|
PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls
|
||||||
|
YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
|
||||||
|
CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
# *.azure-devices.de use this root.
|
||||||
|
Subject: C = DE, O = D-Trust GmbH, CN = D-TRUST Root Class 3 CA 2 2009
|
||||||
|
Not Before: Nov 5 08:35:58 2009 GMT
|
||||||
|
Not After : Nov 5 08:35:58 2029 GMT
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIEMzCCAxugAwIBAgIDCYPzMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNVBAYTAkRF
|
||||||
|
MRUwEwYDVQQKDAxELVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBD
|
||||||
|
bGFzcyAzIENBIDIgMjAwOTAeFw0wOTExMDUwODM1NThaFw0yOTExMDUwODM1NTha
|
||||||
|
ME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxELVRydXN0IEdtYkgxJzAlBgNVBAMM
|
||||||
|
HkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTCCASIwDQYJKoZIhvcNAQEB
|
||||||
|
BQADggEPADCCAQoCggEBANOySs96R+91myP6Oi/WUEWJNTrGa9v+2wBoqOADER03
|
||||||
|
UAifTUpolDWzU9GUY6cgVq/eUXjsKj3zSEhQPgrfRlWLJ23DEE0NkVJD2IfgXU42
|
||||||
|
tSHKXzlABF9bfsyjxiupQB7ZNoTWSPOSHjRGICTBpFGOShrvUD9pXRl/RcPHAY9R
|
||||||
|
ySPocq60vFYJfxLLHLGvKZAKyVXMD9O0Gu1HNVpK7ZxzBCHQqr0ME7UAyiZsxGsM
|
||||||
|
lFqVlNpQmvH/pStmMaTJOKDfHR+4CS7zp+hnUquVH+BGPtikw8paxTGA6Eian5Rp
|
||||||
|
/hnd2HN8gcqW3o7tszIFZYQ05ub9VxC1X3a/L7AQDcUCAwEAAaOCARowggEWMA8G
|
||||||
|
A1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFP3aFMSfMN4hvR5COfyrYyNJ4PGEMA4G
|
||||||
|
A1UdDwEB/wQEAwIBBjCB0wYDVR0fBIHLMIHIMIGAoH6gfIZ6bGRhcDovL2RpcmVj
|
||||||
|
dG9yeS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwUm9vdCUyMENsYXNzJTIwMyUy
|
||||||
|
MENBJTIwMiUyMDIwMDksTz1ELVRydXN0JTIwR21iSCxDPURFP2NlcnRpZmljYXRl
|
||||||
|
cmV2b2NhdGlvbmxpc3QwQ6BBoD+GPWh0dHA6Ly93d3cuZC10cnVzdC5uZXQvY3Js
|
||||||
|
L2QtdHJ1c3Rfcm9vdF9jbGFzc18zX2NhXzJfMjAwOS5jcmwwDQYJKoZIhvcNAQEL
|
||||||
|
BQADggEBAH+X2zDI36ScfSF6gHDOFBJpiBSVYEQBrLLpME+bUMJm2H6NMLVwMeni
|
||||||
|
acfzcNsgFYbQDfC+rAF1hM5+n02/t2A7nPPKHeJeaNijnZflQGDSNiH+0LS4F9p0
|
||||||
|
o3/U37CYAqxva2ssJSRyoWXuJVrl5jLn8t+rSfrzkGkj2wTZ51xY/GXUl77M/C4K
|
||||||
|
zCUqNQT4YJEVdT1B/yMfGchs64JTBKbkTCJNjYy6zltz7GRUUG3RnFX7acM2w4y8
|
||||||
|
PIWmawomDeCTmGCufsYkl4phX5GOZpIJhzbNi5stPvZR1FDUWSi9g/LMKHtThm3Y
|
||||||
|
Johw1+qRzT65ysCQblrGXnRl11z+o+I=
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
# https://www.amazontrust.com/repository/
|
||||||
|
Subject: C = US, O = Amazon, CN = Amazon Root CA 1
|
||||||
|
Not Before: May 26 00:00:00 2015 GMT
|
||||||
|
Not After : Jan 17 00:00:00 2038 GMT
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF
|
||||||
|
ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6
|
||||||
|
b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL
|
||||||
|
MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv
|
||||||
|
b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj
|
||||||
|
ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM
|
||||||
|
9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw
|
||||||
|
IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6
|
||||||
|
VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L
|
||||||
|
93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm
|
||||||
|
jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
|
||||||
|
AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA
|
||||||
|
A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI
|
||||||
|
U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs
|
||||||
|
N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv
|
||||||
|
o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU
|
||||||
|
5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy
|
||||||
|
rqXRfboQnoZsG4q5WTP468SQvvG5
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
Subject: C = US, O = Amazon, CN = Amazon Root CA 2
|
||||||
|
Not Before: May 26 00:00:00 2015 GMT
|
||||||
|
Not After : May 26 00:00:00 2040 GMT
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIFQTCCAymgAwIBAgITBmyf0pY1hp8KD+WGePhbJruKNzANBgkqhkiG9w0BAQwF
|
||||||
|
ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6
|
||||||
|
b24gUm9vdCBDQSAyMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTEL
|
||||||
|
MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv
|
||||||
|
b3QgQ0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK2Wny2cSkxK
|
||||||
|
gXlRmeyKy2tgURO8TW0G/LAIjd0ZEGrHJgw12MBvIITplLGbhQPDW9tK6Mj4kHbZ
|
||||||
|
W0/jTOgGNk3Mmqw9DJArktQGGWCsN0R5hYGCrVo34A3MnaZMUnbqQ523BNFQ9lXg
|
||||||
|
1dKmSYXpN+nKfq5clU1Imj+uIFptiJXZNLhSGkOQsL9sBbm2eLfq0OQ6PBJTYv9K
|
||||||
|
8nu+NQWpEjTj82R0Yiw9AElaKP4yRLuH3WUnAnE72kr3H9rN9yFVkE8P7K6C4Z9r
|
||||||
|
2UXTu/Bfh+08LDmG2j/e7HJV63mjrdvdfLC6HM783k81ds8P+HgfajZRRidhW+me
|
||||||
|
z/CiVX18JYpvL7TFz4QuK/0NURBs+18bvBt+xa47mAExkv8LV/SasrlX6avvDXbR
|
||||||
|
8O70zoan4G7ptGmh32n2M8ZpLpcTnqWHsFcQgTfJU7O7f/aS0ZzQGPSSbtqDT6Zj
|
||||||
|
mUyl+17vIWR6IF9sZIUVyzfpYgwLKhbcAS4y2j5L9Z469hdAlO+ekQiG+r5jqFoz
|
||||||
|
7Mt0Q5X5bGlSNscpb/xVA1wf+5+9R+vnSUeVC06JIglJ4PVhHvG/LopyboBZ/1c6
|
||||||
|
+XUyo05f7O0oYtlNc/LMgRdg7c3r3NunysV+Ar3yVAhU/bQtCSwXVEqY0VThUWcI
|
||||||
|
0u1ufm8/0i2BWSlmy5A5lREedCf+3euvAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMB
|
||||||
|
Af8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSwDPBMMPQFWAJI/TPlUq9LhONm
|
||||||
|
UjANBgkqhkiG9w0BAQwFAAOCAgEAqqiAjw54o+Ci1M3m9Zh6O+oAA7CXDpO8Wqj2
|
||||||
|
LIxyh6mx/H9z/WNxeKWHWc8w4Q0QshNabYL1auaAn6AFC2jkR2vHat+2/XcycuUY
|
||||||
|
+gn0oJMsXdKMdYV2ZZAMA3m3MSNjrXiDCYZohMr/+c8mmpJ5581LxedhpxfL86kS
|
||||||
|
k5Nrp+gvU5LEYFiwzAJRGFuFjWJZY7attN6a+yb3ACfAXVU3dJnJUH/jWS5E4ywl
|
||||||
|
7uxMMne0nxrpS10gxdr9HIcWxkPo1LsmmkVwXqkLN1PiRnsn/eBG8om3zEK2yygm
|
||||||
|
btmlyTrIQRNg91CMFa6ybRoVGld45pIq2WWQgj9sAq+uEjonljYE1x2igGOpm/Hl
|
||||||
|
urR8FLBOybEfdF849lHqm/osohHUqS0nGkWxr7JOcQ3AWEbWaQbLU8uz/mtBzUF+
|
||||||
|
fUwPfHJ5elnNXkoOrJupmHN5fLT0zLm4BwyydFy4x2+IoZCn9Kr5v2c69BoVYh63
|
||||||
|
n749sSmvZ6ES8lgQGVMDMBu4Gon2nL2XA46jCfMdiyHxtN/kHNGfZQIG6lzWE7OE
|
||||||
|
76KlXIx3KadowGuuQNKotOrN8I1LOJwZmhsoVLiJkO/KdYE+HvJkJMcYr07/R54H
|
||||||
|
9jVlpNMKVv/1F2Rs76giJUmTtt8AF9pYfl3uxRuw0dFfIRDH+fO6AgonB8Xx1sfT
|
||||||
|
4PsJYGw=
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
Not Before: May 26 00:00:00 2015 GMT
|
||||||
|
Not After : May 26 00:00:00 2040 GMT
|
||||||
|
Subject: C = US, O = Amazon, CN = Amazon Root CA 3
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5
|
||||||
|
MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g
|
||||||
|
Um9vdCBDQSAzMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG
|
||||||
|
A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg
|
||||||
|
Q0EgMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCmXp8ZBf8ANm+gBG1bG8lKl
|
||||||
|
ui2yEujSLtf6ycXYqm0fc4E7O5hrOXwzpcVOho6AF2hiRVd9RFgdszflZwjrZt6j
|
||||||
|
QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSr
|
||||||
|
ttvXBp43rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkr
|
||||||
|
BqWTrBqYaGFy+uGh0PsceGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteM
|
||||||
|
YyRIHN8wfdVoOw==
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
Not Before: May 26 00:00:00 2015 GMT
|
||||||
|
Not After : May 26 00:00:00 2040 GMT
|
||||||
|
Subject: C = US, O = Amazon, CN = Amazon Root CA 4
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIB8jCCAXigAwIBAgITBmyf18G7EEwpQ+Vxe3ssyBrBDjAKBggqhkjOPQQDAzA5
|
||||||
|
MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g
|
||||||
|
Um9vdCBDQSA0MB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG
|
||||||
|
A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg
|
||||||
|
Q0EgNDB2MBAGByqGSM49AgEGBSuBBAAiA2IABNKrijdPo1MN/sGKe0uoe0ZLY7Bi
|
||||||
|
9i0b2whxIdIA6GO9mif78DluXeo9pcmBqqNbIJhFXRbb/egQbeOc4OO9X4Ri83Bk
|
||||||
|
M6DLJC9wuoihKqB1+IGuYgbEgds5bimwHvouXKNCMEAwDwYDVR0TAQH/BAUwAwEB
|
||||||
|
/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFNPsxzplbszh2naaVvuc84ZtV+WB
|
||||||
|
MAoGCCqGSM49BAMDA2gAMGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlw
|
||||||
|
CkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1AE47xDqUEpHJWEadIRNyp4iciuRMStuW
|
||||||
|
1KyLa2tJElMzrdfkviT8tQp21KW8EA==
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
Not Before: Nov 10 00:00:00 2006 GMT
|
||||||
|
Not After : Nov 10 00:00:00 2031 GMT
|
||||||
|
Subject: C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert Global Root CA
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh
|
||||||
|
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
|
||||||
|
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
|
||||||
|
QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT
|
||||||
|
MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
|
||||||
|
b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG
|
||||||
|
9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB
|
||||||
|
CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97
|
||||||
|
nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt
|
||||||
|
43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P
|
||||||
|
T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4
|
||||||
|
gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO
|
||||||
|
BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR
|
||||||
|
TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw
|
||||||
|
DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr
|
||||||
|
hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg
|
||||||
|
06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF
|
||||||
|
PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls
|
||||||
|
YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
|
||||||
|
CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
Not Before: Nov 13 00:00:00 2012 GMT
|
||||||
|
Not After : Jan 19 03:14:07 2038 GMT
|
||||||
|
Subject: OU = GlobalSign ECC Root CA - R4, O = GlobalSign, CN = GlobalSign
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIB4TCCAYegAwIBAgIRKjikHJYKBN5CsiilC+g0mAIwCgYIKoZIzj0EAwIwUDEk
|
||||||
|
MCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpH
|
||||||
|
bG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoX
|
||||||
|
DTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBD
|
||||||
|
QSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu
|
||||||
|
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuMZ5049sJQ6fLjkZHAOkrprlOQcJ
|
||||||
|
FspjsbmG+IpXwVfOQvpzofdlQv8ewQCybnMO/8ch5RikqtlxP6jUuc6MHaNCMEAw
|
||||||
|
DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFFSwe61F
|
||||||
|
uOJAf/sKbvu+M8k8o4TVMAoGCCqGSM49BAMCA0gAMEUCIQDckqGgE6bPA7DmxCGX
|
||||||
|
kPoUVy0D7O48027KqGx2vKLeuwIgJ6iFJzWbVsaj8kfSt24bAgAXqmemFZHe+pTs
|
||||||
|
ewv4n4Q=
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
Not Before: Nov 1 00:00:42 2018 GMT
|
||||||
|
Not After : Nov 1 00:00:42 2042 GMT
|
||||||
|
Subject: C = US, O = Google Trust Services LLC, CN = GTS LTSR
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIBxTCCAWugAwIBAgINAfD3nVndblD3QnNxUDAKBggqhkjOPQQDAjBEMQswCQYD
|
||||||
|
VQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzERMA8G
|
||||||
|
A1UEAxMIR1RTIExUU1IwHhcNMTgxMTAxMDAwMDQyWhcNNDIxMTAxMDAwMDQyWjBE
|
||||||
|
MQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExM
|
||||||
|
QzERMA8GA1UEAxMIR1RTIExUU1IwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATN
|
||||||
|
8YyO2u+yCQoZdwAkUNv5c3dokfULfrA6QJgFV2XMuENtQZIG5HUOS6jFn8f0ySlV
|
||||||
|
eORCxqFyjDJyRn86d+Iko0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUw
|
||||||
|
AwEB/zAdBgNVHQ4EFgQUPv7/zFLrvzQ+PfNA0OQlsV+4u1IwCgYIKoZIzj0EAwID
|
||||||
|
SAAwRQIhAPKuf/VtBHqGw3TUwUIq7TfaExp3bH7bjCBmVXJupT9FAiBr0SmCtsuk
|
||||||
|
miGgpajjf/gFigGM34F9021bCWs1MbL0SA==
|
||||||
|
-----END CERTIFICATE-----
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
// Copyright (c) 2020 Cesanta Software Limited
|
||||||
|
// All rights reserved
|
||||||
|
//
|
||||||
|
// Example HTTP reverse proxy
|
||||||
|
// 1. Run `make`. This builds and starts a proxy on port 8000
|
||||||
|
// 2. Start your browser, go to https://localhost:8000
|
||||||
|
//
|
||||||
|
// To enable SSL/TLS, build it like this:
|
||||||
|
// make MBEDTLS_DIR=/path/to/your/mbedtls/installation
|
||||||
|
|
||||||
|
static const char *s_backend_url = "https://cesanta.com";
|
||||||
|
static const char *s_listen_url = "http://localhost:8000";
|
||||||
|
|
||||||
|
#include "mongoose.h"
|
||||||
|
|
||||||
|
// Forward client request to the backend connection, rewriting the Host header
|
||||||
|
static void forward_request(struct mg_http_message *hm,
|
||||||
|
struct mg_connection *c) {
|
||||||
|
size_t i, max = sizeof(hm->headers) / sizeof(hm->headers[0]);
|
||||||
|
struct mg_str host = mg_url_host(s_backend_url);
|
||||||
|
mg_printf(c, "%.*s\r\n",
|
||||||
|
(int) (hm->proto.ptr + hm->proto.len - hm->message.ptr),
|
||||||
|
hm->message.ptr);
|
||||||
|
for (i = 0; i < max && hm->headers[i].name.len > 0; i++) {
|
||||||
|
struct mg_str *k = &hm->headers[i].name, *v = &hm->headers[i].value;
|
||||||
|
if (mg_strcmp(*k, mg_str("Host")) == 0) v = &host;
|
||||||
|
mg_printf(c, "%.*s: %.*s\r\n", (int) k->len, k->ptr, (int) v->len, v->ptr);
|
||||||
|
}
|
||||||
|
mg_send(c, "\r\n", 2);
|
||||||
|
mg_send(c, hm->body.ptr, hm->body.len);
|
||||||
|
LOG(LL_DEBUG, ("FORWARDING: %.*s %.*s", (int) hm->method.len, hm->method.ptr,
|
||||||
|
(int) hm->uri.len, hm->uri.ptr));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
|
||||||
|
struct mg_connection *c2 = fn_data;
|
||||||
|
if (ev == MG_EV_HTTP_MSG) {
|
||||||
|
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||||
|
if (c->label[0] != 'B' && c2 == NULL) {
|
||||||
|
// Client request, create backend connection Note that we're passing
|
||||||
|
// client connection `c` as fn_data for the created backend connection.
|
||||||
|
// This way, we tie together these two connections via `fn_data` pointer:
|
||||||
|
// client's c->fn_data points to the backend connection, and backend's
|
||||||
|
// c->fn_data points to the client connection
|
||||||
|
c2 = mg_connect(c->mgr, s_backend_url, fn, c);
|
||||||
|
c->fn_data = c2;
|
||||||
|
if (c2 != NULL) {
|
||||||
|
c2->is_hexdumping = 1;
|
||||||
|
c2->label[0] = 'B'; // Mark this connection as backend
|
||||||
|
} else {
|
||||||
|
c->is_closing = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (c2 != NULL && c2->label[0] == 'B') forward_request(hm, c2);
|
||||||
|
} else if (ev == MG_EV_READ) {
|
||||||
|
if (c->label[0] == 'B' && c2 != NULL) {
|
||||||
|
// All incoming data from the backend, forward to the client
|
||||||
|
mg_send(c2, c->recv.buf, c->recv.len);
|
||||||
|
mg_iobuf_delete(&c->recv, c->recv.len);
|
||||||
|
}
|
||||||
|
} else if (ev == MG_EV_CONNECT) {
|
||||||
|
if (mg_url_is_ssl(s_backend_url)) {
|
||||||
|
struct mg_tls_opts opts = {.ca = "ca.pem"};
|
||||||
|
mg_tls_init(c, &opts);
|
||||||
|
}
|
||||||
|
} else if (ev == MG_EV_CLOSE) {
|
||||||
|
if (c2 != NULL) c2->is_closing = 1;
|
||||||
|
c->fn_data = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
struct mg_mgr mgr;
|
||||||
|
|
||||||
|
mg_log_set("3"); // Set log level
|
||||||
|
mg_mgr_init(&mgr); // Initialise event manager
|
||||||
|
mg_http_listen(&mgr, s_listen_url, fn, NULL); // Start proxy
|
||||||
|
for (;;) mg_mgr_poll(&mgr, 1000); // Event loop
|
||||||
|
mg_mgr_free(&mgr);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
PROG ?= example
|
||||||
|
ROOT ?= $(realpath $(CURDIR)/../..)
|
||||||
|
DEFS ?= -DMG_ENABLE_LINES=1 -DMG_ENABLE_DIRECTORY_LISTING=1 -DMG_ENABLE_SSI=1
|
||||||
|
CFLAGS ?= -I../.. -W -Wall -DMG_ENABLE_IPV6=1 $(DEFS) $(EXTRA)
|
||||||
|
VCFLAGS = /nologo /W3 /O2 /I../.. $(DEFS) $(EXTRA) /link /incremental:no /machine:IX86
|
||||||
|
VC98 = docker run --rm -e Tmp=. -v $(ROOT):$(ROOT) -w $(CURDIR) docker.io/mdashnet/vc98
|
||||||
|
|
||||||
|
all: $(PROG)
|
||||||
|
$(DEBUGGER) ./$(PROG) $(ARGS)
|
||||||
|
|
||||||
|
$(PROG): main.c Makefile
|
||||||
|
$(CC) ../../mongoose.c main.c -I../.. $(CFLAGS) -o $@
|
||||||
|
|
||||||
|
mongoose.exe: main.c
|
||||||
|
$(VC98) wine cl ../../mongoose.c main.c $(VCFLAGS) ws2_32.lib /out:$@
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf $(PROG) *.o *.dSYM *.gcov *.gcno *.gcda *.obj *.exe *.ilk *.pdb mongoose mongoose_* mongoose.*
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
// Copyright (c) 2020 Cesanta Software Limited
|
||||||
|
// All rights reserved
|
||||||
|
|
||||||
|
#include "mongoose.h"
|
||||||
|
|
||||||
|
static const char *s_debug_level = "2";
|
||||||
|
static const char *s_root_dir = ".";
|
||||||
|
static const char *s_listening_address = "http://localhost:8000";
|
||||||
|
static const char *s_enable_hexdump = "no";
|
||||||
|
static const char *s_ssi_pattern = "#.shtml";
|
||||||
|
|
||||||
|
static void cb(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
|
||||||
|
if (ev == MG_EV_HTTP_MSG) {
|
||||||
|
struct mg_http_serve_opts opts = {s_root_dir, s_ssi_pattern};
|
||||||
|
mg_http_serve_dir(c, ev_data, &opts);
|
||||||
|
}
|
||||||
|
(void) fn_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void usage(const char *prog) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"Mongoose v.%s, built " __DATE__ " " __TIME__
|
||||||
|
"\nUsage: %s OPTIONS\n"
|
||||||
|
" -H yes|no - enable traffic hexdump, default: '%s'\n"
|
||||||
|
" -S GLOB - glob pattern for SSI files, default: '%s'\n"
|
||||||
|
" -d DIR - directory to serve, default: '%s'\n"
|
||||||
|
" -l ADDR - listening address, default: '%s'\n"
|
||||||
|
" -v LEVEL - debug level, from 0 to 4, default: '%s'\n",
|
||||||
|
MG_VERSION, prog, s_debug_level, s_enable_hexdump, s_ssi_pattern,
|
||||||
|
s_root_dir, s_listening_address);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
struct mg_mgr mgr;
|
||||||
|
struct mg_connection *c;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
// Parse command-line flags
|
||||||
|
for (i = 1; i < argc; i++) {
|
||||||
|
if (strcmp(argv[i], "-d") == 0) {
|
||||||
|
s_root_dir = argv[++i];
|
||||||
|
} else if (strcmp(argv[i], "-H") == 0) {
|
||||||
|
s_enable_hexdump = argv[++i];
|
||||||
|
} else if (strcmp(argv[i], "-S") == 0) {
|
||||||
|
s_ssi_pattern = argv[++i];
|
||||||
|
} else if (strcmp(argv[i], "-l") == 0) {
|
||||||
|
s_listening_address = argv[++i];
|
||||||
|
} else if (strcmp(argv[i], "-v") == 0) {
|
||||||
|
s_debug_level = argv[++i];
|
||||||
|
} else {
|
||||||
|
usage(argv[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialise stuff
|
||||||
|
mg_log_set(s_debug_level);
|
||||||
|
mg_mgr_init(&mgr);
|
||||||
|
if ((c = mg_http_listen(&mgr, s_listening_address, cb, &mgr)) == NULL) {
|
||||||
|
LOG(LL_ERROR, ("Cannot listen on %s. Use http://ADDR:PORT or :PORT",
|
||||||
|
s_listening_address));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
if (mg_casecmp(s_enable_hexdump, "yes") == 0) c->is_hexdumping = 1;
|
||||||
|
|
||||||
|
// Start infinite event loop
|
||||||
|
LOG(LL_INFO, ("Starting Mongoose web server v%s", MG_VERSION));
|
||||||
|
for (;;) mg_mgr_poll(&mgr, 1000);
|
||||||
|
mg_mgr_free(&mgr);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
PROG = http_client
|
|
||||||
SOURCES = $(PROG).c ../../mongoose.c
|
|
||||||
CFLAGS = -W -Wall -I../.. -DMG_ENABLE_SSL -lssl -lcrypto -pthread $(CFLAGS_EXTRA)
|
|
||||||
|
|
||||||
all: $(PROG)
|
|
||||||
|
|
||||||
$(PROG): $(SOURCES)
|
|
||||||
$(CC) $(SOURCES) -o $@ $(CFLAGS)
|
|
||||||
|
|
||||||
$(PROG).exe: $(SOURCES)
|
|
||||||
cl $(SOURCES) /I../.. /MD /Fe$@
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -rf *.gc* *.dSYM *.exe *.obj *.o a.out $(PROG)
|
|
||||||