mirror of
https://github.com/cesanta/mongoose.git
synced 2026-10-25 12:04:47 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
23141c2fef | ||
|
|
c8ba652f1c | ||
|
|
6ac2fa2ae6 | ||
|
|
0322ec5647 | ||
|
|
a5223a9850 | ||
|
|
016968ada1 | ||
|
|
710b888122 | ||
|
|
cf53959f34 | ||
|
|
30d29fb77f | ||
|
|
c05b51bbfc | ||
|
|
1ab704ac92 | ||
|
|
2bc77e065c | ||
|
|
790daabf7d | ||
|
|
a6598a1278 | ||
|
|
0af5502b74 | ||
|
|
f059e41cac | ||
|
|
2cce91de9a | ||
|
|
0ff5b5b044 | ||
|
|
0c5d9a98c2 | ||
|
|
c9fbdfc1b5 | ||
|
|
6193b5171c | ||
|
|
911115ccc0 | ||
|
|
2f3ddeccc5 | ||
|
|
ca3f5a3257 | ||
|
|
df206bc05a | ||
|
|
531fec34fd | ||
|
|
4c10d1f356 | ||
|
|
94dccdd6f4 | ||
|
|
544352b7d3 | ||
|
|
29c2ae4886 | ||
|
|
1a2e2ec2fd | ||
|
|
3e780d21fc | ||
|
|
63fcea0159 | ||
|
|
e5d21225be | ||
|
|
0c9caf3120 | ||
|
|
54ba36c1c9 | ||
|
|
5077350589 | ||
|
|
2d880c4f5c | ||
|
|
4ca4c862a5 | ||
|
|
0918df1566 | ||
|
|
aa2583cc26 | ||
|
|
e1b1d39635 | ||
|
|
3bf82dd541 | ||
|
|
2896965c97 | ||
|
|
53b784b143 | ||
|
|
8e91e3a305 | ||
|
|
dbc07c8b00 | ||
|
|
ce953575e2 | ||
|
|
80db048578 | ||
|
|
382d165574 | ||
|
|
0fb2f38cb7 | ||
|
|
aa007f1285 | ||
|
|
8752910330 | ||
|
|
2a5a8eec49 | ||
|
|
ceca52de30 | ||
|
|
8a3691055c | ||
|
|
56d12c89da | ||
|
|
2cfce4d8b2 | ||
|
|
f372faf614 | ||
|
|
882f3b3ac3 | ||
|
|
fac0e9b0ac | ||
|
|
a3cf67c380 | ||
|
|
2987cbdb5c | ||
|
|
6083b9c5c5 | ||
|
|
83237a02d9 | ||
|
|
965188bac9 | ||
|
|
66da41d401 | ||
|
|
cfd334ac6c | ||
|
|
b5f6254c1e | ||
|
|
dcbd1cbbd1 | ||
|
|
a3b568f460 | ||
|
|
75770aec80 | ||
|
|
3a8ae7ac17 | ||
|
|
b116b2fa82 | ||
|
|
7806609773 | ||
|
|
72f45aa7e2 | ||
|
|
5e3e6a6dce | ||
|
|
1388bb1db4 | ||
|
|
3cc0d16f65 | ||
|
|
b50095fa61 | ||
|
|
7ad85219d8 | ||
|
|
347a249d10 | ||
|
|
07d982129a | ||
|
|
73f2602ba0 | ||
|
|
44561d163a | ||
|
|
c941a1a39a | ||
|
|
bee22312bc | ||
|
|
bdb16c624c | ||
|
|
e389e70d05 | ||
|
|
695559f691 | ||
|
|
13be74b4c6 | ||
|
|
02a1032fd4 | ||
|
|
788f35b19c | ||
|
|
3721efe1e9 | ||
|
|
e0822ffb78 | ||
|
|
ae7d5a8f94 | ||
|
|
ced7a2e0b5 | ||
|
|
5ed6708468 | ||
|
|
9fe53f307b | ||
|
|
c64d30e1f6 | ||
|
|
b4c25fc7ba | ||
|
|
b67b618811 | ||
|
|
5a19438f70 | ||
|
|
860addf1e3 | ||
|
|
03d571a119 | ||
|
|
0d9ecffc53 | ||
|
|
d4c8384b85 | ||
|
|
bd40145301 | ||
|
|
9b42494316 | ||
|
|
2daff6959f | ||
|
|
e9c434a6a1 | ||
|
|
d6fba7e45d | ||
|
|
0a0130b90c | ||
|
|
facf2af66e | ||
|
|
cc54195f59 | ||
|
|
e2fb707d9f | ||
|
|
7dfff935d6 | ||
|
|
5727a5c0ed | ||
|
|
268d2e9cbe | ||
|
|
1e7da874a4 | ||
|
|
7875a8c2bd | ||
|
|
b0355d45ae | ||
|
|
91136d7731 | ||
|
|
01a058d29b | ||
|
|
e6eca1738f | ||
|
|
2108ec5a0c | ||
|
|
bc4e47630a | ||
|
|
f41c9a2a1f | ||
|
|
6c77208236 | ||
|
|
386d2e5cd4 | ||
|
|
b738fdbffa | ||
|
|
b5704850db | ||
|
|
9c67e8960e | ||
|
|
d3dff4e1d5 | ||
|
|
82872e86fd | ||
|
|
ac229b6606 | ||
|
|
a6bf2bcbf4 | ||
|
|
b0cf8304cb | ||
|
|
0d9fe39dbb | ||
|
|
708af6d9c5 | ||
|
|
e4c71425c9 | ||
|
|
6e07215c1c | ||
|
|
ca9603301e | ||
|
|
d6c388042c | ||
|
|
6f66d794e8 | ||
|
|
1389eec784 | ||
|
|
6ef795e082 | ||
|
|
1e5d258e9e | ||
|
|
70eb4c4bbc | ||
|
|
a639e10a4d | ||
|
|
48750e67f6 | ||
|
|
ce60379af6 | ||
|
|
e0b9e4abfd | ||
|
|
665f205527 | ||
|
|
030daaf5d5 | ||
|
|
760511ec49 | ||
|
|
203688a34b | ||
|
|
29f4703e4f | ||
|
|
3cec6f6745 | ||
|
|
abcea07641 | ||
|
|
6a54704b29 | ||
|
|
8a2fbac4c0 | ||
|
|
96ce6bac69 | ||
|
|
50c0b958ff | ||
|
|
44416902d6 | ||
|
|
25e646c1a1 | ||
|
|
bd723bdc38 | ||
|
|
5e57031724 | ||
|
|
c583913290 | ||
|
|
870ca615de | ||
|
|
64b51699f8 | ||
|
|
50a889dac0 | ||
|
|
0ff0788458 | ||
|
|
fec6009edb | ||
|
|
c4f172a120 | ||
|
|
464c77314d | ||
|
|
f51ca8d5d1 | ||
|
|
7b37e0cb8b | ||
|
|
c7925353e7 | ||
|
|
bd23ec4323 | ||
|
|
3671b2632d | ||
|
|
25115a694c | ||
|
|
2436f9d6c3 | ||
|
|
2238951c18 | ||
|
|
f266dd2c94 | ||
|
|
b03358cb03 | ||
|
|
1bede7e28b | ||
|
|
3536670b82 | ||
|
|
3235c05fd6 | ||
|
|
63db54e7b5 | ||
|
|
1db51eb788 | ||
|
|
0e640ae885 | ||
|
|
1bff6df2a7 | ||
|
|
d0e66de225 | ||
|
|
f537670ce2 | ||
|
|
4cb3341a15 | ||
|
|
d52d9a4a6f | ||
|
|
4a076c7ea4 | ||
|
|
db6e883c22 | ||
|
|
804da054b5 | ||
|
|
fb4e701545 | ||
|
|
ccff4abf13 | ||
|
|
24a7936907 | ||
|
|
0993994139 | ||
|
|
8b740536de | ||
|
|
e851aac853 | ||
|
|
a39861b7bf | ||
|
|
63490249ba | ||
|
|
704f057384 | ||
|
|
40968bc496 | ||
|
|
6873f3c5f6 | ||
|
|
ba5cd7267a | ||
|
|
1bb98e5e8e | ||
|
|
a7774d0f1a | ||
|
|
f52c756fbb | ||
|
|
cc586c6ba2 | ||
|
|
606eab7f4f | ||
|
|
872b85b5f2 | ||
|
|
35bd2b6032 | ||
|
|
c5287b9044 | ||
|
|
223f6d960e | ||
|
|
464b895116 | ||
|
|
05d7b7c8bc | ||
|
|
d8b4db37a0 | ||
|
|
6bb49c780c | ||
|
|
3a60c5764d | ||
|
|
a8b38e4ab9 | ||
|
|
8750f8af1f | ||
|
|
e94a02dc12 | ||
|
|
5680b0fcc5 | ||
|
|
33c56b0edc | ||
|
|
e62e48397d | ||
|
|
8be30350be | ||
|
|
2609a2ab72 | ||
|
|
5a04ab2c56 | ||
|
|
4739de6c28 | ||
|
|
639d7a2fd8 | ||
|
|
8115ce1d82 | ||
|
|
3558b587b7 | ||
|
|
e21ec58ea8 | ||
|
|
74135bca7d | ||
|
|
d369f31608 | ||
|
|
d4b14ca3c1 | ||
|
|
f0994896d5 | ||
|
|
cfdd430b98 | ||
|
|
a6c05a9e83 | ||
|
|
94f63787bb | ||
|
|
367f5df328 | ||
|
|
f096138d6e | ||
|
|
0d00cd51e6 | ||
|
|
b216210a13 | ||
|
|
166833f330 | ||
|
|
4d6bedfd4e | ||
|
|
ace8c1736c | ||
|
|
c658a54d18 | ||
|
|
781a1dc25e | ||
|
|
3ea3b8dfa4 | ||
|
|
a514e143ff | ||
|
|
e1486a79e3 | ||
|
|
ee615248e3 | ||
|
|
687e0e2ee8 | ||
|
|
19aefcb7dd | ||
|
|
6a46244a21 | ||
|
|
60674c11c9 | ||
|
|
91c9ab807b | ||
|
|
9231c7346c | ||
|
|
20cb3a823a | ||
|
|
cbd8d69e6d | ||
|
|
f7fcfa6a42 | ||
|
|
293c5e5852 | ||
|
|
ceb866b4ee | ||
|
|
2f9166e96e | ||
|
|
fe0e0e69e5 | ||
|
|
db96641c10 | ||
|
|
fe83928ca4 | ||
|
|
014414f17f | ||
|
|
6ffe2d7f7a | ||
|
|
30c82d7efe | ||
|
|
999c4ad26c | ||
|
|
30a7965135 | ||
|
|
a8a017a048 | ||
|
|
eac8ffabc4 | ||
|
|
a7a17711ec | ||
|
|
18e28ef879 | ||
|
|
ce7515fca9 | ||
|
|
d5a78fb664 | ||
|
|
1b3a1b74ac | ||
|
|
8dd76e6ef4 | ||
|
|
976b5f37c1 | ||
|
|
31489ab7b1 | ||
|
|
1eb59940a4 | ||
|
|
576d769b56 | ||
|
|
afaba7ee17 | ||
|
|
40f257ef2b | ||
|
|
5840dc8153 | ||
|
|
5ed3dafb56 | ||
|
|
b99bf306ec | ||
|
|
89fae72aa7 | ||
|
|
ab147e8f19 | ||
|
|
81a78f9c8b | ||
|
|
370aeefdde | ||
|
|
c5407a75f4 | ||
|
|
7217aa22f1 | ||
|
|
69bd5f7aa2 | ||
|
|
41b3c1b23e | ||
|
|
f639409533 | ||
|
|
67c44799c8 | ||
|
|
4646e2ad55 | ||
|
|
b77532ea3f | ||
|
|
ed8168e8a1 | ||
|
|
39e2d2ad55 | ||
|
|
27c6656398 | ||
|
|
ffe83051fe | ||
|
|
93cd77ffad | ||
|
|
279c06c64c | ||
|
|
570c8213b6 | ||
|
|
f521999ea6 | ||
|
|
e41df3cf9c | ||
|
|
65f484291f | ||
|
|
77db89961b | ||
|
|
ad50310bb6 | ||
|
|
66ec3d1f1e | ||
|
|
a9da86d05c | ||
|
|
5f25a88821 | ||
|
|
fd7dc33645 | ||
|
|
9c22771a43 | ||
|
|
11640cc3c6 | ||
|
|
2264520a2f | ||
|
|
2f0b411ddd | ||
|
|
e0aceb4f3a | ||
|
|
ea9a60a59a | ||
|
|
458320cffb | ||
|
|
e0214af422 | ||
|
|
df5e997ea7 | ||
|
|
0a3cb63c73 | ||
|
|
37f7f3fb12 | ||
|
|
2ac970fa16 | ||
|
|
de35a353d4 | ||
|
|
dbbda02f70 | ||
|
|
725c30446c | ||
|
|
60473ae41a | ||
|
|
951d20f904 | ||
|
|
85a6abd58b | ||
|
|
2fbe09ad7c | ||
|
|
23325efab2 | ||
|
|
107902bae4 | ||
|
|
9bbf4c8384 | ||
|
|
c39a712540 | ||
|
|
e9f6111ba1 | ||
|
|
ba267a32fd | ||
|
|
f64ebbe0b1 | ||
|
|
8865dd5e84 | ||
|
|
ce57f47de0 | ||
|
|
48be2dbc2a | ||
|
|
8905522a94 | ||
|
|
eea1680cf9 | ||
|
|
d5004cb7eb | ||
|
|
1d1a05bf39 | ||
|
|
2009069037 | ||
|
|
8f7703c2a9 | ||
|
|
8e87c4f013 | ||
|
|
639a6dc2a8 | ||
|
|
cead9a04ca | ||
|
|
e528093027 | ||
|
|
c432b783fb | ||
|
|
e06976836f | ||
|
|
c9f7407573 | ||
|
|
a40e59dbe6 | ||
|
|
61ee3d36d0 | ||
|
|
94dbf21ffb | ||
|
|
998425b14b | ||
|
|
6900dd733a | ||
|
|
9e4cd054c8 | ||
|
|
5dc317fcb0 | ||
|
|
fbd5d77ce8 | ||
|
|
6f8751b479 | ||
|
|
877c4dc698 | ||
|
|
2dfc79129a | ||
|
|
416f4bf10f | ||
|
|
f9a99530ff | ||
|
|
940b65e4db | ||
|
|
b22f7d3a49 | ||
|
|
eaa0e26a85 | ||
|
|
a3a63f7e56 | ||
|
|
c9036f3ac0 | ||
|
|
60858d7fe5 | ||
|
|
1c914bde1d | ||
|
|
a487332aa0 | ||
|
|
3987d4d560 | ||
|
|
8d3181e0bf | ||
|
|
0f1a59aeb4 | ||
|
|
2cdf259940 | ||
|
|
0187fe943a | ||
|
|
a34d1ec00a | ||
|
|
e70d98b7b0 | ||
|
|
bea012a3c1 | ||
|
|
eb2d470f65 | ||
|
|
652c352394 | ||
|
|
f1b37b3101 | ||
|
|
81b9876af8 | ||
|
|
7010addadb | ||
|
|
9e118c8a31 | ||
|
|
2fc654ac35 | ||
|
|
45861c7890 | ||
|
|
1957879e10 | ||
|
|
ddbe690698 | ||
|
|
9ba1596c46 | ||
|
|
de509ae952 | ||
|
|
77817cd019 | ||
|
|
7083bea56b | ||
|
|
3dffd7604a | ||
|
|
5a67af0c73 | ||
|
|
14526a2109 | ||
|
|
a6cfbd2536 | ||
|
|
0d28f99275 | ||
|
|
a281e99661 | ||
|
|
170df7b676 | ||
|
|
3fa5c69f98 | ||
|
|
e31f3058fa | ||
|
|
83a9a726d3 | ||
|
|
8ae0400b0d | ||
|
|
037fdbcccb | ||
|
|
5d2ac4e0a6 | ||
|
|
f977757a9d | ||
|
|
1db13aeed5 | ||
|
|
956788d7de | ||
|
|
45f6612096 | ||
|
|
2392156fd4 | ||
|
|
cf1811f8c3 | ||
|
|
93c5335d80 | ||
|
|
192205b10b | ||
|
|
0377eea9c5 | ||
|
|
ad89868564 | ||
|
|
976f286134 | ||
|
|
503a1a749d | ||
|
|
45a4266172 | ||
|
|
2ea17e8c6d | ||
|
|
67b7d79710 | ||
|
|
2e35e25935 | ||
|
|
d86d409d3c | ||
|
|
1109d3aa3c | ||
|
|
8208d9e250 | ||
|
|
fdd086b11c | ||
|
|
5825e3ea74 | ||
|
|
061ba99124 | ||
|
|
ead098f726 | ||
|
|
7a129c17ba | ||
|
|
400084ea8a | ||
|
|
82ad9a073a | ||
|
|
22aea8acac | ||
|
|
40e5c744da | ||
|
|
e648681f1d | ||
|
|
02f19fc05a | ||
|
|
7690f9e34b | ||
|
|
65c1278975 | ||
|
|
05e1135940 | ||
|
|
7b6e8fb93c | ||
|
|
9f1679e900 | ||
|
|
c0af018e20 | ||
|
|
d553ae992a | ||
|
|
89ef8f2f30 | ||
|
|
9115a99f47 | ||
|
|
bbc65c7987 | ||
|
|
bac0f75dd6 | ||
|
|
6440c358c1 | ||
|
|
6f84c8bbfb | ||
|
|
0adbfcba96 | ||
|
|
136c3e8200 | ||
|
|
7d699ea73c | ||
|
|
fc37b08139 | ||
|
|
3aaf47d4e4 | ||
|
|
346179d1f1 | ||
|
|
0148bc804a | ||
|
|
472e198d4a | ||
|
|
bf6fc3262f | ||
|
|
53311e8d6b | ||
|
|
cc636197bc | ||
|
|
6b4f7e785d | ||
|
|
73ed83c5e3 | ||
|
|
56f128514e | ||
|
|
f0571f9fd6 | ||
|
|
a3663da90e | ||
|
|
f74a1e1dc2 | ||
|
|
74511b42f5 | ||
|
|
04862eec85 | ||
|
|
4d105386ca | ||
|
|
44a35bb5bf | ||
|
|
022c9f0d47 | ||
|
|
e38061970e | ||
|
|
a4e8dc3069 | ||
|
|
fa4179ee53 | ||
|
|
a8c8cfb665 | ||
|
|
e0b6109214 | ||
|
|
d29f849602 | ||
|
|
848c5d753e | ||
|
|
4eef5b14fb | ||
|
|
283af71bbf | ||
|
|
ff85b802c3 | ||
|
|
e2b42e4117 | ||
|
|
63909b59c5 | ||
|
|
7380c65265 | ||
|
|
e9316a4feb | ||
|
|
2ac231cb7e | ||
|
|
a741d53028 | ||
|
|
9ea7b6f8ae | ||
|
|
580d3da3c7 | ||
|
|
aa59dda966 | ||
|
|
47b92e4145 | ||
|
|
fa351959a0 | ||
|
|
1414e2a236 | ||
|
|
5fb275e146 | ||
|
|
9390c66b48 | ||
|
|
2f69ca37d3 | ||
|
|
4cd11de400 | ||
|
|
15a2639355 | ||
|
|
c20f26dbb9 | ||
|
|
cae797cf04 | ||
|
|
0d885add0e | ||
|
|
842231cc5c | ||
|
|
dc55a3ae40 | ||
|
|
4d85cc6c76 | ||
|
|
8ac1b40c11 | ||
|
|
238b43af84 | ||
|
|
12c8e99bd5 | ||
|
|
5f2f359bd6 | ||
|
|
ccf0ce4a1f | ||
|
|
134a5b7b9e | ||
|
|
d39daab29e | ||
|
|
a798b1a937 | ||
|
|
04de3bb2f9 | ||
|
|
86da250e2c | ||
|
|
347a8c2f70 | ||
|
|
9624200663 | ||
|
|
18b1e95350 | ||
|
|
407877a4d5 | ||
|
|
7541c6339a | ||
|
|
31f1efd4f5 | ||
|
|
2477f80a43 | ||
|
|
cf94fb3642 | ||
|
|
2210043b87 | ||
|
|
10872b3227 | ||
|
|
cb324cfb9a | ||
|
|
4ee5849a04 | ||
|
|
fa216849e5 | ||
|
|
df6e35e330 | ||
|
|
96bb9aac36 | ||
|
|
7cec2fe280 | ||
|
|
02937f8852 | ||
|
|
51f0cc2b67 | ||
|
|
253927008c | ||
|
|
9778a4ccfc | ||
|
|
d0e2741832 | ||
|
|
3a5e2fba88 | ||
|
|
85940c8045 | ||
|
|
a0b599b308 | ||
|
|
d43ccda9a7 | ||
|
|
675b83a3ef | ||
|
|
dfdfcc060d | ||
|
|
143fb4f423 | ||
|
|
b7eb12017c | ||
|
|
bd1c6c1506 | ||
|
|
efb7f4f05d | ||
|
|
5475fe661d | ||
|
|
8f62822a33 | ||
|
|
0aa1a9e324 | ||
|
|
7a77bb1c4a | ||
|
|
4576b69e30 | ||
|
|
4fd6eb597d | ||
|
|
257dacd7bb | ||
|
|
c88b7b19b3 | ||
|
|
4fbfb5d0d0 | ||
|
|
67c678270e | ||
|
|
049db9015b | ||
|
|
9dde225b5e | ||
|
|
3a0a22f4cc | ||
|
|
b4a4b15835 | ||
|
|
dca2eab152 | ||
|
|
f9f212442c | ||
|
|
83793aadde | ||
|
|
f7a705c40a | ||
|
|
f5f6edcf5a | ||
|
|
9cb1048c66 | ||
|
|
522a7eb554 | ||
|
|
072833acd5 | ||
|
|
a5aa08e408 | ||
|
|
12d98a1732 | ||
|
|
a6c2c2a10b | ||
|
|
fbe1914226 | ||
|
|
64a744055f | ||
|
|
0007e47c07 | ||
|
|
4708cce8bd | ||
|
|
3eb9156e60 | ||
|
|
2990f9328a | ||
|
|
a0befd65a0 | ||
|
|
872ad8badf | ||
|
|
0970e080d9 | ||
|
|
52fe1461d5 | ||
|
|
d5b33adb88 | ||
|
|
ec84a148f0 | ||
|
|
77d5d4c921 | ||
|
|
58dab48156 | ||
|
|
7abb406d0f | ||
|
|
b941dcd5c5 | ||
|
|
b7adf9b52a | ||
|
|
28f7d83a74 | ||
|
|
34ee1ef3d6 | ||
|
|
e518517456 | ||
|
|
7d0662f1bc | ||
|
|
e3751d29d5 | ||
|
|
04b9ccca22 | ||
|
|
1a17165227 | ||
|
|
b6d968f00c | ||
|
|
a69987a711 | ||
|
|
492328474d | ||
|
|
673a2c581f | ||
|
|
9ef42621e0 | ||
|
|
f5865886b2 | ||
|
|
473e2a1cb2 | ||
|
|
146cf1d1c0 | ||
|
|
ab73055ef3 | ||
|
|
3b83543592 | ||
|
|
d4ac96c24d | ||
|
|
0612129a88 | ||
|
|
9bd5903f1d | ||
|
|
d4eae0e251 | ||
|
|
4d7ea04dd8 | ||
|
|
653fab6b41 | ||
|
|
f4c30b746e | ||
|
|
923e5004e8 | ||
|
|
b14a1e25f0 | ||
|
|
5a3b1123f6 | ||
|
|
6a9494b683 | ||
|
|
63c5658a2b | ||
|
|
fe087cdce9 | ||
|
|
af7efd980c | ||
|
|
2cb325c981 | ||
|
|
66435a7158 | ||
|
|
48417ba911 | ||
|
|
f39c4c8909 | ||
|
|
2a7e720f12 | ||
|
|
ec22250d9b | ||
|
|
a7889756a9 | ||
|
|
9ac67770eb | ||
|
|
3330bca4be | ||
|
|
31f0409bf9 | ||
|
|
ebf9ee089b | ||
|
|
88cf329490 | ||
|
|
bba29d32ce | ||
|
|
2f1f408882 | ||
|
|
46a9e42b8f | ||
|
|
58d3abe165 | ||
|
|
03e737829a | ||
|
|
95d8881454 | ||
|
|
a50a52ca91 | ||
|
|
50371ef309 | ||
|
|
6192d1b53a | ||
|
|
daa9175139 | ||
|
|
8a65611a8c | ||
|
|
6c8a0aa768 | ||
|
|
787b15551d | ||
|
|
2c896e7e5c | ||
|
|
0e49214c7e | ||
|
|
914606a046 | ||
|
|
b30417e908 | ||
|
|
5b8d4cdf68 | ||
|
|
ba06d135c3 | ||
|
|
f0d3d7e81d | ||
|
|
d1bd15291e | ||
|
|
d00b7f4300 | ||
|
|
ebc909b61b | ||
|
|
537fb39b21 | ||
|
|
e106151072 | ||
|
|
257de0709f | ||
|
|
774a819e76 | ||
|
|
ff1412f29d | ||
|
|
c6606c714f | ||
|
|
de3d4e3019 | ||
|
|
2f49e63d5b | ||
|
|
988b40f70d | ||
|
|
b5fdd48d76 | ||
|
|
f4f73a8dfa | ||
|
|
74711c686f | ||
|
|
78c994f7cc | ||
|
|
2d5d668863 | ||
|
|
87279f3518 | ||
|
|
bd10a03da0 | ||
|
|
d138119d24 | ||
|
|
73019665fa | ||
|
|
66824e7757 | ||
|
|
7fe6b29218 | ||
|
|
ebdf973af9 | ||
|
|
71dd7a96c7 | ||
|
|
886dcb3f5d | ||
|
|
37751a2875 | ||
|
|
45347bd44c | ||
|
|
8c4521af03 | ||
|
|
0d2a8db626 | ||
|
|
e791a795b4 | ||
|
|
03d846529d | ||
|
|
607651a3ff | ||
|
|
0714e0dd8f | ||
|
|
224d18589f | ||
|
|
2fd7191836 | ||
|
|
853d162b55 | ||
|
|
762a68a0cf | ||
|
|
1da098671e | ||
|
|
f852a4db0f | ||
|
|
ddea940690 | ||
|
|
292e43b41b | ||
|
|
915e923e35 | ||
|
|
e6ac3af454 | ||
|
|
3adaf8dba9 | ||
|
|
1777cc6e86 | ||
|
|
f9f623bd60 | ||
|
|
fe95707b4e | ||
|
|
a631ee1e1e | ||
|
|
493666dac6 | ||
|
|
46ef4e33c8 | ||
|
|
cafaecfc56 | ||
|
|
47606a71ee | ||
|
|
eedfedd13b | ||
|
|
87d841d81b | ||
|
|
5153eebc9b | ||
|
|
70154f6c23 | ||
|
|
d3577b7877 | ||
|
|
199e0a330f | ||
|
|
a8da1b3334 | ||
|
|
63c19b4631 | ||
|
|
1f471e1cf3 | ||
|
|
ef28c37529 | ||
|
|
cd7e1b9eb7 | ||
|
|
226d476856 | ||
|
|
21965e0e03 | ||
|
|
40ab4a8d3d | ||
|
|
e84d0574fa | ||
|
|
1a64d37fc7 | ||
|
|
9cca843a9b | ||
|
|
ecbf79135f | ||
|
|
96eb48902b | ||
|
|
079c99c47f | ||
|
|
6d2a76b609 | ||
|
|
24e0950ca2 | ||
|
|
98214ce1a4 | ||
|
|
7eed7eab36 | ||
|
|
f0fb5c01a2 | ||
|
|
a92aa3bf49 | ||
|
|
b12cc9fd49 | ||
|
|
a61c3a2636 | ||
|
|
9fd435059f | ||
|
|
3156ac9791 | ||
|
|
b946f33189 | ||
|
|
1e0b7054e6 | ||
|
|
46e04e857c | ||
|
|
4abdeaddbf | ||
|
|
029af1c376 | ||
|
|
c02f2ff4bb | ||
|
|
f74fec8a7e | ||
|
|
50f8e8891b | ||
|
|
d67b1dbd53 | ||
|
|
b0eeb7d67b | ||
|
|
2c6c75cbad | ||
|
|
241388b8a0 | ||
|
|
820b497f42 | ||
|
|
88d8435a02 | ||
|
|
f3f177f3ed | ||
|
|
bfa171cd97 | ||
|
|
19c94ce218 | ||
|
|
5e5033a0f3 | ||
|
|
411a269991 | ||
|
|
bca6aab5a5 | ||
|
|
330e2ff74e | ||
|
|
eb5848478c | ||
|
|
5bb361b1d2 | ||
|
|
0d40364089 | ||
|
|
16c4fe1f37 | ||
|
|
3070e8572d | ||
|
|
baf4d8af27 | ||
|
|
d5acf2e2a7 |
No files matched your search
+20
@@ -0,0 +1,20 @@
|
||||
language: cpp
|
||||
|
||||
env:
|
||||
matrix:
|
||||
- MONGOOSE_NO_SOCKETPAIR
|
||||
- MONGOOSE_NO_FILESYSTEM
|
||||
- MONGOOSE_NO_AUTH
|
||||
- MONGOOSE_NO_DAV
|
||||
- MONGOOSE_NO_DIRECTORY_LISTING
|
||||
- MONGOOSE_NO_LOGGING
|
||||
- MONGOOSE_NO_SSI
|
||||
- MONGOOSE_NO_DL
|
||||
- MONGOOSE_NO_WEBSOCKET
|
||||
|
||||
compiler:
|
||||
- gcc
|
||||
- clang
|
||||
|
||||
script:
|
||||
- cd test && make
|
||||
@@ -5,7 +5,7 @@ All rights reserved
|
||||
This code is dual-licensed: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License version 2 as
|
||||
published by the Free Software Foundation. For the terms of this
|
||||
license, see <http://www.gnu.org/licenses/>.
|
||||
license, see <http://www.gnu.org/licenses>.
|
||||
|
||||
You are free to use this code under the terms of the GNU General
|
||||
Public License, but WITHOUT ANY WARRANTY; without even the implied
|
||||
@@ -13,4 +13,4 @@ warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
Alternatively, you can license this code under a commercial
|
||||
license, as set out in <http://cesanta.com/products.html>.
|
||||
license, as set out in <http://cesanta.com/>.
|
||||
@@ -1,57 +1,86 @@
|
||||
# Project Mission
|
||||
# <img src="http://cesanta.com/images/mongoose_logo.png" width="64" height="64"> Mongoose Web Server
|
||||
|
||||
Project mission is to provide easy to use, powerful, embeddable web server.
|
||||
Mongoose is the most easy to use web server on the planet. A web server of choice for Web developers (PHP, Ruby, Python, etc) and Web designers.
|
||||
|
||||
# Downloads
|
||||
Mongoose is built on top of Libmongoose embedded library, which can turn
|
||||
anything into a web server in 5 minutes worth of effort and few lines of code.
|
||||
Libmongoose is used to serve Web GUI on embedded devices, implement RESTful
|
||||
services, RPC frameworks (e.g. JSON-RPC), handle telemetry data exchange, and
|
||||
perform many other tasks in various different industries including aerospace,
|
||||
manufacturing, finance, research, automotive, gaming, IT.
|
||||
|
||||
Sources, binaries and bundles are available for download at
|
||||
[mongoose downloads](http://cesanta.com/downloads.html).
|
||||
|
||||
# Overview
|
||||
* [Mailing list](http://groups.google.com/group/mongoose-users)
|
||||
* [Downloads](http://cesanta.com/mongoose.shtml)
|
||||
* [Documentation](http://cesanta.com/docs.shtml)
|
||||
|
||||
Mongoose keeps the balance between functionality and
|
||||
simplicity by carefully selected list of features:
|
||||
# Features
|
||||
|
||||
- Works on Windows, Mac, UNIX, iPhone, Android, and many other platforms
|
||||
- Scripting and database support (Lua Server Pages + Sqlite, see
|
||||
[page.lp](https://github.com/valenok/mongoose/blob/master/test/page.lp) ),
|
||||
which provides ready to go, powerful web development platform in
|
||||
one single-click executable with **no dependencies**: forget LAMP!
|
||||
- Support for CGI, SSL, SSI, Digest (MD5) authorization, Websocket, WEbDAV
|
||||
- Resumed download, URL rewrite, file blacklist, IP-based ACL, Windows service
|
||||
- Download speed limit based on client subnet or URI pattern
|
||||
- Simple and clean embedding API,
|
||||
[mongoose.h](https://github.com/valenok/mongoose/blob/master/mongoose.h).
|
||||
- Works on Windows, Mac, UNIX/Linux, iPhone, Android eCos, QNX
|
||||
and many other platforms
|
||||
- CGI, SSI, SSL, Digest auth, Websocket, WEbDAV, Resumed download,
|
||||
URL rewrite, file blacklist
|
||||
- Custom error pages, Virtual hosts, IP-based ACL, Windows service,
|
||||
HTTP/HTTPS client
|
||||
- Simple and clean
|
||||
[embedding API](https://github.com/cesanta/mongoose/blob/master/mongoose.h).
|
||||
The source is in single
|
||||
[mongoose.c](https://github.com/valenok/mongoose/blob/master/mongoose.c) file
|
||||
to make things easy. Embedding examples:
|
||||
[hello.c](https://github.com/valenok/mongoose/blob/master/examples/hello.c),
|
||||
[post.c](https://github.com/valenok/mongoose/blob/master/examples/post.c),
|
||||
[upload.c](https://github.com/valenok/mongoose/blob/master/examples/upload.c),
|
||||
[websocket.c](https://github.com/valenok/mongoose/blob/master/examples/websocket.c)
|
||||
- HTTP client capable of sending arbitrary HTTP/HTTPS requests
|
||||
- [User Manual](https://github.com/valenok/mongoose/blob/master/UserManual.md)
|
||||
[mongoose.c](https://github.com/cesanta/mongoose/blob/master/mongoose.c) file
|
||||
to make embedding easy
|
||||
- Extremely lightweight, has a core of under 40kB and tiny runtime footprint
|
||||
- Asynchronous, non-blocking core supporting single- or multi-threaded usage
|
||||
- On the market since 2004 with over 1 million cumulative downloads
|
||||
- Stable, mature and tested, has several man-years invested
|
||||
in continuous improvement and refinement
|
||||
|
||||
Note that Windows and MacOS binaries have following 3rd party software
|
||||
compiled in:
|
||||
<a href="http://wolfssl.com">WolfSSL lightweight SSL library</a>,
|
||||
<a href="http://sqlite.org">SQLite embedded database</a>,
|
||||
<a href="http://lua.org">Lua embedded scripting engine</a>.
|
||||
# Screenshots
|
||||
|
||||
Questions can be asked at
|
||||
[mongoose-users@googlegroups.com](http://groups.google.com/group/mongoose-users)
|
||||
mailing list.
|
||||
Download, double-click to start, run browser -- that's all!
|
||||
|
||||
[](http://githalytics.com/valenok/mongoose)
|
||||

|
||||

|
||||
|
||||

|
||||

|
||||
|
||||
# License
|
||||
# Acknowledgements
|
||||
|
||||
Mongoose is dual-licensed. It is available under the terms of
|
||||
[GNU GPL v.2](http://www.gnu.org/licenses/old-licenses/gpl-2.0.html) license
|
||||
license for free, or under the terms of standard commercial license provided
|
||||
by [Cesanta Software](http://cesanta.com).
|
||||
Mongoose made better thanks to the contribution of following people:
|
||||
|
||||
[Super Light Regular Expression library](https://github.com/cesanta/slre) is
|
||||
another project by Cesanta Software, developed with the same philosophy
|
||||
of functionality and simplicity.
|
||||
Arnout Vandecappelle, Benoît Amiaux, Boris Pek, Cody Hanson, Colin Leitner,
|
||||
Daniel Oaks, Eric Bakan, Erik Oomen, Filipp Kovalev, Ger Hobbelt,
|
||||
Hendrik Polczynski, Igor Okulist, Jay, Joe Mucchiello, John Safranek,
|
||||
José Miguel Gonçalves, Shueng Chuan, Katerina Blinova, Konstantin Sorokin,
|
||||
Marin Atanasov, Matt Healy, Mitch Hendrickson, Nigel Stewart, Pavel Khlebovich,
|
||||
Sebastian Reinhard, Stefan Doehla, abadc0de, nullable.type,
|
||||
T.Barmann, D.Hughes, J.C.Sloan, R.Romeo, L.E.Spencer, S.Kotay, R.M.Shorter,
|
||||
W.Mar, J.Wilander, Santa from Memphis, S.Davies, C.Beck,
|
||||
O.M.Vilhunen, C.Radik, G.Woodcock, M.Szczepkowski,
|
||||
Eternal Lands Dev Team, T.Tollet, C.Tangerino, G.Karsai, A.Bourgett,
|
||||
C.Blakemore, D.Fonaryov, T.Andrle, O.IJsselmuiden, R.Womack, M.Tomlinson,
|
||||
A.Slåttå, L.Farrell, J.D.P.Ballestero, V.Albaev, B.Harker, T.Scheffel, H.Klein,
|
||||
R.Merit, T.Bennett, H.Solis, A.Zincenko, M.S., S.Krul, K.Cooke, S.McCallum,
|
||||
F.Morenius, and 10 others.
|
||||
|
||||
# Licensing
|
||||
|
||||
Mongoose is released under commercial and
|
||||
[GNU GPL v.2](http://www.gnu.org/licenses/old-licenses/gpl-2.0.html) open
|
||||
source licenses. The GPLv2 open source License does not generally permit
|
||||
incorporating this software into non-open source programs.
|
||||
For those customers who do not wish to comply with the GPLv2 open
|
||||
source license requirements,
|
||||
[Cesanta Software](http://cesanta.com) offers a full,
|
||||
royalty-free commercial license and professional support
|
||||
without any of the GPL restrictions.
|
||||
|
||||
# Other products by Cesanta Software: simple and effective
|
||||
|
||||
- [SSL Wrapper](https://github.com/cesanta/ssl_wrapper) - application to
|
||||
secure network communications
|
||||
- [Frozen](https://github.com/cesanta/frozen) - JSON parser and generator
|
||||
- [SLRE](https://github.com/cesanta/slre) - Super Light Regular Expression
|
||||
library
|
||||
- [Net Skeleton](https://github.com/cesanta/net_skeleton) - framework for
|
||||
building network applications
|
||||
- [SLDR](https://github.com/cesanta/sldr) - Super Light DNS Resolver
|
||||
-547
@@ -1,547 +0,0 @@
|
||||
# Overview
|
||||
|
||||
Mongoose is small and easy to use web server. It is self-contained, and does
|
||||
not require any external software to run.
|
||||
|
||||
On Windows, mongoose iconifies itself to the system tray icon when started.
|
||||
Right-click on the icon pops up a menu, where it is possible to stop
|
||||
mongoose, or configure it, or install it as Windows service. The easiest way
|
||||
to share a folder on Windows is to copy `mongoose.exe` to a folder,
|
||||
double-click the exe, and launch a browser at
|
||||
[http://localhost:8080](http://localhost:8080). Note that 'localhost' should
|
||||
be changed to a machine's name if a folder is accessed from other computer.
|
||||
|
||||
On UNIX and Mac, mongoose is a command line utility. Running `mongoose` in
|
||||
terminal, optionally followed by configuration parameters
|
||||
(`mongoose [OPTIONS]`) or configuration file name
|
||||
(`mongoose [config_file_name]`) starts the
|
||||
web server. Mongoose does not detach from terminal. Pressing `Ctrl-C` keys
|
||||
would stop the server.
|
||||
|
||||
When started, mongoose first searches for the configuration file.
|
||||
If configuration file is specified explicitly in the command line, i.e.
|
||||
`mongoose path_to_config_file`, then specified configuration file is used.
|
||||
Otherwise, mongoose would search for file `mongoose.conf` in the same directory
|
||||
where binary is located, and use it. Configuration file can be absent.
|
||||
|
||||
|
||||
Configuration file is a sequence of lines, each line containing
|
||||
command line argument name and it's value. Empty lines, and lines beginning
|
||||
with `#`, are ignored. Here is the example of `mongoose.conf` file:
|
||||
|
||||
document_root c:\www
|
||||
listening_ports 8080,8043s
|
||||
ssl_certificate c:\mongoose\ssl_cert.pem
|
||||
|
||||
When configuration file is processed, mongoose process command line arguments,
|
||||
if they are specified. Command line arguments therefore can override
|
||||
configuration file settings. Command line arguments must start with `-`.
|
||||
For example, if `mongoose.conf` has line
|
||||
`document_root /var/www`, and mongoose has been started as
|
||||
`mongoose -document_root /etc`, then `/etc` directory will be served as
|
||||
document root, because command line options take priority over
|
||||
configuration file. Configuration options section below provide a good
|
||||
overview of Mongoose features.
|
||||
|
||||
Note that configuration options on the command line must start with `-`,
|
||||
but their names are the same as in the config file. All option names are
|
||||
listed in the next section. Thus, the following two setups are equivalent:
|
||||
|
||||
# Using command line arguments
|
||||
$ mongoose -listening_ports 1234 -document_root /var/www
|
||||
|
||||
# Using config file
|
||||
$ cat mongoose.conf
|
||||
listening_ports 1234
|
||||
document_root /var/www
|
||||
$ mongoose
|
||||
|
||||
Mongoose can also be used to modify `.htpasswd` passwords file:
|
||||
|
||||
mongoose -A <htpasswd_file> <realm> <user> <passwd>
|
||||
|
||||
Unlike other web servers, mongoose does not require CGI scripts be located in
|
||||
a special directory. CGI scripts can be anywhere. CGI (and SSI) files are
|
||||
recognized by the file name pattern. Mongoose uses shell-like glob
|
||||
patterns. Pattern match starts at the beginning of the string, so essentially
|
||||
patterns are prefix patterns. Syntax is as follows:
|
||||
|
||||
** Matches everything
|
||||
* Matches everything but slash character, '/'
|
||||
? Matches any character
|
||||
$ Matches the end of the string
|
||||
| Matches if pattern on the left side or the right side matches.
|
||||
|
||||
All other characters in the pattern match themselves. Examples:
|
||||
|
||||
**.cgi$ Any string that ends with .cgi
|
||||
/foo Any string that begins with /foo
|
||||
**a$|**b$ Any string that ends with a or b
|
||||
|
||||
# Configuration Options
|
||||
|
||||
Below is a list of configuration options Mongoose understands. Every option
|
||||
is followed by it's default value. If default value is not present, then
|
||||
it is empty.
|
||||
|
||||
### cgi_pattern `**.cgi$|**.pl$|**.php$`
|
||||
All files that match `cgi_pattern` are treated as CGI files. Default pattern
|
||||
allows CGI files be anywhere. To restrict CGIs to a certain directory,
|
||||
use `/path/to/cgi-bin/**.cgi` as pattern. Note that full file path is
|
||||
matched against the pattern, not the URI.
|
||||
|
||||
### cgi_environment
|
||||
Extra environment variables to be passed to the CGI script in
|
||||
addition to standard ones. The list must be comma-separated list
|
||||
of name=value pairs, like this: `VARIABLE1=VALUE1,VARIABLE2=VALUE2`.
|
||||
|
||||
### put\_delete\_auth\_file
|
||||
Passwords file for PUT and DELETE requests. Without it, PUT and DELETE requests
|
||||
will fail.
|
||||
|
||||
### cgi_interpreter
|
||||
Path to an executable to use as CGI interpreter for __all__ CGI scripts
|
||||
regardless script extension. If this option is not set (which is a default),
|
||||
Mongoose looks at first line of a CGI script,
|
||||
[shebang line](http://en.wikipedia.org/wiki/Shebang_(Unix\)), for an interpreter.
|
||||
|
||||
For example, if both PHP and perl CGIs are used, then
|
||||
`#!/path/to/php-cgi.exe` and `#!/path/to/perl.exe` must be first lines of the
|
||||
respective CGI scripts. Note that paths should be either full file paths,
|
||||
or file paths relative to the current working directory of mongoose server.
|
||||
If mongoose is started by mouse double-click on Windows, current working
|
||||
directory is a directory where mongoose executable is located.
|
||||
|
||||
If all CGIs use the same interpreter, for example they are all PHP, then
|
||||
`cgi_interpreter` can be set to the path to `php-cgi.exe` executable and
|
||||
shebang line in the CGI scripts can be omitted.
|
||||
Note that PHP scripts must use `php-cgi.exe` executable, not `php.exe`.
|
||||
|
||||
### protect_uri
|
||||
Comma separated list of URI=PATH pairs, specifying that given
|
||||
URIs must be protected with respected password files. Paths must be full
|
||||
file paths.
|
||||
|
||||
### authentication_domain `mydomain.com`
|
||||
Authorization realm used in `.htpasswd` authorization.
|
||||
|
||||
### ssi_pattern `**.shtml$|**.shtm$`
|
||||
All files that match `ssi_pattern` are treated as SSI.
|
||||
|
||||
Server Side Includes (SSI) is a simple interpreted server-side scripting
|
||||
language which is most commonly used to include the contents of a file into
|
||||
a web page. It can be useful when it is desirable to include a common piece
|
||||
of code throughout a website, for example, headers and footers.
|
||||
|
||||
In order for a webpage to recognize an SSI-enabled HTML file, the filename
|
||||
should end with a special extension, by default the extension should be
|
||||
either `.shtml` or `.shtm`.
|
||||
|
||||
Unknown SSI directives are silently ignored by mongoose. Currently, two SSI
|
||||
directives are supported, `<!--#include ...>` and
|
||||
`<!--#exec "command">`. Note that `<!--#include ...>` directive supports
|
||||
three path specifications:
|
||||
|
||||
<!--#include virtual="path"> Path is relative to web server root
|
||||
<!--#include abspath="path"> Path is absolute or relative to
|
||||
web server working dir
|
||||
<!--#include file="path">, Path is relative to current document
|
||||
<!--#include "path">
|
||||
|
||||
The `include` directive may be used to include the contents of a file or the
|
||||
result of running a CGI script. The `exec` directive is used to execute a
|
||||
command on a server, and show command's output. Example:
|
||||
|
||||
<!--#exec "ls -l" -->
|
||||
|
||||
For more information on Server Side Includes, take a look at the Wikipedia:
|
||||
[Server Side Includes](http://en.wikipedia.org/wiki/Server_Side_Includes)
|
||||
|
||||
### throttle
|
||||
Limit download speed for clients. `throttle` is a comma-separated
|
||||
list of key=value pairs, where key could be:
|
||||
|
||||
* limit speed for all connections
|
||||
x.x.x.x/mask limit speed for specified subnet
|
||||
uri_prefix_pattern limit speed for given URIs
|
||||
|
||||
The value is a floating-point number of bytes per second, optionally
|
||||
followed by a `k` or `m` character, meaning kilobytes and
|
||||
megabytes respectively. A limit of 0 means unlimited rate. The
|
||||
last matching rule wins. Examples:
|
||||
|
||||
*=1k,10.0.0.0/8=0 limit all accesses to 1 kilobyte per second,
|
||||
but give connections from 10.0.0.0/8 subnet
|
||||
unlimited speed
|
||||
|
||||
/downloads/=5k limit accesses to all URIs in `/downloads/` to
|
||||
5 kilobytes per secods. All other accesses are unlimited
|
||||
|
||||
### access\_log\_file
|
||||
Path to a file for access logs. Either full path, or relative to current
|
||||
working directory. If absent (default), then accesses are not logged.
|
||||
|
||||
### error\_log\_file
|
||||
Path to a file for error logs. Either full path, or relative to current
|
||||
working directory. If absent (default), then errors are not logged.
|
||||
|
||||
### enable\_directory\_listing `yes`
|
||||
Enable directory listing, either `yes` or `no`.
|
||||
|
||||
### enable\_keep\_alive `no`
|
||||
Enable connection keep alive, either `yes` or `no`.
|
||||
|
||||
Experimental feature. Allows clients to reuse TCP connection for
|
||||
subsequent HTTP requests, which improves performance.
|
||||
For this to work when using request handlers it's important to add the correct
|
||||
Content-Length HTTP header for each request. If this is forgotten the client
|
||||
will time out.
|
||||
|
||||
|
||||
### global\_auth\_file
|
||||
Path to a global passwords file, either full path or relative to the current
|
||||
working directory. If set, per-directory `.htpasswd` files are ignored,
|
||||
and all requests are authorised against that file.
|
||||
|
||||
The file has to include the realm set through `authentication_domain` and the password in digest format:
|
||||
|
||||
user:realm:digest
|
||||
test:test.com:ce0220efc2dd2fad6185e1f1af5a4327
|
||||
|
||||
(e.g. use [this generator](http://www.askapache.com/online-tools/htpasswd-generator))
|
||||
|
||||
### index_files `index.html,index.htm,index.cgi,index.shtml,index.php`
|
||||
Comma-separated list of files to be treated as directory index
|
||||
files.
|
||||
|
||||
### access\_control\_list
|
||||
An Access Control List (ACL) allows restrictions to be put on the list of IP
|
||||
addresses which have access to the web server. In the case of the Mongoose
|
||||
web server, the ACL is a comma separated list of IP subnets, where each
|
||||
subnet is prepended by either a `-` or a `+` sign. A plus sign means allow,
|
||||
where a minus sign means deny. If a subnet mask is omitted, such as `-1.2.3.4`,
|
||||
this means to deny only that single IP address.
|
||||
|
||||
Subnet masks may vary from 0 to 32, inclusive. The default setting is to allow
|
||||
all accesses. On each request the full list is traversed, and
|
||||
the last match wins. Examples:
|
||||
|
||||
-0.0.0.0/0,+192.168/16 deny all acccesses, only allow 192.168/16 subnet
|
||||
|
||||
To learn more about subnet masks, see the
|
||||
[Wikipedia page on Subnetwork](http://en.wikipedia.org/wiki/Subnetwork)
|
||||
|
||||
### extra\_mime\_types
|
||||
Extra mime types to recognize, in form `extension1=type1,exten-
|
||||
sion2=type2,...`. Extension must include dot. Example:
|
||||
`.cpp=plain/text,.java=plain/text`
|
||||
|
||||
### listening_ports `8080`
|
||||
Comma-separated list of ports to listen on. If the port is SSL, a
|
||||
letter `s` must be appeneded, for example, `80,443s` will open
|
||||
port 80 and port 443, and connections on port 443 will be SSL-ed.
|
||||
For non-SSL ports, it is allowed to append letter `r`, meaning 'redirect'.
|
||||
Redirect ports will redirect all their traffic to the first configured
|
||||
SSL port. For example, if `listening_ports` is `80r,443s`, then all
|
||||
HTTP traffic coming at port 80 will be redirected to HTTPS port 443.
|
||||
|
||||
It is possible to specify an IP address to bind to. In this case,
|
||||
an IP address and a colon must be prepended to the port number.
|
||||
For example, to bind to a loopback interface on port 80 and to
|
||||
all interfaces on HTTPS port 443, use `127.0.0.1:80,443s`.
|
||||
|
||||
### document_root `.`
|
||||
A directory to serve. By default, currect directory is served. Current
|
||||
directory is commonly referenced as dot (`.`).
|
||||
|
||||
### ssl_certificate
|
||||
Path to SSL certificate file. This option is only required when at least one
|
||||
of the `listening_ports` is SSL. The file must be in PEM format,
|
||||
and it must have both private key and certificate, see for example
|
||||
[ssl_cert.pem](https://github.com/valenok/mongoose/blob/master/build/ssl_cert.pem)
|
||||
|
||||
### num_threads `50`
|
||||
Number of worker threads. Mongoose handles each incoming connection in a
|
||||
separate thread. Therefore, the value of this option is effectively a number
|
||||
of concurrent HTTP connections Mongoose can handle.
|
||||
|
||||
### run\_as\_user
|
||||
Switch to given user credentials after startup. Usually, this option is
|
||||
required when mongoose needs to bind on privileged port on UNIX. To do
|
||||
that, mongoose needs to be started as root. But running as root is a bad idea,
|
||||
therefore this option can be used to drop privileges. Example:
|
||||
|
||||
mongoose -listening_ports 80 -run_as_user nobody
|
||||
|
||||
### request\_timeout\_ms `30000`
|
||||
Timeout for network read and network write operations, in milliseconds.
|
||||
If client intends to keep long-running connection, either increase this value
|
||||
or use keep-alive messages.
|
||||
|
||||
|
||||
### url\_rewrite\_patterns
|
||||
Comma-separated list of URL rewrites in the form of
|
||||
`uri_pattern=file_or_directory_path`. When Mongoose receives the request,
|
||||
it constructs the file name to show by combining `document_root` and the URI.
|
||||
However, if the rewrite option is used and `uri_pattern` matches the
|
||||
requested URI, then `document_root` is ignored. Insted,
|
||||
`file_or_directory_path` is used, which should be a full path name or
|
||||
a path relative to the web server's current working directory. Note that
|
||||
`uri_pattern`, as all mongoose patterns, is a prefix pattern.
|
||||
|
||||
This makes it possible to serve many directories outside from `document_root`,
|
||||
redirect all requests to scripts, and do other tricky things. For example,
|
||||
to redirect all accesses to `.doc` files to a special script, do:
|
||||
|
||||
mongoose -url_rewrite_patterns **.doc$=/path/to/cgi-bin/handle_doc.cgi
|
||||
|
||||
Or, to imitate user home directories support, do:
|
||||
|
||||
mongoose -url_rewrite_patterns /~joe/=/home/joe/,/~bill=/home/bill/
|
||||
|
||||
### hide\_files\_patterns
|
||||
A pattern for the files to hide. Files that match the pattern will not
|
||||
show up in directory listing and return `404 Not Found` if requested. Pattern
|
||||
must be for a file name only, not including directory name. Example:
|
||||
|
||||
mongoose -hide_files_patterns secret.txt|even_more_secret.txt
|
||||
|
||||
# Lua Server Pages
|
||||
Pre-built Windows and Mac mongoose binaries have built-in Lua Server Pages
|
||||
support. That means it is possible to write PHP-like scripts with mongoose,
|
||||
using Lua programming language instead of PHP. Lua is known
|
||||
for it's speed and small size. Mongoose uses Lua version 5.2.1, the
|
||||
documentation for it can be found at
|
||||
[Lua 5.2 reference manual](http://www.lua.org/manual/5.2/).
|
||||
|
||||
To create a Lua Page, make sure a file has `.lp` extension. For example,
|
||||
let's say it is going to be `my_page.lp`. The contents of the file, just like
|
||||
with PHP, is HTML with embedded Lua code. Lua code must be enclosed in
|
||||
`<? ?>` blocks, and can appear anywhere on the page. For example, to
|
||||
print current weekday name, one can write:
|
||||
|
||||
<p>
|
||||
<span>Today is:</span>
|
||||
<? mg.write(os.date("%A")) ?>
|
||||
</p>
|
||||
|
||||
Note that this example uses function `mg.write()`, which prints data to the
|
||||
web page. Using function `mg.write()` is the way to generate web content from
|
||||
inside Lua code. In addition to `mg.write()`, all standard library functions
|
||||
are accessible from the Lua code (please check reference manual for details),
|
||||
and also information about the request is available in `mg.request_info` object,
|
||||
like request method, all headers, etcetera. Please refer to
|
||||
`struct mg_request_info` definition in
|
||||
[mongoose.h](https://github.com/valenok/mongoose/blob/master/mongoose.h)
|
||||
to see what kind of information is present in `mg.request_info` object. Also,
|
||||
[page.lp](https://github.com/valenok/mongoose/blob/master/test/page.lp) and
|
||||
[prime_numbers.lp](https://github.com/valenok/mongoose/blob/master/examples/lua/prime_numbers.lp)
|
||||
contains some example code that uses `request_info` and other functions(form submitting for example).
|
||||
|
||||
Mongoose exports the following to the Lua server page:
|
||||
|
||||
mg.read() -- reads a chunk from POST data, returns it as a string
|
||||
mg.write(str) -- writes string to the client
|
||||
mg.include(path) -- sources another Lua file
|
||||
mg.redirect(uri) -- internal redirect to a given URI
|
||||
mg.onerror(msg) -- error handler, can be overridden
|
||||
mg.version -- a string that holds Mongoose version
|
||||
mg.request_info -- a table with request information
|
||||
|
||||
-- Connect to the remote TCP server. This function is an implementation
|
||||
-- of simple socket interface. It returns a socket object with three
|
||||
-- methods: send, recv, close, which are synchronous (blocking).
|
||||
-- connect() throws an exception on connection error.
|
||||
connect(host, port, use_ssl)
|
||||
|
||||
-- Example of using connect() interface:
|
||||
local host = 'code.google.com' -- IP address or domain name
|
||||
local ok, sock = pcall(connect, host, 80, 1)
|
||||
if ok then
|
||||
sock:send('GET /p/mongoose/ HTTP/1.0\r\n' ..
|
||||
'Host: ' .. host .. '\r\n\r\n')
|
||||
local reply = sock:recv()
|
||||
sock:close()
|
||||
-- reply now contains the web page https://code.google.com/p/mongoose
|
||||
end
|
||||
|
||||
|
||||
**IMPORTANT: Mongoose does not send HTTP headers for Lua pages. Therefore,
|
||||
every Lua Page must begin with HTTP reply line and headers**, like this:
|
||||
|
||||
<? print('HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n') ?>
|
||||
<html><body>
|
||||
... the rest of the web page ...
|
||||
|
||||
To serve Lua Page, mongoose creates Lua context. That context is used for
|
||||
all Lua blocks within the page. That means, all Lua blocks on the same page
|
||||
share the same context. If one block defines a variable, for example, that
|
||||
variable is visible in the block that follows.
|
||||
|
||||
# Common Problems
|
||||
- PHP doesn't work - getting empty page, or 'File not found' error. The
|
||||
reason for that is wrong paths to the interpreter. Remember that with PHP,
|
||||
correct interpreter is `php-cgi.exe` (`php-cgi` on UNIX). Solution: specify
|
||||
full path to the PHP interpreter, e.g.:
|
||||
`mongoose -cgi_interpreter /full/path/to/php-cgi`
|
||||
|
||||
- Mongoose fails to start. If Mongoose exits immediately when run, this
|
||||
usually indicates a syntax error in the configuration file
|
||||
(named `mongoose.conf` by default) or the command-line arguments.
|
||||
Syntax checking is omitted from Mongoose to keep its size low. However,
|
||||
the Manual should be of help. Note: the syntax changes from time to time,
|
||||
so updating the config file might be necessary after executable update.
|
||||
|
||||
- Embedding with OpenSSL on Windows might fail because of calling convention.
|
||||
To force Mongoose to use `__stdcall` convention, add `/Gz` compilation
|
||||
flag in Visual Studio compiler.
|
||||
|
||||
# Embedding
|
||||
Embedding Mongoose is easy. Copy
|
||||
[mongoose.c](https://github.com/valenok/mongoose/blob/master/mongoose.c) and
|
||||
[mongoose.h](https://github.com/valenok/mongoose/blob/master/mongoose.h)
|
||||
to your application's source tree and include them in the build. For
|
||||
example, your application's code lives in C file `my_app.c`, then on UNIX
|
||||
this command embeds Mongoose:
|
||||
|
||||
$ ls
|
||||
my_app.c mongoose.c mongoose.h
|
||||
$ gcc my_app.c mongoose.c -o my_app -ldl -pthread
|
||||
|
||||
Somewhere in the application code, call `mg_start()` to start the server.
|
||||
Pass configuration options and event handlers to `mg_start()`.
|
||||
Mongoose then calls handlers when certain events happen.
|
||||
For example, when new request arrives, Mongoose calls `begin_request`
|
||||
handler function to let user handle the request. In the handler, user code
|
||||
can get all information about the request -- parsed headers, etcetera.
|
||||
|
||||
Mongoose API is logically divided in three categories: server setup/shutdown
|
||||
functions, functions to be used by user-written event handlers, and
|
||||
convenience utility functions.
|
||||
|
||||
### Starting and stopping embedded web server
|
||||
To start the embedded web server, call `mg_start()`. To stop it, call
|
||||
`mg_stop()`.
|
||||
|
||||
// This structure needs to be passed to mg_start(), to let mongoose know
|
||||
// which callbacks to invoke. For detailed description, see
|
||||
// https://github.com/valenok/mongoose/blob/master/UserManual.md
|
||||
struct mg_callbacks {
|
||||
int (*begin_request)(struct mg_connection *);
|
||||
void (*end_request)(const struct mg_connection *, int reply_status_code);
|
||||
int (*log_message)(const struct mg_connection *, const char *message);
|
||||
int (*init_ssl)(void *ssl_context);
|
||||
int (*websocket_connect)(const struct mg_connection *);
|
||||
void (*websocket_ready)(struct mg_connection *);
|
||||
int (*websocket_data)(struct mg_connection *);
|
||||
const char * (*open_file)(const struct mg_connection *,
|
||||
const char *path, size_t *data_len);
|
||||
void (*init_lua)(struct mg_connection *, void *lua_context);
|
||||
void (*upload)(struct mg_connection *, const char *file_name);
|
||||
int (*http_error)(struct mg_connection *, int status);
|
||||
};
|
||||
|
||||
[hello.c](https://github.com/valenok/mongoose/blob/master/examples/hello.c)
|
||||
provides a minimalistic example.
|
||||
|
||||
Common pattern is to implement `begin_request` callback, and serve static files
|
||||
from memory, and/or construct dynamic replies on the fly. Here is
|
||||
my [embed.c](https://gist.github.com/valenok/4714740) gist
|
||||
that shows how to easily any data can be embedded
|
||||
directly into the executable. If such data needs to be encrypted, then
|
||||
encrypted database or encryption dongles would be a better choice.
|
||||
|
||||
# Build on Android
|
||||
|
||||
This is a small guide to help you run mongoose on Android. Currently it is
|
||||
tested on the HTC Wildfire. If you have managed to run it on other devices
|
||||
as well, please comment or drop an email in the mailing list.
|
||||
Note : You dont need root access to run mongoose on Android.
|
||||
|
||||
- Download the source from the Downloads page.
|
||||
- Download the Android NDK from [http://developer.android.com/tools/sdk/ndk/index.html](http://developer.android.com/tools/sdk/ndk/index.html)
|
||||
- Run `/path-to-ndk/ndk-build -C /path-to-mongoose/build`
|
||||
That should generate mongoose/lib/armeabi/mongoose
|
||||
- Using the adb tool (you need to have Android SDK installed for that),
|
||||
push the generated mongoose binary to `/data/local` folder on device.
|
||||
- From adb shell, navigate to `/data/local` and execute `./mongoose`.
|
||||
- To test if the server is running fine, visit your web-browser and
|
||||
navigate to `http://127.0.0.1:8080` You should see the `Index of /` page.
|
||||
|
||||

|
||||
|
||||
|
||||
Notes:
|
||||
|
||||
- `jni` stands for Java Native Interface. Read up on Android NDK if you want
|
||||
to know how to interact with the native C functions of mongoose in Android
|
||||
Java applications.
|
||||
- TODO: A Java application that interacts with the native binary or a
|
||||
shared library.
|
||||
|
||||
# Mongoose internals
|
||||
|
||||
Mongoose is multithreaded web server. `mg_start()` function allocates
|
||||
web server context (`struct mg_context`), which holds all information
|
||||
about web server instance:
|
||||
|
||||
- configuration options. Note that mongoose makes internal copies of
|
||||
passed options.
|
||||
- SSL context, if any
|
||||
- user-defined callbacks
|
||||
- opened listening sockets
|
||||
- a queue for accepted sockets
|
||||
- mutexes and condition variables for inter-thread synchronization
|
||||
|
||||
When `mg_start()` returns, all initialization is quaranteed to be complete
|
||||
(e.g. listening ports are opened, SSL is initialized, etc). `mg_start()` starts
|
||||
two threads: a master thread, that accepts new connections, and several
|
||||
worker threads, that process accepted connections. The number of worker threads
|
||||
is configurable via `num_threads` configuration option. That number puts a
|
||||
limit on number of simultaneous requests that can be handled by mongoose.
|
||||
|
||||
When master thread accepts new connection, a new accepted socket (described by
|
||||
`struct socket`) it placed into the accepted sockets queue,
|
||||
which has size of 20 (see [code](https://github.com/valenok/mongoose/blob/3892e0199e6ca9613b160535d9d107ede09daa43/mongoose.c#L486)). Any idle worker thread
|
||||
can grab accepted sockets from that queue. If all worker threads are busy,
|
||||
master thread can accept and queue up to 20 more TCP connections,
|
||||
filling up the queue.
|
||||
In the attempt to queue next accepted connection, master thread blocks
|
||||
until there is space in a queue. When master thread is blocked on a
|
||||
full queue, TCP layer in OS can also queue incoming connection.
|
||||
The number is limited by the `listen()` call parameter on listening socket,
|
||||
which is `SOMAXCONN` in case of Mongoose, and depends on a platform.
|
||||
|
||||
Worker threads are running in an infinite loop, which in simplified form
|
||||
looks something like this:
|
||||
|
||||
static void *worker_thread() {
|
||||
while (consume_socket()) {
|
||||
process_new_connection();
|
||||
}
|
||||
}
|
||||
|
||||
Function `consume_socket()` gets new accepted socket from the mongoose socket
|
||||
queue, atomically removing it from the queue. If the queue is empty,
|
||||
`consume_socket()` blocks and waits until new sockets are placed in a queue
|
||||
by the master thread. `process_new_connection()` actually processes the
|
||||
connection, i.e. reads the request, parses it, and performs appropriate action
|
||||
depending on a parsed request.
|
||||
|
||||
Master thread uses `poll()` and `accept()` to accept new connections on
|
||||
listening sockets. `poll()` is used to avoid `FD_SETSIZE` limitation of
|
||||
`select()`. Since there are only a few listening sockets, there is no reason
|
||||
to use hi-performance alternatives like `epoll()` or `kqueue()`. Worker
|
||||
threads use blocking IO on accepted sockets for reading and writing data.
|
||||
All accepted sockets have `SO_RCVTIMEO` and `SO_SNDTIMEO` socket options set
|
||||
(controlled by `request_timeout_ms` mongoose option, 30 seconds default) which
|
||||
specify read/write timeout on client connection.
|
||||
|
||||
# Other Resources
|
||||
- Presentation made by Arnout Vandecappelle at FOSDEM 2011 on 2011-02-06
|
||||
in Brussels, Belgium, called
|
||||
"Creating secure web based user interfaces for Embedded Devices"
|
||||
([pdf](http://mind.be/content/110206_Web-ui.pdf) |
|
||||
[odp](http://mind.be/content/110206_Web-ui.odp))
|
||||
- Linux Journal article by Michel J.Hammel, 2010-04-01, called
|
||||
[Mongoose: an Embeddable Web Server in C](http://www.linuxjournal.com/article/10680)
|
||||
@@ -0,0 +1,12 @@
|
||||
LOCAL_PATH := $(call my-dir)/../..
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
# To build with lua support, uncomment two lines below:
|
||||
#LUA_SOURCES := build/lua_5.2.1.c build/sqlite3.c build/lsqlite3.c
|
||||
#LUA_FLAGS := -I$(LOCAL_PATH)/build -DTHREADSAFE=1 -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_FTS3_PARENTHESIS -DUSE_LUA -DUSE_LUA_SQLITE3 -DLUA_COMPAT_ALL -D"getlocaledecpoint() ='.'"
|
||||
|
||||
LOCAL_CFLAGS := -std=c99 -O2 -W -Wall -pthread -pipe $(LUA_FLAGS) $(COPT)
|
||||
LOCAL_MODULE := mongoose
|
||||
LOCAL_SRC_FILES := examples/server.c mongoose.c $(LUA_SOURCES)
|
||||
|
||||
include $(BUILD_EXECUTABLE)
|
||||
@@ -1,20 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleExecutable</key> <string>Mongoose</string>
|
||||
<key>CFBundlePackageType</key> <string>APPL</string>
|
||||
<key>CFBundleTypeRole</key> <string>None</string>
|
||||
<key>CFBundleIconFiles</key> <array>
|
||||
<string>mongoose_16x16.png</string>
|
||||
<string>mongoose_22x22.png</string>
|
||||
<string>mongoose_32x32.png</string>
|
||||
<string>mongoose_64x64.png</string>
|
||||
</array>
|
||||
<key>LSUIElement</key> <true/>
|
||||
<key>RunAtLoad</key> <true/>
|
||||
<key>Label</key> <string>com.kolkin.mongoose</string>
|
||||
<key>ProgramArguments</key> <array> </array>
|
||||
<key>KeepAlive</key> <true/>
|
||||
</dict>
|
||||
</plist>
|
||||
-218
@@ -1,218 +0,0 @@
|
||||
# This Makefile is part of Mongoose web server project,
|
||||
# https://github.com/valenok/mongoose
|
||||
#
|
||||
# This Makefile is GNU make compatible. You can get GNU Make from
|
||||
# http://gnuwin32.sourceforge.net/packages/make.htm
|
||||
#
|
||||
# Example custom build:
|
||||
# COPT="-g -O0 -DNO_SSL_DL -DUSE_LUA -llua -lcrypto -lssl" make linux
|
||||
#
|
||||
# Flags are:
|
||||
# -DHAVE_MD5 - use system md5 library (-2kb)
|
||||
# -DNDEBUG - strip off all debug code (-5kb)
|
||||
# -DDEBUG - build debug version (very noisy) (+7kb)
|
||||
# -DNO_CGI - disable CGI support (-5kb)
|
||||
# -DNO_SSL - disable SSL functionality (-2kb)
|
||||
# -DNO_SSL_DL - link against system libssl library (-1kb)
|
||||
# -DCONFIG_FILE=\"file\" - use `file' as the default config file
|
||||
# -DSSL_LIB=\"libssl.so.<version>\" - use system versioned SSL shared object
|
||||
# -DCRYPTO_LIB=\"libcrypto.so.<version>\" - use system versioned CRYPTO so
|
||||
# -DUSE_LUA - embed Lua in Mongoose (+100kb)
|
||||
|
||||
PROG = mongoose
|
||||
CFLAGS = -std=c99 -O2 -W -Wall -pedantic -pthread -pipe -I.. $(COPT)
|
||||
|
||||
# To build with Lua, download and unzip Lua 5.2.1 source code into the
|
||||
# mongoose directory, and then add $(LUA_SOURCES) to CFLAGS
|
||||
LUA = ../lua-5.2.1/src
|
||||
LUA_FLAGS = -DLUA_COMPAT_ALL
|
||||
LUA_SOURCES = $(LUA)/lapi.c $(LUA)/lcode.c $(LUA)/lctype.c \
|
||||
$(LUA)/ldebug.c $(LUA)/ldo.c $(LUA)/ldump.c \
|
||||
$(LUA)/lfunc.c $(LUA)/lgc.c $(LUA)/llex.c \
|
||||
$(LUA)/lmem.c $(LUA)/lobject.c $(LUA)/lopcodes.c \
|
||||
$(LUA)/lparser.c $(LUA)/lstate.c $(LUA)/lstring.c \
|
||||
$(LUA)/ltable.c $(LUA)/ltm.c $(LUA)/lundump.c \
|
||||
$(LUA)/lvm.c $(LUA)/lzio.c $(LUA)/lauxlib.c \
|
||||
$(LUA)/lbaselib.c $(LUA)/lbitlib.c $(LUA)/lcorolib.c \
|
||||
$(LUA)/ldblib.c $(LUA)/liolib.c $(LUA)/lmathlib.c \
|
||||
$(LUA)/loslib.c $(LUA)/lstrlib.c $(LUA)/ltablib.c \
|
||||
$(LUA)/loadlib.c $(LUA)/linit.c
|
||||
LUA_HEADERS = $(LUA)/llimits.h $(LUA)/lobject.h $(LUA)/lapi.h $(LUA)/lzio.h \
|
||||
$(LUA)/ldo.h $(LUA)/ltm.h $(LUA)/lstate.h $(LUA)/lgc.h \
|
||||
$(LUA)/lvm.h $(LUA)/ltable.h $(LUA)/lstring.h $(LUA)/lfunc.h \
|
||||
$(LUA)/lundump.h $(LUA)/ldebug.h $(LUA)/lopcodes.h $(LUA)/llex.h \
|
||||
$(LUA)/lparser.h $(LUA)/lcode.h $(LUA)/lmem.h $(LUA)/lctype.h
|
||||
LUA_WINOBJS = $(LUA_SOURCES:%.c=%.obj)
|
||||
|
||||
ifneq ($(OS), Windows_NT)
|
||||
LUA_FLAGS += -DLUA_USE_DLOPEN
|
||||
endif
|
||||
|
||||
lua_5.2.1.c: lua_5.2.1.h
|
||||
(echo '#define LUA_CORE' ; \
|
||||
echo '#define LUA_LIB' ; \
|
||||
echo '#define lobject_c' ; \
|
||||
echo '#define lua_c' ; \
|
||||
echo '#define ltable_c' ; \
|
||||
echo '#include "lua_5.2.1.h"' ; \
|
||||
cat $(LUA_HEADERS) $(LUA_SOURCES) | sed '/^#include "/d') > $@
|
||||
|
||||
lua_5.2.1.h:
|
||||
cat $(LUA)/luaconf.h $(LUA)/lua.h $(LUA)/lauxlib.h $(LUA)/lualib.h | \
|
||||
sed '/^#include "/d' > $@
|
||||
|
||||
# Stock windows binary builds with Lua and YASSL library.
|
||||
YASSL = ../../cyassl-2.4.6
|
||||
YASSL_FLAGS = -I $(YASSL) -I $(YASSL)/cyassl \
|
||||
-D _LIB -D OPENSSL_EXTRA -D HAVE_ERRNO_H \
|
||||
-D HAVE_GETHOSTBYNAME -D HAVE_INET_NTOA -D HAVE_LIMITS_H \
|
||||
-D HAVE_MEMSET -D HAVE_SOCKET -D HAVE_STDDEF_H -D HAVE_STDLIB_H \
|
||||
-D HAVE_STRING_H -D HAVE_SYS_STAT_H -D HAVE_SYS_TYPES_H
|
||||
YASSL_SOURCES = \
|
||||
$(YASSL)/src/internal.c $(YASSL)/src/io.c $(YASSL)/src/keys.c \
|
||||
$(YASSL)/src/ssl.c $(YASSL)/src/tls.c $(YASSL)/ctaocrypt/src/hmac.c \
|
||||
$(YASSL)/ctaocrypt/src/random.c $(YASSL)/ctaocrypt/src/sha.c \
|
||||
$(YASSL)/ctaocrypt/src/sha256.c $(YASSL)/ctaocrypt/src/logging.c \
|
||||
$(YASSL)/ctaocrypt/src/error.c $(YASSL)/ctaocrypt/src/rsa.c \
|
||||
$(YASSL)/ctaocrypt/src/des3.c $(YASSL)/ctaocrypt/src/asn.c \
|
||||
$(YASSL)/ctaocrypt/src/coding.c $(YASSL)/ctaocrypt/src/arc4.c \
|
||||
$(YASSL)/ctaocrypt/src/md4.c $(YASSL)/ctaocrypt/src/md5.c \
|
||||
$(YASSL)/ctaocrypt/src/dh.c $(YASSL)/ctaocrypt/src/dsa.c \
|
||||
$(YASSL)/ctaocrypt/src/pwdbased.c $(YASSL)/ctaocrypt/src/aes.c \
|
||||
$(YASSL)/ctaocrypt/src/md2.c $(YASSL)/ctaocrypt/src/ripemd.c \
|
||||
$(YASSL)/ctaocrypt/src/sha512.c $(YASSL)/src/sniffer.c \
|
||||
$(YASSL)/ctaocrypt/src/rabbit.c $(YASSL)/ctaocrypt/src/misc.c \
|
||||
$(YASSL)/ctaocrypt/src/tfm.c $(YASSL)/ctaocrypt/src/integer.c \
|
||||
$(YASSL)/ctaocrypt/src/ecc.c $(YASSL)/src/ocsp.c $(YASSL)/src/crl.c \
|
||||
$(YASSL)/ctaocrypt/src/hc128.c $(YASSL)/ctaocrypt/src/memory.c
|
||||
|
||||
ALL_SOURCES = ../mongoose.c main.c sqlite3.c lsqlite3.c lua_5.2.1.c \
|
||||
$(YASSL_SOURCES)
|
||||
ALL_OBJECTS = $(ALL_SOURCES:%.c=%.o)
|
||||
ALL_WINOBJS = $(ALL_SOURCES:%.c=%.obj)
|
||||
|
||||
SQLITE_FLAGS = -DTHREADSAFE=1 -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_FTS3_PARENTHESIS
|
||||
MONGOOSE_FLAGS = -DNO_SSL_DL -DUSE_LUA -DUSE_LUA_SQLITE3 -I.. $(COPT)
|
||||
|
||||
FLAGS = $(MONGOOSE_FLAGS) $(SQLITE_FLAGS) $(YASSL_FLAGS) $(LUA_FLAGS)
|
||||
|
||||
# Using Visual Studio 6.0. To build Mongoose:
|
||||
# Set MSVC variable below to where VS 6.0 is installed on your system
|
||||
# Run "PATH_TO_VC6\bin\nmake windows"
|
||||
MSVC = ../../vc6
|
||||
#DBG = /Zi /Od
|
||||
DBG = /DNDEBUG /O1
|
||||
CL = $(MSVC)/bin/cl /MD /TC /nologo $(DBG) /W3 /GA /I$(MSVC)/include
|
||||
LINK_FLAGS = /incremental:no /libpath:$(MSVC)/lib /machine:IX86 \
|
||||
user32.lib shell32.lib comdlg32.lib ws2_32.lib advapi32.lib
|
||||
LINK = $(MSVC)/bin/link $(LINK_FLAGS)
|
||||
|
||||
all:
|
||||
@echo "make (linux|bsd|solaris|mac|windows|mingw|cygwin)"
|
||||
|
||||
%.obj: %.c
|
||||
$(CL) /c $(FLAGS) /Fo$@ $<
|
||||
|
||||
%.o: %.c
|
||||
$(CC) -o $@ $< -c $(FLAGS) $(CFLAGS)
|
||||
|
||||
# Lua library for Windows
|
||||
lua.lib: $(LUA_WINOBJS)
|
||||
$(MSVC)/bin/lib /out:$@ $(LUA_WINOBJS)
|
||||
|
||||
# To build with lua, make sure you have Lua unpacked into lua-5.2.1 directory
|
||||
linux_lua: $(ALL_OBJECTS)
|
||||
$(CC) $(ALL_OBJECTS) -o $(PROG) -ldl
|
||||
|
||||
mongoose.o: mod_lua.c
|
||||
|
||||
# Make sure that the compiler flags come last in the compilation string.
|
||||
# If not so, this can break some on some Linux distros which use
|
||||
# "-Wl,--as-needed" turned on by default in cc command.
|
||||
# Also, this is turned in many other distros in static linkage builds.
|
||||
linux:
|
||||
$(CC) ../mongoose.c main.c -o $(PROG) -ldl $(CFLAGS)
|
||||
|
||||
mac: bsd
|
||||
bsd:
|
||||
$(CC) ../mongoose.c main.c -o $(PROG) $(CFLAGS)
|
||||
|
||||
bsd_lua: $(ALL_OBJECTS)
|
||||
$(CC) $(ALL_OBJECTS) -o $@
|
||||
|
||||
solaris:
|
||||
$(CC) ../mongoose.c main.c -lnsl -lsocket -o $(PROG) $(CFLAGS)
|
||||
|
||||
lib$(PROG).a: $(ALL_OBJECTS)
|
||||
ar cr $@ $(ALL_OBJECTS)
|
||||
|
||||
$(PROG).lib: $(ALL_WINOBJS)
|
||||
$(MSVC)/bin/lib /out:$@ $(ALL_WINOBJS)
|
||||
|
||||
# For codesign to work in non-interactive mode, unlock login keychain:
|
||||
# security unlock ~/Library/Keychains/login.keychain
|
||||
# See e.g. http://lists.apple.com/archives/apple-cdsa/2008/Jan/msg00027.html
|
||||
Mongoose: ../mongoose.c main.c
|
||||
$(CC) $(ALL_SOURCES) \
|
||||
-DUSE_COCOA $(CFLAGS) $(FLAGS) -mmacosx-version-min=10.4 \
|
||||
-framework Cocoa -ObjC -arch i386 -arch x86_64 -o Mongoose
|
||||
|
||||
cocoa: Mongoose
|
||||
V=`perl -lne '/define\s+MONGOOSE_VERSION\s+"(\S+)"/ and print $$1' ../mongoose.c`; DIR=dmg/Mongoose.app && rm -rf $$DIR && mkdir -p $$DIR/Contents/{MacOS,Resources} && install -m 644 mongoose_*.png $$DIR/Contents/Resources/ && install -m 644 Info.plist $$DIR/Contents/ && install -m 755 Mongoose $$DIR/Contents/MacOS/ && ln -fs /Applications dmg/ ; hdiutil create Mongoose_$$V.dmg -volname "Mongoose $$V" -srcfolder dmg -ov #; rm -rf dmg
|
||||
|
||||
un:
|
||||
$(CC) ../test/unit_test.c -o unit_test lua_5.2.1.c $(CFLAGS) -g -O0
|
||||
./unit_test
|
||||
|
||||
wi:
|
||||
$(CL) test/unit_test.c $(LUA_SOURCES) $(LUA_FLAGS) \
|
||||
$(YASSL_SOURCES) $(YASSL_FLAGS) /I. /DNO_SSL_DL \
|
||||
/link /libpath:$(MSVC)/lib advapi32.lib /out:unit_test.exe
|
||||
./unit_test.exe
|
||||
|
||||
windows: $(ALL_WINOBJS)
|
||||
$(MSVC)/bin/rc res.rc
|
||||
$(LINK) /nologo $(ALL_WINOBJS) res.res /out:$(PROG).exe
|
||||
|
||||
windows_tiny: $(ALL_SOURCES)
|
||||
$(MSVC)/bin/rc res.rc
|
||||
$(CL) /nologo ../mongoose.c main.c /I.. \
|
||||
/link $(LINK_FLAGS) res.res /out:$(PROG)-tiny.exe
|
||||
|
||||
# Build for Windows under MinGW
|
||||
#MINGWDBG= -DDEBUG -O0 -ggdb
|
||||
MINGWDBG= -DNDEBUG -Os
|
||||
MINGWOPT= -W -Wall -mthreads -Wl,--subsystem,console $(MINGWDBG) -DHAVE_STDINT $(GCC_WARNINGS) $(COPT)
|
||||
mingw:
|
||||
windres res.rc res.o
|
||||
$(CC) $(MINGWOPT) ../mongoose.c -lws2_32 \
|
||||
-shared -Wl,--out-implib=$(PROG).lib -o $(PROG).dll
|
||||
$(CC) $(MINGWOPT) ../mongoose.c main.c res.o \
|
||||
-lws2_32 -ladvapi32 -lcomdlg32 -o $(PROG).exe
|
||||
|
||||
# Build for Windows under Cygwin
|
||||
#CYGWINDBG= -DDEBUG -O0 -ggdb
|
||||
CYGWINDBG= -DNDEBUG -Os
|
||||
CYGWINOPT= -W -Wall -mthreads -Wl,--subsystem,console $(CYGWINDBG) -DHAVE_STDINT $(GCC_WARNINGS) $(COPT)
|
||||
cygwin:
|
||||
windres res.rc res.o
|
||||
$(CC) $(CYGWINOPT) ../mongoose.c -lws2_32 \
|
||||
-shared -Wl,--out-implib=$(PROG).lib -o $(PROG).dll
|
||||
$(CC) $(CYGWINOPT) -I.. ../mongoose.c main.c res.o \
|
||||
-lws2_32 -ladvapi32 -o $(PROG).exe
|
||||
|
||||
tests:
|
||||
perl ../test/test.pl $(TEST)
|
||||
|
||||
tarball: clean
|
||||
F=mongoose-`perl -lne '/define\s+MONGOOSE_VERSION\s+"(\S+)"/ and print $$1' ../mongoose.c`.tgz ; cd ../.. && tar -czf x mongoose/{LICENSE,*.[ch]} && mv x mongoose/build/$$F
|
||||
|
||||
release: tarball cocoa
|
||||
wine make windows windows_tiny
|
||||
V=`perl -lne '/define\s+MONGOOSE_VERSION\s+"(\S+)"/ and print $$1' ../mongoose.c`; upx mongoose.exe; upx mongoose-tiny.exe ; cp mongoose.exe mongoose-$$V.exe; cp mongoose-tiny.exe mongoose-tiny-$$V.exe; cp mongoose.exe mongoose_php_bundle/; zip -r mongoose-php-$$V.zip mongoose_php_bundle/
|
||||
|
||||
clean:
|
||||
cd ../examples && $(MAKE) clean
|
||||
rm -rf *.o *.core $(PROG) *.obj *.so $(PROG).txt *.dSYM *.tgz \
|
||||
$(PROG).exe *.dll *.lib res.o res.RES *.dSYM *.zip *.pdb \
|
||||
*.exe *dmg* $(ALL_OBJECTS) $(ALL_WINOBJS)
|
||||
@@ -1,15 +0,0 @@
|
||||
LIBRARY
|
||||
EXPORTS
|
||||
mg_start
|
||||
mg_stop
|
||||
mg_read
|
||||
mg_write
|
||||
mg_printf
|
||||
mg_get_header
|
||||
mg_get_var
|
||||
mg_get_cookie
|
||||
mg_get_option
|
||||
mg_get_valid_option_names
|
||||
mg_version
|
||||
mg_modify_passwords_file
|
||||
mg_md5
|
||||
@@ -1,6 +0,0 @@
|
||||
LOCAL_PATH := $(call my-dir)/../..
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_CFLAGS := -std=c99 -O2 -W -Wall -pthread -pipe $(COPT)
|
||||
LOCAL_MODULE := mongoose
|
||||
LOCAL_SRC_FILES := main.c mongoose.c
|
||||
include $(BUILD_EXECUTABLE)
|
||||
-1883
File diff suppressed because it is too large.
Load diff
-17698
File diff suppressed because it is too large.
Load diff
-1247
File diff suppressed because it is too large.
Load diff
-985
@@ -1,985 +0,0 @@
|
||||
// Copyright (c) 2004-2013 Sergey Lyubka
|
||||
//
|
||||
// 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.
|
||||
|
||||
#if defined(_WIN32)
|
||||
#define _CRT_SECURE_NO_WARNINGS // Disable deprecation warning in VS2005
|
||||
#else
|
||||
#define _XOPEN_SOURCE 600 // For PATH_MAX on linux
|
||||
#endif
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "mongoose.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <winsvc.h>
|
||||
#include <shlobj.h>
|
||||
|
||||
#ifndef PATH_MAX
|
||||
#define PATH_MAX MAX_PATH
|
||||
#endif
|
||||
|
||||
#ifndef S_ISDIR
|
||||
#define S_ISDIR(x) ((x) & _S_IFDIR)
|
||||
#endif
|
||||
|
||||
#define DIRSEP '\\'
|
||||
#define snprintf _snprintf
|
||||
#define vsnprintf _vsnprintf
|
||||
#define sleep(x) Sleep((x) * 1000)
|
||||
#define WINCDECL __cdecl
|
||||
#define abs_path(rel, abs, abs_size) _fullpath((abs), (rel), (abs_size))
|
||||
#else
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
#define DIRSEP '/'
|
||||
#define WINCDECL
|
||||
#define abs_path(rel, abs, abs_size) realpath((rel), (abs))
|
||||
#endif // _WIN32
|
||||
|
||||
#define MAX_OPTIONS 100
|
||||
#define MAX_CONF_FILE_LINE_SIZE (8 * 1024)
|
||||
|
||||
static int exit_flag;
|
||||
static char server_name[40]; // Set by init_server_name()
|
||||
static char config_file[PATH_MAX]; // Set by process_command_line_arguments()
|
||||
static struct mg_context *ctx; // Set by start_mongoose()
|
||||
|
||||
#if !defined(CONFIG_FILE)
|
||||
#define CONFIG_FILE "mongoose.conf"
|
||||
#endif /* !CONFIG_FILE */
|
||||
|
||||
static void WINCDECL signal_handler(int sig_num) {
|
||||
#if !defined(_WIN32)
|
||||
// Do not do the trick with ignoring SIGCHLD, cause not all OSes (e.g. QNX)
|
||||
// reap zombies if SIGCHLD is ignored. On QNX, for example, waitpid()
|
||||
// fails if SIGCHLD is ignored, making system() non-functional.
|
||||
if (sig_num == SIGCHLD) {
|
||||
do {} while (waitpid(-1, &sig_num, WNOHANG) > 0);
|
||||
} else
|
||||
#endif
|
||||
{ exit_flag = sig_num; }
|
||||
}
|
||||
|
||||
static void die(const char *fmt, ...) {
|
||||
va_list ap;
|
||||
char msg[200];
|
||||
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(msg, sizeof(msg), fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
#if defined(_WIN32)
|
||||
MessageBox(NULL, msg, "Error", MB_OK);
|
||||
#else
|
||||
fprintf(stderr, "%s\n", msg);
|
||||
#endif
|
||||
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static void show_usage_and_exit(void) {
|
||||
const char **names;
|
||||
int i;
|
||||
|
||||
fprintf(stderr, "Mongoose version %s (c) Sergey Lyubka, built on %s\n",
|
||||
mg_version(), __DATE__);
|
||||
fprintf(stderr, "Usage:\n");
|
||||
fprintf(stderr, " mongoose -A <htpasswd_file> <realm> <user> <passwd>\n");
|
||||
fprintf(stderr, " mongoose [config_file]\n");
|
||||
fprintf(stderr, " mongoose [-option value ...]\n");
|
||||
fprintf(stderr, "\nOPTIONS:\n");
|
||||
|
||||
names = mg_get_valid_option_names();
|
||||
for (i = 0; names[i] != NULL; i += 2) {
|
||||
fprintf(stderr, " -%s %s\n",
|
||||
names[i], names[i + 1] == NULL ? "<empty>" : names[i + 1]);
|
||||
}
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
#if defined(_WIN32) || defined(USE_COCOA)
|
||||
static const char *config_file_top_comment =
|
||||
"# Mongoose web server configuration file.\n"
|
||||
"# For detailed description of every option, visit\n"
|
||||
"# https://github.com/valenok/mongoose/blob/master/UserManual.md\n"
|
||||
"# Lines starting with '#' and empty lines are ignored.\n"
|
||||
"# To make a change, remove leading '#', modify option's value,\n"
|
||||
"# save this file and then restart Mongoose.\n\n";
|
||||
|
||||
static const char *get_url_to_first_open_port(const struct mg_context *ctx) {
|
||||
static char url[100];
|
||||
const char *open_ports = mg_get_option(ctx, "listening_ports");
|
||||
int a, b, c, d, port, n;
|
||||
|
||||
if (sscanf(open_ports, "%d.%d.%d.%d:%d%n", &a, &b, &c, &d, &port, &n) == 5) {
|
||||
snprintf(url, sizeof(url), "%s://%d.%d.%d.%d:%d",
|
||||
open_ports[n] == 's' ? "https" : "http", a, b, c, d, port);
|
||||
} else if (sscanf(open_ports, "%d%n", &port, &n) == 1) {
|
||||
snprintf(url, sizeof(url), "%s://localhost:%d",
|
||||
open_ports[n] == 's' ? "https" : "http", port);
|
||||
} else {
|
||||
snprintf(url, sizeof(url), "%s", "http://localhost:8080");
|
||||
}
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
static void create_config_file(const char *path) {
|
||||
const char **names, *value;
|
||||
FILE *fp;
|
||||
int i;
|
||||
|
||||
// Create config file if it is not present yet
|
||||
if ((fp = fopen(path, "r")) != NULL) {
|
||||
fclose(fp);
|
||||
} else if ((fp = fopen(path, "a+")) != NULL) {
|
||||
fprintf(fp, "%s", config_file_top_comment);
|
||||
names = mg_get_valid_option_names();
|
||||
for (i = 0; names[i * 2] != NULL; i++) {
|
||||
value = mg_get_option(ctx, names[i * 2]);
|
||||
fprintf(fp, "# %s %s\n", names[i * 2], value ? value : "<value>");
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static char *sdup(const char *str) {
|
||||
char *p;
|
||||
if ((p = (char *) malloc(strlen(str) + 1)) != NULL) {
|
||||
strcpy(p, str);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
static void set_option(char **options, const char *name, const char *value) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_OPTIONS - 3; i++) {
|
||||
if (options[i] == NULL) {
|
||||
options[i] = sdup(name);
|
||||
options[i + 1] = sdup(value);
|
||||
options[i + 2] = NULL;
|
||||
break;
|
||||
} else if (!strcmp(options[i], name)) {
|
||||
free(options[i + 1]);
|
||||
options[i + 1] = sdup(value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == MAX_OPTIONS - 3) {
|
||||
die("%s", "Too many options specified");
|
||||
}
|
||||
}
|
||||
|
||||
static void process_command_line_arguments(char *argv[], char **options) {
|
||||
char line[MAX_CONF_FILE_LINE_SIZE], opt[sizeof(line)], val[sizeof(line)], *p;
|
||||
FILE *fp = NULL;
|
||||
size_t i, cmd_line_opts_start = 1, line_no = 0;
|
||||
|
||||
// Should we use a config file ?
|
||||
if (argv[1] != NULL && argv[1][0] != '-') {
|
||||
snprintf(config_file, sizeof(config_file), "%s", argv[1]);
|
||||
cmd_line_opts_start = 2;
|
||||
} else if ((p = strrchr(argv[0], DIRSEP)) == NULL) {
|
||||
// No command line flags specified. Look where binary lives
|
||||
snprintf(config_file, sizeof(config_file), "%s", CONFIG_FILE);
|
||||
} else {
|
||||
snprintf(config_file, sizeof(config_file), "%.*s%c%s",
|
||||
(int) (p - argv[0]), argv[0], DIRSEP, CONFIG_FILE);
|
||||
}
|
||||
|
||||
fp = fopen(config_file, "r");
|
||||
|
||||
// If config file was set in command line and open failed, die
|
||||
if (cmd_line_opts_start == 2 && fp == NULL) {
|
||||
die("Cannot open config file %s: %s", config_file, strerror(errno));
|
||||
}
|
||||
|
||||
// Load config file settings first
|
||||
if (fp != NULL) {
|
||||
fprintf(stderr, "Loading config file %s\n", config_file);
|
||||
|
||||
// Loop over the lines in config file
|
||||
while (fgets(line, sizeof(line), fp) != NULL) {
|
||||
line_no++;
|
||||
|
||||
// Ignore empty lines and comments
|
||||
for (i = 0; isspace(* (unsigned char *) &line[i]); ) i++;
|
||||
if (line[i] == '#' || line[i] == '\0') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (sscanf(line, "%s %[^\r\n#]", opt, val) != 2) {
|
||||
printf("%s: line %d is invalid, ignoring it:\n %s",
|
||||
config_file, (int) line_no, line);
|
||||
} else {
|
||||
set_option(options, opt, val);
|
||||
}
|
||||
}
|
||||
|
||||
(void) fclose(fp);
|
||||
}
|
||||
|
||||
// If we're under MacOS and started by launchd, then the second
|
||||
// argument is process serial number, -psn_.....
|
||||
// In this case, don't process arguments at all.
|
||||
if (argv[1] == NULL || memcmp(argv[1], "-psn_", 5) != 0) {
|
||||
// Handle command line flags.
|
||||
// They override config file and default settings.
|
||||
for (i = cmd_line_opts_start; argv[i] != NULL; i += 2) {
|
||||
if (argv[i][0] != '-' || argv[i + 1] == NULL) {
|
||||
show_usage_and_exit();
|
||||
}
|
||||
set_option(options, &argv[i][1], argv[i + 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void init_server_name(void) {
|
||||
snprintf(server_name, sizeof(server_name), "Mongoose web server v.%s",
|
||||
mg_version());
|
||||
}
|
||||
|
||||
static int log_message(const struct mg_connection *conn, const char *message) {
|
||||
(void) conn;
|
||||
printf("%s\n", message);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int is_path_absolute(const char *path) {
|
||||
#ifdef _WIN32
|
||||
return path != NULL &&
|
||||
((path[0] == '\\' && path[1] == '\\') || // UNC path, e.g. \\server\dir
|
||||
(isalpha(path[0]) && path[1] == ':' && path[2] == '\\')); // E.g. X:\dir
|
||||
#else
|
||||
return path != NULL && path[0] == '/';
|
||||
#endif
|
||||
}
|
||||
|
||||
static char *get_option(char **options, const char *option_name) {
|
||||
int i;
|
||||
|
||||
for (i = 0; options[i] != NULL; i++)
|
||||
if (!strcmp(options[i], option_name))
|
||||
return options[i + 1];
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void verify_existence(char **options, const char *option_name,
|
||||
int must_be_dir) {
|
||||
struct stat st;
|
||||
const char *path = get_option(options, option_name);
|
||||
|
||||
if (path != NULL && (stat(path, &st) != 0 ||
|
||||
((S_ISDIR(st.st_mode) ? 1 : 0) != must_be_dir))) {
|
||||
die("Invalid path for %s: [%s]: (%s). Make sure that path is either "
|
||||
"absolute, or it is relative to mongoose executable.",
|
||||
option_name, path, strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
static void set_absolute_path(char *options[], const char *option_name,
|
||||
const char *path_to_mongoose_exe) {
|
||||
char path[PATH_MAX], abs[PATH_MAX], *option_value;
|
||||
const char *p;
|
||||
|
||||
// Check whether option is already set
|
||||
option_value = get_option(options, option_name);
|
||||
|
||||
// If option is already set and it is an absolute path,
|
||||
// leave it as it is -- it's already absolute.
|
||||
if (option_value != NULL && !is_path_absolute(option_value)) {
|
||||
// Not absolute. Use the directory where mongoose executable lives
|
||||
// be the relative directory for everything.
|
||||
// Extract mongoose executable directory into path.
|
||||
if ((p = strrchr(path_to_mongoose_exe, DIRSEP)) == NULL) {
|
||||
getcwd(path, sizeof(path));
|
||||
} else {
|
||||
snprintf(path, sizeof(path), "%.*s", (int) (p - path_to_mongoose_exe),
|
||||
path_to_mongoose_exe);
|
||||
}
|
||||
|
||||
strncat(path, "/", sizeof(path) - 1);
|
||||
strncat(path, option_value, sizeof(path) - 1);
|
||||
|
||||
// Absolutize the path, and set the option
|
||||
abs_path(path, abs, sizeof(abs));
|
||||
set_option(options, option_name, abs);
|
||||
}
|
||||
}
|
||||
|
||||
static void start_mongoose(int argc, char *argv[]) {
|
||||
struct mg_callbacks callbacks;
|
||||
char *options[MAX_OPTIONS];
|
||||
int i;
|
||||
|
||||
// Edit passwords file if -A option is specified
|
||||
if (argc > 1 && !strcmp(argv[1], "-A")) {
|
||||
if (argc != 6) {
|
||||
show_usage_and_exit();
|
||||
}
|
||||
exit(mg_modify_passwords_file(argv[2], argv[3], argv[4], argv[5]) ?
|
||||
EXIT_SUCCESS : EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// Show usage if -h or --help options are specified
|
||||
if (argc == 2 && (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))) {
|
||||
show_usage_and_exit();
|
||||
}
|
||||
|
||||
options[0] = NULL;
|
||||
set_option(options, "document_root", ".");
|
||||
|
||||
// Update config based on command line arguments
|
||||
process_command_line_arguments(argv, options);
|
||||
|
||||
// Make sure we have absolute paths for files and directories
|
||||
// https://github.com/valenok/mongoose/issues/181
|
||||
set_absolute_path(options, "document_root", argv[0]);
|
||||
set_absolute_path(options, "put_delete_auth_file", argv[0]);
|
||||
set_absolute_path(options, "cgi_interpreter", argv[0]);
|
||||
set_absolute_path(options, "access_log_file", argv[0]);
|
||||
set_absolute_path(options, "error_log_file", argv[0]);
|
||||
set_absolute_path(options, "global_auth_file", argv[0]);
|
||||
set_absolute_path(options, "ssl_certificate", argv[0]);
|
||||
|
||||
// Make extra verification for certain options
|
||||
verify_existence(options, "document_root", 1);
|
||||
verify_existence(options, "cgi_interpreter", 0);
|
||||
verify_existence(options, "ssl_certificate", 0);
|
||||
|
||||
// Setup signal handler: quit on Ctrl-C
|
||||
signal(SIGTERM, signal_handler);
|
||||
signal(SIGINT, signal_handler);
|
||||
|
||||
// Start Mongoose
|
||||
memset(&callbacks, 0, sizeof(callbacks));
|
||||
callbacks.log_message = &log_message;
|
||||
ctx = mg_start(&callbacks, NULL, (const char **) options);
|
||||
for (i = 0; options[i] != NULL; i++) {
|
||||
free(options[i]);
|
||||
}
|
||||
|
||||
if (ctx == NULL) {
|
||||
die("%s", "Failed to start Mongoose.");
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
enum {
|
||||
ID_ICON = 100, ID_QUIT, ID_SETTINGS, ID_SEPARATOR, ID_INSTALL_SERVICE,
|
||||
ID_REMOVE_SERVICE, ID_STATIC, ID_GROUP, ID_SAVE, ID_RESET_DEFAULTS,
|
||||
ID_STATUS, ID_CONNECT,
|
||||
|
||||
// All dynamically created text boxes for options have IDs starting from
|
||||
// ID_CONTROLS, incremented by one.
|
||||
ID_CONTROLS = 200,
|
||||
|
||||
// Text boxes for files have "..." buttons to open file browser. These
|
||||
// buttons have IDs that are ID_FILE_BUTTONS_DELTA higher than associated
|
||||
// text box ID.
|
||||
ID_FILE_BUTTONS_DELTA = 1000
|
||||
};
|
||||
static HICON hIcon;
|
||||
static SERVICE_STATUS ss;
|
||||
static SERVICE_STATUS_HANDLE hStatus;
|
||||
static const char *service_magic_argument = "--";
|
||||
static NOTIFYICONDATA TrayIcon;
|
||||
|
||||
static void WINAPI ControlHandler(DWORD code) {
|
||||
if (code == SERVICE_CONTROL_STOP || code == SERVICE_CONTROL_SHUTDOWN) {
|
||||
ss.dwWin32ExitCode = 0;
|
||||
ss.dwCurrentState = SERVICE_STOPPED;
|
||||
}
|
||||
SetServiceStatus(hStatus, &ss);
|
||||
}
|
||||
|
||||
static void WINAPI ServiceMain(void) {
|
||||
ss.dwServiceType = SERVICE_WIN32;
|
||||
ss.dwCurrentState = SERVICE_RUNNING;
|
||||
ss.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
|
||||
|
||||
hStatus = RegisterServiceCtrlHandler(server_name, ControlHandler);
|
||||
SetServiceStatus(hStatus, &ss);
|
||||
|
||||
while (ss.dwCurrentState == SERVICE_RUNNING) {
|
||||
Sleep(1000);
|
||||
}
|
||||
mg_stop(ctx);
|
||||
|
||||
ss.dwCurrentState = SERVICE_STOPPED;
|
||||
ss.dwWin32ExitCode = (DWORD) -1;
|
||||
SetServiceStatus(hStatus, &ss);
|
||||
}
|
||||
|
||||
|
||||
static void show_error(void) {
|
||||
char buf[256];
|
||||
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL, GetLastError(),
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
buf, sizeof(buf), NULL);
|
||||
MessageBox(NULL, buf, "Error", MB_OK);
|
||||
}
|
||||
|
||||
static void *align(void *ptr, DWORD alig) {
|
||||
ULONG ul = (ULONG) ptr;
|
||||
ul += alig;
|
||||
ul &= ~alig;
|
||||
return ((void *) ul);
|
||||
}
|
||||
|
||||
static int is_boolean_option(const char *option_name) {
|
||||
return !strcmp(option_name, "enable_directory_listing") ||
|
||||
!strcmp(option_name, "enable_keep_alive");
|
||||
}
|
||||
|
||||
static int is_filename_option(const char *option_name) {
|
||||
return !strcmp(option_name, "cgi_interpreter") ||
|
||||
!strcmp(option_name, "global_auth_file") ||
|
||||
!strcmp(option_name, "put_delete_auth_file") ||
|
||||
!strcmp(option_name, "access_log_file") ||
|
||||
!strcmp(option_name, "error_log_file") ||
|
||||
!strcmp(option_name, "ssl_certificate");
|
||||
}
|
||||
|
||||
static int is_directory_option(const char *option_name) {
|
||||
return !strcmp(option_name, "document_root");
|
||||
}
|
||||
|
||||
static int is_numeric_options(const char *option_name) {
|
||||
return !strcmp(option_name, "num_threads");
|
||||
}
|
||||
|
||||
static void save_config(HWND hDlg, FILE *fp) {
|
||||
char value[2000];
|
||||
const char **options, *name, *default_value;
|
||||
int i, id;
|
||||
|
||||
fprintf(fp, "%s", config_file_top_comment);
|
||||
options = mg_get_valid_option_names();
|
||||
for (i = 0; options[i * 2] != NULL; i++) {
|
||||
name = options[i * 2];
|
||||
id = ID_CONTROLS + i;
|
||||
if (is_boolean_option(name)) {
|
||||
snprintf(value, sizeof(value), "%s",
|
||||
IsDlgButtonChecked(hDlg, id) ? "yes" : "no");
|
||||
} else {
|
||||
GetDlgItemText(hDlg, id, value, sizeof(value));
|
||||
}
|
||||
default_value = options[i * 2 + 1] == NULL ? "" : options[i * 2 + 1];
|
||||
// If value is the same as default, skip it
|
||||
if (strcmp(value, default_value) != 0) {
|
||||
fprintf(fp, "%s %s\n", name, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL CALLBACK DlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lP) {
|
||||
FILE *fp;
|
||||
int i;
|
||||
const char *name, *value, **options = mg_get_valid_option_names();
|
||||
|
||||
switch (msg) {
|
||||
case WM_CLOSE:
|
||||
DestroyWindow(hDlg);
|
||||
break;
|
||||
|
||||
case WM_COMMAND:
|
||||
switch (LOWORD(wParam)) {
|
||||
case ID_SAVE:
|
||||
EnableWindow(GetDlgItem(hDlg, ID_SAVE), FALSE);
|
||||
if ((fp = fopen(config_file, "w+")) != NULL) {
|
||||
save_config(hDlg, fp);
|
||||
fclose(fp);
|
||||
mg_stop(ctx);
|
||||
start_mongoose(__argc, __argv);
|
||||
}
|
||||
EnableWindow(GetDlgItem(hDlg, ID_SAVE), TRUE);
|
||||
break;
|
||||
case ID_RESET_DEFAULTS:
|
||||
for (i = 0; options[i * 2] != NULL; i++) {
|
||||
name = options[i * 2];
|
||||
value = options[i * 2 + 1] == NULL ? "" : options[i * 2 + 1];
|
||||
if (is_boolean_option(name)) {
|
||||
CheckDlgButton(hDlg, ID_CONTROLS + i, !strcmp(value, "yes") ?
|
||||
BST_CHECKED : BST_UNCHECKED);
|
||||
} else {
|
||||
SetWindowText(GetDlgItem(hDlg, ID_CONTROLS + i), value);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; options[i * 2] != NULL; i++) {
|
||||
name = options[i * 2];
|
||||
if ((is_filename_option(name) || is_directory_option(name)) &&
|
||||
LOWORD(wParam) == ID_CONTROLS + i + ID_FILE_BUTTONS_DELTA) {
|
||||
OPENFILENAME of;
|
||||
BROWSEINFO bi;
|
||||
char path[PATH_MAX] = "";
|
||||
|
||||
memset(&of, 0, sizeof(of));
|
||||
of.lStructSize = sizeof(of);
|
||||
of.hwndOwner = (HWND) hDlg;
|
||||
of.lpstrFile = path;
|
||||
of.nMaxFile = sizeof(path);
|
||||
of.lpstrInitialDir = mg_get_option(ctx, "document_root");
|
||||
of.Flags = OFN_CREATEPROMPT | OFN_NOCHANGEDIR;
|
||||
|
||||
memset(&bi, 0, sizeof(bi));
|
||||
bi.hwndOwner = (HWND) hDlg;
|
||||
bi.lpszTitle = "Choose WWW root directory:";
|
||||
bi.ulFlags = BIF_RETURNONLYFSDIRS;
|
||||
|
||||
if (is_directory_option(name)) {
|
||||
SHGetPathFromIDList(SHBrowseForFolder(&bi), path);
|
||||
} else {
|
||||
GetOpenFileName(&of);
|
||||
}
|
||||
|
||||
if (path[0] != '\0') {
|
||||
SetWindowText(GetDlgItem(hDlg, ID_CONTROLS + i), path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case WM_INITDIALOG:
|
||||
SendMessage(hDlg, WM_SETICON,(WPARAM) ICON_SMALL, (LPARAM) hIcon);
|
||||
SendMessage(hDlg, WM_SETICON,(WPARAM) ICON_BIG, (LPARAM) hIcon);
|
||||
SetWindowText(hDlg, "Mongoose settings");
|
||||
SetFocus(GetDlgItem(hDlg, ID_SAVE));
|
||||
for (i = 0; options[i * 2] != NULL; i++) {
|
||||
name = options[i * 2];
|
||||
value = mg_get_option(ctx, name);
|
||||
if (is_boolean_option(name)) {
|
||||
CheckDlgButton(hDlg, ID_CONTROLS + i, !strcmp(value, "yes") ?
|
||||
BST_CHECKED : BST_UNCHECKED);
|
||||
} else {
|
||||
SetDlgItemText(hDlg, ID_CONTROLS + i, value == NULL ? "" : value);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void add_control(unsigned char **mem, DLGTEMPLATE *dia, WORD type,
|
||||
DWORD id, DWORD style, WORD x, WORD y,
|
||||
WORD cx, WORD cy, const char *caption) {
|
||||
DLGITEMTEMPLATE *tp;
|
||||
LPWORD p;
|
||||
|
||||
dia->cdit++;
|
||||
|
||||
*mem = align(*mem, 3);
|
||||
tp = (DLGITEMTEMPLATE *) *mem;
|
||||
|
||||
tp->id = (WORD)id;
|
||||
tp->style = style;
|
||||
tp->dwExtendedStyle = 0;
|
||||
tp->x = x;
|
||||
tp->y = y;
|
||||
tp->cx = cx;
|
||||
tp->cy = cy;
|
||||
|
||||
p = align(*mem + sizeof(*tp), 1);
|
||||
*p++ = 0xffff;
|
||||
*p++ = type;
|
||||
|
||||
while (*caption != '\0') {
|
||||
*p++ = (WCHAR) *caption++;
|
||||
}
|
||||
*p++ = 0;
|
||||
p = align(p, 1);
|
||||
|
||||
*p++ = 0;
|
||||
*mem = (unsigned char *) p;
|
||||
}
|
||||
|
||||
static void show_settings_dialog() {
|
||||
#define HEIGHT 15
|
||||
#define WIDTH 400
|
||||
#define LABEL_WIDTH 80
|
||||
|
||||
unsigned char mem[4096], *p;
|
||||
const char **option_names, *long_option_name;
|
||||
DWORD style;
|
||||
DLGTEMPLATE *dia = (DLGTEMPLATE *) mem;
|
||||
WORD i, cl, x, y, width, nelems = 0;
|
||||
static int guard;
|
||||
|
||||
static struct {
|
||||
DLGTEMPLATE template; // 18 bytes
|
||||
WORD menu, class;
|
||||
wchar_t caption[1];
|
||||
WORD fontsiz;
|
||||
wchar_t fontface[7];
|
||||
} dialog_header = {{WS_CAPTION | WS_POPUP | WS_SYSMENU | WS_VISIBLE |
|
||||
DS_SETFONT | WS_DLGFRAME, WS_EX_TOOLWINDOW, 0, 200, 200, WIDTH, 0},
|
||||
0, 0, L"", 8, L"Tahoma"};
|
||||
|
||||
if (guard == 0) {
|
||||
guard++;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
(void) memset(mem, 0, sizeof(mem));
|
||||
(void) memcpy(mem, &dialog_header, sizeof(dialog_header));
|
||||
p = mem + sizeof(dialog_header);
|
||||
|
||||
option_names = mg_get_valid_option_names();
|
||||
for (i = 0; option_names[i * 2] != NULL; i++) {
|
||||
long_option_name = option_names[i * 2];
|
||||
style = WS_CHILD | WS_VISIBLE | WS_TABSTOP;
|
||||
x = 10 + (WIDTH / 2) * (nelems % 2);
|
||||
y = (nelems/2 + 1) * HEIGHT + 5;
|
||||
width = WIDTH / 2 - 20 - LABEL_WIDTH;
|
||||
if (is_numeric_options(long_option_name)) {
|
||||
style |= ES_NUMBER;
|
||||
cl = 0x81;
|
||||
style |= WS_BORDER | ES_AUTOHSCROLL;
|
||||
} else if (is_boolean_option(long_option_name)) {
|
||||
cl = 0x80;
|
||||
style |= BS_AUTOCHECKBOX;
|
||||
} else if (is_filename_option(long_option_name) ||
|
||||
is_directory_option(long_option_name)) {
|
||||
style |= WS_BORDER | ES_AUTOHSCROLL;
|
||||
width -= 20;
|
||||
cl = 0x81;
|
||||
add_control(&p, dia, 0x80,
|
||||
ID_CONTROLS + i + ID_FILE_BUTTONS_DELTA,
|
||||
WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON,
|
||||
(WORD) (x + width + LABEL_WIDTH + 5),
|
||||
y, 15, 12, "...");
|
||||
} else {
|
||||
cl = 0x81;
|
||||
style |= WS_BORDER | ES_AUTOHSCROLL;
|
||||
}
|
||||
add_control(&p, dia, 0x82, ID_STATIC, WS_VISIBLE | WS_CHILD,
|
||||
x, y, LABEL_WIDTH, HEIGHT, long_option_name);
|
||||
add_control(&p, dia, cl, ID_CONTROLS + i, style,
|
||||
(WORD) (x + LABEL_WIDTH), y, width, 12, "");
|
||||
nelems++;
|
||||
}
|
||||
|
||||
y = (WORD) (((nelems + 1) / 2 + 1) * HEIGHT + 5);
|
||||
add_control(&p, dia, 0x80, ID_GROUP, WS_CHILD | WS_VISIBLE |
|
||||
BS_GROUPBOX, 5, 5, WIDTH - 10, y, " Settings ");
|
||||
y += 10;
|
||||
add_control(&p, dia, 0x80, ID_SAVE,
|
||||
WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP,
|
||||
WIDTH - 70, y, 65, 12, "Save Settings");
|
||||
add_control(&p, dia, 0x80, ID_RESET_DEFAULTS,
|
||||
WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP,
|
||||
WIDTH - 140, y, 65, 12, "Reset to defaults");
|
||||
add_control(&p, dia, 0x82, ID_STATIC,
|
||||
WS_CHILD | WS_VISIBLE | WS_DISABLED,
|
||||
5, y, 180, 12, server_name);
|
||||
|
||||
dia->cy = ((nelems + 1) / 2 + 1) * HEIGHT + 30;
|
||||
DialogBoxIndirectParam(NULL, dia, NULL, DlgProc, (LPARAM) NULL);
|
||||
guard--;
|
||||
}
|
||||
|
||||
static int manage_service(int action) {
|
||||
static const char *service_name = "Mongoose";
|
||||
SC_HANDLE hSCM = NULL, hService = NULL;
|
||||
SERVICE_DESCRIPTION descr = {server_name};
|
||||
char path[PATH_MAX + 20]; // Path to executable plus magic argument
|
||||
int success = 1;
|
||||
|
||||
if ((hSCM = OpenSCManager(NULL, NULL, action == ID_INSTALL_SERVICE ?
|
||||
GENERIC_WRITE : GENERIC_READ)) == NULL) {
|
||||
success = 0;
|
||||
show_error();
|
||||
} else if (action == ID_INSTALL_SERVICE) {
|
||||
GetModuleFileName(NULL, path, sizeof(path));
|
||||
strncat(path, " ", sizeof(path));
|
||||
strncat(path, service_magic_argument, sizeof(path));
|
||||
hService = CreateService(hSCM, service_name, service_name,
|
||||
SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
|
||||
SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
|
||||
path, NULL, NULL, NULL, NULL, NULL);
|
||||
if (hService) {
|
||||
ChangeServiceConfig2(hService, SERVICE_CONFIG_DESCRIPTION, &descr);
|
||||
} else {
|
||||
show_error();
|
||||
}
|
||||
} else if (action == ID_REMOVE_SERVICE) {
|
||||
if ((hService = OpenService(hSCM, service_name, DELETE)) == NULL ||
|
||||
!DeleteService(hService)) {
|
||||
show_error();
|
||||
}
|
||||
} else if ((hService = OpenService(hSCM, service_name,
|
||||
SERVICE_QUERY_STATUS)) == NULL) {
|
||||
success = 0;
|
||||
}
|
||||
|
||||
CloseServiceHandle(hService);
|
||||
CloseServiceHandle(hSCM);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
static LRESULT CALLBACK WindowProc(HWND hWnd, UINT msg, WPARAM wParam,
|
||||
LPARAM lParam) {
|
||||
static SERVICE_TABLE_ENTRY service_table[] = {
|
||||
{server_name, (LPSERVICE_MAIN_FUNCTION) ServiceMain},
|
||||
{NULL, NULL}
|
||||
};
|
||||
int service_installed;
|
||||
char buf[200], *service_argv[] = {__argv[0], NULL};
|
||||
POINT pt;
|
||||
HMENU hMenu;
|
||||
static UINT s_uTaskbarRestart; // for taskbar creation
|
||||
|
||||
switch (msg) {
|
||||
case WM_CREATE:
|
||||
if (__argv[1] != NULL &&
|
||||
!strcmp(__argv[1], service_magic_argument)) {
|
||||
start_mongoose(1, service_argv);
|
||||
StartServiceCtrlDispatcher(service_table);
|
||||
exit(EXIT_SUCCESS);
|
||||
} else {
|
||||
start_mongoose(__argc, __argv);
|
||||
s_uTaskbarRestart = RegisterWindowMessage(TEXT("TaskbarCreated"));
|
||||
}
|
||||
break;
|
||||
case WM_COMMAND:
|
||||
switch (LOWORD(wParam)) {
|
||||
case ID_QUIT:
|
||||
mg_stop(ctx);
|
||||
Shell_NotifyIcon(NIM_DELETE, &TrayIcon);
|
||||
PostQuitMessage(0);
|
||||
return 0;
|
||||
case ID_SETTINGS:
|
||||
show_settings_dialog();
|
||||
break;
|
||||
case ID_INSTALL_SERVICE:
|
||||
case ID_REMOVE_SERVICE:
|
||||
manage_service(LOWORD(wParam));
|
||||
break;
|
||||
case ID_CONNECT:
|
||||
printf("[%s]\n", get_url_to_first_open_port(ctx));
|
||||
ShellExecute(NULL, "open", get_url_to_first_open_port(ctx),
|
||||
NULL, NULL, SW_SHOW);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case WM_USER:
|
||||
switch (lParam) {
|
||||
case WM_RBUTTONUP:
|
||||
case WM_LBUTTONUP:
|
||||
case WM_LBUTTONDBLCLK:
|
||||
hMenu = CreatePopupMenu();
|
||||
AppendMenu(hMenu, MF_STRING | MF_GRAYED, ID_SEPARATOR, server_name);
|
||||
AppendMenu(hMenu, MF_SEPARATOR, ID_SEPARATOR, "");
|
||||
service_installed = manage_service(0);
|
||||
snprintf(buf, sizeof(buf), "NT service: %s installed",
|
||||
service_installed ? "" : "not");
|
||||
AppendMenu(hMenu, MF_STRING | MF_GRAYED, ID_SEPARATOR, buf);
|
||||
AppendMenu(hMenu, MF_STRING | (service_installed ? MF_GRAYED : 0),
|
||||
ID_INSTALL_SERVICE, "Install service");
|
||||
AppendMenu(hMenu, MF_STRING | (!service_installed ? MF_GRAYED : 0),
|
||||
ID_REMOVE_SERVICE, "Deinstall service");
|
||||
AppendMenu(hMenu, MF_SEPARATOR, ID_SEPARATOR, "");
|
||||
AppendMenu(hMenu, MF_STRING, ID_CONNECT, "Start browser");
|
||||
AppendMenu(hMenu, MF_STRING, ID_SETTINGS, "Edit Settings");
|
||||
AppendMenu(hMenu, MF_SEPARATOR, ID_SEPARATOR, "");
|
||||
AppendMenu(hMenu, MF_STRING, ID_QUIT, "Exit");
|
||||
GetCursorPos(&pt);
|
||||
SetForegroundWindow(hWnd);
|
||||
TrackPopupMenu(hMenu, 0, pt.x, pt.y, 0, hWnd, NULL);
|
||||
PostMessage(hWnd, WM_NULL, 0, 0);
|
||||
DestroyMenu(hMenu);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case WM_CLOSE:
|
||||
mg_stop(ctx);
|
||||
Shell_NotifyIcon(NIM_DELETE, &TrayIcon);
|
||||
PostQuitMessage(0);
|
||||
return 0; // We've just sent our own quit message, with proper hwnd.
|
||||
default:
|
||||
if (msg==s_uTaskbarRestart)
|
||||
Shell_NotifyIcon(NIM_ADD, &TrayIcon);
|
||||
}
|
||||
|
||||
return DefWindowProc(hWnd, msg, wParam, lParam);
|
||||
}
|
||||
|
||||
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR cmdline, int show) {
|
||||
WNDCLASS cls;
|
||||
HWND hWnd;
|
||||
MSG msg;
|
||||
|
||||
init_server_name();
|
||||
memset(&cls, 0, sizeof(cls));
|
||||
cls.lpfnWndProc = (WNDPROC) WindowProc;
|
||||
cls.hIcon = LoadIcon(NULL, IDI_APPLICATION);
|
||||
cls.lpszClassName = server_name;
|
||||
|
||||
RegisterClass(&cls);
|
||||
hWnd = CreateWindow(cls.lpszClassName, server_name, WS_OVERLAPPEDWINDOW,
|
||||
0, 0, 0, 0, NULL, NULL, NULL, NULL);
|
||||
ShowWindow(hWnd, SW_HIDE);
|
||||
|
||||
TrayIcon.cbSize = sizeof(TrayIcon);
|
||||
TrayIcon.uID = ID_ICON;
|
||||
TrayIcon.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
|
||||
TrayIcon.hIcon = hIcon = LoadImage(GetModuleHandle(NULL),
|
||||
MAKEINTRESOURCE(ID_ICON),
|
||||
IMAGE_ICON, 16, 16, 0);
|
||||
TrayIcon.hWnd = hWnd;
|
||||
snprintf(TrayIcon.szTip, sizeof(TrayIcon.szTip), "%s", server_name);
|
||||
TrayIcon.uCallbackMessage = WM_USER;
|
||||
Shell_NotifyIcon(NIM_ADD, &TrayIcon);
|
||||
|
||||
while (GetMessage(&msg, hWnd, 0, 0) > 0) {
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
|
||||
// Return the WM_QUIT value.
|
||||
return msg.wParam;
|
||||
}
|
||||
#elif defined(USE_COCOA)
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@interface Mongoose : NSObject<NSApplicationDelegate>
|
||||
- (void) openBrowser;
|
||||
- (void) shutDown;
|
||||
@end
|
||||
|
||||
@implementation Mongoose
|
||||
- (void) openBrowser {
|
||||
[[NSWorkspace sharedWorkspace]
|
||||
openURL:[NSURL URLWithString:
|
||||
[NSString stringWithUTF8String:get_url_to_first_open_port(ctx)]]];
|
||||
}
|
||||
- (void) editConfig {
|
||||
create_config_file(config_file);
|
||||
[[NSWorkspace sharedWorkspace]
|
||||
openFile:[NSString stringWithUTF8String:config_file]
|
||||
withApplication:@"TextEdit"];
|
||||
}
|
||||
- (void)shutDown{
|
||||
[NSApp terminate:nil];
|
||||
}
|
||||
@end
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
init_server_name();
|
||||
start_mongoose(argc, argv);
|
||||
|
||||
[NSAutoreleasePool new];
|
||||
[NSApplication sharedApplication];
|
||||
|
||||
// Add delegate to process menu item actions
|
||||
Mongoose *myDelegate = [[Mongoose alloc] autorelease];
|
||||
[NSApp setDelegate: myDelegate];
|
||||
|
||||
// Run this app as agent
|
||||
ProcessSerialNumber psn = { 0, kCurrentProcess };
|
||||
TransformProcessType(&psn, kProcessTransformToBackgroundApplication);
|
||||
SetFrontProcess(&psn);
|
||||
|
||||
// Add status bar menu
|
||||
id menu = [[NSMenu new] autorelease];
|
||||
|
||||
// Add version menu item
|
||||
[menu addItem:[[[NSMenuItem alloc]
|
||||
//initWithTitle:[NSString stringWithFormat:@"%s", server_name]
|
||||
initWithTitle:[NSString stringWithUTF8String:server_name]
|
||||
action:@selector(noexist) keyEquivalent:@""] autorelease]];
|
||||
|
||||
// Add configuration menu item
|
||||
[menu addItem:[[[NSMenuItem alloc]
|
||||
initWithTitle:@"Edit configuration"
|
||||
action:@selector(editConfig) keyEquivalent:@""] autorelease]];
|
||||
|
||||
// Add connect menu item
|
||||
[menu addItem:[[[NSMenuItem alloc]
|
||||
initWithTitle:@"Open web root in a browser"
|
||||
action:@selector(openBrowser) keyEquivalent:@""] autorelease]];
|
||||
|
||||
// Separator
|
||||
[menu addItem:[NSMenuItem separatorItem]];
|
||||
|
||||
// Add quit menu item
|
||||
[menu addItem:[[[NSMenuItem alloc]
|
||||
initWithTitle:@"Quit"
|
||||
action:@selector(shutDown) keyEquivalent:@"q"] autorelease]];
|
||||
|
||||
// Attach menu to the status bar
|
||||
id item = [[[NSStatusBar systemStatusBar]
|
||||
statusItemWithLength:NSVariableStatusItemLength] retain];
|
||||
[item setHighlightMode:YES];
|
||||
[item setImage:[NSImage imageNamed:@"mongoose_22x22.png"]];
|
||||
[item setMenu:menu];
|
||||
|
||||
// Run the app
|
||||
[NSApp activateIgnoringOtherApps:YES];
|
||||
[NSApp run];
|
||||
|
||||
mg_stop(ctx);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
#else
|
||||
int main(int argc, char *argv[]) {
|
||||
init_server_name();
|
||||
start_mongoose(argc, argv);
|
||||
printf("%s started on port(s) %s with web root [%s]\n",
|
||||
server_name, mg_get_option(ctx, "listening_ports"),
|
||||
mg_get_option(ctx, "document_root"));
|
||||
while (exit_flag == 0) {
|
||||
sleep(1);
|
||||
}
|
||||
printf("Exiting on signal %d, waiting for all threads to finish...",
|
||||
exit_flag);
|
||||
fflush(stdout);
|
||||
mg_stop(ctx);
|
||||
printf("%s", " done.\n");
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
#endif /* _WIN32 */
|
||||
-393
@@ -1,393 +0,0 @@
|
||||
#include "lua_5.2.1.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
static void *mmap(void *addr, int64_t len, int prot, int flags, int fd,
|
||||
int offset) {
|
||||
HANDLE fh = (HANDLE) _get_osfhandle(fd);
|
||||
HANDLE mh = CreateFileMapping(fh, 0, PAGE_READONLY, 0, 0, 0);
|
||||
void *p = MapViewOfFile(mh, FILE_MAP_READ, 0, 0, (size_t) len);
|
||||
CloseHandle(mh);
|
||||
return p;
|
||||
}
|
||||
#define munmap(x, y) UnmapViewOfFile(x)
|
||||
#define MAP_FAILED NULL
|
||||
#define MAP_PRIVATE 0
|
||||
#define PROT_READ 0
|
||||
#else
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
static const char *LUASOCKET = "luasocket";
|
||||
|
||||
// Forward declarations
|
||||
static void handle_request(struct mg_connection *);
|
||||
static int handle_lsp_request(struct mg_connection *, const char *,
|
||||
struct file *, struct lua_State *);
|
||||
|
||||
static void reg_string(struct lua_State *L, const char *name, const char *val) {
|
||||
lua_pushstring(L, name);
|
||||
lua_pushstring(L, val);
|
||||
lua_rawset(L, -3);
|
||||
}
|
||||
|
||||
static void reg_int(struct lua_State *L, const char *name, int val) {
|
||||
lua_pushstring(L, name);
|
||||
lua_pushinteger(L, val);
|
||||
lua_rawset(L, -3);
|
||||
}
|
||||
|
||||
static void reg_function(struct lua_State *L, const char *name,
|
||||
lua_CFunction func, struct mg_connection *conn) {
|
||||
lua_pushstring(L, name);
|
||||
lua_pushlightuserdata(L, conn);
|
||||
lua_pushcclosure(L, func, 1);
|
||||
lua_rawset(L, -3);
|
||||
}
|
||||
|
||||
static int lsp_sock_close(lua_State *L) {
|
||||
if (lua_gettop(L) > 0 && lua_istable(L, -1)) {
|
||||
lua_getfield(L, -1, "sock");
|
||||
closesocket((SOCKET) lua_tonumber(L, -1));
|
||||
} else {
|
||||
return luaL_error(L, "invalid :close() call");
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lsp_sock_recv(lua_State *L) {
|
||||
char buf[2000];
|
||||
int n;
|
||||
|
||||
if (lua_gettop(L) > 0 && lua_istable(L, -1)) {
|
||||
lua_getfield(L, -1, "sock");
|
||||
n = recv((SOCKET) lua_tonumber(L, -1), buf, sizeof(buf), 0);
|
||||
if (n <= 0) {
|
||||
lua_pushnil(L);
|
||||
} else {
|
||||
lua_pushlstring(L, buf, n);
|
||||
}
|
||||
} else {
|
||||
return luaL_error(L, "invalid :close() call");
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lsp_sock_send(lua_State *L) {
|
||||
const char *buf;
|
||||
size_t len, sent = 0;
|
||||
int n, sock;
|
||||
|
||||
if (lua_gettop(L) > 1 && lua_istable(L, -2) && lua_isstring(L, -1)) {
|
||||
buf = lua_tolstring(L, -1, &len);
|
||||
lua_getfield(L, -2, "sock");
|
||||
sock = (int) lua_tonumber(L, -1);
|
||||
while (sent < len) {
|
||||
if ((n = send(sock, buf + sent, len - sent, 0)) <= 0) {
|
||||
break;
|
||||
}
|
||||
sent += n;
|
||||
}
|
||||
lua_pushnumber(L, n);
|
||||
} else {
|
||||
return luaL_error(L, "invalid :close() call");
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const struct luaL_Reg luasocket_methods[] = {
|
||||
{"close", lsp_sock_close},
|
||||
{"send", lsp_sock_send},
|
||||
{"recv", lsp_sock_recv},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
static int lsp_connect(lua_State *L) {
|
||||
char ebuf[100];
|
||||
SOCKET sock;
|
||||
|
||||
if (lua_isstring(L, -3) && lua_isnumber(L, -2) && lua_isnumber(L, -1)) {
|
||||
sock = conn2(lua_tostring(L, -3), (int) lua_tonumber(L, -2),
|
||||
(int) lua_tonumber(L, -1), ebuf, sizeof(ebuf));
|
||||
if (sock == INVALID_SOCKET) {
|
||||
return luaL_error(L, ebuf);
|
||||
} else {
|
||||
lua_newtable(L);
|
||||
reg_int(L, "sock", sock);
|
||||
reg_string(L, "host", lua_tostring(L, -4));
|
||||
luaL_getmetatable(L, LUASOCKET);
|
||||
lua_setmetatable(L, -2);
|
||||
}
|
||||
} else {
|
||||
return luaL_error(L, "connect(host,port,is_ssl): invalid parameter given.");
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lsp_error(lua_State *L) {
|
||||
lua_getglobal(L, "mg");
|
||||
lua_getfield(L, -1, "onerror");
|
||||
lua_pushvalue(L, -3);
|
||||
lua_pcall(L, 1, 0, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Silently stop processing chunks.
|
||||
static void lsp_abort(lua_State *L) {
|
||||
int top = lua_gettop(L);
|
||||
lua_getglobal(L, "mg");
|
||||
lua_pushnil(L);
|
||||
lua_setfield(L, -2, "onerror");
|
||||
lua_settop(L, top);
|
||||
lua_pushstring(L, "aborting");
|
||||
lua_error(L);
|
||||
}
|
||||
|
||||
static int lsp(struct mg_connection *conn, const char *path,
|
||||
const char *p, int64_t len, lua_State *L) {
|
||||
int i, j, pos = 0, lines = 1, lualines = 0;
|
||||
char chunkname[MG_BUF_LEN];
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
if (p[i] == '\n') lines++;
|
||||
if (p[i] == '<' && p[i + 1] == '?') {
|
||||
for (j = i + 1; j < len ; j++) {
|
||||
if (p[j] == '\n') lualines++;
|
||||
if (p[j] == '?' && p[j + 1] == '>') {
|
||||
mg_write(conn, p + pos, i - pos);
|
||||
|
||||
snprintf(chunkname, sizeof(chunkname), "@%s+%i", path, lines);
|
||||
lua_pushlightuserdata(L, conn);
|
||||
lua_pushcclosure(L, lsp_error, 1);
|
||||
if (luaL_loadbuffer(L, p + (i + 2), j - (i + 2), chunkname)) {
|
||||
// Syntax error or OOM. Error message is pushed on stack.
|
||||
lua_pcall(L, 1, 0, 0);
|
||||
} else {
|
||||
// Success loading chunk. Call it.
|
||||
lua_pcall(L, 0, 0, 1);
|
||||
}
|
||||
|
||||
pos = j + 2;
|
||||
i = pos - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (lualines > 0) {
|
||||
lines += lualines;
|
||||
lualines = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (i > pos) {
|
||||
mg_write(conn, p + pos, i - pos);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lsp_write(lua_State *L) {
|
||||
int i, num_args;
|
||||
const char *str;
|
||||
size_t size;
|
||||
struct mg_connection *conn = lua_touserdata(L, lua_upvalueindex(1));
|
||||
|
||||
num_args = lua_gettop(L);
|
||||
for (i = 1; i <= num_args; i++) {
|
||||
if (lua_isstring(L, i)) {
|
||||
str = lua_tolstring(L, i, &size);
|
||||
mg_write(conn, str, size);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lsp_read(lua_State *L) {
|
||||
struct mg_connection *conn = lua_touserdata(L, lua_upvalueindex(1));
|
||||
char buf[1024];
|
||||
int len = mg_read(conn, buf, sizeof(buf));
|
||||
|
||||
if (len <= 0) return 0;
|
||||
lua_pushlstring(L, buf, len);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// mg.include: Include another .lp file
|
||||
static int lsp_include(lua_State *L) {
|
||||
struct mg_connection *conn = lua_touserdata(L, lua_upvalueindex(1));
|
||||
struct file file = STRUCT_FILE_INITIALIZER;
|
||||
if (handle_lsp_request(conn, lua_tostring(L, -1), &file, L)) {
|
||||
// handle_lsp_request returned an error code, meaning an error occured in
|
||||
// the included page and mg.onerror returned non-zero. Stop processing.
|
||||
lsp_abort(L);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// mg.cry: Log an error. Default value for mg.onerror.
|
||||
static int lsp_cry(lua_State *L){
|
||||
struct mg_connection *conn = lua_touserdata(L, lua_upvalueindex(1));
|
||||
cry(conn, "%s", lua_tostring(L, -1));
|
||||
return 0;
|
||||
}
|
||||
|
||||
// mg.redirect: Redirect the request (internally).
|
||||
static int lsp_redirect(lua_State *L) {
|
||||
struct mg_connection *conn = lua_touserdata(L, lua_upvalueindex(1));
|
||||
conn->request_info.uri = lua_tostring(L, -1);
|
||||
handle_request(conn);
|
||||
lsp_abort(L);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void prepare_lua_environment(struct mg_connection *conn, lua_State *L) {
|
||||
const struct mg_request_info *ri = mg_get_request_info(conn);
|
||||
extern void luaL_openlibs(lua_State *);
|
||||
int i;
|
||||
|
||||
luaL_openlibs(L);
|
||||
#ifdef USE_LUA_SQLITE3
|
||||
{ extern int luaopen_lsqlite3(lua_State *); luaopen_lsqlite3(L); }
|
||||
#endif
|
||||
|
||||
luaL_newmetatable(L, LUASOCKET);
|
||||
lua_pushliteral(L, "__index");
|
||||
luaL_newlib(L, luasocket_methods);
|
||||
lua_rawset(L, -3);
|
||||
lua_pop(L, 1);
|
||||
lua_register(L, "connect", lsp_connect);
|
||||
|
||||
if (conn == NULL) return;
|
||||
|
||||
// Register mg module
|
||||
lua_newtable(L);
|
||||
|
||||
reg_function(L, "read", lsp_read, conn);
|
||||
reg_function(L, "write", lsp_write, conn);
|
||||
reg_function(L, "cry", lsp_cry, conn);
|
||||
reg_function(L, "include", lsp_include, conn);
|
||||
reg_function(L, "redirect", lsp_redirect, conn);
|
||||
reg_string(L, "version", MONGOOSE_VERSION);
|
||||
|
||||
// Export request_info
|
||||
lua_pushstring(L, "request_info");
|
||||
lua_newtable(L);
|
||||
reg_string(L, "request_method", ri->request_method);
|
||||
reg_string(L, "uri", ri->uri);
|
||||
reg_string(L, "http_version", ri->http_version);
|
||||
reg_string(L, "query_string", ri->query_string);
|
||||
reg_int(L, "remote_ip", ri->remote_ip);
|
||||
reg_int(L, "remote_port", ri->remote_port);
|
||||
reg_int(L, "num_headers", ri->num_headers);
|
||||
lua_pushstring(L, "http_headers");
|
||||
lua_newtable(L);
|
||||
for (i = 0; i < ri->num_headers; i++) {
|
||||
reg_string(L, ri->http_headers[i].name, ri->http_headers[i].value);
|
||||
}
|
||||
lua_rawset(L, -3);
|
||||
lua_rawset(L, -3);
|
||||
|
||||
lua_setglobal(L, "mg");
|
||||
|
||||
// Register default mg.onerror function
|
||||
luaL_dostring(L, "mg.onerror = function(e) mg.write('\\nLua error:\\n', "
|
||||
"debug.traceback(e, 1)) end");
|
||||
}
|
||||
|
||||
static int lua_error_handler(lua_State *L) {
|
||||
const char *error_msg = lua_isstring(L, -1) ? lua_tostring(L, -1) : "?\n";
|
||||
|
||||
lua_getglobal(L, "mg");
|
||||
if (!lua_isnil(L, -1)) {
|
||||
lua_getfield(L, -1, "write"); // call mg.write()
|
||||
lua_pushstring(L, error_msg);
|
||||
lua_pushliteral(L, "\n");
|
||||
lua_call(L, 2, 0);
|
||||
luaL_dostring(L, "mg.write(debug.traceback(), '\\n')");
|
||||
} else {
|
||||
printf("Lua error: [%s]\n", error_msg);
|
||||
luaL_dostring(L, "print(debug.traceback(), '\\n')");
|
||||
}
|
||||
// TODO(lsm): leave the stack balanced
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mg_exec_lua_script(struct mg_connection *conn, const char *path,
|
||||
const void **exports) {
|
||||
int i;
|
||||
lua_State *L;
|
||||
|
||||
if (path != NULL && (L = luaL_newstate()) != NULL) {
|
||||
prepare_lua_environment(conn, L);
|
||||
lua_pushcclosure(L, &lua_error_handler, 0);
|
||||
|
||||
lua_pushglobaltable(L);
|
||||
if (exports != NULL) {
|
||||
for (i = 0; exports[i] != NULL && exports[i + 1] != NULL; i += 2) {
|
||||
lua_pushstring(L, exports[i]);
|
||||
lua_pushcclosure(L, (lua_CFunction) exports[i + 1], 0);
|
||||
lua_rawset(L, -3);
|
||||
}
|
||||
}
|
||||
|
||||
if (luaL_loadfile(L, path) != 0) {
|
||||
lua_error_handler(L);
|
||||
}
|
||||
lua_pcall(L, 0, 0, -2);
|
||||
lua_close(L);
|
||||
}
|
||||
}
|
||||
|
||||
static void lsp_send_err(struct mg_connection *conn, struct lua_State *L,
|
||||
const char *fmt, ...) {
|
||||
char buf[MG_BUF_LEN];
|
||||
va_list ap;
|
||||
int len;
|
||||
|
||||
va_start(ap, fmt);
|
||||
len = vsnprintf(buf, sizeof(buf), fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (L == NULL) {
|
||||
send_http_error(conn, 500, http_500_error, "%s", buf);
|
||||
} else {
|
||||
lua_pushstring(L, buf);
|
||||
lua_error(L);
|
||||
}
|
||||
}
|
||||
|
||||
static int handle_lsp_request(struct mg_connection *conn, const char *path,
|
||||
struct file *filep, struct lua_State *ls) {
|
||||
void *p = NULL;
|
||||
lua_State *L = NULL;
|
||||
int error = 1;
|
||||
|
||||
// We need both mg_stat to get file size, and mg_fopen to get fd
|
||||
if (!mg_stat(conn, path, filep) || !mg_fopen(conn, path, "r", filep)) {
|
||||
lsp_send_err(conn, ls, "File [%s] not found", path);
|
||||
} else if (filep->membuf == NULL &&
|
||||
(p = mmap(NULL, (size_t) filep->size, PROT_READ, MAP_PRIVATE,
|
||||
fileno(filep->fp), 0)) == MAP_FAILED) {
|
||||
lsp_send_err(conn, ls, "mmap(%s, %zu, %d): %s", path, (size_t) filep->size,
|
||||
fileno(filep->fp), strerror(errno));
|
||||
} else if ((L = ls != NULL ? ls : luaL_newstate()) == NULL) {
|
||||
send_http_error(conn, 500, http_500_error, "%s", "luaL_newstate failed");
|
||||
} else {
|
||||
// We're not sending HTTP headers here, Lua page must do it.
|
||||
if (ls == NULL) {
|
||||
prepare_lua_environment(conn, L);
|
||||
if (conn->ctx->callbacks.init_lua != NULL) {
|
||||
conn->ctx->callbacks.init_lua(conn, L);
|
||||
}
|
||||
}
|
||||
error = lsp(conn, path, filep->membuf == NULL ? p : filep->membuf,
|
||||
filep->size, L);
|
||||
}
|
||||
|
||||
if (L != NULL && ls == NULL) lua_close(L);
|
||||
if (p != NULL) munmap(p, filep->size);
|
||||
mg_fclose(filep);
|
||||
return error;
|
||||
}
|
||||
@@ -1,589 +0,0 @@
|
||||
%PDF-1.5␍%âãÏÓ
|
||||
1 0 obj␍<</Metadata 2 0 R/OCProperties<</D<</ON[5 0 R]/Order 6 0 R/RBGroups[]>>/OCGs[5 0 R]>>/Pages 3 0 R/Type/Catalog>>␍endobj␍2 0 obj␍<</Length 16195/Subtype/XML/Type/Metadata>>stream
|
||||
<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
|
||||
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.3-c011 66.145661, 2012/02/06-14:56:27 ">
|
||||
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
||||
<rdf:Description rdf:about=""
|
||||
xmlns:xmp="http://ns.adobe.com/xap/1.0/"
|
||||
xmlns:xmpGImg="http://ns.adobe.com/xap/1.0/g/img/">
|
||||
<xmp:CreatorTool>Adobe Illustrator CS6 (Windows)</xmp:CreatorTool>
|
||||
<xmp:CreateDate>2013-01-02T17:27:47+01:00</xmp:CreateDate>
|
||||
<xmp:ModifyDate>2013-01-02T17:27:47Z</xmp:ModifyDate>
|
||||
<xmp:MetadataDate>2013-01-02T17:27:47Z</xmp:MetadataDate>
|
||||
<xmp:Thumbnails>
|
||||
<rdf:Alt>
|
||||
<rdf:li rdf:parseType="Resource">
|
||||
<xmpGImg:width>256</xmpGImg:width>
|
||||
<xmpGImg:height>228</xmpGImg:height>
|
||||
<xmpGImg:format>JPEG</xmpGImg:format>
|
||||
<xmpGImg:image>/9j/4AAQSkZJRgABAgEASABIAAD/7QAsUGhvdG9zaG9wIDMuMAA4QklNA+0AAAAAABAASAAAAAEA
AQBIAAAAAQAB/+4ADkFkb2JlAGTAAAAAAf/bAIQABgQEBAUEBgUFBgkGBQYJCwgGBggLDAoKCwoK
DBAMDAwMDAwQDA4PEA8ODBMTFBQTExwbGxscHx8fHx8fHx8fHwEHBwcNDA0YEBAYGhURFRofHx8f
Hx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8f/8AAEQgA5AEAAwER
AAIRAQMRAf/EAaIAAAAHAQEBAQEAAAAAAAAAAAQFAwIGAQAHCAkKCwEAAgIDAQEBAQEAAAAAAAAA
AQACAwQFBgcICQoLEAACAQMDAgQCBgcDBAIGAnMBAgMRBAAFIRIxQVEGE2EicYEUMpGhBxWxQiPB
UtHhMxZi8CRygvElQzRTkqKyY3PCNUQnk6OzNhdUZHTD0uIIJoMJChgZhJRFRqS0VtNVKBry4/PE
1OT0ZXWFlaW1xdXl9WZ2hpamtsbW5vY3R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo+Ck5SVlpeYmZ
qbnJ2en5KjpKWmp6ipqqusra6voRAAICAQIDBQUEBQYECAMDbQEAAhEDBCESMUEFURNhIgZxgZEy
obHwFMHR4SNCFVJicvEzJDRDghaSUyWiY7LCB3PSNeJEgxdUkwgJChgZJjZFGidkdFU38qOzwygp
0+PzhJSktMTU5PRldYWVpbXF1eX1RlZmdoaWprbG1ub2R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo
+DlJWWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq+v/aAAwDAQACEQMRAD8A9U4q7FXYq7FXYq7FXYq7
FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FVsssUUbSyuscSAs7sQqqo3JJPQDFWOL+ZXk
Rrj6uNat/UrTkSQn/Iwjh+OR4wx4wyG3ube4iEtvKk0TfZkjYMp+RFRkmSpirsVYj+ZvnFfLPl2R
4XA1O8rDYr3BI+KT5IPxpkJyoMJyoI38vbs3fknRZmbkwtY4yx3NYh6f/GuGPJMeTIckydirsVdi
rsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVeG/nX55mutQby3YSlbO1I+v
lD/eTdfTNP2Y+4/m+WUZJdGnJLoiX/Lfybo/5fxavr31prq4SCWS4t6c4WnA4osbHgVUt8Vdz2pj
wgCyvAAN3nd9aW1gzXGiayLmDvx9S1uFB2AaNqBuv7DNkGs+SyHzf5sh/utavkFa0W5mA29uWPEV
4ijI/wAxfPMYIXW7o1/mfl/xKuHjKeMpbrfmLW9cnjn1a7e7liT042eg4rWuwUAfTgJJQSS9/wDy
ZufW/L+xStTBJPEf+RrOPwfL8fJvx8mb5Nm7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7
FXYq7FXYq7FXYq7FUr8063Hofl6/1V6H6rEWjU9GkPwxqf8AWdgMEjQRI0Hy9pdhqHmHX4LRGMt7
qM/xyHclnPJ5G+QqxzF5uMBZer/n3fww6bpek290EKsXmsFO5jVQsbt7KQQK9foy3IejblLxbKml
2KuxV2KvWvyR8721lI3lq9pGl1KZbGc7fvWAUxN/rcRx99u4y3HLo245dHtuXNzsVdirsVdirsVd
irsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVeffnjfRQeSGt2I53lxFGi9/gJkJ/4TK8
h2a8h2Yl+TWn6RpNrdebNauYrSM8rawaZgtQN5XUHdidlFPfIY6G5Y4xW5YP5+vtM1DzZf32m3cl
7aXL+ok0oYEEihQc6HitKL7ZCXNhI7sewMUw0bQNZ1q5a30u0e6lQcnCUAVfFmYhVHzOICQCUZfe
SPNVlA9xNp0j28ZIkngKXEakdeTwmRRT3ONJMCEjxYqlupaZaMU4/EXHUBRyJHuAMVfR35U+cbjz
L5ff63ve2DiCaQmpkUrVHbp8RGx9xmRCVhyISsM1ybN2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2Ku
xV2KuxV2KuxV2KuxV2KuxV87/nF5wi13zAtlZvz0/S+USOD8LzMf3jj2FAo+Ve+Y+SVlx8krLAmd
2ChmJCiigmtBWtBkGC3FXYqyifzCLv8AK++8qaYq2GryTJK8wf0xexcqvG0jEBWApsTxYCnU0MMt
mFDm5OCYB3Tb/nHLyP590bzNdahqNpPpujPbFJYriqCeRipj4xk78dzzp7d8r0eKYlZ2DlZZAhEf
nXp3ly18wRzaXNEL2YN+kbOL9hxTi54/CrPXcde/fMrIBezgZALedxuyOrrsykEfRkGt67+QV2qa
nq1on93cwxzotfsmFirD/ksPwy3EW3E9oy5udirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsV
dirsVdirsVdiryD80PzahWGbQ/LsweVwY7zUIzVVU7FIWHUnuw6dt9xVOfQNU59A8XylpdirsVdi
rsVTy287+bbXTf0Zb6rcRWQHFYlehVT+yrfaUewOHiLLiKSMxYlmJLE1JPUnAxZ9+UXkjSvM2o3s
mqgyWlgkZ+rKxTm8palWUhuICHofDJwjZbMcbet6f+XuheX9QXVtAhktpkHCe2EjyRywtTmtJC7c
h9pd+op0y3grcNoiByZbk2TsVdirsVdirsVdirsVdirsVdirsVdirsVdirH9Z8/eT9HLJfapCsq7
NDGTNID4FIw5H05EyAYmQDDtR/P7y9CzLYafc3ZHRpCkKk+3941PmMgcoYHKEof/AJyFuix4aGgX
sDcEn7/TGDxUeK0v/OQt3yHLRIytdwLgg0+fpnHxV8VHW3/OQmntT6zo00Xj6Uyyf8SWPD4qfFTQ
fnx5ONs0noXgmUfDA0aVY+HIOVw+KE+IHm3nL82PMXmNHtYyNO0xtjawsSzjwlk2LfIAD2yuUyWu
UyWEZBg7FXYq7FXYq7FV8cMktfTXkR+yOv0DqfoxV0kMsRAkRkJFQGBFR9OKsl/LzzbeeWdeF3FC
9zayr6d7boKkx1ryX/KU7j7u+GMqLKEqL3fR/P2m69epZaNDcSOV9S5nliaKOGMdal/tOTsoAP3D
LxO+TeJWyjJsnYq7FXYq7FXYq7FXYq7FXYq7FXYqoXt9ZWNs91ezx21vGKvLKwRR9JxtbeZeZvz3
0q1LwaBbG/lG31qascHzVdnf/hcqOXuajk7nl2v/AJgebddLLfajJ6Df8esJ9KKngVSnL/ZVysyJ
azIljuRYuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxVWt3uSwhh5OZCAIQOYZjsPg3BP0Yq9G8r/k1
5l1f059bkOl2H2hAQPXI/wAmIfDH/st/bLI4yebYMZPN7H5Z8paH5as2tdKg9ISEGaViWkkZdgXY
/PoNsuEQG4RATjCl2KuxV2KuxV2KuxV2KuxV2KuxVgvnv819I8t87K0Av9YGxgU/u4j/AMWsO/8A
kjfxpkJTphKdPCfMXmrXfMN39Z1W6aYgn0oR8MUYPZEGw+fU98oMiWgyJSjAh2KuxV2KuxV2KuxV
2KuxV2KuxV2KuxV2KuxV2KvS/wAh9LW581XN861WxtjwPhJKwUH/AIDllmIbtmMbvfMvb3Yq7FXY
q7FXYq7FXYq7FXYq7FXYq8p/Nb803055NB0KUfXaFb68U1MNdjGh/wB+eJ/Z+fSqc+gapz6B4ezM
zFmJZmNSTuSTlLS1irsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdir3D/nH2y4aPq17T+/uI
4a/8YU5f8zsuxN2J6vlra7FXYq7FXYq7FXYq7FXYq7FXYqwX81fPv+GtJFpZOP0zfKRB3MUfRpSP
Hsvv8shOVMJyp85szOxdyWZjVmO5JPUk5juO1irsVdirsVdirsVdirsVdirsVdirsVdirsVdirsV
dirsVfTH5TaQ+meRdPWReMt2Gu3H/GY1T/knxzIgKDkQFBl+TZuxV2KuxV2KuxV2KuxV2KuxVC6p
qVppenXOoXb8La1jaSVvZR0HuegwE0gmnyt5m8wXnmDW7rVbs/HO3wR9QkY2RB/qrmMTZcYmyleB
DsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVT7yR5Zm8x+Y7TTUB9At6l24/ZgQ1c/T9k
e5wxFllEWX1PHGkcaxxqFjQBUUbAACgAzKcldirsVdirsVdirsVdirsVdirsVeO/nz5pIFt5bt32
YC5vqHtX91Gfu5Ef6uU5ZdGnLLo8aypqdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirs
VfR35T+Sf8OaF9Zu4+OragFkuARvHH1SL2IrVvf5ZkQjQciEaDOcmzdirsVdirsVdirsVdirsVdi
qld3UFpazXVwwSC3RpZXPRUQFmP0AYq+TvMOsz61rd7qs/8AeXcrSBf5V6Iv+xUAZik2XFJspdgQ
7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXqH5M+Qjqd6PMOoR/7j7N/9DjYbSzr+1v1
WP8A4l8jlmON7tmON7vd8vb3YLine truncated
|
||||
</rdf:li>
|
||||
</rdf:Alt>
|
||||
</xmp:Thumbnails>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about=""
|
||||
xmlns:xmpTPg="http://ns.adobe.com/xap/1.0/t/pg/"
|
||||
xmlns:stDim="http://ns.adobe.com/xap/1.0/sType/Dimensions#"
|
||||
xmlns:xmpG="http://ns.adobe.com/xap/1.0/g/">
|
||||
<xmpTPg:NPages>1</xmpTPg:NPages>
|
||||
<xmpTPg:HasVisibleTransparency>False</xmpTPg:HasVisibleTransparency>
|
||||
<xmpTPg:HasVisibleOverprint>False</xmpTPg:HasVisibleOverprint>
|
||||
<xmpTPg:MaxPageSize rdf:parseType="Resource">
|
||||
<stDim:w>64.000000</stDim:w>
|
||||
<stDim:h>64.000000</stDim:h>
|
||||
<stDim:unit>Points</stDim:unit>
|
||||
</xmpTPg:MaxPageSize>
|
||||
<xmpTPg:PlateNames>
|
||||
<rdf:Seq>
|
||||
<rdf:li>Cyan</rdf:li>
|
||||
<rdf:li>Magenta</rdf:li>
|
||||
<rdf:li>Yellow</rdf:li>
|
||||
<rdf:li>Black</rdf:li>
|
||||
</rdf:Seq>
|
||||
</xmpTPg:PlateNames>
|
||||
<xmpTPg:SwatchGroups>
|
||||
<rdf:Seq>
|
||||
<rdf:li rdf:parseType="Resource">
|
||||
<xmpG:groupName>Default Swatch Group</xmpG:groupName>
|
||||
<xmpG:groupType>0</xmpG:groupType>
|
||||
</rdf:li>
|
||||
</rdf:Seq>
|
||||
</xmpTPg:SwatchGroups>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about=""
|
||||
xmlns:illustrator="http://ns.adobe.com/illustrator/1.0/">
|
||||
<illustrator:Type>Document</illustrator:Type>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about=""
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||
<dc:format>application/pdf</dc:format>
|
||||
<dc:title>
|
||||
<rdf:Alt>
|
||||
<rdf:li xml:lang="x-default">Mongoo 3 smooth green</rdf:li>
|
||||
</rdf:Alt>
|
||||
</dc:title>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about=""
|
||||
xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/">
|
||||
<xmpMM:RenditionClass>proof:pdf</xmpMM:RenditionClass>
|
||||
<xmpMM:DocumentID>uuid:a2f6b830-2598-49b9-8770-4f9fa14f1be3</xmpMM:DocumentID>
|
||||
<xmpMM:InstanceID>uuid:42245d04-b042-4038-b450-94c7cfb8ee6f</xmpMM:InstanceID>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about=""
|
||||
xmlns:pdf="http://ns.adobe.com/pdf/1.3/">
|
||||
<pdf:Producer>Adobe PDF library 10.01</pdf:Producer>
|
||||
</rdf:Description>
|
||||
</rdf:RDF>
|
||||
</x:xmpmeta>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<?xpacket end="w"?>
|
||||
endstream␍endobj␍3 0 obj␍<</Count 1/Kids[7 0 R]/Type/Pages>>␍endobj␍7 0 obj␍<</ArtBox[0.643066 4.46875 63.2324 59.6494]/BleedBox[0.0 0.0 64.0 64.0]/Contents 8 0 R/LastModified(D:20130102172747+01'00')/MediaBox[0.0 0.0 64.0 64.0]/Parent 3 0 R/PieceInfo<</Illustrator 9 0 R>>/Resources<</ExtGState<</GS0 10 0 R>>/Properties<</MC0 5 0 R>>>>/Thumb 11 0 R/TrimBox[0.0 0.0 64.0 64.0]/Type/Page>>␍endobj␍8 0 obj␍<</Filter/FlateDecode/Length 1251>>stream
|
||||
H‰t–KŽ•7…çÿ*¼�kì²]¶§!#Y@+�A "±û|§Ü}i"E4}»ü¨Ç©SÇ÷Õ¯¯Ó«·¯Kúéç×éú|•ä]?7þùãú=ýu•Ül¤’»u~7éˇëÕ›÷%}øûúœj*ü«©ö<gÉfÞ{zøtiãÓu«yøL–K[øÍ¥®ÄRK_ÙÂoÌb5ÝêÊ}Xº�\pp«5ouµ§‡ëÖòžø°�}�ÔKøºÕ�7Oß.㪱P
|
||||
Õ¼†‡Ûʹ¯—åÞ,üY›ªhN,Ï«,,ëºjyt#V˶å»äéÆîZ-vw_©åÚ”é¬ÅÙ™{ìŽ<¨¥äíÖÄ/‡ÌG˜»ê°NùЏըÙ#�Îåª"
|
||||
Þw\¨»§ÇËH;ʹ�•¬e¯Ç¡¨qùýþC€Pq¸ù°D,OrµžW·€Ö÷ÔiúÑçk¢EÓmåmç|9Φ%eÒ´Õ,"�CºÍ<F�¬¦ºÛÆÒ�ä¶:Y)žÍ¥;Í6•¨¤h#‘¢À8âɆæŽ>Ò»\µ¢(JØ\›^v@_ÈŸ=,ñ<•Ûf€³pÒÈÐOǽˆ!,L÷XèKå²ÐK‹nP.6mj~X±ì,¬ÚO»è. 6oDh:�œw:ĉ G‡a÷Ȃh½žŠ`ÖhJ˃,¿ÊÁò㱪€1³G›j 'ž6ì„55WÌ`mu��¢¼E*âdžpƒyé\„—¤×-C*�ß›s�ÐД'ÜÁ"=E‚N’ÕÓS¹¥B€à¤êÇ«“ÇàôŽšî64nSxq~Žž åÄŸî×%›D£†³SMSqXcXÕöV¹␍Ö[¶&Žê–è)øÜ¼˜ì…~¨␍H–8Â]@ôVí">vñ°„Ikw»,ãP0QºIl†§k[jHž ñªaµc¸èg-¢2*u]Ù | ||||