Compare commits
718 Commits
mp-2023_08
...
mp-2025_10
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
31e677a4ae | ||
|
|
4fb9e2ecdf | ||
|
|
bb9f86211d | ||
|
|
2f694f983a | ||
|
|
f858b5b3de | ||
|
|
32bf7c0da4 | ||
|
|
aaf460ec6f | ||
|
|
ffc86b3e61 | ||
|
|
89228ed03b | ||
|
|
ced89d9845 | ||
|
|
617c8551dc | ||
|
|
c32be5cd38 | ||
|
|
7c320b210f | ||
|
|
0fa4c6c8b5 | ||
|
|
9caf468b86 | ||
|
|
55ac83820e | ||
|
|
cfa071c6de | ||
|
|
39dba4ccb8 | ||
|
|
9fec57511a | ||
|
|
01aca2d3b7 | ||
|
|
5a16117240 | ||
|
|
d0c8b3b284 | ||
|
|
1aeeed9845 | ||
|
|
624b1648b5 | ||
|
|
1d6bb38d89 | ||
|
|
28cf031b46 | ||
|
|
c9cfcc5dc4 | ||
|
|
dd577be872 | ||
|
|
2a1af6f947 | ||
|
|
15728e27ca | ||
|
|
0095b38c9f | ||
|
|
9a379f12b2 | ||
|
|
023cabbc1b | ||
|
|
a35211e427 | ||
|
|
8629e52749 | ||
|
|
81e9078b80 | ||
|
|
dafe32792a | ||
|
|
3f9e16f038 | ||
|
|
5bd1e06850 | ||
|
|
5040ccc065 | ||
|
|
494e7b3fbc | ||
|
|
8d22d386b4 | ||
|
|
0f712717d8 | ||
|
|
f201ac4bd6 | ||
|
|
408b173ae1 | ||
|
|
12a64b8c91 | ||
|
|
6920117ba1 | ||
|
|
8d188976eb | ||
|
|
9770cd8d6d | ||
|
|
68829f6428 | ||
|
|
cc00f8e64a | ||
|
|
d08d30d297 | ||
|
|
90f0590d18 | ||
|
|
732eb4f53d | ||
|
|
666e7690a6 | ||
|
|
42e477098c | ||
|
|
162d6d9f4e | ||
|
|
13ee628b8d | ||
|
|
124815079a | ||
|
|
c1afb05250 | ||
|
|
5c24750acc | ||
|
|
4d6edf3fb6 | ||
|
|
b13bace79f | ||
|
|
60a3f1f324 | ||
|
|
860310de7f | ||
|
|
65c89fab07 | ||
|
|
8da865928a | ||
|
|
6b39e0bfb1 | ||
|
|
124e471364 | ||
|
|
8178901ffb | ||
|
|
3fd460637a | ||
|
|
5cd308d10c | ||
|
|
a0e18c80dc | ||
|
|
b0ce010dc8 | ||
|
|
8805712aea | ||
|
|
a1d6f80c36 | ||
|
|
3e00ac4dfb | ||
|
|
fb365c7e1d | ||
|
|
d7145198a1 | ||
|
|
9f6adf7a98 | ||
|
|
348c3a8853 | ||
|
|
7f301d271b | ||
|
|
8f2bd23dc5 | ||
|
|
8db57a7875 | ||
|
|
785f479921 | ||
|
|
61f69f45b0 | ||
|
|
90f6ce73e4 | ||
|
|
3bda196b79 | ||
|
|
757f4fca4f | ||
|
|
54b4693b2e | ||
|
|
1c8e9134bf | ||
|
|
1915133093 | ||
|
|
53e076c2ad | ||
|
|
3ea7170473 | ||
|
|
0dc9f0330c | ||
|
|
17a7dddd02 | ||
|
|
a81acf7b19 | ||
|
|
d7e4ee4cca | ||
|
|
5866a55067 | ||
|
|
40282486f6 | ||
|
|
2b2c41867f | ||
|
|
679865f68b | ||
|
|
5b459ef5ac | ||
|
|
9685e45861 | ||
|
|
fbda9cf228 | ||
|
|
552cd5b2ae | ||
|
|
3926b01b13 | ||
|
|
ffaa27ca24 | ||
|
|
9a1c5799aa | ||
|
|
85e66c352d | ||
|
|
d1b67a4819 | ||
|
|
51d55128a9 | ||
|
|
52a5078706 | ||
|
|
2d15091b0c | ||
|
|
81598881d1 | ||
|
|
4a74a9990f | ||
|
|
6c1e8a45ff | ||
|
|
808a7c4258 | ||
|
|
80ca6e0ac5 | ||
|
|
0989543b1b | ||
|
|
36195f88e0 | ||
|
|
3b916facf4 | ||
|
|
9d59bf31e6 | ||
|
|
a256c6261c | ||
|
|
21830321f7 | ||
|
|
eb27d223fb | ||
|
|
33cae3ab26 | ||
|
|
1612065d8a | ||
|
|
eac37b9927 | ||
|
|
b95a4fa872 | ||
|
|
81669a5442 | ||
|
|
3270a71cb0 | ||
|
|
5ae7f821e4 | ||
|
|
224aca5c41 | ||
|
|
9600be78a5 | ||
|
|
246d00a220 | ||
|
|
809439fd26 | ||
|
|
86741a0e50 | ||
|
|
41843cbab9 | ||
|
|
64854506e5 | ||
|
|
463385a296 | ||
|
|
b97fc98bc1 | ||
|
|
9b86aea7ed | ||
|
|
5bfb49d9e1 | ||
|
|
32a0ad5eae | ||
|
|
65593f95ad | ||
|
|
ec3774c7a5 | ||
|
|
4bd462ea59 | ||
|
|
77d3a201f5 | ||
|
|
127525e3ec | ||
|
|
465e750e3c | ||
|
|
6e062d3f60 | ||
|
|
7efaf720cc | ||
|
|
66ac029a69 | ||
|
|
bae188ddee | ||
|
|
87788fa93c | ||
|
|
5013bb8e29 | ||
|
|
08d420a871 | ||
|
|
3a7951be16 | ||
|
|
6a3f6be8a9 | ||
|
|
6c3926c1e4 | ||
|
|
8467408fd8 | ||
|
|
6bb499740d | ||
|
|
fc073696f8 | ||
|
|
102996f69f | ||
|
|
f9d721ac02 | ||
|
|
6bf8f03fbb | ||
|
|
fa404a5fcf | ||
|
|
3592a745d3 | ||
|
|
7c01aa255f | ||
|
|
d9e7d4df81 | ||
|
|
9b1badb310 | ||
|
|
0dc4a3a952 | ||
|
|
32bd3bc2f9 | ||
|
|
3f2ae9dd03 | ||
|
|
7fbc616ce4 | ||
|
|
8c13f9fdf7 | ||
|
|
6c5dc21f6a | ||
|
|
eb1392f3fd | ||
|
|
2b25fed2cd | ||
|
|
66b298d977 | ||
|
|
1091ec1dee | ||
|
|
d0b5f84316 | ||
|
|
ae1e4c3e37 | ||
|
|
78cbbf334e | ||
|
|
c8c12bb892 | ||
|
|
ae1853ba62 | ||
|
|
e8423ae97f | ||
|
|
597504fb08 | ||
|
|
59a0962420 | ||
|
|
323a5b76be | ||
|
|
b7234a6da2 | ||
|
|
4a5ba97b85 | ||
|
|
bdd710fc5c | ||
|
|
535a695c50 | ||
|
|
357ffe4e17 | ||
|
|
349b4a929a | ||
|
|
a06d245345 | ||
|
|
83225c453d | ||
|
|
fa94190345 | ||
|
|
68aa3beab8 | ||
|
|
3cd23d5f60 | ||
|
|
003f53b0b7 | ||
|
|
c1ea4212f2 | ||
|
|
3283a38981 | ||
|
|
3054274da5 | ||
|
|
2d84198e54 | ||
|
|
f3544f5e93 | ||
|
|
04c02b5e33 | ||
|
|
b709b7e624 | ||
|
|
8c397dd6b2 | ||
|
|
6e923ce075 | ||
|
|
245d44c05d | ||
|
|
4f497fc41a | ||
|
|
e32e8e7c13 | ||
|
|
f3020562bf | ||
|
|
fbb710a4e3 | ||
|
|
cbd498150f | ||
|
|
691ee3c71b | ||
|
|
280d5828bf | ||
|
|
6ecc1721b0 | ||
|
|
1824e8ccdf | ||
|
|
0a45e38939 | ||
|
|
81b008af0c | ||
|
|
439e787d37 | ||
|
|
d242d63c2e | ||
|
|
86982d0000 | ||
|
|
f549ef5d27 | ||
|
|
fe2eaafb7b | ||
|
|
caf149fe8b | ||
|
|
c540135705 | ||
|
|
734c237666 | ||
|
|
85d445ec61 | ||
|
|
b059f4a56e | ||
|
|
b56ab22117 | ||
|
|
5bda393b10 | ||
|
|
4ad508eca6 | ||
|
|
7f856dacf6 | ||
|
|
b6ba56a564 | ||
|
|
f930b846c2 | ||
|
|
fc5394a5c9 | ||
|
|
725ff96425 | ||
|
|
bfd0cd77a9 | ||
|
|
548a7634b7 | ||
|
|
3e4637e174 | ||
|
|
20b7c3f50d | ||
|
|
9206341032 | ||
|
|
6383d18e0e | ||
|
|
cfc7dc6320 | ||
|
|
72acef3aaf | ||
|
|
850975a85b | ||
|
|
68ee246216 | ||
|
|
2ba802bb06 | ||
|
|
688129cf08 | ||
|
|
81721ab7eb | ||
|
|
bf50871208 | ||
|
|
cbf88e05fe | ||
|
|
a808450fa2 | ||
|
|
033b7cd4db | ||
|
|
cd6a918533 | ||
|
|
63ebcbadc9 | ||
|
|
b2802a37aa | ||
|
|
1e95b317bf | ||
|
|
78fec171f9 | ||
|
|
8bfaabcf27 | ||
|
|
2b08847cf7 | ||
|
|
9ea722607f | ||
|
|
409155f0d0 | ||
|
|
026a943648 | ||
|
|
aeb6df5685 | ||
|
|
06886e0094 | ||
|
|
b498a445b2 | ||
|
|
876e9ac7b9 | ||
|
|
a89b875872 | ||
|
|
0ce70e48b1 | ||
|
|
bf583a1aa5 | ||
|
|
1533f82ec4 | ||
|
|
8a43bc252f | ||
|
|
ffcc5c0d9f | ||
|
|
c51043d72a | ||
|
|
2cb534df85 | ||
|
|
4f30623f2d | ||
|
|
b9ac7c65fa | ||
|
|
cef487fb3a | ||
|
|
284539fd52 | ||
|
|
08a1313ba5 | ||
|
|
7349014bd6 | ||
|
|
12cfe2ff4b | ||
|
|
ae1892f196 | ||
|
|
dbad237826 | ||
|
|
56e222a97e | ||
|
|
888792a201 | ||
|
|
41867ed01a | ||
|
|
b82e0d02df | ||
|
|
cd1fce313e | ||
|
|
5153bd2f69 | ||
|
|
d4ad6844e3 | ||
|
|
4f610c68a2 | ||
|
|
3582659018 | ||
|
|
1f537849a9 | ||
|
|
e6d0118ff3 | ||
|
|
ff7d47e155 | ||
|
|
8ae50a8d60 | ||
|
|
08411d9430 | ||
|
|
9bd3182bd5 | ||
|
|
c45eb6cca2 | ||
|
|
b229b39ab8 | ||
|
|
87b5e01581 | ||
|
|
8188f33345 | ||
|
|
7403b6650b | ||
|
|
6bbf2ba788 | ||
|
|
06b0ed8551 | ||
|
|
ada19028e0 | ||
|
|
1e5de0da23 | ||
|
|
bb14dd4c22 | ||
|
|
188e7da379 | ||
|
|
982c9bd649 | ||
|
|
fec37bd221 | ||
|
|
120e3e1e6b | ||
|
|
8d1661d8e4 | ||
|
|
18f61f4d63 | ||
|
|
be74442e7f | ||
|
|
061119819f | ||
|
|
0b8cb929b7 | ||
|
|
f1c858e3a7 | ||
|
|
3fc7eff424 | ||
|
|
36050b14c5 | ||
|
|
fa6acd8e52 | ||
|
|
dbf7f76baa | ||
|
|
18be337160 | ||
|
|
0bd6ef8db4 | ||
|
|
7fb1722c70 | ||
|
|
279d92e338 | ||
|
|
a26dd6f2a5 | ||
|
|
785e4ef28c | ||
|
|
dff347bcb7 | ||
|
|
619ac1564e | ||
|
|
581eeff996 | ||
|
|
b4e747c3db | ||
|
|
04dec73988 | ||
|
|
af75532ba7 | ||
|
|
335163f887 | ||
|
|
b3274466a3 | ||
|
|
064e84f5e8 | ||
|
|
18bc231951 | ||
|
|
9a19bf739d | ||
|
|
9e6feecb88 | ||
|
|
baf77ed182 | ||
|
|
b2f7232422 | ||
|
|
961568f721 | ||
|
|
042db13994 | ||
|
|
ba434d88a2 | ||
|
|
d32e2f4b81 | ||
|
|
e40139fee2 | ||
|
|
d8612a01ca | ||
|
|
474e63c395 | ||
|
|
ceaeb756fb | ||
|
|
603a8e93d0 | ||
|
|
4fdfd77a54 | ||
|
|
6b5f5e877d | ||
|
|
77bb64fbb6 | ||
|
|
92d5e30f3c | ||
|
|
349c11d641 | ||
|
|
027edb9aba | ||
|
|
868c2b32f8 | ||
|
|
2acd25e805 | ||
|
|
b730fd068c | ||
|
|
3e9aeeed05 | ||
|
|
158cf994c5 | ||
|
|
391c06e7e5 | ||
|
|
fa5acddcbe | ||
|
|
7d233136eb | ||
|
|
a4975038b4 | ||
|
|
229e68077c | ||
|
|
143180d68b | ||
|
|
c065415713 | ||
|
|
b01e8ff004 | ||
|
|
de94590fa0 | ||
|
|
b3d7d492d7 | ||
|
|
d29147fe57 | ||
|
|
a0898b8327 | ||
|
|
2ca246deca | ||
|
|
c1d347b70b | ||
|
|
381afa97f4 | ||
|
|
cb379d4149 | ||
|
|
aceffdfad2 | ||
|
|
8ece026f2d | ||
|
|
d000c8621e | ||
|
|
cf1eba68f0 | ||
|
|
b6800e538d | ||
|
|
b8fbbb7125 | ||
|
|
4b4753415a | ||
|
|
1c053d0492 | ||
|
|
44b8848996 | ||
|
|
550967c176 | ||
|
|
e713711a61 | ||
|
|
613a7e629d | ||
|
|
5026a7b753 | ||
|
|
75b602811c | ||
|
|
2897aece2c | ||
|
|
2cc260790c | ||
|
|
1ac4b8cad0 | ||
|
|
ab3b2be725 | ||
|
|
10e4aa8f85 | ||
|
|
ea0d426430 | ||
|
|
27a0214b5d | ||
|
|
f9cd1833da | ||
|
|
f8d3d09716 | ||
|
|
484a455df7 | ||
|
|
21c2c60f4f | ||
|
|
5a46db37c1 | ||
|
|
e545251b27 | ||
|
|
d51ca9b1d1 | ||
|
|
dba503df5b | ||
|
|
732dcd74f7 | ||
|
|
930229b969 | ||
|
|
bb4e16cae7 | ||
|
|
f5606554c9 | ||
|
|
d97d2ac08f | ||
|
|
f834a4ecc5 | ||
|
|
92b7d1bb13 | ||
|
|
b775c9b6b2 | ||
|
|
63acb95834 | ||
|
|
faa46c7e38 | ||
|
|
fee3606a61 | ||
|
|
92bcd366cb | ||
|
|
bc54f5bda1 | ||
|
|
30945807d8 | ||
|
|
95a0e6ea9d | ||
|
|
47275556f9 | ||
|
|
25fb6f262d | ||
|
|
147f920eb6 | ||
|
|
b63d625d12 | ||
|
|
11657cef75 | ||
|
|
5dd0e6fd95 | ||
|
|
9a993445c4 | ||
|
|
4baa949a77 | ||
|
|
c7823d3874 | ||
|
|
074a7e5650 | ||
|
|
64e2cf5d25 | ||
|
|
cc7ef0cf30 | ||
|
|
9102d90c34 | ||
|
|
6832487c46 | ||
|
|
f5cf85a931 | ||
|
|
d57d721dbf | ||
|
|
aa97197413 | ||
|
|
d7df84549b | ||
|
|
8feb8982c1 | ||
|
|
f4acc829f7 | ||
|
|
34b2fe4007 | ||
|
|
72f52da17b | ||
|
|
eecb022a0c | ||
|
|
9063962c7d | ||
|
|
9e25cbb183 | ||
|
|
9af57eaac0 | ||
|
|
f31567e785 | ||
|
|
dc62f1fe05 | ||
|
|
868268d116 | ||
|
|
9f663b0ed9 | ||
|
|
827497bb5e | ||
|
|
688f02df47 | ||
|
|
33ec6d0a67 | ||
|
|
b3f19b0432 | ||
|
|
e6ea506a74 | ||
|
|
2ac090cf14 | ||
|
|
46b24bf442 | ||
|
|
9a854977a4 | ||
|
|
e25b0ad69d | ||
|
|
b632a10fff | ||
|
|
e20b1c52d3 | ||
|
|
08e1428902 | ||
|
|
5f220dc86f | ||
|
|
51d32dc505 | ||
|
|
048eccf4c6 | ||
|
|
9e37ebb261 | ||
|
|
de89bc94b6 | ||
|
|
ab9c177793 | ||
|
|
6ce1aac1d7 | ||
|
|
e56f2600e8 | ||
|
|
614a30fd4e | ||
|
|
5981ec44e4 | ||
|
|
8008819989 | ||
|
|
7edaed601b | ||
|
|
06434512c7 | ||
|
|
fa65bc53b5 | ||
|
|
c1a67a36ef | ||
|
|
1e90682605 | ||
|
|
2357b63b42 | ||
|
|
e1b2650221 | ||
|
|
52ae473ad1 | ||
|
|
833819f713 | ||
|
|
155fc9a743 | ||
|
|
a03fc012f4 | ||
|
|
5b93d58309 | ||
|
|
bef677eda4 | ||
|
|
265a1e6043 | ||
|
|
b21c111aa3 | ||
|
|
b9419520f4 | ||
|
|
8925ce23e9 | ||
|
|
feabc76e36 | ||
|
|
f806cf30e5 | ||
|
|
15199a17a5 | ||
|
|
30654509b1 | ||
|
|
ea2162e8f4 | ||
|
|
ebba98ef16 | ||
|
|
b995f1c3fb | ||
|
|
77e573192e | ||
|
|
ba55a2898d | ||
|
|
16a6bb08b5 | ||
|
|
b2a087c959 | ||
|
|
7349dcba8d | ||
|
|
e4145afbfe | ||
|
|
876d1cad0e | ||
|
|
eea0a66b84 | ||
|
|
b4d71a0fad | ||
|
|
89542e06c9 | ||
|
|
3555b49219 | ||
|
|
791afb80f8 | ||
|
|
924c4d27e8 | ||
|
|
cac611deae | ||
|
|
aee2c384c8 | ||
|
|
78fda7727a | ||
|
|
45e668ec88 | ||
|
|
c6f1ac94fa | ||
|
|
8c9fd4574d | ||
|
|
f9a73a61e9 | ||
|
|
0165b02310 | ||
|
|
24dc3e1c0a | ||
|
|
7b6cb4da34 | ||
|
|
c8fcd46325 | ||
|
|
3ffc4a3410 | ||
|
|
52eb92a00c | ||
|
|
ebce002614 | ||
|
|
595f983071 | ||
|
|
8586269033 | ||
|
|
0f598a5552 | ||
|
|
236f6832a3 | ||
|
|
373a553ac8 | ||
|
|
2964347e7b | ||
|
|
3f0e9c9294 | ||
|
|
0b946c5748 | ||
|
|
c808f8640e | ||
|
|
1fa0d976d2 | ||
|
|
091307290e | ||
|
|
7a045abcc2 | ||
|
|
95d589b126 | ||
|
|
d27664d7c9 | ||
|
|
ebf9c6eb30 | ||
|
|
fef6011426 | ||
|
|
daa07428eb | ||
|
|
0d8d684e78 | ||
|
|
bab6721b2c | ||
|
|
d468d2fb1a | ||
|
|
d897f40903 | ||
|
|
9a7a7e75f9 | ||
|
|
a14c2c892c | ||
|
|
cc64f793ec | ||
|
|
32d5287a3a | ||
|
|
4dd3decb06 | ||
|
|
171caacc92 | ||
|
|
2320ba3a69 | ||
|
|
72c8923bfe | ||
|
|
14c9ac17a1 | ||
|
|
7e745c98e6 | ||
|
|
31d8cb10df | ||
|
|
6174233731 | ||
|
|
216a13e90d | ||
|
|
44c5eb65bd | ||
|
|
edb6c90f46 | ||
|
|
58bc39c2fb | ||
|
|
fecaaaf341 | ||
|
|
263ce00a14 | ||
|
|
9cca3af402 | ||
|
|
541b5ee2ca | ||
|
|
dc4a02a8ff | ||
|
|
5011e7e123 | ||
|
|
cf9408b594 | ||
|
|
3e4e3ffe2d | ||
|
|
9c1188b4d1 | ||
|
|
ea564ba101 | ||
|
|
ca2103f7b3 | ||
|
|
58c6d12e36 | ||
|
|
2f468e4f78 | ||
|
|
daba490c09 | ||
|
|
3638378344 | ||
|
|
f26effc8b3 | ||
|
|
8b22e7d22a | ||
|
|
b413b172e5 | ||
|
|
4e85b59ec9 | ||
|
|
c7551512bc | ||
|
|
6b61763d6f | ||
|
|
106f47d465 | ||
|
|
0cfec70025 | ||
|
|
72e32847c7 | ||
|
|
c6f4759530 | ||
|
|
3e9aa7969b | ||
|
|
e308e07b87 | ||
|
|
f2d527cd2f | ||
|
|
d887747b3c | ||
|
|
bebc4c1b0d | ||
|
|
8968f14122 | ||
|
|
f63079af11 | ||
|
|
cf8edbbd5f | ||
|
|
f1f24168e5 | ||
|
|
d5d6217c5e | ||
|
|
b60de3994c | ||
|
|
6e25647c0a | ||
|
|
a7990db831 | ||
|
|
bf61be029e | ||
|
|
c5ab06b6d0 | ||
|
|
bcc7194254 | ||
|
|
2a776ca895 | ||
|
|
35f2c2bd7e | ||
|
|
393d4b4f56 | ||
|
|
4339a8e80b | ||
|
|
351ab57d62 | ||
|
|
0790ac0dea | ||
|
|
358ceaaa7d | ||
|
|
50ba9ee3a1 | ||
|
|
703f8042f9 | ||
|
|
601559ca6e | ||
|
|
a36639ed8c | ||
|
|
224a5f336a | ||
|
|
9719063a21 | ||
|
|
dbe23f7e73 | ||
|
|
702acb3304 | ||
|
|
cc8dd6e22f | ||
|
|
bb73225b86 | ||
|
|
31ca7ae529 | ||
|
|
64e781f82f | ||
|
|
2d259ae9be | ||
|
|
b38d864612 | ||
|
|
52bbfcfb15 | ||
|
|
a96bd7fc07 | ||
|
|
7962ff6213 | ||
|
|
e840bfd9e6 | ||
|
|
779b37f195 | ||
|
|
dfbc10149c | ||
|
|
22a5402141 | ||
|
|
19af9daea7 | ||
|
|
0a10d136d5 | ||
|
|
0d7aca0060 | ||
|
|
7d33e451cd | ||
|
|
d631c5465f | ||
|
|
ecb2d85ea2 | ||
|
|
c390b1059c | ||
|
|
ba279ae2bb | ||
|
|
30a2743f19 | ||
|
|
46d939fa31 | ||
|
|
f2aff6c235 | ||
|
|
e97a5c0720 | ||
|
|
6dd9a3ba8f | ||
|
|
1775fb7785 | ||
|
|
a639316cdf | ||
|
|
87706e1265 | ||
|
|
fff64ae41e | ||
|
|
3633bb03fc | ||
|
|
172998a5c4 | ||
|
|
acbe4505b9 | ||
|
|
b2193afa46 | ||
|
|
28b130ecd4 | ||
|
|
2ac1182879 | ||
|
|
f2d18fceee | ||
|
|
43c23d754c | ||
|
|
8eee81c682 | ||
|
|
34d395bb0b | ||
|
|
277af02f68 | ||
|
|
68ef24ea9b | ||
|
|
a3d5b33105 | ||
|
|
a7adf15bf6 | ||
|
|
a435b995a8 | ||
|
|
9d71ff27a7 | ||
|
|
090e178ed1 | ||
|
|
a78e354c28 | ||
|
|
9c87c3e5f3 | ||
|
|
01133cc35b | ||
|
|
4dc6031d03 | ||
|
|
c3fd458769 | ||
|
|
433720525d | ||
|
|
375ab592ff | ||
|
|
d2694df67c | ||
|
|
2270163837 | ||
|
|
9282ac3bb2 | ||
|
|
6f858e3909 | ||
|
|
cf26a01bb8 | ||
|
|
2e3705946e | ||
|
|
42f76f9d09 | ||
|
|
bc7a549513 | ||
|
|
f002587aee | ||
|
|
a520b37089 | ||
|
|
4f628a16c6 | ||
|
|
630dc2cecb | ||
|
|
51a585740d | ||
|
|
dab4980a7a | ||
|
|
e847130f0c | ||
|
|
4c88c15874 | ||
|
|
132ec3ce95 | ||
|
|
9178a6fca5 | ||
|
|
eb68e66746 | ||
|
|
b72d474a7f | ||
|
|
2b68bfd3af | ||
|
|
e4a0e8557a | ||
|
|
57bbefdf38 | ||
|
|
7707cb0a82 | ||
|
|
dfad168875 | ||
|
|
7fde61f849 | ||
|
|
8904d33789 | ||
|
|
d28e20b179 | ||
|
|
c5915b5583 | ||
|
|
2626c4365c | ||
|
|
9c35e7a006 | ||
|
|
061438b7c8 | ||
|
|
88035efdf9 | ||
|
|
3546c93d23 | ||
|
|
e232b4adbf | ||
|
|
89019f1e60 | ||
|
|
efc91241d9 | ||
|
|
c90c33ec11 |
6
.gitignore
vendored
6
.gitignore
vendored
@@ -16,5 +16,11 @@ aqhome-nodes.vg
|
||||
aqhome-tool.vg
|
||||
aqhome-mqtt.pid
|
||||
aqhome-mqtt.devices
|
||||
aqhome-react.pid
|
||||
|
||||
core.*
|
||||
core
|
||||
aqhome.geany
|
||||
aqhome-nodes.db
|
||||
aqhome-nodes.db.*
|
||||
|
||||
|
||||
7
0BUILD
7
0BUILD
@@ -2,7 +2,7 @@
|
||||
|
||||
<gwbuild>
|
||||
|
||||
<project name="aqhome" version="0.0.4" so_current="0" so_age="0" so_revision="4" write_config_h="TRUE">
|
||||
<project name="aqhome" version="0.0.19" so_current="0" so_age="0" so_revision="19" write_config_h="TRUE">
|
||||
<setVar name="package">$(project_name)</setVar>
|
||||
<setVar name="version">
|
||||
$(project_vmajor).$(project_vminor).$(project_vpatchlevel)
|
||||
@@ -51,6 +51,8 @@
|
||||
<setVar name="pkgincludedir">$(includedir)/aqhome/$(package)</setVar>
|
||||
<setVar name="pkgdatadir">$(datadir)/$(package)</setVar>
|
||||
|
||||
<setVar name="httpdatadir">/var/www</setVar>
|
||||
|
||||
<option id="enable_testcode" type="string">
|
||||
<default>TRUE</default>
|
||||
<choices>TRUE FALSE</choices>
|
||||
@@ -126,6 +128,7 @@
|
||||
</option>
|
||||
|
||||
|
||||
|
||||
<checkheaders>
|
||||
signal.h
|
||||
sys/stat.h
|
||||
@@ -149,6 +152,8 @@
|
||||
<dep id="gwenhywfar" name="gwenhywfar" minversion="5.11.2" required="TRUE" >
|
||||
<variables>plugindir gwengui-fox16</variables>
|
||||
</dep>
|
||||
<dep id="aqcgi" name="aqcgi" minversion="0.0.1" required="TRUE" />
|
||||
<dep id="aqdiagram" name="aqdiagram" minversion="0.0.1" required="TRUE" />
|
||||
<!-- <dep id="aqdatabase" name="aqdatabase" minversion="1.99.1" required="TRUE" >
|
||||
<variables>aqdatabase_typemakerdir</variables>
|
||||
</dep>
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
aqhome-data
|
||||
aqhome-nodes
|
||||
aqhome-react
|
||||
aqhome-cgi
|
||||
</subdirs>
|
||||
|
||||
</gwbuild>
|
||||
|
||||
150
apps/aqhome-cgi/0BUILD
Normal file
150
apps/aqhome-cgi/0BUILD
Normal file
@@ -0,0 +1,150 @@
|
||||
<?xml?>
|
||||
|
||||
<gwbuild>
|
||||
|
||||
|
||||
<target type="Program" name="aqhome-cgi" install="$(libdir)/cgi-bin" >
|
||||
|
||||
<includes type="c" >
|
||||
$(gwenhywfar_cflags)
|
||||
$(aqcgi_cflags)
|
||||
$(aqdiagram_cflags)
|
||||
-I$(topsrcdir)
|
||||
-I$(topbuilddir)
|
||||
-I$(topsrcdir)/apps
|
||||
-I$(topbuilddir)/apps
|
||||
-I$(builddir)
|
||||
-I$(srcdir)
|
||||
</includes>
|
||||
|
||||
<includes type="tm2" >
|
||||
--include=$(builddir)
|
||||
--include=$(srcdir)
|
||||
</includes>
|
||||
|
||||
<define name="AQHOME_CGI_WWWDIR" value="$(httpdatadir)/aqhome-cgi" quoted="TRUE" />
|
||||
|
||||
<setVar name="local/cflags">$(visibility_cflags)</setVar>
|
||||
|
||||
<setVar name="tm2flags" >
|
||||
</setVar>
|
||||
|
||||
<setVar name="local/typefiles" >
|
||||
</setVar>
|
||||
|
||||
<setVar name="local/built_sources" >
|
||||
</setVar>
|
||||
|
||||
<setVar name="local/built_headers_pub">
|
||||
</setVar>
|
||||
|
||||
<setVar name="local/built_headers_priv" >
|
||||
</setVar>
|
||||
|
||||
<headers dist="true" >
|
||||
</headers>
|
||||
|
||||
<sources>
|
||||
$(local/typefiles)
|
||||
main.c
|
||||
</sources>
|
||||
|
||||
<useTargets>
|
||||
aqhomecgi
|
||||
aqhcgi_service
|
||||
aqhome
|
||||
</useTargets>
|
||||
|
||||
<libraries>
|
||||
$(gwenhywfar_libs)
|
||||
-lm
|
||||
$(aqcgi_libs)
|
||||
$(aqdiagram_libs)
|
||||
</libraries>
|
||||
|
||||
<subdirs>
|
||||
</subdirs>
|
||||
|
||||
|
||||
<extradist>
|
||||
</extradist>
|
||||
|
||||
|
||||
</target>
|
||||
|
||||
|
||||
|
||||
<target type="ConvenienceLibrary" name="aqhomecgi" >
|
||||
|
||||
<includes type="c" >
|
||||
$(gwenhywfar_cflags)
|
||||
-I$(topsrcdir)
|
||||
-I$(topbuilddir)
|
||||
-I$(topsrcdir)/apps
|
||||
-I$(topbuilddir)/apps
|
||||
-I$(builddir)
|
||||
-I$(srcdir)
|
||||
</includes>
|
||||
|
||||
<includes type="tm2" >
|
||||
--include=$(builddir)
|
||||
--include=$(srcdir)
|
||||
</includes>
|
||||
|
||||
<setVar name="local/cflags">$(visibility_cflags)</setVar>
|
||||
|
||||
<setVar name="tm2flags" >
|
||||
</setVar>
|
||||
|
||||
<setVar name="local/typefiles" >
|
||||
</setVar>
|
||||
|
||||
<setVar name="local/built_sources" >
|
||||
</setVar>
|
||||
|
||||
<setVar name="local/built_headers_pub">
|
||||
</setVar>
|
||||
|
||||
<setVar name="local/built_headers_priv" >
|
||||
</setVar>
|
||||
|
||||
<headers dist="true" >
|
||||
service_file.h
|
||||
service_file_p.h
|
||||
</headers>
|
||||
|
||||
<sources>
|
||||
$(local/typefiles)
|
||||
|
||||
service_file.c
|
||||
</sources>
|
||||
|
||||
<useTargets>
|
||||
aqhome
|
||||
aqhcgi_service
|
||||
aqhcgi_modules
|
||||
</useTargets>
|
||||
|
||||
<libraries>
|
||||
$(gwenhywfar_libs)
|
||||
-lm
|
||||
$(aqcgi_libs)
|
||||
$(aqdiagram_libs)
|
||||
</libraries>
|
||||
|
||||
<subdirs>
|
||||
service
|
||||
modules
|
||||
</subdirs>
|
||||
|
||||
|
||||
<extradist>
|
||||
</extradist>
|
||||
|
||||
|
||||
</target>
|
||||
|
||||
|
||||
</gwbuild>
|
||||
|
||||
|
||||
23
apps/aqhome-cgi/README
Normal file
23
apps/aqhome-cgi/README
Normal file
@@ -0,0 +1,23 @@
|
||||
|
||||
|
||||
Modules:
|
||||
- login
|
||||
- signup
|
||||
- main
|
||||
- devices
|
||||
- list
|
||||
- show?name="nodes/12345678"
|
||||
- add
|
||||
- edit
|
||||
- delete
|
||||
- values
|
||||
- rooms
|
||||
|
||||
- users
|
||||
- list
|
||||
- show?alias="admin"
|
||||
- add
|
||||
- edit
|
||||
- delete
|
||||
|
||||
- dashboards
|
||||
0
apps/aqhome-cgi/dummy.c
Normal file
0
apps/aqhome-cgi/dummy.c
Normal file
264
apps/aqhome-cgi/main.c
Normal file
264
apps/aqhome-cgi/main.c
Normal file
@@ -0,0 +1,264 @@
|
||||
|
||||
|
||||
#include "./service_file.h"
|
||||
#include "aqhome-cgi/modules/mroot.h"
|
||||
#include "aqhome-cgi/modules/common/madmin.h"
|
||||
#include "aqhome-cgi/modules/common/mmodules.h"
|
||||
#include "aqhome-cgi/modules/common/musers.h"
|
||||
#include "aqhome-cgi/modules/devices/mdevices.h"
|
||||
#include "aqhome/aqhome.h"
|
||||
|
||||
#include <aqcgi/cgi.h>
|
||||
#include <aqcgi/request.h>
|
||||
#include <aqdiagram/aqdiagram.h>
|
||||
|
||||
#include <gwenhywfar/gwenhywfar.h>
|
||||
#include <gwenhywfar/nogui.h>
|
||||
#include <gwenhywfar/logger.h>
|
||||
#include <gwenhywfar/text.h>
|
||||
#include <gwenhywfar/debug.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
#define AQHOME_CGI_LOGFILE "/var/www/aqhome-cgi/log/aqhome-cgi.log"
|
||||
|
||||
#define AQHOME_CGI_DEFAULT_STATIC_FILES AQHOME_CGI_WWWDIR"/static"
|
||||
#define AQHOME_CGI_DEFAULT_RUNTIME_FILES AQHOME_CGI_WWWDIR"/data"
|
||||
#define AQHOME_CGI_DEFAULT_CACHE_FILES AQHOME_CGI_WWWDIR"/cache"
|
||||
#define AQHOME_CGI_DEFAULT_BASE_URL "http://127.0.0.1/aqbt"
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* forward declarations
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static void _handleRequest(AQCGI_REQUEST *rq, const char *sPathStaticFiles, const char *sPathRuntimeFiles, const char *sBaseUrl);
|
||||
static int _handlePath(AQH_SERVICE *sv, AQCGI_REQUEST *rq, const char *sPathStaticFiles);
|
||||
static void logStart(void);
|
||||
static int _init(const char *sPathRuntimeFiles, const char *sBaseUrl);
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* code
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
GWEN_GUI *gui;
|
||||
const char *sPathStaticFiles;
|
||||
const char *sPathRuntimeFiles;
|
||||
const char *sBaseUrl;
|
||||
|
||||
sPathStaticFiles=getenv("AQHOME_STATIC_FILES");
|
||||
if (!(sPathStaticFiles && *sPathStaticFiles))
|
||||
sPathStaticFiles=AQHOME_CGI_DEFAULT_STATIC_FILES;
|
||||
|
||||
sPathRuntimeFiles=getenv("AQHOME_RUNTIME_FILES");
|
||||
if (!(sPathRuntimeFiles && *sPathRuntimeFiles))
|
||||
sPathRuntimeFiles=AQHOME_CGI_DEFAULT_RUNTIME_FILES;
|
||||
|
||||
sBaseUrl=getenv("AQHOME_BASE_URL");
|
||||
if (!(sBaseUrl && *sBaseUrl))
|
||||
sBaseUrl=AQHOME_CGI_DEFAULT_BASE_URL;
|
||||
|
||||
GWEN_Init();
|
||||
gui=GWEN_NoGui_new();
|
||||
GWEN_Gui_SetGui(gui);
|
||||
|
||||
logStart();
|
||||
GWEN_Logger_Open(GWEN_LOGDOMAIN, "gwenhywfar", AQHOME_CGI_LOGFILE, GWEN_LoggerType_File, GWEN_LoggerFacility_Daemon);
|
||||
GWEN_Logger_Open(AQH_LOGDOMAIN, "aqhome", AQHOME_CGI_LOGFILE, GWEN_LoggerType_File, GWEN_LoggerFacility_Daemon);
|
||||
GWEN_Logger_Open(AQCGI_LOGDOMAIN, "aqcgi", AQHOME_CGI_LOGFILE, GWEN_LoggerType_File, GWEN_LoggerFacility_Daemon);
|
||||
GWEN_Logger_Open(AQDG_LOGDOMAIN, "aqdiagram", AQHOME_CGI_LOGFILE, GWEN_LoggerType_File, GWEN_LoggerFacility_Daemon);
|
||||
GWEN_Logger_Open(NULL, "aqhome-cgi", AQHOME_CGI_LOGFILE, GWEN_LoggerType_File, GWEN_LoggerFacility_Daemon);
|
||||
|
||||
GWEN_Logger_SetLevel(GWEN_LOGDOMAIN, GWEN_LoggerLevel_Debug);
|
||||
GWEN_Logger_SetLevel(AQCGI_LOGDOMAIN, GWEN_LoggerLevel_Debug);
|
||||
GWEN_Logger_SetLevel(NULL, GWEN_LoggerLevel_Debug);
|
||||
|
||||
GWEN_Logger_Close(GWEN_LOGDOMAIN);
|
||||
GWEN_Logger_Open(GWEN_LOGDOMAIN, "gwenhywfar", AQHOME_CGI_LOGFILE, GWEN_LoggerType_File, GWEN_LoggerFacility_Daemon);
|
||||
|
||||
GWEN_Logger_SetLevel(GWEN_LOGDOMAIN, GWEN_LoggerLevel_Debug);
|
||||
GWEN_Logger_SetLevel(AQCGI_LOGDOMAIN, GWEN_LoggerLevel_Debug);
|
||||
GWEN_Logger_SetLevel(AQDG_LOGDOMAIN, GWEN_LoggerLevel_Debug);
|
||||
GWEN_Logger_SetLevel(NULL, GWEN_LoggerLevel_Debug);
|
||||
|
||||
if (argc>1 && argv[1]) {
|
||||
if (0==strcasecmp(argv[1], "init")) {
|
||||
int rv;
|
||||
|
||||
rv=_init(sPathRuntimeFiles, sBaseUrl);
|
||||
if (rv<0) {
|
||||
fprintf(stderr, "Error on init (%d)\n", rv);
|
||||
return 2;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else {
|
||||
AQCGI_REQUEST *rq;
|
||||
|
||||
DBG_ERROR(NULL, "Init CGI");
|
||||
AQCGI_Init();
|
||||
rq=AQCGI_ReadRequest();
|
||||
if (rq) {
|
||||
_handleRequest(rq, sPathStaticFiles, sPathRuntimeFiles, sBaseUrl);
|
||||
}
|
||||
else {
|
||||
fprintf(stdout, "Content-type: text/plain\n\n");
|
||||
fprintf(stdout, "Error: No Request!\n");
|
||||
}
|
||||
AQCGI_Fini();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _handleRequest(AQCGI_REQUEST *rq, const char *sPathStaticFiles, const char *sPathRuntimeFiles, const char *sBaseUrl)
|
||||
{
|
||||
AQH_SERVICE *sv;
|
||||
int rv;
|
||||
|
||||
sv=AQH_ServiceFiles_new(sPathRuntimeFiles, sBaseUrl);
|
||||
|
||||
rv=_handlePath(sv, rq, sPathStaticFiles);
|
||||
if (rv<0) {
|
||||
DBG_INFO(NULL, "here (%d)", rv);
|
||||
}
|
||||
AQH_Service_free(sv);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _handlePath(AQH_SERVICE *sv, AQCGI_REQUEST *rq, const char *sPathStaticFiles)
|
||||
{
|
||||
AQH_MODULE *mRoot;
|
||||
AQH_MODULE *mParent;
|
||||
AQH_SESSION *session;
|
||||
const GWEN_STRINGLIST *sl;
|
||||
|
||||
mRoot=AQH_ModRoot_new(sv, sPathStaticFiles);
|
||||
mParent=mRoot;
|
||||
session=AQH_ModService_ReadSession(mRoot, rq);
|
||||
AQH_ModService_CalcSessionModPerms(mRoot, session);
|
||||
|
||||
sl=AQCGI_Request_GetStringlistPath(rq);
|
||||
if (sl) {
|
||||
GWEN_STRINGLISTENTRY *se;
|
||||
|
||||
se=GWEN_StringList_FirstEntry(sl);
|
||||
while(se) {
|
||||
GWEN_STRINGLISTENTRY *seNext;
|
||||
const char *s;
|
||||
|
||||
seNext=GWEN_StringListEntry_Next(se);
|
||||
s=GWEN_StringListEntry_Data(se);
|
||||
if (s && *s) {
|
||||
if (seNext) {
|
||||
AQH_MODULE *m;
|
||||
|
||||
DBG_ERROR(NULL, "Entry: %s (%s)", s, seNext?"not last":"last");
|
||||
m=AQH_ModService_LoadSubModule(mParent, rq, session, s);
|
||||
if (m==NULL) {
|
||||
AQH_Session_free(session);
|
||||
AQH_Module_free(mRoot);
|
||||
return GWEN_ERROR_GENERIC;
|
||||
}
|
||||
mParent=m;
|
||||
}
|
||||
else {
|
||||
int rv;
|
||||
|
||||
/* last, let module handle remaining part */
|
||||
DBG_ERROR(NULL, "Entry: %s (last)", s);
|
||||
rv=AQH_ModService_HandleRequest(mParent, rq, session, s);
|
||||
if (rv<0) {
|
||||
DBG_INFO(NULL, "here (%d)", rv);
|
||||
AQH_Session_free(session);
|
||||
AQH_Module_free(mRoot);
|
||||
return rv;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
se=seNext;
|
||||
}
|
||||
AQH_Session_free(session);
|
||||
AQH_Module_free(mRoot);
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
AQH_Session_free(session);
|
||||
AQH_Module_free(mRoot);
|
||||
return GWEN_ERROR_GENERIC;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void logStart()
|
||||
{
|
||||
FILE *f;
|
||||
|
||||
f=fopen(AQHOME_CGI_LOGFILE, "a+");
|
||||
if (f!=NULL) {
|
||||
fprintf(f, "Started.\n");
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _init(const char *sPathRuntimeFiles, const char *sBaseUrl)
|
||||
{
|
||||
AQH_SERVICE *sv;
|
||||
int rv;
|
||||
|
||||
DBG_ERROR(NULL, "Creating aqhome-cgi environment in \"%s\"", sPathRuntimeFiles);
|
||||
sv=AQH_ServiceFiles_new(sPathRuntimeFiles, sBaseUrl);
|
||||
rv=AQH_ModAdmin_Create(sv);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "Error creating module \"admin\"");
|
||||
AQH_Service_free(sv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv=AQH_ModAdmModules_Create(sv);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "Error creating module \"modules\"");
|
||||
AQH_Service_free(sv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv=AQH_ModAdmUsers_Create(sv);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "Error creating module \"users\"");
|
||||
AQH_Service_free(sv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv=AQH_ModDevices_Create(sv);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "Error creating module \"devices\"");
|
||||
AQH_Service_free(sv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
AQH_Service_free(sv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
87
apps/aqhome-cgi/modules/0BUILD
Normal file
87
apps/aqhome-cgi/modules/0BUILD
Normal file
@@ -0,0 +1,87 @@
|
||||
<?xml?>
|
||||
|
||||
<gwbuild>
|
||||
|
||||
<target type="ConvenienceLibrary" name="aqhcgi_modules" >
|
||||
|
||||
<includes type="c" >
|
||||
$(gwenhywfar_cflags)
|
||||
-I$(topsrcdir)
|
||||
-I$(topbuilddir)
|
||||
-I$(topsrcdir)/apps
|
||||
-I$(topbuilddir)/apps
|
||||
-I$(builddir)
|
||||
-I$(srcdir)
|
||||
</includes>
|
||||
|
||||
<includes type="tm2" >
|
||||
--include=$(builddir)
|
||||
--include=$(srcdir)
|
||||
</includes>
|
||||
|
||||
|
||||
<define name="not_BUILDING_AQHOME" />
|
||||
|
||||
<setVar name="local/cflags">$(visibility_cflags)</setVar>
|
||||
|
||||
|
||||
<setVar name="tm2flags-INACTIVE" >
|
||||
--api=AQHOME_API
|
||||
</setVar>
|
||||
|
||||
<setVar name="local/typefiles" >
|
||||
</setVar>
|
||||
|
||||
<setVar name="local/built_sources" >
|
||||
</setVar>
|
||||
|
||||
<setVar name="local/built_headers_pub">
|
||||
</setVar>
|
||||
|
||||
|
||||
<setVar name="local/built_headers_priv" >
|
||||
</setVar>
|
||||
|
||||
|
||||
<headers dist="false" install="$(pkgincludedir)/service" >
|
||||
$(local/built_headers_pub)
|
||||
</headers>
|
||||
|
||||
|
||||
<headers dist="true" install="$(pkgincludedir)/service" >
|
||||
mdataclient.h
|
||||
mroot.h
|
||||
</headers>
|
||||
|
||||
|
||||
<headers dist="true" >
|
||||
mroot_p.h
|
||||
</headers>
|
||||
|
||||
|
||||
<sources>
|
||||
$(local/typefiles)
|
||||
|
||||
mdataclient.c
|
||||
mroot.c
|
||||
</sources>
|
||||
|
||||
|
||||
<extradist>
|
||||
</extradist>
|
||||
|
||||
|
||||
<useTargets>
|
||||
aqhcgi_modcom
|
||||
aqhcgi_mdevices
|
||||
</useTargets>
|
||||
|
||||
<subdirs>
|
||||
common
|
||||
devices
|
||||
static
|
||||
</subdirs>
|
||||
|
||||
</target>
|
||||
|
||||
</gwbuild>
|
||||
86
apps/aqhome-cgi/modules/common/0BUILD
Normal file
86
apps/aqhome-cgi/modules/common/0BUILD
Normal file
@@ -0,0 +1,86 @@
|
||||
<?xml?>
|
||||
|
||||
<gwbuild>
|
||||
|
||||
<target type="ConvenienceLibrary" name="aqhcgi_modcom" >
|
||||
|
||||
<includes type="c" >
|
||||
$(gwenhywfar_cflags)
|
||||
-I$(topsrcdir)
|
||||
-I$(topbuilddir)
|
||||
-I$(topsrcdir)/apps
|
||||
-I$(topbuilddir)/apps
|
||||
-I$(builddir)
|
||||
-I$(srcdir)
|
||||
</includes>
|
||||
|
||||
<includes type="tm2" >
|
||||
--include=$(builddir)
|
||||
--include=$(srcdir)
|
||||
</includes>
|
||||
|
||||
|
||||
<define name="not_BUILDING_AQHOME" />
|
||||
|
||||
<setVar name="local/cflags">$(visibility_cflags)</setVar>
|
||||
|
||||
|
||||
<setVar name="tm2flags-INACTIVE" >
|
||||
--api=AQHOME_API
|
||||
</setVar>
|
||||
|
||||
<setVar name="local/typefiles" >
|
||||
</setVar>
|
||||
|
||||
<setVar name="local/built_sources" >
|
||||
</setVar>
|
||||
|
||||
<setVar name="local/built_headers_pub">
|
||||
</setVar>
|
||||
|
||||
|
||||
<setVar name="local/built_headers_priv" >
|
||||
</setVar>
|
||||
|
||||
|
||||
<headers dist="false" install="$(pkgincludedir)/service" >
|
||||
$(local/built_headers_pub)
|
||||
</headers>
|
||||
|
||||
|
||||
<headers dist="true" install="$(pkgincludedir)/service" >
|
||||
mservice.h
|
||||
madmin.h
|
||||
mmodules.h
|
||||
musers.h
|
||||
</headers>
|
||||
|
||||
|
||||
<headers dist="true" >
|
||||
mservice_p.h
|
||||
</headers>
|
||||
|
||||
|
||||
<sources>
|
||||
$(local/typefiles)
|
||||
|
||||
mservice.c
|
||||
madmin.c
|
||||
mmodules.c
|
||||
musers.c
|
||||
</sources>
|
||||
|
||||
|
||||
<extradist>
|
||||
</extradist>
|
||||
|
||||
|
||||
<useTargets>
|
||||
</useTargets>
|
||||
|
||||
<subdirs>
|
||||
</subdirs>
|
||||
|
||||
</target>
|
||||
|
||||
</gwbuild>
|
||||
217
apps/aqhome-cgi/modules/common/madmin.c
Normal file
217
apps/aqhome-cgi/modules/common/madmin.c
Normal file
@@ -0,0 +1,217 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "./madmin.h"
|
||||
|
||||
#include "aqhome-cgi/service/module.h"
|
||||
#include "aqhome-cgi/modules/common/mmodules.h"
|
||||
#include "aqhome-cgi/modules/common/musers.h"
|
||||
|
||||
#include <gwenhywfar/debug.h>
|
||||
#include <gwenhywfar/timestamp.h>
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* defs and enums
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* global vars
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* forward declarations
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static void _createPermDefList(AQH_MODULE *m);
|
||||
static void _createRoleList(AQH_MODULE *m);
|
||||
|
||||
static AQH_MODULE *_loadSubModule(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, const char *sModuleName);
|
||||
static int _handleRequest(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, const char *sLastPathElem);
|
||||
static int _handleRqIndex(AQH_MODULE *m, AQCGI_REQUEST *rq, GWEN_BUFFER *dbuf);
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* code
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void AQH_ModAdmin_Extend(AQH_MODULE *m, AQH_SERVICE *sv, const char *baseFolder)
|
||||
{
|
||||
AQH_ModService_Extend(m, sv, baseFolder);
|
||||
AQH_ModService_SetHandleRequestFn(m, _handleRequest);
|
||||
AQH_ModService_SetLoadSubModuleFn(m, _loadSubModule);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int AQH_ModAdmin_Create(AQH_SERVICE *sv)
|
||||
{
|
||||
AQH_MODULE *m;
|
||||
int rv;
|
||||
|
||||
m=AQH_Module_new();
|
||||
AQH_Module_SetName(m, "admin");
|
||||
AQH_Module_SetDescr(m, "administration module");
|
||||
AQH_Module_SetGuestPerms(m, 0);
|
||||
|
||||
_createPermDefList(m);
|
||||
_createRoleList(m);
|
||||
|
||||
rv=AQH_Service_AddModule(sv, m);
|
||||
if (rv<0) {
|
||||
DBG_INFO(NULL, "here (%d)", rv);
|
||||
}
|
||||
AQH_Module_free(m);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _createPermDefList(AQH_MODULE *m)
|
||||
{
|
||||
AQH_PERMDEF_LIST *permDefList;
|
||||
|
||||
permDefList=AQH_PermDef_List_new();
|
||||
|
||||
AQH_ModService_AddPermDef(permDefList, "AdminUsers", 0x001, "User Administration");
|
||||
AQH_ModService_AddPermDef(permDefList, "AdminModules", 0x002, "Module Administration");
|
||||
|
||||
AQH_Module_SetPermDefList(m, permDefList);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _createRoleList(AQH_MODULE *m)
|
||||
{
|
||||
AQH_ROLE_LIST *roleList;
|
||||
int id=0;
|
||||
|
||||
roleList=AQH_Role_List_new();
|
||||
AQH_ModService_AddRole(roleList, id++, "userAdmin", AQH_MODADM_PERMS_ADMINUSERS, "User administrator");
|
||||
AQH_ModService_AddRole(roleList, id++, "moduleAdmin", AQH_MODADM_PERMS_ADMINMODULES, "Module administrator");
|
||||
AQH_Module_SetRoleList(m, roleList);
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQH_MODULE *_loadSubModule(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, const char *sModuleName)
|
||||
{
|
||||
AQH_SERVICE *sv;
|
||||
|
||||
sv=AQH_ModService_GetService(m);
|
||||
if (strcasecmp(sModuleName, "modules")==0) {
|
||||
AQH_MODULE *mSub;
|
||||
|
||||
mSub=AQH_Service_LoadModule(sv, sModuleName);
|
||||
if (mSub) {
|
||||
const char *s;
|
||||
GWEN_BUFFER *nbuf;
|
||||
|
||||
nbuf=GWEN_Buffer_new(0, 256, 0, 1);
|
||||
s=AQH_ModService_GetBaseFolder(m);
|
||||
GWEN_Buffer_AppendArgs(nbuf, "%s/modules", s?s:".");
|
||||
|
||||
AQH_ModAdmModules_Extend(mSub, AQH_ModService_GetService(m), GWEN_Buffer_GetStart(nbuf));
|
||||
AQH_Module_Tree2_AddChild(m, mSub);
|
||||
GWEN_Buffer_free(nbuf);
|
||||
return mSub;
|
||||
}
|
||||
}
|
||||
else if (strcasecmp(sModuleName, "users")==0) {
|
||||
AQH_MODULE *mSub;
|
||||
|
||||
mSub=AQH_Service_LoadModule(sv, sModuleName);
|
||||
if (mSub) {
|
||||
const char *s;
|
||||
GWEN_BUFFER *nbuf;
|
||||
|
||||
nbuf=GWEN_Buffer_new(0, 256, 0, 1);
|
||||
s=AQH_ModService_GetBaseFolder(m);
|
||||
GWEN_Buffer_AppendArgs(nbuf, "%s/modules", s?s:".");
|
||||
|
||||
AQH_ModAdmUsers_Extend(mSub, AQH_ModService_GetService(m), GWEN_Buffer_GetStart(nbuf));
|
||||
AQH_Module_Tree2_AddChild(m, mSub);
|
||||
GWEN_Buffer_free(nbuf);
|
||||
return mSub;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _handleRequest(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, const char *sLastPathElem)
|
||||
{
|
||||
GWEN_BUFFER *dbuf;
|
||||
int rv=0;
|
||||
|
||||
dbuf=GWEN_Buffer_new(0, 256, 0, 1);
|
||||
AQH_ModService_AddHeader(m, "en", dbuf);
|
||||
|
||||
if (strcasecmp(sLastPathElem, "index.html")==0) {
|
||||
if (AQH_ModService_GetUserPerms(m) & (AQH_MODADM_PERMS_ADMINUSERS | AQH_MODADM_PERMS_ADMINMODULES))
|
||||
rv=_handleRqIndex(m, rq, dbuf);
|
||||
else {
|
||||
AQCGI_Request_SetResponseCode(rq, 403);
|
||||
AQCGI_Request_SetResponseText(rq, "Forbidden");
|
||||
}
|
||||
}
|
||||
else {
|
||||
AQCGI_Request_SetResponseCode(rq, 404);
|
||||
AQCGI_Request_SetResponseText(rq, "Not Found");
|
||||
}
|
||||
AQH_ModService_AddFooter(m, "en", dbuf);
|
||||
AQCGI_Request_SetBufferResponseBody(rq, dbuf);
|
||||
AQCGI_Request_AddResponseHeaderData(rq, "Content-type: text/html");
|
||||
|
||||
return AQCGI_SendResponse(rq);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _handleRqIndex(AQH_MODULE *m, AQCGI_REQUEST *rq, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
if (AQCGI_Request_GetRequestMethod(rq)==AQCGI_REQUEST_METHOD_GET) {
|
||||
uint32_t userPerms;
|
||||
|
||||
GWEN_Buffer_AppendString(dbuf, "<table>");
|
||||
userPerms=AQH_ModService_GetUserPerms(m);
|
||||
if (userPerms & AQH_MODADM_PERMS_ADMINUSERS)
|
||||
GWEN_Buffer_AppendString(dbuf,
|
||||
"<tr>"
|
||||
"<td><a href=\"users/index.html\" >User administration</a></td>"
|
||||
"<td>Add, remove or modify users</td>"
|
||||
"</tr>\n");
|
||||
if (userPerms & AQH_MODADM_PERMS_ADMINMODULES)
|
||||
GWEN_Buffer_AppendString(dbuf,
|
||||
"<tr>"
|
||||
"<td><a href=\"modules/index.html\" >Module administration</a></td>"
|
||||
"<td>Add, remove or modify modules</td>"
|
||||
"</tr>\n");
|
||||
GWEN_Buffer_AppendString(dbuf, "</table>\n");
|
||||
AQCGI_Request_SetResponseCode(rq, 200);
|
||||
AQCGI_Request_SetResponseText(rq, "Ok");
|
||||
return 0;
|
||||
}
|
||||
AQCGI_Request_SetResponseCode(rq, 405);
|
||||
AQCGI_Request_SetResponseText(rq, "Method Not Allowed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
31
apps/aqhome-cgi/modules/common/madmin.h
Normal file
31
apps/aqhome-cgi/modules/common/madmin.h
Normal file
@@ -0,0 +1,31 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef AQHOME_CGI_MADMIN_H
|
||||
#define AQHOME_CGI_MADMIN_H
|
||||
|
||||
#include <aqhome-cgi/modules/common/mservice.h>
|
||||
|
||||
#include <aqcgi/request.h>
|
||||
|
||||
#include <gwenhywfar/buffer.h>
|
||||
|
||||
|
||||
#define AQH_MODADM_PERMS_ADMINUSERS 0x001
|
||||
#define AQH_MODADM_PERMS_ADMINMODULES 0x002
|
||||
|
||||
|
||||
void AQH_ModAdmin_Extend(AQH_MODULE *m, AQH_SERVICE *sv, const char *baseFolder);
|
||||
|
||||
int AQH_ModAdmin_Create(AQH_SERVICE *sv);
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
745
apps/aqhome-cgi/modules/common/mmodules.c
Normal file
745
apps/aqhome-cgi/modules/common/mmodules.c
Normal file
@@ -0,0 +1,745 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "./mmodules.h"
|
||||
|
||||
#include "aqhome-cgi/service/module.h"
|
||||
|
||||
#include <gwenhywfar/debug.h>
|
||||
#include <gwenhywfar/timestamp.h>
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* defs and enums
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#define GBAS GWEN_Buffer_AppendString
|
||||
#define GBAA GWEN_Buffer_AppendArgs
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* forward declarations
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static void _createPermDefList(AQH_MODULE *m);
|
||||
static void _createRoleList(AQH_MODULE *m);
|
||||
|
||||
static AQH_MODULE *_loadSubModule(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, const char *sModuleName);
|
||||
static int _handleRequest(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, const char *sLastPathElem);
|
||||
static void _handleRqIndex(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf);
|
||||
|
||||
static void _handleRqEditModGet(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf);
|
||||
static void _handleRqEditModPost(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf);
|
||||
|
||||
static void _handleRqAddRoleGet(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf);
|
||||
static void _handleRqAddRolePost(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf);
|
||||
|
||||
static void _handleRqEditRoleGet(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf);
|
||||
static void _handleRqEditRolePost(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf);
|
||||
static int _getHighestUsedRoleId(const AQH_ROLE_LIST *roleList);
|
||||
|
||||
static void _handleRqDeleteRole(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf);
|
||||
|
||||
static void _writeEditModForm(const AQH_MODULE *currentMod, const char *sModName, GWEN_BUFFER *dbuf);
|
||||
static void _writeRoleListToForm(const AQH_ROLE_LIST *roleList,
|
||||
const char *sModName,
|
||||
const AQH_PERMDEF_LIST *permDefList,
|
||||
GWEN_BUFFER *dbuf);
|
||||
|
||||
static void _setLocationHeaderForMod(AQCGI_REQUEST *rq, const char *page, const char *sModName);
|
||||
static void _writeEnabledPermissions(const AQH_PERMDEF_LIST *permDefList, uint32_t perms, GWEN_BUFFER *dbuf);
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* vars
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static AQH_MODSERVICE_HANDLER_ENTRY _requestTable[]={
|
||||
{"index.html", AQCGI_REQUEST_METHOD_GET, AQH_MODADMMODULES_PERMS_MODULESREAD, _handleRqIndex},
|
||||
{"editmodule.html", AQCGI_REQUEST_METHOD_GET, AQH_MODADMMODULES_PERMS_MODULESWRITE, _handleRqEditModGet},
|
||||
{"editmodule.html", AQCGI_REQUEST_METHOD_POST, AQH_MODADMMODULES_PERMS_MODULESWRITE, _handleRqEditModPost},
|
||||
{"addrole.html", AQCGI_REQUEST_METHOD_GET, AQH_MODADMMODULES_PERMS_MODULESWRITE, _handleRqAddRoleGet},
|
||||
{"addrole.html", AQCGI_REQUEST_METHOD_POST, AQH_MODADMMODULES_PERMS_MODULESWRITE, _handleRqAddRolePost},
|
||||
{"editrole.html", AQCGI_REQUEST_METHOD_GET, AQH_MODADMMODULES_PERMS_MODULESWRITE, _handleRqEditRoleGet},
|
||||
{"editrole.html", AQCGI_REQUEST_METHOD_POST, AQH_MODADMMODULES_PERMS_MODULESWRITE, _handleRqEditRolePost},
|
||||
{"delrole.html", AQCGI_REQUEST_METHOD_GET, AQH_MODADMMODULES_PERMS_MODULESWRITE, _handleRqDeleteRole},
|
||||
{NULL, 0, 0, NULL}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* code
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void AQH_ModAdmModules_Extend(AQH_MODULE *m, AQH_SERVICE *sv, const char *baseFolder)
|
||||
{
|
||||
AQH_ModService_Extend(m, sv, baseFolder);
|
||||
AQH_ModService_SetHandleRequestFn(m, _handleRequest);
|
||||
AQH_ModService_SetLoadSubModuleFn(m, _loadSubModule);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int AQH_ModAdmModules_Create(AQH_SERVICE *sv)
|
||||
{
|
||||
AQH_MODULE *m;
|
||||
int rv;
|
||||
|
||||
m=AQH_Module_new();
|
||||
AQH_Module_SetName(m, "modules");
|
||||
AQH_Module_SetDescr(m, "modules administration module");
|
||||
AQH_Module_SetGuestPerms(m, 0);
|
||||
|
||||
_createPermDefList(m);
|
||||
_createRoleList(m);
|
||||
|
||||
rv=AQH_Service_AddModule(sv, m);
|
||||
if (rv<0) {
|
||||
DBG_INFO(NULL, "here (%d)", rv);
|
||||
}
|
||||
AQH_Module_free(m);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _createPermDefList(AQH_MODULE *m)
|
||||
{
|
||||
AQH_PERMDEF_LIST *permDefList;
|
||||
|
||||
permDefList=AQH_PermDef_List_new();
|
||||
|
||||
AQH_ModService_AddPermDef(permDefList, "ModuleRead", 0x001, "Read modules");
|
||||
AQH_ModService_AddPermDef(permDefList, "ModuleWrite", 0x002, "Modify modules");
|
||||
AQH_ModService_AddPermDef(permDefList, "ModuleAdd", 0x004, "Add modules");
|
||||
AQH_ModService_AddPermDef(permDefList, "ModuleDel", 0x008, "Remove modules");
|
||||
|
||||
AQH_Module_SetPermDefList(m, permDefList);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _createRoleList(AQH_MODULE *m)
|
||||
{
|
||||
AQH_ROLE_LIST *roleList;
|
||||
int id=0;
|
||||
|
||||
roleList=AQH_Role_List_new();
|
||||
AQH_ModService_AddRole(roleList, id++, "admin",
|
||||
AQH_MODADMMODULES_PERMS_MODULESREAD |
|
||||
AQH_MODADMMODULES_PERMS_MODULESWRITE |
|
||||
AQH_MODADMMODULES_PERMS_MODULESADD |
|
||||
AQH_MODADMMODULES_PERMS_MODULESDEL,
|
||||
"Administrator Role");
|
||||
AQH_Module_SetRoleList(m, roleList);
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQH_MODULE *_loadSubModule(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, const char *sModuleName)
|
||||
{
|
||||
/* no sub-modules */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _handleRequest(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, const char *sLastPathElem)
|
||||
{
|
||||
AQH_ModService_HandleRequestWithTable(m, rq, session, sLastPathElem, _requestTable);
|
||||
return AQCGI_SendResponse(rq);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _handleRqIndex(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
AQH_SERVICE *sv;
|
||||
GWEN_STRINGLIST *slModules;
|
||||
uint32_t perms;
|
||||
|
||||
perms=AQH_ModService_GetUserPerms(m);
|
||||
sv=AQH_ModService_GetService(m);
|
||||
slModules=AQH_Service_ListModules(sv);
|
||||
if (slModules) {
|
||||
GWEN_STRINGLISTENTRY *se;
|
||||
|
||||
GBAS(dbuf, "<h1>Modules</h1>\n");
|
||||
GBAS(dbuf,
|
||||
"<table class=\"datatable\">\n"
|
||||
"<thead>"
|
||||
"<tr><th>Id</th><th>Name</th><th>Description</th><th>Actions</th></tr>\n"
|
||||
"</thead>\n"
|
||||
"<tbody>\n");
|
||||
se=GWEN_StringList_FirstEntry(slModules);
|
||||
while(se) {
|
||||
const char *sModName;
|
||||
|
||||
sModName=GWEN_StringListEntry_Data(se);
|
||||
if (sModName && *sModName) {
|
||||
AQH_MODULE *currentMod;
|
||||
|
||||
currentMod=AQH_Service_LoadModule(sv, sModName);
|
||||
if (currentMod) {
|
||||
const char *s;
|
||||
const char *sName;
|
||||
|
||||
sName=AQH_Module_GetName(currentMod);
|
||||
GBAS(dbuf, "<tr>");
|
||||
GBAA(dbuf, "<td>%lu</td>", (unsigned long int) AQH_Module_GetId(currentMod));
|
||||
GBAA(dbuf, "<td>%s</td>", sName?sName:"");
|
||||
s=AQH_Module_GetDescr(currentMod);
|
||||
GBAA(dbuf, "<td>%s</td>", s?s:"");
|
||||
|
||||
GBAS(dbuf, "<td>");
|
||||
if (perms & AQH_MODADMMODULES_PERMS_MODULESWRITE)
|
||||
GBAA(dbuf, "<a href=\"editmodule.html?name=%s\"><img src=\"/pics/edit.png\"></a>", sName?sName:"");
|
||||
GBAA(dbuf, "</td>\n");
|
||||
GBAA(dbuf, "</tr>\n");
|
||||
AQH_Module_free(currentMod);
|
||||
}
|
||||
}
|
||||
se=GWEN_StringListEntry_Next(se);
|
||||
}
|
||||
GBAS(dbuf,
|
||||
"</tbody>\n"
|
||||
"</table>\n");
|
||||
GWEN_StringList_free(slModules);
|
||||
}
|
||||
if (perms & AQH_MODADMMODULES_PERMS_MODULESADD)
|
||||
GBAS(dbuf, "<hr><a href=\"addmodule.html\">Add Module</a>");
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _handleRqEditModGet(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
AQH_SERVICE *sv;
|
||||
GWEN_DB_NODE *dbQuery;
|
||||
const char *sModName;
|
||||
AQH_MODULE *currentMod;
|
||||
|
||||
sv=AQH_ModService_GetService(m);
|
||||
dbQuery=AQCGI_Request_GetDbQuery(rq);
|
||||
sModName=dbQuery?GWEN_DB_GetCharValue(dbQuery, "name", 0, NULL):NULL;
|
||||
currentMod=(sModName && *sModName)?AQH_Service_LoadModule(sv, sModName):NULL;
|
||||
if (currentMod) {
|
||||
_writeEditModForm(currentMod, sModName, dbuf);
|
||||
AQH_Module_free(currentMod);
|
||||
}
|
||||
else {
|
||||
AQCGI_Request_AddResponseHeaderData(rq, "Location: index.html");
|
||||
AQCGI_Request_SetResponseCode(rq, 303);
|
||||
AQCGI_Request_SetResponseText(rq, "See other");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _handleRqEditModPost(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
AQH_SERVICE *sv;
|
||||
GWEN_DB_NODE *dbPost;
|
||||
const char *sModName;
|
||||
AQH_MODULE *currentMod;
|
||||
|
||||
sv=AQH_ModService_GetService(m);
|
||||
dbPost=AQCGI_Request_GetDbPostBody(rq);
|
||||
sModName=dbPost?GWEN_DB_GetCharValue(dbPost, "module", 0, NULL):NULL;
|
||||
currentMod=(sModName && *sModName)?AQH_Service_LoadModule(sv, sModName):NULL;
|
||||
if (currentMod) {
|
||||
const char *sNewModName;
|
||||
const char *sDescr;
|
||||
int rv;
|
||||
uint32_t perms;
|
||||
const AQH_PERMDEF_LIST *permDefList;
|
||||
|
||||
permDefList=AQH_Module_GetPermDefList(currentMod);
|
||||
sNewModName=GWEN_DB_GetCharValue(dbPost, "name", 0, NULL);
|
||||
sDescr=GWEN_DB_GetCharValue(dbPost, "descr", 0, NULL);
|
||||
perms=AQH_ModService_ReadPermsFromForm(dbPost, permDefList, NULL);
|
||||
if (sNewModName && *sNewModName)
|
||||
AQH_Module_SetName(currentMod, sNewModName);
|
||||
AQH_Module_SetDescr(currentMod, sDescr);
|
||||
AQH_Module_SetGuestPerms(currentMod, perms);
|
||||
|
||||
rv=AQH_Service_SaveModule(sv, currentMod);
|
||||
if (rv<0) {
|
||||
GBAS(dbuf, "<h2>Error</h2><p>Error saving module</p>");
|
||||
DBG_ERROR(NULL, "Could not save module \"%s\"", sModName);
|
||||
AQH_Module_free(currentMod);
|
||||
return;
|
||||
}
|
||||
DBG_ERROR(NULL, "Module \"%s\" saved", sModName);
|
||||
AQH_Module_free(currentMod);
|
||||
AQCGI_Request_AddResponseHeaderData(rq, "Location: index.html");
|
||||
AQCGI_Request_SetResponseCode(rq, 303);
|
||||
AQCGI_Request_SetResponseText(rq, "See other");
|
||||
}
|
||||
else {
|
||||
DBG_ERROR(NULL, "Could not load module \"%s\"", sModName?sModName:"<no name>");
|
||||
GBAS(dbuf, "<p>Error loading module.</p>\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _handleRqAddRoleGet(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
AQH_SERVICE *sv;
|
||||
GWEN_DB_NODE *dbQuery;
|
||||
const char *sModName;
|
||||
AQH_MODULE *currentMod;
|
||||
const AQH_PERMDEF_LIST *permDefList;
|
||||
uint32_t guestPerms;
|
||||
|
||||
sv=AQH_ModService_GetService(m);
|
||||
dbQuery=AQCGI_Request_GetDbQuery(rq);
|
||||
sModName=dbQuery?GWEN_DB_GetCharValue(dbQuery, "mod", 0, NULL):NULL;
|
||||
currentMod=(sModName && *sModName)?AQH_Service_LoadModule(sv, sModName):NULL;
|
||||
guestPerms=currentMod?AQH_Module_GetGuestPerms(currentMod):0;
|
||||
permDefList=currentMod?AQH_Module_GetPermDefList(currentMod):NULL;
|
||||
|
||||
if (currentMod) {
|
||||
if (permDefList) {
|
||||
GBAA(dbuf, "<h2>Add Role for Module %s</h2>\n", sModName?sModName:"");
|
||||
GBAS(dbuf,
|
||||
"<form action=\"addrole.html\" method=\"post\">\n"
|
||||
"<table class=\"formtable\">\n"
|
||||
"<tr><td><label for=\"name\">Name:</label></td><td><input type=\"text\" name=\"name\"></td>"
|
||||
"<tr><td><label for=\"descr\">Description:</label></td><td><input type=\"text\" name=\"descr\"></td></tr>\n");
|
||||
|
||||
GBAS(dbuf, "<tr><td><label>Permissions:</label></td><td>");
|
||||
AQH_ModService_WritePermsToForm(guestPerms, permDefList, NULL, dbuf);
|
||||
GBAS(dbuf, "</td></tr>\n");
|
||||
|
||||
GBAS(dbuf, "</table>\n");
|
||||
GBAA(dbuf, "<input type=\"hidden\" name=\"mod\" value=\"%s\">\n", sModName?sModName:"");
|
||||
GBAS(dbuf, "<input type=\"submit\" value=\"Add\">\n");
|
||||
GBAS(dbuf, "</form>\n\n");
|
||||
}
|
||||
else {
|
||||
GBAS(dbuf, "<p>Please add permission definitions first.</p>\n");
|
||||
GBAA(dbuf, "<p><a href=\"editmodule.html?name=\"%s\"> back to module</p>\n", sModName?sModName:"");
|
||||
}
|
||||
AQH_Module_free(currentMod);
|
||||
}
|
||||
else {
|
||||
GBAS(dbuf, "<p>Error loading module.</p>\n");
|
||||
GBAS(dbuf, "<p><a href=\"index.html\"> back to module list</p>\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _handleRqAddRolePost(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
AQH_SERVICE *sv;
|
||||
GWEN_DB_NODE *dbPost;
|
||||
const char *sModName;
|
||||
AQH_MODULE *currentMod;
|
||||
int newId;
|
||||
const char *sName;
|
||||
const char *sDescr;
|
||||
uint32_t perms;
|
||||
AQH_PERMDEF_LIST *permDefList;
|
||||
AQH_ROLE_LIST *roleList;
|
||||
int rv;
|
||||
|
||||
/* sample data */
|
||||
DBG_ERROR(NULL, "Handling POST request");
|
||||
sv=AQH_ModService_GetService(m);
|
||||
dbPost=AQCGI_Request_GetDbPostBody(rq);
|
||||
sModName=dbPost?GWEN_DB_GetCharValue(dbPost, "mod", 0, NULL):NULL;
|
||||
currentMod=(sModName && *sModName)?AQH_Service_LoadModule(sv, sModName):NULL;
|
||||
permDefList=currentMod?AQH_Module_GetPermDefList(currentMod):NULL;
|
||||
roleList=currentMod?AQH_Module_GetRoleList(currentMod):NULL;
|
||||
/* read role values */
|
||||
newId=(roleList?_getHighestUsedRoleId(roleList):0)+1;
|
||||
sName=dbPost?GWEN_DB_GetCharValue(dbPost, "name", 0, NULL):NULL;
|
||||
sDescr=dbPost?GWEN_DB_GetCharValue(dbPost, "descr", 0, NULL):NULL;
|
||||
perms=(dbPost && permDefList)?AQH_ModService_ReadPermsFromForm(dbPost, permDefList, NULL):0;
|
||||
|
||||
/* validate */
|
||||
if (!(sName && *sName)) {
|
||||
DBG_ERROR(NULL, "Missing value for \"name\"");
|
||||
GBAS(dbuf, "<p>Missing name.</p>\n");
|
||||
GBAA(dbuf, "<p><a href=\"editmodule.html?name=\"%s\"> back to module</p>\n", sModName?sModName:"");
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentMod) {
|
||||
AQH_ROLE *role;
|
||||
|
||||
/* set new values */
|
||||
role=AQH_Role_new();
|
||||
AQH_Role_SetId(role, newId);
|
||||
AQH_Role_SetName(role, sName);
|
||||
AQH_Role_SetDescr(role, sDescr);
|
||||
AQH_Role_SetPerms(role, perms);
|
||||
/* add role */
|
||||
if (roleList==NULL) {
|
||||
roleList=AQH_Role_List_new();
|
||||
AQH_Module_SetRoleList(currentMod, roleList);
|
||||
}
|
||||
AQH_Role_List_Add(role, roleList);
|
||||
|
||||
/* save module */
|
||||
rv=AQH_Service_SaveModule(sv, currentMod);
|
||||
if (rv<0) {
|
||||
GBAS(dbuf, "<p>Error saving module.</p>\n");
|
||||
GBAA(dbuf, "<p><a href=\"editmodule.html?name=\"%s\"> back to module</p>\n", sModName?sModName:"");
|
||||
AQH_Module_free(currentMod);
|
||||
return;
|
||||
}
|
||||
_setLocationHeaderForMod(rq, "editmodule.html", sModName);
|
||||
AQCGI_Request_SetResponseCode(rq, 303);
|
||||
AQCGI_Request_SetResponseText(rq, "See Other");
|
||||
AQH_Module_free(currentMod);
|
||||
}
|
||||
else {
|
||||
GBAS(dbuf, "<p>Error loading module.</p>\n");
|
||||
GBAS(dbuf, "<p><a href=\"index.html\"> back to module list</p>\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _handleRqEditRoleGet(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
AQH_SERVICE *sv;
|
||||
GWEN_DB_NODE *dbQuery;
|
||||
const char *sModName;
|
||||
int id;
|
||||
const char *sName;
|
||||
const char *sDescr;
|
||||
uint32_t perms;
|
||||
AQH_MODULE *currentMod;
|
||||
const AQH_PERMDEF_LIST *permDefList;
|
||||
const AQH_ROLE_LIST *roleList;
|
||||
const AQH_ROLE *role;
|
||||
|
||||
sv=AQH_ModService_GetService(m);
|
||||
dbQuery=AQCGI_Request_GetDbQuery(rq);
|
||||
sModName=dbQuery?GWEN_DB_GetCharValue(dbQuery, "mod", 0, NULL):NULL;
|
||||
id=dbQuery?GWEN_DB_GetIntValue(dbQuery, "id", 0, 0):0;
|
||||
currentMod=(sModName && *sModName)?AQH_Service_LoadModule(sv, sModName):NULL;
|
||||
permDefList=currentMod?AQH_Module_GetPermDefList(currentMod):NULL;
|
||||
roleList=currentMod?AQH_Module_GetRoleList(currentMod):NULL;
|
||||
role=roleList?AQH_Role_List_GetById(roleList, id):NULL;
|
||||
sName=role?AQH_Role_GetName(role):NULL;
|
||||
sDescr=role?AQH_Role_GetDescr(role):NULL;
|
||||
perms=role?AQH_Role_GetPerms(role):0;
|
||||
|
||||
if (role) {
|
||||
GBAA(dbuf, "<h2>Edit Role for Module %s</h2>\n", sModName?sModName:"");
|
||||
GBAA(dbuf,
|
||||
"<form action=\"editrole.html\" method=\"post\">\n"
|
||||
"<table class=\"formtable\">\n"
|
||||
"<tr><td><label for=\"name\">Name:</label></td><td><input type=\"text\" name=\"name\" value=\"%s\"></td></tr>\n"
|
||||
"<tr><td><label for=\"descr\">Description:</label></td><td><input type=\"text\" name=\"descr\" value=\"%s\"></td></tr>\n",
|
||||
sName, sDescr?sDescr:"");
|
||||
|
||||
GBAS(dbuf, "<tr><td><label>Permissions:</label></td><td>");
|
||||
AQH_ModService_WritePermsToForm(perms, permDefList, NULL, dbuf);
|
||||
GBAS(dbuf, "</td></tr>\n");
|
||||
|
||||
GBAS(dbuf, "</table>\n");
|
||||
|
||||
GBAA(dbuf, "<input type=\"hidden\" name=\"mod\" value=\"%s\">\n", sModName?sModName:"");
|
||||
GBAA(dbuf, "<input type=\"hidden\" name=\"oldId\" value=\"%d\">\n", id);
|
||||
GBAS(dbuf, "<input type=\"submit\" value=\"Save\">\n");
|
||||
GBAS(dbuf, "</form>\n\n");
|
||||
}
|
||||
else {
|
||||
GBAS(dbuf, "<p>Role not found.</p>\n");
|
||||
GBAA(dbuf, "<p><a href=\"editmodule.html?name=\"%s\"> back to module</p>\n", sModName?sModName:"");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _handleRqEditRolePost(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
AQH_SERVICE *sv;
|
||||
GWEN_DB_NODE *dbPost;
|
||||
const char *sModName;
|
||||
AQH_MODULE *currentMod;
|
||||
int oldId;
|
||||
const char *sName;
|
||||
const char *sDescr;
|
||||
uint32_t perms;
|
||||
AQH_PERMDEF_LIST *permDefList;
|
||||
AQH_ROLE_LIST *roleList;
|
||||
AQH_ROLE *role;
|
||||
int rv;
|
||||
|
||||
/* sample data */
|
||||
sv=AQH_ModService_GetService(m);
|
||||
dbPost=AQCGI_Request_GetDbPostBody(rq);
|
||||
sModName=dbPost?GWEN_DB_GetCharValue(dbPost, "mod", 0, NULL):NULL;
|
||||
currentMod=(sModName && *sModName)?AQH_Service_LoadModule(sv, sModName):NULL;
|
||||
permDefList=currentMod?AQH_Module_GetPermDefList(currentMod):NULL;
|
||||
roleList=currentMod?AQH_Module_GetRoleList(currentMod):NULL;
|
||||
/* read role data */
|
||||
oldId=dbPost?GWEN_DB_GetIntValue(dbPost, "oldId", 0, -1):-1;
|
||||
sName=dbPost?GWEN_DB_GetCharValue(dbPost, "name", 0, NULL):NULL;
|
||||
sDescr=dbPost?GWEN_DB_GetCharValue(dbPost, "descr", 0, NULL):NULL;
|
||||
role=roleList?AQH_Role_List_GetById(roleList, oldId):NULL;
|
||||
perms=(dbPost && permDefList)?AQH_ModService_ReadPermsFromForm(dbPost, permDefList, NULL):0;
|
||||
/* validate */
|
||||
if (!(sName && *sName)) {
|
||||
DBG_ERROR(NULL, "Missing value for \"name\"");
|
||||
GBAS(dbuf, "<p>Missing name.</p>\n");
|
||||
GBAA(dbuf, "<p><a href=\"editmodule.html?name=\"%s\"> back to module</p>\n", sModName?sModName:"");
|
||||
return;
|
||||
}
|
||||
if (role==NULL) {
|
||||
DBG_ERROR(NULL, "Role %d not found", oldId);
|
||||
GBAS(dbuf, "<p>Role not found.</p>\n");
|
||||
GBAA(dbuf, "<p><a href=\"editmodule.html?name=\"%s\"> back to module</p>\n", sModName?sModName:"");
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentMod) {
|
||||
/* set new values */
|
||||
AQH_Role_SetName(role, sName);
|
||||
AQH_Role_SetDescr(role, sDescr);
|
||||
AQH_Role_SetPerms(role, perms);
|
||||
|
||||
/* save module */
|
||||
rv=AQH_Service_SaveModule(sv, currentMod);
|
||||
if (rv<0) {
|
||||
GBAS(dbuf, "<p>Error saving module.</p>\n");
|
||||
GBAA(dbuf, "<p><a href=\"editmodule.html?name=\"%s\"> back to module</p>\n", sModName?sModName:"");
|
||||
AQH_Module_free(currentMod);
|
||||
return;
|
||||
}
|
||||
|
||||
_setLocationHeaderForMod(rq, "editmodule.html", sModName);
|
||||
AQCGI_Request_SetResponseCode(rq, 303);
|
||||
AQCGI_Request_SetResponseText(rq, "See Other");
|
||||
AQH_Module_free(currentMod);
|
||||
}
|
||||
else {
|
||||
GBAS(dbuf, "<p>Error loading module.</p>\n");
|
||||
GBAS(dbuf, "<p><a href=\"index.html\"> back to module list</p>\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _handleRqDeleteRole(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
AQH_SERVICE *sv;
|
||||
GWEN_DB_NODE *dbQuery;
|
||||
const char *sModName;
|
||||
int id;
|
||||
AQH_MODULE *currentMod;
|
||||
const AQH_ROLE_LIST *roleList;
|
||||
AQH_ROLE *role;
|
||||
|
||||
sv=AQH_ModService_GetService(m);
|
||||
dbQuery=AQCGI_Request_GetDbQuery(rq);
|
||||
sModName=dbQuery?GWEN_DB_GetCharValue(dbQuery, "mod", 0, NULL):NULL;
|
||||
id=dbQuery?GWEN_DB_GetIntValue(dbQuery, "id", 0, 0):0;
|
||||
currentMod=(sModName && *sModName)?AQH_Service_LoadModule(sv, sModName):NULL;
|
||||
if (currentMod) {
|
||||
roleList=currentMod?AQH_Module_GetRoleList(currentMod):NULL;
|
||||
role=roleList?AQH_Role_List_GetById(roleList, id):NULL;
|
||||
if (role) {
|
||||
int rv;
|
||||
|
||||
AQH_Role_List_Del(role);
|
||||
AQH_Role_free(role);
|
||||
|
||||
/* save module */
|
||||
rv=AQH_Service_SaveModule(sv, currentMod);
|
||||
if (rv<0) {
|
||||
GBAS(dbuf, "<p>Error saving module.</p>\n");
|
||||
GBAA(dbuf, "<p><a href=\"editmodule.html?name=\"%s\"> back to module</p>\n", sModName?sModName:"");
|
||||
AQH_Module_free(currentMod);
|
||||
return;
|
||||
}
|
||||
|
||||
_setLocationHeaderForMod(rq, "editmodule.html", sModName);
|
||||
AQCGI_Request_SetResponseCode(rq, 303);
|
||||
AQCGI_Request_SetResponseText(rq, "See Other");
|
||||
}
|
||||
else {
|
||||
GBAS(dbuf, "<p>Role not found.</p>\n");
|
||||
GBAA(dbuf, "<p><a href=\"editmodule.html?name=\"%s\"> back to module</p>\n", sModName?sModName:"");
|
||||
}
|
||||
AQH_Module_free(currentMod);
|
||||
}
|
||||
else {
|
||||
GBAS(dbuf, "<p>Error loading module.</p>\n");
|
||||
GBAS(dbuf, "<p><a href=\"index.html\"> back to module list</p>\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _setLocationHeaderForMod(AQCGI_REQUEST *rq, const char *page, const char *sModName)
|
||||
{
|
||||
GWEN_BUFFER *tbuf;
|
||||
|
||||
tbuf=GWEN_Buffer_new(0, 256, 0, 1);
|
||||
GBAA(tbuf, "Location: %s?name=%s", page?page:"", sModName?sModName:"");
|
||||
AQCGI_Request_AddResponseHeaderData(rq, GWEN_Buffer_GetStart(tbuf));
|
||||
GWEN_Buffer_free(tbuf);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _getHighestUsedRoleId(const AQH_ROLE_LIST *roleList)
|
||||
{
|
||||
int id=0;
|
||||
|
||||
if (roleList) {
|
||||
const AQH_ROLE *role;
|
||||
|
||||
role=AQH_Role_List_First(roleList);
|
||||
while(role) {
|
||||
int rid;
|
||||
|
||||
rid=AQH_Role_GetId(role);
|
||||
id=(rid>id)?rid:id;
|
||||
role=AQH_Role_List_Next(role);
|
||||
}
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _writeEditModForm(const AQH_MODULE *currentMod, const char *sModName, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
const char *sName;
|
||||
const char *sDescr;
|
||||
const AQH_PERMDEF_LIST *permDefList;
|
||||
const AQH_ROLE_LIST *roleList;
|
||||
|
||||
permDefList=AQH_Module_GetPermDefList(currentMod);
|
||||
roleList=AQH_Module_GetRoleList(currentMod);
|
||||
sName=AQH_Module_GetName(currentMod);
|
||||
sDescr=AQH_Module_GetDescr(currentMod);
|
||||
/* write module info */
|
||||
GBAS(dbuf, "<h2>Module Info</h2>\n");
|
||||
GBAA(dbuf,
|
||||
"<form action=\"editmodule.html\" method=\"post\">\n"
|
||||
"<table class=\"formtable\">\n"
|
||||
"<tr><td><label for=\"name\">Name:</label></td><td><input type=\"text\" name=\"name\" value=\"%s\"></td></tr>\n"
|
||||
"<tr><td><label for=\"descr\">Description:</label></td><td><input type=\"text\" name=\"descr\" value=\"%s\"></td></tr>\n",
|
||||
sName?sName:"", sDescr?sDescr:"");
|
||||
|
||||
if (permDefList) {
|
||||
GBAA(dbuf, "<tr><td><label>Guest Permissions:</label></td>\n<td>");
|
||||
AQH_ModService_WritePermsToForm(AQH_Module_GetGuestPerms(currentMod), permDefList, NULL, dbuf);
|
||||
GBAA(dbuf, "</td></tr>");
|
||||
}
|
||||
|
||||
GBAS(dbuf, "</table>\n");
|
||||
|
||||
GBAA(dbuf, "<input type=\"hidden\" name=\"module\" value=\"%s\">\n", sModName?sModName:"");
|
||||
GBAS(dbuf, "<input type=\"submit\" value=\"Save\">\n</form>\n\n");
|
||||
|
||||
/* write role list */
|
||||
GBAS(dbuf, "<h2>User Roles</h2>\n");
|
||||
if (roleList)
|
||||
_writeRoleListToForm(roleList, sModName, permDefList, dbuf);
|
||||
else
|
||||
GBAS(dbuf, "<p>none</p>");
|
||||
GBAA(dbuf, "<a href=\"addrole.html?mod=%s\"><img src=\"/pics/plus.png\">Add Role</a>\n", sModName?sModName:"");
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _writeRoleListToForm(const AQH_ROLE_LIST *roleList,
|
||||
const char *sModName,
|
||||
const AQH_PERMDEF_LIST *permDefList,
|
||||
GWEN_BUFFER *dbuf)
|
||||
{
|
||||
const AQH_ROLE *role;
|
||||
|
||||
GBAS(dbuf,
|
||||
"<table class=\"datatable\">\n"
|
||||
"<thead><tr><th>Id</th><th>Name</th><th>Permissions</th><th>Description</th><th>Actions</th></tr>\n</thead>\n"
|
||||
"<tbody>\n");
|
||||
role=AQH_Role_List_First(roleList);
|
||||
while(role) {
|
||||
uint8_t id;
|
||||
const char *s;
|
||||
|
||||
GBAS(dbuf, "<tr>");
|
||||
/* id */
|
||||
id=AQH_Role_GetId(role);
|
||||
GBAA(dbuf, "<td>%d</td>", id);
|
||||
/* name */
|
||||
s=AQH_Role_GetName(role);
|
||||
GBAA(dbuf, "<td>%s</td>", s?s:"");
|
||||
/* permissions */
|
||||
GBAS(dbuf, "<td>");
|
||||
if (permDefList)
|
||||
_writeEnabledPermissions(permDefList, AQH_Role_GetPerms(role), dbuf);
|
||||
GBAS(dbuf, "</td>");
|
||||
/* description */
|
||||
s=AQH_Role_GetDescr(role);
|
||||
GBAA(dbuf, "<td>%s</td>", s?s:"");
|
||||
/* actions */
|
||||
GBAA(dbuf, "<td>");
|
||||
GBAA(dbuf, "<a href=\"editrole.html?mod=%s&id=%d\"><img src=\"/pics/edit.png\"></a>", sModName?sModName:"", id);
|
||||
GBAA(dbuf, "<a href=\"delrole.html?mod=%s&id=%d\"><img src=\"/pics/minus.png\"></a>", sModName?sModName:"", id);
|
||||
GBAA(dbuf, "</td>");
|
||||
GBAS(dbuf, "</tr>\n");
|
||||
|
||||
role=AQH_Role_List_Next(role);
|
||||
}
|
||||
|
||||
GBAS(dbuf, "</tbody>\n</table>\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void _writeEnabledPermissions(const AQH_PERMDEF_LIST *permDefList, uint32_t perms, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
if (permDefList) {
|
||||
const AQH_PERMDEF *permDef;
|
||||
|
||||
permDef=AQH_PermDef_List_First(permDefList);
|
||||
while(permDef) {
|
||||
const char *s;
|
||||
uint32_t mask;
|
||||
|
||||
s=AQH_PermDef_GetId(permDef);
|
||||
mask=AQH_PermDef_GetMask(permDef);
|
||||
if (perms & mask)
|
||||
GBAA(dbuf, "%s ", s?s:"");
|
||||
permDef=AQH_PermDef_List_Next(permDef);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
35
apps/aqhome-cgi/modules/common/mmodules.h
Normal file
35
apps/aqhome-cgi/modules/common/mmodules.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef AQHOME_CGI_MMODULES_H
|
||||
#define AQHOME_CGI_MMODULES_H
|
||||
|
||||
#include <aqhome-cgi/modules/common/mservice.h>
|
||||
|
||||
#include <aqcgi/request.h>
|
||||
|
||||
#include <gwenhywfar/buffer.h>
|
||||
|
||||
|
||||
|
||||
#define AQH_MODADMMODULES_PERMS_MODULESREAD 0x001
|
||||
#define AQH_MODADMMODULES_PERMS_MODULESWRITE 0x002
|
||||
#define AQH_MODADMMODULES_PERMS_MODULESADD 0x004
|
||||
#define AQH_MODADMMODULES_PERMS_MODULESDEL 0x008
|
||||
|
||||
|
||||
|
||||
void AQH_ModAdmModules_Extend(AQH_MODULE *m, AQH_SERVICE *sv, const char *baseFolder);
|
||||
|
||||
int AQH_ModAdmModules_Create(AQH_SERVICE *sv);
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
684
apps/aqhome-cgi/modules/common/mservice.c
Normal file
684
apps/aqhome-cgi/modules/common/mservice.c
Normal file
@@ -0,0 +1,684 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "./mservice_p.h"
|
||||
|
||||
#include "aqhome-cgi/service/module.h"
|
||||
|
||||
#include <gwenhywfar/debug.h>
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* defs and enums
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#define AQH_MOD_SERVICE_HEADERFILE "header.html"
|
||||
#define AQH_MOD_SERVICE_FOOTERFILE "footer.html"
|
||||
|
||||
|
||||
#define GBAS GWEN_Buffer_AppendString
|
||||
#define GBAA GWEN_Buffer_AppendArgs
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* global vars
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
GWEN_INHERIT(AQH_MODULE, AQH_MOD_SERVICE)
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* forward declarations
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static void GWENHYWFAR_CB _freeData(void *bp, void *p);
|
||||
static void _calcUserModPerms(AQH_MODULE *m, const AQH_USER *user);
|
||||
static uint32_t _calcRolePerms(const AQH_MODULE *m, const AQH_MODULE_PERMS *modPerms);
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* code
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void AQH_ModService_Extend(AQH_MODULE *m, AQH_SERVICE *sv, const char *baseFolder)
|
||||
{
|
||||
AQH_MOD_SERVICE *xm;
|
||||
|
||||
GWEN_NEW_OBJECT(AQH_MOD_SERVICE, xm);
|
||||
GWEN_INHERIT_SETDATA(AQH_MODULE, AQH_MOD_SERVICE, m, xm, _freeData);
|
||||
|
||||
xm->service=sv;
|
||||
xm->baseFolder=(baseFolder && *baseFolder)?strdup(baseFolder):NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _freeData(GWEN_UNUSED void *bp, void *p)
|
||||
{
|
||||
AQH_MOD_SERVICE *xm;
|
||||
|
||||
xm=(AQH_MOD_SERVICE*) p;
|
||||
free(xm->baseFolder);
|
||||
GWEN_FREE_OBJECT(xm);
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQH_SERVICE *AQH_ModService_GetService(const AQH_MODULE *m)
|
||||
{
|
||||
if (m) {
|
||||
AQH_MOD_SERVICE *xm;
|
||||
|
||||
xm=GWEN_INHERIT_GETDATA(AQH_MODULE, AQH_MOD_SERVICE, m);
|
||||
if (xm) {
|
||||
return xm->service;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char *AQH_ModService_GetBaseFolder(const AQH_MODULE *m)
|
||||
{
|
||||
if (m) {
|
||||
AQH_MOD_SERVICE *xm;
|
||||
|
||||
xm=GWEN_INHERIT_GETDATA(AQH_MODULE, AQH_MOD_SERVICE, m);
|
||||
if (xm) {
|
||||
return xm->baseFolder;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint32_t AQH_ModService_GetUserPerms(const AQH_MODULE *m)
|
||||
{
|
||||
if (m) {
|
||||
AQH_MOD_SERVICE *xm;
|
||||
|
||||
xm=GWEN_INHERIT_GETDATA(AQH_MODULE, AQH_MOD_SERVICE, m);
|
||||
if (xm) {
|
||||
return xm->userPerms;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQH_ModService_SetHandleRequestFn(AQH_MODULE *m, AQH_MODSERVICE_HANDLEREQUEST_FN fn)
|
||||
{
|
||||
if (m) {
|
||||
AQH_MOD_SERVICE *xm;
|
||||
|
||||
xm=GWEN_INHERIT_GETDATA(AQH_MODULE, AQH_MOD_SERVICE, m);
|
||||
if (xm) {
|
||||
xm->handleRequestFn=fn;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQH_ModService_SetLoadSubModuleFn(AQH_MODULE *m, AQH_MODSERVICE_LOADSUBMODULE_FN fn)
|
||||
{
|
||||
if (m) {
|
||||
AQH_MOD_SERVICE *xm;
|
||||
|
||||
xm=GWEN_INHERIT_GETDATA(AQH_MODULE, AQH_MOD_SERVICE, m);
|
||||
if (xm) {
|
||||
xm->loadSubModuleFn=fn;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQH_ModService_SetAddHeaderFn(AQH_MODULE *m, AQH_MODSERVICE_ADDHEADER_FN fn)
|
||||
{
|
||||
if (m) {
|
||||
AQH_MOD_SERVICE *xm;
|
||||
|
||||
xm=GWEN_INHERIT_GETDATA(AQH_MODULE, AQH_MOD_SERVICE, m);
|
||||
if (xm) {
|
||||
xm->addHeaderFn=fn;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQH_ModService_SetAddFooterFn(AQH_MODULE *m, AQH_MODSERVICE_ADDFOOTER_FN fn)
|
||||
{
|
||||
if (m) {
|
||||
AQH_MOD_SERVICE *xm;
|
||||
|
||||
xm=GWEN_INHERIT_GETDATA(AQH_MODULE, AQH_MOD_SERVICE, m);
|
||||
if (xm) {
|
||||
xm->addFooterFn=fn;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQH_ModService_AddHeader(AQH_MODULE *m, const char *lang, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
if (m && dbuf) {
|
||||
AQH_MOD_SERVICE *xm;
|
||||
|
||||
xm=GWEN_INHERIT_GETDATA(AQH_MODULE, AQH_MOD_SERVICE, m);
|
||||
if (xm) {
|
||||
if (xm->addHeaderFn)
|
||||
xm->addHeaderFn(m, lang, dbuf);
|
||||
else {
|
||||
AQH_MODULE *mParent;
|
||||
|
||||
mParent=AQH_Module_Tree2_GetParent(m);
|
||||
if (mParent)
|
||||
AQH_ModService_AddHeader(mParent, lang, dbuf);
|
||||
AQH_ModService_ReadStaticFile(m, lang, AQH_MOD_SERVICE_HEADERFILE, dbuf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQH_ModService_AddFooter(AQH_MODULE *m, const char *lang, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
if (m && dbuf) {
|
||||
AQH_MOD_SERVICE *xm;
|
||||
|
||||
xm=GWEN_INHERIT_GETDATA(AQH_MODULE, AQH_MOD_SERVICE, m);
|
||||
if (xm) {
|
||||
if (xm->addFooterFn)
|
||||
xm->addFooterFn(m, lang, dbuf);
|
||||
else {
|
||||
AQH_MODULE *mParent;
|
||||
|
||||
AQH_ModService_ReadStaticFile(m, lang, AQH_MOD_SERVICE_FOOTERFILE, dbuf);
|
||||
|
||||
mParent=AQH_Module_Tree2_GetParent(m);
|
||||
if (mParent)
|
||||
AQH_ModService_AddFooter(mParent, lang, dbuf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int AQH_ModService_RespondWithFile(AQH_MODULE *m, AQCGI_REQUEST *rq, const char *lang, const char *sFilename, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
int rv;
|
||||
|
||||
rv=AQH_ModService_ReadStaticFile(m, lang, sFilename, dbuf);
|
||||
if (rv<0) {
|
||||
AQCGI_Request_SetResponseCode(rq, 500);
|
||||
AQCGI_Request_SetResponseText(rq, "Internal Error");
|
||||
return GWEN_ERROR_INTERNAL;
|
||||
}
|
||||
AQCGI_Request_SetResponseCode(rq, 200);
|
||||
AQCGI_Request_SetResponseText(rq, "Ok");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int AQH_ModService_HandleRequest(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, const char *sLastPathElem)
|
||||
{
|
||||
if (m) {
|
||||
AQH_MOD_SERVICE *xm;
|
||||
|
||||
xm=GWEN_INHERIT_GETDATA(AQH_MODULE, AQH_MOD_SERVICE, m);
|
||||
if (xm && xm->handleRequestFn)
|
||||
return xm->handleRequestFn(m, rq, session, sLastPathElem);
|
||||
}
|
||||
return GWEN_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQH_MODULE *AQH_ModService_LoadSubModule(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, const char *sModuleName)
|
||||
{
|
||||
if (m) {
|
||||
AQH_MOD_SERVICE *xm;
|
||||
|
||||
xm=GWEN_INHERIT_GETDATA(AQH_MODULE, AQH_MOD_SERVICE, m);
|
||||
if (xm && xm->loadSubModuleFn) {
|
||||
AQH_MODULE *mReturn;
|
||||
|
||||
mReturn=xm->loadSubModuleFn(m, rq, session, sModuleName);
|
||||
if (mReturn)
|
||||
AQH_ModService_CalcSessionModPerms(mReturn, session);
|
||||
return mReturn;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int AQH_ModService_ReadStaticFile(AQH_MODULE *m, const char *lang, const char *filename, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
if (m && filename && dbuf) {
|
||||
AQH_MOD_SERVICE *xm;
|
||||
|
||||
xm=GWEN_INHERIT_GETDATA(AQH_MODULE, AQH_MOD_SERVICE, m);
|
||||
if (xm) {
|
||||
GWEN_BUFFER *fbuf;
|
||||
int rv;
|
||||
|
||||
fbuf=GWEN_Buffer_new(0, 256, 0, 1);
|
||||
GWEN_Buffer_AppendString(fbuf, xm->baseFolder);
|
||||
GWEN_Buffer_AppendString(fbuf, GWEN_DIR_SEPARATOR_S);
|
||||
GWEN_Buffer_AppendString(fbuf, (lang && *lang)?lang:"en");
|
||||
GWEN_Buffer_AppendString(fbuf, GWEN_DIR_SEPARATOR_S);
|
||||
GWEN_Buffer_AppendString(fbuf, filename);
|
||||
DBG_ERROR(NULL, "Reading file \"%s\"", GWEN_Buffer_GetStart(fbuf));
|
||||
rv=GWEN_SyncIo_Helper_ReadFile(GWEN_Buffer_GetStart(fbuf), dbuf);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "Read(%s): %d", GWEN_Buffer_GetStart(fbuf), rv);
|
||||
GWEN_Buffer_free(fbuf);
|
||||
return rv;
|
||||
}
|
||||
GWEN_Buffer_free(fbuf);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
DBG_ERROR(NULL, "Any arg is missing (or is not a AQH_MOD_SERVICE object)");
|
||||
return GWEN_ERROR_INTERNAL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQH_SESSION *AQH_ModService_ReadSession(AQH_MODULE *m, AQCGI_REQUEST *rq)
|
||||
{
|
||||
AQH_SERVICE *sv;
|
||||
GWEN_DB_NODE *db;
|
||||
const char *s;
|
||||
|
||||
sv=AQH_ModService_GetService(m);
|
||||
db=AQCGI_Request_GetDbRequestHeader(rq);
|
||||
s=GWEN_DB_GetCharValue(db, "cookies/session", 0, NULL);
|
||||
if (s && *s) {
|
||||
AQH_SESSION *session;
|
||||
|
||||
session=AQH_Service_LoadSession(sv, s);
|
||||
if (session==NULL) {
|
||||
DBG_ERROR(NULL, "Session \"%s\" not found", s);
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
const char *sUserName;
|
||||
GWEN_BUFFER *tbuf;
|
||||
|
||||
sUserName=AQH_Session_GetUserAlias(session);
|
||||
if (sUserName && *sUserName) {
|
||||
AQH_USER *user;
|
||||
|
||||
user=AQH_Service_LoadUser(sv, sUserName);
|
||||
if (user==NULL) {
|
||||
DBG_ERROR(NULL, "User \"%s\" not found", sUserName);
|
||||
AQH_Session_free(session);
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
DBG_ERROR(NULL, "User is \"%s\"", sUserName);
|
||||
}
|
||||
AQH_Session_SetUser(session, user);
|
||||
}
|
||||
/* renew session cookie */
|
||||
tbuf=GWEN_Buffer_new(0, 256, 0, 1);
|
||||
GWEN_Buffer_AppendArgs(tbuf, "Set-Cookie: session=%s; max-age=86400", AQH_Session_GetUid(session));
|
||||
AQCGI_Request_AddResponseHeaderData(rq, GWEN_Buffer_GetStart(tbuf));
|
||||
DBG_ERROR(NULL, "Renew session cookie");
|
||||
GWEN_Buffer_free(tbuf);
|
||||
return session;
|
||||
}
|
||||
}
|
||||
else {
|
||||
DBG_ERROR(NULL, "No session cookie");
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQH_ModService_CalcSessionModPerms(AQH_MODULE *m, const AQH_SESSION *session)
|
||||
{
|
||||
const AQH_USER *user;
|
||||
|
||||
user=session?AQH_Session_GetUser(session):NULL;
|
||||
_calcUserModPerms(m, user);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _calcUserModPerms(AQH_MODULE *m, const AQH_USER *user)
|
||||
{
|
||||
if (m) {
|
||||
AQH_MOD_SERVICE *xm;
|
||||
|
||||
xm=GWEN_INHERIT_GETDATA(AQH_MODULE, AQH_MOD_SERVICE, m);
|
||||
if (xm) {
|
||||
uint32_t perms=0;
|
||||
|
||||
if (user) {
|
||||
if (AQH_User_GetFlags(user) & AQH_USER_FLAGS_ADMIN)
|
||||
perms=0xffffffff;
|
||||
else {
|
||||
const char *sModName;
|
||||
const AQH_MODULE_PERMS_LIST *modPermsList;
|
||||
AQH_MODULE_PERMS *modPerms;
|
||||
|
||||
sModName=AQH_Module_GetName(m);
|
||||
modPermsList=AQH_User_GetModulePermList(user);
|
||||
modPerms=(sModName && modPermsList)?AQH_ModulePerms_List_GetByModuleId(modPermsList, sModName):NULL;
|
||||
if (modPerms)
|
||||
perms=_calcRolePerms(m, modPerms);
|
||||
else
|
||||
perms=AQH_Module_GetGuestPerms(m);
|
||||
}
|
||||
} /* if (user) */
|
||||
else
|
||||
perms=AQH_Module_GetGuestPerms(m);
|
||||
xm->userPerms=perms;
|
||||
}
|
||||
} /* if (m) */
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint32_t _calcRolePerms(const AQH_MODULE *m, const AQH_MODULE_PERMS *modPerms)
|
||||
{
|
||||
uint32_t perms=0;
|
||||
const AQH_ROLE_LIST *roleList;
|
||||
|
||||
roleList=AQH_Module_GetRoleList(m);
|
||||
if (roleList) {
|
||||
int roleArraySize;
|
||||
int i;
|
||||
uint32_t explAddPerms=0;
|
||||
uint32_t explDelPerms=0;
|
||||
|
||||
roleArraySize=AQH_ModulePerms_GetRoleArrayArraySize();
|
||||
for (i=0; i<roleArraySize; i++) {
|
||||
int roleId;
|
||||
|
||||
roleId=AQH_ModulePerms_GetRoleArrayAt(modPerms, i);
|
||||
if (roleId) {
|
||||
const AQH_ROLE *role;
|
||||
|
||||
role=AQH_Role_List_GetById(roleList, roleId);
|
||||
if (role) {
|
||||
perms|=AQH_Role_GetPerms(role);
|
||||
explAddPerms|=AQH_Role_GetExplAddPerms(role);
|
||||
explAddPerms|=AQH_Role_GetExplDelPerms(role);
|
||||
}
|
||||
}
|
||||
} /* for */
|
||||
/* collate permissions */
|
||||
perms|=explAddPerms;
|
||||
perms|=AQH_ModulePerms_GetExplAddPerms(modPerms);
|
||||
perms&=~explDelPerms;
|
||||
perms&=~AQH_ModulePerms_GetExplDelPerms(modPerms);
|
||||
}
|
||||
return perms;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void AQH_ModService_AddPermDef(AQH_PERMDEF_LIST *permDefList, const char *id, uint32_t mask, const char *descr)
|
||||
{
|
||||
AQH_PERMDEF *permDef;
|
||||
|
||||
permDef=AQH_PermDef_new();
|
||||
AQH_PermDef_SetId(permDef, id);
|
||||
AQH_PermDef_SetMask(permDef, mask);
|
||||
AQH_PermDef_SetDescr(permDef, descr);
|
||||
AQH_PermDef_List_Add(permDef, permDefList);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQH_ModService_AddRole(AQH_ROLE_LIST *roleList, int id, const char *name, uint32_t perms, const char *descr)
|
||||
{
|
||||
AQH_ROLE *role;
|
||||
|
||||
role=AQH_Role_new();
|
||||
AQH_Role_SetId(role, id);
|
||||
AQH_Role_SetName(role, name);
|
||||
AQH_Role_SetPerms(role, perms);
|
||||
AQH_Role_SetDescr(role, descr);
|
||||
AQH_Role_List_Add(role, roleList);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQH_ModService_HandleRequestWithTable(AQH_MODULE *m,
|
||||
AQCGI_REQUEST *rq,
|
||||
AQH_SESSION *session,
|
||||
const char *page,
|
||||
const AQH_MODSERVICE_HANDLER_ENTRY *e)
|
||||
{
|
||||
uint32_t perms;
|
||||
GWEN_BUFFER *dbuf;
|
||||
int i;
|
||||
|
||||
perms=AQH_ModService_GetUserPerms(m);
|
||||
DBG_ERROR(NULL, "Perms=%08x", perms);
|
||||
|
||||
dbuf=GWEN_Buffer_new(0, 256, 0, 1);
|
||||
AQH_ModService_AddHeader(m, "en", dbuf);
|
||||
|
||||
for (i=0; ; i++) {
|
||||
if (e[i].page==NULL) {
|
||||
AQCGI_Request_SetResponseCode(rq, 404);
|
||||
AQCGI_Request_SetResponseText(rq, "Not Found");
|
||||
break;
|
||||
}
|
||||
if ((AQCGI_Request_GetRequestMethod(rq)==e[i].httpMethod) &&
|
||||
(strcasecmp(page, e[i].page)==0)) {
|
||||
/* preset result */
|
||||
AQCGI_Request_SetResponseCode(rq, 200);
|
||||
AQCGI_Request_SetResponseText(rq, "Ok");
|
||||
if ((perms & e[i].perms)==e[i].perms)
|
||||
(e[i].handlerFn)(m, rq, session, dbuf);
|
||||
else {
|
||||
GWEN_Buffer_AppendString(dbuf, "<h1>Error</h1><p>No permissions for this request.</p>");
|
||||
AQCGI_Request_SetResponseCode(rq, 403);
|
||||
AQCGI_Request_SetResponseText(rq, "Forbidden");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(AQCGI_Request_GetFlags(rq) & AQH_MODSERVICE_RQFLAGS_RAWFILE)) {
|
||||
DBG_ERROR(NULL, "Not adding footer");
|
||||
AQH_ModService_AddFooter(m, "en", dbuf);
|
||||
}
|
||||
AQCGI_Request_SetBufferResponseBody(rq, dbuf);
|
||||
if (AQCGI_Request_GetFlags(rq) & AQCGI_FLAGS_HAS_CONTENT_HEADER)
|
||||
AQCGI_Request_AddResponseHeaderData(rq, "Content-type: text/html");
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQH_ModService_WritePermsToForm(uint32_t perms, const AQH_PERMDEF_LIST *permDefList, const char *sPrefix, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
if (permDefList) {
|
||||
const AQH_PERMDEF *permDef;
|
||||
GWEN_BUFFER *tbuf;
|
||||
uint32_t pos;
|
||||
|
||||
tbuf=GWEN_Buffer_new(0, 256, 0, 1);
|
||||
if (sPrefix && *sPrefix)
|
||||
GBAA(tbuf, "%s:", sPrefix);
|
||||
pos=GWEN_Buffer_GetPos(tbuf);
|
||||
|
||||
permDef=AQH_PermDef_List_First(permDefList);
|
||||
while(permDef) {
|
||||
const char *s;
|
||||
|
||||
s=AQH_PermDef_GetId(permDef);
|
||||
if (s && *s) {
|
||||
uint32_t mask;
|
||||
|
||||
GBAS(tbuf, s);
|
||||
mask=AQH_PermDef_GetMask(permDef);
|
||||
if (perms & mask)
|
||||
GBAA(dbuf, "<input type=\"checkbox\" name=\"%s\" checked>", GWEN_Buffer_GetStart(tbuf));
|
||||
else
|
||||
GBAA(dbuf, "<input type=\"checkbox\" name=\"%s\">", s?s:"");
|
||||
GBAA(dbuf, "<label for=\"%s\">%s</label>", GWEN_Buffer_GetStart(tbuf), s?s:"");
|
||||
GWEN_Buffer_Crop(tbuf, 0, pos);
|
||||
}
|
||||
permDef=AQH_PermDef_List_Next(permDef);
|
||||
}
|
||||
GWEN_Buffer_free(tbuf);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint32_t AQH_ModService_ReadPermsFromForm(GWEN_DB_NODE *dbPost, const AQH_PERMDEF_LIST *permDefList, const char *sPrefix)
|
||||
{
|
||||
uint32_t result=0;
|
||||
|
||||
if (permDefList) {
|
||||
const AQH_PERMDEF *permDef;
|
||||
GWEN_BUFFER *tbuf;
|
||||
uint32_t pos;
|
||||
|
||||
tbuf=GWEN_Buffer_new(0, 256, 0, 1);
|
||||
if (sPrefix && *sPrefix)
|
||||
GBAA(tbuf, "%s:", sPrefix);
|
||||
pos=GWEN_Buffer_GetPos(tbuf);
|
||||
|
||||
permDef=AQH_PermDef_List_First(permDefList);
|
||||
while(permDef) {
|
||||
const char *id;
|
||||
|
||||
id=AQH_PermDef_GetId(permDef);
|
||||
if (id && *id) {
|
||||
uint32_t mask;
|
||||
const char *s;
|
||||
|
||||
GBAS(tbuf, id);
|
||||
mask=AQH_PermDef_GetMask(permDef);
|
||||
s=GWEN_DB_GetCharValue(dbPost, GWEN_Buffer_GetStart(tbuf), 0, NULL);
|
||||
if (s && *s)
|
||||
result|=mask;
|
||||
GWEN_Buffer_Crop(tbuf, 0, pos);
|
||||
}
|
||||
permDef=AQH_PermDef_List_Next(permDef);
|
||||
}
|
||||
GWEN_Buffer_free(tbuf);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQH_MODULE_LIST *AQH_ModService_LoadRawModules(AQH_MODULE *m)
|
||||
{
|
||||
AQH_SERVICE *sv;
|
||||
GWEN_STRINGLIST *slModuleNames;
|
||||
|
||||
sv=AQH_ModService_GetService(m);
|
||||
slModuleNames=AQH_Service_ListModules(sv);
|
||||
if (slModuleNames) {
|
||||
AQH_MODULE_LIST *modList;
|
||||
GWEN_STRINGLISTENTRY *se;
|
||||
|
||||
modList=AQH_Module_List_new();
|
||||
se=GWEN_StringList_FirstEntry(slModuleNames);
|
||||
while(se) {
|
||||
const char *sModName;
|
||||
|
||||
sModName=GWEN_StringListEntry_Data(se);
|
||||
if (sModName && *sModName) {
|
||||
AQH_MODULE *currentMod;
|
||||
|
||||
currentMod=AQH_Service_LoadModule(sv, sModName);
|
||||
if (currentMod)
|
||||
AQH_Module_List_Add(currentMod, modList);
|
||||
}
|
||||
se=GWEN_StringListEntry_Next(se);
|
||||
}
|
||||
GWEN_StringList_free(slModuleNames);
|
||||
if (AQH_Module_List_GetCount(modList))
|
||||
return modList;
|
||||
AQH_Module_List_free(modList);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQH_USER_LIST *AQH_ModService_LoadRawUsers(AQH_MODULE *m)
|
||||
{
|
||||
AQH_SERVICE *sv;
|
||||
GWEN_STRINGLIST *slUserNames;
|
||||
|
||||
sv=AQH_ModService_GetService(m);
|
||||
slUserNames=AQH_Service_ListUsers(sv);
|
||||
if (slUserNames) {
|
||||
AQH_USER_LIST *userList;
|
||||
GWEN_STRINGLISTENTRY *se;
|
||||
|
||||
userList=AQH_User_List_new();
|
||||
se=GWEN_StringList_FirstEntry(slUserNames);
|
||||
while(se) {
|
||||
const char *sModName;
|
||||
|
||||
sModName=GWEN_StringListEntry_Data(se);
|
||||
if (sModName && *sModName) {
|
||||
AQH_USER *u;
|
||||
|
||||
u=AQH_Service_LoadUser(sv, sModName);
|
||||
if (u)
|
||||
AQH_User_List_Add(u, userList);
|
||||
}
|
||||
se=GWEN_StringListEntry_Next(se);
|
||||
}
|
||||
GWEN_StringList_free(slUserNames);
|
||||
if (AQH_User_List_GetCount(userList))
|
||||
return userList;
|
||||
AQH_User_List_free(userList);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
85
apps/aqhome-cgi/modules/common/mservice.h
Normal file
85
apps/aqhome-cgi/modules/common/mservice.h
Normal file
@@ -0,0 +1,85 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef AQHOME_CGI_MSERVICE_H
|
||||
#define AQHOME_CGI_MSERVICE_H
|
||||
|
||||
#include <aqhome-cgi/service/module.h>
|
||||
#include <aqhome-cgi/service/service.h>
|
||||
#include <aqhome-cgi/service/session.h>
|
||||
|
||||
#include <aqcgi/request.h>
|
||||
|
||||
#include <gwenhywfar/buffer.h>
|
||||
|
||||
|
||||
#define AQH_MODSERVICE_RQFLAGS_RAWFILE 0x10000000
|
||||
|
||||
|
||||
|
||||
typedef int (*AQH_MODSERVICE_HANDLEREQUEST_FN)(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, const char *sLastPathElem);
|
||||
typedef AQH_MODULE* (*AQH_MODSERVICE_LOADSUBMODULE_FN)(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, const char *sModuleName);
|
||||
typedef void (*AQH_MODSERVICE_ADDHEADER_FN)(AQH_MODULE *m, const char *lang, GWEN_BUFFER *dbuf);
|
||||
typedef void (*AQH_MODSERVICE_ADDFOOTER_FN)(AQH_MODULE *m, const char *lang, GWEN_BUFFER *dbuf);
|
||||
|
||||
|
||||
typedef struct AQH_MODSERVICE_HANDLER_ENTRY AQH_MODSERVICE_HANDLER_ENTRY;
|
||||
struct AQH_MODSERVICE_HANDLER_ENTRY {
|
||||
const char *page;
|
||||
int httpMethod;
|
||||
uint32_t perms;
|
||||
void (*handlerFn)(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf);
|
||||
};
|
||||
|
||||
|
||||
|
||||
void AQH_ModService_Extend(AQH_MODULE *m, AQH_SERVICE *sv, const char *baseFolder);
|
||||
|
||||
AQH_SERVICE *AQH_ModService_GetService(const AQH_MODULE *m);
|
||||
const char *AQH_ModService_GetBaseFolder(const AQH_MODULE *m);
|
||||
|
||||
uint32_t AQH_ModService_GetUserPerms(const AQH_MODULE *m);
|
||||
|
||||
void AQH_ModService_AddHeader(AQH_MODULE *m, const char *lang, GWEN_BUFFER *dbuf);
|
||||
void AQH_ModService_AddFooter(AQH_MODULE *m, const char *lang, GWEN_BUFFER *dbuf);
|
||||
|
||||
AQH_MODULE *AQH_ModService_LoadSubModule(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, const char *sModuleName);
|
||||
int AQH_ModService_HandleRequest(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, const char *sLastPathElem);
|
||||
|
||||
AQH_SESSION *AQH_ModService_ReadSession(AQH_MODULE *m, AQCGI_REQUEST *rq);
|
||||
void AQH_ModService_CalcSessionModPerms(AQH_MODULE *m, const AQH_SESSION *session);
|
||||
|
||||
void AQH_ModService_HandleRequestWithTable(AQH_MODULE *m,
|
||||
AQCGI_REQUEST *rq,
|
||||
AQH_SESSION *session,
|
||||
const char *page,
|
||||
const AQH_MODSERVICE_HANDLER_ENTRY *e);
|
||||
|
||||
int AQH_ModService_RespondWithFile(AQH_MODULE *m, AQCGI_REQUEST *rq, const char *lang, const char *sFilename, GWEN_BUFFER *dbuf);
|
||||
int AQH_ModService_ReadStaticFile(AQH_MODULE *m, const char *lang, const char *filename, GWEN_BUFFER *dbuf);
|
||||
|
||||
void AQH_ModService_AddPermDef(AQH_PERMDEF_LIST *permDefList, const char *id, uint32_t mask, const char *descr);
|
||||
void AQH_ModService_AddRole(AQH_ROLE_LIST *roleList, int id, const char *name, uint32_t perms, const char *descr);
|
||||
|
||||
|
||||
void AQH_ModService_WritePermsToForm(uint32_t perms, const AQH_PERMDEF_LIST *permDefList, const char *sPrefix, GWEN_BUFFER *dbuf);
|
||||
uint32_t AQH_ModService_ReadPermsFromForm(GWEN_DB_NODE *dbPost, const AQH_PERMDEF_LIST *permDefList, const char *sPrefix);
|
||||
|
||||
AQH_MODULE_LIST *AQH_ModService_LoadRawModules(AQH_MODULE *m);
|
||||
AQH_USER_LIST *AQH_ModService_LoadRawUsers(AQH_MODULE *m);
|
||||
|
||||
|
||||
void AQH_ModService_SetHandleRequestFn(AQH_MODULE *m, AQH_MODSERVICE_HANDLEREQUEST_FN fn);
|
||||
void AQH_ModService_SetLoadSubModuleFn(AQH_MODULE *m, AQH_MODSERVICE_LOADSUBMODULE_FN fn);
|
||||
|
||||
void AQH_ModService_SetAddHeaderFn(AQH_MODULE *m, AQH_MODSERVICE_ADDHEADER_FN fn);
|
||||
void AQH_ModService_SetAddFooterFn(AQH_MODULE *m, AQH_MODSERVICE_ADDFOOTER_FN fn);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
30
apps/aqhome-cgi/modules/common/mservice_p.h
Normal file
30
apps/aqhome-cgi/modules/common/mservice_p.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef AQHOME_CGI_MSERVICE_P_H
|
||||
#define AQHOME_CGI_MSERVICE_P_H
|
||||
|
||||
#include "aqhome-cgi/modules/common/mservice.h"
|
||||
|
||||
|
||||
typedef struct AQH_MOD_SERVICE AQH_MOD_SERVICE;
|
||||
struct AQH_MOD_SERVICE {
|
||||
AQH_SERVICE *service;
|
||||
char *baseFolder;
|
||||
uint32_t userPerms;
|
||||
|
||||
AQH_MODSERVICE_HANDLEREQUEST_FN handleRequestFn;
|
||||
AQH_MODSERVICE_LOADSUBMODULE_FN loadSubModuleFn;
|
||||
AQH_MODSERVICE_ADDHEADER_FN addHeaderFn;
|
||||
AQH_MODSERVICE_ADDFOOTER_FN addFooterFn;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
640
apps/aqhome-cgi/modules/common/musers.c
Normal file
640
apps/aqhome-cgi/modules/common/musers.c
Normal file
@@ -0,0 +1,640 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "./musers.h"
|
||||
|
||||
#include "aqhome-cgi/service/module.h"
|
||||
|
||||
#include <gwenhywfar/debug.h>
|
||||
#include <gwenhywfar/timestamp.h>
|
||||
#include <gwenhywfar/text.h>
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* defs and enums
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#define GBAS GWEN_Buffer_AppendString
|
||||
#define GBAA GWEN_Buffer_AppendArgs
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* forward declarations
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static void _createPermDefList(AQH_MODULE *m);
|
||||
static void _createRoleList(AQH_MODULE *m);
|
||||
|
||||
static AQH_MODULE *_loadSubModule(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, const char *sModuleName);
|
||||
static int _handleRequest(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, const char *sLastPathElem);
|
||||
static void _handleRqIndex(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf);
|
||||
static void _handleRqEditUserGet(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf);
|
||||
static void _handleRqEditUserPost(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf);
|
||||
static void _handleRqAddUserGet(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf);
|
||||
static void _handleRqAddUserPost(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf);
|
||||
|
||||
static int _getHighestUserId(const AQH_USER_LIST *userList);
|
||||
static int _modulePermsHasRole(const AQH_MODULE_PERMS *modPerms, uint8_t rid);
|
||||
|
||||
static void _writeEditUserForm(AQH_MODULE *m,
|
||||
const AQH_USER *u,
|
||||
const char *sAlias,
|
||||
const char *sUrl,
|
||||
const char *sSubmitText,
|
||||
GWEN_BUFFER *dbuf);
|
||||
static void _writeUserModRolesToForm(const AQH_ROLE_LIST *roles, const AQH_MODULE_PERMS *perms, const char *sModName, GWEN_BUFFER *dbuf);
|
||||
|
||||
static void _readAllModRolesForUserFromForm(AQH_MODULE *m, GWEN_DB_NODE *dbPost, AQH_USER *u);
|
||||
static void _readModRolesFromForm(GWEN_DB_NODE *dbPost,
|
||||
const AQH_ROLE_LIST *roleList,
|
||||
const char *sPrefix,
|
||||
AQH_MODULE_PERMS *modPerms);
|
||||
|
||||
static void _addLabelAndInputToFormTableH(const char *title, const char *name, const char *value, const char *xxtra, GWEN_BUFFER *dbuf);
|
||||
static void _addUserStateLabelAndSelectionToFormTableH(const char *sTitle, const char *sName, int st, GWEN_BUFFER *dbuf);
|
||||
|
||||
static void _setLocationHeaderForMod(AQCGI_REQUEST *rq, const char *page, const char *sModName);
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* vars
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static AQH_MODSERVICE_HANDLER_ENTRY _requestTable[]={
|
||||
{"index.html", AQCGI_REQUEST_METHOD_GET, AQH_MODADMUSERS_PERMS_USERSREAD, _handleRqIndex},
|
||||
{"edituser.html", AQCGI_REQUEST_METHOD_GET, AQH_MODADMUSERS_PERMS_USERSWRITE, _handleRqEditUserGet},
|
||||
{"edituser.html", AQCGI_REQUEST_METHOD_POST, AQH_MODADMUSERS_PERMS_USERSWRITE, _handleRqEditUserPost},
|
||||
{"adduser.html", AQCGI_REQUEST_METHOD_GET, AQH_MODADMUSERS_PERMS_USERSWRITE, _handleRqAddUserGet},
|
||||
{"adduser.html", AQCGI_REQUEST_METHOD_POST, AQH_MODADMUSERS_PERMS_USERSWRITE, _handleRqAddUserPost},
|
||||
{NULL, 0, 0, NULL}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* code
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void AQH_ModAdmUsers_Extend(AQH_MODULE *m, AQH_SERVICE *sv, const char *baseFolder)
|
||||
{
|
||||
AQH_ModService_Extend(m, sv, baseFolder);
|
||||
AQH_ModService_SetHandleRequestFn(m, _handleRequest);
|
||||
AQH_ModService_SetLoadSubModuleFn(m, _loadSubModule);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int AQH_ModAdmUsers_Create(AQH_SERVICE *sv)
|
||||
{
|
||||
AQH_MODULE *m;
|
||||
int rv;
|
||||
|
||||
m=AQH_Module_new();
|
||||
AQH_Module_SetName(m, "users");
|
||||
AQH_Module_SetDescr(m, "user administration module");
|
||||
AQH_Module_SetGuestPerms(m, 0);
|
||||
|
||||
_createPermDefList(m);
|
||||
_createRoleList(m);
|
||||
|
||||
rv=AQH_Service_AddModule(sv, m);
|
||||
if (rv<0) {
|
||||
DBG_INFO(NULL, "here (%d)", rv);
|
||||
}
|
||||
AQH_Module_free(m);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _createPermDefList(AQH_MODULE *m)
|
||||
{
|
||||
AQH_PERMDEF_LIST *permDefList;
|
||||
|
||||
permDefList=AQH_PermDef_List_new();
|
||||
|
||||
AQH_ModService_AddPermDef(permDefList, "UserRead", 0x001, "Read users");
|
||||
AQH_ModService_AddPermDef(permDefList, "UserWrite", 0x002, "Modify users");
|
||||
AQH_ModService_AddPermDef(permDefList, "UserAdd", 0x004, "Add users");
|
||||
AQH_ModService_AddPermDef(permDefList, "UserDel", 0x008, "Remove users");
|
||||
|
||||
AQH_Module_SetPermDefList(m, permDefList);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _createRoleList(AQH_MODULE *m)
|
||||
{
|
||||
AQH_ROLE_LIST *roleList;
|
||||
int id=0;
|
||||
|
||||
roleList=AQH_Role_List_new();
|
||||
AQH_ModService_AddRole(roleList, id++, "admin",
|
||||
AQH_MODADMUSERS_PERMS_USERSREAD |
|
||||
AQH_MODADMUSERS_PERMS_USERSWRITE |
|
||||
AQH_MODADMUSERS_PERMS_USERSADD |
|
||||
AQH_MODADMUSERS_PERMS_USERSDEL,
|
||||
"Administrator Role");
|
||||
AQH_Module_SetRoleList(m, roleList);
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQH_MODULE *_loadSubModule(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, const char *sModuleName)
|
||||
{
|
||||
/* no sub-modules */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _handleRequest(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, const char *sLastPathElem)
|
||||
{
|
||||
AQH_ModService_HandleRequestWithTable(m, rq, session, sLastPathElem, _requestTable);
|
||||
return AQCGI_SendResponse(rq);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _handleRqIndex(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
AQH_USER_LIST *userList;
|
||||
uint32_t perms;
|
||||
|
||||
perms=AQH_ModService_GetUserPerms(m);
|
||||
userList=AQH_ModService_LoadRawUsers(m);
|
||||
|
||||
GBAS(dbuf, "<h1>Users</h1>\n");
|
||||
GBAS(dbuf,
|
||||
"<table class=\"datatable\">\n"
|
||||
"<thead>"
|
||||
"<tr><th>Id</th><th>Alias</th><th>Name</th><th>Status</th><th>Email</th><th>Notes</th><th>Actions</th></tr>\n"
|
||||
"</thead>\n"
|
||||
"<tbody>\n");
|
||||
if (userList) {
|
||||
const AQH_USER *u;
|
||||
|
||||
AQH_User_List_SortByAlias(userList, 1);
|
||||
u=AQH_User_List_First(userList);
|
||||
while(u) {
|
||||
const char *sUserAlias;
|
||||
|
||||
sUserAlias=AQH_User_GetAlias(u);
|
||||
if (sUserAlias && *sUserAlias) {
|
||||
uint32_t id;
|
||||
const char *s;
|
||||
const char *sAlias;
|
||||
|
||||
id=AQH_User_GetId(u);
|
||||
sAlias=AQH_User_GetAlias(u);
|
||||
GBAS(dbuf, "<tr>");
|
||||
GBAA(dbuf, "<td>%lu</td>", (unsigned long int) id);
|
||||
GBAA(dbuf, "<td>%s</td>", sAlias?sAlias:"");
|
||||
s=AQH_User_GetName(u);
|
||||
GBAA(dbuf, "<td>%s</td>", s?s:"");
|
||||
s=AQH_UserState_toString(AQH_User_GetState(u));
|
||||
GBAA(dbuf, "<td>%s</td>", s?s:"");
|
||||
s=AQH_User_GetEmail(u);
|
||||
GBAA(dbuf, "<td>%s</td>", s?s:"");
|
||||
s=AQH_User_GetNotes(u);
|
||||
GBAA(dbuf, "<td>%s</td>", s?s:"");
|
||||
|
||||
GBAS(dbuf, "<td>");
|
||||
if (perms & AQH_MODADMUSERS_PERMS_USERSWRITE) {
|
||||
DBG_ERROR(NULL, "User=%s", sAlias?sAlias:"");
|
||||
GBAS(dbuf, "<a href=\"edituser.html?alias=");
|
||||
GWEN_Text_EscapeToBufferTolerant(sAlias?sAlias:"", dbuf);
|
||||
GBAS(dbuf, "\"><img src=\"/pics/edit.png\"></a>");
|
||||
}
|
||||
GBAA(dbuf, "</td>\n");
|
||||
GBAA(dbuf, "</tr>\n");
|
||||
}
|
||||
u=AQH_User_List_Next(u);
|
||||
}
|
||||
GBAS(dbuf,
|
||||
"</tbody>\n"
|
||||
"</table>\n");
|
||||
AQH_User_List_free(userList);
|
||||
}
|
||||
if (perms & AQH_MODADMUSERS_PERMS_USERSADD)
|
||||
GBAS(dbuf, "<hr><a href=\"adduser.html\">Add User</a>");
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _handleRqEditUserGet(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
AQH_SERVICE *sv;
|
||||
GWEN_DB_NODE *dbQuery;
|
||||
const char *sAlias;
|
||||
AQH_USER *user;
|
||||
|
||||
sv=AQH_ModService_GetService(m);
|
||||
dbQuery=AQCGI_Request_GetDbQuery(rq);
|
||||
sAlias=dbQuery?GWEN_DB_GetCharValue(dbQuery, "alias", 0, NULL):NULL;
|
||||
user=(sAlias && *sAlias)?AQH_Service_LoadUser(sv, sAlias):NULL;
|
||||
if (user) {
|
||||
_writeEditUserForm(m, user, sAlias, "edituser.html", "Save", dbuf);
|
||||
AQH_User_free(user);
|
||||
}
|
||||
else {
|
||||
AQCGI_Request_AddResponseHeaderData(rq, "Location: index.html");
|
||||
AQCGI_Request_SetResponseCode(rq, 303);
|
||||
AQCGI_Request_SetResponseText(rq, "See other");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _handleRqEditUserPost(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
AQH_SERVICE *sv;
|
||||
GWEN_DB_NODE *dbPost;
|
||||
const char *sAlias;
|
||||
AQH_USER *u;
|
||||
|
||||
sv=AQH_ModService_GetService(m);
|
||||
dbPost=AQCGI_Request_GetDbPostBody(rq);
|
||||
sAlias=dbPost?GWEN_DB_GetCharValue(dbPost, "alias", 0, NULL):NULL;
|
||||
u=(sAlias && *sAlias)?AQH_Service_LoadUser(sv, sAlias):NULL;
|
||||
if (u) {
|
||||
const char *s;
|
||||
int state;
|
||||
int rv;
|
||||
|
||||
s=GWEN_DB_GetCharValue(dbPost, "name", 0, NULL);
|
||||
AQH_User_SetName(u, s);
|
||||
s=GWEN_DB_GetCharValue(dbPost, "email", 0, NULL);
|
||||
AQH_User_SetEmail(u, s);
|
||||
s=GWEN_DB_GetCharValue(dbPost, "notes", 0, NULL);
|
||||
AQH_User_SetNotes(u, s);
|
||||
s=GWEN_DB_GetCharValue(dbPost, "status", 0, NULL);
|
||||
state=(s && *s)?AQH_UserState_fromString(s):AQH_UserState_Unknown;
|
||||
if (state!=AQH_UserState_Unknown)
|
||||
AQH_User_SetState(u, state);
|
||||
|
||||
_readAllModRolesForUserFromForm(m, dbPost, u);
|
||||
|
||||
rv=AQH_Service_SaveUser(sv, u);
|
||||
if (rv<0) {
|
||||
GBAS(dbuf, "<h2>Error</h2><p>Error saving user</p>");
|
||||
DBG_ERROR(NULL, "Could not save user \"%s\"", sAlias);
|
||||
AQH_User_free(u);
|
||||
return;
|
||||
}
|
||||
DBG_ERROR(NULL, "User \"%s\" saved", sAlias);
|
||||
AQH_User_free(u);
|
||||
AQCGI_Request_AddResponseHeaderData(rq, "Location: index.html");
|
||||
AQCGI_Request_SetResponseCode(rq, 303);
|
||||
AQCGI_Request_SetResponseText(rq, "See other");
|
||||
}
|
||||
else {
|
||||
DBG_ERROR(NULL, "Could not load user \"%s\"", sAlias?sAlias:"<no name>");
|
||||
GBAS(dbuf, "<p>Error loading user.</p>\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _handleRqAddUserGet(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
DBG_ERROR(NULL, "AddUser");
|
||||
_writeEditUserForm(m, NULL, NULL, "adduser.html", "Add", dbuf);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _handleRqAddUserPost(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
AQH_SERVICE *sv;
|
||||
GWEN_DB_NODE *dbPost;
|
||||
const char *sAlias;
|
||||
|
||||
sv=AQH_ModService_GetService(m);
|
||||
dbPost=AQCGI_Request_GetDbPostBody(rq);
|
||||
sAlias=dbPost?GWEN_DB_GetCharValue(dbPost, "alias", 0, NULL):NULL;
|
||||
// TODO: check alias validity
|
||||
if (sAlias) {
|
||||
AQH_USER *u;
|
||||
const char *s;
|
||||
int state;
|
||||
int rv;
|
||||
uint32_t userId;
|
||||
AQH_USER_LIST *userList;
|
||||
|
||||
u=AQH_User_new();
|
||||
userList=AQH_ModService_LoadRawUsers(m);
|
||||
userId=_getHighestUserId(userList)+1;
|
||||
AQH_User_SetId(u, userId);
|
||||
AQH_User_SetAlias(u, sAlias);
|
||||
s=GWEN_DB_GetCharValue(dbPost, "name", 0, NULL);
|
||||
AQH_User_SetName(u, s);
|
||||
s=GWEN_DB_GetCharValue(dbPost, "email", 0, NULL);
|
||||
AQH_User_SetEmail(u, s);
|
||||
s=GWEN_DB_GetCharValue(dbPost, "notes", 0, NULL);
|
||||
AQH_User_SetNotes(u, s);
|
||||
s=GWEN_DB_GetCharValue(dbPost, "status", 0, NULL);
|
||||
state=(s && *s)?AQH_UserState_fromString(s):AQH_UserState_Unknown;
|
||||
if (state!=AQH_UserState_Unknown)
|
||||
AQH_User_SetState(u, state);
|
||||
|
||||
rv=AQH_Service_AddUser(sv, u);
|
||||
if (rv<0) {
|
||||
GBAS(dbuf, "<h2>Error</h2><p>Error saving user</p>");
|
||||
DBG_ERROR(NULL, "Could not save user \"%s\" (%d)", sAlias, rv);
|
||||
AQH_User_free(u);
|
||||
AQH_User_List_free(userList);
|
||||
return;
|
||||
}
|
||||
DBG_ERROR(NULL, "User \"%s\" saved", sAlias);
|
||||
AQH_User_free(u);
|
||||
AQCGI_Request_AddResponseHeaderData(rq, "Location: index.html");
|
||||
AQCGI_Request_SetResponseCode(rq, 303);
|
||||
AQCGI_Request_SetResponseText(rq, "See other");
|
||||
AQH_User_List_free(userList);
|
||||
}
|
||||
else {
|
||||
DBG_ERROR(NULL, "Missing alias");
|
||||
GBAS(dbuf, "<p>Missing alias.</p>\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _getHighestUserId(const AQH_USER_LIST *userList)
|
||||
{
|
||||
int id=0;
|
||||
|
||||
if (userList) {
|
||||
const AQH_USER *user;
|
||||
|
||||
user=AQH_User_List_First(userList);
|
||||
while(user) {
|
||||
int uid;
|
||||
|
||||
uid=AQH_User_GetId(user);
|
||||
id=(uid>id)?uid:id;
|
||||
user=AQH_User_List_Next(user);
|
||||
}
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _modulePermsHasRole(const AQH_MODULE_PERMS *modPerms, uint8_t rid)
|
||||
{
|
||||
if (modPerms) {
|
||||
int arraySize;
|
||||
int i;
|
||||
|
||||
arraySize=AQH_ModulePerms_GetRoleArrayArraySize();
|
||||
for(i=0; i<arraySize; i++) {
|
||||
if (AQH_ModulePerms_GetRoleArrayAt(modPerms, i)==rid)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void _writeEditUserForm(AQH_MODULE *m,
|
||||
const AQH_USER *u,
|
||||
const char *sAlias,
|
||||
const char *sUrl,
|
||||
const char *sSubmitText,
|
||||
GWEN_BUFFER *dbuf)
|
||||
{
|
||||
AQH_MODULE_LIST *moduleList;
|
||||
|
||||
/* write user info */
|
||||
GBAS(dbuf, "<h2>User Info</h2>\n");
|
||||
GBAA(dbuf,
|
||||
"<form action=\"%s\" method=\"post\">\n"
|
||||
"<table class=\"formtable\">\n",
|
||||
sUrl?sUrl:"");
|
||||
_addLabelAndInputToFormTableH("Alias", "alias", sAlias, "required", dbuf);
|
||||
_addLabelAndInputToFormTableH("Name", "name", u?AQH_User_GetName(u):NULL, NULL, dbuf);
|
||||
_addLabelAndInputToFormTableH("Email", "email", u?AQH_User_GetEmail(u):NULL, NULL, dbuf);
|
||||
_addLabelAndInputToFormTableH("Notes", "notes", u?AQH_User_GetNotes(u):NULL, NULL, dbuf);
|
||||
_addUserStateLabelAndSelectionToFormTableH("Status", "status", u?AQH_User_GetState(u):AQH_UserState_Unknown, dbuf);
|
||||
|
||||
GBAS(dbuf, "</table>\n");
|
||||
|
||||
/* module permissions */
|
||||
GBAS(dbuf, "<h2>Module Roles</h2>\n");
|
||||
GBAS(dbuf,
|
||||
"<table class=\"datatable\">\n"
|
||||
"<thead>"
|
||||
"<tr><th>Module</th><th>Roles</th></tr>\n"
|
||||
"</thead>\n"
|
||||
"<tbody>\n");
|
||||
moduleList=AQH_ModService_LoadRawModules(m);
|
||||
if (moduleList) {
|
||||
const AQH_MODULE_PERMS_LIST *modPermsList;
|
||||
const AQH_MODULE *currentMod;
|
||||
|
||||
modPermsList=u?AQH_User_GetModulePermList(u):NULL;
|
||||
currentMod=AQH_Module_List_First(moduleList);
|
||||
while(currentMod) {
|
||||
const char *sModName;
|
||||
const AQH_MODULE_PERMS *modPerms;
|
||||
|
||||
sModName=AQH_Module_GetName(currentMod);
|
||||
GBAA(dbuf, "<tr><td>%s</td><td>", sModName);
|
||||
|
||||
modPerms=modPermsList?AQH_ModulePerms_List_GetByModuleId(modPermsList, sModName):NULL;
|
||||
_writeUserModRolesToForm(AQH_Module_GetRoleList(currentMod), modPerms, sModName, dbuf);
|
||||
GBAS(dbuf, "</td></tr>\n");
|
||||
GBAS(dbuf, "<td>");
|
||||
|
||||
currentMod=AQH_Module_List_Next(currentMod);
|
||||
} /* while */
|
||||
AQH_Module_List_free(moduleList);
|
||||
}
|
||||
GBAS(dbuf,
|
||||
"</tbody>\n"
|
||||
"</table>\n");
|
||||
|
||||
|
||||
GBAA(dbuf, "<input type=\"hidden\" name=\"alias\" value=\"%s\">\n", sAlias?sAlias:"");
|
||||
GBAA(dbuf, "<input type=\"submit\" value=\"%s\">\n</form>\n\n", sSubmitText?sSubmitText:"Save");
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _readAllModRolesForUserFromForm(AQH_MODULE *m, GWEN_DB_NODE *dbPost, AQH_USER *u)
|
||||
{
|
||||
AQH_MODULE_LIST *moduleList;
|
||||
|
||||
moduleList=AQH_ModService_LoadRawModules(m);
|
||||
if (moduleList) {
|
||||
AQH_MODULE_PERMS_LIST *permsList;
|
||||
const AQH_MODULE *module;
|
||||
|
||||
permsList=AQH_User_GetModulePermList(u);
|
||||
if (permsList==NULL) {
|
||||
DBG_ERROR(NULL, "Creating module perms list for user");
|
||||
permsList=AQH_ModulePerms_List_new();
|
||||
AQH_User_SetModulePermList(u, permsList);
|
||||
}
|
||||
|
||||
module=AQH_Module_List_First(moduleList);
|
||||
while(module) {
|
||||
const char *sModName;
|
||||
const AQH_ROLE_LIST *roleList;
|
||||
|
||||
sModName=AQH_Module_GetName(module);
|
||||
roleList=AQH_Module_GetRoleList(module);
|
||||
if (sModName && *sModName && roleList) {
|
||||
AQH_MODULE_PERMS *modPerms;
|
||||
|
||||
modPerms=AQH_ModulePerms_List_GetByModuleId(permsList, sModName);
|
||||
if (modPerms==NULL) {
|
||||
modPerms=AQH_ModulePerms_new();
|
||||
AQH_ModulePerms_SetModuleId(modPerms, sModName);
|
||||
AQH_ModulePerms_List_Add(modPerms, permsList);
|
||||
}
|
||||
_readModRolesFromForm(dbPost, roleList, sModName, modPerms);
|
||||
}
|
||||
module=AQH_Module_List_Next(module);
|
||||
}
|
||||
|
||||
AQH_Module_List_free(moduleList);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _writeUserModRolesToForm(const AQH_ROLE_LIST *roleList, const AQH_MODULE_PERMS *modPerms, const char *sModName, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
if (roleList) {
|
||||
const AQH_ROLE *role;
|
||||
|
||||
role=AQH_Role_List_First(roleList);
|
||||
while(role) {
|
||||
const char *sRoleName;
|
||||
uint8_t roleId;
|
||||
|
||||
roleId=AQH_Role_GetId(role);
|
||||
sRoleName=AQH_Role_GetName(role);
|
||||
if (sRoleName && *sRoleName) {
|
||||
int isChecked;
|
||||
|
||||
isChecked=(modPerms && _modulePermsHasRole(modPerms, roleId));
|
||||
if (sModName && *sModName) {
|
||||
GBAA(dbuf, "<input type=\"checkbox\" name=\"%s:%s\" %s>", sModName, sRoleName, isChecked?"checked":"");
|
||||
GBAA(dbuf, "<label for=\"%s:%s\">%s</label>", sModName, sRoleName, sRoleName);
|
||||
}
|
||||
else {
|
||||
GBAA(dbuf, "<input type=\"checkbox\" name=\"%s\" %s>", sRoleName, isChecked?"checked":"");
|
||||
GBAA(dbuf, "<label for=\"%s\">%s</label>", sRoleName, sRoleName);
|
||||
}
|
||||
}
|
||||
role=AQH_Role_List_Next(role);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _readModRolesFromForm(GWEN_DB_NODE *dbPost,
|
||||
const AQH_ROLE_LIST *roleList,
|
||||
const char *sPrefix,
|
||||
AQH_MODULE_PERMS *modPerms)
|
||||
{
|
||||
AQH_ModulePerms_PresetRoleArray(modPerms, 0);
|
||||
if (roleList) {
|
||||
GWEN_BUFFER *tbuf;
|
||||
uint32_t pos;
|
||||
const AQH_ROLE *role;
|
||||
int nextRolePos=0;
|
||||
|
||||
tbuf=GWEN_Buffer_new(0, 256, 0, 1);
|
||||
if (sPrefix && *sPrefix)
|
||||
GBAA(tbuf, "%s:", sPrefix);
|
||||
pos=GWEN_Buffer_GetPos(tbuf);
|
||||
|
||||
role=AQH_Role_List_First(roleList);
|
||||
while(role) {
|
||||
const char *roleName;
|
||||
|
||||
roleName=AQH_Role_GetName(role);
|
||||
if (roleName && *roleName) {
|
||||
const char *s;
|
||||
|
||||
GBAS(tbuf, roleName);
|
||||
s=GWEN_DB_GetCharValue(dbPost, GWEN_Buffer_GetStart(tbuf), 0, NULL);
|
||||
if (s && *s) {
|
||||
if (nextRolePos<AQH_ModulePerms_GetRoleArrayArraySize())
|
||||
AQH_ModulePerms_SetRoleArrayAt(modPerms, nextRolePos++, AQH_Role_GetId(role));
|
||||
}
|
||||
GWEN_Buffer_Crop(tbuf, 0, pos);
|
||||
}
|
||||
|
||||
role=AQH_Role_List_Next(role);
|
||||
} /* while */
|
||||
GWEN_Buffer_free(tbuf);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void _addUserStateLabelAndSelectionToFormTableH(const char *sTitle, const char *sName, int st, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
int i;
|
||||
|
||||
GBAA(dbuf, "<tr><td><label for=\"%s\">%s:</label></td>", sName?sName:"", sTitle?sTitle:"");
|
||||
GBAA(dbuf, "<td><select name=\"%s\">", sName?sName:"");
|
||||
for(i=AQH_UserState_Unknown; i<=AQH_UserState_Active; i++) {
|
||||
const char *s;
|
||||
|
||||
s=AQH_UserState_toString(i);
|
||||
GBAA(dbuf, "<option value=\"%s\" %s>%s</option>", s, (i==st)?"selected":"", s);
|
||||
}
|
||||
GBAS(dbuf, "</select></td></tr>");
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _addLabelAndInputToFormTableH(const char *sTitle, const char *sName, const char *sValue, const char *sExtra, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
GBAS(dbuf, "<tr>");
|
||||
GBAA(dbuf, "<td><label for=\"%s:\">%s</label></td>", sName?sName:"", sTitle?sTitle:"");
|
||||
GBAA(dbuf, "<td><input type=\"text\" name=\"%s\"", sName?sName:"");
|
||||
if (sValue && *sValue)
|
||||
GBAA(dbuf, " value=\"%s\"", sValue);
|
||||
if (sExtra && *sExtra)
|
||||
GBAA(dbuf, " %s", sExtra);
|
||||
GBAS(dbuf, "></td>");
|
||||
GBAS(dbuf, "</tr>\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
35
apps/aqhome-cgi/modules/common/musers.h
Normal file
35
apps/aqhome-cgi/modules/common/musers.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef AQHOME_CGI_MUSERS_H
|
||||
#define AQHOME_CGI_MUSERS_H
|
||||
|
||||
#include <aqhome-cgi/modules/common/mservice.h>
|
||||
|
||||
#include <aqcgi/request.h>
|
||||
|
||||
#include <gwenhywfar/buffer.h>
|
||||
|
||||
|
||||
|
||||
#define AQH_MODADMUSERS_PERMS_USERSREAD 0x001
|
||||
#define AQH_MODADMUSERS_PERMS_USERSWRITE 0x002
|
||||
#define AQH_MODADMUSERS_PERMS_USERSADD 0x004
|
||||
#define AQH_MODADMUSERS_PERMS_USERSDEL 0x008
|
||||
|
||||
|
||||
|
||||
void AQH_ModAdmUsers_Extend(AQH_MODULE *m, AQH_SERVICE *sv, const char *baseFolder);
|
||||
|
||||
int AQH_ModAdmUsers_Create(AQH_SERVICE *sv);
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
99
apps/aqhome-cgi/modules/devices/0BUILD
Normal file
99
apps/aqhome-cgi/modules/devices/0BUILD
Normal file
@@ -0,0 +1,99 @@
|
||||
<?xml?>
|
||||
|
||||
<gwbuild>
|
||||
|
||||
<target type="ConvenienceLibrary" name="aqhcgi_mdevices" >
|
||||
|
||||
<includes type="c" >
|
||||
$(gwenhywfar_cflags)
|
||||
$(aqcgi_cflags)
|
||||
$(aqdiagram_cflags)
|
||||
-I$(topsrcdir)
|
||||
-I$(topbuilddir)
|
||||
-I$(topsrcdir)/apps
|
||||
-I$(topbuilddir)/apps
|
||||
-I$(builddir)
|
||||
-I$(srcdir)
|
||||
</includes>
|
||||
|
||||
<includes type="tm2" >
|
||||
--include=$(builddir)
|
||||
--include=$(srcdir)
|
||||
</includes>
|
||||
|
||||
|
||||
<define name="not_BUILDING_AQHOME" />
|
||||
|
||||
<setVar name="local/cflags">$(visibility_cflags)</setVar>
|
||||
|
||||
|
||||
<setVar name="tm2flags-INACTIVE" >
|
||||
--api=AQHOME_API
|
||||
</setVar>
|
||||
|
||||
<setVar name="local/typefiles" >
|
||||
</setVar>
|
||||
|
||||
<setVar name="local/built_sources" >
|
||||
</setVar>
|
||||
|
||||
<setVar name="local/built_headers_pub">
|
||||
</setVar>
|
||||
|
||||
|
||||
<setVar name="local/built_headers_priv" >
|
||||
</setVar>
|
||||
|
||||
|
||||
<headers dist="false" install="$(pkgincludedir)/service" >
|
||||
$(local/built_headers_pub)
|
||||
</headers>
|
||||
|
||||
|
||||
<headers dist="true" install="$(pkgincludedir)/service" >
|
||||
mdevices.h
|
||||
mdevices_init.h
|
||||
mdevices_index.h
|
||||
mdevices_valuestable.h
|
||||
mdevices_valuesgraph.h
|
||||
mdevices_value.h
|
||||
mdevices_setdata.h
|
||||
mdevices_vgraph.h
|
||||
mdevices_device.h
|
||||
mdevices_setdevice.h
|
||||
</headers>
|
||||
|
||||
|
||||
<headers dist="true" >
|
||||
</headers>
|
||||
|
||||
|
||||
<sources>
|
||||
$(local/typefiles)
|
||||
|
||||
mdevices.c
|
||||
mdevices_init.c
|
||||
mdevices_index.c
|
||||
mdevices_valuestable.c
|
||||
mdevices_valuesgraph.c
|
||||
mdevices_value.c
|
||||
mdevices_setdata.c
|
||||
mdevices_vgraph.c
|
||||
mdevices_device.c
|
||||
mdevices_setdevice.c
|
||||
</sources>
|
||||
|
||||
|
||||
<extradist>
|
||||
</extradist>
|
||||
|
||||
|
||||
<useTargets>
|
||||
</useTargets>
|
||||
|
||||
<subdirs>
|
||||
</subdirs>
|
||||
|
||||
</target>
|
||||
|
||||
</gwbuild>
|
||||
395
apps/aqhome-cgi/modules/devices/mdevices.c
Normal file
395
apps/aqhome-cgi/modules/devices/mdevices.c
Normal file
@@ -0,0 +1,395 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "./mdevices.h"
|
||||
|
||||
#include "aqhome-cgi/modules/devices/mdevices_index.h"
|
||||
#include "aqhome-cgi/modules/devices/mdevices_valuestable.h"
|
||||
#include "aqhome-cgi/modules/devices/mdevices_valuesgraph.h"
|
||||
#include "aqhome-cgi/modules/devices/mdevices_value.h"
|
||||
#include "aqhome-cgi/modules/devices/mdevices_setdata.h"
|
||||
#include "aqhome-cgi/modules/devices/mdevices_vgraph.h"
|
||||
#include "aqhome-cgi/modules/devices/mdevices_device.h"
|
||||
#include "aqhome-cgi/modules/devices/mdevices_setdevice.h"
|
||||
#include "aqhome-cgi/service/module.h"
|
||||
#include "aqhome-cgi/modules/mdataclient.h"
|
||||
|
||||
#include <gwenhywfar/debug.h>
|
||||
#include <gwenhywfar/timestamp.h>
|
||||
#include <gwenhywfar/text.h>
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* defs and enums
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#define GBAS GWEN_Buffer_AppendString
|
||||
#define GBAA GWEN_Buffer_AppendArgs
|
||||
|
||||
#define P_DEVICEREAD AQH_MODDEVICES_PERMS_DEVICEREAD
|
||||
#define P_DEVICEWRITE AQH_MODDEVICES_PERMS_DEVICEWRITE
|
||||
#define P_VALUEREAD AQH_MODDEVICES_PERMS_VALUEREAD
|
||||
#define P_VALUEWRITE AQH_MODDEVICES_PERMS_VALUEWRITE
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* forward declarations
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static AQH_MODULE *_loadSubModule(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, const char *sModuleName);
|
||||
static int _handleRequest(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, const char *sLastPathElem);
|
||||
|
||||
static void _handleRqIndexGet(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf);
|
||||
static void _handleRqValuesTableGet(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf);
|
||||
static void _handleRqValuesGraphGet(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf);
|
||||
static void _handleRqValueGet(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf);
|
||||
static void _handleRqSetDataPost(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf);
|
||||
static void _handleRqGraphGet(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf);
|
||||
static void _handleRqDeviceGet(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf);
|
||||
static void _handleRqDevicePost(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf);
|
||||
|
||||
static void _addValueActionToForm(const AQH_VALUE *value, GWEN_BUFFER *dbuf);
|
||||
static void _addLastValueToForm(AQH_DATACLIENT *dc, const AQH_VALUE *value, GWEN_BUFFER *dbuf);
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* vars
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static AQH_MODSERVICE_HANDLER_ENTRY _requestTable[]={
|
||||
{"index.html", AQCGI_REQUEST_METHOD_GET, P_DEVICEREAD, _handleRqIndexGet},
|
||||
{"device.html", AQCGI_REQUEST_METHOD_GET, P_DEVICEREAD | P_VALUEREAD, _handleRqDeviceGet},
|
||||
{"device.html", AQCGI_REQUEST_METHOD_POST, P_DEVICEWRITE, _handleRqDevicePost},
|
||||
{"vtable.html", AQCGI_REQUEST_METHOD_GET, P_DEVICEREAD | P_VALUEREAD, _handleRqValuesTableGet},
|
||||
{"vgraph.html", AQCGI_REQUEST_METHOD_GET, P_DEVICEREAD | P_VALUEREAD, _handleRqValuesGraphGet},
|
||||
{"value.html", AQCGI_REQUEST_METHOD_GET, P_DEVICEREAD | P_VALUEREAD, _handleRqValueGet},
|
||||
{"setdata.html", AQCGI_REQUEST_METHOD_POST, P_VALUEWRITE, _handleRqSetDataPost},
|
||||
{"graph.html", AQCGI_REQUEST_METHOD_GET, P_DEVICEREAD | P_VALUEREAD, _handleRqGraphGet},
|
||||
{NULL, 0, 0, NULL}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* code
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void AQH_ModDevices_Extend(AQH_MODULE *m, AQH_SERVICE *sv, const char *baseFolder)
|
||||
{
|
||||
AQH_ModService_Extend(m, sv, baseFolder);
|
||||
AQH_ModService_SetHandleRequestFn(m, _handleRequest);
|
||||
AQH_ModService_SetLoadSubModuleFn(m, _loadSubModule);
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQH_MODULE *_loadSubModule(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, const char *sModuleName)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _handleRequest(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, const char *sLastPathElem)
|
||||
{
|
||||
AQH_ModService_HandleRequestWithTable(m, rq, session, sLastPathElem, _requestTable);
|
||||
return AQCGI_SendResponse(rq);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _handleRqIndexGet(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
AQH_ModDataClient_HandleRequest(m, rq, session, AQH_ModDevices_RunIndex, dbuf);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _handleRqValuesTableGet(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
AQH_ModDataClient_HandleRequest(m, rq, session, AQH_ModDevices_RunValuesAsTable, dbuf);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _handleRqValuesGraphGet(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
AQH_ModDataClient_HandleRequest(m, rq, session, AQH_ModDevices_RunValuesAsGraph, dbuf);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _handleRqValueGet(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
AQH_ModDataClient_HandleRequest(m, rq, session, AQH_ModDevices_RunValue, dbuf);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _handleRqSetDataPost(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
AQH_ModDataClient_HandleRequest(m, rq, session, AQH_ModDevices_RunSetData, dbuf);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _handleRqGraphGet(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
AQH_ModDataClient_HandleRequest(m, rq, session, AQH_ModDevices_RunGraphValue, dbuf);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _handleRqDeviceGet(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
AQH_ModDataClient_HandleRequest(m, rq, session, AQH_ModDevices_RunDevice, dbuf);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _handleRqDevicePost(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
AQH_ModDataClient_HandleRequest(m, rq, session, AQH_ModDevices_RunSetDevice, dbuf);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
uint32_t AQH_ModDevices_ColorFromHexString(const char *s)
|
||||
{
|
||||
uint32_t colorIn=0;
|
||||
|
||||
while(*s && *s<33)
|
||||
s++;
|
||||
if (*s=='#')
|
||||
s++;
|
||||
while(*s) {
|
||||
uint c;
|
||||
|
||||
c=(*s)-'0';
|
||||
if (c>9)
|
||||
c-=7;
|
||||
colorIn<<=4;
|
||||
colorIn|=c & 0xf;
|
||||
s++;
|
||||
}
|
||||
|
||||
/* hex 00RRGGBB -> GGRRWWBB */
|
||||
//return _htmlColorToValueRGBW(colorIn);
|
||||
return colorIn;
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint32_t AQH_ModDevices_HtmlColorToValueRGBW(uint32_t colorIn)
|
||||
{
|
||||
uint32_t colorOut;
|
||||
/* hex 00RRGGBB -> GGRRWWBB */
|
||||
/* RGBW GGRRWWBB GGRRWWBB GGRRWWBB */
|
||||
/* html 00RRGGBB 00RRGGBB 00RRGGBB*/
|
||||
colorOut=(colorIn & 0x00ff0000) | ((colorIn<<16) & 0xff000000) | (colorIn & 0x000000ff);
|
||||
return colorOut;
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint32_t AQH_ModDevices_RgbwToHtmlColor(uint32_t colorIn)
|
||||
{
|
||||
uint32_t colorOut;
|
||||
/* RGBW GGRRWWBB GGRRWWBB GGRRWWBB */
|
||||
/* hex 00RRGGBB 00RRGGBB 00RRGGBB*/
|
||||
colorOut=(colorIn & 0x00ff0000) | ( (colorIn>>16) & 0x0000ff00) | (colorIn & 0x000000ff);
|
||||
return colorOut;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _addValueActionToForm(const AQH_VALUE *value, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
const char *sValueName;
|
||||
|
||||
sValueName=AQH_Value_GetName(value);
|
||||
switch(AQH_Value_GetModality(value)) {
|
||||
case AQH_ValueModality_RGBW:
|
||||
GBAA(dbuf, "<input type=\"color\" name=\"%s\" value=\"refresh\"/>", sValueName);
|
||||
break;
|
||||
case AQH_ValueModality_OnOff:
|
||||
GBAA(dbuf,
|
||||
"<select name=\"%s\">"
|
||||
"<option value=\"unchanged\">unchanged</option>"
|
||||
"<option value=\"off\">off</option>"
|
||||
"<option value=\"on\">on</option>"
|
||||
"</select>",
|
||||
sValueName);
|
||||
break;
|
||||
case AQH_ValueModality_OnOffAuto:
|
||||
GBAA(dbuf,
|
||||
"<select name=\"%s\">"
|
||||
"<option value=\"unchanged\">unchanged</option>"
|
||||
"<option value=\"off\">off</option>"
|
||||
"<option value=\"on\">on</option>"
|
||||
"<option value=\"auto\">auto</option>"
|
||||
"</select>",
|
||||
sValueName);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _addLastValueToForm(AQH_DATACLIENT *dc, const AQH_VALUE *value, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
const char *sValueSystemName;
|
||||
const char *sValueName;
|
||||
uint64_t dataPoints[2];
|
||||
uint64_t recvdNum;
|
||||
// uint64_t timestamp;
|
||||
union {double f; uint64_t i;} u;
|
||||
int intVal;
|
||||
|
||||
sValueSystemName=AQH_Value_GetNameForSystem(value);
|
||||
sValueName=AQH_Value_GetName(value);
|
||||
recvdNum=AQH_DataClient_GetLastData(dc, sValueSystemName, &dataPoints[0], 1);
|
||||
if (recvdNum>0) {
|
||||
// timestamp=dataPoints[0];
|
||||
u.i=dataPoints[1];
|
||||
intVal=(int) u.f;
|
||||
}
|
||||
else {
|
||||
u.i=0;
|
||||
intVal=-1;
|
||||
}
|
||||
|
||||
if (AQH_Value_GetValueType(value)==AQH_ValueType_Actor) {
|
||||
DBG_ERROR(NULL, "Adding actor");
|
||||
switch(AQH_Value_GetModality(value)) {
|
||||
case AQH_ValueModality_RGBW:
|
||||
DBG_ERROR(NULL, "Color: %.f RGBW=%08x HTML=%08x, RGBW2=%08x",
|
||||
u.f,
|
||||
(uint32_t) (u.f),
|
||||
AQH_ModDevices_RgbwToHtmlColor(u.f),
|
||||
AQH_ModDevices_HtmlColorToValueRGBW(AQH_ModDevices_RgbwToHtmlColor(u.f)));
|
||||
#if 1
|
||||
GBAA(dbuf, "<input type=\"text\" name=\"%s\" value=\"#%08x\"/>", sValueName, (uint32_t) (u.f));
|
||||
#else
|
||||
GBAA(dbuf, "<input type=\"color\" name=\"%s\" value=\"#%08x\"/>#%08x (#%08x)",
|
||||
sValueName,
|
||||
_rgbwToHtmlColor((unsigned int) (u.f)),
|
||||
_rgbwToHtmlColor((unsigned int) (u.f)),
|
||||
(uint32_t) (u.f));
|
||||
#endif
|
||||
break;
|
||||
case AQH_ValueModality_OnOff:
|
||||
GBAA(dbuf, "<select name=\"%s\">" "<option value=\"unchanged\" >unchanged</option>", sValueName);
|
||||
GBAA(dbuf, "<option value=\"off\" %s>off</option>", (intVal==0)?"selected":"");
|
||||
GBAA(dbuf, "<option value=\"on\" %s>on</option>", (intVal==1)?"selected":"");
|
||||
GBAS(dbuf, "</select>");
|
||||
break;
|
||||
case AQH_ValueModality_OnOffAuto:
|
||||
GBAA(dbuf, "<select name=\"%s\">" "<option value=\"unchanged\" >unchanged</option>", sValueName);
|
||||
GBAA(dbuf, "<option value=\"off\" %s>off</option>", (intVal==0)?"selected":"");
|
||||
GBAA(dbuf, "<option value=\"on\" %s>on</option>", (intVal==1)?"selected":"");
|
||||
GBAA(dbuf, "<option value=\"auto\" %s>auto</option>", (intVal==2)?"selected":"");
|
||||
GBAS(dbuf, "</select>");
|
||||
break;
|
||||
default:
|
||||
// GBAA(dbuf, "<input type=\"text\" name=\"%s\" value=\"%.2f\"/>", sValueName, u.f);
|
||||
GBAA(dbuf, "%.2f", u.f);
|
||||
break;
|
||||
} /* switch */
|
||||
} /* if actor */
|
||||
else {
|
||||
DBG_ERROR(NULL, "Adding sensor (%s=%.2f)", sValueName, u.f);
|
||||
GBAA(dbuf, "%.2f", u.f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQH_VALUE *AQH_ModDevices_GetValueForDevice(AQH_DATACLIENT *dc, const char *sDeviceName, const char *sValueName)
|
||||
{
|
||||
AQH_VALUE_LIST *valueList;
|
||||
|
||||
valueList=AQH_DataClient_GetValues(dc, sDeviceName, 0);
|
||||
if (valueList) {
|
||||
AQH_VALUE *value;
|
||||
|
||||
value=AQH_Value_List_First(valueList);
|
||||
while(value) {
|
||||
const char *s;
|
||||
|
||||
s=AQH_Value_GetName(value);
|
||||
if (s && *s && strcasecmp(s, sValueName)==0) {
|
||||
break;
|
||||
}
|
||||
value=AQH_Value_List_Next(value);
|
||||
}
|
||||
|
||||
if (value) {
|
||||
AQH_Value_List_Del(value);
|
||||
AQH_Value_List_free(valueList);
|
||||
return value;
|
||||
}
|
||||
|
||||
AQH_Value_List_free(valueList);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQH_DEVICE *AQH_ModDevices_GetDevice(AQH_DATACLIENT *dc, const char *sDeviceName)
|
||||
{
|
||||
AQH_DEVICE_LIST *deviceList;
|
||||
|
||||
deviceList=AQH_DataClient_GetDevices(dc, sDeviceName);
|
||||
if (deviceList) {
|
||||
AQH_DEVICE *device;
|
||||
|
||||
device=AQH_Device_List_First(deviceList);
|
||||
while(device) {
|
||||
const char *s;
|
||||
|
||||
s=AQH_Device_GetNameForSystem(device);
|
||||
if (s && *s && 0==strcasecmp(s, sDeviceName)) {
|
||||
AQH_Device_List_Del(device);
|
||||
AQH_Device_List_free(deviceList);
|
||||
return device;
|
||||
}
|
||||
device=AQH_Device_List_Next(device);
|
||||
}
|
||||
AQH_Device_List_free(deviceList);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
55
apps/aqhome-cgi/modules/devices/mdevices.h
Normal file
55
apps/aqhome-cgi/modules/devices/mdevices.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef AQHOME_CGI_MODULES_DEVICES_H
|
||||
#define AQHOME_CGI_MODULES_DEVICES_H
|
||||
|
||||
|
||||
#include "aqhome-cgi/modules/mdataclient.h"
|
||||
|
||||
#include "aqhome/aqhome.h"
|
||||
#include "aqhome/dataclient/client.h"
|
||||
|
||||
#include <aqcgi/request.h>
|
||||
|
||||
#include <gwenhywfar/buffer.h>
|
||||
|
||||
|
||||
#define AQH_MODDEVICES_PERMS_DEVICEREAD 0x001
|
||||
#define AQH_MODDEVICES_PERMS_DEVICEWRITE 0x002
|
||||
#define AQH_MODDEVICES_PERMS_DEVICEADD 0x004
|
||||
#define AQH_MODDEVICES_PERMS_DEVICEDEL 0x008
|
||||
|
||||
#define AQH_MODDEVICES_PERMS_VALUEREAD 0x010
|
||||
#define AQH_MODDEVICES_PERMS_VALUEWRITE 0x020
|
||||
#define AQH_MODDEVICES_PERMS_VALUEADD 0x040
|
||||
#define AQH_MODDEVICES_PERMS_VALUEDEL 0x080
|
||||
#define AQH_MODDEVICES_PERMS_VALUESET 0x100
|
||||
|
||||
|
||||
#define AQH_MODDEVICES_GRAPH_WIDTH 640
|
||||
#define AQH_MODDEVICES_GRAPH_HEIGHT 480
|
||||
|
||||
|
||||
|
||||
void AQH_ModDevices_Extend(AQH_MODULE *m, AQH_SERVICE *sv, const char *baseFolder);
|
||||
int AQH_ModDevices_Create(AQH_SERVICE *sv);
|
||||
|
||||
|
||||
uint32_t AQH_ModDevices_ColorFromHexString(const char *s);
|
||||
uint32_t AQH_ModDevices_HtmlColorToValueRGBW(uint32_t colorIn);
|
||||
uint32_t AQH_ModDevices_RgbwToHtmlColor(uint32_t colorIn);
|
||||
|
||||
AQH_VALUE *AQH_ModDevices_GetValueForDevice(AQH_DATACLIENT *dc, const char *sDeviceName, const char *sValueName);
|
||||
AQH_DEVICE *AQH_ModDevices_GetDevice(AQH_DATACLIENT *dc, const char *sDeviceName);
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
131
apps/aqhome-cgi/modules/devices/mdevices_device.c
Normal file
131
apps/aqhome-cgi/modules/devices/mdevices_device.c
Normal file
@@ -0,0 +1,131 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "./mdevices_device.h"
|
||||
|
||||
#include "aqhome-cgi/service/module.h"
|
||||
#include "aqhome-cgi/modules/mdataclient.h"
|
||||
|
||||
#include <gwenhywfar/debug.h>
|
||||
#include <gwenhywfar/timestamp.h>
|
||||
#include <gwenhywfar/text.h>
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* defs and enums
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#define GBAS GWEN_Buffer_AppendString
|
||||
#define GBAA GWEN_Buffer_AppendArgs
|
||||
|
||||
#define I18N(msg) msg
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* forward declarations
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static void _runDeviceWithArgs(AQH_MODULE *m,
|
||||
AQCGI_REQUEST *rq,
|
||||
AQH_SESSION *session,
|
||||
AQH_DATACLIENT *dc,
|
||||
const char *sDeviceName,
|
||||
GWEN_BUFFER *dbuf);
|
||||
static void _mkDeviceForm(AQH_DATACLIENT *dc, const char *sDeviceName, const AQH_DEVICE *device, GWEN_BUFFER *dbuf);
|
||||
static void _addFieldToForm(const char *sFieldTitle, const char *sFieldName, const char *sFieldContent, GWEN_BUFFER *dbuf);
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* code
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void AQH_ModDevices_RunDevice(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DATACLIENT *dc, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
GWEN_DB_NODE *dbQuery;
|
||||
const char *sDeviceName;
|
||||
|
||||
DBG_ERROR(NULL, "RunValue");
|
||||
dbQuery=AQCGI_Request_GetDbQuery(rq);
|
||||
sDeviceName=GWEN_DB_GetCharValue(dbQuery, "device", 0, NULL);
|
||||
if (sDeviceName && *sDeviceName) {
|
||||
GWEN_BUFFER *bufDeviceName;
|
||||
|
||||
bufDeviceName=GWEN_Buffer_new(0, 64, 0, 1);
|
||||
GWEN_Text_UnescapeToBufferTolerant(sDeviceName, bufDeviceName);
|
||||
_runDeviceWithArgs(m, rq, session, dc, GWEN_Buffer_GetStart(bufDeviceName), dbuf);
|
||||
GWEN_Buffer_free(bufDeviceName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _runDeviceWithArgs(AQH_MODULE *m,
|
||||
AQCGI_REQUEST *rq,
|
||||
AQH_SESSION *session,
|
||||
AQH_DATACLIENT *dc,
|
||||
const char *sDeviceName,
|
||||
GWEN_BUFFER *dbuf)
|
||||
{
|
||||
GWEN_DB_NODE *dbQuery;
|
||||
AQH_DEVICE *device;
|
||||
|
||||
dbQuery=AQCGI_Request_GetDbQuery(rq);
|
||||
DBG_ERROR(NULL, "Device=%s", sDeviceName?sDeviceName:"<empty>");
|
||||
|
||||
GBAA(dbuf,"<h1>Device %s</h1>\n", sDeviceName);
|
||||
|
||||
device=AQH_ModDevices_GetDevice(dc, sDeviceName);
|
||||
if (device) {
|
||||
_mkDeviceForm(dc, sDeviceName, device, dbuf);
|
||||
AQH_Device_free(device);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _mkDeviceForm(AQH_DATACLIENT *dc, const char *sDeviceName, const AQH_DEVICE *device, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
const char *s;
|
||||
|
||||
GBAS(dbuf,"<form action=\"device.html\" method=\"post\">\n");
|
||||
GBAA(dbuf, "<input type=\"hidden\" name=\"device\" value=\"%s\">\n", sDeviceName);
|
||||
|
||||
GBAS(dbuf,"<table>\n");
|
||||
_addFieldToForm(I18N("Room"), "roomName", AQH_Device_GetRoomName(device), dbuf);
|
||||
_addFieldToForm(I18N("GUI Name"), "nameForGui", AQH_Device_GetNameForGui(device), dbuf);
|
||||
_addFieldToForm(I18N("Location"), "location", AQH_Device_GetLocation(device), dbuf);
|
||||
_addFieldToForm(I18N("Description"), "description", AQH_Device_GetDescription(device), dbuf);
|
||||
GBAS(dbuf,"</table>\n");
|
||||
GBAS(dbuf,"<br>\n");
|
||||
|
||||
GBAS(dbuf,"<input type=\"submit\" name=\"action\" value=\"Send\"/>");
|
||||
GBAS(dbuf, "</form>\n\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _addFieldToForm(const char *sFieldTitle, const char *sFieldName, const char *sFieldContent, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
GBAS(dbuf, "<tr>");
|
||||
GBAA(dbuf, "<td><label for=\"%s\">%s</label></td>", sFieldName, sFieldTitle);
|
||||
GBAA(dbuf, "<td><input type=\"text\" name=\"%s\" value=\"%s\"/></td>", sFieldName, sFieldContent?sFieldContent:"");
|
||||
GBAS(dbuf, "</tr>");
|
||||
}
|
||||
|
||||
|
||||
|
||||
27
apps/aqhome-cgi/modules/devices/mdevices_device.h
Normal file
27
apps/aqhome-cgi/modules/devices/mdevices_device.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef AQHOME_CGI_MDEVICES_DEVICE_H
|
||||
#define AQHOME_CGI_MDEVICES_DEVICE_H
|
||||
|
||||
|
||||
#include "aqhome-cgi/modules/devices/mdevices.h"
|
||||
|
||||
#include "aqhome/aqhome.h"
|
||||
#include "aqhome/dataclient/client.h"
|
||||
|
||||
#include <aqcgi/request.h>
|
||||
|
||||
#include <gwenhywfar/buffer.h>
|
||||
|
||||
|
||||
|
||||
void AQH_ModDevices_RunDevice(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DATACLIENT *dc, GWEN_BUFFER *dbuf);
|
||||
|
||||
|
||||
#endif
|
||||
135
apps/aqhome-cgi/modules/devices/mdevices_index.c
Normal file
135
apps/aqhome-cgi/modules/devices/mdevices_index.c
Normal file
@@ -0,0 +1,135 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "./mdevices_index.h"
|
||||
|
||||
#include "aqhome-cgi/service/module.h"
|
||||
#include "aqhome-cgi/modules/mdataclient.h"
|
||||
|
||||
#include <gwenhywfar/debug.h>
|
||||
#include <gwenhywfar/timestamp.h>
|
||||
#include <gwenhywfar/text.h>
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* defs and enums
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#define GBAS GWEN_Buffer_AppendString
|
||||
#define GBAA GWEN_Buffer_AppendArgs
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* forward declarations
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static void _addLinkForDevice(const char *page, const char *sDevice, const char *action, const char *imgName, GWEN_BUFFER *dbuf);
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* code
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void AQH_ModDevices_RunIndex(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DATACLIENT *dc, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
AQH_DEVICE_LIST *deviceList;
|
||||
AQH_DEVICE *device;
|
||||
uint32_t perms;
|
||||
|
||||
perms=AQH_ModService_GetUserPerms(m);
|
||||
|
||||
deviceList=AQH_DataClient_GetDevices(dc, NULL);
|
||||
if (deviceList==NULL) {
|
||||
DBG_ERROR(NULL, "No device received");
|
||||
GBAS(dbuf, "<p>No devices.</p>");
|
||||
return;
|
||||
}
|
||||
|
||||
GBAS(dbuf, "<h1>Devices</h1>\n");
|
||||
GBAS(dbuf,
|
||||
"<table class=\"datatable\">\n"
|
||||
"<thead>\n"
|
||||
"<tr>"
|
||||
"<th>Name For System</th>"
|
||||
"<th>Name For GUI</th>"
|
||||
"<th>Room</th>"
|
||||
"<th>Location</th>"
|
||||
"<th>Description</th>"
|
||||
"<th>Actions</th>"
|
||||
"</tr>\n"
|
||||
"</thead>\n"
|
||||
"<tbody>\n");
|
||||
|
||||
device=AQH_Device_List_First(deviceList);
|
||||
while(device) {
|
||||
const char *s;
|
||||
const char *sDevice;
|
||||
|
||||
GBAA(dbuf, "<tr>");
|
||||
/* name for system */
|
||||
sDevice=AQH_Device_GetNameForSystem(device);
|
||||
GBAA(dbuf,"<td>%s</td>", sDevice?sDevice:"");
|
||||
/* nameForGui */
|
||||
s=AQH_Device_GetNameForGui(device);
|
||||
GBAA(dbuf, "<td>%s</td>", s?s:"");
|
||||
/* room */
|
||||
s=AQH_Device_GetRoomName(device);
|
||||
GBAA(dbuf, "<td>%s</td>", s?s:"");
|
||||
/* location */
|
||||
s=AQH_Device_GetLocation(device);
|
||||
GBAA(dbuf, "<td>%s</td>", s?s:"");
|
||||
/* description */
|
||||
s=AQH_Device_GetDescription(device);
|
||||
GBAA(dbuf, "<td>%s</td>", s?s:"");
|
||||
|
||||
GBAS(dbuf, "<td>");
|
||||
if (perms & AQH_MODDEVICES_PERMS_VALUEREAD) {
|
||||
_addLinkForDevice("vtable.html", sDevice, "table view", "/pics/document-table.png", dbuf);
|
||||
_addLinkForDevice("vgraph.html", sDevice, "graph view", "/pics/graph.png", dbuf);
|
||||
}
|
||||
|
||||
if (perms & AQH_MODDEVICES_PERMS_DEVICEWRITE) {
|
||||
_addLinkForDevice("device.html", sDevice, "edit device", "/pics/edit.png", dbuf);
|
||||
}
|
||||
|
||||
GBAS(dbuf, "</td>");
|
||||
|
||||
GBAA(dbuf, "</tr>");
|
||||
device=AQH_Device_List_Next(device);
|
||||
}
|
||||
|
||||
GBAS(dbuf,
|
||||
"</tbody>\n"
|
||||
"</table>\n");
|
||||
AQH_Device_List_free(deviceList);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _addLinkForDevice(const char *page, const char *sDevice, const char *action, const char *imgName, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
GBAA(dbuf,"<a href=\"%s?device=", page);
|
||||
GWEN_Text_EscapeToBufferTolerant(sDevice, dbuf);
|
||||
GBAS(dbuf,"\">");
|
||||
GBAA(dbuf,"<img src=\"%s\" alt=\"%s\" title=\"%s\" />", imgName, action, action);
|
||||
GBAS(dbuf,"</a>");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
27
apps/aqhome-cgi/modules/devices/mdevices_index.h
Normal file
27
apps/aqhome-cgi/modules/devices/mdevices_index.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef AQHOME_CGI_MDEVICES_INDEX_H
|
||||
#define AQHOME_CGI_MDEVICES_INDEX_H
|
||||
|
||||
|
||||
#include "aqhome-cgi/modules/devices/mdevices.h"
|
||||
|
||||
#include "aqhome/aqhome.h"
|
||||
#include "aqhome/dataclient/client.h"
|
||||
|
||||
#include <aqcgi/request.h>
|
||||
|
||||
#include <gwenhywfar/buffer.h>
|
||||
|
||||
|
||||
|
||||
void AQH_ModDevices_RunIndex(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DATACLIENT *dc, GWEN_BUFFER *dbuf);
|
||||
|
||||
|
||||
#endif
|
||||
129
apps/aqhome-cgi/modules/devices/mdevices_init.c
Normal file
129
apps/aqhome-cgi/modules/devices/mdevices_init.c
Normal file
@@ -0,0 +1,129 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "./mdevices_init.h"
|
||||
|
||||
#include "aqhome-cgi/service/module.h"
|
||||
#include "aqhome-cgi/modules/mdataclient.h"
|
||||
|
||||
#include <gwenhywfar/debug.h>
|
||||
#include <gwenhywfar/timestamp.h>
|
||||
#include <gwenhywfar/text.h>
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* defs and enums
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#define GBAS GWEN_Buffer_AppendString
|
||||
#define GBAA GWEN_Buffer_AppendArgs
|
||||
|
||||
#define P_DEVICEREAD AQH_MODDEVICES_PERMS_DEVICEREAD
|
||||
#define P_VALUEREAD AQH_MODDEVICES_PERMS_VALUEREAD
|
||||
#define P_VALUEWRITE AQH_MODDEVICES_PERMS_VALUEWRITE
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* forward declarations
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static void _createPermDefList(AQH_MODULE *m);
|
||||
static void _createRoleList(AQH_MODULE *m);
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* code
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int AQH_ModDevices_Create(AQH_SERVICE *sv)
|
||||
{
|
||||
AQH_MODULE *m;
|
||||
int rv;
|
||||
|
||||
m=AQH_Module_new();
|
||||
AQH_Module_SetName(m, "devices");
|
||||
AQH_Module_SetDescr(m, "device module");
|
||||
AQH_Module_SetGuestPerms(m, 0);
|
||||
|
||||
_createPermDefList(m);
|
||||
_createRoleList(m);
|
||||
|
||||
rv=AQH_Service_AddModule(sv, m);
|
||||
if (rv<0) {
|
||||
DBG_INFO(NULL, "here (%d)", rv);
|
||||
}
|
||||
AQH_Module_free(m);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _createPermDefList(AQH_MODULE *m)
|
||||
{
|
||||
AQH_PERMDEF_LIST *permDefList;
|
||||
|
||||
permDefList=AQH_PermDef_List_new();
|
||||
|
||||
AQH_ModService_AddPermDef(permDefList, "DeviceRead", 0x001, "Read and list devices");
|
||||
AQH_ModService_AddPermDef(permDefList, "DeviceWrite", 0x002, "Modify devices");
|
||||
AQH_ModService_AddPermDef(permDefList, "DeviceAdd", 0x004, "Add devices");
|
||||
AQH_ModService_AddPermDef(permDefList, "DeviceDel", 0x008, "Remove devices");
|
||||
|
||||
AQH_ModService_AddPermDef(permDefList, "ValueRead", 0x010, "Read and list values");
|
||||
AQH_ModService_AddPermDef(permDefList, "ValueWrite", 0x020, "Modify values");
|
||||
AQH_ModService_AddPermDef(permDefList, "ValueAdd", 0x040, "Add values");
|
||||
AQH_ModService_AddPermDef(permDefList, "ValueDel", 0x080, "Remove values");
|
||||
AQH_ModService_AddPermDef(permDefList, "ValueSet", 0x100, "Set values");
|
||||
|
||||
AQH_Module_SetPermDefList(m, permDefList);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _createRoleList(AQH_MODULE *m)
|
||||
{
|
||||
AQH_ROLE_LIST *roleList;
|
||||
int id=0;
|
||||
|
||||
roleList=AQH_Role_List_new();
|
||||
AQH_ModService_AddRole(roleList, id++, "Reader",
|
||||
AQH_MODDEVICES_PERMS_DEVICEREAD |
|
||||
AQH_MODDEVICES_PERMS_VALUEREAD,
|
||||
"Read devices and values");
|
||||
AQH_ModService_AddRole(roleList, id++, "Writer",
|
||||
AQH_MODDEVICES_PERMS_DEVICEREAD |
|
||||
AQH_MODDEVICES_PERMS_DEVICEWRITE |
|
||||
AQH_MODDEVICES_PERMS_DEVICEADD |
|
||||
AQH_MODDEVICES_PERMS_DEVICEDEL |
|
||||
AQH_MODDEVICES_PERMS_VALUEREAD |
|
||||
AQH_MODDEVICES_PERMS_VALUEWRITE |
|
||||
AQH_MODDEVICES_PERMS_VALUEADD |
|
||||
AQH_MODDEVICES_PERMS_VALUEDEL |
|
||||
AQH_MODDEVICES_PERMS_VALUESET,
|
||||
"Read and write devices and values");
|
||||
AQH_ModService_AddRole(roleList, id++, "Setter",
|
||||
AQH_MODDEVICES_PERMS_DEVICEREAD |
|
||||
AQH_MODDEVICES_PERMS_VALUEREAD |
|
||||
AQH_MODDEVICES_PERMS_VALUESET,
|
||||
"Set values");
|
||||
AQH_Module_SetRoleList(m, roleList);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
27
apps/aqhome-cgi/modules/devices/mdevices_init.h
Normal file
27
apps/aqhome-cgi/modules/devices/mdevices_init.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef AQHOME_CGI_MDEVICES_INIT_H
|
||||
#define AQHOME_CGI_MDEVICES_INIT_H
|
||||
|
||||
|
||||
#include "aqhome-cgi/modules/devices/mdevices.h"
|
||||
|
||||
#include "aqhome/aqhome.h"
|
||||
#include "aqhome/dataclient/client.h"
|
||||
|
||||
#include <aqcgi/request.h>
|
||||
|
||||
#include <gwenhywfar/buffer.h>
|
||||
|
||||
|
||||
|
||||
int AQH_ModDevices_Create(AQH_SERVICE *sv);
|
||||
|
||||
|
||||
#endif
|
||||
194
apps/aqhome-cgi/modules/devices/mdevices_setdata.c
Normal file
194
apps/aqhome-cgi/modules/devices/mdevices_setdata.c
Normal file
@@ -0,0 +1,194 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "./mdevices_setdata.h"
|
||||
|
||||
#include "aqhome-cgi/service/module.h"
|
||||
#include "aqhome-cgi/modules/mdataclient.h"
|
||||
|
||||
#include <gwenhywfar/debug.h>
|
||||
#include <gwenhywfar/timestamp.h>
|
||||
#include <gwenhywfar/text.h>
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* defs and enums
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#define GBAS GWEN_Buffer_AppendString
|
||||
#define GBAA GWEN_Buffer_AppendArgs
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* forward declarations
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static void _setRgbwData(AQH_DATACLIENT *dc, const AQH_VALUE *value, const char *sValue);
|
||||
static void _setOnOffData(AQH_DATACLIENT *dc, const AQH_VALUE *value, const char *sValue);
|
||||
static void _setOnOffAutoData(AQH_DATACLIENT *dc, const AQH_VALUE *value, const char *sValue);
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* code
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void AQH_ModDevices_RunSetData(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DATACLIENT *dc, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
AQH_SERVICE *sv;
|
||||
GWEN_DB_NODE *dbPost;
|
||||
const char *sDeviceName;
|
||||
const char *sValueName;
|
||||
const AQH_VALUE *value;
|
||||
|
||||
/* sample data */
|
||||
sv=AQH_ModService_GetService(m);
|
||||
dbPost=AQCGI_Request_GetDbPostBody(rq);
|
||||
sDeviceName=dbPost?GWEN_DB_GetCharValue(dbPost, "device", 0, NULL):NULL;
|
||||
sValueName=dbPost?GWEN_DB_GetCharValue(dbPost, "value", 0, NULL):NULL;
|
||||
DBG_ERROR(NULL, "Device=[%s], value=[%s]", sDeviceName?sDeviceName:"", sValueName?sValueName:"");
|
||||
|
||||
value=AQH_ModDevices_GetValueForDevice(dc, sDeviceName, sValueName);
|
||||
if(value && AQH_Value_GetValueType(value)==AQH_ValueType_Actor) {
|
||||
const char *sValueName;
|
||||
const char *sValue;
|
||||
|
||||
sValueName=AQH_Value_GetName(value);
|
||||
sValue=GWEN_DB_GetCharValue(dbPost, sValueName, 0, NULL);
|
||||
if (sValueName && *sValueName) {
|
||||
DBG_ERROR(NULL, "Setting value %s to %s", sValueName?sValueName:"no name", sValue?sValue:"no value");
|
||||
switch(AQH_Value_GetModality(value)) {
|
||||
case AQH_ValueModality_RGBW: _setRgbwData(dc, value, sValue); break;
|
||||
case AQH_ValueModality_OnOff: _setOnOffData(dc, value, sValue); break;
|
||||
case AQH_ValueModality_OnOffAuto: _setOnOffAutoData(dc, value, sValue); break;
|
||||
default:
|
||||
break;
|
||||
} /* switch */
|
||||
} /* if (sValueName) */
|
||||
}
|
||||
|
||||
if (sDeviceName && *sDeviceName) {
|
||||
GWEN_BUFFER *pbuf;
|
||||
|
||||
pbuf=GWEN_Buffer_new(0, 256, 0, 1);
|
||||
if (sValueName && *sValueName) {
|
||||
GBAS(pbuf, "Location: /aqbt/devices/value.html?device=");
|
||||
GWEN_Text_EscapeToBuffer(sDeviceName, pbuf);
|
||||
GBAS(pbuf, "&value=");
|
||||
GWEN_Text_EscapeToBuffer(sValueName, pbuf);
|
||||
}
|
||||
else {
|
||||
GBAS(pbuf, "Location: /aqbt/devices/values.html?device=");
|
||||
GWEN_Text_EscapeToBuffer(sDeviceName, pbuf);
|
||||
}
|
||||
AQCGI_Request_AddResponseHeaderData(rq, GWEN_Buffer_GetStart(pbuf));
|
||||
GWEN_Buffer_free(pbuf);
|
||||
}
|
||||
AQCGI_Request_SetResponseCode(rq, 303);
|
||||
AQCGI_Request_SetResponseText(rq, "See other");
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _setRgbwData(AQH_DATACLIENT *dc, const AQH_VALUE *value, const char *sValue)
|
||||
{
|
||||
if (sValue) {
|
||||
const char *sValueSystemName;
|
||||
uint32_t color;
|
||||
int rv;
|
||||
|
||||
sValueSystemName=AQH_Value_GetNameForSystem(value);
|
||||
color=AQH_ModDevices_ColorFromHexString(sValue);
|
||||
DBG_ERROR(NULL, "Send value [#%08x] to %s", color, sValueSystemName);
|
||||
rv=AQH_DataClient_SetData(dc, value, (double) color);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "Error sending data: %d", rv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _setOnOffData(AQH_DATACLIENT *dc, const AQH_VALUE *value, const char *sValue)
|
||||
{
|
||||
if (sValue) {
|
||||
const char *sValueSystemName;
|
||||
int rv;
|
||||
|
||||
sValueSystemName=AQH_Value_GetNameForSystem(value);
|
||||
if (strcasecmp(sValue, "unchanged")==0) {
|
||||
DBG_ERROR(NULL, "Value %s unchanged", sValueSystemName);
|
||||
}
|
||||
else if (strcasecmp(sValue, "on")==0) {
|
||||
DBG_ERROR(NULL, "Send value 1 to %s", sValueSystemName);
|
||||
rv=AQH_DataClient_SetData(dc, value, 1.0);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "Error sending data: %d", rv);
|
||||
}
|
||||
}
|
||||
else if (strcasecmp(sValue, "off")==0) {
|
||||
DBG_ERROR(NULL, "Send value 0 to %s", sValueSystemName);
|
||||
rv=AQH_DataClient_SetData(dc, value, 0.0);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "Error sending data: %d", rv);
|
||||
}
|
||||
}
|
||||
else {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _setOnOffAutoData(AQH_DATACLIENT *dc, const AQH_VALUE *value, const char *sValue)
|
||||
{
|
||||
if (sValue) {
|
||||
const char *sValueSystemName;
|
||||
int rv;
|
||||
|
||||
sValueSystemName=AQH_Value_GetNameForSystem(value);
|
||||
if (strcasecmp(sValue, "unchanged")==0) {
|
||||
DBG_ERROR(NULL, "Value %s unchanged", sValueSystemName);
|
||||
}
|
||||
else if (strcasecmp(sValue, "on")==0) {
|
||||
DBG_ERROR(NULL, "Send value 1 to %s", sValueSystemName);
|
||||
rv=AQH_DataClient_SetData(dc, value, 1.0);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "Error sending data: %d", rv);
|
||||
}
|
||||
}
|
||||
else if (strcasecmp(sValue, "off")==0) {
|
||||
DBG_ERROR(NULL, "Send value 0 to %s", sValueSystemName);
|
||||
rv=AQH_DataClient_SetData(dc, value, 0.0);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "Error sending data: %d", rv);
|
||||
}
|
||||
}
|
||||
else if (strcasecmp(sValue, "auto")==0) {
|
||||
DBG_ERROR(NULL, "Send value 2 to %s", sValueSystemName);
|
||||
rv=AQH_DataClient_SetData(dc, value, 2.0);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "Error sending data: %d", rv);
|
||||
}
|
||||
}
|
||||
else {
|
||||
DBG_ERROR(NULL, "Invalid value [%s] for %s", sValue, sValueSystemName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
27
apps/aqhome-cgi/modules/devices/mdevices_setdata.h
Normal file
27
apps/aqhome-cgi/modules/devices/mdevices_setdata.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef AQHOME_CGI_MDEVICES_SETVALUE_H
|
||||
#define AQHOME_CGI_MDEVICES_SETVALUE_H
|
||||
|
||||
|
||||
#include "aqhome-cgi/modules/devices/mdevices.h"
|
||||
|
||||
#include "aqhome/aqhome.h"
|
||||
#include "aqhome/dataclient/client.h"
|
||||
|
||||
#include <aqcgi/request.h>
|
||||
|
||||
#include <gwenhywfar/buffer.h>
|
||||
|
||||
|
||||
|
||||
void AQH_ModDevices_RunSetData(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DATACLIENT *dc, GWEN_BUFFER *dbuf);
|
||||
|
||||
|
||||
#endif
|
||||
105
apps/aqhome-cgi/modules/devices/mdevices_setdevice.c
Normal file
105
apps/aqhome-cgi/modules/devices/mdevices_setdevice.c
Normal file
@@ -0,0 +1,105 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "./mdevices_setdevice.h"
|
||||
|
||||
#include "aqhome-cgi/service/module.h"
|
||||
#include "aqhome-cgi/modules/mdataclient.h"
|
||||
|
||||
#include <gwenhywfar/debug.h>
|
||||
#include <gwenhywfar/timestamp.h>
|
||||
#include <gwenhywfar/text.h>
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* defs and enums
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#define GBAS GWEN_Buffer_AppendString
|
||||
#define GBAA GWEN_Buffer_AppendArgs
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* forward declarations
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static void _handleDeviceForm(AQH_DATACLIENT *dc, AQH_DEVICE *device, GWEN_DB_NODE *dbPost, GWEN_BUFFER *dbuf);
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* code
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void AQH_ModDevices_RunSetDevice(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DATACLIENT *dc, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
AQH_SERVICE *sv;
|
||||
GWEN_DB_NODE *dbPost;
|
||||
const char *sDeviceName;
|
||||
AQH_DEVICE *device;
|
||||
|
||||
DBG_ERROR(NULL, "Post device.html");
|
||||
/* sample data */
|
||||
sv=AQH_ModService_GetService(m);
|
||||
dbPost=AQCGI_Request_GetDbPostBody(rq);
|
||||
sDeviceName=dbPost?GWEN_DB_GetCharValue(dbPost, "device", 0, NULL):NULL;
|
||||
DBG_ERROR(NULL, "Device=[%s]", sDeviceName?sDeviceName:"");
|
||||
|
||||
device=AQH_ModDevices_GetDevice(dc, sDeviceName);
|
||||
if (device) {
|
||||
int rv;
|
||||
|
||||
DBG_ERROR(NULL, "Reading data from form");
|
||||
_handleDeviceForm(dc, device, dbPost, dbuf);
|
||||
DBG_ERROR(NULL, "Updating device on server");
|
||||
rv=AQH_DataClient_ModDevice(dc, device);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "here (%d)", rv);
|
||||
}
|
||||
AQH_Device_free(device);
|
||||
}
|
||||
else {
|
||||
DBG_ERROR(NULL, "device not found");
|
||||
}
|
||||
|
||||
if (sDeviceName && *sDeviceName) {
|
||||
GWEN_BUFFER *pbuf;
|
||||
|
||||
pbuf=GWEN_Buffer_new(0, 256, 0, 1);
|
||||
GBAS(pbuf, "Location: /aqbt/devices/device.html?device=");
|
||||
GWEN_Text_EscapeToBuffer(sDeviceName, pbuf);
|
||||
AQCGI_Request_AddResponseHeaderData(rq, GWEN_Buffer_GetStart(pbuf));
|
||||
GWEN_Buffer_free(pbuf);
|
||||
}
|
||||
AQCGI_Request_SetResponseCode(rq, 303);
|
||||
AQCGI_Request_SetResponseText(rq, "See other");
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _handleDeviceForm(AQH_DATACLIENT *dc, AQH_DEVICE *device, GWEN_DB_NODE *dbPost, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
AQH_Device_SetRoomName(device, GWEN_DB_GetCharValue(dbPost, "roomName", 0, NULL));
|
||||
AQH_Device_SetNameForGui(device, GWEN_DB_GetCharValue(dbPost, "nameForGui", 0, NULL));
|
||||
AQH_Device_SetLocation(device, GWEN_DB_GetCharValue(dbPost, "location", 0, NULL));
|
||||
AQH_Device_SetDescription(device, GWEN_DB_GetCharValue(dbPost, "description", 0, NULL));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
27
apps/aqhome-cgi/modules/devices/mdevices_setdevice.h
Normal file
27
apps/aqhome-cgi/modules/devices/mdevices_setdevice.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef AQHOME_CGI_MDEVICES_SETDEVICE_H
|
||||
#define AQHOME_CGI_MDEVICES_SETDEVICE_H
|
||||
|
||||
|
||||
#include "aqhome-cgi/modules/devices/mdevices.h"
|
||||
|
||||
#include "aqhome/aqhome.h"
|
||||
#include "aqhome/dataclient/client.h"
|
||||
|
||||
#include <aqcgi/request.h>
|
||||
|
||||
#include <gwenhywfar/buffer.h>
|
||||
|
||||
|
||||
|
||||
void AQH_ModDevices_RunSetDevice(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DATACLIENT *dc, GWEN_BUFFER *dbuf);
|
||||
|
||||
|
||||
#endif
|
||||
245
apps/aqhome-cgi/modules/devices/mdevices_value.c
Normal file
245
apps/aqhome-cgi/modules/devices/mdevices_value.c
Normal file
@@ -0,0 +1,245 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "./mdevices_value.h"
|
||||
|
||||
#include "aqhome-cgi/service/module.h"
|
||||
#include "aqhome-cgi/modules/mdataclient.h"
|
||||
|
||||
#include <gwenhywfar/debug.h>
|
||||
#include <gwenhywfar/timestamp.h>
|
||||
#include <gwenhywfar/text.h>
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* defs and enums
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#define GBAS GWEN_Buffer_AppendString
|
||||
#define GBAA GWEN_Buffer_AppendArgs
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* forward declarations
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static void _runValueWithArgs(AQH_MODULE *m,
|
||||
AQCGI_REQUEST *rq,
|
||||
AQH_SESSION *session,
|
||||
AQH_DATACLIENT *dc,
|
||||
const char *sDeviceName,
|
||||
const char *sValueName,
|
||||
GWEN_BUFFER *dbuf);
|
||||
static void _mkValueForm(AQH_DATACLIENT *dc, const char *sDeviceName, const AQH_VALUE *value, GWEN_BUFFER *dbuf);
|
||||
static void _writeRgbwToForm(const char *sValueName, uint32_t color, GWEN_BUFFER *dbuf);
|
||||
static void _writeOnOffToForm(const char *sValueName, int intVal, GWEN_BUFFER *dbuf);
|
||||
static void _writeOnOffAutoToForm(const char *sValueName, int intVal, GWEN_BUFFER *dbuf);
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* code
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void AQH_ModDevices_RunValue(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DATACLIENT *dc, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
GWEN_DB_NODE *dbQuery;
|
||||
const char *sDeviceName;
|
||||
const char *sValueName;
|
||||
|
||||
DBG_ERROR(NULL, "RunValue");
|
||||
dbQuery=AQCGI_Request_GetDbQuery(rq);
|
||||
sDeviceName=GWEN_DB_GetCharValue(dbQuery, "device", 0, NULL);
|
||||
sValueName=GWEN_DB_GetCharValue(dbQuery, "value", 0, NULL);
|
||||
if (sDeviceName && *sDeviceName && sValueName && *sValueName) {
|
||||
GWEN_BUFFER *bufDeviceName;
|
||||
GWEN_BUFFER *bufValueName;
|
||||
|
||||
bufDeviceName=GWEN_Buffer_new(0, 64, 0, 1);
|
||||
GWEN_Text_UnescapeToBufferTolerant(sDeviceName, bufDeviceName);
|
||||
bufValueName=GWEN_Buffer_new(0, 64, 0, 1);
|
||||
GWEN_Text_UnescapeToBufferTolerant(sValueName, bufValueName);
|
||||
_runValueWithArgs(m, rq, session, dc,
|
||||
GWEN_Buffer_GetStart(bufDeviceName),
|
||||
GWEN_Buffer_GetStart(bufValueName),
|
||||
dbuf);
|
||||
GWEN_Buffer_free(bufValueName);
|
||||
GWEN_Buffer_free(bufDeviceName);
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (sDeviceName && *sDeviceName && sValueName && *sValueName) {
|
||||
GWEN_BUFFER *pbuf;
|
||||
|
||||
pbuf=GWEN_Buffer_new(0, 256, 0, 1);
|
||||
GBAS(pbuf, "Location: /aqbt/devices/value.html?device=");
|
||||
GWEN_Text_EscapeToBufferTolerant(sDeviceName, pbuf);
|
||||
GBAS(pbuf, "&value=");
|
||||
GWEN_Text_EscapeToBufferTolerant(sValueName, pbuf);
|
||||
AQCGI_Request_AddResponseHeaderData(rq, GWEN_Buffer_GetStart(pbuf));
|
||||
GWEN_Buffer_free(pbuf);
|
||||
}
|
||||
AQCGI_Request_SetResponseCode(rq, 303);
|
||||
AQCGI_Request_SetResponseText(rq, "See other");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _runValueWithArgs(AQH_MODULE *m,
|
||||
AQCGI_REQUEST *rq,
|
||||
AQH_SESSION *session,
|
||||
AQH_DATACLIENT *dc,
|
||||
const char *sDeviceName,
|
||||
const char *sValueName,
|
||||
GWEN_BUFFER *dbuf)
|
||||
{
|
||||
GWEN_DB_NODE *dbQuery;
|
||||
AQH_VALUE_LIST *valueList;
|
||||
|
||||
dbQuery=AQCGI_Request_GetDbQuery(rq);
|
||||
DBG_ERROR(NULL, "Device=%s, value=%s", sDeviceName?sDeviceName:"<empty>", sValueName?sValueName:"<empty>");
|
||||
|
||||
GBAA(dbuf,"<h1>Value %s/%s</h1>\n", sDeviceName, sValueName);
|
||||
|
||||
valueList=AQH_DataClient_GetValues(dc, sDeviceName, 0);
|
||||
if (valueList) {
|
||||
const AQH_VALUE *value;
|
||||
|
||||
value=AQH_Value_List_First(valueList);
|
||||
while(value) {
|
||||
const char *s;
|
||||
|
||||
s=AQH_Value_GetName(value);
|
||||
if (s && *s && strcasecmp(s, sValueName)==0)
|
||||
break;
|
||||
value=AQH_Value_List_Next(value);
|
||||
}
|
||||
if (value && AQH_Value_GetValueType(value)==AQH_ValueType_Actor) {
|
||||
_mkValueForm(dc, sDeviceName, value, dbuf);
|
||||
}
|
||||
else {
|
||||
GBAS(dbuf, "<table>\n");
|
||||
GBAS(dbuf, "<tr><td>");
|
||||
GBAS(dbuf, "<img src=\"graph.html?device=");
|
||||
GWEN_Text_EscapeToBufferTolerant(sDeviceName, dbuf);
|
||||
GBAS(dbuf, "&value=");
|
||||
GWEN_Text_EscapeToBufferTolerant(sValueName, dbuf);
|
||||
GBAS(dbuf, "&period=4h\"/>");
|
||||
GBAS(dbuf, "</td></tr>");
|
||||
|
||||
GBAS(dbuf, "<tr><td>");
|
||||
GBAS(dbuf, "<img src=\"graph.html?device=");
|
||||
GWEN_Text_EscapeToBufferTolerant(sDeviceName, dbuf);
|
||||
GBAS(dbuf, "&value=");
|
||||
GWEN_Text_EscapeToBufferTolerant(sValueName, dbuf);
|
||||
GBAS(dbuf, "&period=1d\"/>");
|
||||
GBAS(dbuf, "</td></tr>");
|
||||
|
||||
GBAS(dbuf, "<tr><td>");
|
||||
GBAS(dbuf, "<img src=\"graph.html?device=");
|
||||
GWEN_Text_EscapeToBufferTolerant(sDeviceName, dbuf);
|
||||
GBAS(dbuf, "&value=");
|
||||
GWEN_Text_EscapeToBufferTolerant(sValueName, dbuf);
|
||||
GBAS(dbuf, "&period=1w\"/>");
|
||||
GBAS(dbuf, "</td></tr>");
|
||||
|
||||
GBAS(dbuf, "</table>");
|
||||
}
|
||||
AQH_Value_List_free(valueList);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _mkValueForm(AQH_DATACLIENT *dc, const char *sDeviceName, const AQH_VALUE *value, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
const char *sValueSystemName;
|
||||
const char *sValueName;
|
||||
uint64_t dataPoints[2];
|
||||
uint64_t recvdNum;
|
||||
// uint64_t timestamp;
|
||||
union {double f; uint64_t i;} u;
|
||||
int intVal;
|
||||
|
||||
sValueSystemName=AQH_Value_GetNameForSystem(value);
|
||||
sValueName=AQH_Value_GetName(value);
|
||||
recvdNum=AQH_DataClient_GetLastData(dc, sValueSystemName, &dataPoints[0], 1);
|
||||
if (recvdNum>0) {
|
||||
// timestamp=dataPoints[0];
|
||||
u.i=dataPoints[1];
|
||||
intVal=(int) u.f;
|
||||
}
|
||||
else {
|
||||
u.i=0;
|
||||
intVal=-1;
|
||||
}
|
||||
|
||||
GBAS(dbuf,"<form action=\"setdata.html\" method=\"post\">\n");
|
||||
GBAA(dbuf, "<input type=\"hidden\" name=\"device\" value=\"%s\">\n", sDeviceName);
|
||||
GBAA(dbuf, "<input type=\"hidden\" name=\"value\" value=\"%s\">\n", sValueName);
|
||||
|
||||
DBG_ERROR(NULL, "Adding actor");
|
||||
switch(AQH_Value_GetModality(value)) {
|
||||
case AQH_ValueModality_RGBW: _writeRgbwToForm(sValueName, u.f, dbuf); break;
|
||||
case AQH_ValueModality_OnOff: _writeOnOffToForm(sValueName, intVal, dbuf); break;
|
||||
case AQH_ValueModality_OnOffAuto: _writeOnOffAutoToForm(sValueName, intVal, dbuf); break;
|
||||
default: GBAA(dbuf, "%.2f", u.f); break;
|
||||
} /* switch */
|
||||
|
||||
GBAS(dbuf,"<input type=\"submit\" name=\"action\" value=\"Send\"/>");
|
||||
GBAS(dbuf, "</form>\n\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _writeRgbwToForm(const char *sValueName, uint32_t color, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
#if 1
|
||||
GBAA(dbuf, "<input type=\"text\" name=\"%s\" value=\"#%08x\"/>", sValueName, color);
|
||||
#else
|
||||
GBAA(dbuf, "<input type=\"color\" name=\"%s\" value=\"#%08x\"/>#%08x (#%08x)",
|
||||
sValueName,
|
||||
AQH_ModDevices_RgbwToHtmlColor(color),
|
||||
AQH_ModDevices_RgbwToHtmlColor(color),
|
||||
color);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _writeOnOffToForm(const char *sValueName, int intVal, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
GBAA(dbuf, "<select name=\"%s\">" "<option value=\"unchanged\" >unchanged</option>", sValueName);
|
||||
GBAA(dbuf, "<option value=\"off\" %s>off</option>", (intVal==0)?"selected":"");
|
||||
GBAA(dbuf, "<option value=\"on\" %s>on</option>", (intVal==1)?"selected":"");
|
||||
GBAS(dbuf, "</select>");
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _writeOnOffAutoToForm(const char *sValueName, int intVal, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
GBAA(dbuf, "<select name=\"%s\">" "<option value=\"unchanged\" >unchanged</option>", sValueName);
|
||||
GBAA(dbuf, "<option value=\"off\" %s>off</option>", (intVal==0)?"selected":"");
|
||||
GBAA(dbuf, "<option value=\"on\" %s>on</option>", (intVal==1)?"selected":"");
|
||||
GBAA(dbuf, "<option value=\"auto\" %s>auto</option>", (intVal==2)?"selected":"");
|
||||
GBAS(dbuf, "</select>");
|
||||
}
|
||||
|
||||
|
||||
|
||||
27
apps/aqhome-cgi/modules/devices/mdevices_value.h
Normal file
27
apps/aqhome-cgi/modules/devices/mdevices_value.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef AQHOME_CGI_MDEVICES_VALUE_H
|
||||
#define AQHOME_CGI_MDEVICES_VALUE_H
|
||||
|
||||
|
||||
#include "aqhome-cgi/modules/devices/mdevices.h"
|
||||
|
||||
#include "aqhome/aqhome.h"
|
||||
#include "aqhome/dataclient/client.h"
|
||||
|
||||
#include <aqcgi/request.h>
|
||||
|
||||
#include <gwenhywfar/buffer.h>
|
||||
|
||||
|
||||
|
||||
void AQH_ModDevices_RunValue(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DATACLIENT *dc, GWEN_BUFFER *dbuf);
|
||||
|
||||
|
||||
#endif
|
||||
175
apps/aqhome-cgi/modules/devices/mdevices_valuesgraph.c
Normal file
175
apps/aqhome-cgi/modules/devices/mdevices_valuesgraph.c
Normal file
@@ -0,0 +1,175 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "./mdevices_valuesgraph.h"
|
||||
#include "./mdevices_index.h"
|
||||
|
||||
#include "aqhome-cgi/service/module.h"
|
||||
#include "aqhome-cgi/modules/mdataclient.h"
|
||||
|
||||
#include <gwenhywfar/debug.h>
|
||||
#include <gwenhywfar/timestamp.h>
|
||||
#include <gwenhywfar/text.h>
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* defs and enums
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#define GBAS GWEN_Buffer_AppendString
|
||||
#define GBAA GWEN_Buffer_AppendArgs
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* forward declarations
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static void _writeValueToDetailedTable(const char *sDeviceName, const AQH_VALUE *value, GWEN_BUFFER *dbuf);
|
||||
static void _writeValueListToTable(const char *sDeviceName, const AQH_VALUE_LIST *valueList, GWEN_BUFFER *dbuf);
|
||||
static void _writeValueToTable(const char *sDeviceName, const AQH_VALUE *value, GWEN_BUFFER *dbuf);
|
||||
static void _addGraphLink(const char *sDeviceName, const char *sValueName, const char *sPeriod, GWEN_BUFFER *dbuf, int withLink);
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* code
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void AQH_ModDevices_RunValuesAsGraph(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DATACLIENT *dc, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
GWEN_DB_NODE *dbQuery;
|
||||
const char *sDeviceName;
|
||||
|
||||
dbQuery=AQCGI_Request_GetDbQuery(rq);
|
||||
sDeviceName=GWEN_DB_GetCharValue(dbQuery, "device", 0, NULL);
|
||||
if (!(sDeviceName && *sDeviceName))
|
||||
AQH_ModDevices_RunIndex(m, rq, session, dc, dbuf);
|
||||
else {
|
||||
const char *sValueName;
|
||||
|
||||
sValueName=GWEN_DB_GetCharValue(dbQuery, "value", 0, NULL);
|
||||
if (sValueName && *sValueName) {
|
||||
AQH_VALUE *value;
|
||||
|
||||
GBAA(dbuf,"<h1>Value %s/%s</h1>\n", sDeviceName, sValueName);
|
||||
value=AQH_ModDevices_GetValueForDevice(dc, sDeviceName, sValueName);
|
||||
if (value) {
|
||||
_writeValueToDetailedTable(sDeviceName, value, dbuf);
|
||||
AQH_Value_free(value);
|
||||
AQCGI_Request_AddResponseHeaderData(rq, "Refresh: 120");
|
||||
}
|
||||
}
|
||||
else {
|
||||
AQH_VALUE_LIST *valueList;
|
||||
|
||||
valueList=AQH_DataClient_GetValues(dc, sDeviceName, 0);
|
||||
if (valueList && AQH_Value_List_GetCount(valueList)) {
|
||||
|
||||
GBAA(dbuf,"<h1>Values for Device %s</h1>\n", sDeviceName);
|
||||
_writeValueListToTable(sDeviceName, valueList, dbuf);
|
||||
GBAS(dbuf, "\n");
|
||||
}
|
||||
else {
|
||||
GBAS(dbuf,"<p>No values.</p>\n");
|
||||
}
|
||||
AQH_Value_List_free(valueList);
|
||||
AQCGI_Request_AddResponseHeaderData(rq, "Refresh: 305");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _writeValueToDetailedTable(const char *sDeviceName, const AQH_VALUE *value, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
const char *sValueName;
|
||||
|
||||
GBAS(dbuf, "<table>\n");
|
||||
sValueName=AQH_Value_GetName(value);
|
||||
|
||||
GBAS(dbuf, "<tr><td>");
|
||||
_addGraphLink(sDeviceName, sValueName, "4h", dbuf, 0);
|
||||
GBAS(dbuf, "</td><td>");
|
||||
_addGraphLink(sDeviceName, sValueName, "1d", dbuf, 0);
|
||||
GBAS(dbuf, "</td></tr><tr><td>");
|
||||
_addGraphLink(sDeviceName, sValueName, "1w", dbuf, 0);
|
||||
GBAS(dbuf, "</td><td>");
|
||||
_addGraphLink(sDeviceName, sValueName, "12m", dbuf, 0);
|
||||
GBAS(dbuf, "</td></tr>\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _writeValueListToTable(const char *sDeviceName, const AQH_VALUE_LIST *valueList, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
const AQH_VALUE *value;
|
||||
|
||||
GBAS(dbuf, "<table>\n");
|
||||
|
||||
|
||||
value=AQH_Value_List_First(valueList);
|
||||
while(value) {
|
||||
if (AQH_Value_GetValueType(value)!=AQH_ValueType_Actor)
|
||||
_writeValueToTable(sDeviceName, value, dbuf);
|
||||
value=AQH_Value_List_Next(value);
|
||||
}
|
||||
GBAS(dbuf, "</table>\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _writeValueToTable(const char *sDeviceName, const AQH_VALUE *value, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
const char *sValueName;
|
||||
|
||||
/* name */
|
||||
sValueName=AQH_Value_GetName(value);
|
||||
|
||||
GBAS(dbuf, "<tr><td>");
|
||||
_addGraphLink(sDeviceName, sValueName, "1d", dbuf, 1);
|
||||
GBAS(dbuf, "</td><td>");
|
||||
_addGraphLink(sDeviceName, sValueName, "1w", dbuf, 1);
|
||||
GBAS(dbuf, "</td></tr>\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _addGraphLink(const char *sDeviceName, const char *sValueName, const char *sPeriod, GWEN_BUFFER *dbuf, int withLink)
|
||||
{
|
||||
if (withLink) {
|
||||
GBAS(dbuf, "<a href=\"vgraph.html?device=");
|
||||
GWEN_Text_EscapeToBufferTolerant(sDeviceName, dbuf);
|
||||
GBAS(dbuf, "&value=");
|
||||
GWEN_Text_EscapeToBufferTolerant(sValueName, dbuf);
|
||||
GBAS(dbuf, "\">");
|
||||
}
|
||||
|
||||
GBAS(dbuf, "<img src=\"graph.html?device=");
|
||||
GWEN_Text_EscapeToBufferTolerant(sDeviceName, dbuf);
|
||||
GBAS(dbuf, "&value=");
|
||||
GWEN_Text_EscapeToBufferTolerant(sValueName, dbuf);
|
||||
GBAA(dbuf, "&period=%s\"", sPeriod);
|
||||
GBAA(dbuf, " alt=\"%s\" width=\"%d\" height=\"%d\"", sValueName, AQH_MODDEVICES_GRAPH_WIDTH, AQH_MODDEVICES_GRAPH_HEIGHT);
|
||||
GBAS(dbuf, "/>");
|
||||
|
||||
if (withLink) {
|
||||
GBAS(dbuf, "</a>");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
27
apps/aqhome-cgi/modules/devices/mdevices_valuesgraph.h
Normal file
27
apps/aqhome-cgi/modules/devices/mdevices_valuesgraph.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef AQHOME_CGI_MDEVICES_VALUESGRAPH_H
|
||||
#define AQHOME_CGI_MDEVICES_VALUESGRAPH_H
|
||||
|
||||
|
||||
#include "aqhome-cgi/modules/devices/mdevices.h"
|
||||
|
||||
#include "aqhome/aqhome.h"
|
||||
#include "aqhome/dataclient/client.h"
|
||||
|
||||
#include <aqcgi/request.h>
|
||||
|
||||
#include <gwenhywfar/buffer.h>
|
||||
|
||||
|
||||
|
||||
void AQH_ModDevices_RunValuesAsGraph(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DATACLIENT *dc, GWEN_BUFFER *dbuf);
|
||||
|
||||
|
||||
#endif
|
||||
145
apps/aqhome-cgi/modules/devices/mdevices_valuestable.c
Normal file
145
apps/aqhome-cgi/modules/devices/mdevices_valuestable.c
Normal file
@@ -0,0 +1,145 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "./mdevices_valuestable.h"
|
||||
#include "./mdevices_index.h"
|
||||
|
||||
#include "aqhome-cgi/service/module.h"
|
||||
#include "aqhome-cgi/modules/mdataclient.h"
|
||||
|
||||
#include <gwenhywfar/debug.h>
|
||||
#include <gwenhywfar/timestamp.h>
|
||||
#include <gwenhywfar/text.h>
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* defs and enums
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#define GBAS GWEN_Buffer_AppendString
|
||||
#define GBAA GWEN_Buffer_AppendArgs
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* forward declarations
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static void _writeValueListToTable(const char *sDeviceName, const AQH_VALUE_LIST *valueList, uint32_t perms, GWEN_BUFFER *dbuf);
|
||||
static void _writeValueToTable(const char *sDeviceName, const AQH_VALUE *value, uint32_t perms, GWEN_BUFFER *dbuf);
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* code
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void AQH_ModDevices_RunValuesAsTable(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DATACLIENT *dc, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
GWEN_DB_NODE *dbQuery;
|
||||
const char *sDeviceName;
|
||||
uint32_t perms;
|
||||
|
||||
perms=AQH_ModService_GetUserPerms(m);
|
||||
|
||||
dbQuery=AQCGI_Request_GetDbQuery(rq);
|
||||
sDeviceName=GWEN_DB_GetCharValue(dbQuery, "device", 0, NULL);
|
||||
if (!(sDeviceName && *sDeviceName))
|
||||
AQH_ModDevices_RunIndex(m, rq, session, dc, dbuf);
|
||||
else {
|
||||
AQH_VALUE_LIST *valueList;
|
||||
|
||||
valueList=AQH_DataClient_GetValues(dc, sDeviceName, 0);
|
||||
if (valueList && AQH_Value_List_GetCount(valueList)) {
|
||||
|
||||
GBAA(dbuf,"<h1>Values for Device %s</h1>\n", sDeviceName);
|
||||
_writeValueListToTable(sDeviceName, valueList, perms, dbuf);
|
||||
GBAS(dbuf, "\n");
|
||||
}
|
||||
else {
|
||||
GBAS(dbuf,"<p>No values.</p>\n");
|
||||
}
|
||||
AQH_Value_List_free(valueList);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _writeValueListToTable(const char *sDeviceName, const AQH_VALUE_LIST *valueList, uint32_t perms, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
const AQH_VALUE *value;
|
||||
|
||||
GBAS(dbuf,
|
||||
"<table class=\"datatable\">\n"
|
||||
"<thead>"
|
||||
"<tr>"
|
||||
"<th>Name</th>"
|
||||
"<th>Type</th>"
|
||||
"<th>Modality</th>"
|
||||
#if 0
|
||||
"<th>Driver</th>"
|
||||
"<th>Device</th>"
|
||||
"<th>Name for System</th>"
|
||||
#endif
|
||||
"</tr>"
|
||||
"</thead>\n"
|
||||
"<tbody>\n");
|
||||
|
||||
value=AQH_Value_List_First(valueList);
|
||||
while(value) {
|
||||
//if (AQH_Value_GetModality(value)!=AQH_ValueModality_Stats)
|
||||
_writeValueToTable(sDeviceName, value, perms, dbuf);
|
||||
value=AQH_Value_List_Next(value);
|
||||
}
|
||||
GBAS(dbuf,
|
||||
"</tbody>\n"
|
||||
"</table>\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _writeValueToTable(const char *sDeviceName, const AQH_VALUE *value, uint32_t perms, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
const char *s;
|
||||
|
||||
GBAS(dbuf, "<tr>");
|
||||
|
||||
/* name for system */
|
||||
s=AQH_Value_GetName(value);
|
||||
if (perms & AQH_MODDEVICES_PERMS_VALUEREAD) {
|
||||
uint32_t pos;
|
||||
|
||||
pos=GWEN_Buffer_GetPos(dbuf);
|
||||
GBAS(dbuf,"<td><a href=\"value.html?device=");
|
||||
GWEN_Text_EscapeToBuffer(sDeviceName, dbuf);
|
||||
GBAS(dbuf,"&value=");
|
||||
GWEN_Text_EscapeToBuffer(s, dbuf);
|
||||
GBAA(dbuf,"\">%s</a></td>", s);
|
||||
}
|
||||
else
|
||||
GBAA(dbuf,"<td>%s</td>", s?s:"");
|
||||
|
||||
s=AQH_ValueType_toString(AQH_Value_GetValueType(value));
|
||||
GBAA(dbuf, "<td>%s</td>", s?s:"");
|
||||
|
||||
s=AQH_ValueModality_toString(AQH_Value_GetModality(value));
|
||||
GBAA(dbuf, "<td>%s</td>", s?s:"");
|
||||
|
||||
GBAA(dbuf, "</tr>\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
27
apps/aqhome-cgi/modules/devices/mdevices_valuestable.h
Normal file
27
apps/aqhome-cgi/modules/devices/mdevices_valuestable.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef AQHOME_CGI_MDEVICES_VALUESTABLE_H
|
||||
#define AQHOME_CGI_MDEVICES_VALUESTABLE_H
|
||||
|
||||
|
||||
#include "aqhome-cgi/modules/devices/mdevices.h"
|
||||
|
||||
#include "aqhome/aqhome.h"
|
||||
#include "aqhome/dataclient/client.h"
|
||||
|
||||
#include <aqcgi/request.h>
|
||||
|
||||
#include <gwenhywfar/buffer.h>
|
||||
|
||||
|
||||
|
||||
void AQH_ModDevices_RunValuesAsTable(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DATACLIENT *dc, GWEN_BUFFER *dbuf);
|
||||
|
||||
|
||||
#endif
|
||||
384
apps/aqhome-cgi/modules/devices/mdevices_vgraph.c
Normal file
384
apps/aqhome-cgi/modules/devices/mdevices_vgraph.c
Normal file
@@ -0,0 +1,384 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "./mdevices_vgraph.h"
|
||||
|
||||
#include "aqhome-cgi/service/module.h"
|
||||
#include "aqhome-cgi/modules/mdataclient.h"
|
||||
|
||||
#include <aqdiagram/graph/timegraph.h>
|
||||
#include <aqdiagram/graph/w_graph.h>
|
||||
#include <aqdiagram/draw/context_cairo.h>
|
||||
//#include <aqdiagram/data/date.h>
|
||||
//#include <aqdiagram/data/floatingavg.h>
|
||||
|
||||
#include <gwenhywfar/debug.h>
|
||||
#include <gwenhywfar/timestamp.h>
|
||||
#include <gwenhywfar/text.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* defs and enums
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#define GBAS GWEN_Buffer_AppendString
|
||||
#define GBAA GWEN_Buffer_AppendArgs
|
||||
|
||||
|
||||
|
||||
enum {
|
||||
VALUEGRAPH_PERIOD_4H=1,
|
||||
VALUEGRAPH_PERIOD_1D,
|
||||
VALUEGRAPH_PERIOD_1W,
|
||||
VALUEGRAPH_PERIOD_1M,
|
||||
VALUEGRAPH_PERIOD_6M,
|
||||
VALUEGRAPH_PERIOD_12M,
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* vars
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
typedef struct MY_GRAPH_PARAMS MY_GRAPH_PARAMS;
|
||||
struct MY_GRAPH_PARAMS {
|
||||
const char *name;
|
||||
const char *title;
|
||||
const char *modifiers;
|
||||
int startTimeDiff;
|
||||
int acceptedAgeInSeconds;
|
||||
};
|
||||
|
||||
|
||||
|
||||
static MY_GRAPH_PARAMS _graphParams[]={
|
||||
{"4h", "last 4 hours", "Lm5", 4*60*60, 2*60},
|
||||
{"1d", "last 24 hours", "Lm30", 24*60*60, 5*60},
|
||||
{"1w", "last 7 days", "Lm240", 7*24*60*60, 15*60},
|
||||
{"1m", "last 30 days", "Lm480", 30*24*60*60, 60*60},
|
||||
{"6m", "last 6 months", "Lm720", 182*24*60*60, 60*60},
|
||||
{"12m","last 12 months", "Lm1440", 365*24*60*60, 60*60},
|
||||
{NULL, NULL, NULL, 0, 0}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* forward declarations
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static void _runGraphValueWithArgs(AQH_MODULE *m,
|
||||
AQCGI_REQUEST *rq,
|
||||
AQH_DATACLIENT *dc,
|
||||
const char *sDeviceName,
|
||||
const char *sValueName,
|
||||
GWEN_BUFFER *dbuf);
|
||||
static void _createGraph(AQH_DATACLIENT *dc,
|
||||
const AQH_VALUE *v,
|
||||
const MY_GRAPH_PARAMS *graphParams,
|
||||
const char *graphTitle, int precision, const char *curveLabel,
|
||||
const char *sImgFile, int imgWidth, int imgHeight, uint64_t numDataPoints);
|
||||
static int _fileIsCurrent(const char *sPath, int seconds);
|
||||
static AQDG_GRAPH *_mkGraphObjectWithTitle(const char *graphTitle, const MY_GRAPH_PARAMS *graphParams, int precision);
|
||||
static void _mkPathForValueAndPeriod(AQH_MODULE *m, const AQH_VALUE *v, const MY_GRAPH_PARAMS *graphParams, GWEN_BUFFER *dbuf);
|
||||
static AQDG_GRAPH_DATAPAIR_LIST *_requestDataPairList(AQH_DATACLIENT *dc, const char *valueName,
|
||||
uint64_t tsBegin, uint64_t tsEnd, uint64_t num);
|
||||
static AQDG_GRAPH_DATAPAIR_LIST *_createDataPairListFromDataPoints(const uint64_t *dataPoints, uint64_t numValues);
|
||||
static const MY_GRAPH_PARAMS *_getParamsByName(const char *s);
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* code
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void AQH_ModDevices_RunGraphValue(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DATACLIENT *dc, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
GWEN_DB_NODE *dbQuery;
|
||||
const char *sDeviceName;
|
||||
const char *sValueName;
|
||||
|
||||
DBG_DEBUG(NULL, "GraphValue");
|
||||
dbQuery=AQCGI_Request_GetDbQuery(rq);
|
||||
sDeviceName=GWEN_DB_GetCharValue(dbQuery, "device", 0, NULL);
|
||||
sValueName=GWEN_DB_GetCharValue(dbQuery, "value", 0, NULL);
|
||||
DBG_DEBUG(NULL, "Device=%s, value=%s", sDeviceName?sDeviceName:"<empty>", sValueName?sValueName:"<empty>");
|
||||
if (sDeviceName && *sDeviceName && sValueName && *sValueName) {
|
||||
GWEN_BUFFER *bufDeviceName;
|
||||
GWEN_BUFFER *bufValueName;
|
||||
|
||||
bufDeviceName=GWEN_Buffer_new(0, 64, 0, 1);
|
||||
GWEN_Text_UnescapeToBufferTolerant(sDeviceName, bufDeviceName);
|
||||
bufValueName=GWEN_Buffer_new(0, 64, 0, 1);
|
||||
GWEN_Text_UnescapeToBufferTolerant(sValueName, bufValueName);
|
||||
_runGraphValueWithArgs(m, rq, dc,
|
||||
GWEN_Buffer_GetStart(bufDeviceName),
|
||||
GWEN_Buffer_GetStart(bufValueName),
|
||||
dbuf);
|
||||
GWEN_Buffer_free(bufValueName);
|
||||
GWEN_Buffer_free(bufDeviceName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _runGraphValueWithArgs(AQH_MODULE *m,
|
||||
AQCGI_REQUEST *rq,
|
||||
AQH_DATACLIENT *dc,
|
||||
const char *sDeviceName,
|
||||
const char *sValueName,
|
||||
GWEN_BUFFER *dbuf)
|
||||
{
|
||||
GWEN_DB_NODE *dbQuery;
|
||||
AQH_VALUE *value;
|
||||
const MY_GRAPH_PARAMS *graphParams;
|
||||
const char *sPeriod;
|
||||
|
||||
DBG_DEBUG(NULL, "GraphValue with args");
|
||||
dbQuery=AQCGI_Request_GetDbQuery(rq);
|
||||
sPeriod=GWEN_DB_GetCharValue(dbQuery, "period", 0, NULL);
|
||||
graphParams=_getParamsByName(sPeriod);
|
||||
if (graphParams==NULL)
|
||||
graphParams=&_graphParams[0];
|
||||
DBG_DEBUG(NULL, "Device=%s, value=%s, period=%s",
|
||||
sDeviceName?sDeviceName:"<empty>", sValueName?sValueName:"<empty>",
|
||||
sPeriod?sPeriod:"<empty>");
|
||||
|
||||
value=AQH_ModDevices_GetValueForDevice(dc, sDeviceName, sValueName);
|
||||
if (value) {
|
||||
GWEN_BUFFER *fbuf;
|
||||
int rv;
|
||||
|
||||
fbuf=GWEN_Buffer_new(0, 256, 0, 1);
|
||||
_mkPathForValueAndPeriod(m, value, graphParams, fbuf);
|
||||
if (!_fileIsCurrent(GWEN_Buffer_GetStart(fbuf), graphParams->acceptedAgeInSeconds)) {
|
||||
DBG_DEBUG(NULL, "Creating graph");
|
||||
_createGraph(dc,
|
||||
value,
|
||||
graphParams,
|
||||
sValueName,
|
||||
2,
|
||||
AQH_ValueModality_toString(AQH_Value_GetModality(value)),
|
||||
GWEN_Buffer_GetStart(fbuf),
|
||||
AQH_MODDEVICES_GRAPH_WIDTH, AQH_MODDEVICES_GRAPH_HEIGHT,
|
||||
100000);
|
||||
}
|
||||
|
||||
if (1) {
|
||||
GWEN_BUFFER *ibuf;
|
||||
|
||||
ibuf=GWEN_Buffer_new(0, 1024, 0, 1);
|
||||
// return file
|
||||
rv=GWEN_SyncIo_Helper_ReadFile(GWEN_Buffer_GetStart(fbuf), ibuf);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "Error reading \"%s\" (%d)", GWEN_Buffer_GetStart(fbuf), rv);
|
||||
}
|
||||
else {
|
||||
GWEN_Buffer_Reset(dbuf);
|
||||
GWEN_Buffer_AppendBytes(dbuf, GWEN_Buffer_GetStart(ibuf), GWEN_Buffer_GetUsedBytes(ibuf));
|
||||
AQCGI_Request_AddResponseHeaderData(rq, "Content-type: image/png");
|
||||
AQCGI_Request_AddFlags(rq, AQH_MODSERVICE_RQFLAGS_RAWFILE);
|
||||
}
|
||||
GWEN_Buffer_free(ibuf);
|
||||
}
|
||||
|
||||
GWEN_Buffer_free(fbuf);
|
||||
AQH_Value_free(value);
|
||||
}
|
||||
else {
|
||||
DBG_ERROR(NULL, "Could not get value \"%s/%s\"", sDeviceName, sValueName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _fileIsCurrent(const char *sPath, int seconds)
|
||||
{
|
||||
struct stat sb;
|
||||
time_t t1;
|
||||
|
||||
if (lstat(sPath, &sb)==-1) {
|
||||
DBG_ERROR(NULL, "Error on lstat(%s): %s (%d)", sPath, strerror(errno), errno);
|
||||
return 0;
|
||||
}
|
||||
t1=time(0);
|
||||
if ((t1-sb.st_mtime)<(time_t) seconds) {
|
||||
DBG_DEBUG(NULL, "File %s is current", sPath);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _createGraph(AQH_DATACLIENT *dc,
|
||||
const AQH_VALUE *v,
|
||||
const MY_GRAPH_PARAMS *graphParams,
|
||||
const char *graphTitle, int precision,
|
||||
const char *curveLabel,
|
||||
const char *sImgFile, int imgWidth, int imgHeight, uint64_t numDataPoints)
|
||||
{
|
||||
const char *sValue;
|
||||
AQDG_GRAPH *g;
|
||||
AQDG_DRAW_CONTEXT *drawContext;
|
||||
AQDG_OBJECT *graphObject;
|
||||
uint64_t tsBegin;
|
||||
uint64_t tsEnd;
|
||||
AQDG_GRAPH_DATAPAIR_LIST *dpList;
|
||||
|
||||
sValue=AQH_Value_GetNameForSystem(v);
|
||||
tsEnd=time(0);
|
||||
tsBegin=time(0)-(graphParams->startTimeDiff);
|
||||
g=_mkGraphObjectWithTitle(graphTitle, graphParams, precision);
|
||||
|
||||
dpList=_requestDataPairList(dc, sValue, tsBegin, tsEnd, numDataPoints);
|
||||
if (dpList) {
|
||||
DBG_DEBUG(NULL, "Adding data for %s", sValue);
|
||||
AQDG_TimeGraph_ModifyDataAndAddCurve(g, curveLabel?curveLabel:sValue, graphParams->modifiers, dpList);
|
||||
}
|
||||
else {
|
||||
DBG_ERROR(NULL, "No data for %s", sValue);
|
||||
AQDG_Graph_free(g);
|
||||
return;
|
||||
}
|
||||
|
||||
AQDG_TimeGraph_SetupTicks(g, 0, 0.0, 0.0);
|
||||
|
||||
DBG_DEBUG(NULL, "Draw graph for %s", sValue);
|
||||
drawContext=AQDG_Draw_ContextCairo_Png_new(sImgFile, imgWidth, imgHeight);
|
||||
graphObject=AQDG_GraphWidget_new(NULL, AQDG_OBJECT_OPTIONS_STRETCHX | AQDG_OBJECT_OPTIONS_STRETCHY, drawContext);
|
||||
AQDG_Object_SetWidth(graphObject, imgWidth);
|
||||
AQDG_Object_SetHeight(graphObject, imgHeight);
|
||||
|
||||
AQDG_GraphWidget_SetupDefaultPens(graphObject);
|
||||
AQDG_GraphWidget_SetupDefaultFonts(graphObject);
|
||||
|
||||
AQDG_GraphWidget_FinishWithGraph(graphObject, g);
|
||||
|
||||
AQDG_Object_free(graphObject);
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQDG_GRAPH *_mkGraphObjectWithTitle(const char *graphTitle, const MY_GRAPH_PARAMS *graphParams, int precision)
|
||||
{
|
||||
AQDG_GRAPH *g;
|
||||
GWEN_BUFFER *tbuf;
|
||||
|
||||
tbuf=GWEN_Buffer_new(0, 256, 0, 1);
|
||||
|
||||
GBAA(tbuf, "%s - %s", graphTitle, graphParams->title);
|
||||
|
||||
g=AQDG_TimeGraph_new(GWEN_Buffer_GetStart(tbuf), NULL, "Value", NULL, precision);
|
||||
GWEN_Buffer_free(tbuf);
|
||||
return g;
|
||||
}
|
||||
|
||||
|
||||
void _mkPathForValueAndPeriod(AQH_MODULE *m, const AQH_VALUE *v, const MY_GRAPH_PARAMS *graphParams, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
AQH_SERVICE *sv;
|
||||
const char *s;
|
||||
|
||||
sv=AQH_ModService_GetService(m);
|
||||
|
||||
/* cache folder */
|
||||
s=AQH_Service_GetCacheFolder(sv);
|
||||
GBAA(dbuf, "%s%s", s, GWEN_DIR_SEPARATOR_S);
|
||||
|
||||
/* var name */
|
||||
s=AQH_Value_GetNameForSystem(v);
|
||||
GWEN_Text_EscapeToBuffer(s, dbuf);
|
||||
|
||||
GBAA(dbuf, "-%s.png", graphParams->name);
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQDG_GRAPH_DATAPAIR_LIST *_requestDataPairList(AQH_DATACLIENT *dc, const char *valueName,
|
||||
uint64_t tsBegin, uint64_t tsEnd, uint64_t num)
|
||||
{
|
||||
uint64_t *dataPoints;
|
||||
uint64_t recvdNum;
|
||||
|
||||
dataPoints=malloc(num*sizeof(uint64_t)*2);
|
||||
|
||||
recvdNum=AQH_DataClient_GetPeriodData(dc, valueName, dataPoints, num, tsBegin, tsEnd);
|
||||
if (recvdNum>0) {
|
||||
AQDG_GRAPH_DATAPAIR_LIST *dpList;
|
||||
|
||||
dpList=_createDataPairListFromDataPoints(dataPoints, recvdNum);
|
||||
free(dataPoints);
|
||||
return dpList;
|
||||
}
|
||||
else {
|
||||
DBG_ERROR(NULL, "No data received for %s", valueName);
|
||||
free(dataPoints);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQDG_GRAPH_DATAPAIR_LIST *_createDataPairListFromDataPoints(const uint64_t *dataPoints, uint64_t numValues)
|
||||
{
|
||||
AQDG_GRAPH_DATAPAIR_LIST *dpList;
|
||||
uint64_t i;
|
||||
|
||||
DBG_DEBUG(NULL, "Got %d datapoints", (int) numValues);
|
||||
dpList=AQDG_Graph_DataPair_List_new();
|
||||
for(i=0; i<numValues; i++) {
|
||||
AQDG_GRAPH_DATAPAIR *dp;
|
||||
double timestamp;
|
||||
union {double f; uint64_t i;} u;
|
||||
|
||||
timestamp=(double)(*(dataPoints++));
|
||||
u.i=*(dataPoints++);
|
||||
dp=AQDG_Graph_DataPair_new();
|
||||
AQDG_Graph_DataPair_SetValueX(dp, timestamp);
|
||||
AQDG_Graph_DataPair_SetValueY(dp, u.f);
|
||||
AQDG_Graph_DataPair_List_Add(dp, dpList);
|
||||
}
|
||||
AQDG_Graph_DataPair_List_SortByValueX(dpList, 1);
|
||||
return dpList;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const MY_GRAPH_PARAMS *_getParamsByName(const char *s)
|
||||
{
|
||||
const MY_GRAPH_PARAMS *p;
|
||||
|
||||
p=_graphParams;
|
||||
while(p->name) {
|
||||
if (strcasecmp(p->name, s)==0)
|
||||
return p;
|
||||
p++;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
27
apps/aqhome-cgi/modules/devices/mdevices_vgraph.h
Normal file
27
apps/aqhome-cgi/modules/devices/mdevices_vgraph.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef AQHOME_CGI_MDEVICES_VGRAPH_H
|
||||
#define AQHOME_CGI_MDEVICES_VGRAPH_H
|
||||
|
||||
|
||||
#include "aqhome-cgi/modules/devices/mdevices.h"
|
||||
|
||||
#include "aqhome/aqhome.h"
|
||||
#include "aqhome/dataclient/client.h"
|
||||
|
||||
#include <aqcgi/request.h>
|
||||
|
||||
#include <gwenhywfar/buffer.h>
|
||||
|
||||
|
||||
|
||||
void AQH_ModDevices_RunGraphValue(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DATACLIENT *dc, GWEN_BUFFER *dbuf);
|
||||
|
||||
|
||||
#endif
|
||||
BIN
apps/aqhome-cgi/modules/html/pics/cancel.png
Normal file
BIN
apps/aqhome-cgi/modules/html/pics/cancel.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.7 KiB |
BIN
apps/aqhome-cgi/modules/html/pics/edit.png
Normal file
BIN
apps/aqhome-cgi/modules/html/pics/edit.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 912 B |
BIN
apps/aqhome-cgi/modules/html/pics/graph.png
Normal file
BIN
apps/aqhome-cgi/modules/html/pics/graph.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.7 KiB |
BIN
apps/aqhome-cgi/modules/html/pics/minus.png
Normal file
BIN
apps/aqhome-cgi/modules/html/pics/minus.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 356 B |
BIN
apps/aqhome-cgi/modules/html/pics/ok.png
Normal file
BIN
apps/aqhome-cgi/modules/html/pics/ok.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1013 B |
BIN
apps/aqhome-cgi/modules/html/pics/plus.png
Normal file
BIN
apps/aqhome-cgi/modules/html/pics/plus.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 834 B |
63
apps/aqhome-cgi/modules/html/style.css
Normal file
63
apps/aqhome-cgi/modules/html/style.css
Normal file
@@ -0,0 +1,63 @@
|
||||
body {
|
||||
background-color: whitesmoke;
|
||||
}
|
||||
|
||||
table.datatable {
|
||||
border: thin solid;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
|
||||
table.datatable th, td {
|
||||
border: thin solid;
|
||||
border-collapse: collapse;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
|
||||
table.datatable tbody tr:nth-child(odd) {
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
|
||||
|
||||
table.formtable {
|
||||
border: thin solid;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
|
||||
table.formtable th, td {
|
||||
border: thin solid;
|
||||
border-collapse: collapse;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
ul.mainmenu {
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
background-color: #333333;
|
||||
}
|
||||
|
||||
|
||||
ul.mainmenu li {
|
||||
float: left;
|
||||
}
|
||||
|
||||
ul.mainmenu li a {
|
||||
display: block;
|
||||
color: white;
|
||||
text-align: center;
|
||||
padding: 14px 16px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
ul.mainmenu li a:hover {
|
||||
background-color: #111111;
|
||||
}
|
||||
|
||||
|
||||
102
apps/aqhome-cgi/modules/mdataclient.c
Normal file
102
apps/aqhome-cgi/modules/mdataclient.c
Normal file
@@ -0,0 +1,102 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "./mdataclient.h"
|
||||
|
||||
#include "aqhome-cgi/service/module.h"
|
||||
|
||||
#include "aqhome/msg/ipc/m_ipc.h"
|
||||
#include "aqhome/msg/ipc/data/m_ipcd.h"
|
||||
|
||||
#include <gwenhywfar/debug.h>
|
||||
#include <gwenhywfar/timestamp.h>
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* defs and enums
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* global vars
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* forward declarations
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* code
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void AQH_ModDataClient_Extend(AQH_MODULE *m, AQH_SERVICE *sv, const char *baseFolder)
|
||||
{
|
||||
|
||||
AQH_ModService_Extend(m, sv, baseFolder);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQH_ModDataClient_HandleRequest(AQH_MODULE *m,
|
||||
AQCGI_REQUEST *rq,
|
||||
AQH_SESSION *session,
|
||||
AQH_MODDATACLIENT_RUN_FN runFn,
|
||||
GWEN_BUFFER *dbuf)
|
||||
{
|
||||
AQH_EVENT_LOOP *eventLoop;
|
||||
AQH_DATACLIENT *dc;
|
||||
int rv;
|
||||
|
||||
rv=AQH_Init();
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "here (%d)", rv);
|
||||
AQCGI_Request_SetResponseCode(rq, 500);
|
||||
AQCGI_Request_SetResponseText(rq, "Internal Error");
|
||||
return;
|
||||
}
|
||||
|
||||
eventLoop=AQH_EventLoop_new();
|
||||
dc=AQH_DataClient_new(eventLoop, AQH_IPC_PROTOCOL_DATA_ID, AQH_IPC_PROTOCOL_DATA_VERSION);
|
||||
rv=AQH_DataClient_ReadConfigFile(dc);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "here (%d)", rv);
|
||||
AQCGI_Request_SetResponseCode(rq, 500);
|
||||
AQCGI_Request_SetResponseText(rq, "Internal Error");
|
||||
return;
|
||||
}
|
||||
|
||||
rv=AQH_DataClient_ConnectWithArgs(dc, 0);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "Error connecting (%d)", rv);
|
||||
AQH_DataClient_free(dc);
|
||||
AQH_EventLoop_free(eventLoop);
|
||||
AQCGI_Request_SetResponseCode(rq, 500);
|
||||
AQCGI_Request_SetResponseText(rq, "Internal Error");
|
||||
return;
|
||||
}
|
||||
|
||||
if (runFn)
|
||||
runFn(m, rq, session, dc, dbuf);
|
||||
|
||||
AQH_DataClient_free(dc);
|
||||
AQH_EventLoop_free(eventLoop);
|
||||
|
||||
AQH_Fini();
|
||||
}
|
||||
|
||||
|
||||
|
||||
37
apps/aqhome-cgi/modules/mdataclient.h
Normal file
37
apps/aqhome-cgi/modules/mdataclient.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef AQHOME_CGI_MDATACLIENT_H
|
||||
#define AQHOME_CGI_MDATACLIENT_H
|
||||
|
||||
#include <aqhome-cgi/modules/common/mservice.h>
|
||||
|
||||
#include <aqcgi/request.h>
|
||||
|
||||
#include "aqhome/aqhome.h"
|
||||
#include "aqhome/dataclient/client.h"
|
||||
|
||||
#include <gwenhywfar/buffer.h>
|
||||
|
||||
|
||||
|
||||
typedef void (*AQH_MODDATACLIENT_RUN_FN)(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DATACLIENT *dc, GWEN_BUFFER *dbuf);
|
||||
|
||||
|
||||
void AQH_ModDataClient_Extend(AQH_MODULE *m, AQH_SERVICE *sv, const char *baseFolder);
|
||||
void AQH_ModDataClient_HandleRequest(AQH_MODULE *m,
|
||||
AQCGI_REQUEST *rq,
|
||||
AQH_SESSION *session,
|
||||
AQH_MODDATACLIENT_RUN_FN runFn,
|
||||
GWEN_BUFFER *dbuf);
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
326
apps/aqhome-cgi/modules/mroot.c
Normal file
326
apps/aqhome-cgi/modules/mroot.c
Normal file
@@ -0,0 +1,326 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "./mroot_p.h"
|
||||
|
||||
#include "aqhome-cgi/service/module.h"
|
||||
#include "aqhome-cgi/modules/devices/mdevices.h"
|
||||
#include "aqhome-cgi/modules/common/madmin.h"
|
||||
|
||||
#include <gwenhywfar/debug.h>
|
||||
#include <gwenhywfar/timestamp.h>
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* defs and enums
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* global vars
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* forward declarations
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static AQH_MODULE *_loadSubModule(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, const char *sModuleName);
|
||||
static int _handleRequest(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, const char *sLastPathElem);
|
||||
static int _handleRqIndex(AQH_MODULE *m, AQCGI_REQUEST *rq, GWEN_BUFFER *dbuf);
|
||||
static int _handleRqLogin(AQH_MODULE *m, AQCGI_REQUEST *rq, GWEN_BUFFER *dbuf);
|
||||
static int _handleRqLoginPost(AQH_MODULE *m, AQCGI_REQUEST *rq, GWEN_BUFFER *dbuf);
|
||||
static AQH_USER *_getAndCheckUser(AQH_MODULE *m, AQCGI_REQUEST *rq, GWEN_BUFFER *dbuf);
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* code
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
AQH_MODULE *AQH_ModRoot_new(AQH_SERVICE *sv, const char *baseFolder)
|
||||
{
|
||||
AQH_MODULE *m;
|
||||
|
||||
m=AQH_Module_new();
|
||||
AQH_ModService_Extend(m, sv, baseFolder);
|
||||
AQH_ModService_SetHandleRequestFn(m, _handleRequest);
|
||||
AQH_ModService_SetLoadSubModuleFn(m, _loadSubModule);
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQH_MODULE *_loadSubModule(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, const char *sModuleName)
|
||||
{
|
||||
AQH_SERVICE *sv;
|
||||
|
||||
sv=AQH_ModService_GetService(m);
|
||||
if (strcasecmp(sModuleName, "devices")==0) {
|
||||
AQH_MODULE *mSub;
|
||||
|
||||
mSub=AQH_Service_LoadModule(sv, sModuleName);
|
||||
if (mSub) {
|
||||
const char *s;
|
||||
GWEN_BUFFER *nbuf;
|
||||
|
||||
nbuf=GWEN_Buffer_new(0, 256, 0, 1);
|
||||
s=AQH_ModService_GetBaseFolder(m);
|
||||
GWEN_Buffer_AppendArgs(nbuf, "%s/devices", s?s:".");
|
||||
|
||||
AQH_ModDevices_Extend(mSub, AQH_ModService_GetService(m), GWEN_Buffer_GetStart(nbuf));
|
||||
AQH_Module_Tree2_AddChild(m, mSub);
|
||||
GWEN_Buffer_free(nbuf);
|
||||
return mSub;
|
||||
}
|
||||
}
|
||||
else if (strcasecmp(sModuleName, "admin")==0) {
|
||||
AQH_MODULE *mSub;
|
||||
|
||||
mSub=AQH_Service_LoadModule(sv, sModuleName);
|
||||
if (mSub) {
|
||||
const char *s;
|
||||
GWEN_BUFFER *nbuf;
|
||||
|
||||
nbuf=GWEN_Buffer_new(0, 256, 0, 1);
|
||||
s=AQH_ModService_GetBaseFolder(m);
|
||||
GWEN_Buffer_AppendArgs(nbuf, "%s/devices", s?s:".");
|
||||
|
||||
AQH_ModAdmin_Extend(mSub, AQH_ModService_GetService(m), GWEN_Buffer_GetStart(nbuf));
|
||||
AQH_Module_Tree2_AddChild(m, mSub);
|
||||
GWEN_Buffer_free(nbuf);
|
||||
return mSub;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _handleRequest(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, const char *sLastPathElem)
|
||||
{
|
||||
GWEN_BUFFER *dbuf;
|
||||
|
||||
dbuf=GWEN_Buffer_new(0, 256, 0, 1);
|
||||
AQH_ModService_AddHeader(m, "en", dbuf);
|
||||
|
||||
if (strcasecmp(sLastPathElem, "login")==0)
|
||||
_handleRqLogin(m, rq, dbuf);
|
||||
else if (strcasecmp(sLastPathElem, "signup")==0) {
|
||||
AQCGI_Request_SetResponseCode(rq, 501);
|
||||
AQCGI_Request_SetResponseText(rq, "Not Implemented");
|
||||
}
|
||||
else if (strcasecmp(sLastPathElem, "confirm")==0) {
|
||||
AQCGI_Request_SetResponseCode(rq, 501);
|
||||
AQCGI_Request_SetResponseText(rq, "Not Implemented");
|
||||
}
|
||||
else if (strcasecmp(sLastPathElem, "index.html")==0)
|
||||
_handleRqIndex(m, rq, dbuf);
|
||||
else {
|
||||
AQCGI_Request_SetResponseCode(rq, 404);
|
||||
AQCGI_Request_SetResponseText(rq, "Not Found");
|
||||
}
|
||||
|
||||
AQH_ModService_AddFooter(m, "en", dbuf);
|
||||
AQCGI_Request_SetBufferResponseBody(rq, dbuf);
|
||||
AQCGI_Request_AddResponseHeaderData(rq, "Content-type: text/html");
|
||||
|
||||
return AQCGI_SendResponse(rq);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _handleRqIndex(AQH_MODULE *m, AQCGI_REQUEST *rq, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
if (AQCGI_Request_GetRequestMethod(rq)==AQCGI_REQUEST_METHOD_GET)
|
||||
return AQH_ModService_RespondWithFile(m, rq, "en", "index.html", dbuf);
|
||||
else {
|
||||
DBG_ERROR(NULL, "Invalid request method %d", AQCGI_Request_GetRequestMethod(rq));
|
||||
AQCGI_Request_SetResponseCode(rq, 405);
|
||||
AQCGI_Request_SetResponseText(rq, "Method Not Allowed");
|
||||
return GWEN_ERROR_GENERIC;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _handleRqLogin(AQH_MODULE *m, AQCGI_REQUEST *rq, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
if (AQCGI_Request_GetRequestMethod(rq)==AQCGI_REQUEST_METHOD_GET)
|
||||
AQH_ModService_RespondWithFile(m, rq, "en", "login.html", dbuf);
|
||||
else if (AQCGI_Request_GetRequestMethod(rq)==AQCGI_REQUEST_METHOD_POST)
|
||||
_handleRqLoginPost(m, rq, dbuf);
|
||||
else {
|
||||
DBG_ERROR(NULL, "Invalid request method %d", AQCGI_Request_GetRequestMethod(rq));
|
||||
AQCGI_Request_SetResponseCode(rq, 405);
|
||||
AQCGI_Request_SetResponseText(rq, "Method Not Allowed");
|
||||
return GWEN_ERROR_GENERIC;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _handleRqLoginPost(AQH_MODULE *m, AQCGI_REQUEST *rq, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
AQH_SERVICE *sv;
|
||||
AQH_USER *user;
|
||||
AQH_SESSION *session;
|
||||
GWEN_BUFFER *tbuf;
|
||||
GWEN_TIMESTAMP *ts;
|
||||
int rv;
|
||||
|
||||
DBG_ERROR(NULL, "Handling request");
|
||||
sv=AQH_ModService_GetService(m);
|
||||
user=_getAndCheckUser(m, rq, dbuf);
|
||||
if (user==NULL) {
|
||||
DBG_INFO(NULL, "here");
|
||||
AQCGI_Request_SetResponseCode(rq, 500);
|
||||
AQCGI_Request_SetResponseText(rq, "Internal Error");
|
||||
return GWEN_ERROR_GENERIC;
|
||||
}
|
||||
|
||||
ts=GWEN_Timestamp_NowInLocalTime();
|
||||
AQH_User_SetTimestampLastLogin(user, ts);
|
||||
DBG_ERROR(NULL, "Saving user");
|
||||
rv=AQH_Service_SaveUser(sv, user);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "Error saving user \"%s\"", AQH_User_GetAlias(user));
|
||||
AQCGI_Request_SetResponseCode(rq, 500);
|
||||
AQCGI_Request_SetResponseText(rq, "Internal Error");
|
||||
AQH_User_free(user);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* generate session */
|
||||
DBG_ERROR(NULL, "Generating session");
|
||||
tbuf=GWEN_Buffer_new(0, 64, 0, 1);
|
||||
AQCGI_GenerateSessionId(tbuf);
|
||||
session=AQH_Session_new();
|
||||
AQH_Session_SetTimestampCreation(session, ts);
|
||||
AQH_Session_SetTimestampLastAccess(session, ts);
|
||||
AQH_Session_SetUid(session, GWEN_Buffer_GetStart(tbuf));
|
||||
GWEN_Buffer_free(tbuf);
|
||||
AQH_Session_SetUserAlias(session, AQH_User_GetAlias(user));
|
||||
rv=AQH_Service_AddSession(sv, session);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "Error adding session for user \"%s\" (%d)", AQH_User_GetAlias(user), rv);
|
||||
AQCGI_Request_SetResponseCode(rq, 500);
|
||||
AQCGI_Request_SetResponseText(rq, "Internal Error");
|
||||
AQH_Session_free(session);
|
||||
AQH_User_free(user);
|
||||
return GWEN_ERROR_INTERNAL;
|
||||
}
|
||||
|
||||
/* add Set-Cookie header */
|
||||
tbuf=GWEN_Buffer_new(0, 256, 0, 1);
|
||||
GWEN_Buffer_AppendArgs(tbuf, "Set-Cookie: session=%s; max-age=86400", AQH_Session_GetUid(session));
|
||||
AQCGI_Request_AddResponseHeaderData(rq, GWEN_Buffer_GetStart(tbuf));
|
||||
GWEN_Buffer_free(tbuf);
|
||||
|
||||
/* finish */
|
||||
AQCGI_Request_AddResponseHeaderData(rq, "Location: index.html");
|
||||
AQCGI_Request_SetResponseCode(rq, 303);
|
||||
AQCGI_Request_SetResponseText(rq, "See other");
|
||||
AQH_Session_free(session);
|
||||
AQH_User_free(user);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQH_USER *_getAndCheckUser(AQH_MODULE *m, AQCGI_REQUEST *rq, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
GWEN_DB_NODE *dbPost;
|
||||
|
||||
dbPost=AQCGI_Request_GetDbPostBody(rq);
|
||||
if (dbPost) {
|
||||
AQH_SERVICE *sv;
|
||||
const char *sUserName;
|
||||
const char *sPasswd;
|
||||
AQH_USER *user;
|
||||
const char *hashedPaswd;
|
||||
GWEN_BUFFER *buf;
|
||||
|
||||
sv=AQH_ModService_GetService(m);
|
||||
sUserName=GWEN_DB_GetCharValue(dbPost, "userid", 0, NULL);
|
||||
sPasswd=GWEN_DB_GetCharValue(dbPost, "password", 0, NULL);
|
||||
if (!(sUserName && *sUserName && sPasswd && *sPasswd)) {
|
||||
DBG_ERROR(NULL, "Either user name or password missing");
|
||||
AQCGI_Request_SetResponseCode(rq, 400);
|
||||
AQCGI_Request_SetResponseText(rq, "Bad Request");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DBG_ERROR(NULL, "Loading user \"%s\" (%p)", sUserName, sv);
|
||||
user=AQH_Service_LoadUser(sv, sUserName);
|
||||
if (user==NULL) {
|
||||
DBG_ERROR(NULL, "User \"%s\" not found", sUserName);
|
||||
AQCGI_Request_SetResponseCode(rq, 403);
|
||||
AQCGI_Request_SetResponseText(rq, "Forbidden");
|
||||
return NULL;
|
||||
}
|
||||
DBG_ERROR(NULL, "Loaded user \"%s\"", sUserName);
|
||||
|
||||
if (AQH_User_GetState(user)!=AQH_UserState_Active) {
|
||||
DBG_ERROR(NULL, "User \"%s\" not active", sUserName);
|
||||
AQCGI_Request_SetResponseCode(rq, 403);
|
||||
AQCGI_Request_SetResponseText(rq, "Forbidden");
|
||||
AQH_User_free(user);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
hashedPaswd=AQH_User_GetHashedPassword(user);
|
||||
if (!(hashedPaswd && *hashedPaswd)) {
|
||||
DBG_ERROR(NULL, "User \"%s\" has no hashed password", sUserName);
|
||||
AQCGI_Request_SetResponseCode(rq, 403);
|
||||
AQCGI_Request_SetResponseText(rq, "Forbidden");
|
||||
AQH_User_free(user);
|
||||
return NULL;
|
||||
}
|
||||
buf=GWEN_Buffer_new(0, 256, 0, 1);
|
||||
AQCGI_HashMd256ToBuffer(sPasswd, buf);
|
||||
DBG_ERROR(NULL, "Password: [%s]", sPasswd); // TODO: Remove!!!
|
||||
DBG_ERROR(NULL, "Hashed password: [%s]", GWEN_Buffer_GetStart(buf));
|
||||
if (strcasecmp(GWEN_Buffer_GetStart(buf), hashedPaswd)!=0) {
|
||||
DBG_ERROR(NULL, "Bad password for user \"%s\"", sUserName);
|
||||
AQCGI_Request_SetResponseCode(rq, 403);
|
||||
AQCGI_Request_SetResponseText(rq, "Forbidden");
|
||||
GWEN_Buffer_free(buf);
|
||||
AQH_User_free(user);
|
||||
return NULL;
|
||||
}
|
||||
GWEN_Buffer_free(buf);
|
||||
|
||||
DBG_ERROR(NULL, "User \"%s\" accepted", sUserName);
|
||||
return user;
|
||||
}
|
||||
else {
|
||||
DBG_ERROR(NULL, "No POST data");
|
||||
AQCGI_SendResponseWithStatus(rq, 400, "Bad Request");
|
||||
AQCGI_Request_SetResponseCode(rq, 400);
|
||||
AQCGI_Request_SetResponseText(rq, "Bad Request");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
27
apps/aqhome-cgi/modules/mroot.h
Normal file
27
apps/aqhome-cgi/modules/mroot.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef AQHOME_CGI_MROOT_H
|
||||
#define AQHOME_CGI_MROOT_H
|
||||
|
||||
#include <aqhome-cgi/modules/common/mservice.h>
|
||||
|
||||
#include <aqcgi/request.h>
|
||||
|
||||
#include <gwenhywfar/buffer.h>
|
||||
|
||||
|
||||
AQH_MODULE *AQH_ModRoot_new(AQH_SERVICE *sv, const char *baseFolder);
|
||||
|
||||
AQH_MODULE *AQH_ModRoot_LoadSubModule(AQH_MODULE *m, AQCGI_REQUEST *rq, const char *sModuleName);
|
||||
int AQH_ModRoot_HandleRequest(AQH_MODULE *m, AQCGI_REQUEST *rq, const char *sLastPathElem);
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
18
apps/aqhome-cgi/modules/mroot_p.h
Normal file
18
apps/aqhome-cgi/modules/mroot_p.h
Normal file
@@ -0,0 +1,18 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef AQHOME_CGI_MROOT_P_H
|
||||
#define AQHOME_CGI_MROOT_P_H
|
||||
|
||||
#include "aqhome-cgi/modules/mroot.h"
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
7
apps/aqhome-cgi/modules/static/0BUILD
Normal file
7
apps/aqhome-cgi/modules/static/0BUILD
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml?>
|
||||
|
||||
<gwbuild>
|
||||
<subdirs>
|
||||
en
|
||||
</subdirs>
|
||||
</gwbuild>
|
||||
14
apps/aqhome-cgi/modules/static/en/0BUILD
Normal file
14
apps/aqhome-cgi/modules/static/en/0BUILD
Normal file
@@ -0,0 +1,14 @@
|
||||
<?xml?>
|
||||
|
||||
<gwbuild>
|
||||
|
||||
<data dist="true" install="$(httpdatadir)/aqhome-cgi/static/en">
|
||||
header.html
|
||||
footer.html
|
||||
login.html
|
||||
index.html
|
||||
</data>
|
||||
|
||||
|
||||
</gwbuild>
|
||||
|
||||
4
apps/aqhome-cgi/modules/static/en/footer.html
Normal file
4
apps/aqhome-cgi/modules/static/en/footer.html
Normal file
@@ -0,0 +1,4 @@
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
26
apps/aqhome-cgi/modules/static/en/header.html
Normal file
26
apps/aqhome-cgi/modules/static/en/header.html
Normal file
@@ -0,0 +1,26 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<!-- copyright (c) 2025 by martin@libchipcard.de -->
|
||||
<meta name="generator" content="FTE 1.1" />
|
||||
<meta name="revised" content="martin,2025-06-12" />
|
||||
<meta name="keywords" content="" />
|
||||
<meta name="description" content="" />
|
||||
<meta name="author" content="martin" />
|
||||
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1" />
|
||||
<link rel="stylesheet" href="/style.css" >
|
||||
<title>AqHome</title>
|
||||
</head>
|
||||
|
||||
<ul class="mainmenu" >
|
||||
<li><a href="/aqbt/devices/index.html">Devices</a></li>
|
||||
<li><a href="/aqbt/admin/index.html">Admin</a></li>
|
||||
<li><a href="#news">News</a></li>
|
||||
<li><a href="#contact">Contact</a></li>
|
||||
<li style="float:right"><a href="/aqbt/login">Login</a></li>
|
||||
</ul>
|
||||
|
||||
<body>
|
||||
|
||||
6
apps/aqhome-cgi/modules/static/en/index.html
Normal file
6
apps/aqhome-cgi/modules/static/en/index.html
Normal file
@@ -0,0 +1,6 @@
|
||||
|
||||
|
||||
<h1> AqHome Main Page </h1>
|
||||
|
||||
<p>Nothing to see for now</p>
|
||||
|
||||
25
apps/aqhome-cgi/modules/static/en/login.html
Normal file
25
apps/aqhome-cgi/modules/static/en/login.html
Normal file
@@ -0,0 +1,25 @@
|
||||
|
||||
<div class="main">
|
||||
<h1>AqHome</h1>
|
||||
<h3>Enter your login credentials</h3>
|
||||
|
||||
<form action="login" method="post">
|
||||
<label for="userid">Username:</label>
|
||||
<input type="text" id="userid" name="userid" placeholder="Enter your Username" required>
|
||||
<label for="password">Password:</label>
|
||||
<input type="password" id="password" name="password" placeholder="Enter your Password" required>
|
||||
|
||||
<div class="wrap">
|
||||
<button type="submit">Submit</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<p>Not registered?
|
||||
<a href="signup" style="text-decoration: none;">
|
||||
Create an account
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
63
apps/aqhome-cgi/modules/static/style.css
Normal file
63
apps/aqhome-cgi/modules/static/style.css
Normal file
@@ -0,0 +1,63 @@
|
||||
body {
|
||||
background-color: whitesmoke;
|
||||
}
|
||||
|
||||
table.datatable {
|
||||
border: thin solid;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
|
||||
table.datatable th, td {
|
||||
border: thin solid;
|
||||
border-collapse: collapse;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
|
||||
table.datatable tbody tr:nth-child(odd) {
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
|
||||
|
||||
table.formtable {
|
||||
border: thin solid;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
|
||||
table.formtable th, td {
|
||||
border: thin solid;
|
||||
border-collapse: collapse;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
ul.mainmenu {
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
background-color: #333333;
|
||||
}
|
||||
|
||||
|
||||
ul.mainmenu li {
|
||||
float: left;
|
||||
}
|
||||
|
||||
ul.mainmenu li a {
|
||||
display: block;
|
||||
color: white;
|
||||
text-align: center;
|
||||
padding: 14px 16px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
ul.mainmenu li a:hover {
|
||||
background-color: #111111;
|
||||
}
|
||||
|
||||
|
||||
86
apps/aqhome-cgi/service/0BUILD
Normal file
86
apps/aqhome-cgi/service/0BUILD
Normal file
@@ -0,0 +1,86 @@
|
||||
<?xml?>
|
||||
|
||||
<gwbuild>
|
||||
|
||||
<target type="ConvenienceLibrary" name="aqhcgi_service" >
|
||||
|
||||
<includes type="c" >
|
||||
$(gwenhywfar_cflags)
|
||||
-I$(topsrcdir)
|
||||
-I$(topbuilddir)
|
||||
-I$(topsrcdir)/apps
|
||||
-I$(topbuilddir)/apps
|
||||
-I$(builddir)
|
||||
-I$(srcdir)
|
||||
</includes>
|
||||
|
||||
<includes type="tm2" >
|
||||
--include=$(builddir)
|
||||
--include=$(srcdir)
|
||||
</includes>
|
||||
|
||||
|
||||
<define name="not_BUILDING_AQHOME" />
|
||||
|
||||
<setVar name="local/cflags">$(visibility_cflags)</setVar>
|
||||
|
||||
|
||||
<setVar name="tm2flags-INACTIVE" >
|
||||
--api=AQHOME_API
|
||||
</setVar>
|
||||
|
||||
<setVar name="local/typefiles" >
|
||||
module.t2d
|
||||
moduleperms.t2d
|
||||
role.t2d
|
||||
user.t2d
|
||||
session.t2d
|
||||
permdef.t2d
|
||||
</setVar>
|
||||
|
||||
<setVar name="local/built_sources" >
|
||||
</setVar>
|
||||
|
||||
<setVar name="local/built_headers_pub">
|
||||
</setVar>
|
||||
|
||||
|
||||
<setVar name="local/built_headers_priv" >
|
||||
</setVar>
|
||||
|
||||
|
||||
<headers dist="false" install="$(pkgincludedir)/service" >
|
||||
$(local/built_headers_pub)
|
||||
</headers>
|
||||
|
||||
|
||||
<headers dist="true" install="$(pkgincludedir)/service" >
|
||||
service.h
|
||||
</headers>
|
||||
|
||||
|
||||
<headers dist="true" >
|
||||
service_p.h
|
||||
</headers>
|
||||
|
||||
|
||||
<sources>
|
||||
$(local/typefiles)
|
||||
|
||||
service.c
|
||||
</sources>
|
||||
|
||||
|
||||
<extradist>
|
||||
</extradist>
|
||||
|
||||
|
||||
<useTargets>
|
||||
</useTargets>
|
||||
|
||||
<subdirs>
|
||||
</subdirs>
|
||||
|
||||
</target>
|
||||
|
||||
</gwbuild>
|
||||
20
apps/aqhome-cgi/service/README
Normal file
20
apps/aqhome-cgi/service/README
Normal file
@@ -0,0 +1,20 @@
|
||||
|
||||
|
||||
- service:
|
||||
- userList
|
||||
- rootModule
|
||||
- sessionList
|
||||
|
||||
- user:
|
||||
- modulePerms
|
||||
|
||||
- module:
|
||||
- roleList
|
||||
- permDefList
|
||||
|
||||
- session
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
103
apps/aqhome-cgi/service/module.t2d
Normal file
103
apps/aqhome-cgi/service/module.t2d
Normal file
@@ -0,0 +1,103 @@
|
||||
<?xml?>
|
||||
|
||||
<tm2>
|
||||
<type id="AQH_MODULE" type="pointer">
|
||||
<descr>
|
||||
</descr>
|
||||
<lang id="c">
|
||||
<identifier>AQH_MODULE</identifier>
|
||||
<prefix>AQH_Module</prefix>
|
||||
<baseFileName>module</baseFileName>
|
||||
|
||||
<flags>
|
||||
with_inherit
|
||||
with_xml
|
||||
with_db
|
||||
with_list1
|
||||
with_list2
|
||||
with_tree2
|
||||
nodup
|
||||
nocopy
|
||||
</flags>
|
||||
|
||||
<headers>
|
||||
<header type="sys" loc="pre">aqhome/api.h</header>
|
||||
<header type="sys" loc="pre">gwenhywfar/error.h</header>
|
||||
<header type="sys" loc="post">aqhome-cgi/service/role.h</header>
|
||||
<header type="sys" loc="post">aqhome-cgi/service/permdef.h</header>
|
||||
</headers>
|
||||
|
||||
<inlines>
|
||||
</inlines>
|
||||
|
||||
</lang>
|
||||
|
||||
<defines>
|
||||
<define id="AQH_MODULE_FLAGS" prefix="AQH_MODULE_FLAGS_">
|
||||
<item name="ACTIVE" value="0x00000001" />
|
||||
</define>
|
||||
|
||||
</defines>
|
||||
|
||||
|
||||
<members>
|
||||
|
||||
<member name="id" type="uint32_t" maxlen="4">
|
||||
<default>0</default>
|
||||
<preset>0</preset>
|
||||
<access>public</access>
|
||||
<flags>with_getbymember sortbymember</flags>
|
||||
</member>
|
||||
|
||||
<member name="flags" type="uint32_t" maxlen="4">
|
||||
<default>0</default>
|
||||
<preset>0</preset>
|
||||
<access>public</access>
|
||||
<flags>with_flags</flags>
|
||||
</member>
|
||||
|
||||
<member name="name" type="char_ptr" maxlen="16">
|
||||
<default>0</default>
|
||||
<preset>0</preset>
|
||||
<access>public</access>
|
||||
<flags>own with_getbymember sortbymember</flags>
|
||||
</member>
|
||||
|
||||
<member name="descr" type="char_ptr" maxlen="256">
|
||||
<default>0</default>
|
||||
<preset>0</preset>
|
||||
<access>public</access>
|
||||
<flags>own</flags>
|
||||
</member>
|
||||
|
||||
<member name="guestPerms" type="uint32_t" maxlen="4">
|
||||
<default>0</default>
|
||||
<preset>0</preset>
|
||||
<access>public</access>
|
||||
<flags></flags>
|
||||
</member>
|
||||
|
||||
<member name="roleList" type="AQH_ROLE_LIST" elementName="role" >
|
||||
<default>NULL</default>
|
||||
<preset>NULL</preset>
|
||||
<access>public</access>
|
||||
<flags>own</flags>
|
||||
<getflags>none</getflags>
|
||||
<setflags>none</setflags>
|
||||
</member>
|
||||
|
||||
<member name="permDefList" type="AQH_PERMDEF_LIST" elementName="permdef" >
|
||||
<default>NULL</default>
|
||||
<preset>NULL</preset>
|
||||
<access>public</access>
|
||||
<flags>own</flags>
|
||||
<getflags>none</getflags>
|
||||
<setflags>none</setflags>
|
||||
</member>
|
||||
|
||||
</members>
|
||||
|
||||
</type>
|
||||
|
||||
</tm2>
|
||||
|
||||
67
apps/aqhome-cgi/service/moduleperms.t2d
Normal file
67
apps/aqhome-cgi/service/moduleperms.t2d
Normal file
@@ -0,0 +1,67 @@
|
||||
<?xml?>
|
||||
|
||||
<tm2>
|
||||
<type id="AQH_MODULE_PERMS" type="pointer">
|
||||
<descr>
|
||||
</descr>
|
||||
<lang id="c">
|
||||
<identifier>AQH_MODULE_PERMS</identifier>
|
||||
<prefix>AQH_ModulePerms</prefix>
|
||||
<baseFileName>moduleperms</baseFileName>
|
||||
|
||||
<flags>
|
||||
with_inherit
|
||||
with_xml
|
||||
with_db
|
||||
with_list1
|
||||
with_list2
|
||||
</flags>
|
||||
|
||||
<headers>
|
||||
<header type="sys" loc="pre">aqhome/api.h</header>
|
||||
<header type="sys" loc="pre">gwenhywfar/error.h</header>
|
||||
<header type="sys" loc="post">aqhome-cgi/service/role.h</header>
|
||||
</headers>
|
||||
|
||||
<inlines>
|
||||
</inlines>
|
||||
|
||||
</lang>
|
||||
|
||||
|
||||
<members>
|
||||
|
||||
<member name="moduleId" type="char_ptr" maxlen="256">
|
||||
<default>0</default>
|
||||
<preset>0</preset>
|
||||
<access>public</access>
|
||||
<flags>with_getbymember sortbymember</flags>
|
||||
</member>
|
||||
|
||||
<member name="explAddPerms" type="uint32_t" maxlen="4">
|
||||
<default>0</default>
|
||||
<preset>0</preset>
|
||||
<access>public</access>
|
||||
<flags></flags>
|
||||
</member>
|
||||
|
||||
<member name="explDelPerms" type="uint32_t" maxlen="4">
|
||||
<default>0</default>
|
||||
<preset>0</preset>
|
||||
<access>public</access>
|
||||
<flags></flags>
|
||||
</member>
|
||||
|
||||
<member name="roleArray" type="uint8_t_array" maxlen="16">
|
||||
<default>0</default>
|
||||
<preset>0</preset>
|
||||
<access>public</access>
|
||||
<flags></flags>
|
||||
</member>
|
||||
|
||||
</members>
|
||||
|
||||
</type>
|
||||
|
||||
</tm2>
|
||||
|
||||
79
apps/aqhome-cgi/service/role.t2d
Normal file
79
apps/aqhome-cgi/service/role.t2d
Normal file
@@ -0,0 +1,79 @@
|
||||
<?xml?>
|
||||
|
||||
<tm2>
|
||||
<type id="AQH_ROLE" type="pointer">
|
||||
<descr>
|
||||
</descr>
|
||||
<lang id="c">
|
||||
<identifier>AQH_ROLE</identifier>
|
||||
<prefix>AQH_Role</prefix>
|
||||
<baseFileName>role</baseFileName>
|
||||
|
||||
<flags>
|
||||
with_xml
|
||||
with_db
|
||||
with_list1
|
||||
with_list2
|
||||
</flags>
|
||||
|
||||
<headers>
|
||||
<header type="sys" loc="pre">aqhome/api.h</header>
|
||||
<header type="sys" loc="pre">gwenhywfar/error.h</header>
|
||||
</headers>
|
||||
|
||||
<inlines>
|
||||
</inlines>
|
||||
|
||||
</lang>
|
||||
|
||||
|
||||
<members>
|
||||
|
||||
<member name="id" type="uint8_t" maxlen="1">
|
||||
<default>0</default>
|
||||
<preset>0</preset>
|
||||
<access>public</access>
|
||||
<flags>with_getbymember</flags>
|
||||
</member>
|
||||
|
||||
<member name="name" type="char_ptr" maxlen="16">
|
||||
<default>0</default>
|
||||
<preset>0</preset>
|
||||
<access>public</access>
|
||||
<flags>own</flags>
|
||||
</member>
|
||||
|
||||
<member name="descr" type="char_ptr" maxlen="256">
|
||||
<default>0</default>
|
||||
<preset>0</preset>
|
||||
<access>public</access>
|
||||
<flags>own</flags>
|
||||
</member>
|
||||
|
||||
<member name="perms" type="uint32_t" maxlen="4">
|
||||
<default>0</default>
|
||||
<preset>0</preset>
|
||||
<access>public</access>
|
||||
<flags></flags>
|
||||
</member>
|
||||
|
||||
<member name="explAddPerms" type="uint32_t" maxlen="4">
|
||||
<default>0</default>
|
||||
<preset>0</preset>
|
||||
<access>public</access>
|
||||
<flags></flags>
|
||||
</member>
|
||||
|
||||
<member name="explDelPerms" type="uint32_t" maxlen="4">
|
||||
<default>0</default>
|
||||
<preset>0</preset>
|
||||
<access>public</access>
|
||||
<flags></flags>
|
||||
</member>
|
||||
|
||||
</members>
|
||||
|
||||
</type>
|
||||
|
||||
</tm2>
|
||||
|
||||
414
apps/aqhome-cgi/service/service.c
Normal file
414
apps/aqhome-cgi/service/service.c
Normal file
@@ -0,0 +1,414 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
//#define DISABLE_DEBUGLOG
|
||||
|
||||
|
||||
#include "aqhome-cgi/service/service_p.h"
|
||||
|
||||
#include <gwenhywfar/stringlist.h>
|
||||
#include <gwenhywfar/text.h>
|
||||
#include <gwenhywfar/debug.h>
|
||||
|
||||
|
||||
|
||||
GWEN_INHERIT_FUNCTIONS(AQH_SERVICE);
|
||||
GWEN_LIST_FUNCTIONS(AQH_SERVICE, AQH_Service);
|
||||
|
||||
|
||||
|
||||
|
||||
AQH_SERVICE *AQH_Service_new(const char *baseFolder, const char *baseUrl)
|
||||
{
|
||||
AQH_SERVICE *sv;
|
||||
|
||||
GWEN_NEW_OBJECT(AQH_SERVICE, sv);
|
||||
GWEN_INHERIT_INIT(AQH_SERVICE, sv);
|
||||
GWEN_LIST_INIT(AQH_SERVICE, sv);
|
||||
|
||||
sv->baseUrl=baseUrl?strdup(baseUrl):NULL;
|
||||
sv->baseFolder=baseFolder?strdup(baseFolder):NULL;
|
||||
|
||||
if (sv->baseFolder) {
|
||||
GWEN_BUFFER *dbuf;
|
||||
uint32_t pos;
|
||||
|
||||
dbuf=GWEN_Buffer_new(0, 256, 0, 1);
|
||||
GWEN_Buffer_AppendArgs(dbuf, "%s%s", sv->baseFolder, GWEN_DIR_SEPARATOR_S);
|
||||
pos=GWEN_Buffer_GetPos(dbuf);
|
||||
|
||||
/* data folder */
|
||||
GWEN_Buffer_AppendString(dbuf, "data");
|
||||
sv->runtimeFolder=strdup(GWEN_Buffer_GetStart(dbuf));
|
||||
DBG_ERROR(NULL, "Runtime folder: %s", GWEN_Buffer_GetStart(dbuf));
|
||||
GWEN_Buffer_Crop(dbuf, 0, pos);
|
||||
|
||||
/* cache folder */
|
||||
GWEN_Buffer_AppendString(dbuf, "cache");
|
||||
sv->cacheFolder=strdup(GWEN_Buffer_GetStart(dbuf));
|
||||
DBG_ERROR(NULL, "Cache folder: %s", GWEN_Buffer_GetStart(dbuf));
|
||||
GWEN_Buffer_Crop(dbuf, 0, pos);
|
||||
|
||||
GWEN_Buffer_free(dbuf);
|
||||
}
|
||||
|
||||
return sv;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQH_Service_free(AQH_SERVICE *sv)
|
||||
{
|
||||
if (sv) {
|
||||
GWEN_LIST_FINI(AQH_SERVICE, sv);
|
||||
GWEN_INHERIT_FINI(AQH_SERVICE, sv);
|
||||
|
||||
free(sv->baseUrl);
|
||||
free(sv->baseFolder);
|
||||
free(sv->runtimeFolder);
|
||||
free(sv->cacheFolder);
|
||||
GWEN_FREE_OBJECT(sv);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char *AQH_Service_GetBaseUrl(const AQH_SERVICE *sv)
|
||||
{
|
||||
return sv?sv->baseUrl:NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char *AQH_Service_GetBaseFolder(const AQH_SERVICE *sv)
|
||||
{
|
||||
return sv?sv->baseFolder:NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char *AQH_Service_GetRuntimeFolder(const AQH_SERVICE *sv)
|
||||
{
|
||||
return sv?sv->runtimeFolder:NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char *AQH_Service_GetCacheFolder(const AQH_SERVICE *sv)
|
||||
{
|
||||
return sv?sv->cacheFolder:NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#if 0
|
||||
AQH_MODULE *AQH_Service_GetModuleByPath(const AQH_SERVICE *sv, const char *s)
|
||||
{
|
||||
if (sv && s && *s) {
|
||||
GWEN_STRINGLIST *sl;
|
||||
|
||||
sl=GWEN_StringList_fromString2(s, "/", 0,
|
||||
GWEN_TEXT_FLAGS_DEL_QUOTES |
|
||||
GWEN_TEXT_FLAGS_DEL_LEADING_BLANKS |
|
||||
GWEN_TEXT_FLAGS_DEL_MULTIPLE_BLANKS |
|
||||
GWEN_TEXT_FLAGS_DEL_TRAILING_BLANKS);
|
||||
if (sl) {
|
||||
GWEN_STRINGLISTENTRY *se;
|
||||
AQH_MODULE *m;
|
||||
|
||||
m=sv->rootModule;
|
||||
se=GWEN_StringList_FirstEntry(sl);
|
||||
while(se && m) {
|
||||
const char *sWantedName;
|
||||
|
||||
sWantedName=GWEN_StringListEntry_Data(se);
|
||||
if (sWantedName && *sWantedName) {
|
||||
AQH_MODULE *mTemp;
|
||||
|
||||
mTemp=AQH_Module_Tree2_GetFirstChild(m);
|
||||
while(mTemp) {
|
||||
const char *sModName;
|
||||
|
||||
sModName=AQH_Module_GetName(mTemp);
|
||||
if (sModName && *sModName && 0==strcasecmp(sModName, sWantedName))
|
||||
break;
|
||||
mTemp=AQH_Module_Tree2_GetNext(mTemp);
|
||||
}
|
||||
if (mTemp==NULL) {
|
||||
DBG_ERROR(NULL, "Module \%s\" not found", sWantedName);
|
||||
GWEN_StringList_free(sl);
|
||||
return NULL;
|
||||
}
|
||||
m=mTemp;
|
||||
}
|
||||
else {
|
||||
DBG_ERROR(NULL, "Empty path element in \"%s\"", s);
|
||||
GWEN_StringList_free(sl);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
se=GWEN_StringListEntry_Next(se);
|
||||
} /* while(se && m) */
|
||||
GWEN_StringList_free(sl);
|
||||
return m;
|
||||
}
|
||||
else {
|
||||
DBG_ERROR(NULL, "Bad path \"%s\"", s);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
int AQH_Service_HandleRequest(AQH_SERVICE *sv, AQCGI_REQUEST *req)
|
||||
{
|
||||
return (sv && sv->handleRequestFn)?(sv->handleRequestFn(sv, req)):GWEN_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQH_USER *AQH_Service_LoadUser(AQH_SERVICE *sv, const char *s)
|
||||
{
|
||||
return (sv && sv->loadUserFn)?(sv->loadUserFn(sv, s)):NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int AQH_Service_SaveUser(AQH_SERVICE *sv, AQH_USER *user)
|
||||
{
|
||||
return (sv && sv->saveUserFn)?(sv->saveUserFn(sv, user)):GWEN_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int AQH_Service_AddUser(AQH_SERVICE *sv, AQH_USER *user)
|
||||
{
|
||||
return (sv && sv->addUserFn)?(sv->addUserFn(sv, user)):GWEN_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int AQH_Service_DelUser(AQH_SERVICE *sv, const char *s)
|
||||
{
|
||||
return (sv && sv->delUserFn)?(sv->delUserFn(sv, s)):GWEN_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
|
||||
GWEN_STRINGLIST *AQH_Service_ListUsers(AQH_SERVICE *sv)
|
||||
{
|
||||
return (sv && sv->listUsersFn)?(sv->listUsersFn(sv)):NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQH_MODULE *AQH_Service_LoadModule(AQH_SERVICE *sv, const char *s)
|
||||
{
|
||||
return (sv && sv->loadModuleFn)?(sv->loadModuleFn(sv, s)):NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int AQH_Service_SaveModule(AQH_SERVICE *sv, AQH_MODULE *module)
|
||||
{
|
||||
return (sv && sv->saveModuleFn)?(sv->saveModuleFn(sv, module)):GWEN_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int AQH_Service_AddModule(AQH_SERVICE *sv, AQH_MODULE *module)
|
||||
{
|
||||
return (sv && sv->addModuleFn)?(sv->addModuleFn(sv, module)):GWEN_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int AQH_Service_DelModule(AQH_SERVICE *sv, const char *s)
|
||||
{
|
||||
return (sv && sv->delModuleFn)?(sv->delModuleFn(sv, s)):GWEN_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
|
||||
GWEN_STRINGLIST *AQH_Service_ListModules(AQH_SERVICE *sv)
|
||||
{
|
||||
return (sv && sv->listModulesFn)?(sv->listModulesFn(sv)):NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQH_SESSION* AQH_Service_LoadSession(AQH_SERVICE *sv, const char *s)
|
||||
{
|
||||
return (sv && sv->loadSessionFn)?(sv->loadSessionFn(sv, s)):NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int AQH_Service_SaveSession(AQH_SERVICE *sv, AQH_SESSION *session)
|
||||
{
|
||||
return (sv && sv->saveSessionFn)?(sv->saveSessionFn(sv, session)):GWEN_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int AQH_Service_AddSession(AQH_SERVICE *sv, AQH_SESSION *session)
|
||||
{
|
||||
return (sv && sv->addSessionFn)?(sv->addSessionFn(sv, session)):GWEN_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int AQH_Service_DelSession(AQH_SERVICE *sv, const char *s)
|
||||
{
|
||||
return (sv && sv->delSessionFn)?(sv->delSessionFn(sv, s)):GWEN_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void AQH_Service_SetHandleRequestFn(AQH_SERVICE *sv, AQH_SERVICE_HANDLEREQUEST_FN f)
|
||||
{
|
||||
if (sv)
|
||||
sv->handleRequestFn=f;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQH_Service_SetLoadUserFn(AQH_SERVICE *sv, AQH_SERVICE_LOADUSER_FN f)
|
||||
{
|
||||
if (sv)
|
||||
sv->loadUserFn=f;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQH_Service_SetSaveUserFn(AQH_SERVICE *sv, AQH_SERVICE_SAVEUSER_FN f)
|
||||
{
|
||||
if (sv)
|
||||
sv->saveUserFn=f;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQH_Service_SetAddUserFn(AQH_SERVICE *sv, AQH_SERVICE_ADDUSER_FN f)
|
||||
{
|
||||
if (sv)
|
||||
sv->addUserFn=f;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQH_Service_SetDelUserFn(AQH_SERVICE *sv, AQH_SERVICE_DELUSER_FN f)
|
||||
{
|
||||
if (sv)
|
||||
sv->delUserFn=f;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQH_Service_SetListUsersFn(AQH_SERVICE *sv, AQH_SERVICE_LISTUSERS_FN f)
|
||||
{
|
||||
if (sv)
|
||||
sv->listUsersFn=f;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQH_Service_SetLoadModuleFn(AQH_SERVICE *sv, AQH_SERVICE_LOADMODULE_FN f)
|
||||
{
|
||||
if (sv)
|
||||
sv->loadModuleFn=f;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQH_Service_SetSaveModuleFn(AQH_SERVICE *sv, AQH_SERVICE_SAVEMODULE_FN f)
|
||||
{
|
||||
if (sv)
|
||||
sv->saveModuleFn=f;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQH_Service_SetAddModuleFn(AQH_SERVICE *sv, AQH_SERVICE_ADDMODULE_FN f)
|
||||
{
|
||||
if (sv)
|
||||
sv->addModuleFn=f;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQH_Service_SetDelModuleFn(AQH_SERVICE *sv, AQH_SERVICE_DELMODULE_FN f)
|
||||
{
|
||||
if (sv)
|
||||
sv->delModuleFn=f;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQH_Service_SetListModulesFn(AQH_SERVICE *sv, AQH_SERVICE_LISTMODULES_FN f)
|
||||
{
|
||||
if (sv)
|
||||
sv->listModulesFn=f;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQH_Service_SetLoadSessionFn(AQH_SERVICE *sv, AQH_SERVICE_LOADSESSION_FN f)
|
||||
{
|
||||
if (sv)
|
||||
sv->loadSessionFn=f;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQH_Service_SetSaveSessionFn(AQH_SERVICE *sv, AQH_SERVICE_SAVESESSION_FN f)
|
||||
{
|
||||
if (sv)
|
||||
sv->saveSessionFn=f;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQH_Service_SetAddSessionFn(AQH_SERVICE *sv, AQH_SERVICE_ADDSESSION_FN f)
|
||||
{
|
||||
if (sv)
|
||||
sv->addSessionFn=f;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQH_Service_SetDelSessionFn(AQH_SERVICE *sv, AQH_SERVICE_DELSESSION_FN f)
|
||||
{
|
||||
if (sv)
|
||||
sv->delSessionFn=f;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQH_Service_SetListSessionsFn(AQH_SERVICE *sv, AQH_SERVICE_LISTSESSIONS_FN f)
|
||||
{
|
||||
if (sv)
|
||||
sv->listSessionsFn=f;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
107
apps/aqhome-cgi/service/service.h
Normal file
107
apps/aqhome-cgi/service/service.h
Normal file
@@ -0,0 +1,107 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef AQHOME_SERVICE_H
|
||||
#define AQHOME_SERVICE_H
|
||||
|
||||
|
||||
#include <aqhome/api.h>
|
||||
|
||||
#include <gwenhywfar/inherit.h>
|
||||
#include <gwenhywfar/list.h>
|
||||
#include <gwenhywfar/stringlist.h>
|
||||
|
||||
|
||||
typedef struct AQH_SERVICE AQH_SERVICE;
|
||||
GWEN_INHERIT_FUNCTION_DEFS(AQH_SERVICE);
|
||||
GWEN_LIST_FUNCTION_DEFS(AQH_SERVICE, AQH_Service);
|
||||
|
||||
|
||||
#include "aqhome-cgi/service/user.h"
|
||||
#include "aqhome-cgi/service/module.h"
|
||||
#include "aqhome-cgi/service/session.h"
|
||||
|
||||
#include <aqcgi/cgi.h>
|
||||
|
||||
|
||||
typedef int (*AQH_SERVICE_HANDLEREQUEST_FN)(AQH_SERVICE *sv, AQCGI_REQUEST *req);
|
||||
|
||||
typedef AQH_USER* (*AQH_SERVICE_LOADUSER_FN)(AQH_SERVICE *sv, const char *s);
|
||||
typedef int (*AQH_SERVICE_SAVEUSER_FN)(AQH_SERVICE *sv, AQH_USER *user);
|
||||
typedef int (*AQH_SERVICE_ADDUSER_FN)(AQH_SERVICE *sv, AQH_USER *user);
|
||||
typedef int (*AQH_SERVICE_DELUSER_FN)(AQH_SERVICE *sv, const char *s);
|
||||
typedef GWEN_STRINGLIST* (*AQH_SERVICE_LISTUSERS_FN)(AQH_SERVICE *sv);
|
||||
|
||||
typedef AQH_MODULE* (*AQH_SERVICE_LOADMODULE_FN)(AQH_SERVICE *sv, const char *s);
|
||||
typedef int (*AQH_SERVICE_SAVEMODULE_FN)(AQH_SERVICE *sv, AQH_MODULE *module);
|
||||
typedef int (*AQH_SERVICE_ADDMODULE_FN)(AQH_SERVICE *sv, AQH_MODULE *module);
|
||||
typedef int (*AQH_SERVICE_DELMODULE_FN)(AQH_SERVICE *sv, const char *s);
|
||||
typedef GWEN_STRINGLIST* (*AQH_SERVICE_LISTMODULES_FN)(AQH_SERVICE *sv);
|
||||
|
||||
|
||||
typedef AQH_SESSION* (*AQH_SERVICE_LOADSESSION_FN)(AQH_SERVICE *sv, const char *s);
|
||||
typedef int (*AQH_SERVICE_SAVESESSION_FN)(AQH_SERVICE *sv, AQH_SESSION *session);
|
||||
typedef int (*AQH_SERVICE_ADDSESSION_FN)(AQH_SERVICE *sv, AQH_SESSION *session);
|
||||
typedef int (*AQH_SERVICE_DELSESSION_FN)(AQH_SERVICE *sv, const char *s);
|
||||
typedef GWEN_STRINGLIST* (*AQH_SERVICE_LISTSESSIONS_FN)(AQH_SERVICE *sv);
|
||||
|
||||
|
||||
|
||||
AQH_SERVICE *AQH_Service_new(const char *baseFolder, const char *baseUrl);
|
||||
void AQH_Service_free(AQH_SERVICE *sv);
|
||||
|
||||
const char *AQH_Service_GetBaseUrl(const AQH_SERVICE *sv);
|
||||
const char *AQH_Service_GetBaseFolder(const AQH_SERVICE *sv);
|
||||
const char *AQH_Service_GetRuntimeFolder(const AQH_SERVICE *sv);
|
||||
const char *AQH_Service_GetCacheFolder(const AQH_SERVICE *sv);
|
||||
|
||||
int AQH_Service_HandleRequest(AQH_SERVICE *sv, AQCGI_REQUEST *req);
|
||||
|
||||
AQH_USER *AQH_Service_LoadUser(AQH_SERVICE *sv, const char *s);
|
||||
int AQH_Service_SaveUser(AQH_SERVICE *sv, AQH_USER *user);
|
||||
int AQH_Service_AddUser(AQH_SERVICE *sv, AQH_USER *user);
|
||||
int AQH_Service_DelUser(AQH_SERVICE *sv, const char *s);
|
||||
GWEN_STRINGLIST *AQH_Service_ListUsers(AQH_SERVICE *sv);
|
||||
|
||||
AQH_MODULE *AQH_Service_LoadModule(AQH_SERVICE *sv, const char *s);
|
||||
int AQH_Service_SaveModule(AQH_SERVICE *sv, AQH_MODULE *module);
|
||||
int AQH_Service_AddModule(AQH_SERVICE *sv, AQH_MODULE *module);
|
||||
int AQH_Service_DelModule(AQH_SERVICE *sv, const char *s);
|
||||
GWEN_STRINGLIST *AQH_Service_ListModules(AQH_SERVICE *sv);
|
||||
|
||||
AQH_SESSION* AQH_Service_LoadSession(AQH_SERVICE *sv, const char *s);
|
||||
int AQH_Service_SaveSession(AQH_SERVICE *sv, AQH_SESSION *session);
|
||||
int AQH_Service_AddSession(AQH_SERVICE *sv, AQH_SESSION *session);
|
||||
int AQH_Service_DelSession(AQH_SERVICE *sv, const char *s);
|
||||
GWEN_STRINGLIST *AQH_Service_ListSessions(AQH_SERVICE *sv);
|
||||
|
||||
|
||||
|
||||
void AQH_Service_SetHandleRequestFn(AQH_SERVICE *sv, AQH_SERVICE_HANDLEREQUEST_FN f);
|
||||
|
||||
void AQH_Service_SetLoadUserFn(AQH_SERVICE *sv, AQH_SERVICE_LOADUSER_FN f);
|
||||
void AQH_Service_SetSaveUserFn(AQH_SERVICE *sv, AQH_SERVICE_SAVEUSER_FN f);
|
||||
void AQH_Service_SetAddUserFn(AQH_SERVICE *sv, AQH_SERVICE_ADDUSER_FN f);
|
||||
void AQH_Service_SetDelUserFn(AQH_SERVICE *sv, AQH_SERVICE_DELUSER_FN f);
|
||||
void AQH_Service_SetListUsersFn(AQH_SERVICE *sv, AQH_SERVICE_LISTUSERS_FN f);
|
||||
|
||||
void AQH_Service_SetLoadModuleFn(AQH_SERVICE *sv, AQH_SERVICE_LOADMODULE_FN f);
|
||||
void AQH_Service_SetSaveModuleFn(AQH_SERVICE *sv, AQH_SERVICE_SAVEMODULE_FN f);
|
||||
void AQH_Service_SetAddModuleFn(AQH_SERVICE *sv, AQH_SERVICE_ADDMODULE_FN f);
|
||||
void AQH_Service_SetDelModuleFn(AQH_SERVICE *sv, AQH_SERVICE_DELMODULE_FN f);
|
||||
void AQH_Service_SetListModulesFn(AQH_SERVICE *sv, AQH_SERVICE_LISTMODULES_FN f);
|
||||
|
||||
void AQH_Service_SetLoadSessionFn(AQH_SERVICE *sv, AQH_SERVICE_LOADSESSION_FN f);
|
||||
void AQH_Service_SetSaveSessionFn(AQH_SERVICE *sv, AQH_SERVICE_SAVESESSION_FN f);
|
||||
void AQH_Service_SetAddSessionFn(AQH_SERVICE *sv, AQH_SERVICE_ADDSESSION_FN f);
|
||||
void AQH_Service_SetDelSessionFn(AQH_SERVICE *sv, AQH_SERVICE_DELSESSION_FN f);
|
||||
void AQH_Service_SetListSessionsFn(AQH_SERVICE *sv, AQH_SERVICE_LISTSESSIONS_FN f);
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
50
apps/aqhome-cgi/service/service_p.h
Normal file
50
apps/aqhome-cgi/service/service_p.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2023 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef AQHOME_SERVICE_P_H
|
||||
#define AQHOME_SERVICE_P_H
|
||||
|
||||
|
||||
#include "aqhome-cgi/service/service.h"
|
||||
|
||||
|
||||
struct AQH_SERVICE {
|
||||
GWEN_INHERIT_ELEMENT(AQH_SERVICE);
|
||||
GWEN_LIST_ELEMENT(AQH_SERVICE);
|
||||
|
||||
char *baseUrl;
|
||||
char *baseFolder;
|
||||
char *runtimeFolder;
|
||||
char *cacheFolder;
|
||||
|
||||
AQH_SERVICE_HANDLEREQUEST_FN handleRequestFn;
|
||||
|
||||
AQH_SERVICE_LOADUSER_FN loadUserFn;
|
||||
AQH_SERVICE_SAVEUSER_FN saveUserFn;
|
||||
AQH_SERVICE_ADDUSER_FN addUserFn;
|
||||
AQH_SERVICE_DELUSER_FN delUserFn;
|
||||
AQH_SERVICE_LISTUSERS_FN listUsersFn;
|
||||
|
||||
AQH_SERVICE_LOADMODULE_FN loadModuleFn;
|
||||
AQH_SERVICE_SAVEMODULE_FN saveModuleFn;
|
||||
AQH_SERVICE_ADDMODULE_FN addModuleFn;
|
||||
AQH_SERVICE_DELMODULE_FN delModuleFn;
|
||||
AQH_SERVICE_LISTMODULES_FN listModulesFn;
|
||||
|
||||
AQH_SERVICE_LOADSESSION_FN loadSessionFn;
|
||||
AQH_SERVICE_SAVESESSION_FN saveSessionFn;
|
||||
AQH_SERVICE_ADDSESSION_FN addSessionFn;
|
||||
AQH_SERVICE_DELSESSION_FN delSessionFn;
|
||||
AQH_SERVICE_LISTSESSIONS_FN listSessionsFn;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
117
apps/aqhome-cgi/service/session.t2d
Normal file
117
apps/aqhome-cgi/service/session.t2d
Normal file
@@ -0,0 +1,117 @@
|
||||
<?xml?>
|
||||
|
||||
<tm2>
|
||||
<type id="AQH_SESSION" type="pointer">
|
||||
<descr>
|
||||
</descr>
|
||||
<lang id="c">
|
||||
<identifier>AQH_SESSION</identifier>
|
||||
<prefix>AQH_Session</prefix>
|
||||
<baseFileName>session</baseFileName>
|
||||
|
||||
<flags>
|
||||
with_xml
|
||||
with_db
|
||||
with_list1
|
||||
with_list2
|
||||
nodup
|
||||
nocopy
|
||||
</flags>
|
||||
|
||||
<headers>
|
||||
<header type="sys" loc="pre">aqhome/api.h</header>
|
||||
<header type="sys" loc="pre">gwenhywfar/error.h</header>
|
||||
<header type="sys" loc="pre">gwenhywfar/timestamp.h</header>
|
||||
<header type="sys" loc="post">aqhome-cgi/service/user.h</header>
|
||||
</headers>
|
||||
|
||||
<inlines>
|
||||
</inlines>
|
||||
|
||||
</lang>
|
||||
|
||||
|
||||
|
||||
<defines>
|
||||
<define id="AQH_SESSION_RTFLAGS" prefix="AQH_SESSION_RTFLAGS_">
|
||||
<item name="MODIFIED" value="0x00000001" />
|
||||
</define>
|
||||
</defines>
|
||||
|
||||
|
||||
<members>
|
||||
|
||||
<member name="uid" type="char_ptr" maxlen="64">
|
||||
<default>0</default>
|
||||
<preset>0</preset>
|
||||
<access>public</access>
|
||||
<flags>own with_getbymember</flags>
|
||||
</member>
|
||||
|
||||
<member name="flags" type="uint32_t" maxlen="4">
|
||||
<default>0</default>
|
||||
<preset>0</preset>
|
||||
<access>public</access>
|
||||
<flags>with_flags</flags>
|
||||
</member>
|
||||
|
||||
<member name="userAlias" type="char_ptr" maxlen="64">
|
||||
<default>NULL</default>
|
||||
<preset>NULL</preset>
|
||||
<access>public</access>
|
||||
<flags>own</flags>
|
||||
</member>
|
||||
|
||||
<member name="state" type="int" maxlen="4">
|
||||
<default>0</default>
|
||||
<preset>0</preset>
|
||||
<access>public</access>
|
||||
<flags></flags>
|
||||
</member>
|
||||
|
||||
<member name="tempToken" type="char_ptr" maxlen="64">
|
||||
<default>0</default>
|
||||
<preset>0</preset>
|
||||
<access>public</access>
|
||||
<flags>own</flags>
|
||||
</member>
|
||||
|
||||
<member name="timestampCreation" type="gwen_timestamp" maxlen="8">
|
||||
<default>NULL</default>
|
||||
<preset>NULL</preset>
|
||||
<access>public</access>
|
||||
<flags>own</flags>
|
||||
</member>
|
||||
|
||||
<member name="timestampLastAccess" type="gwen_timestamp" maxlen="8">
|
||||
<default>NULL</default>
|
||||
<preset>NULL</preset>
|
||||
<access>public</access>
|
||||
<flags>own</flags>
|
||||
</member>
|
||||
|
||||
|
||||
<member name="user" type="AQH_USER">
|
||||
<default>NULL</default>
|
||||
<preset>NULL</preset>
|
||||
<access>public</access>
|
||||
<setflags>assign</setflags>
|
||||
<getflags>none</getflags>
|
||||
<flags>volatile nodup nocopy</flags>
|
||||
</member>
|
||||
|
||||
|
||||
|
||||
<member name="runtimeFlags" type="uint32_t" maxlen="4">
|
||||
<default>0</default>
|
||||
<preset>0</preset>
|
||||
<access>public</access>
|
||||
<flags>with_flags volatile</flags>
|
||||
</member>
|
||||
|
||||
</members>
|
||||
|
||||
</type>
|
||||
|
||||
</tm2>
|
||||
|
||||
164
apps/aqhome-cgi/service/user.t2d
Normal file
164
apps/aqhome-cgi/service/user.t2d
Normal file
@@ -0,0 +1,164 @@
|
||||
<?xml?>
|
||||
|
||||
<tm2>
|
||||
<type id="AQH_USER" type="pointer">
|
||||
<descr>
|
||||
</descr>
|
||||
<lang id="c">
|
||||
<identifier>AQH_USER</identifier>
|
||||
<prefix>AQH_User</prefix>
|
||||
<baseFileName>user</baseFileName>
|
||||
|
||||
<flags>
|
||||
with_xml
|
||||
with_db
|
||||
with_list1
|
||||
with_list2
|
||||
with_refcount
|
||||
nodup
|
||||
nocopy
|
||||
</flags>
|
||||
|
||||
<headers>
|
||||
<header type="sys" loc="pre">aqhome/api.h</header>
|
||||
<header type="sys" loc="pre">gwenhywfar/error.h</header>
|
||||
<header type="sys" loc="pre">gwenhywfar/timestamp.h</header>
|
||||
<header type="sys" loc="post">aqhome-cgi/service/moduleperms.h</header>
|
||||
</headers>
|
||||
|
||||
<inlines>
|
||||
</inlines>
|
||||
|
||||
</lang>
|
||||
|
||||
<defines>
|
||||
<define id="AQH_USER_FLAGS" prefix="AQH_USER_FLAGS_">
|
||||
<item name="ADMIN" value="0x00000001" />
|
||||
</define>
|
||||
|
||||
<define id="AQH_USER_RTFLAGS" prefix="AQH_USER_RTFLAGS_">
|
||||
<item name="MODIFIED" value="0x00000001" />
|
||||
<item name="PERMSCALC" value="0x00000002" />
|
||||
</define>
|
||||
|
||||
</defines>
|
||||
|
||||
<enums>
|
||||
|
||||
<enum id="AQH_USER_STATE" prefix="AQH_UserState_">
|
||||
<item name="suspended">
|
||||
<descr>User suspended</descr>
|
||||
</item>
|
||||
|
||||
<item name="waitForConfirmation">
|
||||
<descr>Waiting for email confirmation</descr>
|
||||
</item>
|
||||
|
||||
<item name="waitForApproval">
|
||||
<descr>Waiting for approval by admin</descr>
|
||||
</item>
|
||||
|
||||
<item name="active">
|
||||
<descr>User active</descr>
|
||||
</item>
|
||||
|
||||
</enum>
|
||||
|
||||
</enums>
|
||||
|
||||
|
||||
<members>
|
||||
|
||||
<member name="id" type="uint32_t" maxlen="4">
|
||||
<default>0</default>
|
||||
<preset>0</preset>
|
||||
<access>public</access>
|
||||
<flags>with_getbymember sortbymember</flags>
|
||||
</member>
|
||||
|
||||
<member name="flags" type="uint32_t" maxlen="4">
|
||||
<default>0</default>
|
||||
<preset>0</preset>
|
||||
<access>public</access>
|
||||
<flags>with_flags</flags>
|
||||
</member>
|
||||
|
||||
<member name="state" type="int" maxlen="4">
|
||||
<default>0</default>
|
||||
<preset>0</preset>
|
||||
<access>public</access>
|
||||
<flags>sortbymember</flags>
|
||||
</member>
|
||||
|
||||
<member name="name" type="char_ptr" maxlen="16">
|
||||
<default>0</default>
|
||||
<preset>0</preset>
|
||||
<access>public</access>
|
||||
<flags>own sortbymember</flags>
|
||||
</member>
|
||||
|
||||
<member name="alias" type="char_ptr" maxlen="16">
|
||||
<default>0</default>
|
||||
<preset>0</preset>
|
||||
<access>public</access>
|
||||
<flags>own with_getbymember sortbymember</flags>
|
||||
</member>
|
||||
|
||||
<member name="hashedPassword" type="char_ptr" maxlen="128">
|
||||
<default>0</default>
|
||||
<preset>0</preset>
|
||||
<access>public</access>
|
||||
<flags>own</flags>
|
||||
</member>
|
||||
|
||||
<member name="email" type="char_ptr" maxlen="128">
|
||||
<default>0</default>
|
||||
<preset>0</preset>
|
||||
<access>public</access>
|
||||
<flags>own with_getbymember sortbymember</flags>
|
||||
</member>
|
||||
|
||||
<member name="notes" type="char_ptr" maxlen="256">
|
||||
<default>0</default>
|
||||
<preset>0</preset>
|
||||
<access>public</access>
|
||||
<flags>own</flags>
|
||||
</member>
|
||||
|
||||
<member name="timestampCreation" type="gwen_timestamp" maxlen="8">
|
||||
<default>NULL</default>
|
||||
<preset>NULL</preset>
|
||||
<access>public</access>
|
||||
<flags>own sortbymember</flags>
|
||||
</member>
|
||||
|
||||
<member name="timestampLastLogin" type="gwen_timestamp" maxlen="8">
|
||||
<default>NULL</default>
|
||||
<preset>NULL</preset>
|
||||
<access>public</access>
|
||||
<flags>own sortbymember</flags>
|
||||
</member>
|
||||
|
||||
<member name="modulePermList" type="AQH_MODULE_PERMS_LIST">
|
||||
<default>NULL</default>
|
||||
<preset>NULL</preset>
|
||||
<access>public</access>
|
||||
<getflags>none</getflags>
|
||||
<setflags>none</setflags>
|
||||
<flags>own</flags>
|
||||
</member>
|
||||
|
||||
|
||||
<member name="runtimeFlags" type="uint32_t" maxlen="4">
|
||||
<default>0</default>
|
||||
<preset>0</preset>
|
||||
<access>public</access>
|
||||
<flags>volatile with_flags</flags>
|
||||
</member>
|
||||
|
||||
</members>
|
||||
|
||||
</type>
|
||||
|
||||
</tm2>
|
||||
|
||||
612
apps/aqhome-cgi/service_file.c
Normal file
612
apps/aqhome-cgi/service_file.c
Normal file
@@ -0,0 +1,612 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
//#define DISABLE_DEBUGLOG
|
||||
|
||||
|
||||
#include "./service_file_p.h"
|
||||
|
||||
#include <gwenhywfar/misc.h>
|
||||
#include <gwenhywfar/debug.h>
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* defs and enums
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#define AQH_SERVICE_FILE_GROUP_USERS "users"
|
||||
#define AQH_SERVICE_FILE_GROUP_MODULES "modules"
|
||||
#define AQH_SERVICE_FILE_GROUP_SESSIONS "sessions"
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* global vars
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
GWEN_INHERIT(AQH_SERVICE, AQH_SERVICE_FILE)
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* forward declarations
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static void GWENHYWFAR_CB _freeData(void *bp, void *p);
|
||||
|
||||
static AQH_USER *_loadUser(AQH_SERVICE *sv, const char *s);
|
||||
static int _saveUser(AQH_SERVICE *sv, AQH_USER *user);
|
||||
static int _addUser(AQH_SERVICE *sv, AQH_USER *user);
|
||||
static int _delUser(AQH_SERVICE *sv, const char *s);
|
||||
static GWEN_STRINGLIST *_listUsers(AQH_SERVICE *sv);
|
||||
|
||||
static AQH_MODULE *_loadModule(AQH_SERVICE *sv, const char *s);
|
||||
static int _saveModule(AQH_SERVICE *sv, AQH_MODULE *module);
|
||||
static int _addModule(AQH_SERVICE *sv, AQH_MODULE *module);
|
||||
static int _delModule(AQH_SERVICE *sv, const char *s);
|
||||
static GWEN_STRINGLIST *_listModules(AQH_SERVICE *sv);
|
||||
|
||||
static AQH_SESSION* _loadSession(AQH_SERVICE *sv, const char *s);
|
||||
static int _saveSession(AQH_SERVICE *sv, AQH_SESSION *session);
|
||||
static int _addSession(AQH_SERVICE *sv, AQH_SESSION *session);
|
||||
static int _delSession(AQH_SERVICE *sv, const char *s);
|
||||
static GWEN_STRINGLIST *_listSessions(AQH_SERVICE *sv);
|
||||
|
||||
static GWEN_DB_NODE *_loadGroupLocked(AQH_SERVICE *sv, const char *groupName, const char *subGroupName);
|
||||
static int _saveGroupLocked(AQH_SERVICE *sv, const char *groupName, const char *subGroupName, GWEN_DB_NODE *db);
|
||||
static int _addGroupLocked(AQH_SERVICE *sv, const char *groupName, const char *subGroupName, GWEN_DB_NODE *db);
|
||||
static int _deleteGroup(AQH_SERVICE *sv, const char *groupName, const char *subGroupName);
|
||||
static GWEN_STRINGLIST *_listGroup(AQH_SERVICE *sv, const char *groupName);
|
||||
|
||||
//static void _logGroup(const char *groupName, const char *subGroupName, GWEN_DB_NODE *db);
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* code
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
AQH_SERVICE *AQH_ServiceFiles_new(const char *baseFolder, const char *baseUrl)
|
||||
{
|
||||
AQH_SERVICE *sv;
|
||||
AQH_SERVICE_FILE *xs;
|
||||
GWEN_BUFFER *dbuf;
|
||||
|
||||
sv=AQH_Service_new(baseFolder, baseUrl);
|
||||
GWEN_NEW_OBJECT(AQH_SERVICE_FILE, xs);
|
||||
GWEN_INHERIT_SETDATA(AQH_SERVICE, AQH_SERVICE_FILE, sv, xs, _freeData);
|
||||
|
||||
AQH_Service_SetLoadUserFn(sv, _loadUser);
|
||||
AQH_Service_SetSaveUserFn(sv, _saveUser);
|
||||
AQH_Service_SetAddUserFn(sv, _addUser);
|
||||
AQH_Service_SetDelUserFn(sv, _delUser);
|
||||
AQH_Service_SetListUsersFn(sv, _listUsers);
|
||||
|
||||
AQH_Service_SetLoadModuleFn(sv, _loadModule);
|
||||
AQH_Service_SetSaveModuleFn(sv, _saveModule);
|
||||
AQH_Service_SetAddModuleFn(sv, _addModule);
|
||||
AQH_Service_SetDelModuleFn(sv, _delModule);
|
||||
AQH_Service_SetListModulesFn(sv, _listModules);
|
||||
|
||||
AQH_Service_SetLoadSessionFn(sv, _loadSession);
|
||||
AQH_Service_SetSaveSessionFn(sv, _saveSession);
|
||||
AQH_Service_SetAddSessionFn(sv, _addSession);
|
||||
AQH_Service_SetDelSessionFn(sv, _delSession);
|
||||
AQH_Service_SetListSessionsFn(sv, _listSessions);
|
||||
|
||||
dbuf=GWEN_Buffer_new(0, 256, 0, 1);
|
||||
GWEN_Buffer_AppendArgs(dbuf, "dir://%s", AQH_Service_GetRuntimeFolder(sv));
|
||||
DBG_ERROR(NULL, "Creating config mgr \"%s\"", GWEN_Buffer_GetStart(dbuf));
|
||||
xs->configMgr=GWEN_ConfigMgr_Factory(GWEN_Buffer_GetStart(dbuf));
|
||||
if (xs->configMgr==NULL) {
|
||||
DBG_ERROR(NULL, "Error creating config mgr \"%s\"", GWEN_Buffer_GetStart(dbuf));
|
||||
GWEN_Buffer_free(dbuf);
|
||||
AQH_Service_free(sv);
|
||||
return NULL;
|
||||
}
|
||||
GWEN_Buffer_free(dbuf);
|
||||
|
||||
return sv;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void GWENHYWFAR_CB _freeData(GWEN_UNUSED void *bp, void *p)
|
||||
{
|
||||
AQH_SERVICE_FILE *xs;
|
||||
|
||||
xs=(AQH_SERVICE_FILE*) p;
|
||||
GWEN_ConfigMgr_free(xs->configMgr);
|
||||
GWEN_FREE_OBJECT(xs);
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQH_USER *_loadUser(AQH_SERVICE *sv, const char *s)
|
||||
{
|
||||
GWEN_DB_NODE *db;
|
||||
|
||||
db=_loadGroupLocked(sv, AQH_SERVICE_FILE_GROUP_USERS, s);
|
||||
if (db) {
|
||||
AQH_USER *user;
|
||||
|
||||
user=AQH_User_fromDb(db);
|
||||
GWEN_DB_Group_free(db);
|
||||
return user;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _saveUser(AQH_SERVICE *sv, AQH_USER *user)
|
||||
{
|
||||
const char *s;
|
||||
|
||||
s=AQH_User_GetAlias(user);
|
||||
if (s && *s) {
|
||||
GWEN_DB_NODE *db;
|
||||
int rv;
|
||||
|
||||
db=GWEN_DB_Group_new(s);
|
||||
rv=AQH_User_toDb(user, db);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "here (%d)", rv);
|
||||
GWEN_DB_Group_free(db);
|
||||
return rv;
|
||||
}
|
||||
|
||||
//_logGroup(AQH_SERVICE_FILE_GROUP_USERS, s, db);
|
||||
|
||||
rv=_saveGroupLocked(sv, AQH_SERVICE_FILE_GROUP_USERS, s, db);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "here (%d)", rv);
|
||||
GWEN_DB_Group_free(db);
|
||||
return rv;
|
||||
}
|
||||
GWEN_DB_Group_free(db);
|
||||
return 0;
|
||||
}
|
||||
return GWEN_ERROR_INVALID;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _addUser(AQH_SERVICE *sv, AQH_USER *user)
|
||||
{
|
||||
const char *s;
|
||||
|
||||
s=AQH_User_GetAlias(user);
|
||||
if (s && *s) {
|
||||
GWEN_DB_NODE *db;
|
||||
int rv;
|
||||
|
||||
db=GWEN_DB_Group_new(s);
|
||||
rv=AQH_User_toDb(user, db);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "here (%d)", rv);
|
||||
GWEN_DB_Group_free(db);
|
||||
return rv;
|
||||
}
|
||||
rv=_addGroupLocked(sv, AQH_SERVICE_FILE_GROUP_USERS, s, db);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "here (%d)", rv);
|
||||
GWEN_DB_Group_free(db);
|
||||
return rv;
|
||||
}
|
||||
GWEN_DB_Group_free(db);
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
DBG_ERROR(NULL, "Missing alias");
|
||||
}
|
||||
return GWEN_ERROR_INVALID;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _delUser(AQH_SERVICE *sv, const char *s)
|
||||
{
|
||||
return _deleteGroup(sv, AQH_SERVICE_FILE_GROUP_USERS, s);
|
||||
}
|
||||
|
||||
|
||||
|
||||
GWEN_STRINGLIST *_listUsers(AQH_SERVICE *sv)
|
||||
{
|
||||
return _listGroup(sv, AQH_SERVICE_FILE_GROUP_USERS);
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQH_MODULE *_loadModule(AQH_SERVICE *sv, const char *s)
|
||||
{
|
||||
GWEN_DB_NODE *db;
|
||||
|
||||
db=_loadGroupLocked(sv, AQH_SERVICE_FILE_GROUP_MODULES, s);
|
||||
if (db) {
|
||||
AQH_MODULE *module;
|
||||
|
||||
module=AQH_Module_fromDb(db);
|
||||
GWEN_DB_Group_free(db);
|
||||
return module;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _saveModule(AQH_SERVICE *sv, AQH_MODULE *module)
|
||||
{
|
||||
const char *s;
|
||||
|
||||
s=AQH_Module_GetName(module);
|
||||
if (s && *s) {
|
||||
GWEN_DB_NODE *db;
|
||||
int rv;
|
||||
|
||||
db=GWEN_DB_Group_new(s);
|
||||
rv=AQH_Module_toDb(module, db);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "here (%d)", rv);
|
||||
GWEN_DB_Group_free(db);
|
||||
return rv;
|
||||
}
|
||||
rv=_saveGroupLocked(sv, AQH_SERVICE_FILE_GROUP_MODULES, s, db);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "here (%d)", rv);
|
||||
GWEN_DB_Group_free(db);
|
||||
return rv;
|
||||
}
|
||||
GWEN_DB_Group_free(db);
|
||||
return 0;
|
||||
}
|
||||
return GWEN_ERROR_INVALID;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _addModule(AQH_SERVICE *sv, AQH_MODULE *module)
|
||||
{
|
||||
const char *s;
|
||||
|
||||
s=AQH_Module_GetName(module);
|
||||
if (s && *s) {
|
||||
GWEN_DB_NODE *db;
|
||||
int rv;
|
||||
|
||||
db=GWEN_DB_Group_new(s);
|
||||
rv=AQH_Module_toDb(module, db);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "here (%d)", rv);
|
||||
GWEN_DB_Group_free(db);
|
||||
return rv;
|
||||
}
|
||||
rv=_addGroupLocked(sv, AQH_SERVICE_FILE_GROUP_MODULES, s, db);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "here (%d)", rv);
|
||||
GWEN_DB_Group_free(db);
|
||||
return rv;
|
||||
}
|
||||
GWEN_DB_Group_free(db);
|
||||
return 0;
|
||||
}
|
||||
return GWEN_ERROR_INVALID;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _delModule(AQH_SERVICE *sv, const char *s)
|
||||
{
|
||||
return _deleteGroup(sv, AQH_SERVICE_FILE_GROUP_MODULES, s);
|
||||
}
|
||||
|
||||
|
||||
|
||||
GWEN_STRINGLIST *_listModules(AQH_SERVICE *sv)
|
||||
{
|
||||
return _listGroup(sv, AQH_SERVICE_FILE_GROUP_MODULES);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
AQH_SESSION* _loadSession(AQH_SERVICE *sv, const char *s)
|
||||
{
|
||||
GWEN_DB_NODE *db;
|
||||
|
||||
db=_loadGroupLocked(sv, AQH_SERVICE_FILE_GROUP_SESSIONS, s);
|
||||
if (db) {
|
||||
AQH_SESSION *session;
|
||||
|
||||
session=AQH_Session_fromDb(db);
|
||||
GWEN_DB_Group_free(db);
|
||||
return session;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _saveSession(AQH_SERVICE *sv, AQH_SESSION *session)
|
||||
{
|
||||
const char *s;
|
||||
|
||||
s=AQH_Session_GetUid(session);
|
||||
if (s && *s) {
|
||||
GWEN_DB_NODE *db;
|
||||
int rv;
|
||||
|
||||
db=GWEN_DB_Group_new(s);
|
||||
rv=AQH_Session_toDb(session, db);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "here (%d)", rv);
|
||||
GWEN_DB_Group_free(db);
|
||||
return rv;
|
||||
}
|
||||
rv=_saveGroupLocked(sv, AQH_SERVICE_FILE_GROUP_SESSIONS, s, db);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "here (%d)", rv);
|
||||
GWEN_DB_Group_free(db);
|
||||
return rv;
|
||||
}
|
||||
GWEN_DB_Group_free(db);
|
||||
return 0;
|
||||
}
|
||||
return GWEN_ERROR_INVALID;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _addSession(AQH_SERVICE *sv, AQH_SESSION *session)
|
||||
{
|
||||
const char *s;
|
||||
|
||||
s=AQH_Session_GetUid(session);
|
||||
if (s && *s) {
|
||||
GWEN_DB_NODE *db;
|
||||
int rv;
|
||||
|
||||
db=GWEN_DB_Group_new(s);
|
||||
rv=AQH_Session_toDb(session, db);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "here (%d)", rv);
|
||||
GWEN_DB_Group_free(db);
|
||||
return rv;
|
||||
}
|
||||
rv=_addGroupLocked(sv, AQH_SERVICE_FILE_GROUP_SESSIONS, s, db);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "here (%d)", rv);
|
||||
GWEN_DB_Group_free(db);
|
||||
return rv;
|
||||
}
|
||||
GWEN_DB_Group_free(db);
|
||||
return 0;
|
||||
}
|
||||
return GWEN_ERROR_INVALID;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _delSession(AQH_SERVICE *sv, const char *s)
|
||||
{
|
||||
return _deleteGroup(sv, AQH_SERVICE_FILE_GROUP_SESSIONS, s);
|
||||
}
|
||||
|
||||
|
||||
|
||||
GWEN_STRINGLIST *_listSessions(AQH_SERVICE *sv)
|
||||
{
|
||||
return _listGroup(sv, AQH_SERVICE_FILE_GROUP_SESSIONS);
|
||||
}
|
||||
|
||||
|
||||
|
||||
GWEN_DB_NODE *_loadGroupLocked(AQH_SERVICE *sv, const char *groupName, const char *subGroupName)
|
||||
{
|
||||
DBG_ERROR(NULL, "Lock and load group %s/%s", groupName, subGroupName);
|
||||
if (sv && groupName && subGroupName) {
|
||||
AQH_SERVICE_FILE *xs;
|
||||
|
||||
xs=GWEN_INHERIT_GETDATA(AQH_SERVICE, AQH_SERVICE_FILE, sv);
|
||||
if (xs) {
|
||||
GWEN_DB_NODE *db=NULL;
|
||||
int rv;
|
||||
|
||||
DBG_ERROR(NULL, "Locking group %s/%s", groupName, subGroupName);
|
||||
rv=GWEN_ConfigMgr_LockGroup(xs->configMgr, groupName, subGroupName);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "Error locking group \"%s/%s\": %d", groupName, subGroupName, rv);
|
||||
return NULL;
|
||||
}
|
||||
DBG_ERROR(NULL, "Loading group %s/%s", groupName, subGroupName);
|
||||
rv=GWEN_ConfigMgr_GetGroup(xs->configMgr, groupName, subGroupName, &db);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "Error reading group \"%s/%s\": %d", groupName, subGroupName, rv);
|
||||
GWEN_ConfigMgr_UnlockGroup(xs->configMgr, groupName, subGroupName);
|
||||
return NULL;
|
||||
}
|
||||
DBG_ERROR(NULL, "Unlocking group %s/%s", groupName, subGroupName);
|
||||
rv=GWEN_ConfigMgr_UnlockGroup(xs->configMgr, groupName, subGroupName);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "Error unlocking group \"%s/%s\": %d", groupName, subGroupName, rv);
|
||||
GWEN_DB_Group_free(db);
|
||||
return NULL;
|
||||
}
|
||||
return db;
|
||||
}
|
||||
}
|
||||
else {
|
||||
DBG_ERROR(NULL, "Missing argument");
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _saveGroupLocked(AQH_SERVICE *sv, const char *groupName, const char *subGroupName, GWEN_DB_NODE *db)
|
||||
{
|
||||
if (sv && groupName && subGroupName && db) {
|
||||
AQH_SERVICE_FILE *xs;
|
||||
|
||||
xs=GWEN_INHERIT_GETDATA(AQH_SERVICE, AQH_SERVICE_FILE, sv);
|
||||
if (xs) {
|
||||
int rv;
|
||||
|
||||
DBG_ERROR(NULL, "Locking group %s/%s", groupName, subGroupName);
|
||||
rv=GWEN_ConfigMgr_LockGroup(xs->configMgr, groupName, subGroupName);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "Error locking group \"%s/%s\": %d", groupName, subGroupName, rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
DBG_ERROR(NULL, "Writing group %s/%s", groupName, subGroupName);
|
||||
rv=GWEN_ConfigMgr_SetGroup(xs->configMgr, groupName, subGroupName, db);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "Error writing group \"%s/%s\": %d", groupName, subGroupName, rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
DBG_ERROR(NULL, "Unlocking group %s/%s", groupName, subGroupName);
|
||||
rv=GWEN_ConfigMgr_UnlockGroup(xs->configMgr, groupName, subGroupName);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "Error unlocking group \"%s/%s\": %d", groupName, subGroupName, rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return GWEN_ERROR_INVALID;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _addGroupLocked(AQH_SERVICE *sv, const char *groupName, const char *subGroupName, GWEN_DB_NODE *db)
|
||||
{
|
||||
if (sv && groupName && subGroupName && db) {
|
||||
AQH_SERVICE_FILE *xs;
|
||||
|
||||
xs=GWEN_INHERIT_GETDATA(AQH_SERVICE, AQH_SERVICE_FILE, sv);
|
||||
if (xs) {
|
||||
int rv;
|
||||
|
||||
rv=GWEN_ConfigMgr_HasGroup(xs->configMgr, groupName, subGroupName);
|
||||
if (rv>=0) {
|
||||
DBG_ERROR(NULL, "Group \"%s/%s\" already exists", groupName, subGroupName);
|
||||
return GWEN_ERROR_FOUND;
|
||||
}
|
||||
|
||||
rv=GWEN_ConfigMgr_LockGroup(xs->configMgr, groupName, subGroupName);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "Error locking group \"%s/%s\": %d", groupName, subGroupName, rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv=GWEN_ConfigMgr_SetGroup(xs->configMgr, groupName, subGroupName, db);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "Error writing group \"%s/%s\": %d", groupName, subGroupName, rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv=GWEN_ConfigMgr_UnlockGroup(xs->configMgr, groupName, subGroupName);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "Error unlocking group \"%s/%s\": %d", groupName, subGroupName, rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return GWEN_ERROR_INVALID;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _deleteGroup(AQH_SERVICE *sv, const char *groupName, const char *subGroupName)
|
||||
{
|
||||
if (sv && groupName && subGroupName) {
|
||||
AQH_SERVICE_FILE *xs;
|
||||
|
||||
xs=GWEN_INHERIT_GETDATA(AQH_SERVICE, AQH_SERVICE_FILE, sv);
|
||||
if (xs) {
|
||||
int rv;
|
||||
|
||||
rv=GWEN_ConfigMgr_DeleteGroup(xs->configMgr, groupName, subGroupName);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "Error writing group \"%s/%s\": %d", groupName, subGroupName, rv);
|
||||
return rv;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return GWEN_ERROR_INVALID;
|
||||
}
|
||||
|
||||
|
||||
|
||||
GWEN_STRINGLIST *_listGroup(AQH_SERVICE *sv, const char *groupName)
|
||||
{
|
||||
if (sv && groupName) {
|
||||
AQH_SERVICE_FILE *xs;
|
||||
|
||||
xs=GWEN_INHERIT_GETDATA(AQH_SERVICE, AQH_SERVICE_FILE, sv);
|
||||
if (xs) {
|
||||
GWEN_STRINGLIST *sl;
|
||||
int rv;
|
||||
|
||||
sl=GWEN_StringList_new();
|
||||
rv=GWEN_ConfigMgr_ListSubGroups(xs->configMgr, groupName, sl);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "Error listing group \"%s\": %d", groupName, rv);
|
||||
GWEN_StringList_free(sl);
|
||||
return NULL;
|
||||
}
|
||||
if (GWEN_StringList_Count(sl)==0) {
|
||||
GWEN_StringList_free(sl);
|
||||
return NULL;
|
||||
}
|
||||
return sl;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#if 0
|
||||
void _logGroup(const char *groupName, const char *subGroupName, GWEN_DB_NODE *db)
|
||||
{
|
||||
if (db) {
|
||||
GWEN_BUFFER *dbuf;
|
||||
|
||||
dbuf=GWEN_Buffer_new(0, 256, 0, 1);
|
||||
GWEN_DB_WriteToBuffer(db, dbuf, GWEN_DB_FLAGS_DEFAULT);
|
||||
DBG_ERROR(NULL, "Group %s/%s:\n%s", groupName?groupName:"<empty>", subGroupName?subGroupName:"<empty>",
|
||||
GWEN_Buffer_GetStart(dbuf));
|
||||
GWEN_Buffer_free(dbuf);
|
||||
}
|
||||
else {
|
||||
DBG_ERROR(NULL, "Group %s/%s empty", groupName?groupName:"<empty>", subGroupName?subGroupName:"<empty>");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
21
apps/aqhome-cgi/service_file.h
Normal file
21
apps/aqhome-cgi/service_file.h
Normal file
@@ -0,0 +1,21 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef AQHOME_SERVICE_FILE_H
|
||||
#define AQHOME_SERVICE_FILE_H
|
||||
|
||||
|
||||
#include "aqhome-cgi/service/service.h"
|
||||
|
||||
|
||||
AQH_SERVICE *AQH_ServiceFiles_new(const char *baseFolder, const char *baseUrl);
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
27
apps/aqhome-cgi/service_file_p.h
Normal file
27
apps/aqhome-cgi/service_file_p.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef AQHOME_SERVICE_FILE_P_H
|
||||
#define AQHOME_SERVICE_FILE_P_H
|
||||
|
||||
|
||||
#include "aqhome-cgi/service_file.h"
|
||||
|
||||
#include <gwenhywfar/configmgr.h>
|
||||
|
||||
|
||||
|
||||
typedef struct AQH_SERVICE_FILE AQH_SERVICE_FILE;
|
||||
struct AQH_SERVICE_FILE {
|
||||
GWEN_CONFIGMGR *configMgr;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
@@ -35,40 +35,32 @@
|
||||
</setVar>
|
||||
|
||||
<headers dist="true" >
|
||||
aqhome_data.h
|
||||
aqhome_data_p.h
|
||||
fini.h
|
||||
init.h
|
||||
loop.h
|
||||
c_connect.h
|
||||
c_updatedata.h
|
||||
c_getvalues.h
|
||||
c_getdevices.h
|
||||
c_getdatapoints.h
|
||||
c_getlastdatapoint.h
|
||||
c_setdata.h
|
||||
c_addvalue.h
|
||||
c_annvalue.h
|
||||
c_moddevice.h
|
||||
server.h
|
||||
server_p.h
|
||||
s_connect.h
|
||||
s_getdevices.h
|
||||
s_getvalues.h
|
||||
s_addvalue.h
|
||||
s_annvalue.h
|
||||
s_updatedata.h
|
||||
s_setdata.h
|
||||
s_getdatapoints.h
|
||||
s_moddevice.h
|
||||
</headers>
|
||||
|
||||
<sources>
|
||||
$(local/typefiles)
|
||||
|
||||
aqhome_data.c
|
||||
fini.c
|
||||
init.c
|
||||
loop.c
|
||||
c_connect.c
|
||||
c_updatedata.c
|
||||
c_getvalues.c
|
||||
c_getdevices.c
|
||||
c_getdatapoints.c
|
||||
c_getlastdatapoint.c
|
||||
c_setdata.c
|
||||
c_addvalue.c
|
||||
c_annvalue.c
|
||||
c_moddevice.c
|
||||
server.c
|
||||
s_connect.c
|
||||
s_getdevices.c
|
||||
s_getvalues.c
|
||||
s_addvalue.c
|
||||
s_annvalue.c
|
||||
s_updatedata.c
|
||||
s_setdata.c
|
||||
s_getdatapoints.c
|
||||
s_moddevice.c
|
||||
main.c
|
||||
</sources>
|
||||
|
||||
|
||||
@@ -1,152 +0,0 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2023 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "./aqhome_data_p.h"
|
||||
#include "aqhome/ipc/endpoint_ipc.h"
|
||||
|
||||
#include <gwenhywfar/misc.h>
|
||||
#include <gwenhywfar/debug.h>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
AQHOME_DATA *AqHomeData_new()
|
||||
{
|
||||
AQHOME_DATA *aqh;
|
||||
|
||||
GWEN_NEW_OBJECT(AQHOME_DATA, aqh);
|
||||
aqh->storageMutex=GWEN_Mutex_new();
|
||||
aqh->requestTree=GWEN_MsgRequest_new();
|
||||
|
||||
return aqh;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AqHomeData_free(AQHOME_DATA *aqh)
|
||||
{
|
||||
if (aqh) {
|
||||
GWEN_Mutex_free(aqh->storageMutex);
|
||||
|
||||
GWEN_MsgRequest_free(aqh->requestTree);
|
||||
GWEN_MsgEndpoint_free(aqh->ipcdEndpoint);
|
||||
GWEN_DB_Group_free(aqh->dbArgs);
|
||||
AQH_Storage_free(aqh->storage);
|
||||
free(aqh->pidFile);
|
||||
|
||||
GWEN_FREE_OBJECT(aqh);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
GWEN_MSG_ENDPOINT *AqHomeData_GetIpcdEndpoint(const AQHOME_DATA *aqh)
|
||||
{
|
||||
return aqh?(aqh->ipcdEndpoint):NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
GWEN_DB_NODE *AqHomeData_GetDbArgs(const AQHOME_DATA *aqh)
|
||||
{
|
||||
return aqh?(aqh->dbArgs):NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQH_STORAGE *AqHomeData_GetStorage(const AQHOME_DATA *aqh)
|
||||
{
|
||||
return aqh?(aqh->storage):NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
GWEN_MSG_REQUEST *AqHomeData_GetRequestTree(const AQHOME_DATA *aqh)
|
||||
{
|
||||
return aqh?aqh->requestTree:NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AqHomeData_AddRequestToTree(AQHOME_DATA *aqh, GWEN_MSG_REQUEST *rq)
|
||||
{
|
||||
if (aqh && rq)
|
||||
GWEN_MsgRequest_Tree2_AddChild(aqh->requestTree, rq);
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char *AqHomeData_GetPidFile(const AQHOME_DATA *aqh)
|
||||
{
|
||||
return aqh?aqh->pidFile:NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int AqHomeData_GetTimeout(const AQHOME_DATA *aqh)
|
||||
{
|
||||
return aqh?aqh->timeout:0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int AqHomeData_LockStorage(AQHOME_DATA *aqh)
|
||||
{
|
||||
int rv;
|
||||
|
||||
rv=GWEN_Mutex_Lock(aqh->storageMutex);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "Error obtaining lock on storage mutex");
|
||||
return rv;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int AqHomeData_UnlockStorage(AQHOME_DATA *aqh)
|
||||
{
|
||||
int rv;
|
||||
|
||||
rv=GWEN_Mutex_Unlock(aqh->storageMutex);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "Error releasing lock on storage mutex");
|
||||
return rv;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
|
||||
GWEN_MSG_ENDPOINT *AqHomeData_GetIpcEndpointByServiceName(const AQHOME_DATA *aqh, const char *serviceName)
|
||||
{
|
||||
GWEN_MSG_ENDPOINT *ep;
|
||||
|
||||
ep=GWEN_MsgEndpoint_Tree2_GetFirstChild(aqh->ipcdEndpoint);
|
||||
while(ep) {
|
||||
const char *s;
|
||||
|
||||
s=AQH_IpcEndpoint_GetServiceName(ep);
|
||||
if (s && *s && strcasecmp(s, serviceName)==0)
|
||||
return ep;
|
||||
ep=GWEN_MsgEndpoint_Tree2_GetNext(ep);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2023 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef AQHOME_DATA_H
|
||||
#define AQHOME_DATA_H
|
||||
|
||||
|
||||
#include "aqhome/data/storage.h"
|
||||
|
||||
#include <gwenhywfar/endpoint.h>
|
||||
#include <gwenhywfar/request.h>
|
||||
|
||||
|
||||
|
||||
typedef struct AQHOME_DATA AQHOME_DATA;
|
||||
|
||||
|
||||
AQHOME_DATA *AqHomeData_new();
|
||||
void AqHomeData_free(AQHOME_DATA *aqh);
|
||||
|
||||
GWEN_MSG_ENDPOINT *AqHomeData_GetIpcdEndpoint(const AQHOME_DATA *aqh);
|
||||
|
||||
GWEN_MSG_ENDPOINT *AqHomeData_GetIpcEndpointByServiceName(const AQHOME_DATA *aqh, const char *serviceName);
|
||||
|
||||
GWEN_DB_NODE *AqHomeData_GetDbArgs(const AQHOME_DATA *aqh);
|
||||
|
||||
AQH_STORAGE *AqHomeData_GetStorage(const AQHOME_DATA *aqh);
|
||||
|
||||
const char *AqHomeData_GetPidFile(const AQHOME_DATA *aqh);
|
||||
|
||||
int AqHomeData_GetTimeout(const AQHOME_DATA *aqh);
|
||||
|
||||
int AqHomeData_LockStorage(AQHOME_DATA *aqh);
|
||||
int AqHomeData_UnlockStorage(AQHOME_DATA *aqh);
|
||||
|
||||
GWEN_MSG_REQUEST *AqHomeData_GetRequestTree(const AQHOME_DATA *aqh);
|
||||
void AqHomeData_AddRequestToTree(AQHOME_DATA *aqh, GWEN_MSG_REQUEST *rq);
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2023 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef AQHOME_DATA_P_H
|
||||
#define AQHOME_DATA_P_H
|
||||
|
||||
|
||||
#include "./aqhome_data.h"
|
||||
|
||||
#include <gwenhywfar/mutex.h>
|
||||
|
||||
|
||||
#define AQHOME_DATA_DEFAULT_PIDFILE "/var/run/aqhome-data.pid"
|
||||
#define AQHOME_DATA_DEFAULT_DATADIR "/var/lib/aqhome-data/data"
|
||||
#define AQHOME_DATA_DEFAULT_IPC_PORT 45456
|
||||
|
||||
#define AQHOME_DATA_STATEFILENAME "statefile"
|
||||
|
||||
|
||||
|
||||
struct AQHOME_DATA {
|
||||
GWEN_MSG_ENDPOINT *ipcdEndpoint;
|
||||
|
||||
GWEN_DB_NODE *dbArgs;
|
||||
|
||||
AQH_STORAGE *storage;
|
||||
|
||||
char *pidFile;
|
||||
|
||||
int timeout; /* timeout for run e.g. inside valgrind */
|
||||
|
||||
GWEN_MUTEX *storageMutex;
|
||||
|
||||
GWEN_MSG_REQUEST *requestTree;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2023 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "./c_addvalue.h"
|
||||
#include "./aqhome_data_p.h"
|
||||
#include "./loop.h"
|
||||
#include "aqhome/ipc/data/ipc_data.h"
|
||||
#include "aqhome/ipc/endpoint_ipc.h"
|
||||
#include "aqhome/ipc/msg_ipc_result.h"
|
||||
#include "aqhome/ipc/data/msg_data_values.h"
|
||||
#include "aqhome/ipc/msg_ipc_tag16.h"
|
||||
|
||||
#include <gwenhywfar/debug.h>
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* defines
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* forward declarations
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* implementations
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void AqHomeData_HandleAddValue(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *ep, GWEN_MSG *msg)
|
||||
{
|
||||
GWEN_MSG *outMsg;
|
||||
int resultCode=AQH_MSG_IPC_SUCCESS;
|
||||
AQH_VALUE *recvdValue;
|
||||
|
||||
AQH_ValuesDataIpcMsg_Parse(msg, 0);
|
||||
recvdValue=AQH_ValuesDataIpcMsg_ReadFirstValue(msg);
|
||||
if (recvdValue) {
|
||||
AQH_VALUE *value;
|
||||
|
||||
value=AqHomeData_GetOrCreateValueForDriverWithTemplate(aqh, ep, recvdValue);
|
||||
if (value==NULL)
|
||||
resultCode=AQH_MSG_IPC_ERROR_PERMS;
|
||||
AQH_Value_free(recvdValue);
|
||||
}
|
||||
|
||||
outMsg=AQH_ResultIpcMsg_new(AQH_MSGTYPE_IPC_DATA_RESULT,
|
||||
GWEN_MsgEndpoint_GetNextMessageId(ep), GWEN_IpcMsg_GetMsgId(msg),
|
||||
resultCode);
|
||||
GWEN_MsgEndpoint_AddSendMessage(ep, outMsg);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2023 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef AQHOME_DATA_C_ADDVALUE_H
|
||||
#define AQHOME_DATA_C_ADDVALUE_H
|
||||
|
||||
|
||||
#include "./aqhome_data.h"
|
||||
|
||||
|
||||
void AqHomeData_HandleAddValue(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *ep, GWEN_MSG *msg);
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2024 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "./c_annvalue.h"
|
||||
#include "./aqhome_data_p.h"
|
||||
#include "./loop.h"
|
||||
#include "aqhome/ipc/data/ipc_data.h"
|
||||
#include "aqhome/ipc/endpoint_ipc.h"
|
||||
#include "aqhome/ipc/data/msg_data_values.h"
|
||||
#include "aqhome/ipc/msg_ipc_tag16.h"
|
||||
|
||||
#include <gwenhywfar/debug.h>
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* defines
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* forward declarations
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* implementations
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void AqHomeData_HandleAnnounceValue(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *ep, GWEN_MSG *msg)
|
||||
{
|
||||
AQH_VALUE *recvdValue;
|
||||
|
||||
AQH_ValuesDataIpcMsg_Parse(msg, 0);
|
||||
recvdValue=AQH_ValuesDataIpcMsg_ReadFirstValue(msg);
|
||||
if (recvdValue) {
|
||||
AQH_VALUE *value;
|
||||
|
||||
value=AqHomeData_GetOrCreateValueForDriverWithTemplate(aqh, ep, recvdValue);
|
||||
if (value==NULL) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "Could not create announced value");
|
||||
}
|
||||
AQH_Value_free(recvdValue);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2024 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef AQHOME_DATA_C_ANNVALUE_H
|
||||
#define AQHOME_DATA_C_ANNVALUE_H
|
||||
|
||||
|
||||
#include "./aqhome_data.h"
|
||||
|
||||
|
||||
void AqHomeData_HandleAnnounceValue(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *ep, GWEN_MSG *msg);
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,93 +0,0 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2023 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "./c_connect.h"
|
||||
#include "./aqhome_data_p.h"
|
||||
#include "aqhome/ipc/data/ipc_data.h"
|
||||
#include "aqhome/ipc/endpoint_ipc.h"
|
||||
#include "aqhome/ipc/msg_ipc_result.h"
|
||||
#include "aqhome/ipc/data/msg_data_connect.h"
|
||||
#include "aqhome/ipc/msg_ipc_tag16.h"
|
||||
|
||||
#include <gwenhywfar/debug.h>
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* defines
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* forward declarations
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* implementations
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void AqHomeData_HandleConnect(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *ep, GWEN_MSG *msg)
|
||||
{
|
||||
GWEN_MSG *outMsg;
|
||||
int resultCode=AQH_MSG_IPC_SUCCESS;
|
||||
char *clientId=NULL;
|
||||
char *userId=NULL;
|
||||
char *passw=NULL;
|
||||
uint32_t flags;
|
||||
|
||||
AQH_ConnectDataIpcMsg_Parse(msg, 0);
|
||||
clientId=AQH_Tag16IpcMsg_GetTagDataAsNewString(msg, AQH_MSGDATA_CONNECT_TAGS_CLIENTID, NULL);
|
||||
userId=AQH_Tag16IpcMsg_GetTagDataAsNewString(msg, AQH_MSGDATA_CONNECT_TAGS_USERID, NULL);
|
||||
flags=AQH_Tag16IpcMsg_GetTagDataAsUint32(msg, AQH_MSGDATA_CONNECT_TAGS_FLAGS, 0);
|
||||
passw=AQH_Tag16IpcMsg_GetTagDataAsNewString(msg, AQH_MSGDATA_CONNECT_TAGS_PASSWORD, NULL);
|
||||
|
||||
if (clientId)
|
||||
AQH_IpcEndpoint_SetServiceName(ep, clientId);
|
||||
if (userId)
|
||||
AQH_IpcEndpoint_SetUserName(ep, userId);
|
||||
|
||||
if (flags & AQH_MSGDATA_CONNECT_FLAGS_WANTUPDATES)
|
||||
GWEN_MsgEndpoint_AddFlags(ep, AQH_IPCENDPOINT_FLAGS_WANTUPDATES);
|
||||
|
||||
/* TODO: add user management, for now we allow all */
|
||||
AQH_IpcEndpoint_SetPermissions(ep,
|
||||
AQH_IPCENDPOINT_PERMS_LISTVALUES |
|
||||
AQH_IPCENDPOINT_PERMS_READVALUE |
|
||||
AQH_IPCENDPOINT_PERMS_ADDVALUE |
|
||||
AQH_IPCENDPOINT_PERMS_LISTDATA |
|
||||
AQH_IPCENDPOINT_PERMS_READDATA |
|
||||
AQH_IPCENDPOINT_PERMS_ADDDATA |
|
||||
AQH_IPCENDPOINT_PERMS_LISTDEVICES |
|
||||
AQH_IPCENDPOINT_PERMS_READDEVICE |
|
||||
AQH_IPCENDPOINT_PERMS_ADDDEVICE |
|
||||
AQH_IPCENDPOINT_PERMS_MODDEVICE);
|
||||
free(passw);
|
||||
free(userId);
|
||||
free(clientId);
|
||||
|
||||
outMsg=AQH_ResultIpcMsg_new(AQH_MSGTYPE_IPC_DATA_RESULT,
|
||||
GWEN_MsgEndpoint_GetNextMessageId(ep), GWEN_IpcMsg_GetMsgId(msg),
|
||||
resultCode);
|
||||
GWEN_MsgEndpoint_AddSendMessage(ep, outMsg);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2023 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef AQHOME_DATA_C_CONNECT_H
|
||||
#define AQHOME_DATA_C_CONNECT_H
|
||||
|
||||
|
||||
#include "./aqhome_data.h"
|
||||
|
||||
|
||||
void AqHomeData_HandleConnect(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *ep, GWEN_MSG *msg);
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,211 +0,0 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2023 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "./c_getdatapoints.h"
|
||||
#include "./aqhome_data_p.h"
|
||||
#include "aqhome/ipc/data/ipc_data.h"
|
||||
#include "aqhome/ipc/data/msg_data_multidata.h"
|
||||
#include "aqhome/ipc/data/msg_data_getdata.h"
|
||||
#include "aqhome/ipc/endpoint_ipc.h"
|
||||
#include "aqhome/ipc/msg_ipc_result.h"
|
||||
#include "aqhome/ipc/msg_ipc_tag16.h"
|
||||
|
||||
#include <gwenhywfar/debug.h>
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* defines
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#define AQHOMEDATA_HANDLEGETDATAPOINTS_MAXTABLEENTRIES 2048
|
||||
#define AQHOMEDATA_HANDLEGETDATAPOINTS_MAXDATAPOINTS 1024
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* forward declarations
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int _getAndSendDataPoints(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *ep,
|
||||
const AQH_VALUE *value,
|
||||
uint64_t tsBegin, uint64_t tsEnd, uint64_t num, uint32_t refMsgId);
|
||||
static int _getAndSendDataPointsNoNum(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *ep, const AQH_VALUE *value, uint64_t tsBegin, uint64_t tsEnd,
|
||||
uint32_t refMsgId);
|
||||
static int _getAndSendDataPointsWithNum(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *ep, const AQH_VALUE *value, uint64_t num, uint32_t refMsgId);
|
||||
static void _sendDataPointsResponse(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *ep, const AQH_VALUE *value, const uint64_t *tablePtr,
|
||||
uint32_t refMsgId);
|
||||
static void _getAndSendLastDatapoint(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *ep, const AQH_VALUE *value, uint32_t refMsgId);
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* implementations
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
void AqHomeData_HandleGetDataPoints(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *ep, GWEN_MSG *recvdMsg)
|
||||
{
|
||||
GWEN_MSG *outMsg;
|
||||
int resultCode=AQH_MSG_IPC_SUCCESS;
|
||||
|
||||
if (AQH_IpcEndpoint_GetPermissions(ep) & AQH_IPCENDPOINT_PERMS_READDATA) {
|
||||
AQH_VALUE *value;
|
||||
char *valueName;
|
||||
uint64_t tsBegin;
|
||||
uint64_t tsEnd;
|
||||
uint64_t numRequested;
|
||||
|
||||
AQH_GetDataDataIpcMsg_Parse(recvdMsg, 0);
|
||||
valueName=AQH_Tag16IpcMsg_GetTagDataAsNewString(recvdMsg, AQH_MSGDATA_GETDATA_TAGS_NAME, NULL);
|
||||
tsBegin=AQH_Tag16IpcMsg_GetTagDataAsUint64(recvdMsg, AQH_MSGDATA_GETDATA_TAGS_BEGIN, 0);
|
||||
tsEnd=AQH_Tag16IpcMsg_GetTagDataAsUint64(recvdMsg, AQH_MSGDATA_GETDATA_TAGS_END, 0);
|
||||
numRequested=AQH_Tag16IpcMsg_GetTagDataAsUint64(recvdMsg, AQH_MSGDATA_GETDATA_TAGS_NUM, 0);
|
||||
|
||||
value=AQH_Storage_GetValueByNameForSystem(aqh->storage, valueName);
|
||||
if (value) {
|
||||
resultCode=_getAndSendDataPoints(aqh, ep, value, tsBegin, tsEnd, numRequested, GWEN_IpcMsg_GetMsgId(recvdMsg));
|
||||
if (resultCode==AQH_MSG_IPC_SUCCESS)
|
||||
return;
|
||||
}
|
||||
else {
|
||||
DBG_INFO(NULL, "Value \"%s\" does not exist", valueName);
|
||||
resultCode=AQH_MSG_IPC_ERROR_NOTFOUND;
|
||||
}
|
||||
free(valueName);
|
||||
}
|
||||
else {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "No permissions to read data");
|
||||
resultCode=AQH_MSG_IPC_ERROR_PERMS;
|
||||
}
|
||||
|
||||
outMsg=AQH_ResultIpcMsg_new(AQH_MSGTYPE_IPC_DATA_RESULT,
|
||||
GWEN_MsgEndpoint_GetNextMessageId(ep), GWEN_IpcMsg_GetMsgId(recvdMsg),
|
||||
resultCode);
|
||||
GWEN_MsgEndpoint_AddSendMessage(ep, outMsg);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _getAndSendDataPoints(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *ep, const AQH_VALUE *value, uint64_t tsBegin, uint64_t tsEnd, uint64_t num,
|
||||
uint32_t refMsgId)
|
||||
{
|
||||
if (num==0)
|
||||
return _getAndSendDataPointsNoNum(aqh, ep, value, tsBegin, tsEnd, refMsgId);
|
||||
else if (num==1) {
|
||||
_getAndSendLastDatapoint(aqh, ep, value, refMsgId);
|
||||
return AQH_MSG_IPC_SUCCESS;
|
||||
}
|
||||
else
|
||||
return _getAndSendDataPointsWithNum(aqh, ep, value, num, refMsgId);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _getAndSendDataPointsNoNum(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *ep, const AQH_VALUE *value, uint64_t tsBegin, uint64_t tsEnd,
|
||||
uint32_t refMsgId)
|
||||
{
|
||||
uint64_t valueId;
|
||||
uint64_t *tablePtr;
|
||||
|
||||
valueId=AQH_Value_GetId(value);
|
||||
tablePtr=AQH_Storage_GetDataPoints(aqh->storage, valueId, tsBegin, tsEnd, AQHOMEDATA_HANDLEGETDATAPOINTS_MAXTABLEENTRIES);
|
||||
if (tablePtr) {
|
||||
_sendDataPointsResponse(aqh, ep, value, tablePtr, refMsgId);
|
||||
free(tablePtr);
|
||||
return AQH_MSG_IPC_SUCCESS;
|
||||
}
|
||||
else {
|
||||
DBG_INFO(NULL, "No matching datapoints for value \"%s\"", AQH_Value_GetNameForSystem(value));
|
||||
return AQH_MSG_IPC_ERROR_NODATA;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _getAndSendDataPointsWithNum(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *ep, const AQH_VALUE *value, uint64_t num, uint32_t refMsgId)
|
||||
{
|
||||
uint64_t valueId;
|
||||
uint64_t *tablePtr;
|
||||
|
||||
if (num>AQHOMEDATA_HANDLEGETDATAPOINTS_MAXDATAPOINTS)
|
||||
num=AQHOMEDATA_HANDLEGETDATAPOINTS_MAXDATAPOINTS;
|
||||
valueId=AQH_Value_GetId(value);
|
||||
tablePtr=AQH_Storage_GetLastNDataPoints(aqh->storage, valueId, num);
|
||||
if (tablePtr) {
|
||||
_sendDataPointsResponse(aqh, ep, value, tablePtr, refMsgId);
|
||||
free(tablePtr);
|
||||
return AQH_MSG_IPC_SUCCESS;
|
||||
}
|
||||
else {
|
||||
DBG_INFO(NULL, "No matching datapoints for value \"%s\"", AQH_Value_GetNameForSystem(value));
|
||||
return AQH_MSG_IPC_ERROR_NODATA;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _sendDataPointsResponse(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *ep, const AQH_VALUE *value, const uint64_t *tablePtr,
|
||||
uint32_t refMsgId)
|
||||
{
|
||||
int numTableEntries;
|
||||
int numDataPoints;
|
||||
GWEN_MSG *outMsg;
|
||||
|
||||
numTableEntries=(int)(tablePtr[0]);
|
||||
numDataPoints=numTableEntries/2;
|
||||
outMsg=AQH_MultiDataDataIpcMsg_new(AQH_MSGTYPE_IPC_DATA_GETDATA_RSP,
|
||||
GWEN_MsgEndpoint_GetNextMessageId(ep), refMsgId,
|
||||
value, &(tablePtr[1]), numDataPoints);
|
||||
GWEN_MsgEndpoint_AddSendMessage(ep, outMsg);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _getAndSendLastDatapoint(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *ep, const AQH_VALUE *value, uint32_t refMsgId)
|
||||
{
|
||||
GWEN_MSG *outMsg;
|
||||
int resultCode=AQH_MSG_IPC_SUCCESS;
|
||||
int rv;
|
||||
uint64_t timestamp=0;
|
||||
double data=0.0;
|
||||
|
||||
rv=AQH_Storage_GetLastDataPoint(aqh->storage, AQH_Value_GetId(value), ×tamp, &data);
|
||||
if (rv<0) {
|
||||
switch(rv) {
|
||||
case GWEN_ERROR_INVALID: resultCode=AQH_MSG_IPC_ERROR_INVALID; break;
|
||||
case GWEN_ERROR_NO_DATA: resultCode=AQH_MSG_IPC_ERROR_NODATA; break;
|
||||
default: resultCode=AQH_MSG_IPC_ERROR_GENERIC; break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
outMsg=AQH_MultiDataDataIpcMsg_newForOne(AQH_MSGTYPE_IPC_DATA_GETDATA_RSP,
|
||||
GWEN_MsgEndpoint_GetNextMessageId(ep), refMsgId,
|
||||
value, timestamp, data);
|
||||
GWEN_MsgEndpoint_AddSendMessage(ep, outMsg);
|
||||
return;
|
||||
}
|
||||
|
||||
outMsg=AQH_ResultIpcMsg_new(AQH_MSGTYPE_IPC_DATA_RESULT,
|
||||
GWEN_MsgEndpoint_GetNextMessageId(ep), refMsgId,
|
||||
resultCode);
|
||||
GWEN_MsgEndpoint_AddSendMessage(ep, outMsg);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2023 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef AQHOME_DATA_C_GETDATAPOINTS_H
|
||||
#define AQHOME_DATA_C_GETDATAPOINTS_H
|
||||
|
||||
|
||||
#include "./aqhome_data.h"
|
||||
|
||||
|
||||
void AqHomeData_HandleGetDataPoints(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *ep, GWEN_MSG *msg);
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,106 +0,0 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2023 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "./c_getdevices.h"
|
||||
#include "./aqhome_data_p.h"
|
||||
#include "aqhome/ipc/data/ipc_data.h"
|
||||
#include "aqhome/ipc/data/msg_data_devices.h"
|
||||
#include "aqhome/ipc/msg_ipc_result.h"
|
||||
|
||||
#include <gwenhywfar/debug.h>
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* defines
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#define AQHOMEDATA_DEVICESPERMSG 10
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* forward declarations
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static void _sendDeviceList(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *ep, const AQH_DEVICE_LIST *vl, uint32_t flags, uint32_t refMsgId);
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* implementations
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void AqHomeData_HandleGetDevices(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *ep, const GWEN_MSG *msg)
|
||||
{
|
||||
const AQH_DEVICE_LIST *origDeviceList;
|
||||
|
||||
DBG_INFO(NULL, "HandleGetDevices");
|
||||
origDeviceList=AQH_Storage_GetDeviceList(aqh->storage);
|
||||
if (origDeviceList) {
|
||||
DBG_INFO(NULL, "Have a list of %d devices", AQH_Device_List_GetCount(origDeviceList));
|
||||
if (AQH_Device_List_GetCount(origDeviceList)<AQHOMEDATA_DEVICESPERMSG) {
|
||||
DBG_INFO(NULL, "Sending all entries in one message");
|
||||
_sendDeviceList(aqh, ep, origDeviceList, AQH_MSGDATA_DEVICES_FLAGS_LASTMSG, GWEN_IpcMsg_GetMsgId(msg));
|
||||
}
|
||||
else {
|
||||
AQH_DEVICE_LIST *tmpDeviceList;
|
||||
const AQH_DEVICE *v;
|
||||
|
||||
DBG_INFO(NULL, "Sending entries in multiple messages");
|
||||
tmpDeviceList=AQH_Device_List_new();
|
||||
v=AQH_Device_List_First(origDeviceList);
|
||||
while(v) {
|
||||
const AQH_DEVICE *next;
|
||||
AQH_DEVICE *copyOfDevice;
|
||||
|
||||
next=AQH_Device_List_Next(v);
|
||||
copyOfDevice=AQH_Device_dup(v);
|
||||
AQH_Device_List_Add(copyOfDevice, tmpDeviceList);
|
||||
if (AQH_Device_List_GetCount(tmpDeviceList)>=AQHOMEDATA_DEVICESPERMSG) {
|
||||
DBG_INFO(NULL, "Sending %d devices", AQH_Device_List_GetCount(tmpDeviceList));
|
||||
_sendDeviceList(aqh, ep, tmpDeviceList, next?0:AQH_MSGDATA_DEVICES_FLAGS_LASTMSG, GWEN_IpcMsg_GetMsgId(msg));
|
||||
AQH_Device_List_Clear(tmpDeviceList);
|
||||
}
|
||||
v=next;
|
||||
}
|
||||
if (AQH_Device_List_GetCount(tmpDeviceList)) {
|
||||
DBG_INFO(NULL, "Sending %d devices", AQH_Device_List_GetCount(tmpDeviceList));
|
||||
_sendDeviceList(aqh, ep, tmpDeviceList, AQH_MSGDATA_DEVICES_FLAGS_LASTMSG, GWEN_IpcMsg_GetMsgId(msg)); /* send remaining */
|
||||
}
|
||||
AQH_Device_List_free(tmpDeviceList);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* empty list */
|
||||
_sendDeviceList(aqh, ep, NULL, AQH_MSGDATA_DEVICES_FLAGS_LASTMSG, GWEN_IpcMsg_GetMsgId(msg));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _sendDeviceList(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *ep, const AQH_DEVICE_LIST *vl, uint32_t flags, uint32_t refMsgId)
|
||||
{
|
||||
GWEN_MSG *msg;
|
||||
|
||||
msg=AQH_DevicesDataIpcMsg_new(AQH_MSGTYPE_IPC_DATA_GETDEVICES_RSP,
|
||||
GWEN_MsgEndpoint_GetNextMessageId(ep), refMsgId,
|
||||
flags, vl);
|
||||
GWEN_MsgEndpoint_AddSendMessage(ep, msg);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2023 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef AQHOME_DATA_C_GETDEVICES_H
|
||||
#define AQHOME_DATA_C_GETDEVICES_H
|
||||
|
||||
|
||||
#include "./aqhome_data.h"
|
||||
|
||||
|
||||
void AqHomeData_HandleGetDevices(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *ep, const GWEN_MSG *msg);
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,107 +0,0 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2023 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "./c_getlastdatapoint.h"
|
||||
#include "./aqhome_data_p.h"
|
||||
#include "aqhome/ipc/data/ipc_data.h"
|
||||
#include "aqhome/ipc/data/msg_data_getdata.h"
|
||||
#include "aqhome/ipc/data/msg_data_multidata.h"
|
||||
#include "aqhome/ipc/endpoint_ipc.h"
|
||||
#include "aqhome/ipc/msg_ipc_result.h"
|
||||
#include "aqhome/ipc/msg_ipc_tag16.h"
|
||||
|
||||
#include <gwenhywfar/debug.h>
|
||||
#include <gwenhywfar/text.h>
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* defines
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* forward declarations
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* implementations
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
void AqHomeData_HandleGetLastDataPoint(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *ep, GWEN_MSG *recvdMsg)
|
||||
{
|
||||
GWEN_MSG *outMsg;
|
||||
int resultCode=AQH_MSG_IPC_SUCCESS;
|
||||
|
||||
if (AQH_IpcEndpoint_GetPermissions(ep) & AQH_IPCENDPOINT_PERMS_READDATA) {
|
||||
char *valueName;
|
||||
|
||||
AQH_GetDataDataIpcMsg_Parse(recvdMsg, 0);
|
||||
valueName=AQH_Tag16IpcMsg_GetTagDataAsNewString(recvdMsg, AQH_MSGDATA_GETDATA_TAGS_NAME, NULL);
|
||||
if (valueName && *valueName) {
|
||||
const AQH_VALUE *storedValue;
|
||||
|
||||
storedValue=AQH_Storage_GetValueByNameForSystem(aqh->storage, valueName);
|
||||
if (storedValue) {
|
||||
uint64_t timestamp=0;
|
||||
double data=0.0;
|
||||
int rv;
|
||||
|
||||
rv=AQH_Storage_GetLastDataPoint(aqh->storage, AQH_Value_GetId(storedValue), ×tamp, &data);
|
||||
if (rv<0) {
|
||||
switch(rv) {
|
||||
case GWEN_ERROR_INVALID: resultCode=AQH_MSG_IPC_ERROR_INVALID; break;
|
||||
case GWEN_ERROR_NO_DATA: resultCode=AQH_MSG_IPC_ERROR_NODATA; break;
|
||||
default: resultCode=AQH_MSG_IPC_ERROR_GENERIC; break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
outMsg=AQH_MultiDataDataIpcMsg_newForOne(AQH_MSGTYPE_IPC_DATA_GETLASTDATA_RSP,
|
||||
GWEN_MsgEndpoint_GetNextMessageId(ep), GWEN_IpcMsg_GetMsgId(recvdMsg),
|
||||
storedValue, timestamp, data);
|
||||
GWEN_MsgEndpoint_AddSendMessage(ep, outMsg);
|
||||
free(valueName);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
DBG_INFO(NULL, "Value \"%s\" not found", valueName);
|
||||
resultCode=AQH_MSG_IPC_ERROR_NOTFOUND;
|
||||
}
|
||||
free(valueName);
|
||||
}
|
||||
else {
|
||||
DBG_INFO(NULL, "No name for value");
|
||||
resultCode=AQH_MSG_IPC_ERROR_NOTFOUND;
|
||||
}
|
||||
}
|
||||
else {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "No permissions to read data");
|
||||
resultCode=AQH_MSG_IPC_ERROR_PERMS;
|
||||
}
|
||||
|
||||
outMsg=AQH_ResultIpcMsg_new(AQH_MSGTYPE_IPC_DATA_RESULT,
|
||||
GWEN_MsgEndpoint_GetNextMessageId(ep), GWEN_IpcMsg_GetMsgId(recvdMsg),
|
||||
resultCode);
|
||||
GWEN_MsgEndpoint_AddSendMessage(ep, outMsg);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2023 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef AQHOME_DATA_C_GETLASTDATAPOINT_H
|
||||
#define AQHOME_DATA_C_GETLASTDATAPOINT_H
|
||||
|
||||
|
||||
#include "./aqhome_data.h"
|
||||
|
||||
|
||||
void AqHomeData_HandleGetLastDataPoint(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *ep, GWEN_MSG *msg);
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,106 +0,0 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2023 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "./c_getvalues.h"
|
||||
#include "./aqhome_data_p.h"
|
||||
#include "aqhome/ipc/data/ipc_data.h"
|
||||
#include "aqhome/ipc/data/msg_data_values.h"
|
||||
#include "aqhome/ipc/msg_ipc_result.h"
|
||||
|
||||
#include <gwenhywfar/debug.h>
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* defines
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#define AQHOMEDATA_VALUESPERMSG 10
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* forward declarations
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static void _sendValueList(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *ep, const AQH_VALUE_LIST *vl, uint32_t flags, uint32_t refMsgId);
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* implementations
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void AqHomeData_HandleGetValues(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *ep, const GWEN_MSG *msg)
|
||||
{
|
||||
const AQH_VALUE_LIST *origValueList;
|
||||
|
||||
DBG_INFO(NULL, "HandleGetValues");
|
||||
origValueList=AQH_Storage_GetValueList(aqh->storage);
|
||||
if (origValueList) {
|
||||
DBG_INFO(NULL, "Have a list of %d values", AQH_Value_List_GetCount(origValueList));
|
||||
if (AQH_Value_List_GetCount(origValueList)<AQHOMEDATA_VALUESPERMSG) {
|
||||
DBG_INFO(NULL, "Sending all entries in one message");
|
||||
_sendValueList(aqh, ep, origValueList, AQH_MSGDATA_VALUES_FLAGS_LASTMSG, GWEN_IpcMsg_GetMsgId(msg));
|
||||
}
|
||||
else {
|
||||
AQH_VALUE_LIST *tmpValueList;
|
||||
const AQH_VALUE *v;
|
||||
|
||||
DBG_INFO(NULL, "Sending entries in multiple messages");
|
||||
tmpValueList=AQH_Value_List_new();
|
||||
v=AQH_Value_List_First(origValueList);
|
||||
while(v) {
|
||||
const AQH_VALUE *next;
|
||||
AQH_VALUE *copyOfValue;
|
||||
|
||||
next=AQH_Value_List_Next(v);
|
||||
copyOfValue=AQH_Value_dup(v);
|
||||
AQH_Value_List_Add(copyOfValue, tmpValueList);
|
||||
if (AQH_Value_List_GetCount(tmpValueList)>=AQHOMEDATA_VALUESPERMSG) {
|
||||
DBG_INFO(NULL, "Sending %d values", AQH_Value_List_GetCount(tmpValueList));
|
||||
_sendValueList(aqh, ep, tmpValueList, next?0:AQH_MSGDATA_VALUES_FLAGS_LASTMSG, GWEN_IpcMsg_GetMsgId(msg));
|
||||
AQH_Value_List_Clear(tmpValueList);
|
||||
}
|
||||
v=next;
|
||||
}
|
||||
if (AQH_Value_List_GetCount(tmpValueList)) {
|
||||
DBG_INFO(NULL, "Sending %d values", AQH_Value_List_GetCount(tmpValueList));
|
||||
_sendValueList(aqh, ep, tmpValueList, AQH_MSGDATA_VALUES_FLAGS_LASTMSG, GWEN_IpcMsg_GetMsgId(msg)); /* send remaining */
|
||||
}
|
||||
AQH_Value_List_free(tmpValueList);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* empty list */
|
||||
_sendValueList(aqh, ep, NULL, AQH_MSGDATA_VALUES_FLAGS_LASTMSG, GWEN_IpcMsg_GetMsgId(msg));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _sendValueList(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *ep, const AQH_VALUE_LIST *vl, uint32_t flags, uint32_t refMsgId)
|
||||
{
|
||||
GWEN_MSG *msg;
|
||||
|
||||
msg=AQH_ValuesDataIpcMsg_new(AQH_MSGTYPE_IPC_DATA_GETVALUES_RSP,
|
||||
GWEN_MsgEndpoint_GetNextMessageId(ep), refMsgId,
|
||||
flags, vl);
|
||||
GWEN_MsgEndpoint_AddSendMessage(ep, msg);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2023 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef AQHOME_DATA_C_GETVALUES_H
|
||||
#define AQHOME_DATA_C_GETVALUES_H
|
||||
|
||||
|
||||
#include "./aqhome_data.h"
|
||||
|
||||
|
||||
void AqHomeData_HandleGetValues(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *ep, const GWEN_MSG *msg);
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,114 +0,0 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2023 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "./c_getlastdatapoint.h"
|
||||
#include "./aqhome_data_p.h"
|
||||
#include "aqhome/ipc/data/ipc_data.h"
|
||||
#include "aqhome/ipc/data/msg_data_devices.h"
|
||||
#include "aqhome/ipc/endpoint_ipc.h"
|
||||
#include "aqhome/ipc/msg_ipc_result.h"
|
||||
#include "aqhome/ipc/msg_ipc_tag16.h"
|
||||
|
||||
#include <gwenhywfar/debug.h>
|
||||
#include <gwenhywfar/text.h>
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* defines
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* forward declarations
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* implementations
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
void AqHomeData_HandleModDevice(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *ep, GWEN_MSG *recvdMsg)
|
||||
{
|
||||
GWEN_MSG *outMsg;
|
||||
int resultCode=AQH_MSG_IPC_SUCCESS;
|
||||
|
||||
if (AQH_IpcEndpoint_GetPermissions(ep) & AQH_IPCENDPOINT_PERMS_MODDEVICE) {
|
||||
AQH_DEVICE *device;
|
||||
|
||||
AQH_DevicesDataIpcMsg_Parse(recvdMsg, 0);
|
||||
device=AQH_DevicesDataIpcMsg_ReadFirstDevice(recvdMsg);
|
||||
if (device) {
|
||||
const char *deviceNameForSystem;
|
||||
|
||||
deviceNameForSystem=AQH_Device_GetNameForSystem(device);
|
||||
if (deviceNameForSystem && *deviceNameForSystem) {
|
||||
AQH_DEVICE *storedDevice;
|
||||
|
||||
storedDevice=AQH_Storage_GetDeviceByNameForSystem(aqh->storage, deviceNameForSystem);
|
||||
if (storedDevice) {
|
||||
const char *s;
|
||||
|
||||
s=AQH_Device_GetNameForGui(device);
|
||||
if (s && *s)
|
||||
AQH_Device_SetNameForGui(storedDevice, s);
|
||||
|
||||
s=AQH_Device_GetRoomName(device);
|
||||
if (s && *s)
|
||||
AQH_Device_SetRoomName(storedDevice, s);
|
||||
|
||||
s=AQH_Device_GetLocation(device);
|
||||
if (s && *s)
|
||||
AQH_Device_SetLocation(storedDevice, s);
|
||||
|
||||
s=AQH_Device_GetDescription(device);
|
||||
if (s && *s)
|
||||
AQH_Device_SetDescription(storedDevice, s);
|
||||
|
||||
AQH_Storage_AddRuntimeFlags(aqh->storage, AQH_STORAGE_RTFLAGS_MODIFIED);
|
||||
resultCode=AQH_MSG_IPC_SUCCESS;
|
||||
}
|
||||
else {
|
||||
DBG_INFO(NULL, "Device \"%s\" not found", deviceNameForSystem);
|
||||
resultCode=AQH_MSG_IPC_ERROR_NOTFOUND;
|
||||
}
|
||||
}
|
||||
else {
|
||||
DBG_INFO(NULL, "No name for value");
|
||||
resultCode=AQH_MSG_IPC_ERROR_NOTFOUND;
|
||||
}
|
||||
}
|
||||
else {
|
||||
DBG_INFO(NULL, "No device info in message");
|
||||
resultCode=AQH_MSG_IPC_ERROR_INVALID;
|
||||
}
|
||||
}
|
||||
else {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "No permissions to read data");
|
||||
resultCode=AQH_MSG_IPC_ERROR_PERMS;
|
||||
}
|
||||
|
||||
outMsg=AQH_ResultIpcMsg_new(AQH_MSGTYPE_IPC_DATA_RESULT,
|
||||
GWEN_MsgEndpoint_GetNextMessageId(ep), GWEN_IpcMsg_GetMsgId(recvdMsg),
|
||||
resultCode);
|
||||
GWEN_MsgEndpoint_AddSendMessage(ep, outMsg);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2023 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef AQHOME_DATA_C_MODDEVICE_H
|
||||
#define AQHOME_DATA_C_MODDEVICE_H
|
||||
|
||||
|
||||
#include "./aqhome_data.h"
|
||||
|
||||
|
||||
void AqHomeData_HandleModDevice(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *ep, GWEN_MSG *recvdMsg);
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,258 +0,0 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2023 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "./c_setdata.h"
|
||||
#include "./aqhome_data_p.h"
|
||||
#include "./loop.h"
|
||||
#include "aqhome/aqhome.h"
|
||||
#include "aqhome/ipc/requests.h"
|
||||
#include "aqhome/ipc/data/ipc_data.h"
|
||||
#include "aqhome/ipc/data/msg_data_set.h"
|
||||
#include "aqhome/ipc/endpoint_ipc.h"
|
||||
#include "aqhome/ipc/msg_ipc_result.h"
|
||||
#include "aqhome/ipc/msg_ipc_tag16.h"
|
||||
|
||||
#include <gwenhywfar/debug.h>
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* defines
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#define R_SETDATA_REQUEST_EXPIRE_SECS 20
|
||||
#define R_SETDATA_SUBREQUEST_EXPIRE_SECS 10
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* forward declarations
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static GWEN_MSG_REQUEST *_mkRequest_SetData(AQHOME_DATA *aqh,
|
||||
GWEN_MSG_ENDPOINT *epSrc, uint32_t requestMsgId,
|
||||
GWEN_MSG_ENDPOINT *epDriver,
|
||||
const AQH_VALUE *v, const char *data);
|
||||
static void _rqSubRequestFinished(GWEN_MSG_REQUEST *rq, GWEN_MSG_REQUEST *subRq, int reason);
|
||||
static void _rqAbort(GWEN_MSG_REQUEST *rq, int reason);
|
||||
|
||||
static GWEN_MSG_REQUEST *_mkSubRequest_SetData(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *epDriver, const AQH_VALUE *v, const char *data);
|
||||
static int _subRqHandleResponse(GWEN_MSG_REQUEST *rq, GWEN_MSG *msg);
|
||||
static void _subRqAbort(GWEN_MSG_REQUEST *rq, int reason);
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* implementations
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void AqHomeData_HandleSetData(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *epSrc, GWEN_MSG *recvdMsg)
|
||||
{
|
||||
uint32_t msgId;
|
||||
AQH_VALUE *recvdValue;
|
||||
const char *valueName;
|
||||
char *valueDataFreeable;
|
||||
AQH_VALUE *systemValue;
|
||||
|
||||
msgId=GWEN_IpcMsg_GetMsgId(recvdMsg);
|
||||
DBG_INFO(NULL, "Received IPC SetDataRequest message (msgId=%d)", msgId);
|
||||
|
||||
AQH_SetDataIpcMsg_Parse(recvdMsg, 0);
|
||||
recvdValue=AQH_SetDataIpcMsg_ReadValue(recvdMsg);
|
||||
valueName=recvdValue?AQH_Value_GetNameForSystem(recvdValue):NULL;
|
||||
valueDataFreeable=AQH_SetDataIpcMsg_ReadData(recvdMsg);
|
||||
|
||||
systemValue=AQH_Storage_GetValueByNameForSystem(aqh->storage, valueName);
|
||||
if (systemValue) {
|
||||
if (AQH_Value_GetValueType(systemValue)==AQH_ValueType_Actor) {
|
||||
const char *driverName;
|
||||
|
||||
driverName=AQH_Value_GetDriver(systemValue);
|
||||
if (driverName && *driverName) {
|
||||
GWEN_MSG_ENDPOINT *epDriver;
|
||||
|
||||
epDriver=AqHomeData_GetIpcEndpointByServiceName(aqh, driverName);
|
||||
if (epDriver) {
|
||||
GWEN_MSG_REQUEST *rq;
|
||||
|
||||
DBG_DEBUG(NULL, "Creating SETDATA request for driver endpoint (%s)", GWEN_MsgEndpoint_GetName(epDriver));
|
||||
rq=_mkRequest_SetData(aqh, epSrc, msgId, epDriver, systemValue, valueDataFreeable);
|
||||
AqHomeData_AddRequestToTree(aqh, rq);
|
||||
}
|
||||
else {
|
||||
DBG_ERROR(NULL, "Driver \"%s\" not available", driverName);
|
||||
AQH_IpcEndpoint_SendResponseResult(epSrc, msgId, AQH_MSGTYPE_IPC_DATA_RESULT, AQH_MSG_IPC_ERROR_GENERIC);
|
||||
}
|
||||
}
|
||||
else {
|
||||
DBG_ERROR(NULL, "No driver name");
|
||||
AQH_IpcEndpoint_SendResponseResult(epSrc, msgId, AQH_MSGTYPE_IPC_DATA_RESULT, AQH_MSG_IPC_ERROR_GENERIC);
|
||||
}
|
||||
}
|
||||
else {
|
||||
DBG_ERROR(NULL, "Value \"%s\" is not an actor", valueName);
|
||||
AQH_IpcEndpoint_SendResponseResult(epSrc, msgId, AQH_MSGTYPE_IPC_DATA_RESULT, AQH_MSG_IPC_ERROR_INVALID);
|
||||
}
|
||||
}
|
||||
else {
|
||||
DBG_ERROR(NULL, "Unknown value \"%s\"", valueName);
|
||||
AQH_IpcEndpoint_SendResponseResult(epSrc, msgId, AQH_MSGTYPE_IPC_DATA_RESULT, AQH_MSG_IPC_ERROR_NOTFOUND);
|
||||
}
|
||||
AQH_Value_free(recvdValue);
|
||||
free(valueDataFreeable);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* IPC Request SETDATA
|
||||
*/
|
||||
|
||||
GWEN_MSG_REQUEST *_mkRequest_SetData(AQHOME_DATA *aqh,
|
||||
GWEN_MSG_ENDPOINT *epSrc, uint32_t requestMsgId,
|
||||
GWEN_MSG_ENDPOINT *epDriver,
|
||||
const AQH_VALUE *v, const char *data)
|
||||
{
|
||||
GWEN_MSG_REQUEST *rq;
|
||||
GWEN_MSG_REQUEST *subRq;
|
||||
|
||||
rq=GWEN_MsgRequest_new();
|
||||
GWEN_MsgRequest_SetPrivateData(rq, aqh);
|
||||
GWEN_MsgRequest_SetEndpoint(rq, epSrc);
|
||||
GWEN_MsgRequest_SetRequestMsgId(rq, requestMsgId);
|
||||
GWEN_MsgRequest_SetSubRequestFinishedFn(rq, _rqSubRequestFinished);
|
||||
GWEN_MsgRequest_SetAbortFn(rq, _rqAbort);
|
||||
GWEN_MsgRequest_SetTimestamps(rq, R_SETDATA_REQUEST_EXPIRE_SECS);
|
||||
|
||||
subRq=_mkSubRequest_SetData(aqh, epDriver, v, data);
|
||||
GWEN_MsgRequest_Tree2_AddChild(rq, subRq);
|
||||
|
||||
return rq;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _rqSubRequestFinished(GWEN_MSG_REQUEST *rq, GWEN_MSG_REQUEST *subRq, int reason)
|
||||
{
|
||||
GWEN_MSG_ENDPOINT *ep;
|
||||
uint32_t refMsgId;
|
||||
int result;
|
||||
|
||||
DBG_DEBUG(NULL, "SubRequest finished (reason: %d)", reason);
|
||||
refMsgId=GWEN_MsgRequest_GetRequestMsgId(rq);
|
||||
ep=GWEN_MsgRequest_GetEndpoint(rq);
|
||||
result=GWEN_MsgRequest_GetResult(subRq);
|
||||
|
||||
if (reason==GWEN_MSG_REQUEST_REASON_ABORTED)
|
||||
AQH_IpcEndpoint_SendResponseResult(ep, refMsgId, AQH_MSGTYPE_IPC_DATA_RESULT, AQH_MSG_IPC_ERROR_GENERIC);
|
||||
else
|
||||
AQH_IpcEndpoint_SendResponseResult(ep, refMsgId, AQH_MSGTYPE_IPC_DATA_RESULT, result);
|
||||
|
||||
GWEN_MsgRequest_SetResult(rq, result);
|
||||
GWEN_MsgRequest_SetState(rq, GWEN_MSG_REQUEST_STATE_DONE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _rqAbort(GWEN_MSG_REQUEST *rq, int reason)
|
||||
{
|
||||
GWEN_MSG_ENDPOINT *ep;
|
||||
uint32_t refMsgId;
|
||||
GWEN_MSG_REQUEST *rqParent;
|
||||
|
||||
DBG_INFO(NULL, "Aborting request");
|
||||
refMsgId=GWEN_MsgRequest_GetRequestMsgId(rq);
|
||||
ep=GWEN_MsgRequest_GetEndpoint(rq);
|
||||
AQH_IpcEndpoint_SendResponseResult(ep, refMsgId, AQH_MSGTYPE_IPC_DATA_RESULT, AQH_MSG_IPC_ERROR_GENERIC);
|
||||
GWEN_MsgRequest_SetState(rq, GWEN_MSG_REQUEST_STATE_DONE);
|
||||
|
||||
rqParent=GWEN_MsgRequest_Tree2_GetParent(rq);
|
||||
if (rqParent)
|
||||
GWEN_MsgRequest_SubRequestFinished(rqParent, rq, reason);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Driver Request SETDATA
|
||||
*/
|
||||
|
||||
|
||||
GWEN_MSG_REQUEST *_mkSubRequest_SetData(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *epDriver, const AQH_VALUE *v, const char *data)
|
||||
{
|
||||
GWEN_MSG_REQUEST *rq;
|
||||
uint16_t msgId;
|
||||
GWEN_MSG *driverMsg;
|
||||
|
||||
rq=GWEN_MsgRequest_new();
|
||||
GWEN_MsgRequest_SetPrivateData(rq, aqh);
|
||||
GWEN_MsgRequest_SetEndpoint(rq, epDriver);
|
||||
|
||||
GWEN_MsgRequest_SetHandleResponseFn(rq, _subRqHandleResponse);
|
||||
GWEN_MsgRequest_SetAbortFn(rq, _subRqAbort);
|
||||
|
||||
msgId=GWEN_MsgEndpoint_GetNextMessageId(epDriver);
|
||||
GWEN_MsgRequest_SetRequestMsgId(rq, msgId);
|
||||
GWEN_MsgRequest_SetTimestamps(rq, R_SETDATA_SUBREQUEST_EXPIRE_SECS);
|
||||
|
||||
driverMsg=AQH_SetDataIpcMsg_new(AQH_MSGTYPE_IPC_DATA_SETDATA, msgId, 0, v, data);
|
||||
GWEN_MsgEndpoint_AddSendMessage(epDriver, driverMsg);
|
||||
|
||||
return rq;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _subRqHandleResponse(GWEN_MSG_REQUEST *rq, GWEN_MSG *msg)
|
||||
{
|
||||
DBG_DEBUG(NULL, "Checking message from driver");
|
||||
if (GWEN_IpcMsg_GetCode(msg)==AQH_MSGTYPE_IPC_DATA_RESULT) {
|
||||
uint32_t result;
|
||||
GWEN_MSG_REQUEST *rqParent;
|
||||
|
||||
result=AQH_ResultIpcMsg_GetResultCode(msg);
|
||||
DBG_INFO(NULL, "Received result for request: %d", result);
|
||||
GWEN_MsgRequest_SetResult(rq, result);
|
||||
GWEN_MsgRequest_SetState(rq, GWEN_MSG_REQUEST_STATE_DONE);
|
||||
rqParent=GWEN_MsgRequest_Tree2_GetParent(rq);
|
||||
if (rqParent)
|
||||
GWEN_MsgRequest_SubRequestFinished(rqParent, rq, GWEN_MSG_REQUEST_REASON_DONE);
|
||||
return GWEN_MSG_REQUEST_RESULT_HANDLED;
|
||||
}
|
||||
else {
|
||||
DBG_ERROR(NULL, "Unexpected response message %d", GWEN_IpcMsg_GetCode(msg));
|
||||
}
|
||||
|
||||
return GWEN_MSG_REQUEST_RESULT_NOT_HANDLED;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _subRqAbort(GWEN_MSG_REQUEST *rq, int reason)
|
||||
{
|
||||
GWEN_MSG_REQUEST *rqParent;
|
||||
|
||||
DBG_INFO(NULL, "Aborting request");
|
||||
|
||||
GWEN_MsgRequest_SetResult(rq, AQH_MSG_IPC_ERROR_GENERIC);
|
||||
GWEN_MsgRequest_SetState(rq, GWEN_MSG_REQUEST_STATE_DONE);
|
||||
|
||||
rqParent=GWEN_MsgRequest_Tree2_GetParent(rq);
|
||||
if (rqParent)
|
||||
GWEN_MsgRequest_SubRequestFinished(rqParent, rq, reason);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2023 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef AQHOME_DATA_C_SETDATA_H
|
||||
#define AQHOME_DATA_C_SETDATA_H
|
||||
|
||||
|
||||
#include "./aqhome_data.h"
|
||||
|
||||
|
||||
void AqHomeData_HandleSetData(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *ep, GWEN_MSG *recvdMsg);
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,153 +0,0 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2023 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "./c_updatedata.h"
|
||||
#include "./aqhome_data_p.h"
|
||||
#include "./loop.h"
|
||||
#include "aqhome/ipc/data/ipc_data.h"
|
||||
#include "aqhome/ipc/data/msg_data_multidata.h"
|
||||
#include "aqhome/ipc/endpoint_ipc.h"
|
||||
#include "aqhome/ipc/msg_ipc_result.h"
|
||||
#include "aqhome/ipc/msg_ipc_tag16.h"
|
||||
|
||||
#include <gwenhywfar/debug.h>
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* defines
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#define DISABLE_DEBUGLOG
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* forward declarations
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int _storeDataPoints(AQHOME_DATA *aqh, const AQH_VALUE *v, const uint64_t *dataPoints, unsigned int numValues);
|
||||
static void _sendDataChangedMsgToAllClients(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *epSrc, const AQH_VALUE *v,
|
||||
const uint64_t *dataPoints, uint32_t numValues);
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* implementations
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void AqHomeData_HandleUpdateData(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *ep, GWEN_MSG *recvdMsg)
|
||||
{
|
||||
GWEN_MSG *outMsg;
|
||||
int resultCode=AQH_MSG_IPC_SUCCESS;
|
||||
const GWEN_TAG16 *tag;
|
||||
AQH_VALUE *recvdValue;
|
||||
const char *valueName;
|
||||
const uint64_t *dataPoints=NULL;
|
||||
unsigned int numberOfPoints=0;
|
||||
|
||||
AQH_MultiDataDataIpcMsg_Parse(recvdMsg, 0);
|
||||
|
||||
recvdValue=AQH_MultiDataDataIpcMsg_ReadValue(recvdMsg);
|
||||
valueName=recvdValue?AQH_Value_GetName(recvdValue):NULL;
|
||||
tag=AQH_Tag16IpcMsg_FindFirstTagByType(recvdMsg, AQH_MSGDATA_MULTIDATA_TAGS_DATA);
|
||||
dataPoints=tag?((const uint64_t*)GWEN_Tag16_GetTagData(tag)):NULL;
|
||||
numberOfPoints=(tag?GWEN_Tag16_GetTagLength(tag):0)/(2*sizeof(uint64_t));
|
||||
|
||||
if (numberOfPoints>0) {
|
||||
AQH_VALUE *value;
|
||||
|
||||
value=AqHomeData_GetOrCreateValueForDriverWithTemplate(aqh, ep, recvdValue);
|
||||
if (value) {
|
||||
resultCode=_storeDataPoints(aqh, value, dataPoints, numberOfPoints);
|
||||
if (resultCode==AQH_MSG_IPC_SUCCESS)
|
||||
_sendDataChangedMsgToAllClients(aqh, ep, value, dataPoints, numberOfPoints);
|
||||
}
|
||||
else {
|
||||
DBG_INFO(NULL, "No permissions to add datapoint for value \"%s\"", valueName);
|
||||
resultCode=AQH_MSG_IPC_ERROR_PERMS;
|
||||
}
|
||||
}
|
||||
else {
|
||||
DBG_INFO(NULL, "No datapoints");
|
||||
resultCode=AQH_MSG_IPC_ERROR_INVALID;
|
||||
}
|
||||
AQH_Value_free(recvdValue);
|
||||
|
||||
outMsg=AQH_ResultIpcMsg_new(AQH_MSGTYPE_IPC_DATA_RESULT,
|
||||
GWEN_MsgEndpoint_GetNextMessageId(ep), GWEN_IpcMsg_GetMsgId(recvdMsg),
|
||||
resultCode);
|
||||
GWEN_MsgEndpoint_AddSendMessage(ep, outMsg);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _storeDataPoints(AQHOME_DATA *aqh, const AQH_VALUE *v, const uint64_t *dataPoints, unsigned int numValues)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
for(i=0; i<numValues; i++) {
|
||||
uint64_t timestamp;
|
||||
union {double f; uint64_t i;} u;
|
||||
int rv;
|
||||
|
||||
timestamp=*(dataPoints++);
|
||||
u.i=*(dataPoints++);
|
||||
rv=AQH_Storage_AddDatapoint(aqh->storage, AQH_Value_GetId(v), timestamp, u.f);
|
||||
if (rv<0) {
|
||||
DBG_INFO(NULL, "here (%d)", rv);
|
||||
return AQH_MSG_IPC_ERROR_GENERIC;
|
||||
}
|
||||
else {
|
||||
DBG_DEBUG(NULL, "Datapoint added for value \"%s\"", AQH_Value_GetNameForSystem(v));
|
||||
}
|
||||
} /* for */
|
||||
|
||||
return AQH_MSG_IPC_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _sendDataChangedMsgToAllClients(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *epSrc, const AQH_VALUE *v,
|
||||
const uint64_t *dataPoints, uint32_t numValues)
|
||||
{
|
||||
GWEN_MSG_ENDPOINT *ep;
|
||||
|
||||
ep=GWEN_MsgEndpoint_Tree2_GetFirstChild(aqh->ipcdEndpoint);
|
||||
while(ep) {
|
||||
if (ep!=epSrc) {
|
||||
if (GWEN_MsgEndpoint_GetFlags(ep) & AQH_IPCENDPOINT_FLAGS_WANTUPDATES) {
|
||||
GWEN_MSG *msg;
|
||||
|
||||
DBG_DEBUG(AQH_LOGDOMAIN, "Sending update msg to endpoint %s", GWEN_MsgEndpoint_GetName(ep));
|
||||
msg=AQH_MultiDataDataIpcMsg_new(AQH_MSGTYPE_IPC_DATA_DATACHANGED,
|
||||
GWEN_MsgEndpoint_GetNextMessageId(ep), 0,
|
||||
v, dataPoints, numValues);
|
||||
GWEN_MsgEndpoint_AddSendMessage(ep, msg);
|
||||
}
|
||||
else {
|
||||
DBG_DEBUG(AQH_LOGDOMAIN, "Endpoint %s doesn't want updates", GWEN_MsgEndpoint_GetName(ep));
|
||||
}
|
||||
}
|
||||
else {
|
||||
DBG_DEBUG(AQH_LOGDOMAIN, "Not sending update msg to source of updates");
|
||||
}
|
||||
ep=GWEN_MsgEndpoint_Tree2_GetNext(ep);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2023 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef AQHOME_DATA_C_UPDATEDATA_H
|
||||
#define AQHOME_DATA_C_UPDATEDATA_H
|
||||
|
||||
|
||||
#include "./aqhome_data.h"
|
||||
|
||||
|
||||
void AqHomeData_HandleUpdateData(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *ep, GWEN_MSG *recvdMsg);
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2023 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "./fini.h"
|
||||
#include "./aqhome_data_p.h"
|
||||
|
||||
#include <gwenhywfar/gwenhywfar.h>
|
||||
#include <gwenhywfar/args.h>
|
||||
#include <gwenhywfar/debug.h>
|
||||
#include <gwenhywfar/endpoint_tcpd.h>
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* defines
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* forward declarations
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static void _disconnectTree(GWEN_MSG_ENDPOINT *ep);
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* implementations
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void AqHomeData_Fini(AQHOME_DATA *aqh)
|
||||
{
|
||||
if (aqh) {
|
||||
if (aqh->ipcdEndpoint) {
|
||||
_disconnectTree(aqh->ipcdEndpoint);
|
||||
GWEN_MsgEndpoint_Disconnect(aqh->ipcdEndpoint);
|
||||
}
|
||||
GWEN_MsgEndpoint_free(aqh->ipcdEndpoint);
|
||||
aqh->ipcdEndpoint=NULL;
|
||||
|
||||
if (aqh->pidFile)
|
||||
remove(aqh->pidFile);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _disconnectTree(GWEN_MSG_ENDPOINT *ep)
|
||||
{
|
||||
GWEN_MSG_ENDPOINT *epChild;
|
||||
|
||||
epChild=GWEN_MsgEndpoint_Tree2_GetFirstChild(ep);
|
||||
while(epChild) {
|
||||
_disconnectTree(epChild);
|
||||
epChild=GWEN_MsgEndpoint_Tree2_GetNext(epChild);
|
||||
} /* while */
|
||||
|
||||
GWEN_MsgEndpoint_Disconnect(ep);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2023 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef AQHOME_DATA_FINI_H
|
||||
#define AQHOME_DATA_FINI_H
|
||||
|
||||
|
||||
#include "./aqhome_data.h"
|
||||
|
||||
|
||||
|
||||
void AqHomeData_Fini(AQHOME_DATA *aqh);
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,341 +0,0 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2023 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "./init.h"
|
||||
#include "./aqhome_data_p.h"
|
||||
|
||||
#include "aqhome/aqhome.h"
|
||||
#include "aqhome/ipc/endpoint_ipc.h"
|
||||
|
||||
#include <gwenhywfar/gwenhywfar.h>
|
||||
#include <gwenhywfar/args.h>
|
||||
#include <gwenhywfar/debug.h>
|
||||
#include <gwenhywfar/endpoint_tcpd.h>
|
||||
#include <gwenhywfar/endpoint_msgio.h>
|
||||
#include <gwenhywfar/directory.h>
|
||||
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
# include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_STAT_H
|
||||
# include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* defines
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#define I18N(msg) msg
|
||||
#define I18S(msg) msg
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* forward declarations
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int _setupStorage(AQHOME_DATA *aqh, GWEN_DB_NODE *dbArgs);
|
||||
|
||||
static void _setupIpc(AQHOME_DATA *aqh, GWEN_DB_NODE *dbArgs);
|
||||
|
||||
static GWEN_MSG_ENDPOINT *_acceptIpcFn(GWEN_MSG_ENDPOINT *ep, GWEN_SOCKET *sk, const GWEN_INETADDRESS *addr, void *data);
|
||||
|
||||
static int _readArgs(int argc, char **argv, GWEN_DB_NODE *dbArgs);
|
||||
static int _createPidFile(const char *pidFilename);
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* implementations
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int AqHomeData_Init(AQHOME_DATA *aqh, int argc, char **argv)
|
||||
{
|
||||
GWEN_DB_NODE *dbArgs;
|
||||
int rv;
|
||||
const char *s;
|
||||
|
||||
dbArgs=GWEN_DB_Group_new("args");
|
||||
rv=_readArgs(argc, argv, dbArgs);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "Error reading args (%d)", rv);
|
||||
return rv;
|
||||
}
|
||||
AQH_MergeConfigFileIntoConfig(dbArgs, "ConfigFile");
|
||||
|
||||
aqh->dbArgs=dbArgs;
|
||||
|
||||
s=GWEN_DB_GetCharValue(dbArgs, "loglevel", 0, NULL);
|
||||
if (s && *s) {
|
||||
GWEN_LOGGER_LEVEL ll;
|
||||
|
||||
ll=GWEN_Logger_Name2Level(s);
|
||||
GWEN_Logger_SetLevel(NULL, ll);
|
||||
}
|
||||
|
||||
aqh->timeout=GWEN_DB_GetIntValue(dbArgs, "timeout", 0, 0);
|
||||
|
||||
s=GWEN_DB_GetCharValue(dbArgs, "pidfile", 0, AQHOME_DATA_DEFAULT_PIDFILE);
|
||||
if (s && *s) {
|
||||
free(aqh->pidFile);
|
||||
aqh->pidFile=strdup(s);
|
||||
rv=_createPidFile(s);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "Error creating PID file (%d)", rv);
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
rv=_setupStorage(aqh, dbArgs);
|
||||
if (rv<0) {
|
||||
DBG_INFO(NULL, "here (%d)", rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
_setupIpc(aqh, dbArgs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _setupStorage(AQHOME_DATA *aqh, GWEN_DB_NODE *dbArgs)
|
||||
{
|
||||
const char *dataFolder;
|
||||
GWEN_BUFFER *nameBuf;
|
||||
AQH_STORAGE *sto;
|
||||
int rv;
|
||||
|
||||
dataFolder=GWEN_DB_GetCharValue(dbArgs, "dataFolder", 0, AQHOME_DATA_DEFAULT_DATADIR);
|
||||
nameBuf=GWEN_Buffer_new(0, 256, 0, 1);
|
||||
GWEN_Buffer_AppendArgs(nameBuf, "%s%s%s", dataFolder, GWEN_DIR_SEPARATOR_S, AQHOME_DATA_STATEFILENAME);
|
||||
|
||||
sto=AQH_Storage_new();
|
||||
AQH_Storage_SetStateFile(sto, GWEN_Buffer_GetStart(nameBuf));
|
||||
AQH_Storage_SetDataFileFolder(sto, dataFolder);
|
||||
GWEN_Buffer_free(nameBuf);
|
||||
|
||||
rv=AQH_Storage_Init(sto);
|
||||
if (rv<0) {
|
||||
DBG_INFO(NULL, "here (%d)", rv);
|
||||
AQH_Storage_free(sto);
|
||||
return rv;
|
||||
}
|
||||
aqh->storage=sto;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _setupIpc(AQHOME_DATA *aqh, GWEN_DB_NODE *dbArgs)
|
||||
{
|
||||
const char *tcpAddress;
|
||||
int tcpPort;
|
||||
|
||||
tcpAddress=GWEN_DB_GetCharValue(dbArgs, "tcpAddress", 0, NULL);
|
||||
if (!(tcpAddress && *tcpAddress))
|
||||
tcpAddress=GWEN_DB_GetCharValue(dbArgs, "ConfigFile/brokerAddress", 0, NULL);
|
||||
|
||||
tcpPort=GWEN_DB_GetIntValue(dbArgs, "tcpPort", 0, -1);
|
||||
if (tcpPort<0)
|
||||
tcpPort=GWEN_DB_GetIntValue(dbArgs, "ConfigFile/brokerPort", 0, AQHOME_DATA_DEFAULT_IPC_PORT);
|
||||
|
||||
if (tcpAddress && *tcpAddress && tcpPort>0) {
|
||||
GWEN_MSG_ENDPOINT *ep;
|
||||
|
||||
DBG_INFO(NULL, "Starting TCP service on \"%s\":%d", tcpAddress, tcpPort);
|
||||
ep=GWEN_TcpdEndpoint_new(tcpAddress, tcpPort, NULL, 0);
|
||||
GWEN_TcpdEndpoint_SetAcceptFn(ep, _acceptIpcFn, aqh);
|
||||
|
||||
aqh->ipcdEndpoint=ep;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
GWEN_MSG_ENDPOINT *_acceptIpcFn(GWEN_MSG_ENDPOINT *ep,
|
||||
GWEN_SOCKET *sk,
|
||||
const GWEN_INETADDRESS *addr,
|
||||
GWEN_UNUSED void *data)
|
||||
{
|
||||
/* AQHOME_DATA *aqh;
|
||||
*
|
||||
* aqh=(AQHOME_DATA*) data;
|
||||
*/
|
||||
DBG_INFO(NULL, "Incoming IPC connection");
|
||||
return AQH_IpcEndpoint_CreateIpcTcpServiceForSocket(sk, NULL, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _createPidFile(const char *pidFilename)
|
||||
{
|
||||
FILE *f;
|
||||
int pidfd;
|
||||
|
||||
if (remove(pidFilename)==0) {
|
||||
DBG_ERROR(0, "Old PID file existed, removed. (Unclean shutdown?)");
|
||||
}
|
||||
|
||||
#ifdef HAVE_SYS_STAT_H
|
||||
pidfd = open(pidFilename, O_EXCL|O_CREAT|O_WRONLY, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
|
||||
if (pidfd < 0) {
|
||||
DBG_ERROR(NULL, "Could not create PID file \"%s\" (%s), aborting.", pidFilename, strerror(errno));
|
||||
return GWEN_ERROR_IO;
|
||||
}
|
||||
|
||||
f = fdopen(pidfd, "w");
|
||||
#else /* HAVE_STAT_H */
|
||||
f=fopen(pidFilename,"w+");
|
||||
#endif /* HAVE_STAT_H */
|
||||
|
||||
/* write pid */
|
||||
#ifdef HAVE_GETPID
|
||||
fprintf(f,"%d\n",getpid());
|
||||
#else
|
||||
fprintf(f,"-1\n");
|
||||
#endif
|
||||
if (fclose(f)) {
|
||||
DBG_ERROR(0, "Could not close PID file \"%s\" (%s), aborting.", pidFilename, strerror(errno));
|
||||
return GWEN_ERROR_IO;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int _readArgs(int argc, char **argv, GWEN_DB_NODE *dbArgs)
|
||||
{
|
||||
int rv;
|
||||
const GWEN_ARGS args[]= {
|
||||
{
|
||||
GWEN_ARGS_FLAGS_HAS_ARGUMENT, /* flags */
|
||||
GWEN_ArgsType_Char, /* type */
|
||||
"loglevel", /* name */
|
||||
0, /* minnum */
|
||||
1, /* maxnum */
|
||||
"L", /* short option */
|
||||
"loglevel", /* long option */
|
||||
I18S("Specify loglevel"), /* short description */
|
||||
I18S("Specify loglevel") /* long description */
|
||||
},
|
||||
{
|
||||
GWEN_ARGS_FLAGS_HAS_ARGUMENT, /* flags */
|
||||
GWEN_ArgsType_Char, /* type */
|
||||
"tcpAddress", /* name */
|
||||
0, /* minnum */
|
||||
1, /* maxnum */
|
||||
"t", /* short option */
|
||||
"tcpaddress", /* long option */
|
||||
I18S("Specify the TCP address to listen on (disabled if missing)"),
|
||||
I18S("Specify the TCP address to listen on (disabled if missing)")
|
||||
},
|
||||
{
|
||||
GWEN_ARGS_FLAGS_HAS_ARGUMENT, /* flags */
|
||||
GWEN_ArgsType_Int, /* type */
|
||||
"tcpPort", /* name */
|
||||
0, /* minnum */
|
||||
1, /* maxnum */
|
||||
"P", /* short option */
|
||||
"tcpport", /* long option */
|
||||
I18S("Specify the TCP port to listen on"),
|
||||
I18S("Specify the TCP port to listen on")
|
||||
},
|
||||
{
|
||||
GWEN_ARGS_FLAGS_HAS_ARGUMENT, /* flags */
|
||||
GWEN_ArgsType_Char, /* type */
|
||||
"datafolder", /* name */
|
||||
0, /* minnum */
|
||||
1, /* maxnum */
|
||||
NULL, /* short option */
|
||||
"datafolder", /* long option */
|
||||
I18S("Folder where data files are stored"),
|
||||
I18S("Folder where data files are stored")
|
||||
},
|
||||
{
|
||||
GWEN_ARGS_FLAGS_HAS_ARGUMENT, /* flags */
|
||||
GWEN_ArgsType_Char, /* type */
|
||||
"pidfile", /* name */
|
||||
0, /* minnum */
|
||||
1, /* maxnum */
|
||||
"p", /* short option */
|
||||
"pidfile", /* long option */
|
||||
I18S("Specify the PID file"),
|
||||
I18S("Specify the PID file")
|
||||
},
|
||||
{
|
||||
GWEN_ARGS_FLAGS_HAS_ARGUMENT, /* flags */
|
||||
GWEN_ArgsType_Int, /* type */
|
||||
"timeout", /* name */
|
||||
0, /* minnum */
|
||||
1, /* maxnum */
|
||||
"T", /* short option */
|
||||
"timeout", /* long option */
|
||||
I18S("Specify timeout in second (default: no timeout)"),
|
||||
I18S("Specify timeout in second (default: no timeout)")
|
||||
},
|
||||
{
|
||||
GWEN_ARGS_FLAGS_HELP | GWEN_ARGS_FLAGS_LAST, /* flags */
|
||||
GWEN_ArgsType_Int, /* type */
|
||||
"help", /* name */
|
||||
0, /* minnum */
|
||||
0, /* maxnum */
|
||||
"h", /* short option */
|
||||
"help",
|
||||
I18S("Show this help screen."),
|
||||
I18S("Show this help screen.")
|
||||
}
|
||||
};
|
||||
|
||||
rv=GWEN_Args_Check(argc, argv, 1, 0, args, dbArgs);
|
||||
if (rv==GWEN_ARGS_RESULT_ERROR) {
|
||||
fprintf(stderr, "ERROR: Could not parse arguments main\n");
|
||||
return GWEN_ERROR_INVALID;
|
||||
}
|
||||
else if (rv==GWEN_ARGS_RESULT_HELP) {
|
||||
GWEN_BUFFER *ubuf;
|
||||
|
||||
ubuf=GWEN_Buffer_new(0, 1024, 0, 1);
|
||||
GWEN_Buffer_AppendArgs(ubuf,
|
||||
I18N("This is version %s.\nUsage: %s [OPTIONS]\n\nOptions:\n"),
|
||||
AQHOME_VERSION_STRING,
|
||||
argv[0]);
|
||||
if (GWEN_Args_Usage(args, ubuf, GWEN_ArgsOutType_Txt)) {
|
||||
fprintf(stderr, "ERROR: Could not create help string\n");
|
||||
return 1;
|
||||
}
|
||||
GWEN_Buffer_AppendString(ubuf, "\n");
|
||||
|
||||
fprintf(stdout, "%s\n", GWEN_Buffer_GetStart(ubuf));
|
||||
GWEN_Buffer_free(ubuf);
|
||||
return GWEN_ERROR_CLOSE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2023 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef AQHOME_DATA_INIT_H
|
||||
#define AQHOME_DATA_INIT_H
|
||||
|
||||
|
||||
#include "./aqhome_data.h"
|
||||
|
||||
|
||||
|
||||
int AqHomeData_Init(AQHOME_DATA *aqh, int argc, char **argv);
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user