Compare commits
6031 Commits
v2.4
...
fix/migrat
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f0dd363c99 | ||
|
|
6cb8f55215 | ||
|
|
92a3c73f80 | ||
|
|
4f268ed193 | ||
|
|
d80259ee8f | ||
|
|
83224e7729 | ||
|
|
6cca30ca45 | ||
|
|
b2a5564685 | ||
|
|
7dc542f3c2 | ||
|
|
3ac426b5d1 | ||
|
|
4d55bc1ae3 | ||
|
|
26ef0be9d6 | ||
|
|
d030492664 | ||
|
|
cc01c110f1 | ||
|
|
fdda40994b | ||
|
|
4dbf9a0bbb | ||
|
|
eb4b6ecf25 | ||
|
|
c380c23592 | ||
|
|
a41426474e | ||
|
|
764aa48c14 | ||
|
|
8f1fce8f4b | ||
|
|
76a6b42075 | ||
|
|
5c6b286a62 | ||
|
|
11e00e04b5 | ||
|
|
5ef4a5e8b0 | ||
|
|
03932e8ca7 | ||
|
|
b23348916b | ||
|
|
7d727555e2 | ||
|
|
1c4a48258f | ||
|
|
d9288b896e | ||
|
|
553c0f7f07 | ||
|
|
531490397d | ||
|
|
6b423f534c | ||
|
|
4137275f24 | ||
|
|
d2cbe1f712 | ||
|
|
62b63f87e0 | ||
|
|
2dc5bd15cc | ||
|
|
7341f85c2d | ||
|
|
9478e35cb7 | ||
|
|
cd7e5abe25 | ||
|
|
c47f8c2cd6 | ||
|
|
f08c54e166 | ||
|
|
fd5b3be03f | ||
|
|
112b961762 | ||
|
|
250fbd217f | ||
|
|
0421e3784c | ||
|
|
8ec7651075 | ||
|
|
6d8b4fdfc6 | ||
|
|
9abb240105 | ||
|
|
8acfa029d9 | ||
|
|
16af216b80 | ||
|
|
5589fa171c | ||
|
|
0e7706ffa3 | ||
|
|
1a4870690b | ||
|
|
8bf6480aed | ||
|
|
7ae0b207fc | ||
|
|
fa194e0a0c | ||
|
|
8fc0f1f26a | ||
|
|
8c39365db1 | ||
|
|
c3a762823d | ||
|
|
2fd51bd244 | ||
|
|
1ad135ad69 | ||
|
|
6e905a7f80 | ||
|
|
3956ca49b6 | ||
|
|
cd8d9ab84e | ||
|
|
38c561ae41 | ||
|
|
fa45a4bec8 | ||
|
|
1bec0d2c7e | ||
|
|
aedb2f0a93 | ||
|
|
8e5ac2dbac | ||
|
|
d4cf5d95a6 | ||
|
|
5cef02e60d | ||
|
|
afdf45031f | ||
|
|
7dd2eb20a2 | ||
|
|
6645136f6b | ||
|
|
84a659dfac | ||
|
|
be00f3e723 | ||
|
|
74e52675f1 | ||
|
|
74d451a9c7 | ||
|
|
ba058be236 | ||
|
|
ada7d2bd31 | ||
|
|
bcc3a7e35e | ||
|
|
c0e39087bc | ||
|
|
c1a8607e54 | ||
|
|
8c56572d0b | ||
|
|
e9fdfac569 | ||
|
|
5f1e4680f7 | ||
|
|
65806a905a | ||
|
|
cc476a49fe | ||
|
|
564957c203 | ||
|
|
8dbdae40e8 | ||
|
|
e3dc06708c | ||
|
|
885895e994 | ||
|
|
0f4ad7734c | ||
|
|
111dfc63ff | ||
|
|
73301da68f | ||
|
|
0cf0b2ab76 | ||
|
|
05707c624d | ||
|
|
65d6f5d890 | ||
|
|
20d20e116c | ||
|
|
b1acea33a1 | ||
|
|
6888897999 | ||
|
|
3daaabfebd | ||
|
|
251f3295f3 | ||
|
|
23f6c3069a | ||
|
|
7128c18b4c | ||
|
|
3e8189e9ce | ||
|
|
62ef2d1777 | ||
|
|
ce5ef79a3a | ||
|
|
092891aeb4 | ||
|
|
d60ad57cac | ||
|
|
53220cb5d6 | ||
|
|
129272a695 | ||
|
|
f02162b021 | ||
|
|
0ad2a79624 | ||
|
|
e291a9f7e0 | ||
|
|
cffb3117d4 | ||
|
|
1789b1ce99 | ||
|
|
333764a7c1 | ||
|
|
915352aefb | ||
|
|
c911bf30ab | ||
|
|
fc73cee156 | ||
|
|
59e25d0283 | ||
|
|
f80efa51aa | ||
|
|
ba2d10c65e | ||
|
|
a57d539098 | ||
|
|
50dcd8d62f | ||
|
|
a965afa249 | ||
|
|
cd7226d5e9 | ||
|
|
f2cb6e35ed | ||
|
|
3df0a6a996 | ||
|
|
76d7863270 | ||
|
|
e566338a79 | ||
|
|
f66707bd3e | ||
|
|
dcc057cd1f | ||
|
|
f277f5d202 | ||
|
|
80143325e8 | ||
|
|
bcef4f0c97 | ||
|
|
1d7071fb19 | ||
|
|
b4444023a2 | ||
|
|
4209e7dee8 | ||
|
|
632d8af4b0 | ||
|
|
5e69078ed1 | ||
|
|
bd9915105a | ||
|
|
a21b4c5203 | ||
|
|
e3fc5cc8f2 | ||
|
|
c26b043c58 | ||
|
|
8b078f67b8 | ||
|
|
cfbf3f61cd | ||
|
|
e8582f7740 | ||
|
|
9e9c985245 | ||
|
|
a302d7b5d7 | ||
|
|
72afa1073d | ||
|
|
b304562c8e | ||
|
|
8e4fc27168 | ||
|
|
7206569b1d | ||
|
|
fc156f521c | ||
|
|
4972cc6fdc | ||
|
|
f6681f75fb | ||
|
|
c672b66eb4 | ||
|
|
5024a98a4f | ||
|
|
9564a6e92d | ||
|
|
27fd80c01e | ||
|
|
e89d93a5d3 | ||
|
|
904a1a18b0 | ||
|
|
a69c2df36e | ||
|
|
4f52c6afc0 | ||
|
|
bc54b5b2ff | ||
|
|
c42890ad54 | ||
|
|
6bdb3cb87c | ||
|
|
9186e81a93 | ||
|
|
21a9410242 | ||
|
|
58a41641ab | ||
|
|
a16e053b2a | ||
|
|
1ed5994fa5 | ||
|
|
db1431a1ae | ||
|
|
67de7be802 | ||
|
|
2c32d485bd | ||
|
|
15d7fab2cb | ||
|
|
3ca6ca53a4 | ||
|
|
0980f9acf6 | ||
|
|
3cc1945942 | ||
|
|
7b980ed9ac | ||
|
|
0614c3c7a0 | ||
|
|
897e23089c | ||
|
|
7ca4b59b34 | ||
|
|
7d82b0294b | ||
|
|
b22731c613 | ||
|
|
e90df12053 | ||
|
|
bdbec058e9 | ||
|
|
bffffa4d1e | ||
|
|
5cb740ef01 | ||
|
|
12fbf86f66 | ||
|
|
8b324741e0 | ||
|
|
6ffb20f09e | ||
|
|
5c670c21f2 | ||
|
|
e8802173f5 | ||
|
|
325c9fc0a2 | ||
|
|
9c6d4ffa9b | ||
|
|
2b33a0494b | ||
|
|
19deafedae | ||
|
|
be5a8dc51a | ||
|
|
4148f2cb5b | ||
|
|
2c497a9a3e | ||
|
|
fafd47ba75 | ||
|
|
ddc289ca3e | ||
|
|
6b1d0e09d1 | ||
|
|
aa704a2e0e | ||
|
|
21fb5dabe1 | ||
|
|
c2ed30480d | ||
|
|
ccdbfd4130 | ||
|
|
548e142406 | ||
|
|
bfc2cf69e5 | ||
|
|
fe8e63853c | ||
|
|
b835fa06a6 | ||
|
|
424e825bd9 | ||
|
|
7e91b9ab47 | ||
|
|
97324ae97e | ||
|
|
5dfcd02c40 | ||
|
|
25f384a923 | ||
|
|
bfc18f8329 | ||
|
|
92b15cf744 | ||
|
|
8f24e8aa5f | ||
|
|
5cb9f4faaa | ||
|
|
4df7cee6c2 | ||
|
|
a2951cd3b8 | ||
|
|
520641fa5e | ||
|
|
ca9eaf9688 | ||
|
|
1e6fe9c3f2 | ||
|
|
5d2cb552d3 | ||
|
|
fdd5b5ced0 | ||
|
|
81e628a943 | ||
|
|
4a1dd7f79e | ||
|
|
cfc0d07173 | ||
|
|
0742c017a8 | ||
|
|
c1d6bcbcc2 | ||
|
|
2fdb6559dc | ||
|
|
dc5a7c4f16 | ||
|
|
e232361b2d | ||
|
|
3cf538e307 | ||
|
|
159be01e0e | ||
|
|
f6a3b0247d | ||
|
|
36f05cb20f | ||
|
|
628e1bbe41 | ||
|
|
4add164d43 | ||
|
|
78bd872b41 | ||
|
|
70376c24bd | ||
|
|
7b19b650d4 | ||
|
|
741b9e1b3e | ||
|
|
8a924867c9 | ||
|
|
d15beff4ba | ||
|
|
d30a7612ab | ||
|
|
01e0c60959 | ||
|
|
250a44ca9d | ||
|
|
dd64cf7872 | ||
|
|
5270336679 | ||
|
|
443c5e8243 | ||
|
|
dd2c1c69dd | ||
|
|
7bf97cf02a | ||
|
|
3abd2c04ce | ||
|
|
99e72f61d8 | ||
|
|
f478913dee | ||
|
|
1812d9c358 | ||
|
|
7426076297 | ||
|
|
c0cc9bac35 | ||
|
|
8886232faa | ||
|
|
8141fdd003 | ||
|
|
3ad90c1006 | ||
|
|
f4c9278b86 | ||
|
|
cd30772c43 | ||
|
|
200a82acfb | ||
|
|
2371f43609 | ||
|
|
6ce747c935 | ||
|
|
9f7cd050e9 | ||
|
|
976dc1c32d | ||
|
|
24ade13c02 | ||
|
|
7ec20d867b | ||
|
|
29d4ed1134 | ||
|
|
bf0c3c0e0f | ||
|
|
cb30943c2d | ||
|
|
c19bfb912f | ||
|
|
e6c15c3d9f | ||
|
|
448b1f4d6c | ||
|
|
78c755b538 | ||
|
|
4474268ae8 | ||
|
|
2955737782 | ||
|
|
b33bbd7e28 | ||
|
|
b5a7567f3b | ||
|
|
3cebb3f060 | ||
|
|
09ce000340 | ||
|
|
91d95e2c8a | ||
|
|
091a6891eb | ||
|
|
5d77c2b362 | ||
|
|
44703bbbc6 | ||
|
|
26132faf46 | ||
|
|
32ab5aa50b | ||
|
|
5391513fe7 | ||
|
|
b32f778654 | ||
|
|
f01362caf1 | ||
|
|
c69e0eb254 | ||
|
|
48a4693a5a | ||
|
|
db07cc9070 | ||
|
|
9f5d4f0eb0 | ||
|
|
5490a6ea6d | ||
|
|
80db52691b | ||
|
|
91e0d668e0 | ||
|
|
81ad1a76e6 | ||
|
|
67ddb64bcc | ||
|
|
c7d60295d9 | ||
|
|
8cfccf9d1f | ||
|
|
b595b3b5f4 | ||
|
|
398f90f7f4 | ||
|
|
47998e1c8a | ||
|
|
d80fcf2e62 | ||
|
|
9f9e5dffc2 | ||
|
|
fcb98d7e4a | ||
|
|
7879f07011 | ||
|
|
74a44cad7a | ||
|
|
32c640e838 | ||
|
|
eb7daf4d2c | ||
|
|
7442454d32 | ||
|
|
3c7a6ce535 | ||
|
|
f3af03174e | ||
|
|
472602ffb9 | ||
|
|
7aab7d9849 | ||
|
|
08dd321f73 | ||
|
|
58a1e85826 | ||
|
|
eb23fbf879 | ||
|
|
206cf9c4ea | ||
|
|
71b17294bc | ||
|
|
82a83c497d | ||
|
|
2fd0de4743 | ||
|
|
dedaf5432e | ||
|
|
c02401b81e | ||
|
|
eaa878e7a4 | ||
|
|
8042d9e3fd | ||
|
|
cb4f6d4159 | ||
|
|
bfd8b572cb | ||
|
|
8fb3a594eb | ||
|
|
9dd138b033 | ||
|
|
0635ea7455 | ||
|
|
0597128de8 | ||
|
|
0fdd959c7f | ||
|
|
e03ddf5d41 | ||
|
|
cb3e448b38 | ||
|
|
6bb7d10a6d | ||
|
|
fd1372df3e | ||
|
|
760f903d12 | ||
|
|
07e6c0d250 | ||
|
|
48c1d5a3d2 | ||
|
|
3ed29f494b | ||
|
|
b57cf27103 | ||
|
|
f5e6364f98 | ||
|
|
ed1a6278b7 | ||
|
|
b322f1e98b | ||
|
|
5b75cb1950 | ||
|
|
9ff43040ec | ||
|
|
75fadb9b55 | ||
|
|
1a59b407e0 | ||
|
|
c771739f68 | ||
|
|
bcb712b6e3 | ||
|
|
bb095bb209 | ||
|
|
b5ab8ac198 | ||
|
|
8b3469cabc | ||
|
|
aca7b31b83 | ||
|
|
8f36fdf11c | ||
|
|
f193edd428 | ||
|
|
3ba6ab5ec7 | ||
|
|
f0878c0890 | ||
|
|
2009fa85ec | ||
|
|
7b6f0d1596 | ||
|
|
f8bfd59f11 | ||
|
|
499ba9785f | ||
|
|
6e946f76d6 | ||
|
|
92e741fd5a | ||
|
|
31a8f150b2 | ||
|
|
07b448d784 | ||
|
|
9a3affd81e | ||
|
|
935a4ce0b3 | ||
|
|
cc8f9fe057 | ||
|
|
e1c41fe4d5 | ||
|
|
37c6b353b3 | ||
|
|
60de50bb73 | ||
|
|
ba2682c907 | ||
|
|
d6dbb40ef1 | ||
|
|
47f06dfd71 | ||
|
|
e773d0399f | ||
|
|
ebb0db0a3b | ||
|
|
b662fd6f01 | ||
|
|
9eb47319f5 | ||
|
|
debab10792 | ||
|
|
b756262ebe | ||
|
|
e781311f23 | ||
|
|
df9c60e351 | ||
|
|
aa4ceb4198 | ||
|
|
220c0675ef | ||
|
|
19bfa08b83 | ||
|
|
7eb69a5cc8 | ||
|
|
e14792bc48 | ||
|
|
05e7d0ee92 | ||
|
|
9c3578856f | ||
|
|
d2828310f2 | ||
|
|
00340136bd | ||
|
|
0c6363572b | ||
|
|
1b87ec067e | ||
|
|
8e8c7ecad2 | ||
|
|
0066c6fbff | ||
|
|
6e8029f69f | ||
|
|
12c6dd5dff | ||
|
|
c6049d4002 | ||
|
|
0cfcdc4b50 | ||
|
|
2ae79f2443 | ||
|
|
e8338d0590 | ||
|
|
719ce801f5 | ||
|
|
13676c40ca | ||
|
|
c3c31a1a60 | ||
|
|
b333e30162 | ||
|
|
fe4d934a40 | ||
|
|
a6c0d279b6 | ||
|
|
3f7413d538 | ||
|
|
c90a27c509 | ||
|
|
ac86ae1e4c | ||
|
|
6d02d4056f | ||
|
|
fe7299323c | ||
|
|
274d4c263c | ||
|
|
54186a63ee | ||
|
|
a87d1bbc4f | ||
|
|
750fb66a8c | ||
|
|
0b23b9b268 | ||
|
|
e49d7fa5f1 | ||
|
|
8a71e4253e | ||
|
|
2529fbeacd | ||
|
|
63b2a1f44a | ||
|
|
c6756b1678 | ||
|
|
c34464d1e8 | ||
|
|
16180e4b23 | ||
|
|
03637e9081 | ||
|
|
159817b7e2 | ||
|
|
2681835f94 | ||
|
|
7f7ec13c82 | ||
|
|
32a741b5c7 | ||
|
|
bbbb4609d2 | ||
|
|
e364349901 | ||
|
|
f5fe550a2e | ||
|
|
bfc824f2ff | ||
|
|
29d010dc2c | ||
|
|
96bf07863f | ||
|
|
62f9694aa4 | ||
|
|
4523f078bb | ||
|
|
6016131280 | ||
|
|
974fea592d | ||
|
|
9d57f64937 | ||
|
|
1276242a4e | ||
|
|
a6565bf9a1 | ||
|
|
c785667efe | ||
|
|
cc333f79cc | ||
|
|
df7633bd1b | ||
|
|
4efcdf1189 | ||
|
|
f16cf71781 | ||
|
|
19d3489bcb | ||
|
|
2338c9e916 | ||
|
|
536d170009 | ||
|
|
f4b67065cc | ||
|
|
2b79abb948 | ||
|
|
2e73eb36ef | ||
|
|
271884c4bb | ||
|
|
3c4f217876 | ||
|
|
ab09233753 | ||
|
|
af9b8df118 | ||
|
|
b61e8be3b4 | ||
|
|
54ab71d817 | ||
|
|
e7c89ce25f | ||
|
|
d3813c4be5 | ||
|
|
d854eb1a97 | ||
|
|
86aa6b1df6 | ||
|
|
1da36bd4e7 | ||
|
|
f65b126433 | ||
|
|
766cb26af5 | ||
|
|
e8884083ef | ||
|
|
e3c6f162d8 | ||
|
|
de6e61705e | ||
|
|
834e52f15d | ||
|
|
0b4131189d | ||
|
|
72c972175d | ||
|
|
2746ee3ae9 | ||
|
|
bc96d3b0a9 | ||
|
|
395110f92f | ||
|
|
758ace57c0 | ||
|
|
4c129afb10 | ||
|
|
ced1c5d50b | ||
|
|
ce21b4c731 | ||
|
|
480a8c8d7f | ||
|
|
0a193f98a4 | ||
|
|
4c4a2ad5bd | ||
|
|
ab3b6dfa67 | ||
|
|
6292e65b37 | ||
|
|
300a4e2299 | ||
|
|
ed5d794008 | ||
|
|
ec86124997 | ||
|
|
2e9e579bba | ||
|
|
d377cfbc3e | ||
|
|
15be8eeffa | ||
|
|
635b4e952f | ||
|
|
c86e7b3f96 | ||
|
|
dcc7e96d2f | ||
|
|
ccd8c470a5 | ||
|
|
00d7e998b4 | ||
|
|
fd8fdd3513 | ||
|
|
a44e51bf76 | ||
|
|
91c5967b27 | ||
|
|
842a9d7778 | ||
|
|
7523c49f62 | ||
|
|
369ccf13a8 | ||
|
|
38ecc1693f | ||
|
|
30bfc7cc9f | ||
|
|
45687d675b | ||
|
|
ca7836bf71 | ||
|
|
8bcd1d4c54 | ||
|
|
19e081b8ac | ||
|
|
ba61ee284b | ||
|
|
2a72012ca1 | ||
|
|
79ebbacc4a | ||
|
|
6cf39d9b92 | ||
|
|
c571d8d37d | ||
|
|
33a41391b5 | ||
|
|
d77dbf736c | ||
|
|
2deadb2e4a | ||
|
|
2c7fa4a7b3 | ||
|
|
ed0dfa8b77 | ||
|
|
27522fbc18 | ||
|
|
aaa9acc0b9 | ||
|
|
123ba1f154 | ||
|
|
2005d04625 | ||
|
|
2841a33b81 | ||
|
|
539f379cb4 | ||
|
|
ec83d6b793 | ||
|
|
f7ba059b94 | ||
|
|
e374950915 | ||
|
|
6ae713eaf5 | ||
|
|
40c75289b5 | ||
|
|
188b2b858a | ||
|
|
46ff257344 | ||
|
|
2061f3a70e | ||
|
|
51de1dcfcd | ||
|
|
60b6a1016c | ||
|
|
22863845a0 | ||
|
|
679aab10d0 | ||
|
|
6001fe34ec | ||
|
|
96640ea2c8 | ||
|
|
1fa5cb84db | ||
|
|
9622265c8d | ||
|
|
71357ecae7 | ||
|
|
7886dc0172 | ||
|
|
044e856e6b | ||
|
|
0385b1d076 | ||
|
|
e87d03a5ef | ||
|
|
70547755d6 | ||
|
|
f52b2b9863 | ||
|
|
bef5d85e6b | ||
|
|
afa688e3a0 | ||
|
|
f5885c8f64 | ||
|
|
edf0060acf | ||
|
|
7b341cc005 | ||
|
|
885b626a68 | ||
|
|
aba41b45b0 | ||
|
|
69a264a3c2 | ||
|
|
43ddfcf2ca | ||
|
|
0bf33edda1 | ||
|
|
fc72902029 | ||
|
|
3f4e2105b3 | ||
|
|
ec9d84692f | ||
|
|
c3d1f366ec | ||
|
|
ea23c8364d | ||
|
|
df92b8ac14 | ||
|
|
f19a56cf87 | ||
|
|
4955c52af7 | ||
|
|
20a35936ca | ||
|
|
d6a018a3f8 | ||
|
|
fef2861eae | ||
|
|
babe7a7798 | ||
|
|
7fbc7d458b | ||
|
|
c46a06b522 | ||
|
|
0ff736fadd | ||
|
|
3f6e41e8f4 | ||
|
|
dc73ace7c4 | ||
|
|
76d978144f | ||
|
|
55f72ac925 | ||
|
|
047eac6d9c | ||
|
|
16ea50ad55 | ||
|
|
1f241a3d45 | ||
|
|
a229a623bb | ||
|
|
f035687fca | ||
|
|
52268f0155 | ||
|
|
843f57399c | ||
|
|
cdc1c1ace1 | ||
|
|
ff72650b8d | ||
|
|
a74887db20 | ||
|
|
9084b170cb | ||
|
|
ff2c2290c7 | ||
|
|
c33963b250 | ||
|
|
eca84e0986 | ||
|
|
fb831b5f48 | ||
|
|
2878c1ba84 | ||
|
|
9b68fa0b27 | ||
|
|
a7ed968ee2 | ||
|
|
487a64abec | ||
|
|
1330aa8f1c | ||
|
|
53e8127781 | ||
|
|
e65b171aea | ||
|
|
268a5dac40 | ||
|
|
1afc96c055 | ||
|
|
924f8b8844 | ||
|
|
1c6919cf07 | ||
|
|
996234ad66 | ||
|
|
18c9ae64b4 | ||
|
|
272ca8c55d | ||
|
|
43882693a5 | ||
|
|
ee4eb8db20 | ||
|
|
8e0a40e717 | ||
|
|
9fc01263e6 | ||
|
|
052f9763b5 | ||
|
|
7747cd2232 | ||
|
|
bd55b2e566 | ||
|
|
2227a2c569 | ||
|
|
48dd045d91 | ||
|
|
3c693c1da5 | ||
|
|
7bb0ca59d1 | ||
|
|
587a2a1c04 | ||
|
|
c360743d41 | ||
|
|
8ef8a27583 | ||
|
|
a3ea2cd8c3 | ||
|
|
5ae0405446 | ||
|
|
eda83a4141 | ||
|
|
03a1f4370a | ||
|
|
f270642d67 | ||
|
|
2a03671fb9 | ||
|
|
375d4d9bc1 | ||
|
|
35512c4dc9 | ||
|
|
00cbb8bc8a | ||
|
|
98c7d877ec | ||
|
|
6edd6a4d55 | ||
|
|
aec852fa51 | ||
|
|
e42c692ec7 | ||
|
|
7e240251d5 | ||
|
|
ab2aea7bbf | ||
|
|
8dd8f989ab | ||
|
|
762256a71b | ||
|
|
78cd440a61 | ||
|
|
30661fedcb | ||
|
|
a3955a7ebb | ||
|
|
e295997d51 | ||
|
|
8495565a6f | ||
|
|
cefbfdf2a4 | ||
|
|
91dabc574d | ||
|
|
80091232a7 | ||
|
|
924de1d9ed | ||
|
|
60a7c50120 | ||
|
|
a01d31e25d | ||
|
|
2d4d9078c4 | ||
|
|
64319fa96e | ||
|
|
047017dc6a | ||
|
|
c557f29db2 | ||
|
|
1eb4ad8238 | ||
|
|
5490625d8d | ||
|
|
5389ef1a70 | ||
|
|
198ca65f7d | ||
|
|
04c3f7a603 | ||
|
|
85d256d53c | ||
|
|
ca66c1ea9c | ||
|
|
0fa5c62450 | ||
|
|
a3bb3872bf | ||
|
|
d637d2a7a5 | ||
|
|
001f2012a2 | ||
|
|
c39cb8cfe0 | ||
|
|
d5013bfd6c | ||
|
|
7bc1126978 | ||
|
|
7a66083e68 | ||
|
|
17fffa4e49 | ||
|
|
3fd7b4ee24 | ||
|
|
5459daa03d | ||
|
|
306df56203 | ||
|
|
117c15319d | ||
|
|
b8419ba3c5 | ||
|
|
8347de1cc6 | ||
|
|
8e481e27da | ||
|
|
7d3f354dd7 | ||
|
|
e0d7e5df85 | ||
|
|
913be6c349 | ||
|
|
1c4e58efe3 | ||
|
|
9c27e4766d | ||
|
|
eb0bd026d7 | ||
|
|
7e95371fe8 | ||
|
|
499998c537 | ||
|
|
8bf4ab0cd6 | ||
|
|
088b2c2920 | ||
|
|
34a261e522 | ||
|
|
ba3e290915 | ||
|
|
53fb7ae0ef | ||
|
|
366345e87e | ||
|
|
667418c71d | ||
|
|
b0fa3795e9 | ||
|
|
ec82aec55f | ||
|
|
7da57c6acd | ||
|
|
0becc7615a | ||
|
|
a4322c624f | ||
|
|
001024b4da | ||
|
|
792b0d419b | ||
|
|
7351a4d3b1 | ||
|
|
364537b324 | ||
|
|
b2c73f8325 | ||
|
|
f7b9d70054 | ||
|
|
6a45c6a8e0 | ||
|
|
c1335c6852 | ||
|
|
6c302c9bc8 | ||
|
|
fc67de8c19 | ||
|
|
494734bf27 | ||
|
|
11679a5188 | ||
|
|
aa9b4530c8 | ||
|
|
bea63f9d2d | ||
|
|
137e6dc184 | ||
|
|
de5e6e4163 | ||
|
|
350c9e02ea | ||
|
|
f59610081e | ||
|
|
50d67dce73 | ||
|
|
43ba31f402 | ||
|
|
3ae72114c7 | ||
|
|
783f9e5569 | ||
|
|
b5800ef718 | ||
|
|
44bfb8ebf0 | ||
|
|
ea748822ef | ||
|
|
c0e352094d | ||
|
|
a91eb48d48 | ||
|
|
6b1c8a7fff | ||
|
|
7cbe713873 | ||
|
|
0e8f285f4f | ||
|
|
cd17040f95 | ||
|
|
2784b267ec | ||
|
|
dbc6b814b2 | ||
|
|
0568a69d83 | ||
|
|
3cb3adc5ca | ||
|
|
3695610300 | ||
|
|
bf16fe4a37 | ||
|
|
9bf372ef43 | ||
|
|
414df5b372 | ||
|
|
5e431210fd | ||
|
|
8f7c828407 | ||
|
|
b8acccde90 | ||
|
|
019be067d9 | ||
|
|
632aead691 | ||
|
|
e3ffec5762 | ||
|
|
0e558e4c36 | ||
|
|
31f16510e2 | ||
|
|
d2d1195928 | ||
|
|
c520b29326 | ||
|
|
31ee15200d | ||
|
|
9f31ab8a6f | ||
|
|
23f2db01bb | ||
|
|
82b60b09d4 | ||
|
|
5bdb089b7f | ||
|
|
c92826c152 | ||
|
|
85e7fc5a0e | ||
|
|
10fe85933b | ||
|
|
412079a798 | ||
|
|
f9b29cfb62 | ||
|
|
73733308ba | ||
|
|
614554f26f | ||
|
|
8d91ca874b | ||
|
|
b075e25ab9 | ||
|
|
eaded9fdb1 | ||
|
|
19d50b9669 | ||
|
|
8e5467de70 | ||
|
|
fe1618d697 | ||
|
|
a3e610dbf2 | ||
|
|
b8c3f6d999 | ||
|
|
e6ae2e98cc | ||
|
|
654e111038 | ||
|
|
cd638b102f | ||
|
|
b74c6d5120 | ||
|
|
fd4e8766e4 | ||
|
|
c95d34389b | ||
|
|
83afff953f | ||
|
|
b8ffd2700c | ||
|
|
9bcb323568 | ||
|
|
e9e0aa37f4 | ||
|
|
0df06dc2fb | ||
|
|
53d09417dd | ||
|
|
eed4b70512 | ||
|
|
8fbad01d45 | ||
|
|
1a9dbec83c | ||
|
|
5985d506f1 | ||
|
|
fc706b6cbb | ||
|
|
7eeedf1b5f | ||
|
|
364fd38996 | ||
|
|
b412e88b02 | ||
|
|
11725a0999 | ||
|
|
d065afdbb1 | ||
|
|
c36d0257ec | ||
|
|
87a612f884 | ||
|
|
dd3a7a4edb | ||
|
|
d10d59303e | ||
|
|
b9cf2d9959 | ||
|
|
aaf828117d | ||
|
|
9c4e74ffa7 | ||
|
|
2a0f720153 | ||
|
|
cc17fe18a9 | ||
|
|
61ff5b2c76 | ||
|
|
56eae4afbe | ||
|
|
66bfa606a7 | ||
|
|
32fb2e69ff | ||
|
|
c71460e4b6 | ||
|
|
d885e92674 | ||
|
|
9d4a69c1d0 | ||
|
|
0656ceb149 | ||
|
|
95b12bad34 | ||
|
|
fa116389c2 | ||
|
|
8ca5788561 | ||
|
|
1dc33129e5 | ||
|
|
c96463bda2 | ||
|
|
edbaf6d697 | ||
|
|
58275ecd13 | ||
|
|
c6d1137eb0 | ||
|
|
fb032ea6e7 | ||
|
|
536b3497c9 | ||
|
|
8f09a1d837 | ||
|
|
c255082ef5 | ||
|
|
76b7453f90 | ||
|
|
66ed7c9ea3 | ||
|
|
ac2f13adef | ||
|
|
6b919f3a2e | ||
|
|
4d21bae669 | ||
|
|
7ea0bbb85c | ||
|
|
3ddec99f4a | ||
|
|
e1f12668fa | ||
|
|
686da5a948 | ||
|
|
8a2829de87 | ||
|
|
3a592e56ba | ||
|
|
3c91b6558d | ||
|
|
b9a6970bfd | ||
|
|
20f8c6af3c | ||
|
|
c35ed68051 | ||
|
|
75a32d22a3 | ||
|
|
71e262c37f | ||
|
|
04b909c837 | ||
|
|
309ee78903 | ||
|
|
d6f5552ccf | ||
|
|
67a973a17d | ||
|
|
0b60601f86 | ||
|
|
0b5da9f0da | ||
|
|
0589641bf0 | ||
|
|
ddf972cede | ||
|
|
73de49323c | ||
|
|
16385af3ef | ||
|
|
6cb0be82ca | ||
|
|
2dd31ce6ee | ||
|
|
31a9e18997 | ||
|
|
821c7dc190 | ||
|
|
eedd93d782 | ||
|
|
c5faf3d174 | ||
|
|
1f3f849106 | ||
|
|
ca74152d1d | ||
|
|
4fd0f15d90 | ||
|
|
b9f19fc357 | ||
|
|
2380359270 | ||
|
|
d75adb49f4 | ||
|
|
90da155053 | ||
|
|
2a61a03bdf | ||
|
|
a4bdf2454b | ||
|
|
4b503a080b | ||
|
|
46fe37b4da | ||
|
|
d6275cdd7c | ||
|
|
45cab12392 | ||
|
|
5ecdfb53c2 | ||
|
|
d86b325dfe | ||
|
|
c65ea9c47c | ||
|
|
741717aa38 | ||
|
|
2d13cd2f1d | ||
|
|
788e7cc777 | ||
|
|
0ac89ac2e3 | ||
|
|
e5ea361b53 | ||
|
|
df0155abe1 | ||
|
|
ca00ffa101 | ||
|
|
3ad8965959 | ||
|
|
460f83580e | ||
|
|
c7ad7113d7 | ||
|
|
0a6ebadb52 | ||
|
|
b9e401aaa3 | ||
|
|
18ab94135f | ||
|
|
be0efa2332 | ||
|
|
9bde5de601 | ||
|
|
db42ed1e4f | ||
|
|
262ffe458b | ||
|
|
e59f5db145 | ||
|
|
362c604744 | ||
|
|
68a03cc877 | ||
|
|
671da760d3 | ||
|
|
3c3d913934 | ||
|
|
50be36400c | ||
|
|
5f9523afa6 | ||
|
|
81a31b9e7b | ||
|
|
d0affcb376 | ||
|
|
9939cf1d77 | ||
|
|
ce7f926e92 | ||
|
|
6b4f77bdfe | ||
|
|
267792aa1e | ||
|
|
9331cbff4b | ||
|
|
d30a5f1b95 | ||
|
|
d6e25403ee | ||
|
|
79f4a7cef0 | ||
|
|
9ed3ede0d9 | ||
|
|
771b7cfcc7 | ||
|
|
7bb86e4118 | ||
|
|
c992fd48b0 | ||
|
|
afc8241c2c | ||
|
|
6cae37e720 | ||
|
|
d604aec9f1 | ||
|
|
bb4698429f | ||
|
|
634e3b0e46 | ||
|
|
21c7c8a008 | ||
|
|
9048429bbb | ||
|
|
9c33fcb32a | ||
|
|
eb1f2ac01c | ||
|
|
d88e940a57 | ||
|
|
f27f796b34 | ||
|
|
318ee3b7d3 | ||
|
|
f894585a2e | ||
|
|
ac2f63b138 | ||
|
|
be8f25f8b8 | ||
|
|
c85e4227cf | ||
|
|
c9042704d5 | ||
|
|
57f29a2c5d | ||
|
|
142e9f4a1a | ||
|
|
0c65c27e0c | ||
|
|
4a53e56bd2 | ||
|
|
d349a4640f | ||
|
|
dfcdb1a747 | ||
|
|
e05ef73011 | ||
|
|
2c29b25782 | ||
|
|
d87cad76fb | ||
|
|
9e47b61c8f | ||
|
|
4413224a31 | ||
|
|
d882652a85 | ||
|
|
f73b965fcd | ||
|
|
fe598a05f6 | ||
|
|
09977fdfec | ||
|
|
b9ebb05246 | ||
|
|
955e36a955 | ||
|
|
972591fe39 | ||
|
|
14db88d6bb | ||
|
|
64d0621d2b | ||
|
|
5dabdfe354 | ||
|
|
e7c0ca47b4 | ||
|
|
2bb7c05ed1 | ||
|
|
20ad03fe15 | ||
|
|
58231e55df | ||
|
|
12674c0824 | ||
|
|
c59e11a332 | ||
|
|
ec1d4c5500 | ||
|
|
34f45d011d | ||
|
|
539f9d4da0 | ||
|
|
c6342ed84c | ||
|
|
9072a6a7f0 | ||
|
|
3b5d10d087 | ||
|
|
0d5d3a1b22 | ||
|
|
8d2e023ec0 | ||
|
|
4a1473aee9 | ||
|
|
78f9e38425 | ||
|
|
08c7691d1e | ||
|
|
62bf9957dc | ||
|
|
dafc9983f5 | ||
|
|
a44b8e4bfc | ||
|
|
c8e69c6139 | ||
|
|
da8893f477 | ||
|
|
7562376373 | ||
|
|
619cebb62c | ||
|
|
6a2200a8e6 | ||
|
|
661433c115 | ||
|
|
e7e7a817bb | ||
|
|
d245226053 | ||
|
|
a5d10a6256 | ||
|
|
c32761e786 | ||
|
|
095696ec04 | ||
|
|
7971cf0adc | ||
|
|
fc83883934 | ||
|
|
1550f29f06 | ||
|
|
a206980242 | ||
|
|
8c2f56b0e6 | ||
|
|
b4349b41ce | ||
|
|
67f04787d6 | ||
|
|
1ee922d16c | ||
|
|
14ab586603 | ||
|
|
372070ab39 | ||
|
|
4004a93d1a | ||
|
|
c2bb190dce | ||
|
|
b8eae60fcc | ||
|
|
c86ff5d084 | ||
|
|
126da094bd | ||
|
|
f713b14ba0 | ||
|
|
a4e20f79a3 | ||
|
|
6b146ed2d1 | ||
|
|
e0e0baf076 | ||
|
|
95e799ed6e | ||
|
|
202aa25c09 | ||
|
|
06de172952 | ||
|
|
ff5ee29566 | ||
|
|
d393497641 | ||
|
|
0034538794 | ||
|
|
33d2163f19 | ||
|
|
ea26171c18 | ||
|
|
82dfcbcd83 | ||
|
|
233453267e | ||
|
|
f3c27f706f | ||
|
|
983d79b3e6 | ||
|
|
6d8abc2e30 | ||
|
|
38775cffdf | ||
|
|
b13a75a223 | ||
|
|
21026d9414 | ||
|
|
ba74051502 | ||
|
|
cdbe4c9b86 | ||
|
|
ca04c13315 | ||
|
|
3c86af0e59 | ||
|
|
ddaa1bf0d4 | ||
|
|
6b8ba3c15e | ||
|
|
7536c312ee | ||
|
|
a8b6eb9b70 | ||
|
|
67385b7ed4 | ||
|
|
64e61aac4a | ||
|
|
2fd5b944ad | ||
|
|
f91606bb17 | ||
|
|
122bc6b927 | ||
|
|
3491dbfd04 | ||
|
|
871067acd8 | ||
|
|
06cf7afbc2 | ||
|
|
81927334f2 | ||
|
|
01bf9ca42a | ||
|
|
c8c6533440 | ||
|
|
f1b15f7e92 | ||
|
|
e0c351f0e4 | ||
|
|
7957acf42f | ||
|
|
c3e8d76d63 | ||
|
|
128a3ab1be | ||
|
|
df3e9e5f51 | ||
|
|
c322458dcb | ||
|
|
21be1bd58e | ||
|
|
469a267150 | ||
|
|
090727b1d3 | ||
|
|
85ffbcf05e | ||
|
|
528abc9c97 | ||
|
|
8b98fd06ed | ||
|
|
bc6fb0c934 | ||
|
|
e773e3302c | ||
|
|
0cf59cf0fa | ||
|
|
bc471cb0bd | ||
|
|
429510e168 | ||
|
|
4c9401175c | ||
|
|
235673dac8 | ||
|
|
d737948f64 | ||
|
|
52283478c8 | ||
|
|
c84be5de61 | ||
|
|
d85982dc51 | ||
|
|
5c61f6cb65 | ||
|
|
4c0a94d2b9 | ||
|
|
5c090d25e1 | ||
|
|
89c0706abc | ||
|
|
e5695f862f | ||
|
|
e3db5fc601 | ||
|
|
9c51050283 | ||
|
|
17779bad94 | ||
|
|
fed58f03bf | ||
|
|
c5b3b8dd68 | ||
|
|
46986714d4 | ||
|
|
4f3debcb5b | ||
|
|
223ef72250 | ||
|
|
cf467db61d | ||
|
|
fae1d13892 | ||
|
|
4265bcb178 | ||
|
|
9471c69882 | ||
|
|
79c0b446e1 | ||
|
|
a478f2460b | ||
|
|
2dc599f266 | ||
|
|
d7f7ef9965 | ||
|
|
888e44e53d | ||
|
|
18d28533eb | ||
|
|
56527e5dd9 | ||
|
|
997a771dc8 | ||
|
|
77f0012f6b | ||
|
|
b7b5ffa8dd | ||
|
|
34b66002e9 | ||
|
|
71b560667b | ||
|
|
9dd51b79b5 | ||
|
|
7fd062c4d8 | ||
|
|
3731b65bd5 | ||
|
|
6057b134ae | ||
|
|
0749de3d1f | ||
|
|
d48c557134 | ||
|
|
a705fbca73 | ||
|
|
276c480f50 | ||
|
|
25ba68104b | ||
|
|
3d01e4d0cf | ||
|
|
1b0b0ca445 | ||
|
|
e1a2591c4d | ||
|
|
f8a12917e2 | ||
|
|
37b45d411d | ||
|
|
22ebf21487 | ||
|
|
bf5fffaca7 | ||
|
|
9debd22179 | ||
|
|
a8ce1354c8 | ||
|
|
0a780a959a | ||
|
|
951b4ed002 | ||
|
|
755ec8bf2f | ||
|
|
1c1407e083 | ||
|
|
9463c3c69f | ||
|
|
54bcf5626f | ||
|
|
ba8a50c829 | ||
|
|
bb57a9e616 | ||
|
|
4f4dfe3ac0 | ||
|
|
d4ce5b1c2a | ||
|
|
b6d1bd7335 | ||
|
|
17ec88d96f | ||
|
|
0df38cd64e | ||
|
|
0932c5c498 | ||
|
|
73ca4ebdbc | ||
|
|
da6596e516 | ||
|
|
d88629e23f | ||
|
|
d581401f4e | ||
|
|
60c35cb93c | ||
|
|
2c3fea321b | ||
|
|
40f00c6f0b | ||
|
|
00e51f32b5 | ||
|
|
f90fb8b946 | ||
|
|
2ff1fa1b85 | ||
|
|
7eff36b3bb | ||
|
|
5332b31b92 | ||
|
|
16640ee174 | ||
|
|
5fe170666a | ||
|
|
7e6f81f814 | ||
|
|
80c770357c | ||
|
|
5cc317de5b | ||
|
|
515e5f8c8a | ||
|
|
3d53bda121 | ||
|
|
8bc5b16527 | ||
|
|
c1a927fff1 | ||
|
|
760325eb76 | ||
|
|
bf256aa5a7 | ||
|
|
8dbe6fc0b7 | ||
|
|
fe8b0e98ab | ||
|
|
ef45578af3 | ||
|
|
89b88416b3 | ||
|
|
5d913ad192 | ||
|
|
711035fd8f | ||
|
|
0f74165c9d | ||
|
|
46e1a87e9e | ||
|
|
f998eee467 | ||
|
|
230d6a435f | ||
|
|
53c0982c8b | ||
|
|
d6cfa57ef3 | ||
|
|
49b9dc8888 | ||
|
|
1335c44deb | ||
|
|
9b5ea13a33 | ||
|
|
66eeee5548 | ||
|
|
597c045f9e | ||
|
|
a4b899c256 | ||
|
|
5421aad03e | ||
|
|
eeccfb27f8 | ||
|
|
4cf3280500 | ||
|
|
8c4a9aa6e3 | ||
|
|
9ab566884d | ||
|
|
37102e5a01 | ||
|
|
5a98fa1f76 | ||
|
|
114f562758 | ||
|
|
b3c8045b52 | ||
|
|
a0419bc1f0 | ||
|
|
e35a9da921 | ||
|
|
97447b2f3b | ||
|
|
c67f313ee8 | ||
|
|
49a9f6f2db | ||
|
|
e6683803ed | ||
|
|
27fa284eda | ||
|
|
b98e331375 | ||
|
|
6c9bd7a632 | ||
|
|
5816f495f4 | ||
|
|
5d5a85b7b6 | ||
|
|
c78cf82fc6 | ||
|
|
d77677312c | ||
|
|
d38fcb0549 | ||
|
|
c7410b0be9 | ||
|
|
20c561c83c | ||
|
|
7320c10dd3 | ||
|
|
f418481b9f | ||
|
|
a3516474e8 | ||
|
|
9e2e0019fb | ||
|
|
aef3d89814 | ||
|
|
f2641fb0e5 | ||
|
|
e50438dc11 | ||
|
|
6062df0923 | ||
|
|
989c52ef24 | ||
|
|
4a589286b7 | ||
|
|
3327df8d9c | ||
|
|
3cdaad060b | ||
|
|
0b81dd387b | ||
|
|
64dc002c3f | ||
|
|
6c7a28a7b5 | ||
|
|
21158cb6bc | ||
|
|
71bc237639 | ||
|
|
c6da627b7d | ||
|
|
a3ac1caac6 | ||
|
|
8f3e6f1a50 | ||
|
|
99b7f996e2 | ||
|
|
aa0a9e2976 | ||
|
|
9028898ba7 | ||
|
|
0e8c1ec023 | ||
|
|
313c0ddf28 | ||
|
|
2c38de26b7 | ||
|
|
fc2a564cc0 | ||
|
|
b613758419 | ||
|
|
9c03915cb0 | ||
|
|
e29aa4e205 | ||
|
|
a45c9f9f50 | ||
|
|
b3ba17bfd4 | ||
|
|
2610739624 | ||
|
|
567a915336 | ||
|
|
68eddd2377 | ||
|
|
aeb92416c8 | ||
|
|
cca5c49eaa | ||
|
|
8c778c14dc | ||
|
|
d5c798d1a9 | ||
|
|
14e1eea22d | ||
|
|
ab6b37bdcf | ||
|
|
c8c4eb59b7 | ||
|
|
2651abbe6c | ||
|
|
7b77d991df | ||
|
|
64465510de | ||
|
|
f59749b1c3 | ||
|
|
27ef7e5538 | ||
|
|
a7a467a167 | ||
|
|
21af75a2d2 | ||
|
|
2bd3366bb1 | ||
|
|
d89720330f | ||
|
|
8d1f286f30 | ||
|
|
c7108a632c | ||
|
|
b025cfeea9 | ||
|
|
bc8fcc744c | ||
|
|
a3f1317add | ||
|
|
c90d8284ef | ||
|
|
7ab9664255 | ||
|
|
3a22657645 | ||
|
|
64d75c012e | ||
|
|
4567f264b4 | ||
|
|
cbcd12631d | ||
|
|
c4f9a475f3 | ||
|
|
71d310c50f | ||
|
|
b486786041 | ||
|
|
3dd26b500d | ||
|
|
aefbe1f5b6 | ||
|
|
13135498c1 | ||
|
|
9f918972d2 | ||
|
|
b25805348f | ||
|
|
d6c48f80f4 | ||
|
|
59dab6a568 | ||
|
|
ecfb96d339 | ||
|
|
e0baf4c7ec | ||
|
|
e4444ae6a5 | ||
|
|
8e4adb6e39 | ||
|
|
6aaa446354 | ||
|
|
7d5f6c8331 | ||
|
|
3d8672bc59 | ||
|
|
b49db58ec2 | ||
|
|
edc808ee89 | ||
|
|
a28d691387 | ||
|
|
56a32047b8 | ||
|
|
ef71ca05a9 | ||
|
|
48d5d6bed2 | ||
|
|
04abc4dacd | ||
|
|
fd41801977 | ||
|
|
1be082a0e1 | ||
|
|
6204698e05 | ||
|
|
edba325a3e | ||
|
|
518cbd10e0 | ||
|
|
0a8761ee68 | ||
|
|
3d4476c9fb | ||
|
|
e05b64b56b | ||
|
|
4150826211 | ||
|
|
469776afd6 | ||
|
|
5c564e53ca | ||
|
|
853cd9670a | ||
|
|
cfbc731eab | ||
|
|
46f991f578 | ||
|
|
ad70ece73e | ||
|
|
39cb1029e9 | ||
|
|
c058a511e6 | ||
|
|
a39c470f2d | ||
|
|
72fcdb128a | ||
|
|
44667b5ffb | ||
|
|
696d1c4ec3 | ||
|
|
0b10c50a0b | ||
|
|
c78aac3051 | ||
|
|
6efb3a3372 | ||
|
|
2845c72bde | ||
|
|
a650641da4 | ||
|
|
1ed5ff306d | ||
|
|
bf57a786e6 | ||
|
|
37889f27de | ||
|
|
80bef5f6b6 | ||
|
|
bd8288d6ef | ||
|
|
98c238064e | ||
|
|
312fa6d134 | ||
|
|
a783da823e | ||
|
|
17485023a2 | ||
|
|
0be987239e | ||
|
|
75f40e7160 | ||
|
|
73d5902bed | ||
|
|
eb045a0dea | ||
|
|
b70b895fc5 | ||
|
|
46331e415c | ||
|
|
dcea3cf2c6 | ||
|
|
e02c7ff249 | ||
|
|
f3d062aaf4 | ||
|
|
bacb98be32 | ||
|
|
7ef7719b6b | ||
|
|
f740e0fefb | ||
|
|
a33f71289d | ||
|
|
8c498acd4c | ||
|
|
3d773beff2 | ||
|
|
d88ab2ca60 | ||
|
|
287d5d37b1 | ||
|
|
f9d1893f96 | ||
|
|
2c5907a8b1 | ||
|
|
954a0c2a14 | ||
|
|
b20aa865b9 | ||
|
|
ed8c6c04d4 | ||
|
|
4b674ecfe3 | ||
|
|
5818f3f997 | ||
|
|
7d731870e5 | ||
|
|
1f26e85399 | ||
|
|
de02220a12 | ||
|
|
4d24fa6c15 | ||
|
|
50d14fb6db | ||
|
|
b6cc845caf | ||
|
|
635b67dbf3 | ||
|
|
e7289563df | ||
|
|
d501b676e9 | ||
|
|
fbc0b57dd1 | ||
|
|
cf0fcf3ad7 | ||
|
|
e2e803f76c | ||
|
|
2c07d27ad7 | ||
|
|
0b9d4a47ad | ||
|
|
67f5f16f84 | ||
|
|
ae9d16baf2 | ||
|
|
fe51a4f8d0 | ||
|
|
300c7b1518 | ||
|
|
5241c1c704 | ||
|
|
dae96e7384 | ||
|
|
3fa8f76d99 | ||
|
|
52c3df1a8e | ||
|
|
477df86ff1 | ||
|
|
b7742ddb9b | ||
|
|
ce8731b746 | ||
|
|
08faf21b2e | ||
|
|
60615e60aa | ||
|
|
2dd08f070e | ||
|
|
110e752552 | ||
|
|
0961103933 | ||
|
|
0fa94e0946 | ||
|
|
9b9acfd4a7 | ||
|
|
82695aba7d | ||
|
|
36dd533ef3 | ||
|
|
2735481da8 | ||
|
|
edec1220fc | ||
|
|
c5b3f6c27a | ||
|
|
1d033ef441 | ||
|
|
83ac2c5005 | ||
|
|
0decc1252b | ||
|
|
f2e1cc9dae | ||
|
|
f7c800863e | ||
|
|
6d73454942 | ||
|
|
2e2a3aa048 | ||
|
|
e23e291dd4 | ||
|
|
6a0c6c4a9b | ||
|
|
94cb0d0a7e | ||
|
|
d78c689e55 | ||
|
|
3915efbfd5 | ||
|
|
853f6b7da2 | ||
|
|
73aa43611f | ||
|
|
c19788dd18 | ||
|
|
71072b4beb | ||
|
|
c9383eab99 | ||
|
|
052a1f294e | ||
|
|
325f20d5c2 | ||
|
|
1c28da7bbd | ||
|
|
aba5e884eb | ||
|
|
9ac5690a7d | ||
|
|
8de814ab34 | ||
|
|
7929a6c133 | ||
|
|
9840148ba9 | ||
|
|
7e223a2a10 | ||
|
|
c9e76c978e | ||
|
|
2601162243 | ||
|
|
37cef84643 | ||
|
|
23e6fa1ec5 | ||
|
|
db116971ce | ||
|
|
2b124b1c69 | ||
|
|
9356d7bbb1 | ||
|
|
29a867d5ae | ||
|
|
86dd612882 | ||
|
|
42d3368955 | ||
|
|
21ae81ffdb | ||
|
|
b33434d02a | ||
|
|
d3e94cbceb | ||
|
|
9b4f6c84cd | ||
|
|
4d31d5ee11 | ||
|
|
9878477896 | ||
|
|
c0a2ab7b77 | ||
|
|
30ba79f6a0 | ||
|
|
cd3c97f113 | ||
|
|
e4a1f3a175 | ||
|
|
6121c162ff | ||
|
|
0d74b27101 | ||
|
|
7fa8cdd03e | ||
|
|
fe9031b26f | ||
|
|
326cd6a1f8 | ||
|
|
063f92f8f4 | ||
|
|
be6a73f102 | ||
|
|
b714c4598a | ||
|
|
0f192998eb | ||
|
|
8a5c7dec71 | ||
|
|
69e4e9a2ae | ||
|
|
4230be0c80 | ||
|
|
d45c9fc522 | ||
|
|
efa99a177e | ||
|
|
c2384ecc6f | ||
|
|
2f38452565 | ||
|
|
5cebceadda | ||
|
|
722a716de3 | ||
|
|
614d18cd3d | ||
|
|
54ce8c2622 | ||
|
|
329c161054 | ||
|
|
f8e84b3c3f | ||
|
|
c9809371ab | ||
|
|
a48750e257 | ||
|
|
0d4c69cc6f | ||
|
|
479b2bc075 | ||
|
|
2ade05d60f | ||
|
|
59fc3804be | ||
|
|
48138d32b6 | ||
|
|
ff5e788889 | ||
|
|
ab7d83384f | ||
|
|
48136c5bbc | ||
|
|
0219e5dfe0 | ||
|
|
0631cb4984 | ||
|
|
40b96e673b | ||
|
|
36ca858668 | ||
|
|
899cac0aac | ||
|
|
16b732fe8a | ||
|
|
1bf2f8d0b7 | ||
|
|
c756bcb9d1 | ||
|
|
42424b515b | ||
|
|
bd956b5f16 | ||
|
|
9be5199f7c | ||
|
|
9db19c5e96 | ||
|
|
91b4233d3a | ||
|
|
0b905c28c1 | ||
|
|
f4286a4d12 | ||
|
|
6ffa2ba1b2 | ||
|
|
e9250d62c5 | ||
|
|
08999bf315 | ||
|
|
2bd670a3dd | ||
|
|
f342b2c9f6 | ||
|
|
2a0bb5b9ee | ||
|
|
c3c5342b48 | ||
|
|
d7d8e9730b | ||
|
|
7c60ee8df1 | ||
|
|
ee9f4856a2 | ||
|
|
444526ad58 | ||
|
|
844c4dcdc8 | ||
|
|
881d92632c | ||
|
|
76d4e1209f | ||
|
|
d956498c8c | ||
|
|
e09dd56807 | ||
|
|
30ec1c94cc | ||
|
|
5d68dac90e | ||
|
|
77e5121d43 | ||
|
|
74d7d10554 | ||
|
|
2f4c4d9176 | ||
|
|
1dd9d55d82 | ||
|
|
8cbffa179d | ||
|
|
5bb79de70b | ||
|
|
534f9a63bf | ||
|
|
f0f5cc52d9 | ||
|
|
bad6d8a59e | ||
|
|
7aa28e4a3a | ||
|
|
e80a7731c9 | ||
|
|
3cd662eaeb | ||
|
|
6ead24b315 | ||
|
|
cdde832ed3 | ||
|
|
57ba60ce54 | ||
|
|
ed6b85241b | ||
|
|
918f7a504c | ||
|
|
3260cb40b5 | ||
|
|
a79c1159a9 | ||
|
|
65a04246cd | ||
|
|
f1245685dc | ||
|
|
ec3a5c2989 | ||
|
|
b20b38d44f | ||
|
|
d5253f26f4 | ||
|
|
a65a841c56 | ||
|
|
1b0b24daf5 | ||
|
|
7010ed454c | ||
|
|
ce86157067 | ||
|
|
3097c8fbdc | ||
|
|
363e2f10bb | ||
|
|
bfd9fe80ef | ||
|
|
c2080324b7 | ||
|
|
875ad04fde | ||
|
|
0124e491d0 | ||
|
|
81698ef1ed | ||
|
|
2ff10fcd0a | ||
|
|
5823f5e254 | ||
|
|
7807a93e10 | ||
|
|
c6a2a6f739 | ||
|
|
241e53ed45 | ||
|
|
d605b4b8f9 | ||
|
|
0e359a6321 | ||
|
|
5b84cd0a61 | ||
|
|
5bd7cc9c9d | ||
|
|
886f0c7df3 | ||
|
|
3989cc19e9 | ||
|
|
bcb59159ed | ||
|
|
2b52f92647 | ||
|
|
71ed842dfd | ||
|
|
f45248df80 | ||
|
|
5729f64ddc | ||
|
|
2a869419b4 | ||
|
|
4a2f4c1bce | ||
|
|
5ef731fc57 | ||
|
|
71ebd64f4e | ||
|
|
9f0e0dbd37 | ||
|
|
ef30a85afb | ||
|
|
1b809e4e8e | ||
|
|
3d3bb45a46 | ||
|
|
d2a98ae954 | ||
|
|
2e1ce7fc87 | ||
|
|
920cf6de14 | ||
|
|
1eb31174a5 | ||
|
|
ff4487ff74 | ||
|
|
54c58327f1 | ||
|
|
db5e94b14a | ||
|
|
7167e6d5e4 | ||
|
|
39a66b608b | ||
|
|
b06efb6ab7 | ||
|
|
ab4bce4787 | ||
|
|
469c179b32 | ||
|
|
190ab79606 | ||
|
|
669f1b0f4a | ||
|
|
31de661bbb | ||
|
|
3a67d1cf8d | ||
|
|
c0f454ddfa | ||
|
|
ef0a22f9ec | ||
|
|
533a77d6d5 | ||
|
|
76ae75689c | ||
|
|
a780fc59e2 | ||
|
|
28085cf7d8 | ||
|
|
a3cc5df317 | ||
|
|
2eff53b2bb | ||
|
|
8d6ce78c65 | ||
|
|
b52a3a021d | ||
|
|
ae39e338fe | ||
|
|
e243c562c2 | ||
|
|
4c267f7732 | ||
|
|
647ba6ec9d | ||
|
|
ba6d700e7e | ||
|
|
e485a7b9bb | ||
|
|
bfda52ed79 | ||
|
|
941f90d5c1 | ||
|
|
14a379d448 | ||
|
|
671fcaffc3 | ||
|
|
bc8150adfa | ||
|
|
b750b01acc | ||
|
|
996a2c74fa | ||
|
|
d85fee27a9 | ||
|
|
cdd4d9ea9e | ||
|
|
cedd1a2591 | ||
|
|
ac4a975be5 | ||
|
|
996f8fff28 | ||
|
|
e733553295 | ||
|
|
0c4e1b51ab | ||
|
|
c6da1a3918 | ||
|
|
c1eb35a35e | ||
|
|
b5e0f142cc | ||
|
|
8713135b01 | ||
|
|
7cdd8871e5 | ||
|
|
596689b4c9 | ||
|
|
a872fabe7d | ||
|
|
bc21a7155d | ||
|
|
b7bba6a689 | ||
|
|
04f9e92bff | ||
|
|
16fb6665ec | ||
|
|
d84da71310 | ||
|
|
77a30ac0c2 | ||
|
|
56fb954d64 | ||
|
|
99981b5e66 | ||
|
|
19ae9d3ee6 | ||
|
|
d03aa0c0c7 | ||
|
|
3c41ec08a3 | ||
|
|
fdc4cf9869 | ||
|
|
a0ecfcc1dc | ||
|
|
b30d729aa4 | ||
|
|
f8af1a1baa | ||
|
|
ab27a3bd45 | ||
|
|
f3acc7c839 | ||
|
|
6f6b54ea05 | ||
|
|
3cad8e4c5b | ||
|
|
9535e2fd6d | ||
|
|
0ea7344c30 | ||
|
|
55dce14655 | ||
|
|
5bf35dc687 | ||
|
|
c5828df198 | ||
|
|
77e322afa6 | ||
|
|
541257849d | ||
|
|
80560d4a4a | ||
|
|
38bb4a4908 | ||
|
|
2b74b47b4a | ||
|
|
109340033e | ||
|
|
0f246b8df5 | ||
|
|
5b03160295 | ||
|
|
7b0513d1e6 | ||
|
|
466520366d | ||
|
|
9dbcbdbe66 | ||
|
|
a9b9718ffa | ||
|
|
fb073373d6 | ||
|
|
fd050693a2 | ||
|
|
dad6247cb0 | ||
|
|
841222fa21 | ||
|
|
0576810438 | ||
|
|
b755330f4c | ||
|
|
cf59f35a4e | ||
|
|
2131a1fe7f | ||
|
|
a88a94c4f1 | ||
|
|
1c286c7bc4 | ||
|
|
6d670991c3 | ||
|
|
3439045228 | ||
|
|
b710e107d6 | ||
|
|
2673c2c072 | ||
|
|
e393048488 | ||
|
|
2feea70311 | ||
|
|
62f29ba3fa | ||
|
|
89b1cfcd85 | ||
|
|
89e187947e | ||
|
|
d2faa93241 | ||
|
|
0df099a6a5 | ||
|
|
482ac12c9b | ||
|
|
b2592f5d31 | ||
|
|
d0e8b0c962 | ||
|
|
d48d3aba69 | ||
|
|
cbc99d45c6 | ||
|
|
be68a5339c | ||
|
|
606b05eec1 | ||
|
|
a1ee7d92a9 | ||
|
|
6941155572 | ||
|
|
b6d73ac081 | ||
|
|
6fec4acd82 | ||
|
|
b241a19e87 | ||
|
|
a7ba55ffb0 | ||
|
|
115e3eeda9 | ||
|
|
21897d7fbd | ||
|
|
31c7c019cb | ||
|
|
b97f76e678 | ||
|
|
839a70cc37 | ||
|
|
a068567926 | ||
|
|
06fd8123c3 | ||
|
|
c2f3477a82 | ||
|
|
ff64d8cf4d | ||
|
|
e8e8104b36 | ||
|
|
e1dca46423 | ||
|
|
ea5a3bf0b2 | ||
|
|
98867d8d71 | ||
|
|
c88c943cda | ||
|
|
3ef90a9e47 | ||
|
|
58a21bee07 | ||
|
|
676b7e60f3 | ||
|
|
43b88cd628 | ||
|
|
e163ed449d | ||
|
|
ee749f700f | ||
|
|
bb7c7cdf33 | ||
|
|
ffe45e8b76 | ||
|
|
f86ef0128e | ||
|
|
bdab701470 | ||
|
|
1ecb9165ee | ||
|
|
2ff3b95117 | ||
|
|
3ad5097b12 | ||
|
|
d68a2ffaf3 | ||
|
|
913dcead7f | ||
|
|
1358209a9a | ||
|
|
b729a44209 | ||
|
|
5a55fa5e48 | ||
|
|
d419eaf463 | ||
|
|
a8deebde4d | ||
|
|
2ec4e84db4 | ||
|
|
075b3f6468 | ||
|
|
7911841355 | ||
|
|
d2c75a33d5 | ||
|
|
15dfd19f58 | ||
|
|
9ae6b40818 | ||
|
|
aa2da80768 | ||
|
|
b05fc5bb2b | ||
|
|
c99c86af7f | ||
|
|
f552173be3 | ||
|
|
d02aa3ced1 | ||
|
|
d0eb0d5037 | ||
|
|
fbfec961d5 | ||
|
|
fba7517cc6 | ||
|
|
0c125eba2c | ||
|
|
7f4bb24fd3 | ||
|
|
b1ea60484e | ||
|
|
57c40cbd09 | ||
|
|
95d1464e36 | ||
|
|
092e533a30 | ||
|
|
18c6ef8aac | ||
|
|
6be647a85f | ||
|
|
6f7edbc92e | ||
|
|
9beb3a9b6c | ||
|
|
3b6e6317b8 | ||
|
|
a9b5fcd923 | ||
|
|
38d4b2a883 | ||
|
|
e2e7d0a6aa | ||
|
|
aa5c15a728 | ||
|
|
7dea5012ce | ||
|
|
fdca19e66d | ||
|
|
c9e341b5d4 | ||
|
|
012d1e4b3d | ||
|
|
31a096dec2 | ||
|
|
a52a5e7ef2 | ||
|
|
a0d74d1e9d | ||
|
|
0cbf77eb9f | ||
|
|
36470eb138 | ||
|
|
e80e54a61a | ||
|
|
118c0d209d | ||
|
|
9b9e907013 | ||
|
|
4ac4bc5c18 | ||
|
|
8c926d6af6 | ||
|
|
a1d85155fd | ||
|
|
2d0619afec | ||
|
|
ab9d589995 | ||
|
|
4fb5157719 | ||
|
|
641eb7821b | ||
|
|
87f2ae82cd | ||
|
|
469b715442 | ||
|
|
04ffd22b4d | ||
|
|
c120f8a8d8 | ||
|
|
0a5eee4d99 | ||
|
|
2b49988013 | ||
|
|
954b3e784f | ||
|
|
0612685fac | ||
|
|
e3a22dcbfa | ||
|
|
4f660966d0 | ||
|
|
7df22cd8e0 | ||
|
|
01764cc581 | ||
|
|
08cf9aa5a7 | ||
|
|
1ae67e1de8 | ||
|
|
f2cba6cad1 | ||
|
|
df3c46349a | ||
|
|
a2d5b8050a | ||
|
|
01c310a78f | ||
|
|
a9e761ec13 | ||
|
|
761c1cd305 | ||
|
|
6f60555f79 | ||
|
|
c901443676 | ||
|
|
a51be7d498 | ||
|
|
f3ceebbe06 | ||
|
|
57d9b96b53 | ||
|
|
5895690b58 | ||
|
|
d26f8dd665 | ||
|
|
2ba350984f | ||
|
|
60513f93a3 | ||
|
|
3b574096b8 | ||
|
|
58905a1188 | ||
|
|
aa88be335e | ||
|
|
f90dffbf1a | ||
|
|
1fb6366c41 | ||
|
|
4736e03108 | ||
|
|
18bedc0493 | ||
|
|
74948ae5c1 | ||
|
|
9b57f7fa33 | ||
|
|
866045968d | ||
|
|
f2e0cf8a92 | ||
|
|
4c39edbeb9 | ||
|
|
b388ac5bb5 | ||
|
|
7855859726 | ||
|
|
5df7ed2f32 | ||
|
|
25ded79190 | ||
|
|
d3e00f038b | ||
|
|
d5f13018a7 | ||
|
|
c6e3805bbb | ||
|
|
ea451e3c22 | ||
|
|
b97f890a8c | ||
|
|
6198165df8 | ||
|
|
8090071eff | ||
|
|
89c80947df | ||
|
|
b51751e892 | ||
|
|
45d4ab4c22 | ||
|
|
f536718aaa | ||
|
|
f1740da9ff | ||
|
|
9bdbe88a66 | ||
|
|
d25240fe9f | ||
|
|
20b6f9cceb | ||
|
|
f27fd9f899 | ||
|
|
13cf0c1288 | ||
|
|
ae762574e5 | ||
|
|
126b9ae381 | ||
|
|
57fe3b6621 | ||
|
|
56fa9714b5 | ||
|
|
03a8ca5c1b | ||
|
|
78027bd2bf | ||
|
|
7dc7cbb80e | ||
|
|
debc9a69c5 | ||
|
|
1ab193fa9d | ||
|
|
9ec012289f | ||
|
|
c42b97ddb2 | ||
|
|
e5bfafefb9 | ||
|
|
b62495d89e | ||
|
|
c6810a0124 | ||
|
|
8e7670db41 | ||
|
|
7c0c30fb0b | ||
|
|
cbfb58f7a2 | ||
|
|
0c45d23c22 | ||
|
|
3f8fedfb16 | ||
|
|
cbc3fbdfe6 | ||
|
|
020b6b8064 | ||
|
|
523f650157 | ||
|
|
bfee230c79 | ||
|
|
c5ed8f8bed | ||
|
|
66dfa5fc1e | ||
|
|
1791fe22f6 | ||
|
|
a5422dbdf6 | ||
|
|
a2625df5e2 | ||
|
|
7507d533ac | ||
|
|
0944807491 | ||
|
|
a216848c1d | ||
|
|
e033ee6664 | ||
|
|
8c56f54a1e | ||
|
|
6b33b8b4c0 | ||
|
|
ae1a59285d | ||
|
|
0d710fc9e3 | ||
|
|
eb86a5e3b0 | ||
|
|
667e938954 | ||
|
|
41bdb741b7 | ||
|
|
a139af8184 | ||
|
|
60fa93ab47 | ||
|
|
b4102547ac | ||
|
|
ef0bdf6470 | ||
|
|
87cf9add8c | ||
|
|
3a05ac27a2 | ||
|
|
eb5661b553 | ||
|
|
41479524f8 | ||
|
|
357b6702ec | ||
|
|
dfe64d9f51 | ||
|
|
78cdd34992 | ||
|
|
16fb914855 | ||
|
|
20faa1bd1c | ||
|
|
922f795fe6 | ||
|
|
9dc539c98b | ||
|
|
18e4eb460c | ||
|
|
e841347057 | ||
|
|
6deac6dfce | ||
|
|
0d8ece1be2 | ||
|
|
8443262214 | ||
|
|
6993a24224 | ||
|
|
d59eab9a6e | ||
|
|
e47eb30a6e | ||
|
|
641951b3a0 | ||
|
|
db231ded91 | ||
|
|
61f13a334d | ||
|
|
36937b1913 | ||
|
|
d0af1a950b | ||
|
|
a217c75134 | ||
|
|
454c9a411c | ||
|
|
f44b2f6aa3 | ||
|
|
d1539335bc | ||
|
|
44d020a54c | ||
|
|
3e73782f0e | ||
|
|
13cb0c1785 | ||
|
|
49810262db | ||
|
|
58bc98ca44 | ||
|
|
4093959d3e | ||
|
|
06c5fe2a89 | ||
|
|
6cb8f3f403 | ||
|
|
e004d27b28 | ||
|
|
e432fae956 | ||
|
|
0ecb8bf5e9 | ||
|
|
2c689e8642 | ||
|
|
c2fb907490 | ||
|
|
a8e97257d7 | ||
|
|
fee1b8b736 | ||
|
|
f13e0dacde | ||
|
|
0711f4d63a | ||
|
|
d2e9a20d96 | ||
|
|
40ae29f5bf | ||
|
|
31909098f8 | ||
|
|
065e5cb1fe | ||
|
|
d4c33e5188 | ||
|
|
70c48afc04 | ||
|
|
ec5183b553 | ||
|
|
50316ee617 | ||
|
|
c4c8e1e5e1 | ||
|
|
2a82e1fec1 | ||
|
|
be7bfb2cb4 | ||
|
|
8bdcb8ff0d | ||
|
|
541b53229c | ||
|
|
1c2c10c4a5 | ||
|
|
e03585e0bb | ||
|
|
03b15dae35 | ||
|
|
c64b96e2a8 | ||
|
|
cd8120d33f | ||
|
|
809e4bdb1d | ||
|
|
f7982dfbe1 | ||
|
|
e26472756f | ||
|
|
6826d9f316 | ||
|
|
bd982c6f94 | ||
|
|
bd6ca0ad62 | ||
|
|
be03f29a9e | ||
|
|
354c6aab8f | ||
|
|
a7c6eaca5f | ||
|
|
e7d937c412 | ||
|
|
b375dd2c81 | ||
|
|
4abd8196ae | ||
|
|
ae4e41eaaa | ||
|
|
5d2be124a2 | ||
|
|
89d94ac3d1 | ||
|
|
0ae020ef82 | ||
|
|
95a28ae125 | ||
|
|
e5c7549f8f | ||
|
|
4386cc4f22 | ||
|
|
cb49ce38f5 | ||
|
|
3128d14d1f | ||
|
|
bef9cd3bc2 | ||
|
|
60a4814ac1 | ||
|
|
fec1595183 | ||
|
|
3e79e0b1ab | ||
|
|
c80f0766c5 | ||
|
|
fb454ebe14 | ||
|
|
ee556088b5 | ||
|
|
660c17814d | ||
|
|
a7c58e7112 | ||
|
|
05b6717187 | ||
|
|
2c461460db | ||
|
|
5aab68ab41 | ||
|
|
5648ad6b61 | ||
|
|
c9edcfa335 | ||
|
|
33e5735053 | ||
|
|
ad39ba30bd | ||
|
|
50100017a5 | ||
|
|
de02bcc8a0 | ||
|
|
83f2e2d85a | ||
|
|
01c9bbd3ca | ||
|
|
e93d7ad8ff | ||
|
|
59b0a6af6f | ||
|
|
326168509c | ||
|
|
47aa1644a8 | ||
|
|
08a84e51d6 | ||
|
|
d631cd8b04 | ||
|
|
0445559610 | ||
|
|
615b19c3d6 | ||
|
|
948337dd8e | ||
|
|
fe463f15b3 | ||
|
|
716e981a79 | ||
|
|
b88efd2527 | ||
|
|
568ebd67ca | ||
|
|
c628c970ae | ||
|
|
fa0815fb1d | ||
|
|
e9796d5671 | ||
|
|
8041bbf443 | ||
|
|
d6c4f0696f | ||
|
|
b88510d89a | ||
|
|
4d98e156b6 | ||
|
|
5db45aed8b | ||
|
|
b865fa7c0a | ||
|
|
41e899260f | ||
|
|
12b9748c43 | ||
|
|
4fd412d7c3 | ||
|
|
aa7c3b6852 | ||
|
|
17ed5398e6 | ||
|
|
5eabf4255b | ||
|
|
538827397c | ||
|
|
b81cbaa088 | ||
|
|
e02cf6fac5 | ||
|
|
b8cd238fa1 | ||
|
|
8e219cb799 | ||
|
|
65786ba5d6 | ||
|
|
42f55f5202 | ||
|
|
725f02f442 | ||
|
|
ebdb68a47a | ||
|
|
623ce1fe18 | ||
|
|
57e65dd5c0 | ||
|
|
bb1a6243d6 | ||
|
|
ad9b981e8b | ||
|
|
5b1eaa7e38 | ||
|
|
5c72ff75d9 | ||
|
|
cd4072fbf8 | ||
|
|
6b536b7428 | ||
|
|
d4dd446ba3 | ||
|
|
8b4921405a | ||
|
|
492a0317b0 | ||
|
|
b5983a3fc1 | ||
|
|
4bef49e2eb | ||
|
|
27399a762a | ||
|
|
83ecaa0fc9 | ||
|
|
79ff21a2fe | ||
|
|
87da9084e6 | ||
|
|
72df833b8e | ||
|
|
5a48478196 | ||
|
|
8fa9096508 | ||
|
|
319b8eef75 | ||
|
|
7c53b97004 | ||
|
|
18fc45c006 | ||
|
|
fa574cfd08 | ||
|
|
932cdd3329 | ||
|
|
dc2781d1f9 | ||
|
|
48820d181c | ||
|
|
51daeaa6ab | ||
|
|
514dc013df | ||
|
|
548ad6375d | ||
|
|
6fc7dc28a2 | ||
|
|
b207ceeab2 | ||
|
|
8380112129 | ||
|
|
dffb58ae8f | ||
|
|
0ff32c3629 | ||
|
|
dfd331c5b7 | ||
|
|
0a81d687e8 | ||
|
|
dfcdfd4b0a | ||
|
|
ec9f490fcc | ||
|
|
331502e14c | ||
|
|
18c24d985f | ||
|
|
ddb36c013d | ||
|
|
98dc51869e | ||
|
|
510b646736 | ||
|
|
da6b78f4c5 | ||
|
|
61616b8c86 | ||
|
|
be14000778 | ||
|
|
93c1a62998 | ||
|
|
527fc3c5cf | ||
|
|
8f7f0881c6 | ||
|
|
17aabf26f7 | ||
|
|
6ee6eea1fb | ||
|
|
ea22774d16 | ||
|
|
5c9fbd7d1f | ||
|
|
b0ea043b6a | ||
|
|
27366fe9f0 | ||
|
|
25b873cf7b | ||
|
|
643d2c0f3e | ||
|
|
533e5dddd0 | ||
|
|
60f0ab51c9 | ||
|
|
56cd7c4d59 | ||
|
|
f50cff54de | ||
|
|
acfb092e4b | ||
|
|
e9b039139c | ||
|
|
e4b2d29552 | ||
|
|
b4ca13b3ad | ||
|
|
b9b7d5f8eb | ||
|
|
849139176e | ||
|
|
ae0d1de188 | ||
|
|
b8bba7951f | ||
|
|
76ce5ec66b | ||
|
|
7b41b99549 | ||
|
|
0cc999ea1f | ||
|
|
a99eac9d10 | ||
|
|
e76f0119b4 | ||
|
|
a3ae47023f | ||
|
|
6ff0926f4a | ||
|
|
73963fecda | ||
|
|
d8822b70cf | ||
|
|
f50d59fe94 | ||
|
|
cf1c1e2e7e | ||
|
|
f5a5f68a1a | ||
|
|
94cd7f59d4 | ||
|
|
6009e86947 | ||
|
|
56e0549c7a | ||
|
|
49f099e382 | ||
|
|
3205606fc3 | ||
|
|
3aaf9d89b3 | ||
|
|
2c3aa9ab00 | ||
|
|
bf392d7a60 | ||
|
|
9bf0f2a161 | ||
|
|
bbfbf67fcf | ||
|
|
fe30ce10d3 | ||
|
|
3136d239df | ||
|
|
c9350fa76d | ||
|
|
b96ce13085 | ||
|
|
7ea6d7b92b | ||
|
|
011fa8c6ea | ||
|
|
1ebf0785b6 | ||
|
|
0320d85028 | ||
|
|
95f4c632f7 | ||
|
|
4b59287683 | ||
|
|
5f9dac8d2b | ||
|
|
9844a3288f | ||
|
|
03a8cff55e | ||
|
|
c9dd3ee2e9 | ||
|
|
52cb389d94 | ||
|
|
2b1bc6a46e | ||
|
|
6160eb6894 | ||
|
|
318ca75269 | ||
|
|
13a49b0753 | ||
|
|
58724a38a9 | ||
|
|
8fef35be0f | ||
|
|
202ba055ea | ||
|
|
5488fb0caf | ||
|
|
0a47140239 | ||
|
|
7248d1a504 | ||
|
|
7934a9bcb4 | ||
|
|
d90313fe4d | ||
|
|
c73001f392 | ||
|
|
7579ab178a | ||
|
|
903808a477 | ||
|
|
005da06b3d | ||
|
|
852f6b95f5 | ||
|
|
5dc7ec0fa0 | ||
|
|
de8976da7a | ||
|
|
e43450f56e | ||
|
|
4f7bb7b811 | ||
|
|
01ab82b869 | ||
|
|
dd205c55c1 | ||
|
|
b60ec8a48f | ||
|
|
acf2879057 | ||
|
|
27f0fd2372 | ||
|
|
af1129fc28 | ||
|
|
ee172cd6e9 | ||
|
|
d0e250a616 | ||
|
|
b2ba55c27b | ||
|
|
3f83c314b6 | ||
|
|
5094fab491 | ||
|
|
9d04c517e6 | ||
|
|
b421e422c2 | ||
|
|
60afebfd03 | ||
|
|
414ab53d9a | ||
|
|
5c17e41cf1 | ||
|
|
5ce8791693 | ||
|
|
3c6ea2612d | ||
|
|
10addc5923 | ||
|
|
9ee37cb503 | ||
|
|
e1b1512183 | ||
|
|
c76435883b | ||
|
|
2ede032de5 | ||
|
|
8dc8c350be | ||
|
|
ab753e88a2 | ||
|
|
d524f9a73b | ||
|
|
7d79cf5cce | ||
|
|
be25b4d9c4 | ||
|
|
a1e913de7a | ||
|
|
9e96ff37de | ||
|
|
a9c66c7b45 | ||
|
|
2b9898e9ca | ||
|
|
0add5eb291 | ||
|
|
4cf241b42b | ||
|
|
1b41a5d59a | ||
|
|
987ae3810d | ||
|
|
4d25f69526 | ||
|
|
e728d7f761 | ||
|
|
7cc35d3b04 | ||
|
|
78469ee58d | ||
|
|
369288cc48 | ||
|
|
742d802940 | ||
|
|
fdaf815f42 | ||
|
|
988b1ff02f | ||
|
|
df13b9c32a | ||
|
|
4710963ccf | ||
|
|
1540e5bfda | ||
|
|
017d405b28 | ||
|
|
ddb354f78b | ||
|
|
393c7730ec | ||
|
|
4f0e47e927 | ||
|
|
f4965d8493 | ||
|
|
c0cf8dba87 | ||
|
|
a9136d752a | ||
|
|
d7bac21149 | ||
|
|
dc6c53b6a3 | ||
|
|
86d4c9b1e0 | ||
|
|
288d487fc0 | ||
|
|
462457fe7f | ||
|
|
20ef5e0264 | ||
|
|
ad5802715e | ||
|
|
989bbad37e | ||
|
|
63f6c6a894 | ||
|
|
d42785a3bf | ||
|
|
401c029dc4 | ||
|
|
ed9d74593d | ||
|
|
9286965ee2 | ||
|
|
fa57c457f3 | ||
|
|
0343171703 | ||
|
|
176fbaf83b | ||
|
|
94a4f844a8 | ||
|
|
d18a8b1b8a | ||
|
|
a37dba2c81 | ||
|
|
471006676c | ||
|
|
0155d42650 | ||
|
|
e80990c27a | ||
|
|
e6dcccc7bd | ||
|
|
3cc9ba4ee8 | ||
|
|
6dc85c3527 | ||
|
|
7e1a8c1ceb | ||
|
|
4f01daf5bc | ||
|
|
0f20470a38 | ||
|
|
851947bbf2 | ||
|
|
413fa94e98 | ||
|
|
308eb5eda5 | ||
|
|
093054a1eb | ||
|
|
4130af0aab | ||
|
|
90a5a13197 | ||
|
|
1632632668 | ||
|
|
982c1b0059 | ||
|
|
26f71e4dbe | ||
|
|
b6ac1585ec | ||
|
|
a9b19df4ec | ||
|
|
d27a565d39 | ||
|
|
2de5362adc | ||
|
|
de42669bb7 | ||
|
|
3095fd4dd6 | ||
|
|
ebbb7168a4 | ||
|
|
40ac3e7eb7 | ||
|
|
25c5661c1b | ||
|
|
a993b8b34d | ||
|
|
16f664cdb4 | ||
|
|
a2d2639ee8 | ||
|
|
d1caad76d8 | ||
|
|
fff7adfb20 | ||
|
|
7d19ee1b25 | ||
|
|
7b15a88dc4 | ||
|
|
dc35709a1b | ||
|
|
0fad979206 | ||
|
|
277179f150 | ||
|
|
15a9d662ac | ||
|
|
1b35eebad8 | ||
|
|
6d4844a0b3 | ||
|
|
4994da5170 | ||
|
|
175d32c5f6 | ||
|
|
1481cc583f | ||
|
|
dbc54b3063 | ||
|
|
bb936f4fdb | ||
|
|
7b8611ced0 | ||
|
|
497bfd80a5 | ||
|
|
22ce5c0d70 | ||
|
|
4a711340ef | ||
|
|
f617ed2f44 | ||
|
|
bf4fada3b7 | ||
|
|
360d0e4e6b | ||
|
|
4f390ce801 | ||
|
|
027b97cbfa | ||
|
|
d16b472592 | ||
|
|
6e67124770 | ||
|
|
e6bfb0fe17 | ||
|
|
dc8ae4f0ab | ||
|
|
d2a8b4d2b9 | ||
|
|
c07d86b9f9 | ||
|
|
9e490775ff | ||
|
|
58785020bd | ||
|
|
1c74b41869 | ||
|
|
6104d81622 | ||
|
|
121c93e822 | ||
|
|
b4c2bf678f | ||
|
|
14944b0283 | ||
|
|
8ecaaba247 | ||
|
|
0fbcc6d8b5 | ||
|
|
707e21b927 | ||
|
|
f4a1cc6dec | ||
|
|
3dd05606ca | ||
|
|
1e8bfd33f5 | ||
|
|
545b6605bc | ||
|
|
8131b5961c | ||
|
|
81d4531e10 | ||
|
|
050e2963c7 | ||
|
|
3c09cd4a3a | ||
|
|
839fe32042 | ||
|
|
85c15a7167 | ||
|
|
b73580fa93 | ||
|
|
4a5f344b09 | ||
|
|
af95e8c250 | ||
|
|
ee7090b8fc | ||
|
|
7be019ff52 | ||
|
|
d14ee26d6a | ||
|
|
52398052e9 | ||
|
|
ddbd57f459 | ||
|
|
601f9048cd | ||
|
|
c5c414a7a2 | ||
|
|
bc91be6c08 | ||
|
|
d0e29ab7b0 | ||
|
|
714a79ffce | ||
|
|
cd3ad0bdc7 | ||
|
|
a8db753493 | ||
|
|
75633f0950 | ||
|
|
082cfb2f1c | ||
|
|
1072078e26 | ||
|
|
b0f1333657 | ||
|
|
f10a151469 | ||
|
|
eadd82761c | ||
|
|
00f4393f48 | ||
|
|
50f6fffbdc | ||
|
|
baf5340dc0 | ||
|
|
e528903488 | ||
|
|
dc2fce8e1d | ||
|
|
c4005c4a31 | ||
|
|
0a70bbd255 | ||
|
|
c91d9cc0b6 | ||
|
|
8e10c22356 | ||
|
|
37a44c0773 | ||
|
|
2a5cf221fa | ||
|
|
92aa510bda | ||
|
|
6b04997fc3 | ||
|
|
e0b3405a4d | ||
|
|
10c2dad48a | ||
|
|
52e2a2610e | ||
|
|
a809624356 | ||
|
|
29f06a4444 | ||
|
|
3f9e79f152 | ||
|
|
633e56e8a9 | ||
|
|
bf01f725f7 | ||
|
|
276b191845 | ||
|
|
c7bc58e94b | ||
|
|
8f22203d24 | ||
|
|
782fec841e | ||
|
|
cfa909a93d | ||
|
|
e0fde41d87 | ||
|
|
574f7c1a1f | ||
|
|
ec8f4050d0 | ||
|
|
60c51886e0 | ||
|
|
cbb1461010 | ||
|
|
07cc5b501c | ||
|
|
ebb1a730c1 | ||
|
|
9dff55b212 | ||
|
|
8ae03b64d7 | ||
|
|
bb30c818ab | ||
|
|
c944f6a320 | ||
|
|
62ec7de963 | ||
|
|
aa4c0ff329 | ||
|
|
37217ece73 | ||
|
|
28d4f4b142 | ||
|
|
8d5d423adb | ||
|
|
cda0133dd1 | ||
|
|
eda7f40fef | ||
|
|
e589e665a7 | ||
|
|
b32b5ad6e9 | ||
|
|
e2de199f47 | ||
|
|
948f4a8827 | ||
|
|
a1633123aa | ||
|
|
2444296348 | ||
|
|
4be7ebe61f | ||
|
|
a720fe1789 | ||
|
|
2cec9eaf65 | ||
|
|
313f999af4 | ||
|
|
0b0ec43bf5 | ||
|
|
f0439c8d12 | ||
|
|
40e8657137 | ||
|
|
52dd72dfa5 | ||
|
|
922ce7359c | ||
|
|
779fe670f7 | ||
|
|
570a7a5c11 | ||
|
|
bd1b004d94 | ||
|
|
5457b2c6ea | ||
|
|
02f3316710 | ||
|
|
69a909fc4c | ||
|
|
ec09b5843c | ||
|
|
078e7e1686 | ||
|
|
d29947ba32 | ||
|
|
1f03faddef | ||
|
|
d1bce7e685 | ||
|
|
880352ea65 | ||
|
|
3231e5c3ba | ||
|
|
f482156cca | ||
|
|
620e1e9c73 | ||
|
|
8a119d72e2 | ||
|
|
807a5cfb23 | ||
|
|
54d0b9a1b8 | ||
|
|
ca7a5bc0fe | ||
|
|
0c5185f8ba | ||
|
|
eaf1244932 | ||
|
|
7c2bbf840a | ||
|
|
85673b8273 | ||
|
|
b6cd7b8e3d | ||
|
|
869473172c | ||
|
|
63e407cfdc | ||
|
|
0251117c77 | ||
|
|
44e1455b12 | ||
|
|
76460f01e9 | ||
|
|
4b8a72fda7 | ||
|
|
edaee4e962 | ||
|
|
77bfb3fb67 | ||
|
|
6a881545b0 | ||
|
|
d0de5fda30 | ||
|
|
a1f120b2ff | ||
|
|
185319d560 | ||
|
|
5c6dd3f6f4 | ||
|
|
8e5abc1f15 | ||
|
|
9248c92b5c | ||
|
|
583ea4d17a | ||
|
|
edcdf9f619 | ||
|
|
c809c34024 | ||
|
|
037d52104a | ||
|
|
1fb70c977c | ||
|
|
eeb26e3975 | ||
|
|
12817c09bb | ||
|
|
4840bdb031 | ||
|
|
a85e7a2a43 | ||
|
|
b93628acb3 | ||
|
|
7f7b9d089c | ||
|
|
61d233f069 | ||
|
|
d457d40e0b | ||
|
|
6571a63ffa | ||
|
|
a7e81c8ea0 | ||
|
|
73d9abae3e | ||
|
|
c8b9e42649 | ||
|
|
62c00ae1d8 | ||
|
|
ea67c828cd | ||
|
|
476975540a | ||
|
|
3fbb0ac8dd | ||
|
|
71903eb27f | ||
|
|
193ff38ab3 | ||
|
|
bb8dbe9da5 | ||
|
|
f9d16c2b15 | ||
|
|
29bad2fe9b | ||
|
|
f4aca3f21d | ||
|
|
c6f9fe3af2 | ||
|
|
612d408034 | ||
|
|
a86f578139 | ||
|
|
5bac1ad58b | ||
|
|
cf2b021502 | ||
|
|
cd9b1fcb8c | ||
|
|
81ca78e7f4 | ||
|
|
fc0899b2ad | ||
|
|
2e138eb99f | ||
|
|
4f21f67775 | ||
|
|
d883854aad | ||
|
|
756c99653e | ||
|
|
3269c63f89 | ||
|
|
149fb0c216 | ||
|
|
d244a018d0 | ||
|
|
2e0370367c | ||
|
|
3cb4f6d9d4 | ||
|
|
ae3b8be4d4 | ||
|
|
61a40c1b43 | ||
|
|
a27c7b1398 | ||
|
|
a71f35d263 | ||
|
|
9a6deb5a1a | ||
|
|
f582344b9a | ||
|
|
e41c4b5bb6 | ||
|
|
7b48431917 | ||
|
|
847c4f26aa | ||
|
|
1f36ec48e3 | ||
|
|
ff08add7c0 | ||
|
|
b4131ae817 | ||
|
|
ffc91a6c81 | ||
|
|
525ec8cd01 | ||
|
|
b209629579 | ||
|
|
a8af2e1837 | ||
|
|
93ecc046ea | ||
|
|
8bef5dc805 | ||
|
|
ad41bcca5a | ||
|
|
aed2e35bc0 | ||
|
|
ab90ff565a | ||
|
|
ca8982494b | ||
|
|
a7b44426cd | ||
|
|
e7af42a9f8 | ||
|
|
b9fed8fca6 | ||
|
|
79b8dac0fa | ||
|
|
d8eee47ca4 | ||
|
|
a3e32d9a15 | ||
|
|
989d1aff60 | ||
|
|
95b2560a08 | ||
|
|
76133074d1 | ||
|
|
4cfe463dfa | ||
|
|
03c65dd0e9 | ||
|
|
6faddfcd3d | ||
|
|
1820c2c598 | ||
|
|
23b688287f | ||
|
|
42ccc1ef24 | ||
|
|
aef7892de6 | ||
|
|
cc40c18f49 | ||
|
|
b1838512b2 | ||
|
|
1c50caa8ca | ||
|
|
febdbceab1 | ||
|
|
597b4bfcca | ||
|
|
5c65006a66 | ||
|
|
34727c00c6 | ||
|
|
352146ef92 | ||
|
|
b107ae2ab9 | ||
|
|
d5d1a607ad | ||
|
|
2594164772 | ||
|
|
209555c42e | ||
|
|
e27f50b8e5 | ||
|
|
484f618685 | ||
|
|
da398c3d9c | ||
|
|
4e0ad52001 | ||
|
|
c9829dd3e4 | ||
|
|
35cf863f4b | ||
|
|
c53be459c6 | ||
|
|
ab1ea5a366 | ||
|
|
97e11bd94e | ||
|
|
10de7f649b | ||
|
|
d793ef1ab8 | ||
|
|
d3d45a8776 | ||
|
|
9f86fd0cb4 | ||
|
|
71d5b42726 | ||
|
|
3e78ed95d4 | ||
|
|
20a839fef5 | ||
|
|
b2d8c4374b | ||
|
|
251c9fee98 | ||
|
|
9f77810ca8 | ||
|
|
dc93462d42 | ||
|
|
4371c9ba03 | ||
|
|
6e2e825a5f | ||
|
|
af754e3fc4 | ||
|
|
06860ed5b4 | ||
|
|
09190c1735 | ||
|
|
a95b473417 | ||
|
|
56e3565a9e | ||
|
|
63230cb72d | ||
|
|
f81e57d5b8 | ||
|
|
ecd6817aaf | ||
|
|
6f58d58cae | ||
|
|
40d0caa70b | ||
|
|
0692be9bae | ||
|
|
0d28dce326 | ||
|
|
96031214c6 | ||
|
|
3420439f31 | ||
|
|
ab3f6dfcc6 | ||
|
|
3ebd43ebf0 | ||
|
|
38ff343134 | ||
|
|
6a8d3100d2 | ||
|
|
c3ec2e68ad | ||
|
|
bfe714e985 | ||
|
|
1d5755a4c2 | ||
|
|
445127accc | ||
|
|
c156af020c | ||
|
|
fa8751f9ad | ||
|
|
420f60b5c7 | ||
|
|
65fdbc85d5 | ||
|
|
87f75c737a | ||
|
|
5ff9052200 | ||
|
|
9641e268ea | ||
|
|
b154dd5f07 | ||
|
|
0683842ec3 | ||
|
|
f5121c64be | ||
|
|
054c7a2c05 | ||
|
|
3d3fc2947e | ||
|
|
e8e5d4afda | ||
|
|
8382f4d727 | ||
|
|
be3e198f9a | ||
|
|
acc50b709e | ||
|
|
5a6763f90d | ||
|
|
218476fab0 | ||
|
|
ec850dc820 | ||
|
|
c48b03584f | ||
|
|
efe8216445 | ||
|
|
0405aaa3da | ||
|
|
6bb213e56f | ||
|
|
2fb4256f84 | ||
|
|
82476138c1 | ||
|
|
5293beeb77 | ||
|
|
0c8f5f1221 | ||
|
|
4f4a12bb40 | ||
|
|
1dbe6c83c3 | ||
|
|
2b5033e732 | ||
|
|
8d9ff550d4 | ||
|
|
f1733f9c5d | ||
|
|
92c3c86be4 | ||
|
|
ada8b53423 | ||
|
|
7a1b6fd205 | ||
|
|
b78cbb98d8 | ||
|
|
04abcb71f6 | ||
|
|
1fe3507bc5 | ||
|
|
9fedafed15 | ||
|
|
23b3a9a650 | ||
|
|
7b2ac25a52 | ||
|
|
f91421418a | ||
|
|
3a14e8b013 | ||
|
|
ad97e95f2f | ||
|
|
5b01facd73 | ||
|
|
6fe637b9ee | ||
|
|
94d83dbb2d | ||
|
|
c9a843b417 | ||
|
|
b986c5585d | ||
|
|
87c115fc86 | ||
|
|
acee97916e | ||
|
|
1a741f696e | ||
|
|
37e7cd5211 | ||
|
|
91a2d052a7 | ||
|
|
06134d3ffc | ||
|
|
092957c14a | ||
|
|
d5e8f1a781 | ||
|
|
b5af125be6 | ||
|
|
ecc49318f0 | ||
|
|
974bba4a45 | ||
|
|
951732fc1b | ||
|
|
b6700924b2 | ||
|
|
5d43639e93 | ||
|
|
27e4208631 | ||
|
|
b505ad22e6 | ||
|
|
d67122dffc | ||
|
|
0774c4e5ca | ||
|
|
01850c2128 | ||
|
|
cbc210b014 | ||
|
|
c53ee4202b | ||
|
|
f2be12f97b | ||
|
|
6996ffa451 | ||
|
|
435a5fb3ad | ||
|
|
4947350ca5 | ||
|
|
c1495b0fa8 | ||
|
|
67dda9c8bb | ||
|
|
c8987e20c2 | ||
|
|
bcf03647ef | ||
|
|
a9d0690f4d | ||
|
|
10fbed50f3 | ||
|
|
785f1fedd9 | ||
|
|
b0c5dcf42f | ||
|
|
cf21efa103 | ||
|
|
7613e94ef6 | ||
|
|
b49c702f33 | ||
|
|
09532638d5 | ||
|
|
97df6d7415 | ||
|
|
54bfaa28c1 | ||
|
|
a09f92f9cc | ||
|
|
afd28fab03 | ||
|
|
d92ced6fb6 | ||
|
|
ae98fde321 | ||
|
|
9ddce88092 | ||
|
|
44f8fcb600 | ||
|
|
814fdcf9b6 | ||
|
|
5060605626 | ||
|
|
453ba14cbd | ||
|
|
285e6fe090 | ||
|
|
c3023fe681 | ||
|
|
c5df104a66 | ||
|
|
f6213d4f4d | ||
|
|
ca2ea388b7 | ||
|
|
69dba022c4 | ||
|
|
bfb99c361c | ||
|
|
5796054305 | ||
|
|
a3e1473ac1 | ||
|
|
7b5fc60e00 | ||
|
|
807ce0af4e | ||
|
|
3f05efd60f | ||
|
|
03d93aa19a | ||
|
|
cad9386ff6 | ||
|
|
7de6bbca61 | ||
|
|
1d43c0a2fa | ||
|
|
c8d32e0dd3 | ||
|
|
be3a21ae07 | ||
|
|
69081a9175 | ||
|
|
ab2f8a0c09 | ||
|
|
b961a501bb | ||
|
|
8e1bf6e3d4 | ||
|
|
d6756eb46b | ||
|
|
efbd42f7b5 | ||
|
|
3f90261520 | ||
|
|
ff5894d772 | ||
|
|
225285cb97 | ||
|
|
3220e2b978 | ||
|
|
54ae458b61 | ||
|
|
e076db5a4e | ||
|
|
a3d2a1062f | ||
|
|
2e6198077d | ||
|
|
55ab3b2dc7 | ||
|
|
bdc8cf2bc8 | ||
|
|
74836bebe4 | ||
|
|
95150a5d85 | ||
|
|
4d23b3267f | ||
|
|
e19adccd9c | ||
|
|
a25f331e83 | ||
|
|
69c06ba6fe | ||
|
|
8abeb2204b | ||
|
|
ec06fd0ad4 | ||
|
|
a904c183df | ||
|
|
5246b3e496 | ||
|
|
f80fdd7e83 | ||
|
|
6ba58896d2 | ||
|
|
3aa838bbe4 | ||
|
|
2c3a27e9c7 | ||
|
|
5532df24e4 | ||
|
|
b3898b9b2a | ||
|
|
9ce84714cd | ||
|
|
0bc112ce52 | ||
|
|
d46ff1d2d7 | ||
|
|
0cfecd31d3 | ||
|
|
008e88b84b | ||
|
|
2f698904e4 | ||
|
|
106f079afc | ||
|
|
6c1e3a17f7 | ||
|
|
540c57f755 | ||
|
|
5e26e8245b | ||
|
|
983117d788 | ||
|
|
b372f808dd | ||
|
|
bc9b623638 | ||
|
|
d5781fb110 | ||
|
|
487718512d | ||
|
|
8a92fb24c4 | ||
|
|
5c575e73c7 | ||
|
|
2180531a84 | ||
|
|
6812e8880e | ||
|
|
a932209143 | ||
|
|
4946b5907b | ||
|
|
efeba594ae | ||
|
|
b27e4c3dc3 | ||
|
|
5e1241acd2 | ||
|
|
126f7101ff | ||
|
|
b320e74921 | ||
|
|
add5e4ca5e | ||
|
|
466fd79c66 | ||
|
|
4596d9a577 | ||
|
|
b4ae142149 | ||
|
|
3fe43ce1d9 | ||
|
|
8524aecfed | ||
|
|
e04dc9d2bb | ||
|
|
3dcb9722d3 | ||
|
|
bd0215524b | ||
|
|
53e3ff2b24 | ||
|
|
5bb8163674 | ||
|
|
a891d64395 | ||
|
|
6b1d2523e8 | ||
|
|
08ee9526ad | ||
|
|
0efc46260f | ||
|
|
6a01a1257f | ||
|
|
a2a7e80007 | ||
|
|
cce66a13b6 | ||
|
|
43bced7997 | ||
|
|
788cd78321 | ||
|
|
e5d1cb5a2e | ||
|
|
d94bbfca7f | ||
|
|
465a39427b | ||
|
|
2664ac0efc | ||
|
|
c1277705d8 | ||
|
|
61cfd2f9f9 | ||
|
|
ee4dabeca6 | ||
|
|
e57d0fb93c | ||
|
|
ee20164207 | ||
|
|
d7ee44960e | ||
|
|
c13ebd3a9d | ||
|
|
6594a0a6e7 | ||
|
|
de44563301 | ||
|
|
e3d9cf0ac1 | ||
|
|
bd572d8843 | ||
|
|
037737d653 | ||
|
|
d2c7c426de | ||
|
|
1d09c6e47d | ||
|
|
84244b7cd5 | ||
|
|
422680ee9f | ||
|
|
42c7653e99 | ||
|
|
78c0c58946 | ||
|
|
cae61614f4 | ||
|
|
a7f6c9b3a0 | ||
|
|
5950b4bb78 | ||
|
|
817b19888f | ||
|
|
b64fb578fc | ||
|
|
e9e92368b0 | ||
|
|
ffcb173a7f | ||
|
|
b9c9c2797f | ||
|
|
204a4e459b | ||
|
|
0a53e966ea | ||
|
|
2e17c23333 | ||
|
|
63f3381a2b | ||
|
|
2292720fed | ||
|
|
b77efa521f | ||
|
|
cfe221706b | ||
|
|
54ae9d83b0 | ||
|
|
293e2a8e80 | ||
|
|
71cd6c137b | ||
|
|
0e14d11a20 | ||
|
|
bbc392caeb | ||
|
|
61840edb30 | ||
|
|
9867b7fccf | ||
|
|
58f198626a | ||
|
|
a145f1d931 | ||
|
|
9748f19172 | ||
|
|
ba1e94d3d9 | ||
|
|
cd9fadbc44 | ||
|
|
062a180a1c | ||
|
|
860ec1a7c4 | ||
|
|
5ca1bfc11c | ||
|
|
2f189cd076 | ||
|
|
2f0e6a6dda | ||
|
|
f187b42a98 | ||
|
|
f9250d91a5 | ||
|
|
491c828661 | ||
|
|
644ec36e64 | ||
|
|
838e1b19ec | ||
|
|
d5bbb2b640 | ||
|
|
dc91d4b1f9 | ||
|
|
9984647ebb | ||
|
|
ec5b16ef85 | ||
|
|
c3c60e10f1 | ||
|
|
8a2363621d | ||
|
|
dbbf21071b | ||
|
|
e967fe2266 | ||
|
|
b5c7657e01 | ||
|
|
680d6e2d31 | ||
|
|
7a19d24058 | ||
|
|
995ee41d6b | ||
|
|
b2f4385232 | ||
|
|
1f9a7d0b0c | ||
|
|
d5feffa117 | ||
|
|
fc62cf7e2f | ||
|
|
93f1859bab | ||
|
|
dcf0a605cf | ||
|
|
710036adae | ||
|
|
8a91fe6992 | ||
|
|
09c4c88a6d | ||
|
|
69919ac85c | ||
|
|
26f2410fe6 | ||
|
|
d43c32e9e8 | ||
|
|
5c4ee23795 | ||
|
|
fb3d871553 | ||
|
|
ae654730c4 | ||
|
|
ec79e86bee | ||
|
|
e8dabc71af | ||
|
|
9c0de0f731 | ||
|
|
4948862dce | ||
|
|
7479485d45 | ||
|
|
1e284f69ea | ||
|
|
516ed83638 | ||
|
|
26361883b4 | ||
|
|
d26f2dcb2c | ||
|
|
cc657c0c26 | ||
|
|
d90d7b6927 | ||
|
|
de6dc90575 | ||
|
|
3cdd6204c5 | ||
|
|
d996e9c9ee | ||
|
|
a4ba8d4b8f | ||
|
|
cd8a423b32 | ||
|
|
f7ca74cf1d | ||
|
|
ebba32e1c4 | ||
|
|
e02da90faa | ||
|
|
0de5132e2b | ||
|
|
7d2507527a | ||
|
|
97decb3a73 | ||
|
|
f360959efc | ||
|
|
465589c0fd | ||
|
|
9fcf7a2610 | ||
|
|
3035fbf468 | ||
|
|
c4c354bc4b | ||
|
|
c5da1bb952 | ||
|
|
486c41a69a | ||
|
|
87800a3659 | ||
|
|
d5fbe1b629 | ||
|
|
a3cee67a61 | ||
|
|
5ffc8c7443 | ||
|
|
04fd296ffe | ||
|
|
262d5eea22 | ||
|
|
ed5869646f | ||
|
|
b984fc4e0e | ||
|
|
0ef4901e48 | ||
|
|
8d85d46c1a | ||
|
|
eca975a370 | ||
|
|
3bb94d469d | ||
|
|
724afc000f | ||
|
|
be2d494fcf | ||
|
|
a36734db66 | ||
|
|
1cad069050 | ||
|
|
d24e0a6060 | ||
|
|
f65f793a0d | ||
|
|
f7ad489805 | ||
|
|
62459c4f00 | ||
|
|
05bd88b4d8 | ||
|
|
0546fff1ce | ||
|
|
83f7bd66e6 | ||
|
|
14ebb2fb93 | ||
|
|
916b2920be | ||
|
|
a20963889c | ||
|
|
4b77475807 | ||
|
|
9f672593bc | ||
|
|
a285ae65fb | ||
|
|
917a0239a9 | ||
|
|
3261c2e273 | ||
|
|
d0125d5aad | ||
|
|
65a3da92f1 | ||
|
|
5c621fa253 | ||
|
|
f9e71bee0a | ||
|
|
c3804877ed | ||
|
|
35e53ab9c7 | ||
|
|
053987b9e1 | ||
|
|
c0bc93c7c4 | ||
|
|
1f596eb2bc | ||
|
|
3f59b51be1 | ||
|
|
9d59da8974 | ||
|
|
51218bd1ad | ||
|
|
e1c3c53058 | ||
|
|
9fa497b056 | ||
|
|
057fbfc2b9 | ||
|
|
33156071cd | ||
|
|
bbb759c684 | ||
|
|
f1a7bc9ecd | ||
|
|
d514608f91 | ||
|
|
e8c2e26358 | ||
|
|
61c67849d7 | ||
|
|
2cdbb34763 | ||
|
|
538ba918c1 | ||
|
|
c330df9700 | ||
|
|
1789a2db29 | ||
|
|
c270b83341 | ||
|
|
02f0788033 | ||
|
|
a2ea6e8d47 | ||
|
|
a986f53134 | ||
|
|
9d2d45b473 | ||
|
|
0c892e6b3a | ||
|
|
a0fc38d6a2 | ||
|
|
28cbf45d1d | ||
|
|
72829be281 | ||
|
|
d57f9906bd | ||
|
|
3d4fea6510 | ||
|
|
f670644954 | ||
|
|
dd6821814a | ||
|
|
f33584511c | ||
|
|
3ec84553ef | ||
|
|
a301d4381f | ||
|
|
49b8ad7e94 | ||
|
|
180d29c7b3 | ||
|
|
a23ba91681 | ||
|
|
d986da63a5 | ||
|
|
d3ac8bb6f8 | ||
|
|
f87f3b9199 | ||
|
|
67bdcbcf19 | ||
|
|
69b2a5a876 | ||
|
|
a79dff3d98 | ||
|
|
c859a23136 | ||
|
|
7f92671765 | ||
|
|
ec38105b08 | ||
|
|
85dceb12a1 | ||
|
|
5126c37c1e | ||
|
|
e7e03e36de | ||
|
|
13c393fc9d | ||
|
|
cc2f375b13 | ||
|
|
49d5109c96 | ||
|
|
e5c8f5e2fa | ||
|
|
ff925a7578 | ||
|
|
33939a30ea | ||
|
|
308b296285 | ||
|
|
d55012f724 | ||
|
|
7c6eecc9c8 | ||
|
|
e4cbf5023a | ||
|
|
46356d3027 | ||
|
|
958a263437 | ||
|
|
a89ae82270 | ||
|
|
cedc39bf09 | ||
|
|
0131055ec9 | ||
|
|
0627e68078 | ||
|
|
7d78f6314a | ||
|
|
0f509f4a34 | ||
|
|
b043000044 | ||
|
|
c338eab3c6 | ||
|
|
24e1dc92ba | ||
|
|
00f98543ad | ||
|
|
8684356b44 | ||
|
|
a89615365e | ||
|
|
3c36c22ca8 | ||
|
|
7a2f5f43f9 | ||
|
|
dac27f1f18 | ||
|
|
6f276ae4bb | ||
|
|
537e288758 | ||
|
|
3cea1bd423 | ||
|
|
c976bbcfd2 | ||
|
|
ec29829550 | ||
|
|
cf7180af5b | ||
|
|
c58e3acc78 | ||
|
|
b78aef1e7e | ||
|
|
f20e4ddf3b | ||
|
|
40656641b6 | ||
|
|
6f8e8e98bb | ||
|
|
24b4aabae9 | ||
|
|
a9c6d79cda | ||
|
|
45bf4b02e7 | ||
|
|
667c5138cc | ||
|
|
85cf98888d | ||
|
|
048e5bb9a2 | ||
|
|
b9d47d0dd2 | ||
|
|
1813c25117 | ||
|
|
940c9c3bae | ||
|
|
5d0d7336ff | ||
|
|
6a26a05dbf | ||
|
|
c22e94c9c7 | ||
|
|
4aafa8cf47 | ||
|
|
9235a11d5f | ||
|
|
f141b9f778 | ||
|
|
1dca1efbc6 | ||
|
|
28c6b1393f | ||
|
|
6c97b8b875 | ||
|
|
ec2426b24d | ||
|
|
5cd3b11391 | ||
|
|
d30b565d98 | ||
|
|
74008d28a7 | ||
|
|
0d1b3cee4f | ||
|
|
0b44cb4426 | ||
|
|
eb8e4496b2 | ||
|
|
30f45d4df7 | ||
|
|
24e1c78d52 | ||
|
|
476fecbcf5 | ||
|
|
327b58fa03 | ||
|
|
d3eea9404d | ||
|
|
ca309d3b28 | ||
|
|
0ebd68f17f | ||
|
|
3696373609 | ||
|
|
165affc39b | ||
|
|
f794018e0c | ||
|
|
337cc5ca18 | ||
|
|
4e4d6b5d1f | ||
|
|
b011adc453 | ||
|
|
d8abc1d266 | ||
|
|
6cde066edd | ||
|
|
d163e38380 | ||
|
|
d9195970b7 | ||
|
|
20b946eae5 | ||
|
|
c00357663b | ||
|
|
2feb5f22cc | ||
|
|
f3aee056ad | ||
|
|
91ff5ca0ca | ||
|
|
4238e36d7f | ||
|
|
03a9d3bc5b | ||
|
|
fe46dee194 | ||
|
|
1c6c35f861 | ||
|
|
926b25fd54 | ||
|
|
e58142b4ac | ||
|
|
3e5c6afaee | ||
|
|
a1bf9fad98 | ||
|
|
afdc4219d0 | ||
|
|
94e4ed6644 | ||
|
|
ef8aaba014 | ||
|
|
d2ae07e69b | ||
|
|
760dd01b50 | ||
|
|
5bf90cb77d | ||
|
|
f5c3dc5d9d | ||
|
|
f2b820079a | ||
|
|
083024496a | ||
|
|
e01eea8ba8 | ||
|
|
eef948d797 | ||
|
|
8017be7d09 | ||
|
|
5b628a4c77 | ||
|
|
ddbdb51d20 | ||
|
|
0081a7ca92 | ||
|
|
e80ae4906f | ||
|
|
e4e22fb58e | ||
|
|
7086a400e8 | ||
|
|
a25a13fde0 | ||
|
|
993beab3b7 | ||
|
|
06875f2cc9 | ||
|
|
448fc7231c | ||
|
|
d0d030bafc | ||
|
|
833131e15f | ||
|
|
fb2810557a | ||
|
|
82a64db42b | ||
|
|
57af0ba0a4 | ||
|
|
17c1e64f7e | ||
|
|
af13ceac24 | ||
|
|
af2ec61965 | ||
|
|
a55cc55338 | ||
|
|
b2fb3fd35a | ||
|
|
94b7c8eb59 | ||
|
|
6d671007dd | ||
|
|
1a8d5fb4a9 | ||
|
|
f90c412b35 | ||
|
|
c73b5456eb | ||
|
|
3d87398721 | ||
|
|
96681887b8 | ||
|
|
f2c675cff6 | ||
|
|
1844bf17a7 | ||
|
|
47b56d6123 | ||
|
|
814d5f6d6c | ||
|
|
512d2dd5f8 | ||
|
|
ad20d5ac1c | ||
|
|
b79ff05e29 | ||
|
|
32b50f8188 | ||
|
|
a44096a26d | ||
|
|
32cf94fc74 | ||
|
|
39e28cd80a | ||
|
|
9b1356ad01 | ||
|
|
45521b377a | ||
|
|
46a366635c | ||
|
|
384b588a2d | ||
|
|
03e5a78d8f | ||
|
|
e32c76b059 | ||
|
|
ba7782f867 | ||
|
|
c5091b0e49 | ||
|
|
b54e32f0ca | ||
|
|
328e7738d5 | ||
|
|
aca359c2e2 | ||
|
|
1cd40dc9e5 | ||
|
|
dc9407281f | ||
|
|
8f727c1f35 | ||
|
|
a08ea28feb | ||
|
|
c5535dd9a0 | ||
|
|
3519cc5e44 | ||
|
|
d251bbbb05 | ||
|
|
1fc3ec9029 | ||
|
|
1877128fc4 | ||
|
|
76c5b4a06b | ||
|
|
9cd674b528 | ||
|
|
5aea7eb860 | ||
|
|
ec30df2020 | ||
|
|
bb33427c79 | ||
|
|
28a16cebda | ||
|
|
49c79405bc | ||
|
|
3098f32a07 | ||
|
|
b1e9c05bee | ||
|
|
69e06d89ff | ||
|
|
56b04017e7 | ||
|
|
3af61c031d | ||
|
|
f42a57088f | ||
|
|
4834452875 | ||
|
|
c5b9d99b48 | ||
|
|
f8d4c36f6d | ||
|
|
fa9ecbdb81 | ||
|
|
2bf6b29b8f | ||
|
|
25812f88f6 | ||
|
|
037989b8e4 | ||
|
|
dbc82cfb6a | ||
|
|
941a766aa3 | ||
|
|
72be7ad5f0 | ||
|
|
b2a36f71a0 | ||
|
|
6b17620389 | ||
|
|
b04195041a | ||
|
|
8ca4c66e3c | ||
|
|
449b7bf6e4 | ||
|
|
88e4b6390c | ||
|
|
de92bd1884 | ||
|
|
1b276a74fe | ||
|
|
fff31558a0 | ||
|
|
8084c4b2a3 | ||
|
|
1ca852191f | ||
|
|
af5fc6547a | ||
|
|
70f2b26c86 | ||
|
|
cfd95dbe87 | ||
|
|
c5bb404d6a | ||
|
|
4c23964964 | ||
|
|
e4a6dcd35c | ||
|
|
d4addd53ad | ||
|
|
d21298c156 | ||
|
|
9dba9fb366 | ||
|
|
09d40679c0 | ||
|
|
a323b126e5 | ||
|
|
553aad6ed2 | ||
|
|
5ca2ad6148 | ||
|
|
40537e1522 | ||
|
|
064a75b21b | ||
|
|
1d3445bc0f | ||
|
|
79232d02c9 | ||
|
|
9bd4986781 | ||
|
|
c3d443aaff | ||
|
|
b087888f94 | ||
|
|
da3dfd0998 | ||
|
|
4468d81472 | ||
|
|
7ddae8f2eb | ||
|
|
6b2851a671 | ||
|
|
4763969c8f | ||
|
|
f9b75e486c | ||
|
|
f868052062 | ||
|
|
61f0cbe10a | ||
|
|
0f4968d75c | ||
|
|
3077c22e4f | ||
|
|
0decc37b5a | ||
|
|
4a953b66e0 | ||
|
|
8435eeed4d | ||
|
|
cffb4de83b | ||
|
|
55175087c4 | ||
|
|
0ddfa8ad10 | ||
|
|
b74fb3f179 | ||
|
|
9d3d33b6a2 | ||
|
|
2abaa60c2e | ||
|
|
d5547f5c7c | ||
|
|
061510098c | ||
|
|
4fc3546887 | ||
|
|
868948509a | ||
|
|
e71492a2b3 | ||
|
|
c2055f3514 | ||
|
|
2809579dd7 | ||
|
|
c7afe3e9a4 | ||
|
|
cd026cd865 | ||
|
|
bc705aac03 | ||
|
|
a7c73036f0 | ||
|
|
e80d27f273 | ||
|
|
23adbf9540 | ||
|
|
a7347238e6 | ||
|
|
bf55666492 | ||
|
|
8ab0b0e460 | ||
|
|
b8e1849cec | ||
|
|
2255d05664 | ||
|
|
45a8eda49b | ||
|
|
b1207949ac | ||
|
|
d61fd01d61 | ||
|
|
4d5d3108fb | ||
|
|
e422f4154f | ||
|
|
0651f1bcd4 | ||
|
|
11f0ade921 | ||
|
|
5cab2e1c43 | ||
|
|
6381bdbf33 | ||
|
|
c8bcd4af2d | ||
|
|
cabb06230c | ||
|
|
4a75566a3b | ||
|
|
d9c924b472 | ||
|
|
52aa52c3b1 | ||
|
|
d254d6075a | ||
|
|
8004080643 | ||
|
|
13878974a6 | ||
|
|
6689e00e6a | ||
|
|
9b8a108f86 | ||
|
|
a3569d88c9 | ||
|
|
f2f6b6ede9 | ||
|
|
7f81cfd45a | ||
|
|
13b8e1a2ae | ||
|
|
36dbdf955d | ||
|
|
714b6c98ef | ||
|
|
7181d7ae6a | ||
|
|
9422d57283 | ||
|
|
5724cec1e5 | ||
|
|
35ca54d98f | ||
|
|
7398a9ebf9 | ||
|
|
4188fb536e | ||
|
|
a11e5e2deb | ||
|
|
5dd7e8c4d9 | ||
|
|
40bc390c3b | ||
|
|
8776348a80 | ||
|
|
49fb4421dd | ||
|
|
d232f08933 | ||
|
|
feba4da0b8 | ||
|
|
928d7186b5 | ||
|
|
3149a95d6a | ||
|
|
ed7ebfd58d | ||
|
|
808e310799 | ||
|
|
23fbb3cf22 | ||
|
|
c11e643f13 | ||
|
|
f5541860bc | ||
|
|
83ff0055b6 | ||
|
|
213f23aaf6 | ||
|
|
9970f3786f | ||
|
|
d01a568b8b | ||
|
|
e397884e1e | ||
|
|
ef65bac79b | ||
|
|
c0837c726f | ||
|
|
ce5429aba7 | ||
|
|
aa191e9202 | ||
|
|
a8f0283e93 | ||
|
|
999e47a26c | ||
|
|
a8103ca22d | ||
|
|
ef17f4913b | ||
|
|
1a30043776 | ||
|
|
b7e8b91eec | ||
|
|
3be1904653 | ||
|
|
cadd0e4244 | ||
|
|
f35ea9a3ca | ||
|
|
0971630e01 | ||
|
|
b60a9fa371 | ||
|
|
ab45360808 | ||
|
|
8523c0da32 | ||
|
|
f0dfa4d53d | ||
|
|
f2bedddce4 | ||
|
|
552138e851 | ||
|
|
ff71379a8e | ||
|
|
23a7feeb6e | ||
|
|
34f5db9ed4 | ||
|
|
9fd70cbdf9 | ||
|
|
87506852d1 | ||
|
|
e6893bc419 | ||
|
|
ebeab06710 | ||
|
|
1911c3690d | ||
|
|
3f3254a4df | ||
|
|
20ccb7b558 | ||
|
|
8cfe89604a | ||
|
|
15f0ba839f | ||
|
|
c400b914e5 | ||
|
|
a431c829cb | ||
|
|
25d0e125e5 | ||
|
|
b89a78ce17 | ||
|
|
f568012b9d | ||
|
|
328fb70e54 | ||
|
|
2f24e5ceb7 | ||
|
|
97809277df | ||
|
|
3d3e7a330c | ||
|
|
adf2275018 | ||
|
|
c1ecfbfe63 | ||
|
|
a7e7680789 | ||
|
|
382c19024f | ||
|
|
9379487942 | ||
|
|
5e99baf7b9 | ||
|
|
31951dae4c | ||
|
|
b1ab7f46e0 | ||
|
|
4e0c7ed5a6 | ||
|
|
2ef76d5e31 | ||
|
|
d3dda443cd | ||
|
|
ec3802c180 | ||
|
|
76654c7856 | ||
|
|
90239bb969 | ||
|
|
a6e4b0fea5 | ||
|
|
8ad37af70e | ||
|
|
c102d359f8 | ||
|
|
a07891e3e6 | ||
|
|
e946a35b18 | ||
|
|
68d7337f98 | ||
|
|
8b4198fd8d | ||
|
|
9c795fa40d | ||
|
|
5f2217a079 | ||
|
|
0cda4b7f23 | ||
|
|
e17e69604c | ||
|
|
e1bf4d4344 | ||
|
|
0c8a32b9ae | ||
|
|
d8c60aaae7 | ||
|
|
3216d65353 | ||
|
|
0df8d0a4e2 | ||
|
|
43f19034b9 | ||
|
|
2e6a937240 | ||
|
|
05d8a7f6be | ||
|
|
ceaf4bc6bc | ||
|
|
f2cc2f433c | ||
|
|
858aa6255c | ||
|
|
1d8ea9e869 | ||
|
|
8ead0b5483 | ||
|
|
72c081cfd6 | ||
|
|
1f701c94a7 | ||
|
|
acfc49fd41 | ||
|
|
9c29bd627e | ||
|
|
d24b141d8b | ||
|
|
bac9e005ae | ||
|
|
60bcca54eb | ||
|
|
eccea8a911 | ||
|
|
0833d0d8d5 | ||
|
|
55fce489bc | ||
|
|
2ce40c3c07 | ||
|
|
255cfb7d62 | ||
|
|
8a327be400 | ||
|
|
1cae76b443 | ||
|
|
828e8d2ae4 | ||
|
|
ce35509a40 | ||
|
|
24b8b4e904 | ||
|
|
c2c1dc7469 | ||
|
|
47c1071bb8 | ||
|
|
e401651f09 | ||
|
|
1449def040 | ||
|
|
d4d1ec2568 | ||
|
|
7455ac9bfb | ||
|
|
b6b1dcb275 | ||
|
|
2e4f49a223 | ||
|
|
88d4108f92 | ||
|
|
c9f3c02cb7 | ||
|
|
557372b312 | ||
|
|
18b24535fe | ||
|
|
20e0bca71d | ||
|
|
6977f655e3 | ||
|
|
e6fc9dc75d | ||
|
|
b57b3f4588 | ||
|
|
776ae92416 | ||
|
|
6ba53c1ac0 | ||
|
|
699d419c71 | ||
|
|
d4870b3854 | ||
|
|
e49a9096a5 | ||
|
|
33148ba832 | ||
|
|
bca23dd896 | ||
|
|
3a483a1b20 | ||
|
|
310d33b8ee | ||
|
|
8b5dcc3872 | ||
|
|
36d9af10f0 | ||
|
|
0c8fcbc684 | ||
|
|
7edab27e53 | ||
|
|
9b3531f634 | ||
|
|
d8f85a8981 | ||
|
|
3b229489c2 | ||
|
|
c2fcbbb0c6 | ||
|
|
8e82bf69d8 | ||
|
|
284f9e3f2f | ||
|
|
5ffc3561ed | ||
|
|
952f1271b4 | ||
|
|
250b445eee | ||
|
|
331472b592 | ||
|
|
82d5afe996 | ||
|
|
7361d5d3ea | ||
|
|
6086614274 | ||
|
|
6bb4780d32 | ||
|
|
631f5b4848 | ||
|
|
0f17712f6c | ||
|
|
4941e0f8ad | ||
|
|
fbee18e24d | ||
|
|
f37b2bc7c1 | ||
|
|
56278c6394 | ||
|
|
b1d6c03190 | ||
|
|
1200a77b22 | ||
|
|
bb9a18ef08 | ||
|
|
a8b493cb7d | ||
|
|
1a275ba184 | ||
|
|
187848660c | ||
|
|
c3f391dc5a | ||
|
|
971e6f2664 | ||
|
|
a1d6ef04ec | ||
|
|
ff47ab12fb | ||
|
|
a97e361661 | ||
|
|
34d84522dd | ||
|
|
3390fbf238 | ||
|
|
98ad1feaeb | ||
|
|
37e8a91d5b | ||
|
|
68c27eb2a1 | ||
|
|
143e75d213 | ||
|
|
295ac49f83 | ||
|
|
d31a498e6c | ||
|
|
2fd88a1c6a | ||
|
|
fbab930cb1 | ||
|
|
bfcbd72e4b | ||
|
|
d9d3caec22 | ||
|
|
238a56cac3 | ||
|
|
51765b1f65 | ||
|
|
7159ecb632 | ||
|
|
11f3425876 | ||
|
|
e131395cce | ||
|
|
d26ea2b948 | ||
|
|
5584a9ce5d | ||
|
|
e2e8b733a8 | ||
|
|
f18bf35b20 | ||
|
|
44d8cb77e3 | ||
|
|
fc10e3fcac | ||
|
|
b92ccb2de4 | ||
|
|
30af6e73be | ||
|
|
2895b9bfb7 | ||
|
|
84bd86f1ee | ||
|
|
7193f40b87 | ||
|
|
acd69fa4b0 | ||
|
|
71d8f5f96f | ||
|
|
856a2096eb | ||
|
|
76cb129d3c | ||
|
|
246d5cd587 | ||
|
|
f390671018 | ||
|
|
512ec7fb87 | ||
|
|
24219422df | ||
|
|
aed20cf7c6 | ||
|
|
6584933e92 | ||
|
|
8cf8da4c78 | ||
|
|
ad1f210528 | ||
|
|
cadab61a21 | ||
|
|
0b87f489d5 | ||
|
|
e3e5e016d5 | ||
|
|
3425b9a82e | ||
|
|
5ecfc58e5f | ||
|
|
6011dd7372 | ||
|
|
7ed45d26c2 | ||
|
|
fcdc85eab8 | ||
|
|
56a2924a33 | ||
|
|
09886a3f11 | ||
|
|
e8ec0dc701 | ||
|
|
41d9d57c84 | ||
|
|
b87bcc8f5f | ||
|
|
0541d8f1c5 | ||
|
|
4606693e62 | ||
|
|
e61d8e4fb8 | ||
|
|
6b4685b333 | ||
|
|
d4ac818a0b | ||
|
|
c17d95bfed | ||
|
|
f14184df30 | ||
|
|
47bbea9ba7 | ||
|
|
7265935cd4 | ||
|
|
40bda4b3d1 | ||
|
|
b7891f92a5 | ||
|
|
8b79017d0f | ||
|
|
5465ac9ba0 | ||
|
|
b8eaa9a527 | ||
|
|
5d274008db | ||
|
|
220e755596 | ||
|
|
fc5034696d | ||
|
|
4a6f77bc59 | ||
|
|
1e87850952 | ||
|
|
3472241289 | ||
|
|
a944b6ff79 | ||
|
|
6c4741bc61 | ||
|
|
8a42ef431b | ||
|
|
2cf1f0e8fc | ||
|
|
55e50eced6 | ||
|
|
30a2923380 | ||
|
|
f2b3752f3d | ||
|
|
36945a67d0 | ||
|
|
c5a2ca5c98 | ||
|
|
9f2ce0e296 | ||
|
|
55e10d8287 | ||
|
|
94c772e1a8 | ||
|
|
2b6d9c34c9 | ||
|
|
1a5c86d32e | ||
|
|
c7219fbdff | ||
|
|
4c249a1186 | ||
|
|
158ea1d43b | ||
|
|
535b8458d4 | ||
|
|
49b3f82675 | ||
|
|
9543203610 | ||
|
|
cacfe4d387 | ||
|
|
a7f0137e5f | ||
|
|
b2eb364a4b | ||
|
|
bb3b1bc6ba | ||
|
|
ae8eb3f177 | ||
|
|
27c7325174 | ||
|
|
8ee3d810b0 | ||
|
|
d7dde06552 | ||
|
|
448495a4a3 | ||
|
|
52cc8e2fcf | ||
|
|
fb9cdea008 | ||
|
|
6c54bf036c | ||
|
|
657bc4edcd | ||
|
|
b75dd5ff73 | ||
|
|
607664c860 | ||
|
|
094bd49f35 | ||
|
|
18fbe60381 | ||
|
|
f1956119fb | ||
|
|
876170767c | ||
|
|
f4f77ec88b | ||
|
|
9ba2038702 | ||
|
|
b176ba9e80 | ||
|
|
cacb47ca7e | ||
|
|
500e424fee | ||
|
|
f1b02c0cab | ||
|
|
828302702b | ||
|
|
0827d4fe40 | ||
|
|
ebff965414 | ||
|
|
b45954c560 | ||
|
|
80307a3bcd | ||
|
|
e8acb5967b | ||
|
|
939806f021 | ||
|
|
cc47bf8f6c | ||
|
|
8b80aaebf5 | ||
|
|
8f35ebc0c2 | ||
|
|
793bdd9743 | ||
|
|
9d50f52bb2 | ||
|
|
db62afbb64 | ||
|
|
3dc3e8e40e | ||
|
|
c79fc81292 | ||
|
|
62a6a878d4 | ||
|
|
4efb533d2e | ||
|
|
891473c7fc | ||
|
|
81e8ef5c40 | ||
|
|
e17885088b | ||
|
|
494340fe67 | ||
|
|
01625dfd49 | ||
|
|
a154f1540f | ||
|
|
5254fc6efe | ||
|
|
afa2e9c2f7 | ||
|
|
a4c8f1a0a4 | ||
|
|
d5a9a9a2d8 | ||
|
|
3b8f8fb0ef | ||
|
|
677033afca | ||
|
|
8e0d76b63b | ||
|
|
64df41ed90 | ||
|
|
442a372142 | ||
|
|
95e5baa967 | ||
|
|
b80edfb996 | ||
|
|
e06543bd17 | ||
|
|
cca8412921 | ||
|
|
d15a5ad5c1 | ||
|
|
8ed75dd176 | ||
|
|
d43ad263ea | ||
|
|
e602008459 | ||
|
|
322a18f0e6 | ||
|
|
05eb749e66 | ||
|
|
7e8d31a62c | ||
|
|
8ca0582afc | ||
|
|
b9f5fca546 | ||
|
|
5c2dcb5e74 | ||
|
|
3ef4af9326 | ||
|
|
f89f7ecd3e | ||
|
|
be0c457445 | ||
|
|
3c04dbb4ed | ||
|
|
cfca367eef | ||
|
|
8a243c5872 | ||
|
|
b30b3f3aeb | ||
|
|
2d3906450a | ||
|
|
5ecc46d85b | ||
|
|
ddd6f3dbe5 | ||
|
|
f5237db580 | ||
|
|
761fd13a70 | ||
|
|
e3fa06d7ff | ||
|
|
61a76f4493 | ||
|
|
c5f46702c8 | ||
|
|
c24e5cd3f6 | ||
|
|
cc3035267f | ||
|
|
29ee8250e9 | ||
|
|
47ed0b7627 | ||
|
|
423280cee1 | ||
|
|
8c0faa0b9a | ||
|
|
45ab2a3d7a | ||
|
|
8804f5c423 | ||
|
|
1078aa499c | ||
|
|
05d015169c | ||
|
|
6c9e7586d5 | ||
|
|
28bed0041e | ||
|
|
6f03e30151 | ||
|
|
6085d6ffd1 | ||
|
|
6ecd93d0c9 | ||
|
|
863ea7294f | ||
|
|
af59824819 | ||
|
|
80e17ab721 | ||
|
|
f89d69b081 | ||
|
|
5ba413569e | ||
|
|
b3e969f000 | ||
|
|
a9a40ca46c | ||
|
|
79aada0b87 | ||
|
|
162a7b56fe | ||
|
|
69dc22c10f | ||
|
|
9642cda949 | ||
|
|
dd6a9a0b84 | ||
|
|
945dcc6c2b | ||
|
|
f60791ac7c | ||
|
|
b64155a165 | ||
|
|
472f7725c7 | ||
|
|
90f01b5fc4 | ||
|
|
20a2daa114 | ||
|
|
9b6a2c7068 | ||
|
|
0a4d3ef6e6 | ||
|
|
2dc1851892 | ||
|
|
8d721d086c | ||
|
|
6f0bb30def | ||
|
|
c54f04ef4c | ||
|
|
eb83081a5c | ||
|
|
8976930e20 | ||
|
|
164a81776e | ||
|
|
9c8526db49 | ||
|
|
d92f9b4dbd | ||
|
|
1556163fb0 | ||
|
|
616962200a | ||
|
|
eb9c44a347 | ||
|
|
f36ac48de0 | ||
|
|
f63267a7f9 | ||
|
|
2c8dcd86e5 | ||
|
|
9631519eb1 | ||
|
|
557d076d2e | ||
|
|
8a40c91d1a | ||
|
|
90efa3b610 | ||
|
|
35dc4800e0 | ||
|
|
ec4e4d3b72 | ||
|
|
63312ac4b8 | ||
|
|
d158a7d51e | ||
|
|
209a2ab3ec | ||
|
|
009fa2f1b7 | ||
|
|
5221767a70 | ||
|
|
9492ff26c6 | ||
|
|
06764d0f36 | ||
|
|
0db76aada0 | ||
|
|
7362416afb | ||
|
|
9be854031f | ||
|
|
709851503f | ||
|
|
6ca47dc3b3 | ||
|
|
d8774901ee | ||
|
|
8dba2a88e2 | ||
|
|
2c33c64fae | ||
|
|
b9ae01d819 | ||
|
|
2390b80359 | ||
|
|
c34c3eb016 | ||
|
|
85d159bdd1 | ||
|
|
da1d2b2c48 | ||
|
|
5f8b0b3c89 | ||
|
|
0f868f7649 | ||
|
|
8b0785996e | ||
|
|
645d8e0ebd | ||
|
|
3a3c0befa7 | ||
|
|
80c40e6050 | ||
|
|
31730e7197 | ||
|
|
7d76db00ac | ||
|
|
8aceb8bf53 | ||
|
|
a17d1be7a4 | ||
|
|
1e6cc63abe | ||
|
|
3b300a4d6a | ||
|
|
3e727c5e5d | ||
|
|
e0edac32c7 | ||
|
|
e4b3bc4209 | ||
|
|
51b09efceb | ||
|
|
2dabacd024 | ||
|
|
0613dcc87b | ||
|
|
d59a2a4cfc | ||
|
|
2c091f3a3c | ||
|
|
cfcdc53185 | ||
|
|
bd33018660 | ||
|
|
e7589945a2 | ||
|
|
67a5594909 | ||
|
|
70ad656af0 | ||
|
|
f22b83d379 | ||
|
|
114f84c948 | ||
|
|
7875df0d6b | ||
|
|
0d286b99d5 | ||
|
|
e03d4f2de8 | ||
|
|
7fddce4a1f | ||
|
|
3cd8b7d882 | ||
|
|
3578a3e311 | ||
|
|
a9ad8d67aa | ||
|
|
43e1121618 | ||
|
|
97dd1b4cf3 | ||
|
|
288635abc9 | ||
|
|
7884423e05 | ||
|
|
1615fa63e3 | ||
|
|
39ab1e1ea7 | ||
|
|
10c048d84a | ||
|
|
a458482e51 | ||
|
|
de46dbd56f | ||
|
|
60365ad36a | ||
|
|
466e6d9b30 | ||
|
|
11d48554e3 | ||
|
|
b9bcfe36ff | ||
|
|
05faa7bdf2 | ||
|
|
88b1f0ca7f | ||
|
|
f0f7bda2f3 | ||
|
|
664d0ea023 | ||
|
|
cd7c00ef8e | ||
|
|
3f20981aab | ||
|
|
f54a812ad5 | ||
|
|
aa1d67a4de | ||
|
|
feb2150d9b | ||
|
|
3aa525b0c0 | ||
|
|
6323d5afed | ||
|
|
e3e3b4da58 | ||
|
|
a0bd517380 | ||
|
|
4316b15ae2 | ||
|
|
ef1ce7d4d6 | ||
|
|
a643f40cce | ||
|
|
47099e2855 | ||
|
|
2deb2bf03f | ||
|
|
3bb05edb52 | ||
|
|
ee2169dd13 | ||
|
|
11282aaca3 | ||
|
|
909bc92c01 | ||
|
|
a6f9272d4b | ||
|
|
911596daf8 | ||
|
|
8d8482d60b | ||
|
|
f3cc8c71c4 | ||
|
|
f6b3c62b06 | ||
|
|
26afe04926 | ||
|
|
500a755250 | ||
|
|
d02bf258af | ||
|
|
56990618e9 | ||
|
|
54a85d3a63 | ||
|
|
d56beedd7a | ||
|
|
c2d3e99ddd | ||
|
|
5e48b3f7f7 | ||
|
|
00d62b3423 | ||
|
|
c957124fad | ||
|
|
28063aa7f7 | ||
|
|
c458e4a93b | ||
|
|
e7ae62ba76 | ||
|
|
ff5411a93a | ||
|
|
d3073e5e23 | ||
|
|
34ae4844fa | ||
|
|
8191ec01e5 | ||
|
|
4d39ab9753 | ||
|
|
7a1df15724 | ||
|
|
42b5574f9b | ||
|
|
5f4be0de35 | ||
|
|
6c605f55f9 | ||
|
|
774c6e8ac0 | ||
|
|
17be6b860e | ||
|
|
474ac4a15d | ||
|
|
b8fedf76cd | ||
|
|
ca88c59d4e | ||
|
|
d69e62589a | ||
|
|
c9d4995900 | ||
|
|
279e809aaf | ||
|
|
d61857efae | ||
|
|
0d037e96fb | ||
|
|
6376f9aef4 | ||
|
|
f5a1fa21f7 | ||
|
|
4a90dac68e | ||
|
|
2624e56de5 | ||
|
|
aef54d6694 | ||
|
|
e839a7784c | ||
|
|
bea99abd8d | ||
|
|
a5c4ae955a | ||
|
|
d7d53849a3 | ||
|
|
b354f722be | ||
|
|
ea1aad9774 | ||
|
|
817d644795 | ||
|
|
56b8c4bfdb | ||
|
|
c65c26b463 | ||
|
|
bf059e5ee8 | ||
|
|
15a5f425bf | ||
|
|
3125d24ded | ||
|
|
6b6d105c2f | ||
|
|
bab44c52ae | ||
|
|
2f19605750 | ||
|
|
7311db3a63 | ||
|
|
0a00936e99 | ||
|
|
7cac207c00 | ||
|
|
feb412b02a | ||
|
|
199de9ebc0 | ||
|
|
504ae0193f | ||
|
|
1ae403b742 | ||
|
|
939c99cdbf | ||
|
|
2f36acae49 | ||
|
|
e938132c53 | ||
|
|
1b34286264 | ||
|
|
54f4f6d2d7 | ||
|
|
07e5e8e67a | ||
|
|
3c25094495 | ||
|
|
95e3a5944d | ||
|
|
64f29120c8 | ||
|
|
d92434b1e9 | ||
|
|
01cd056bcc | ||
|
|
56f2ea3ec2 | ||
|
|
d45695a088 | ||
|
|
2ceeac41fe | ||
|
|
cc4ada99d8 | ||
|
|
16d67f55b3 | ||
|
|
18b41adbf6 | ||
|
|
898fdf7a60 | ||
|
|
78143c2ff4 | ||
|
|
7b1524ad01 | ||
|
|
5799485b0f | ||
|
|
9cddb6ca39 | ||
|
|
defc17ba46 | ||
|
|
106d5afba1 | ||
|
|
0a9965292c | ||
|
|
4fb66e632f | ||
|
|
5787895794 | ||
|
|
d90489b31d | ||
|
|
f38912a0c9 | ||
|
|
f24ab8508e | ||
|
|
2d8fff099f | ||
|
|
dce36d8ded | ||
|
|
18d0278279 | ||
|
|
4e525040f3 | ||
|
|
fdf2649f2f | ||
|
|
b09c660833 | ||
|
|
c02a24cf71 | ||
|
|
a77136bd1d | ||
|
|
e0eb5eb2b1 | ||
|
|
714fd93292 | ||
|
|
a293b5a371 | ||
|
|
1c93868ae1 | ||
|
|
61ff0452e1 | ||
|
|
406098e55a | ||
|
|
a2825be819 | ||
|
|
6830b08723 | ||
|
|
eead2f059b | ||
|
|
291c111ce8 | ||
|
|
2ccf063dfe | ||
|
|
49aee8b931 | ||
|
|
f2a3b557c8 | ||
|
|
b0eceddcec | ||
|
|
0a062d26e6 | ||
|
|
20b2dd6b19 | ||
|
|
83592a5e70 | ||
|
|
70fb733fea | ||
|
|
eb8333c772 | ||
|
|
c9a98b68c8 | ||
|
|
247d3ed729 | ||
|
|
031c6428d5 | ||
|
|
f2e9d585f7 | ||
|
|
8af9853b9a | ||
|
|
783f50657b | ||
|
|
3a50b91722 | ||
|
|
3631d1349e | ||
|
|
05c8687041 | ||
|
|
66f32b7601 | ||
|
|
9101916719 | ||
|
|
edb594461d | ||
|
|
9464b71a6e | ||
|
|
7d56e2a937 | ||
|
|
218aa03f05 | ||
|
|
1db03a10d7 | ||
|
|
e1f818ffb7 | ||
|
|
9934f505a5 | ||
|
|
8c2b8f7241 | ||
|
|
bf70c2c660 | ||
|
|
74b912a0b7 | ||
|
|
93d40b083e | ||
|
|
162ee28d0c | ||
|
|
d328d17d03 | ||
|
|
2778d88e8a | ||
|
|
b5c6178644 | ||
|
|
ea8927e1da | ||
|
|
bc1065a7fc | ||
|
|
f4c7d389e5 | ||
|
|
03387391de | ||
|
|
24df5f5208 | ||
|
|
9348a8ab15 | ||
|
|
fbd55dd740 | ||
|
|
e5e26413e9 | ||
|
|
527fe2f5e1 | ||
|
|
38d213ee6c | ||
|
|
613f2d3b86 | ||
|
|
e7ad972783 | ||
|
|
2f939d8c56 | ||
|
|
7ef751f96d | ||
|
|
fb66fb12c5 | ||
|
|
042dcf795c | ||
|
|
aad39c5ffc | ||
|
|
c3ed710e31 | ||
|
|
cb65907e60 | ||
|
|
bb8a263d70 | ||
|
|
70fd94edb3 | ||
|
|
d0492898eb | ||
|
|
c6ba03802f | ||
|
|
1bebcef265 | ||
|
|
209fbf82c4 | ||
|
|
6ce79ae1d0 | ||
|
|
b3eb5c4f0e | ||
|
|
ec4e9780ed | ||
|
|
22abbffbb7 | ||
|
|
05a724afae | ||
|
|
1957b002bc | ||
|
|
04cef25add | ||
|
|
ab1a6d8829 | ||
|
|
98afb0e998 | ||
|
|
e9d81fc883 | ||
|
|
22fac5e1e0 | ||
|
|
b6a2a4ad5a | ||
|
|
5f00347019 | ||
|
|
89a22ded54 | ||
|
|
1e31fa89aa | ||
|
|
b477b7f777 | ||
|
|
0de15f7a97 | ||
|
|
35ecf40259 | ||
|
|
009363a7bb | ||
|
|
a3758612ec | ||
|
|
8dc94e014f | ||
|
|
ad886ac164 | ||
|
|
78e7c8b8e9 | ||
|
|
3779085051 | ||
|
|
c29c4ceb0f | ||
|
|
07fc047dd8 | ||
|
|
bc46694ea7 | ||
|
|
0c2827e130 | ||
|
|
cb09e0bc9a | ||
|
|
06d5ea9d51 | ||
|
|
a4650c6226 | ||
|
|
c85a603491 | ||
|
|
536585b846 | ||
|
|
ecde222512 | ||
|
|
5b472ff67c | ||
|
|
6f2ec22894 | ||
|
|
05798fe07a | ||
|
|
8ab5ffd876 | ||
|
|
2b6709d83f | ||
|
|
e4cc5b3847 | ||
|
|
8bad56e897 | ||
|
|
92e691408f | ||
|
|
0a9c234127 | ||
|
|
0283a1ab74 | ||
|
|
b32096b16e | ||
|
|
3d7582faec | ||
|
|
54a88ab5ab | ||
|
|
aff5ff08d5 | ||
|
|
fc0440546f | ||
|
|
172b8d2427 | ||
|
|
6d10a498a5 | ||
|
|
881819ed5f | ||
|
|
3275c5f710 | ||
|
|
b0cc1a38c3 | ||
|
|
e8025dbc81 | ||
|
|
e10182c839 | ||
|
|
b4f1fe08f0 | ||
|
|
64171fa2a1 | ||
|
|
048eacd305 | ||
|
|
24aa72c19d | ||
|
|
92b5fe4be4 | ||
|
|
939055f19c | ||
|
|
c47f3e3307 | ||
|
|
cf6a1ac9ad | ||
|
|
f1146a3443 | ||
|
|
6823a62644 | ||
|
|
2516a1e298 | ||
|
|
288f93c5dd | ||
|
|
8ef64dbe74 | ||
|
|
01e091fd17 | ||
|
|
8b4c0b456b | ||
|
|
02a601deff | ||
|
|
b207fadc04 | ||
|
|
bf3883ed46 | ||
|
|
3a58e9d33a | ||
|
|
570c54002f | ||
|
|
d51c067e1b | ||
|
|
2fea5d428d | ||
|
|
2b8a8b03a8 | ||
|
|
d51e0c49b1 | ||
|
|
d913534793 | ||
|
|
36907edd50 | ||
|
|
7ec169ab10 | ||
|
|
7873da1ae5 | ||
|
|
ef5a6e7880 | ||
|
|
96f01e670f | ||
|
|
10139241f5 | ||
|
|
5902be2a49 | ||
|
|
cc946ce068 | ||
|
|
1102fdc44b | ||
|
|
c995c81fff | ||
|
|
6684af9938 | ||
|
|
8bafd12f95 | ||
|
|
76266cf31b | ||
|
|
4ad0cdf5d4 | ||
|
|
1a87d3a659 | ||
|
|
085f2c6ca0 | ||
|
|
98fdb95645 | ||
|
|
3035c9a366 | ||
|
|
5004cf331a | ||
|
|
74eb8c8622 | ||
|
|
b74300f67c | ||
|
|
107babe8f4 | ||
|
|
8fd9a22d18 | ||
|
|
8c5c1316dd | ||
|
|
daff5d8b5a | ||
|
|
6c4a7b626e | ||
|
|
1aa5943e67 | ||
|
|
69fe889f92 | ||
|
|
2ef87ad110 | ||
|
|
c655e6ea73 | ||
|
|
5d7ef9281f | ||
|
|
6fa00e7cc8 | ||
|
|
2f2825f15e | ||
|
|
e377fe5503 | ||
|
|
69b41dd72e | ||
|
|
69fa9874dd | ||
|
|
a620a5c430 | ||
|
|
1f3db8b602 | ||
|
|
f6732a484e | ||
|
|
4015122d33 | ||
|
|
42eb811910 | ||
|
|
c9042ffedd | ||
|
|
4e2c6a7b8e | ||
|
|
7453bf2ee6 | ||
|
|
7d17c652f3 | ||
|
|
075f00cecd | ||
|
|
b9f2ba0717 | ||
|
|
ed04be5faa | ||
|
|
90119c75d5 | ||
|
|
d30056026b | ||
|
|
bc8a5916d8 | ||
|
|
f202602f99 | ||
|
|
69f361a3a1 | ||
|
|
da9ff0cc66 | ||
|
|
703ff09a91 | ||
|
|
30035ce1c2 | ||
|
|
39b74ebfd4 | ||
|
|
3bd677c102 | ||
|
|
4eb7d2868c | ||
|
|
0e4473685b | ||
|
|
b721ed49ab | ||
|
|
25601b9fcc | ||
|
|
db10c8ab46 | ||
|
|
55f78e3b64 | ||
|
|
7abf349730 | ||
|
|
f9d41caeb6 | ||
|
|
b166410cbf | ||
|
|
31d5a7ae9e | ||
|
|
5bb91759b4 | ||
|
|
80c4b7c9bb | ||
|
|
ea0a9ceb37 | ||
|
|
68dd2a6b91 | ||
|
|
f875976268 | ||
|
|
e23c6899e0 | ||
|
|
c35c7b2cea | ||
|
|
1c2aa44d46 | ||
|
|
3b44a0da32 | ||
|
|
58353e2839 | ||
|
|
5e0572637e | ||
|
|
501b26decd | ||
|
|
c6596f2c54 | ||
|
|
2863308090 | ||
|
|
7fef1fdc83 | ||
|
|
3081c151bd | ||
|
|
c793295be0 | ||
|
|
fe0a35cc7a | ||
|
|
0b67eebaec | ||
|
|
03201e2f20 | ||
|
|
dfc32b26a6 | ||
|
|
173ad339bb | ||
|
|
89fd962615 | ||
|
|
a928cd3fa1 | ||
|
|
f190a6ebc5 | ||
|
|
9beb9fd941 | ||
|
|
525a1228c3 | ||
|
|
19fd25c7cd | ||
|
|
5b0927ca4b | ||
|
|
324d4433c3 | ||
|
|
615ca56ea3 | ||
|
|
41dd163453 | ||
|
|
5cd2c77d98 | ||
|
|
f270f7430c | ||
|
|
99b23627d0 | ||
|
|
26fcb1b2a0 | ||
|
|
e9c4e8123c | ||
|
|
a290e01bdf | ||
|
|
9cc392fa02 | ||
|
|
7c2046cce7 | ||
|
|
4d731ca30b | ||
|
|
f2016f26d7 | ||
|
|
b13171cc45 | ||
|
|
9c645e2010 | ||
|
|
bb6f409e89 | ||
|
|
61ec7723f6 | ||
|
|
9c136a5579 | ||
|
|
a5733508ae | ||
|
|
a8818c16d8 | ||
|
|
c8e1e6dc8a | ||
|
|
7bcea98d0c | ||
|
|
74b15d10d9 | ||
|
|
356c70cdae | ||
|
|
dfb5c37d98 | ||
|
|
30dcf6ff47 | ||
|
|
a0603ad3b7 | ||
|
|
551add5f44 | ||
|
|
88944a31ec | ||
|
|
3473ebc0fe | ||
|
|
8c657910ae | ||
|
|
1886c44579 | ||
|
|
1dcc1871fb | ||
|
|
19e688effb | ||
|
|
6a2b885988 | ||
|
|
bfc4775b34 | ||
|
|
981004606b | ||
|
|
9d40fd1eda | ||
|
|
db1e5f10ea | ||
|
|
fbb6b56d99 | ||
|
|
f1f70133dc | ||
|
|
d0f55e5125 | ||
|
|
5e308dbd51 | ||
|
|
c3c554f4d6 | ||
|
|
320c06e0a4 | ||
|
|
2e398c5da4 | ||
|
|
b1484104bd | ||
|
|
c738a9a044 | ||
|
|
519cb71022 | ||
|
|
fcd92d27f7 | ||
|
|
3eacfa9831 | ||
|
|
ff6df76e36 | ||
|
|
1d64b614c7 | ||
|
|
a832dd7f67 | ||
|
|
a96b4d28e1 | ||
|
|
57e8b7f924 | ||
|
|
263eb856d5 | ||
|
|
5a4f088b24 | ||
|
|
c1913bfa7d | ||
|
|
474881e4c7 | ||
|
|
7e0aa822b6 | ||
|
|
940d780a4c | ||
|
|
ad9575ce18 | ||
|
|
ce86205df0 | ||
|
|
3cf9942465 | ||
|
|
153031482f | ||
|
|
1f74b1e2fd | ||
|
|
42393123a0 | ||
|
|
af2cff5177 | ||
|
|
5435b93df2 | ||
|
|
3a3dde6298 | ||
|
|
b4bc90fb85 | ||
|
|
02040cd25d | ||
|
|
bdc6bd4135 | ||
|
|
e720de401d | ||
|
|
ce97896ffd | ||
|
|
86fa4e9ee8 | ||
|
|
f09c166350 | ||
|
|
24868fdb2b | ||
|
|
a463250ecf | ||
|
|
d38e034e92 | ||
|
|
6eb9192cd1 | ||
|
|
94f15f1b3c | ||
|
|
ee296f36c1 | ||
|
|
598a7b3cc0 | ||
|
|
52baf26d7d | ||
|
|
fb3e6ee35c | ||
|
|
af1d1bd9c2 | ||
|
|
f32ad7699d | ||
|
|
79294bb6ca | ||
|
|
1cd4710718 | ||
|
|
48c19ade8e | ||
|
|
0acf70f836 | ||
|
|
fd584dd03b | ||
|
|
2740c68a63 | ||
|
|
62a242a894 | ||
|
|
8b060e9699 | ||
|
|
b1f769b671 | ||
|
|
77378da70a | ||
|
|
160030b75f | ||
|
|
0a0c3a2fb7 | ||
|
|
e9f1ca338f | ||
|
|
073c7e54df | ||
|
|
2834f2ccc2 | ||
|
|
6c56665403 | ||
|
|
0d794226ab | ||
|
|
ab2af11775 | ||
|
|
83662c9e50 | ||
|
|
6c1d52199f | ||
|
|
cfaf1ac67c | ||
|
|
a6caa0e680 | ||
|
|
c4b43f92ce | ||
|
|
3d1ccd9625 | ||
|
|
76bd53ef1f | ||
|
|
8fa209f0df | ||
|
|
88835512dd | ||
|
|
6b862dd9e9 | ||
|
|
be0b76c954 | ||
|
|
e45559da20 | ||
|
|
d7b5870ba6 | ||
|
|
bb7a7d94ef | ||
|
|
9a475cc010 | ||
|
|
ae30c285a2 | ||
|
|
df18c7cd59 | ||
|
|
2e74219ff9 | ||
|
|
b0ae954f1e | ||
|
|
a2404f104a | ||
|
|
38547ced7a | ||
|
|
9a9d9007cd | ||
|
|
bd2d81f691 | ||
|
|
1b9e7fbf2e | ||
|
|
d4a49d192f | ||
|
|
8cb66544d2 | ||
|
|
140ac192aa | ||
|
|
b961b13d60 | ||
|
|
febdb4a190 | ||
|
|
1d60b62e7a | ||
|
|
41e1e4cb68 | ||
|
|
d5b88e0df8 | ||
|
|
20fd61468d | ||
|
|
0a0d25dff4 | ||
|
|
38ba079baa | ||
|
|
33f7979359 | ||
|
|
8460b2544b | ||
|
|
bc514ea955 | ||
|
|
6f8893d950 | ||
|
|
de6aaf18ab | ||
|
|
0fe64cf5cc | ||
|
|
9a95531fb9 | ||
|
|
9df6a8dd06 | ||
|
|
1590a179fa | ||
|
|
5e16487ef6 | ||
|
|
2b3afbfef8 | ||
|
|
c3c7dcc9f5 | ||
|
|
273728b481 | ||
|
|
81a1057cac | ||
|
|
fd310c6445 | ||
|
|
a9b52518bf | ||
|
|
87da40068c | ||
|
|
b8f1eadb7f | ||
|
|
b522d8eaf6 | ||
|
|
89ff99322d | ||
|
|
56e17d1010 | ||
|
|
708067e875 | ||
|
|
d2ab0694b7 | ||
|
|
8a14a63d5d | ||
|
|
8235b18854 | ||
|
|
e0e9ebbe74 | ||
|
|
6e6259975e | ||
|
|
10bc8414b9 | ||
|
|
4e25e0dc5c | ||
|
|
b1a9793d94 | ||
|
|
6dea00668e | ||
|
|
ae9182c92e | ||
|
|
af17355fe7 | ||
|
|
dce3e50a00 | ||
|
|
cf31561267 | ||
|
|
a97f0b1298 | ||
|
|
d1e0f3ae18 | ||
|
|
47a6786e8f | ||
|
|
a69fcbb91e | ||
|
|
8e2b51b391 | ||
|
|
560af43204 | ||
|
|
9c119f919e | ||
|
|
baefec86f2 | ||
|
|
eb763d2dc2 | ||
|
|
512c650441 | ||
|
|
dc44fc9e27 | ||
|
|
05640f9a6b | ||
|
|
6f2fb57c08 | ||
|
|
2547cc4c8d | ||
|
|
112ddb3c77 | ||
|
|
9f4ef66f41 | ||
|
|
086f0790fc | ||
|
|
709b44f736 | ||
|
|
6cd4ff6d68 | ||
|
|
abd3e828de | ||
|
|
b85af50d14 | ||
|
|
0e8fd49669 | ||
|
|
945e22874e | ||
|
|
77ab47a984 | ||
|
|
ed8088f203 | ||
|
|
8831b22fc8 | ||
|
|
0341bd1758 | ||
|
|
9bb4a5fb25 | ||
|
|
ebfffea5dc | ||
|
|
81939ab265 | ||
|
|
f2fe84c9d3 | ||
|
|
051f463350 | ||
|
|
f626406685 | ||
|
|
dd971b6ee5 | ||
|
|
8776b822db | ||
|
|
fc76b1a6a3 | ||
|
|
9183200b6f | ||
|
|
f1b8abf503 | ||
|
|
9502356980 | ||
|
|
a535ca9db4 | ||
|
|
2c762899de | ||
|
|
24fd23493d | ||
|
|
6f1ed28d0a | ||
|
|
66b7d04b82 | ||
|
|
044afa838c | ||
|
|
7ba47f504c | ||
|
|
0be1717ff4 | ||
|
|
189a4e0078 | ||
|
|
3adf8785d8 | ||
|
|
b74862bfc5 | ||
|
|
01273124ea | ||
|
|
721ada7e16 | ||
|
|
bd9dc91396 | ||
|
|
de6c43a8d3 | ||
|
|
93dea7b942 | ||
|
|
f6fc6a5e56 | ||
|
|
ca24f7c143 | ||
|
|
17b0db6515 | ||
|
|
83b0600863 | ||
|
|
38961fb31b | ||
|
|
6c130b7960 | ||
|
|
7244d44a1d | ||
|
|
9b060aab34 | ||
|
|
ba5bbf3523 | ||
|
|
697b0295f3 | ||
|
|
66d7ebd6c3 | ||
|
|
ae24f1255f | ||
|
|
ec7e75a6e3 | ||
|
|
aee106ae69 | ||
|
|
2a881a90ac | ||
|
|
ce6c465942 | ||
|
|
3748a0ed33 | ||
|
|
7a1a2dec67 | ||
|
|
7ed1bbad49 | ||
|
|
078cc7660e | ||
|
|
af2893d2ce | ||
|
|
0fe5efba76 | ||
|
|
fb6631d317 | ||
|
|
cd0b8927c5 | ||
|
|
3fab34687c | ||
|
|
b2d78edae9 | ||
|
|
412cacac49 | ||
|
|
dcb9797f35 | ||
|
|
4dcee5cd84 | ||
|
|
a64211123f | ||
|
|
1645677c3a | ||
|
|
4f85ace525 | ||
|
|
e8fde702a0 | ||
|
|
e339f3852c | ||
|
|
032f94afc0 | ||
|
|
e9b50442fa | ||
|
|
77b3764481 | ||
|
|
90ccbef431 | ||
|
|
02ea9b9abc | ||
|
|
4cd598ae10 | ||
|
|
8eeb8ad779 | ||
|
|
2ffb103acb | ||
|
|
a0c17368ed | ||
|
|
d76e761d0b | ||
|
|
6023984703 | ||
|
|
cde7b53de3 | ||
|
|
b36a44a954 | ||
|
|
fcc3d5450d | ||
|
|
057cecb3e0 | ||
|
|
86c6e0e826 | ||
|
|
5c223b5f4e | ||
|
|
883aa30aca | ||
|
|
763b51fe22 | ||
|
|
dd1aa9163c | ||
|
|
e087797edc | ||
|
|
5e6f8489a9 | ||
|
|
48351fed79 | ||
|
|
875a5d309d | ||
|
|
70e876ee13 | ||
|
|
7a269e757e | ||
|
|
87edbeaf58 | ||
|
|
339f95b00c | ||
|
|
e480c761cd | ||
|
|
26c628f8a5 | ||
|
|
59d6907d71 | ||
|
|
b4450a3918 | ||
|
|
7032be6049 | ||
|
|
70a6a79b8c | ||
|
|
f24f77c5bd | ||
|
|
66ae79f9b8 | ||
|
|
378338c684 | ||
|
|
7da076df18 | ||
|
|
45fbadbb26 | ||
|
|
a7def771c8 | ||
|
|
543f1243e2 | ||
|
|
a001443ad7 | ||
|
|
36166c129a | ||
|
|
4e7a485e23 | ||
|
|
9e5795bf55 | ||
|
|
053b38e0bd | ||
|
|
2aa3a109a0 | ||
|
|
472708376d | ||
|
|
cfed3d59e9 | ||
|
|
95fd9d4863 | ||
|
|
c89bca6ec8 | ||
|
|
ee262c30c2 | ||
|
|
6b8240d4de | ||
|
|
4035c933df | ||
|
|
abd44dd284 | ||
|
|
95d7fe76b5 | ||
|
|
a052f397fe | ||
|
|
09d6e73b0a | ||
|
|
7fb6b71d52 | ||
|
|
07e37d7fc3 | ||
|
|
fbe3dc0dcd | ||
|
|
6018c0c2fc | ||
|
|
52a2f166fd | ||
|
|
26cb6a1929 | ||
|
|
7c63bbfe44 | ||
|
|
109026222e | ||
|
|
af8e629df4 | ||
|
|
f7f1daa69f | ||
|
|
01f980d49c | ||
|
|
99fab7e52a | ||
|
|
692292b1d4 | ||
|
|
cd608d9d5b | ||
|
|
ba67144e34 | ||
|
|
162d9d7d57 | ||
|
|
357f5a2cfd | ||
|
|
d1ca32b0a5 | ||
|
|
34f326c559 | ||
|
|
7785dac50e | ||
|
|
01f643e5eb | ||
|
|
8037f3e332 | ||
|
|
19e30b829a | ||
|
|
afe5176e01 | ||
|
|
a48317883d | ||
|
|
5ac92ae4eb | ||
|
|
8fb6ba19a1 | ||
|
|
314f7e7889 | ||
|
|
4fcf8fd23f | ||
|
|
10a30344e5 | ||
|
|
1206dda347 | ||
|
|
b764d17c64 | ||
|
|
ba0abdb88d | ||
|
|
1428b58dde | ||
|
|
e57425df5f | ||
|
|
5e7dfaf220 | ||
|
|
ad5c011b6c | ||
|
|
fcdd33b585 | ||
|
|
f767f066ad | ||
|
|
b8d0e5e5a1 | ||
|
|
26ad23f01e | ||
|
|
21d771e171 | ||
|
|
66616eb0f0 | ||
|
|
18eb8a2159 | ||
|
|
72a1fc3f64 | ||
|
|
96eea32a9d | ||
|
|
3239c7023a | ||
|
|
5333895a9f | ||
|
|
da05491992 | ||
|
|
b9f5d79f3d | ||
|
|
fddc515ee1 | ||
|
|
3d4516dc95 | ||
|
|
509c864cc3 | ||
|
|
8b22f435ad | ||
|
|
55d39595e1 | ||
|
|
f8944177a0 | ||
|
|
3060c4d887 | ||
|
|
13ee5dc728 | ||
|
|
06873fe69e | ||
|
|
a8ac212ee6 | ||
|
|
3d9d13222b | ||
|
|
745adabb05 | ||
|
|
3861b57dc6 | ||
|
|
99a4a80017 | ||
|
|
033ba26041 | ||
|
|
439999cb62 | ||
|
|
7291aa07ca | ||
|
|
9181e2652e | ||
|
|
409f76aa34 | ||
|
|
54e2c6181a | ||
|
|
a281d87315 | ||
|
|
2a5587f236 | ||
|
|
2d18b2d784 | ||
|
|
585f842206 | ||
|
|
8cb4304c13 | ||
|
|
737819b56e | ||
|
|
a7130e6530 | ||
|
|
f9cfed5aff | ||
|
|
f65a9dbfd2 | ||
|
|
96c59fada4 | ||
|
|
153a9d8ac7 | ||
|
|
297d4eec57 | ||
|
|
c31b4383e6 | ||
|
|
0375a3caa3 | ||
|
|
08cddba200 | ||
|
|
1bf43b0425 | ||
|
|
35828f9cea | ||
|
|
90af12fdb8 | ||
|
|
dc63182647 | ||
|
|
5fede23cf7 | ||
|
|
bc4762f270 | ||
|
|
01429d59bd | ||
|
|
731d15f9b5 | ||
|
|
f0bd7fae5c | ||
|
|
f8322cc2d4 | ||
|
|
dfdb9e393b | ||
|
|
bd07d7f32e | ||
|
|
f588c6f93c | ||
|
|
d9ec3d2c22 | ||
|
|
e2b87759d8 | ||
|
|
52e0aa11af | ||
|
|
1421c31179 | ||
|
|
d5587e32d0 | ||
|
|
28eb348707 | ||
|
|
91bcc18e6a | ||
|
|
5b43f13935 | ||
|
|
85b3fef08d | ||
|
|
cc7c48237c | ||
|
|
15037fa888 | ||
|
|
d595fef18f | ||
|
|
be5fa22b6f | ||
|
|
a5c6bbeee7 | ||
|
|
094a645e60 | ||
|
|
51acdfa633 | ||
|
|
2c16a75ef1 | ||
|
|
6fd7e0311c | ||
|
|
1bcf2dd0fc | ||
|
|
9a3cf949cf | ||
|
|
cec214f900 | ||
|
|
dad669d68b | ||
|
|
561f40d97e | ||
|
|
dad18dc5de | ||
|
|
5c95c4074b | ||
|
|
4301b9a12a | ||
|
|
0bbe0aed83 | ||
|
|
b16f797317 | ||
|
|
4bb71ae046 | ||
|
|
679b098aa7 | ||
|
|
e0e88fdb52 | ||
|
|
8bba3a257c | ||
|
|
8529c1287f | ||
|
|
9c7f7756b4 | ||
|
|
f1cfb16bf9 | ||
|
|
95796e1978 | ||
|
|
968b981ecb | ||
|
|
3aeb378b56 | ||
|
|
28bafe7427 | ||
|
|
1317b67657 | ||
|
|
3f462c771f | ||
|
|
31aa42c35e | ||
|
|
f7a17248b7 | ||
|
|
b60e6310bf | ||
|
|
6a89c6bf3b | ||
|
|
b3b7aae7d7 | ||
|
|
fe8c365d17 | ||
|
|
9acc3aac01 | ||
|
|
1ad23a065e | ||
|
|
de102fde5c | ||
|
|
77554fbd13 | ||
|
|
6863bff7c5 | ||
|
|
eaf6938c35 | ||
|
|
34ad2157dd | ||
|
|
0635309f23 | ||
|
|
2661ef53a2 | ||
|
|
eddca8f127 | ||
|
|
cef0211c00 | ||
|
|
86052540d9 | ||
|
|
930cb15e2c | ||
|
|
8bb9dd460b | ||
|
|
8a3c78ca0a | ||
|
|
62a5e36afd | ||
|
|
00b28f0aed | ||
|
|
7c94aa9f07 | ||
|
|
ec8c40b69b | ||
|
|
2981f3cbd1 | ||
|
|
c2e1819098 | ||
|
|
58f3ff69d8 | ||
|
|
72d8d10e64 | ||
|
|
63d02df0bc | ||
|
|
f579fd3895 | ||
|
|
34df34ba27 | ||
|
|
2689b37c35 | ||
|
|
9b6427144f | ||
|
|
9212eea8bd | ||
|
|
6de5d6dd0a | ||
|
|
08f08fea61 | ||
|
|
1ed2a8637f | ||
|
|
d8bcbdadd6 | ||
|
|
d196c13f2c | ||
|
|
7ba251d3a6 | ||
|
|
0b72c639fb | ||
|
|
bd1c5a42e8 | ||
|
|
845d8c0e63 | ||
|
|
bcb8a52418 | ||
|
|
322cb2387b | ||
|
|
bfe56942f9 | ||
|
|
b4c32e47c6 | ||
|
|
248d8680f7 | ||
|
|
1bda965a7c | ||
|
|
2ee305769d | ||
|
|
3a8a936575 | ||
|
|
6b6fbc4709 | ||
|
|
3fd2ffd466 | ||
|
|
b56ca2b834 | ||
|
|
10f77df8bb | ||
|
|
df7671d393 | ||
|
|
a263936243 | ||
|
|
11924d425b | ||
|
|
0bd5a5f382 | ||
|
|
757eb64be3 | ||
|
|
6b3aea933d | ||
|
|
2935275227 | ||
|
|
cbe045b946 | ||
|
|
c58a95ca2e | ||
|
|
80a3bce6d5 | ||
|
|
6f0289de49 | ||
|
|
0966d7660e | ||
|
|
27e90cc4e6 | ||
|
|
b785213c3a | ||
|
|
642a73508d | ||
|
|
8f7b023769 | ||
|
|
a122fb2900 | ||
|
|
a299a2cc5f | ||
|
|
47196d86ad | ||
|
|
a713cf7952 | ||
|
|
6cd7b8ff5e | ||
|
|
f8264f8277 | ||
|
|
0e4d5e9103 | ||
|
|
f599bcfef9 | ||
|
|
74a4e62cc9 | ||
|
|
63a414a544 | ||
|
|
7d1f5091a7 | ||
|
|
3b54cab3bc | ||
|
|
52d06d906e | ||
|
|
d9e949b27c | ||
|
|
b65fe9d64f | ||
|
|
168397e90d | ||
|
|
e3c1fcd2c6 | ||
|
|
a2bc86fbcb | ||
|
|
26c6446252 | ||
|
|
e5e44db5ac | ||
|
|
d4f833c739 | ||
|
|
806f44abe6 | ||
|
|
900bdc5ee2 | ||
|
|
200995bf29 | ||
|
|
3a90c1c192 | ||
|
|
cc68155dfa | ||
|
|
b8545eb1df | ||
|
|
76531da340 | ||
|
|
12bec1df68 | ||
|
|
2b778695b1 | ||
|
|
ad61852804 | ||
|
|
dbd8aee4ee | ||
|
|
677694b01a | ||
|
|
85f0241c0d | ||
|
|
ade2185a9f | ||
|
|
0d27005dda | ||
|
|
8ee2bdec4d | ||
|
|
de6ce276d0 | ||
|
|
fbea81dcd7 | ||
|
|
502c349b8b | ||
|
|
5fb0aa70de | ||
|
|
7750e1344c | ||
|
|
8be37130e9 | ||
|
|
fa055481a7 | ||
|
|
d080e5d7a8 | ||
|
|
ad07655630 | ||
|
|
7cceb8615a | ||
|
|
ab9c8f4859 | ||
|
|
ffb8a74111 | ||
|
|
45587194e5 | ||
|
|
ccbf391913 | ||
|
|
ebf0db4bbf | ||
|
|
7765efa6c4 | ||
|
|
02d4b6794c | ||
|
|
836b717346 | ||
|
|
9ac265980f | ||
|
|
40798da6b1 | ||
|
|
fc596e41d4 | ||
|
|
1f9b0f7cef | ||
|
|
7bcc15e416 | ||
|
|
1a3bdbaabf | ||
|
|
5e35fdbc52 | ||
|
|
ab2c486f25 | ||
|
|
7fd7430d38 | ||
|
|
089b98430f | ||
|
|
5c7fc05a32 | ||
|
|
ced0d3c2c0 | ||
|
|
1afc5d351d | ||
|
|
09bbc81470 | ||
|
|
f7274addcd | ||
|
|
09bfa2ef77 | ||
|
|
a48518d234 | ||
|
|
a4a9879643 | ||
|
|
d1ccd7a460 | ||
|
|
9181a4a1d8 | ||
|
|
3268e1611a | ||
|
|
ea9ec384c6 | ||
|
|
bbb958b7ed | ||
|
|
cf724176dc | ||
|
|
18d1c98f08 | ||
|
|
d0cd39a25f | ||
|
|
03d4fcd17d | ||
|
|
02d658be65 | ||
|
|
1e627c7e8f | ||
|
|
9170488b0a | ||
|
|
b02730a5ad | ||
|
|
9af26cbaac | ||
|
|
73741f1518 | ||
|
|
9a9cb61345 | ||
|
|
6abd6d8879 | ||
|
|
c3b51b4ceb | ||
|
|
321ea8a3a9 | ||
|
|
4d6263872d | ||
|
|
fcdd58ac94 | ||
|
|
ef8292d371 | ||
|
|
bc6a985f7c | ||
|
|
7320fc11d2 | ||
|
|
51f6d75db4 | ||
|
|
a328326e39 | ||
|
|
4eedf8a746 | ||
|
|
c5f5252145 | ||
|
|
3f189ae7fe | ||
|
|
7fadd469c9 | ||
|
|
823e874d20 | ||
|
|
739aaafa9a | ||
|
|
62d001225a | ||
|
|
e50947eb58 | ||
|
|
ca056d32d2 | ||
|
|
63a455f4f7 | ||
|
|
a0e0465036 | ||
|
|
d174a9d015 | ||
|
|
7eb6124721 | ||
|
|
f458780ba7 | ||
|
|
8ad52806de | ||
|
|
dc22a50dcc | ||
|
|
852341c601 | ||
|
|
d5ed6c1901 | ||
|
|
e15548cbf5 | ||
|
|
5e28e6b9ac | ||
|
|
c78d43f640 | ||
|
|
da41383476 | ||
|
|
6ff79835da | ||
|
|
1d608b204a | ||
|
|
c2b8bed3a8 | ||
|
|
3365ef7aaa | ||
|
|
68c17b26dc | ||
|
|
e647efd471 | ||
|
|
15db1ffdd5 | ||
|
|
4632b0f797 | ||
|
|
65c35a5530 | ||
|
|
c449a1c0e0 | ||
|
|
b020010f0d | ||
|
|
0276c72fe2 | ||
|
|
e4aec05d0f | ||
|
|
2919f852ad | ||
|
|
a6e3b9de37 | ||
|
|
04a9791be2 | ||
|
|
6b896a1c54 | ||
|
|
cb8df06685 | ||
|
|
bfe5506cc1 | ||
|
|
b64066fec7 | ||
|
|
ffd31d8330 | ||
|
|
d89254fedf | ||
|
|
a771ddf667 | ||
|
|
ce2e410468 | ||
|
|
c1982c04ff | ||
|
|
9a62026830 | ||
|
|
d12efccd0b | ||
|
|
54afffed19 | ||
|
|
fc8fcdbece | ||
|
|
abd1fedc9d | ||
|
|
9725985037 | ||
|
|
754f3359ec | ||
|
|
4c131b8c28 | ||
|
|
15c674ba29 | ||
|
|
00aff6a906 | ||
|
|
c45c3a72b5 | ||
|
|
662d450651 | ||
|
|
a8897becd2 | ||
|
|
d0126f4454 | ||
|
|
fdb64a5702 | ||
|
|
73a80ff7dc | ||
|
|
a795fd698d | ||
|
|
2fb0dc0a4a | ||
|
|
5b4653cf39 | ||
|
|
aa8e1497a3 | ||
|
|
eb13d846ef | ||
|
|
c674a175ee | ||
|
|
afabf30ec6 | ||
|
|
420158494d | ||
|
|
6b7b0e0eb3 | ||
|
|
ad70db7e0e | ||
|
|
ef1ce66793 | ||
|
|
c364fd80b6 | ||
|
|
3bc5d1bae0 | ||
|
|
e4e34acba1 | ||
|
|
ff3c36a7a2 | ||
|
|
1e7e3259b5 | ||
|
|
5e53f484be | ||
|
|
513bc32d87 | ||
|
|
e7c944ff0b | ||
|
|
9355a8ad0e | ||
|
|
a74e48a138 | ||
|
|
ea5ee7b0f9 | ||
|
|
bc8cf1b2d8 | ||
|
|
bb28d94884 | ||
|
|
a4f58b0a22 | ||
|
|
bcf8139708 | ||
|
|
9b0390c9da | ||
|
|
e88f58c34e | ||
|
|
8f402f5c77 | ||
|
|
60054da582 | ||
|
|
4626b8ced5 | ||
|
|
ab7d193f98 | ||
|
|
cbf84c1840 | ||
|
|
420fb69166 | ||
|
|
c9c28cb59a | ||
|
|
9073f34b30 | ||
|
|
fb5578c0d4 | ||
|
|
4244f716e0 | ||
|
|
07a4f970d4 | ||
|
|
2335097c99 | ||
|
|
bef0a2fef0 | ||
|
|
c48e6c91f5 | ||
|
|
f082b5ba54 | ||
|
|
8841bdd252 | ||
|
|
58261098fb | ||
|
|
9432d3035a | ||
|
|
9907fc2770 | ||
|
|
d42caa8672 | ||
|
|
8117ec8e20 | ||
|
|
ff2783f9fc | ||
|
|
156a51c945 | ||
|
|
c72ffae4a2 | ||
|
|
7f3b0030ea | ||
|
|
9a626948f8 | ||
|
|
5c43df66a8 | ||
|
|
d0e3c546f8 | ||
|
|
a9cb93d801 | ||
|
|
ee8f29d178 | ||
|
|
da363070c7 | ||
|
|
50cf891e01 | ||
|
|
715838cf89 | ||
|
|
cd0c3f9418 | ||
|
|
efaee2b68b | ||
|
|
372c699cc6 | ||
|
|
8cb01cdd29 | ||
|
|
7a243f890e | ||
|
|
10982a0f45 | ||
|
|
d4c378ed5d | ||
|
|
7872f68a45 | ||
|
|
ec8c848106 | ||
|
|
3b50ce8c54 | ||
|
|
afabb5957b | ||
|
|
1eeaa01234 | ||
|
|
e2898217d2 | ||
|
|
f81dadc5d0 | ||
|
|
a0019d86c5 | ||
|
|
3c4a9bba78 | ||
|
|
4348653431 | ||
|
|
09cfa9bb20 | ||
|
|
e7713a9028 | ||
|
|
906a1753be | ||
|
|
a3d519b671 | ||
|
|
8591f9d576 | ||
|
|
c10ec5548f | ||
|
|
684ac98c8e | ||
|
|
db89fa9881 | ||
|
|
9a80421d73 | ||
|
|
2ddacf40c0 | ||
|
|
92f4824884 | ||
|
|
9a2ffabc33 | ||
|
|
2977168da1 | ||
|
|
85e3f37503 | ||
|
|
ba015c1918 | ||
|
|
1556adb678 | ||
|
|
6bfe729112 | ||
|
|
c340668870 | ||
|
|
207422f83a | ||
|
|
004ba28378 | ||
|
|
6f38801ed8 | ||
|
|
1509eb7d82 | ||
|
|
b8d2bfc890 | ||
|
|
8a2ee95e4a | ||
|
|
bc91716082 | ||
|
|
a00034a6a7 | ||
|
|
8dc0dc4d69 | ||
|
|
2f4b7ce3dd | ||
|
|
d4f83cb1d4 | ||
|
|
aaab3306a8 | ||
|
|
2bafa2f2ac | ||
|
|
9ac378ae09 | ||
|
|
bf867bd9fd | ||
|
|
7fd9ff43af | ||
|
|
bebb569c43 | ||
|
|
74e33bb1a0 | ||
|
|
b591df55b0 | ||
|
|
bddf31443c | ||
|
|
b9e0e88fe9 | ||
|
|
5120d9ec33 | ||
|
|
0a423ffd40 | ||
|
|
505c9e8979 | ||
|
|
75deb02961 | ||
|
|
480211033d | ||
|
|
c0886cb5c6 | ||
|
|
294df8690c | ||
|
|
5374f652dd | ||
|
|
fb72ac9904 | ||
|
|
b6639d9e7e | ||
|
|
74cb79252c | ||
|
|
6cd3c93472 | ||
|
|
eb63e75379 | ||
|
|
ca9321624c | ||
|
|
40f18df90f | ||
|
|
0d63cfd6c3 | ||
|
|
3d6b22de6c | ||
|
|
fc233fcdd3 | ||
|
|
20370d4348 | ||
|
|
0f90671241 | ||
|
|
a866c4e388 | ||
|
|
e7241a989c | ||
|
|
6e788668f9 | ||
|
|
b246dba7e7 | ||
|
|
f98de3d5db | ||
|
|
fab7d60373 | ||
|
|
b4e5358145 | ||
|
|
486db1e797 | ||
|
|
78cb43d0dc | ||
|
|
870454330d | ||
|
|
509cfd15f2 | ||
|
|
2061daa902 | ||
|
|
629ca970a1 | ||
|
|
c8ad6f23a8 | ||
|
|
d8912fd0a7 | ||
|
|
925c80edd4 | ||
|
|
2f6afd375b | ||
|
|
d92646324c | ||
|
|
c9fe62a691 | ||
|
|
cb52ad3ba3 | ||
|
|
2ec4acfe52 | ||
|
|
1c64f1d0cf | ||
|
|
48f4f44289 | ||
|
|
80c19cbf7d | ||
|
|
c97cfde9f9 | ||
|
|
7b26b308ad | ||
|
|
4c10634d85 | ||
|
|
3ba7d7640f | ||
|
|
907995a221 | ||
|
|
7bf0985a57 | ||
|
|
3ca21d8c8a | ||
|
|
a3a87c8883 | ||
|
|
de4401823e | ||
|
|
3ee10f5983 | ||
|
|
0fc8ac8d4d | ||
|
|
41bb53a29f | ||
|
|
cdee6d55d3 | ||
|
|
e5a1afaa26 | ||
|
|
f50cbe74cb | ||
|
|
5dbbf91917 | ||
|
|
7424a29960 | ||
|
|
eb22ca2467 | ||
|
|
ddbcbe5458 | ||
|
|
6e54cfd2ac | ||
|
|
fc3d4b3def | ||
|
|
df55b2c516 | ||
|
|
4d9fb57e22 | ||
|
|
3ed08b5c39 | ||
|
|
d715471426 | ||
|
|
486a4929da | ||
|
|
aacddb745b | ||
|
|
924f499303 | ||
|
|
e863a200e8 | ||
|
|
bb7f8ae69d | ||
|
|
33b6fe72da | ||
|
|
733919be4a | ||
|
|
4333e5487b | ||
|
|
22ead933b6 | ||
|
|
d53a3af191 | ||
|
|
08e7b7e0ad | ||
|
|
68cb0782c0 | ||
|
|
0e5a8e0033 | ||
|
|
4945f33254 | ||
|
|
3fa05293fc | ||
|
|
27e5f2798d | ||
|
|
291ca0874a | ||
|
|
96f2aa1803 | ||
|
|
c6857501aa | ||
|
|
3aba1607b2 | ||
|
|
f667298b64 | ||
|
|
0f4c8d4923 | ||
|
|
6d2c5b2312 | ||
|
|
a95ce11ca6 | ||
|
|
808503d526 | ||
|
|
d4b6fb9214 | ||
|
|
9bce5a09f3 | ||
|
|
bd61f38169 | ||
|
|
cac9c63325 | ||
|
|
e6d555ac31 | ||
|
|
fd0dd9f54c | ||
|
|
88c161769d | ||
|
|
01bf1ae92d | ||
|
|
9193c71cff | ||
|
|
db278d81e4 | ||
|
|
bdad454a0d | ||
|
|
ac8064c754 | ||
|
|
736e963cef | ||
|
|
b191cd73a7 | ||
|
|
86d3ca48ae | ||
|
|
fd7e4f2268 | ||
|
|
e9475a9739 | ||
|
|
d4270e02e9 | ||
|
|
b9a263ecb2 | ||
|
|
4929d415a6 | ||
|
|
b9e1f518aa | ||
|
|
0caa44e979 | ||
|
|
ca56ca5bd8 | ||
|
|
a0f0dff88e | ||
|
|
e5cc38a210 | ||
|
|
6cb5bb7200 | ||
|
|
563696e291 | ||
|
|
c755b3c49e | ||
|
|
b9f3493dbc | ||
|
|
8c08e9e473 | ||
|
|
c2930b0ca5 | ||
|
|
4300759287 | ||
|
|
fc1854cadd | ||
|
|
933973b12c | ||
|
|
5b54b9cb11 | ||
|
|
d2f815bba7 | ||
|
|
a5a067d50f | ||
|
|
699e299345 | ||
|
|
05e114173d | ||
|
|
d958b3ff65 | ||
|
|
0d7e06a141 | ||
|
|
633095aee1 | ||
|
|
a4aeb9a1dd | ||
|
|
71005e1db3 | ||
|
|
d7d6d6f991 | ||
|
|
5986121cfc | ||
|
|
c452a4569e | ||
|
|
a182a208dc | ||
|
|
d273b4b48b | ||
|
|
afed7d4af0 | ||
|
|
b429e890ad | ||
|
|
2f976504e8 | ||
|
|
b5fc88227b | ||
|
|
4b7b859db9 | ||
|
|
f7d0de53bb | ||
|
|
603ec997ba | ||
|
|
f7266ef4c8 | ||
|
|
3d43e1568c | ||
|
|
3cf6a65da9 | ||
|
|
c1a3f003e8 | ||
|
|
3f61aea7fc | ||
|
|
bd68db51e0 | ||
|
|
b8a5ed710e | ||
|
|
34be601dd7 | ||
|
|
1d64ad1ccd | ||
|
|
dfb4ac0365 | ||
|
|
f2d7a3d26d | ||
|
|
6d415a7384 | ||
|
|
0ef8832b04 | ||
|
|
e42a037b7d | ||
|
|
fe18d69b65 | ||
|
|
a1a9a7fa9e | ||
|
|
07029f93e3 | ||
|
|
e99ef9c093 | ||
|
|
fef9ab674e | ||
|
|
ee37c37cab | ||
|
|
b636c1e1f8 | ||
|
|
8b9f0487c0 | ||
|
|
a6cbd5a2fd | ||
|
|
ece1667fb0 | ||
|
|
50bd8b4a09 | ||
|
|
93d91353a1 | ||
|
|
8dc9143b34 | ||
|
|
a0d9a1133c | ||
|
|
7740e4268c | ||
|
|
f36e4ba336 | ||
|
|
3df2ef8587 | ||
|
|
354309fcad | ||
|
|
e832bfc61e | ||
|
|
99057ed859 | ||
|
|
c47c5e466f | ||
|
|
edd00e8e70 | ||
|
|
82e7de2aaa | ||
|
|
b723714c0c | ||
|
|
a2903b6e63 | ||
|
|
9a1876571b | ||
|
|
c07d7165ab | ||
|
|
d695c5972f | ||
|
|
bbc09ed313 | ||
|
|
1d21b0da9a | ||
|
|
617a147706 | ||
|
|
d4dccfdb2d | ||
|
|
035e4bf727 | ||
|
|
9ec5bbd560 | ||
|
|
34482c5ed6 | ||
|
|
7d414b5628 | ||
|
|
d9528dfd09 | ||
|
|
12f5f8ba00 | ||
|
|
db0f3307e0 | ||
|
|
9c83825cb8 | ||
|
|
7a22471787 | ||
|
|
7548d9a8fe | ||
|
|
26789f9b36 | ||
|
|
b4524839bb | ||
|
|
6605c269cf | ||
|
|
c30478bf4a | ||
|
|
d986746ef9 | ||
|
|
a8fa061f2e | ||
|
|
72015b0226 | ||
|
|
f8e9726922 | ||
|
|
884363bd05 | ||
|
|
bdd240ecb6 | ||
|
|
04da292df9 | ||
|
|
85b8676b8e | ||
|
|
114bc13c23 | ||
|
|
5fef5f1ed4 | ||
|
|
807b60b0e6 | ||
|
|
fbc800e556 | ||
|
|
1991ee7a7d | ||
|
|
ffbfadbccf | ||
|
|
c3e2bce956 | ||
|
|
0c9520d7e3 | ||
|
|
1e7e5230cc | ||
|
|
f1efc97357 | ||
|
|
fb5ac6d6d7 | ||
|
|
4e7ca51beb | ||
|
|
d561600a31 | ||
|
|
024e843998 | ||
|
|
126f275e18 | ||
|
|
c65e5ff8e0 | ||
|
|
ef13e67572 | ||
|
|
7920fcbb5e | ||
|
|
fa36fdeb03 | ||
|
|
c143b5ccb4 | ||
|
|
05c8406fca | ||
|
|
69e3a45083 | ||
|
|
45259b6ec6 | ||
|
|
d6fe48112c | ||
|
|
dcf6e6b14d | ||
|
|
908697a963 | ||
|
|
bdaf961196 | ||
|
|
6bd5d9b1a4 | ||
|
|
beb0dae5a7 | ||
|
|
fad2d6b1d1 | ||
|
|
9cd830b6aa | ||
|
|
d9a16b0ff4 | ||
|
|
cb5c94ef5e | ||
|
|
85fbd66871 | ||
|
|
3da75d6125 | ||
|
|
d4a3a5c180 | ||
|
|
65e0fcbf10 | ||
|
|
e22aca49c8 | ||
|
|
71e3a473d6 | ||
|
|
c2cfc09f63 | ||
|
|
cbfad28f7e | ||
|
|
6a4a468022 | ||
|
|
01f10b56e8 | ||
|
|
90ec0a610e | ||
|
|
42bff1ce1b | ||
|
|
e3c7a1f31f | ||
|
|
0debbffa70 | ||
|
|
473b58d26d | ||
|
|
7e9498f04c | ||
|
|
300001e766 | ||
|
|
21fc6344bf | ||
|
|
a38edd891f | ||
|
|
794fa21137 | ||
|
|
977d1d1998 | ||
|
|
cde003bc98 | ||
|
|
9e4e1d1cb2 | ||
|
|
60142cd960 | ||
|
|
f9570a82cc | ||
|
|
36285ead57 | ||
|
|
13e488dace | ||
|
|
f169da8fd0 | ||
|
|
60741298b7 | ||
|
|
f73734acb0 | ||
|
|
fc360abe43 | ||
|
|
3996e11425 | ||
|
|
3a4fe3e391 | ||
|
|
98db002770 | ||
|
|
7c89b6934a | ||
|
|
380a19274d | ||
|
|
f1c1caf7bd | ||
|
|
e2997b8135 | ||
|
|
4ed6e4d016 | ||
|
|
ac8d24a1ce | ||
|
|
fc776921d5 | ||
|
|
55a653aca4 | ||
|
|
0d6a6b97f9 | ||
|
|
469ff45f01 | ||
|
|
bc077acfb8 | ||
|
|
4269626f5d | ||
|
|
8fa897aadb | ||
|
|
f549618d12 | ||
|
|
2fa47aaf31 | ||
|
|
b0874fb23a | ||
|
|
fb70fd77e8 | ||
|
|
01f17f9cbb | ||
|
|
4c853defb2 | ||
|
|
bd0db56ba0 | ||
|
|
95f0b3710d | ||
|
|
e0ac109dd1 | ||
|
|
86349527e7 | ||
|
|
18005ceee8 | ||
|
|
7653b3d088 | ||
|
|
911053f63f | ||
|
|
eb52f81a5c | ||
|
|
4839953328 | ||
|
|
aba0d93fda | ||
|
|
0de74c0448 | ||
|
|
ee927346b7 | ||
|
|
2f8015cbca | ||
|
|
f3bf7c4b38 | ||
|
|
e37c4d57da | ||
|
|
acff90c000 | ||
|
|
5f9e72dd71 | ||
|
|
be0bcb8f7d | ||
|
|
44c3d56439 | ||
|
|
519d731ddd | ||
|
|
119c00c22a | ||
|
|
12596dd697 | ||
|
|
cb38f5f0d7 | ||
|
|
b49384ffe4 | ||
|
|
7fb622638b | ||
|
|
bd0cc134bf | ||
|
|
476fd1f695 | ||
|
|
96053d13be | ||
|
|
c958bed418 | ||
|
|
2b2c240d39 | ||
|
|
1f0ae16216 | ||
|
|
b79392ba2c | ||
|
|
8ee98f0a4a | ||
|
|
82e78fb651 | ||
|
|
d0826b2c33 | ||
|
|
ff588200c0 | ||
|
|
5d6072524c | ||
|
|
07a66a70fc | ||
|
|
69ba8a3c2f | ||
|
|
a30c75ef71 | ||
|
|
d0b3727c5d | ||
|
|
6e94bf5b6d | ||
|
|
0f04e270a7 | ||
|
|
ec4f5007e7 | ||
|
|
21b906e0e0 | ||
|
|
7ebaf8e843 | ||
|
|
640398ced4 | ||
|
|
ebbe1fc236 | ||
|
|
aac8e45397 | ||
|
|
5ebfa5ecf7 | ||
|
|
12e041c9ef | ||
|
|
54913f06a3 | ||
|
|
44a36368a2 | ||
|
|
8f9ff930b3 | ||
|
|
e199f6db87 | ||
|
|
c83dd3ccd7 | ||
|
|
78fbafa1cd | ||
|
|
c0012540ed | ||
|
|
9ab6df0e54 | ||
|
|
685b775b68 | ||
|
|
9056a5a7b6 | ||
|
|
e1c56bcbfe | ||
|
|
15d68467a1 | ||
|
|
3b6ecc573e | ||
|
|
9427b1e594 | ||
|
|
3ca3eaa62c | ||
|
|
dda448e050 | ||
|
|
60873144ea | ||
|
|
a9d17c96be | ||
|
|
aaee895b2b | ||
|
|
7d7e17b351 | ||
|
|
c71a976e76 | ||
|
|
3623183072 | ||
|
|
e6bd979aeb | ||
|
|
266c160108 | ||
|
|
b5b6350cc7 | ||
|
|
bbcf4800de | ||
|
|
41056ace02 | ||
|
|
60a80dd678 | ||
|
|
0efda04920 | ||
|
|
8819e58882 | ||
|
|
28eeaf201b | ||
|
|
74bfcea6a8 | ||
|
|
16f1d7fad9 | ||
|
|
9aa38cf0ae | ||
|
|
a7fa7466fb | ||
|
|
3f73c61cee | ||
|
|
a64f4cd871 | ||
|
|
a41eff1276 | ||
|
|
b88fe572fe | ||
|
|
59ba6f8aec | ||
|
|
25343da6b7 | ||
|
|
60d17b97f5 | ||
|
|
8cb72d87e4 | ||
|
|
8872594ab9 | ||
|
|
b50584119b | ||
|
|
975f4f2a17 | ||
|
|
16e4f79f09 | ||
|
|
76cae20c33 | ||
|
|
b66f23cfd0 | ||
|
|
27d6e5d8cf | ||
|
|
ff5d5b97c3 | ||
|
|
ce46c4dec4 | ||
|
|
77e8be09a1 | ||
|
|
013d77488a | ||
|
|
29ad2496b6 | ||
|
|
97a013b2b7 | ||
|
|
77808223dc | ||
|
|
fc89851ce9 | ||
|
|
c4c6555814 | ||
|
|
df0087fb23 | ||
|
|
ef3c13fe2b | ||
|
|
0ad704e532 | ||
|
|
2220d2dab8 | ||
|
|
49f48e2aaa | ||
|
|
dce24df379 | ||
|
|
b59136c262 | ||
|
|
fb9664b636 | ||
|
|
5b736ae05e | ||
|
|
ee114b3075 | ||
|
|
123b16991b | ||
|
|
5792fc0bef | ||
|
|
42c93917ef | ||
|
|
8c0f860601 | ||
|
|
df30a4c0d1 | ||
|
|
9ce13f0035 | ||
|
|
3884b01503 | ||
|
|
a84c3adeab | ||
|
|
a65b784907 | ||
|
|
05dadad2e1 | ||
|
|
3a9b39b842 | ||
|
|
e612003293 | ||
|
|
a43577fa26 | ||
|
|
7e10dcdcf0 | ||
|
|
7ee1110351 | ||
|
|
51c4c51d9e | ||
|
|
fc4fe54099 | ||
|
|
b5b240d0be | ||
|
|
4c42f00a86 | ||
|
|
090fbd04af | ||
|
|
461de48625 | ||
|
|
9352ba6e4a | ||
|
|
5e883239f9 | ||
|
|
5ea08a2120 | ||
|
|
a6fa60868b | ||
|
|
99878ae7d6 | ||
|
|
26202014a2 | ||
|
|
f4f8b96788 | ||
|
|
e5ede16749 | ||
|
|
fbe3547129 | ||
|
|
23f7363c70 | ||
|
|
97c44042e1 | ||
|
|
a03caea549 | ||
|
|
aa23fb1d56 | ||
|
|
4f35aac6dd | ||
|
|
4418ca9e9f | ||
|
|
570611fc09 | ||
|
|
94dd5b1ebe | ||
|
|
74524e024d | ||
|
|
324e00194f | ||
|
|
e42b6dcc8e | ||
|
|
d71b799e75 | ||
|
|
87e7121332 | ||
|
|
94f6354c94 | ||
|
|
b79059ebdb | ||
|
|
07b7e8a1a6 | ||
|
|
7ae2fc37c0 | ||
|
|
4f98c1bebb | ||
|
|
2feec01e10 | ||
|
|
72b95e192e | ||
|
|
47aad254d8 | ||
|
|
bc14074d2a | ||
|
|
5ab5b1a190 | ||
|
|
b055f190f5 | ||
|
|
84b8953352 | ||
|
|
93a591d487 | ||
|
|
e6c0f38a7c | ||
|
|
d169305e5d | ||
|
|
f107ae4f9b | ||
|
|
bad7a08804 | ||
|
|
25cbf4cb35 | ||
|
|
7f179f9a58 | ||
|
|
5287ea8537 | ||
|
|
43e2aaebf0 | ||
|
|
e60eb66283 | ||
|
|
ca59b808d8 | ||
|
|
8a15fd44d5 | ||
|
|
dac2b8942e | ||
|
|
54a1c5b63a | ||
|
|
61b02bf6d3 | ||
|
|
9d048b2fdf | ||
|
|
d9e28a7422 | ||
|
|
1fecdf42ca | ||
|
|
d4bf85b67c | ||
|
|
7131ff27c3 | ||
|
|
a30f78c1c8 | ||
|
|
7e0afffca8 | ||
|
|
293c60fb9c | ||
|
|
f5be8b2a5e | ||
|
|
6772603c15 | ||
|
|
a22904f99b | ||
|
|
6710d2852f | ||
|
|
b157bc5cd7 | ||
|
|
10e1a03c76 | ||
|
|
d20df92e9f | ||
|
|
44170207ac | ||
|
|
9354799a26 | ||
|
|
33745be745 | ||
|
|
6a28070017 | ||
|
|
91b948332e | ||
|
|
d1a7fe2d44 | ||
|
|
8224ef20a4 | ||
|
|
a4c3464bc8 | ||
|
|
5966d76e9a | ||
|
|
c39324d11f | ||
|
|
8c151c62ce | ||
|
|
50d16d8215 | ||
|
|
3bbac9a5f2 | ||
|
|
3600fd277e | ||
|
|
e8bb4a7e36 | ||
|
|
36987cb1cc | ||
|
|
5382b4fa37 | ||
|
|
28ef8068c8 | ||
|
|
ca0cbd68d6 | ||
|
|
c281b47905 | ||
|
|
aca5064743 | ||
|
|
6f780316c4 | ||
|
|
4e262d81f0 | ||
|
|
6c2ff950ee | ||
|
|
7684069d0b | ||
|
|
73c85ae68a | ||
|
|
911e39ba09 | ||
|
|
9a421d510a | ||
|
|
3bc7172e5e | ||
|
|
1a83988e26 | ||
|
|
0d0fc2504a | ||
|
|
0d4402ee0c | ||
|
|
722def9362 | ||
|
|
6a8bef83b3 | ||
|
|
a9c3e2c7ba | ||
|
|
7fcb40739d | ||
|
|
5a3d319677 | ||
|
|
8466d0b681 | ||
|
|
5de179f1eb | ||
|
|
36e10595cc | ||
|
|
78c8723629 | ||
|
|
edd7f28104 | ||
|
|
dba1ab3fc0 | ||
|
|
3df9c48012 | ||
|
|
6f6450bcff | ||
|
|
1f34203167 | ||
|
|
fed20648c6 | ||
|
|
3fc3c5cae4 | ||
|
|
daa5366b57 | ||
|
|
ac1c299369 | ||
|
|
5bbb3ac49a | ||
|
|
014bdf911a | ||
|
|
874853fe18 | ||
|
|
274b71f8bc | ||
|
|
c41d543d81 | ||
|
|
7729ddab30 | ||
|
|
60c0e59a83 | ||
|
|
ac49e639bd | ||
|
|
f01b20c2af | ||
|
|
a0d47be088 | ||
|
|
521374e238 | ||
|
|
34806ee2c2 | ||
|
|
4a0d5138a1 | ||
|
|
e6a3758899 | ||
|
|
fcb7d9111e | ||
|
|
d907731027 | ||
|
|
ac8d295bb9 | ||
|
|
a963beb96e | ||
|
|
737b510116 | ||
|
|
47cba83450 | ||
|
|
21d4199a38 | ||
|
|
655c422c3c | ||
|
|
b6f8bd408f | ||
|
|
a3edd0b976 | ||
|
|
8e8efa5caf | ||
|
|
a41b8f62a2 | ||
|
|
452ee8c2df | ||
|
|
5ca6599ca9 | ||
|
|
dcedf6bfd0 | ||
|
|
1f4b43645b | ||
|
|
3d5140458b | ||
|
|
f16574085f | ||
|
|
3ed62d45f5 | ||
|
|
b1a7b0a186 | ||
|
|
ec0c68621c | ||
|
|
a0977af081 | ||
|
|
a3ef9efd2f | ||
|
|
d58f7c6ec9 | ||
|
|
d124c2c12e | ||
|
|
0229f70761 | ||
|
|
dde9281139 | ||
|
|
6eedfb572e | ||
|
|
edf81a232d | ||
|
|
c2cb92a0b0 | ||
|
|
640af300cb | ||
|
|
6c0c6182e9 | ||
|
|
05ad4445b5 | ||
|
|
1dd9f0747e | ||
|
|
150e01be8b | ||
|
|
95ee3216c4 | ||
|
|
3b5e409b38 | ||
|
|
eb201b614a | ||
|
|
162a6b8b5c | ||
|
|
4ec01769cb | ||
|
|
19b656132d | ||
|
|
6305c7e2ab | ||
|
|
04c60e8a1c | ||
|
|
b6ceb06a32 | ||
|
|
8cb2f85a08 | ||
|
|
7ccfb6ea88 | ||
|
|
531398b532 | ||
|
|
ec6ecf0d60 | ||
|
|
fdb0e31a78 | ||
|
|
01a9534729 | ||
|
|
921278c5ea | ||
|
|
d938f73207 | ||
|
|
344e63c2dc | ||
|
|
681144b2a3 | ||
|
|
e4295f5d3c | ||
|
|
77135ca3c7 | ||
|
|
29b548f07c | ||
|
|
cb33ef77f7 | ||
|
|
49ded54306 | ||
|
|
6c0a8a4337 | ||
|
|
e9a0ddf798 | ||
|
|
d217626318 | ||
|
|
4f5fcc2a37 | ||
|
|
ed94f4b1df | ||
|
|
a57b097afc | ||
|
|
eb42b894c4 | ||
|
|
af666e2209 | ||
|
|
2f2e746e56 | ||
|
|
b3e7619048 | ||
|
|
0121136498 | ||
|
|
7eb43a0b47 | ||
|
|
c0430a2248 | ||
|
|
6796b8bdad | ||
|
|
475d016029 | ||
|
|
201304e678 | ||
|
|
fdb104348c | ||
|
|
f54828352d | ||
|
|
cc157def63 | ||
|
|
8fc83655ab | ||
|
|
9fb549293a | ||
|
|
e4cc5b5b70 | ||
|
|
6f0b659b38 | ||
|
|
652bdf1518 | ||
|
|
f6ac0d73b4 | ||
|
|
ae47be0ce9 | ||
|
|
491c37eafe | ||
|
|
3ade7a8b0e | ||
|
|
3c7738b6d0 | ||
|
|
037318e2ff | ||
|
|
a9a499939e | ||
|
|
7e5bcd2ec3 | ||
|
|
f49ca48a22 | ||
|
|
9cb4e8bde8 | ||
|
|
95edb49bb8 | ||
|
|
fb69bf551e | ||
|
|
fe8d0f8ea8 | ||
|
|
acc5fa2a95 | ||
|
|
f2e33f8581 | ||
|
|
4748cdc2c9 | ||
|
|
2bc364023a | ||
|
|
3070f61e20 | ||
|
|
57df56dc62 | ||
|
|
e11ef5a7f0 | ||
|
|
6a17a3eeec | ||
|
|
66ff9a24c6 | ||
|
|
a3b3a7a34d | ||
|
|
c04b3559d0 | ||
|
|
e642b41b5b | ||
|
|
ba6881d685 | ||
|
|
20d8c9053b | ||
|
|
0749e4ed70 | ||
|
|
b0cc69ff80 | ||
|
|
02c4669e95 | ||
|
|
8550b76e23 | ||
|
|
fdf27e3d24 | ||
|
|
069023fca2 | ||
|
|
1fd6648db1 | ||
|
|
7a08c8b694 | ||
|
|
60aad3f19b | ||
|
|
51dcc2bc0f | ||
|
|
941525d1e0 | ||
|
|
5fb6c5b012 | ||
|
|
3affa73257 | ||
|
|
c647e27e15 | ||
|
|
f696ed48b3 | ||
|
|
73645f299a | ||
|
|
6aeb5f1172 | ||
|
|
ce8f07750f | ||
|
|
a32ad0dbf2 | ||
|
|
61ff12e8d4 | ||
|
|
02b0e96db8 | ||
|
|
e942440bb7 | ||
|
|
a27f1f17de | ||
|
|
e106ff0fef | ||
|
|
6f068e0b9c | ||
|
|
ada531c88a | ||
|
|
f0a2248c81 | ||
|
|
11f2524b9b | ||
|
|
b011e5f838 | ||
|
|
f45eb84d6b | ||
|
|
412c0a172d | ||
|
|
c1d8496b93 | ||
|
|
4657959790 | ||
|
|
2b0ba281a4 | ||
|
|
325a41c598 | ||
|
|
9b8efe1b27 | ||
|
|
024b741552 | ||
|
|
4e95f4678f | ||
|
|
a86b982591 | ||
|
|
ec8da00485 | ||
|
|
bcfe130d51 | ||
|
|
0e143f7275 | ||
|
|
7670b4e380 | ||
|
|
636a9123b8 | ||
|
|
caaee40889 | ||
|
|
1f130b6550 | ||
|
|
2ce47f49b1 | ||
|
|
0250e03b86 | ||
|
|
ce110aab90 | ||
|
|
fd92752f52 | ||
|
|
3c4a305976 | ||
|
|
791e5bbd55 | ||
|
|
46df6e7dd3 | ||
|
|
9ccf9d57a8 | ||
|
|
fa89bd830a | ||
|
|
3ba05d0274 | ||
|
|
0d9a8d70bf | ||
|
|
5c79184d3b | ||
|
|
3d619d9ccc | ||
|
|
afdf3ae7a1 | ||
|
|
943f7c06b5 | ||
|
|
27a9642090 | ||
|
|
d0b6ff2d08 | ||
|
|
97737ee9e3 | ||
|
|
5e27ccc37c | ||
|
|
682113892a | ||
|
|
376eb81181 | ||
|
|
4fc40d96d9 | ||
|
|
e6634531c7 | ||
|
|
66724826f5 | ||
|
|
04e375a523 | ||
|
|
65638973ea | ||
|
|
9c26bdd676 | ||
|
|
b31931c907 | ||
|
|
c74af2c21f | ||
|
|
c160b2e54b | ||
|
|
c4234f4542 | ||
|
|
62fa9c0f6e | ||
|
|
8198f06073 | ||
|
|
6f2117d786 | ||
|
|
b3ec3b487c | ||
|
|
d67957d015 | ||
|
|
94f131a0b7 | ||
|
|
7af0029175 | ||
|
|
f4228b04f8 | ||
|
|
ffaf243160 | ||
|
|
29d48bbd9a | ||
|
|
37dda79db2 | ||
|
|
063e3e85e1 | ||
|
|
42afaa9f66 | ||
|
|
366fcf76f6 | ||
|
|
72e8ec7d93 | ||
|
|
13a479a9f6 | ||
|
|
1194e48bd8 | ||
|
|
1e0666d1ef | ||
|
|
1c53ad6876 | ||
|
|
dc2a537f6b | ||
|
|
a5d3022e9f | ||
|
|
4541da1f17 | ||
|
|
a16cd9aef7 | ||
|
|
6cf446032f | ||
|
|
3fda2d9ac3 | ||
|
|
c03268707a | ||
|
|
7829e907c9 | ||
|
|
b5529e5138 | ||
|
|
d601afcebc | ||
|
|
892a90bf51 | ||
|
|
d52a8f08ed | ||
|
|
b7e27bf6b4 | ||
|
|
9ee96d6176 | ||
|
|
c0e1772e21 | ||
|
|
62dc160c65 | ||
|
|
f03303e5aa | ||
|
|
7bc2844b9d | ||
|
|
ba283755be | ||
|
|
2209beff8a | ||
|
|
00cc480bc1 | ||
|
|
d7de5b2afa | ||
|
|
221b72439b | ||
|
|
08e6f60941 | ||
|
|
10066209e7 | ||
|
|
08e95ed606 | ||
|
|
a5ad48aa18 | ||
|
|
81fdfcba22 | ||
|
|
24de6d6fc9 | ||
|
|
aec6fcd00b | ||
|
|
619082dbed | ||
|
|
09cdf5081c | ||
|
|
d7abbbfac4 | ||
|
|
c714196647 | ||
|
|
b702c1d9a8 | ||
|
|
56ac04c48e | ||
|
|
b58519b974 | ||
|
|
ad574f5e90 | ||
|
|
4941a657bf | ||
|
|
3d4bff9414 | ||
|
|
2d03616c10 | ||
|
|
fcb9ba08a8 | ||
|
|
77f4126f9b | ||
|
|
4c890ab202 | ||
|
|
d10e9b1b6e | ||
|
|
a6bee76581 | ||
|
|
2f4f5a6ad2 | ||
|
|
3853997295 | ||
|
|
76899c9ac5 | ||
|
|
99a5b3a98a | ||
|
|
219aff9a93 | ||
|
|
b6e1b3bff0 | ||
|
|
1ce888e828 | ||
|
|
1c10a801dc | ||
|
|
48fa83c9ac | ||
|
|
31ea3a2757 | ||
|
|
05e0003555 | ||
|
|
be79281418 | ||
|
|
01f53f6d6c | ||
|
|
107e0404de | ||
|
|
ab99e80333 | ||
|
|
3154a378a6 | ||
|
|
8e04f1c03e | ||
|
|
c0aadeab3d | ||
|
|
6c87698f1a | ||
|
|
db2e9f8bf3 | ||
|
|
9a4c5cef86 | ||
|
|
bdfc86f850 | ||
|
|
70dadfba28 | ||
|
|
01e1e34874 | ||
|
|
28a3cbfa87 | ||
|
|
0b480c2d3f | ||
|
|
391dea445a | ||
|
|
e074c72130 | ||
|
|
96f3f863e5 | ||
|
|
3877f6fd94 | ||
|
|
cbbc6df05a | ||
|
|
32ff7fb321 | ||
|
|
5537e57eec | ||
|
|
9c94af04cc | ||
|
|
3f0b15902d | ||
|
|
4d3835dde2 | ||
|
|
8514f42d0d | ||
|
|
6d9fbe8d41 | ||
|
|
849185d3c9 | ||
|
|
47cc757ed0 | ||
|
|
f6edd435af | ||
|
|
0c0dd914f7 | ||
|
|
c6405bc93b | ||
|
|
cdffdfbded | ||
|
|
0bbfb323b1 | ||
|
|
4f08359786 | ||
|
|
7efb17537a | ||
|
|
7e06769d44 | ||
|
|
5347ee4896 | ||
|
|
834bf30a10 | ||
|
|
22ea384ac8 | ||
|
|
3e6dd9ea9e | ||
|
|
10f363e9e7 | ||
|
|
69e8c014c3 | ||
|
|
dbb40e1dda | ||
|
|
d710b97276 | ||
|
|
0e6e8040ba | ||
|
|
c6fb0bad4b | ||
|
|
2d08217173 | ||
|
|
36645d9335 | ||
|
|
97d3aedba1 | ||
|
|
5976b20aec | ||
|
|
ad8573c739 | ||
|
|
7f9410fd34 | ||
|
|
71133f6b59 | ||
|
|
5d5d6c2c70 | ||
|
|
37fa462db5 | ||
|
|
1a2046a7eb | ||
|
|
3dff7e80fc | ||
|
|
6eea9239a7 | ||
|
|
75f1969bd2 | ||
|
|
e97755eb91 | ||
|
|
b938949cdb | ||
|
|
447af208b3 | ||
|
|
d47fbbbe96 | ||
|
|
767b72fbfa | ||
|
|
b94a8da9d6 | ||
|
|
12b5be239b | ||
|
|
0fbf72bb09 | ||
|
|
ae2117ff5a | ||
|
|
b80821c4b7 | ||
|
|
cf01b5a002 | ||
|
|
bb66d559e7 | ||
|
|
7b8fa3b922 | ||
|
|
777676b525 | ||
|
|
28f2a1309e | ||
|
|
4b0a7c2252 | ||
|
|
2625d9f7fe | ||
|
|
45f24c8a85 | ||
|
|
5f7c11f495 | ||
|
|
ec4d2d65a6 | ||
|
|
3e20f5dd3c | ||
|
|
7014b5a150 | ||
|
|
f8427ab789 | ||
|
|
31fc2bfeb7 | ||
|
|
fb5bc16c83 | ||
|
|
724075e448 | ||
|
|
45cb9a2e80 | ||
|
|
456eee05f2 | ||
|
|
23872f77a8 | ||
|
|
37c1999965 | ||
|
|
86dd4dd784 | ||
|
|
00b65abd09 | ||
|
|
fee55fa642 | ||
|
|
76ea1962be | ||
|
|
df3cf72d29 | ||
|
|
32dd594f06 | ||
|
|
ba0ba1de94 | ||
|
|
660e71f032 | ||
|
|
169e6fdba4 | ||
|
|
138aeaf8c7 | ||
|
|
33669793b7 | ||
|
|
80f4bf9475 | ||
|
|
bed869b08e | ||
|
|
f2150ee7e1 | ||
|
|
eaf89995ee | ||
|
|
2311b42bca | ||
|
|
a4fbccac9b | ||
|
|
a0cf93a7ca | ||
|
|
f444c7d4a5 | ||
|
|
8ef4c12f97 | ||
|
|
c520c55ff4 | ||
|
|
6145748bfb | ||
|
|
1a1026b367 | ||
|
|
8c45bd32b7 | ||
|
|
2b5cee05e6 | ||
|
|
5442954db6 | ||
|
|
5ee382c8eb | ||
|
|
901cb44f5e | ||
|
|
7388461ede | ||
|
|
5223627b71 | ||
|
|
646c4a3ccc | ||
|
|
0b9e78df2c | ||
|
|
a9c24b456d | ||
|
|
b4463bf42c | ||
|
|
8f8dc66c70 | ||
|
|
b746250e71 | ||
|
|
26b7e7ec8e | ||
|
|
bc09760c84 | ||
|
|
ceb229c6ac | ||
|
|
1e6ac33ef1 | ||
|
|
86eafe7a33 | ||
|
|
00f46dc149 | ||
|
|
396c7ab9ee | ||
|
|
fa2cef6395 | ||
|
|
04638c9065 | ||
|
|
02bb5b6742 | ||
|
|
fad5fafa32 | ||
|
|
b0dd231018 | ||
|
|
0b5f005a5d | ||
|
|
babca8d47b | ||
|
|
eb462955fe | ||
|
|
b79db36336 | ||
|
|
404ea0ce6d | ||
|
|
d3971b26e4 | ||
|
|
a44a201f00 | ||
|
|
1d80fdddd4 | ||
|
|
f09745b4ad | ||
|
|
d13ae0610e | ||
|
|
3eaa447323 | ||
|
|
604506da10 | ||
|
|
122ce11381 | ||
|
|
8cbd9f7f08 | ||
|
|
7c41e5bafc | ||
|
|
4452f784a8 | ||
|
|
ced0ae0d65 | ||
|
|
876c51302a | ||
|
|
a6877e7c13 | ||
|
|
f633d1fa5b | ||
|
|
4f90b41343 | ||
|
|
e4ddf8bc33 | ||
|
|
613ab9febc | ||
|
|
e92cceecc1 | ||
|
|
3283f3ed7d | ||
|
|
0ed30b802d | ||
|
|
beefff8cce | ||
|
|
b1554d6a89 | ||
|
|
4230b03884 | ||
|
|
2182b8339e | ||
|
|
b07b77c58f | ||
|
|
6542407fa3 | ||
|
|
ebf995536b | ||
|
|
adcd7f10ee | ||
|
|
af83936047 | ||
|
|
c3b5b97a41 | ||
|
|
6c58ea18dc | ||
|
|
830b287e5d | ||
|
|
52549d51ab | ||
|
|
fe05ed13e5 | ||
|
|
3a46e7fc0a | ||
|
|
88674e21cf | ||
|
|
a0673c7028 | ||
|
|
592af80659 | ||
|
|
3ec9b3b021 | ||
|
|
ca2d3a192c | ||
|
|
209bf7d746 | ||
|
|
13777cc1aa | ||
|
|
bffc77e478 | ||
|
|
0ebb7eecdb | ||
|
|
99863bb799 | ||
|
|
800d2f0859 | ||
|
|
f397844603 | ||
|
|
2d895f328c | ||
|
|
b14b182084 | ||
|
|
8687d25d88 | ||
|
|
7001edcd1d | ||
|
|
4a1e88f4bf | ||
|
|
b41608d40b | ||
|
|
c5d45edf2d | ||
|
|
0116b6341c | ||
|
|
3e7ecda80f | ||
|
|
f0e5b2b6f9 | ||
|
|
5976ec9323 | ||
|
|
eb3463fad1 | ||
|
|
5f9e5869e9 | ||
|
|
950480bb77 | ||
|
|
6530ec58c7 | ||
|
|
b1515c5e3f | ||
|
|
6581f119fd | ||
|
|
9ad7c12710 | ||
|
|
8e289215b4 | ||
|
|
3718c3be56 | ||
|
|
c3c051385c | ||
|
|
21c688a8a8 | ||
|
|
668b883651 | ||
|
|
c396aeed52 | ||
|
|
40f541bc31 | ||
|
|
44974f98a0 | ||
|
|
b7cb3df9bc | ||
|
|
432e6d5395 | ||
|
|
fdf805bc7b | ||
|
|
73e13f3875 | ||
|
|
da959e1296 | ||
|
|
94600c54cb | ||
|
|
c4fc2e089d | ||
|
|
06444c1c27 | ||
|
|
f8897942f3 | ||
|
|
4d0b4cfb36 | ||
|
|
7116634739 | ||
|
|
36492f4857 | ||
|
|
3a887af513 | ||
|
|
3142992c57 | ||
|
|
68a9b88b58 | ||
|
|
3c801e5b91 | ||
|
|
ecd46f8560 | ||
|
|
dee8ce587d | ||
|
|
4c24186911 | ||
|
|
af360a1a20 | ||
|
|
b5406240c6 | ||
|
|
73bfbba5f7 | ||
|
|
46d7bfecdb | ||
|
|
a734927591 | ||
|
|
255706e173 | ||
|
|
b2fbf46e60 | ||
|
|
e37495d80b | ||
|
|
beb6b950f7 | ||
|
|
2d1c0be24e | ||
|
|
9941651b3c | ||
|
|
31fda124f3 | ||
|
|
b7f6498a5c | ||
|
|
282da1c2b6 | ||
|
|
8e6ec6ef0c | ||
|
|
704b3ee673 | ||
|
|
c18a1c3eca | ||
|
|
4e1870197e | ||
|
|
3bf61cce95 | ||
|
|
68889b0544 | ||
|
|
8a90a47fc2 | ||
|
|
c93c4cc5e6 | ||
|
|
06cba7defd | ||
|
|
8b76bbe51d | ||
|
|
aa1d3a4c2e | ||
|
|
66817411f9 | ||
|
|
23c3196935 | ||
|
|
38e73a188a | ||
|
|
3fdf588cc9 | ||
|
|
9412fe8a0a | ||
|
|
c6450e60e1 | ||
|
|
8126e9f4b1 | ||
|
|
70e4104c17 | ||
|
|
29e0e1760b | ||
|
|
442b7b4c4d | ||
|
|
548153fd5e | ||
|
|
5060ed8970 | ||
|
|
d18e064d21 | ||
|
|
0cfb3c7ab4 | ||
|
|
2e0c2f2e77 | ||
|
|
48f9a61ff0 | ||
|
|
0042e3ae02 | ||
|
|
a1204cf246 | ||
|
|
fc499d9e7c | ||
|
|
b83704dac2 | ||
|
|
b93e46de14 | ||
|
|
3c49aa9d9d | ||
|
|
a448b48eaf | ||
|
|
3c6551f202 | ||
|
|
9e0c7ed29a | ||
|
|
677293f3a9 | ||
|
|
34bd7ce3a7 | ||
|
|
21a07e7419 | ||
|
|
6b50ea6504 | ||
|
|
895647b908 | ||
|
|
0ece58b9cb | ||
|
|
49a56cf131 | ||
|
|
5fa0d798e2 | ||
|
|
cadc506aa5 | ||
|
|
eee0ccef8c | ||
|
|
088bd632ab | ||
|
|
52b5d7143b | ||
|
|
60bf14d4dd | ||
|
|
c00fb44cee | ||
|
|
5111880edf | ||
|
|
3d78b44a8e | ||
|
|
f2d71d41a8 | ||
|
|
b75b290351 | ||
|
|
701ae06e4a | ||
|
|
edd0b809b7 | ||
|
|
98a0d17431 | ||
|
|
b1bd56cd51 | ||
|
|
ae336da7a1 | ||
|
|
4a61b80dd6 | ||
|
|
ef99fe2d18 | ||
|
|
352ebc3193 | ||
|
|
556799428c | ||
|
|
d74c8261aa | ||
|
|
ac373545d0 | ||
|
|
a21948d2c6 | ||
|
|
940480effe | ||
|
|
29c593b8b0 | ||
|
|
0c444e6f2b | ||
|
|
6cf6e16d22 | ||
|
|
abef758ff6 | ||
|
|
e5f9663a0e | ||
|
|
ff5ed561cc | ||
|
|
71fd32b1f4 | ||
|
|
fcf3b4e4e2 |
4
.codespellignore
Normal file
4
.codespellignore
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
doubleclick
|
||||||
|
wan
|
||||||
|
nwe
|
||||||
|
padd
|
||||||
20
.editorconfig
Normal file
20
.editorconfig
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
# EditorConfig is awesome: https://editorconfig.org/
|
||||||
|
|
||||||
|
# top-most EditorConfig file
|
||||||
|
root = true
|
||||||
|
|
||||||
|
# Unix-style newlines with a newline ending every file
|
||||||
|
[*]
|
||||||
|
end_of_line = lf
|
||||||
|
insert_final_newline = true
|
||||||
|
indent_style = space
|
||||||
|
indent_size = tab
|
||||||
|
tab_width = 4
|
||||||
|
charset = utf-8
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
|
[*.yml]
|
||||||
|
tab_width = 2
|
||||||
|
|
||||||
|
[*.md]
|
||||||
|
tab_width = 2
|
||||||
38
.gitattributes
vendored
Normal file
38
.gitattributes
vendored
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
# FROM https://github.com/libgit2/libgit2sharp
|
||||||
|
# Text files that should be normalized to LF in odb.
|
||||||
|
*.cs text diff=csharp
|
||||||
|
*.config text
|
||||||
|
|
||||||
|
*.sln text
|
||||||
|
*.csproj text
|
||||||
|
|
||||||
|
*.md text
|
||||||
|
*.sh text
|
||||||
|
*.ps1 text
|
||||||
|
*.cmd text
|
||||||
|
*.bat text
|
||||||
|
*.markdown text
|
||||||
|
*.msbuild text
|
||||||
|
|
||||||
|
Lib/* binary
|
||||||
|
GitHub.Tests.Integration/Resources/* binary
|
||||||
|
|
||||||
|
|
||||||
|
# Binary files that should not be normalized or diffed
|
||||||
|
*.png binary
|
||||||
|
*.jpg binary
|
||||||
|
*.gif binary
|
||||||
|
|
||||||
|
*.pfx binary
|
||||||
|
*.snk binary
|
||||||
|
*.dll binary
|
||||||
|
*.exe binary
|
||||||
|
*.lib binary
|
||||||
|
*.exp binary
|
||||||
|
*.pdb binary
|
||||||
|
*.sdf binary
|
||||||
|
*.7z binary
|
||||||
|
|
||||||
|
|
||||||
|
# Catch all for anything we forgot. Add rules if you get CRLF -> LF warnings.
|
||||||
|
* text eol=lf
|
||||||
2
.github/dco.yml
vendored
Normal file
2
.github/dco.yml
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
require:
|
||||||
|
members: false
|
||||||
22
.github/dependabot.yml
vendored
Normal file
22
.github/dependabot.yml
vendored
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
version: 2
|
||||||
|
updates:
|
||||||
|
- package-ecosystem: github-actions
|
||||||
|
directory: "/"
|
||||||
|
schedule:
|
||||||
|
interval: weekly
|
||||||
|
day: saturday
|
||||||
|
time: "10:00"
|
||||||
|
open-pull-requests-limit: 10
|
||||||
|
target-branch: development
|
||||||
|
reviewers:
|
||||||
|
- "pi-hole/core-maintainers"
|
||||||
|
- package-ecosystem: pip
|
||||||
|
directory: "/test"
|
||||||
|
schedule:
|
||||||
|
interval: weekly
|
||||||
|
day: saturday
|
||||||
|
time: "10:00"
|
||||||
|
open-pull-requests-limit: 10
|
||||||
|
target-branch: development
|
||||||
|
reviewers:
|
||||||
|
- "pi-hole/core-maintainers"
|
||||||
7
.github/release.yml
vendored
Normal file
7
.github/release.yml
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
changelog:
|
||||||
|
exclude:
|
||||||
|
labels:
|
||||||
|
- internal
|
||||||
|
authors:
|
||||||
|
- dependabot
|
||||||
|
- github-actions
|
||||||
40
.github/workflows/codeql-analysis.yml
vendored
Normal file
40
.github/workflows/codeql-analysis.yml
vendored
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
name: "CodeQL"
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
- development
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
- development
|
||||||
|
schedule:
|
||||||
|
- cron: '32 11 * * 6'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
analyze:
|
||||||
|
name: Analyze
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
actions: read
|
||||||
|
contents: read
|
||||||
|
security-events: write
|
||||||
|
|
||||||
|
steps:
|
||||||
|
-
|
||||||
|
name: Checkout repository
|
||||||
|
uses: actions/checkout@v4.2.2
|
||||||
|
# Initializes the CodeQL tools for scanning.
|
||||||
|
-
|
||||||
|
name: Initialize CodeQL
|
||||||
|
uses: github/codeql-action/init@v3
|
||||||
|
with:
|
||||||
|
languages: 'python'
|
||||||
|
-
|
||||||
|
name: Autobuild
|
||||||
|
uses: github/codeql-action/autobuild@v3
|
||||||
|
-
|
||||||
|
name: Perform CodeQL Analysis
|
||||||
|
uses: github/codeql-action/analyze@v3
|
||||||
21
.github/workflows/merge-conflict.yml
vendored
Normal file
21
.github/workflows/merge-conflict.yml
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
name: "Check for merge conflicts"
|
||||||
|
on:
|
||||||
|
# So that PRs touching the same files as the push are updated
|
||||||
|
push:
|
||||||
|
# So that the `dirtyLabel` is removed if conflicts are resolve
|
||||||
|
# We recommend `pull_request_target` so that github secrets are available.
|
||||||
|
# In `pull_request` we wouldn't be able to change labels of fork PRs
|
||||||
|
pull_request_target:
|
||||||
|
types: [synchronize]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
main:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Check if PRs are have merge conflicts
|
||||||
|
uses: eps1lon/actions-label-merge-conflict@v3.0.2
|
||||||
|
with:
|
||||||
|
dirtyLabel: "PR: Merge Conflict"
|
||||||
|
repoToken: "${{ secrets.GITHUB_TOKEN }}"
|
||||||
|
commentOnDirty: "This pull request has conflicts, please resolve those before we can evaluate the pull request."
|
||||||
|
commentOnClean: "Conflicts have been resolved."
|
||||||
47
.github/workflows/stale.yml
vendored
Normal file
47
.github/workflows/stale.yml
vendored
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
name: Mark stale issues
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 8 * * *'
|
||||||
|
workflow_dispatch:
|
||||||
|
issue_comment:
|
||||||
|
|
||||||
|
env:
|
||||||
|
stale_label: stale
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
stale_action:
|
||||||
|
if: github.event_name != 'issue_comment'
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
issues: write
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/stale@v9.0.0
|
||||||
|
with:
|
||||||
|
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
days-before-stale: 30
|
||||||
|
days-before-close: 5
|
||||||
|
stale-issue-message: 'This issue is stale because it has been open 30 days with no activity. Please comment or update this issue or it will be closed in 5 days.'
|
||||||
|
stale-issue-label: '${{ env.stale_label }}'
|
||||||
|
exempt-issue-labels: 'Internal, Fixed in next release, Bug: Confirmed, Documentation Needed'
|
||||||
|
exempt-all-issue-assignees: true
|
||||||
|
operations-per-run: 300
|
||||||
|
close-issue-reason: 'not_planned'
|
||||||
|
|
||||||
|
remove_stale:
|
||||||
|
# trigger "stale" removal immediately when stale issues are commented on
|
||||||
|
# we need to explicitly check that the trigger does not run on comment on a PR as
|
||||||
|
# https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#issue_comment-on-issues-only-or-pull-requests-only
|
||||||
|
if: ${{ !github.event.issue.pull_request && github.event_name != 'schedule' }}
|
||||||
|
permissions:
|
||||||
|
contents: read # for actions/checkout
|
||||||
|
issues: write # to edit issues label
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4.2.2
|
||||||
|
- name: Remove 'stale' label
|
||||||
|
run: gh issue edit ${{ github.event.issue.number }} --remove-label ${{ env.stale_label }}
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
35
.github/workflows/stale_pr.yml
vendored
Normal file
35
.github/workflows/stale_pr.yml
vendored
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
name: Close stale PR
|
||||||
|
# This action will add a `stale` label and close immediately every PR that meets the following conditions:
|
||||||
|
# - it is already marked with "merge conflict" label
|
||||||
|
# - there was no update/comment on the PR in the last 30 days.
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 10 * * *'
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
stale:
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
issues: write
|
||||||
|
pull-requests: write
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/stale@v9.0.0
|
||||||
|
with:
|
||||||
|
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
# Do not automatically mark PR/issue as stale
|
||||||
|
days-before-stale: -1
|
||||||
|
# Override 'days-before-stale' for PR only
|
||||||
|
days-before-pr-stale: 30
|
||||||
|
# Close PRs immediately, after marking them 'stale'
|
||||||
|
days-before-pr-close: 0
|
||||||
|
# only run the action on merge conflict PR
|
||||||
|
any-of-labels: 'PR: Merge Conflict'
|
||||||
|
exempt-pr-labels: 'internal, never-stale, ON HOLD, WIP'
|
||||||
|
exempt-all-pr-assignees: true
|
||||||
|
operations-per-run: 300
|
||||||
|
stale-pr-message: ''
|
||||||
|
close-pr-message: 'Existing merge conflicts have not been addressed. This PR is considered abandoned.'
|
||||||
40
.github/workflows/sync-back-to-dev.yml
vendored
Normal file
40
.github/workflows/sync-back-to-dev.yml
vendored
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
name: Sync Back to Development
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
|
||||||
|
# The section is needed to drop the default write-all permissions for all jobs
|
||||||
|
# that are granted on `push` event. By specifying any permission explicitly
|
||||||
|
# all others are set to none. By using the principle of least privilege the damage a compromised
|
||||||
|
# workflow can do (because of an injection or compromised third party tool or
|
||||||
|
# action) is restricted. Adding labels to issues, commenting
|
||||||
|
# on pull-requests, etc. may need additional permissions:
|
||||||
|
#
|
||||||
|
# Syntax for this section:
|
||||||
|
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#permissions
|
||||||
|
#
|
||||||
|
# Reference for how to assign permissions on a job-by-job basis:
|
||||||
|
# https://docs.github.com/en/actions/using-jobs/assigning-permissions-to-jobs
|
||||||
|
#
|
||||||
|
# Reference for available permissions that we can enable if needed:
|
||||||
|
# https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token
|
||||||
|
permissions: {}
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
sync-branches:
|
||||||
|
# The job needs to be able to pull the code and create a pull request.
|
||||||
|
permissions:
|
||||||
|
contents: read # for actions/checkout
|
||||||
|
pull-requests: write # to create pull request
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
name: Syncing branches
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4.2.2
|
||||||
|
- name: Opening pull request
|
||||||
|
run: gh pr create -B development -H master --title 'Sync master back into development' --body 'Created by Github action' --label 'internal'
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
91
.github/workflows/test.yml
vendored
Normal file
91
.github/workflows/test.yml
vendored
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
name: Test Supported Distributions
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
types: [opened, synchronize, reopened, ready_for_review]
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
env:
|
||||||
|
FORCE_COLOR: 1
|
||||||
|
PYTHONUNBUFFERED: 1
|
||||||
|
PYTHONUTF8: 1
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
smoke-tests:
|
||||||
|
if: github.event.pull_request.draft == false
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4.2.2
|
||||||
|
|
||||||
|
- name: Check scripts in repository are executable
|
||||||
|
run: |
|
||||||
|
IFS=$'\n';
|
||||||
|
for f in $(find . -name '*.sh'); do if [[ ! -x $f ]]; then echo "$f is not executable" && FAIL=1; fi ;done
|
||||||
|
unset IFS;
|
||||||
|
# If FAIL is 1 then we fail.
|
||||||
|
[[ $FAIL == 1 ]] && exit 1 || echo "Scripts are executable!"
|
||||||
|
|
||||||
|
- name: Run shellcheck
|
||||||
|
uses: ludeeus/action-shellcheck@master
|
||||||
|
with:
|
||||||
|
check_together: 'yes'
|
||||||
|
format: tty
|
||||||
|
severity: error
|
||||||
|
|
||||||
|
- name: Spell-Checking
|
||||||
|
uses: codespell-project/actions-codespell@master
|
||||||
|
with:
|
||||||
|
ignore_words_file: .codespellignore
|
||||||
|
|
||||||
|
- name: Get editorconfig-checker
|
||||||
|
uses: editorconfig-checker/action-editorconfig-checker@main # tag v1.0.0 is really out of date
|
||||||
|
|
||||||
|
- name: Run editorconfig-checker
|
||||||
|
run: editorconfig-checker
|
||||||
|
|
||||||
|
- name: Check python code formatting with black
|
||||||
|
uses: psf/black@stable
|
||||||
|
with:
|
||||||
|
src: "./test"
|
||||||
|
options: "--check --diff --color"
|
||||||
|
|
||||||
|
distro-test:
|
||||||
|
if: github.event.pull_request.draft == false
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: smoke-tests
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
distro:
|
||||||
|
[
|
||||||
|
debian_11,
|
||||||
|
debian_12,
|
||||||
|
ubuntu_20,
|
||||||
|
ubuntu_22,
|
||||||
|
ubuntu_24,
|
||||||
|
centos_9,
|
||||||
|
fedora_40,
|
||||||
|
fedora_41,
|
||||||
|
]
|
||||||
|
env:
|
||||||
|
DISTRO: ${{matrix.distro}}
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4.2.2
|
||||||
|
|
||||||
|
- name: Set up Python 3.10
|
||||||
|
uses: actions/setup-python@v5.3.0
|
||||||
|
with:
|
||||||
|
python-version: "3.10"
|
||||||
|
|
||||||
|
- name: Install wheel
|
||||||
|
run: pip install wheel
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pip install -r test/requirements.txt
|
||||||
|
|
||||||
|
- name: Test with tox
|
||||||
|
run: tox -c test/tox.${DISTRO}.ini
|
||||||
12
.gitignore
vendored
Normal file
12
.gitignore
vendored
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
.DS_Store
|
||||||
|
*.pyc
|
||||||
|
*.swp
|
||||||
|
__pycache__
|
||||||
|
.cache
|
||||||
|
.pytest_cache
|
||||||
|
.tox
|
||||||
|
.eggs
|
||||||
|
*.egg-info
|
||||||
|
.idea/
|
||||||
|
*.iml
|
||||||
|
.vscode/
|
||||||
5
CONTRIBUTING.md
Normal file
5
CONTRIBUTING.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
# Contributors Guide
|
||||||
|
|
||||||
|
Please read and understand the contribution guide before creating an issue or pull request.
|
||||||
|
|
||||||
|
The guide can be found here: [https://docs.pi-hole.net/guides/github/contributing/](https://docs.pi-hole.net/guides/github/contributing/)
|
||||||
389
LICENSE
389
LICENSE
@@ -1,339 +1,146 @@
|
|||||||
GNU GENERAL PUBLIC LICENSE
|
Copyright (C) 2017 Pi-hole, LLC (https://pi-hole.net)
|
||||||
Version 2, June 1991
|
Pi-hole Core
|
||||||
|
|
||||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc., <http://fsf.org/>
|
This software is licensed under the European Union Public License (EUPL)
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
The license is available in the 22 official languages of the EU. The English version is included here.
|
||||||
Everyone is permitted to copy and distribute verbatim copies
|
Please see https://joinup.ec.europa.eu/community/eupl/og_page/eupl for official translations of the other languages.
|
||||||
of this license document, but changing it is not allowed.
|
|
||||||
|
|
||||||
Preamble
|
This license applies to the whole project EXCEPT:
|
||||||
|
|
||||||
The licenses for most software are designed to take away your
|
- any commits made to the master branch prior to the release of version 3.0
|
||||||
freedom to share and change it. By contrast, the GNU General Public
|
|
||||||
License is intended to guarantee your freedom to share and change free
|
|
||||||
software--to make sure the software is free for all its users. This
|
|
||||||
General Public License applies to most of the Free Software
|
|
||||||
Foundation's software and to any other program whose authors commit to
|
|
||||||
using it. (Some other Free Software Foundation software is covered by
|
|
||||||
the GNU Lesser General Public License instead.) You can apply it to
|
|
||||||
your programs, too.
|
|
||||||
|
|
||||||
When we speak of free software, we are referring to freedom, not
|
The licenses that existed prior to this change have remained intact.
|
||||||
price. Our General Public Licenses are designed to make sure that you
|
|
||||||
have the freedom to distribute copies of free software (and charge for
|
|
||||||
this service if you wish), that you receive source code or can get it
|
|
||||||
if you want it, that you can change the software or use pieces of it
|
|
||||||
in new free programs; and that you know you can do these things.
|
|
||||||
|
|
||||||
To protect your rights, we need to make restrictions that forbid
|
-------------------------------------------------------------
|
||||||
anyone to deny you these rights or to ask you to surrender the rights.
|
EUROPEAN UNION PUBLIC LICENCE v. 1.2
|
||||||
These restrictions translate to certain responsibilities for you if you
|
|
||||||
distribute copies of the software, or if you modify it.
|
|
||||||
|
|
||||||
For example, if you distribute copies of such a program, whether
|
EUPL © the European Union 2007, 2016
|
||||||
gratis or for a fee, you must give the recipients all the rights that
|
|
||||||
you have. You must make sure that they, too, receive or can get the
|
|
||||||
source code. And you must show them these terms so they know their
|
|
||||||
rights.
|
|
||||||
|
|
||||||
We protect your rights with two steps: (1) copyright the software, and
|
This European Union Public Licence (the EUPL) applies to the Work (as defined below) which is provided under the terms of this Licence. Any use of the Work, other than as authorised under this Licence is prohibited (to the extent such use is covered by a right of the copyright holder of the Work).
|
||||||
(2) offer you this license which gives you legal permission to copy,
|
The Work is provided under the terms of this Licence when the Licensor (as defined below) has placed the following notice immediately following the copyright notice for the Work:
|
||||||
distribute and/or modify the software.
|
Licensed under the EUPL
|
||||||
|
or has expressed by any other means his willingness to license under the EUPL.
|
||||||
|
|
||||||
Also, for each author's protection and ours, we want to make certain
|
1. Definitions
|
||||||
that everyone understands that there is no warranty for this free
|
|
||||||
software. If the software is modified by someone else and passed on, we
|
|
||||||
want its recipients to know that what they have is not the original, so
|
|
||||||
that any problems introduced by others will not reflect on the original
|
|
||||||
authors' reputations.
|
|
||||||
|
|
||||||
Finally, any free program is threatened constantly by software
|
In this Licence, the following terms have the following meaning:
|
||||||
patents. We wish to avoid the danger that redistributors of a free
|
|
||||||
program will individually obtain patent licenses, in effect making the
|
|
||||||
program proprietary. To prevent this, we have made it clear that any
|
|
||||||
patent must be licensed for everyone's free use or not licensed at all.
|
|
||||||
|
|
||||||
The precise terms and conditions for copying, distribution and
|
- The Licence: this Licence.
|
||||||
modification follow.
|
- The Original Work: the work or software distributed or communicated by the Licensor under this Licence, available as Source Code and also as Executable Code as the case may be.
|
||||||
|
- Derivative Works: the works or software that could be created by the Licensee, based upon the Original Work or modifications thereof. This Licence does not define the extent of modification or dependence on the Original Work required in order to classify a work as a Derivative Work; this extent is determined by copyright law applicable in the country mentioned in Article 15.
|
||||||
|
- The Work: the Original Work or its Derivative Works.
|
||||||
|
- The Source Code: the human-readable form of the Work which is the most convenient for people to study and modify.
|
||||||
|
- The Executable Code: any code which has generally been compiled and which is meant to be interpreted by a computer as a program.
|
||||||
|
- The Licensor: the natural or legal person that distributes or communicates the Work under the Licence.
|
||||||
|
- Contributor(s): any natural or legal person who modifies the Work under the Licence, or otherwise contributes to the creation of a Derivative Work.
|
||||||
|
- The Licensee or You: any natural or legal person who makes any usage of the Work under the terms of the Licence.
|
||||||
|
- Distribution or Communication: any act of selling, giving, lending, renting, distributing, communicating, transmitting, or otherwise making available, online or offline, copies of the Work or providing access to its essential functionalities at the disposal of any other natural or legal person.
|
||||||
|
|
||||||
GNU GENERAL PUBLIC LICENSE
|
2. Scope of the rights granted by the Licence
|
||||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
|
||||||
|
|
||||||
0. This License applies to any program or other work which contains
|
The Licensor hereby grants You a worldwide, royalty-free, non-exclusive, sublicensable licence to do the following, for the duration of copyright vested in the Original Work:
|
||||||
a notice placed by the copyright holder saying it may be distributed
|
- use the Work in any circumstance and for all usage,
|
||||||
under the terms of this General Public License. The "Program", below,
|
- reproduce the Work,
|
||||||
refers to any such program or work, and a "work based on the Program"
|
- modify the Work, and make Derivative Works based upon the Work,
|
||||||
means either the Program or any derivative work under copyright law:
|
- communicate to the public, including the right to make available or display the Work or copies thereof to the public and perform publicly, as the case may be, the Work,
|
||||||
that is to say, a work containing the Program or a portion of it,
|
- distribute the Work or copies thereof,
|
||||||
either verbatim or with modifications and/or translated into another
|
- lend and rent the Work or copies thereof,
|
||||||
language. (Hereinafter, translation is included without limitation in
|
- sublicense rights in the Work or copies thereof.
|
||||||
the term "modification".) Each licensee is addressed as "you".
|
Those rights can be exercised on any media, supports and formats, whether now known or later invented, as far as the applicable law permits so.
|
||||||
|
In the countries where moral rights apply, the Licensor waives his right to exercise his moral right to the extent allowed by law in order to make effective the licence of the economic rights here above listed.
|
||||||
|
The Licensor grants to the Licensee royalty-free, non-exclusive usage rights to any patents held by the Licensor, to the extent necessary to make use of the rights granted on the Work under this Licence.
|
||||||
|
|
||||||
Activities other than copying, distribution and modification are not
|
3. Communication of the Source Code
|
||||||
covered by this License; they are outside its scope. The act of
|
|
||||||
running the Program is not restricted, and the output from the Program
|
|
||||||
is covered only if its contents constitute a work based on the
|
|
||||||
Program (independent of having been made by running the Program).
|
|
||||||
Whether that is true depends on what the Program does.
|
|
||||||
|
|
||||||
1. You may copy and distribute verbatim copies of the Program's
|
The Licensor may provide the Work either in its Source Code form, or as Executable Code. If the Work is provided as Executable Code, the Licensor provides in addition a machine-readable copy of the Source Code of the Work along with each copy of the Work that the Licensor distributes or indicates, in a notice following the copyright notice attached to the Work, a repository where the Source Code is easily and freely accessible for as long as the Licensor continues to distribute or communicate the Work.
|
||||||
source code as you receive it, in any medium, provided that you
|
|
||||||
conspicuously and appropriately publish on each copy an appropriate
|
|
||||||
copyright notice and disclaimer of warranty; keep intact all the
|
|
||||||
notices that refer to this License and to the absence of any warranty;
|
|
||||||
and give any other recipients of the Program a copy of this License
|
|
||||||
along with the Program.
|
|
||||||
|
|
||||||
You may charge a fee for the physical act of transferring a copy, and
|
4. Limitations on copyright
|
||||||
you may at your option offer warranty protection in exchange for a fee.
|
|
||||||
|
|
||||||
2. You may modify your copy or copies of the Program or any portion
|
Nothing in this Licence is intended to deprive the Licensee of the benefits from any exception or limitation to the exclusive rights of the rights owners in the Work, of the exhaustion of those rights or of other applicable limitations thereto.
|
||||||
of it, thus forming a work based on the Program, and copy and
|
|
||||||
distribute such modifications or work under the terms of Section 1
|
|
||||||
above, provided that you also meet all of these conditions:
|
|
||||||
|
|
||||||
a) You must cause the modified files to carry prominent notices
|
5. Obligations of the Licensee
|
||||||
stating that you changed the files and the date of any change.
|
|
||||||
|
|
||||||
b) You must cause any work that you distribute or publish, that in
|
The grant of the rights mentioned above is subject to some restrictions and obligations imposed on the Licensee. Those obligations are the following:
|
||||||
whole or in part contains or is derived from the Program or any
|
|
||||||
part thereof, to be licensed as a whole at no charge to all third
|
|
||||||
parties under the terms of this License.
|
|
||||||
|
|
||||||
c) If the modified program normally reads commands interactively
|
Attribution right: The Licensee shall keep intact all copyright, patent or trademarks notices and all notices that refer to the Licence and to the disclaimer of warranties. The Licensee must include a copy of such notices and a copy of the Licence with every copy of the Work he/she distributes or communicates. The Licensee must cause any Derivative Work to carry prominent notices stating that the Work has been modified and the date of modification.
|
||||||
when run, you must cause it, when started running for such
|
|
||||||
interactive use in the most ordinary way, to print or display an
|
|
||||||
announcement including an appropriate copyright notice and a
|
|
||||||
notice that there is no warranty (or else, saying that you provide
|
|
||||||
a warranty) and that users may redistribute the program under
|
|
||||||
these conditions, and telling the user how to view a copy of this
|
|
||||||
License. (Exception: if the Program itself is interactive but
|
|
||||||
does not normally print such an announcement, your work based on
|
|
||||||
the Program is not required to print an announcement.)
|
|
||||||
|
|
||||||
These requirements apply to the modified work as a whole. If
|
Copyleft clause: If the Licensee distributes or communicates copies of the Original Works or Derivative Works, this Distribution or Communication will be done under the terms of this Licence or of a later version of this Licence unless the Original Work is expressly distributed only under this version of the Licence - for example by communicating EUPL v. 1.2 only. The Licensee (becoming Licensor) cannot offer or impose any additional terms or conditions on the Work or Derivative Work that alter or restrict the terms of the Licence.
|
||||||
identifiable sections of that work are not derived from the Program,
|
|
||||||
and can be reasonably considered independent and separate works in
|
|
||||||
themselves, then this License, and its terms, do not apply to those
|
|
||||||
sections when you distribute them as separate works. But when you
|
|
||||||
distribute the same sections as part of a whole which is a work based
|
|
||||||
on the Program, the distribution of the whole must be on the terms of
|
|
||||||
this License, whose permissions for other licensees extend to the
|
|
||||||
entire whole, and thus to each and every part regardless of who wrote it.
|
|
||||||
|
|
||||||
Thus, it is not the intent of this section to claim rights or contest
|
Compatibility clause: If the Licensee Distributes or Communicates Derivative Works or copies thereof based upon both the Work and another work licensed under a Compatible Licence, this Distribution or Communication can be done under the terms of this Compatible Licence. For the sake of this clause, Compatible Licence refers to the licences listed in the appendix attached to this Licence. Should the Licensee's obligations under the Compatible Licence conflict with his/her obligations under this Licence, the obligations of the Compatible Licence shall prevail.
|
||||||
your rights to work written entirely by you; rather, the intent is to
|
|
||||||
exercise the right to control the distribution of derivative or
|
|
||||||
collective works based on the Program.
|
|
||||||
|
|
||||||
In addition, mere aggregation of another work not based on the Program
|
Provision of Source Code: When distributing or communicating copies of the Work, the Licensee will provide a machine-readable copy of the Source Code or indicate a repository where this Source will be easily and freely available for as long as the Licensee continues to distribute or communicate the Work.
|
||||||
with the Program (or with a work based on the Program) on a volume of
|
|
||||||
a storage or distribution medium does not bring the other work under
|
|
||||||
the scope of this License.
|
|
||||||
|
|
||||||
3. You may copy and distribute the Program (or a work based on it,
|
Legal Protection: This Licence does not grant permission to use the trade names, trademarks, service marks, or names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the copyright notice.
|
||||||
under Section 2) in object code or executable form under the terms of
|
|
||||||
Sections 1 and 2 above provided that you also do one of the following:
|
|
||||||
|
|
||||||
a) Accompany it with the complete corresponding machine-readable
|
6. Chain of Authorship
|
||||||
source code, which must be distributed under the terms of Sections
|
|
||||||
1 and 2 above on a medium customarily used for software interchange; or,
|
|
||||||
|
|
||||||
b) Accompany it with a written offer, valid for at least three
|
The original Licensor warrants that the copyright in the Original Work granted hereunder is owned by him/her or licensed to him/her and that he/she has the power and authority to grant the Licence.
|
||||||
years, to give any third party, for a charge no more than your
|
|
||||||
cost of physically performing source distribution, a complete
|
|
||||||
machine-readable copy of the corresponding source code, to be
|
|
||||||
distributed under the terms of Sections 1 and 2 above on a medium
|
|
||||||
customarily used for software interchange; or,
|
|
||||||
|
|
||||||
c) Accompany it with the information you received as to the offer
|
Each Contributor warrants that the copyright in the modifications he/she brings to the Work are owned by him/her or licensed to him/her and that he/she has the power and authority to grant the Licence.
|
||||||
to distribute corresponding source code. (This alternative is
|
|
||||||
allowed only for noncommercial distribution and only if you
|
|
||||||
received the program in object code or executable form with such
|
|
||||||
an offer, in accord with Subsection b above.)
|
|
||||||
|
|
||||||
The source code for a work means the preferred form of the work for
|
Each time You accept the Licence, the original Licensor and subsequent Contributors grant You a licence to their contributions to the Work, under the terms of this Licence.
|
||||||
making modifications to it. For an executable work, complete source
|
|
||||||
code means all the source code for all modules it contains, plus any
|
|
||||||
associated interface definition files, plus the scripts used to
|
|
||||||
control compilation and installation of the executable. However, as a
|
|
||||||
special exception, the source code distributed need not include
|
|
||||||
anything that is normally distributed (in either source or binary
|
|
||||||
form) with the major components (compiler, kernel, and so on) of the
|
|
||||||
operating system on which the executable runs, unless that component
|
|
||||||
itself accompanies the executable.
|
|
||||||
|
|
||||||
If distribution of executable or object code is made by offering
|
7. Disclaimer of Warranty
|
||||||
access to copy from a designated place, then offering equivalent
|
|
||||||
access to copy the source code from the same place counts as
|
|
||||||
distribution of the source code, even though third parties are not
|
|
||||||
compelled to copy the source along with the object code.
|
|
||||||
|
|
||||||
4. You may not copy, modify, sublicense, or distribute the Program
|
The Work is a work in progress, which is continuously improved by numerous Contributors. It is not a finished work and may therefore contain defects or bugs inherent to this type of development.
|
||||||
except as expressly provided under this License. Any attempt
|
For the above reason, the Work is provided under the Licence on an as is basis and without warranties of any kind concerning the Work, including without limitation merchantability, fitness for a particular purpose, absence of defects or errors, accuracy, non-infringement of intellectual property rights other than copyright as stated in Article 6 of this Licence.
|
||||||
otherwise to copy, modify, sublicense or distribute the Program is
|
This disclaimer of warranty is an essential part of the Licence and a condition for the grant of any rights to the Work.
|
||||||
void, and will automatically terminate your rights under this License.
|
|
||||||
However, parties who have received copies, or rights, from you under
|
|
||||||
this License will not have their licenses terminated so long as such
|
|
||||||
parties remain in full compliance.
|
|
||||||
|
|
||||||
5. You are not required to accept this License, since you have not
|
8. Disclaimer of Liability
|
||||||
signed it. However, nothing else grants you permission to modify or
|
|
||||||
distribute the Program or its derivative works. These actions are
|
|
||||||
prohibited by law if you do not accept this License. Therefore, by
|
|
||||||
modifying or distributing the Program (or any work based on the
|
|
||||||
Program), you indicate your acceptance of this License to do so, and
|
|
||||||
all its terms and conditions for copying, distributing or modifying
|
|
||||||
the Program or works based on it.
|
|
||||||
|
|
||||||
6. Each time you redistribute the Program (or any work based on the
|
Except in the cases of wilful misconduct or damages directly caused to natural persons, the Licensor will in no event be liable for any direct or indirect, material or moral, damages of any kind, arising out of the Licence or of the use of the Work, including without limitation, damages for loss of goodwill, work stoppage, computer failure or malfunction, loss of data or any commercial damage, even if the Licensor has been advised of the possibility of such damage. However, the Licensor will be liable under statutory product liability laws as far such laws apply to the Work.
|
||||||
Program), the recipient automatically receives a license from the
|
|
||||||
original licensor to copy, distribute or modify the Program subject to
|
|
||||||
these terms and conditions. You may not impose any further
|
|
||||||
restrictions on the recipients' exercise of the rights granted herein.
|
|
||||||
You are not responsible for enforcing compliance by third parties to
|
|
||||||
this License.
|
|
||||||
|
|
||||||
7. If, as a consequence of a court judgment or allegation of patent
|
9. Additional agreements
|
||||||
infringement or for any other reason (not limited to patent issues),
|
|
||||||
conditions are imposed on you (whether by court order, agreement or
|
|
||||||
otherwise) that contradict the conditions of this License, they do not
|
|
||||||
excuse you from the conditions of this License. If you cannot
|
|
||||||
distribute so as to satisfy simultaneously your obligations under this
|
|
||||||
License and any other pertinent obligations, then as a consequence you
|
|
||||||
may not distribute the Program at all. For example, if a patent
|
|
||||||
license would not permit royalty-free redistribution of the Program by
|
|
||||||
all those who receive copies directly or indirectly through you, then
|
|
||||||
the only way you could satisfy both it and this License would be to
|
|
||||||
refrain entirely from distribution of the Program.
|
|
||||||
|
|
||||||
If any portion of this section is held invalid or unenforceable under
|
While distributing the Work, You may choose to conclude an additional agreement, defining obligations or services consistent with this Licence. However, if accepting obligations, You may act only on your own behalf and on your sole responsibility, not on behalf of the original Licensor or any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against such Contributor by the fact You have accepted any warranty or additional liability.
|
||||||
any particular circumstance, the balance of the section is intended to
|
|
||||||
apply and the section as a whole is intended to apply in other
|
|
||||||
circumstances.
|
|
||||||
|
|
||||||
It is not the purpose of this section to induce you to infringe any
|
10. Acceptance of the Licence
|
||||||
patents or other property right claims or to contest validity of any
|
|
||||||
such claims; this section has the sole purpose of protecting the
|
|
||||||
integrity of the free software distribution system, which is
|
|
||||||
implemented by public license practices. Many people have made
|
|
||||||
generous contributions to the wide range of software distributed
|
|
||||||
through that system in reliance on consistent application of that
|
|
||||||
system; it is up to the author/donor to decide if he or she is willing
|
|
||||||
to distribute software through any other system and a licensee cannot
|
|
||||||
impose that choice.
|
|
||||||
|
|
||||||
This section is intended to make thoroughly clear what is believed to
|
The provisions of this Licence can be accepted by clicking on an icon I agree placed under the bottom of a window displaying the text of this Licence or by affirming consent in any other similar way, in accordance with the rules of applicable law. Clicking on that icon indicates your clear and irrevocable acceptance of this Licence and all of its terms and conditions.
|
||||||
be a consequence of the rest of this License.
|
Similarly, you irrevocably accept this Licence and all of its terms and conditions by exercising any rights granted to You by Article 2 of this Licence, such as the use of the Work, the creation by You of a Derivative Work or the Distribution or Communication by You of the Work or copies thereof.
|
||||||
|
|
||||||
8. If the distribution and/or use of the Program is restricted in
|
11. Information to the public
|
||||||
certain countries either by patents or by copyrighted interfaces, the
|
|
||||||
original copyright holder who places the Program under this License
|
|
||||||
may add an explicit geographical distribution limitation excluding
|
|
||||||
those countries, so that distribution is permitted only in or among
|
|
||||||
countries not thus excluded. In such case, this License incorporates
|
|
||||||
the limitation as if written in the body of this License.
|
|
||||||
|
|
||||||
9. The Free Software Foundation may publish revised and/or new versions
|
In case of any Distribution or Communication of the Work by means of electronic communication by You (for example, by offering to download the Work from a remote location) the distribution channel or media (for example, a website) must at least provide to the public the information requested by the applicable law regarding the Licensor, the Licence and the way it may be accessible, concluded, stored and reproduced by the Licensee.
|
||||||
of the General Public License from time to time. Such new versions will
|
|
||||||
be similar in spirit to the present version, but may differ in detail to
|
|
||||||
address new problems or concerns.
|
|
||||||
|
|
||||||
Each version is given a distinguishing version number. If the Program
|
12. Termination of the Licence
|
||||||
specifies a version number of this License which applies to it and "any
|
|
||||||
later version", you have the option of following the terms and conditions
|
|
||||||
either of that version or of any later version published by the Free
|
|
||||||
Software Foundation. If the Program does not specify a version number of
|
|
||||||
this License, you may choose any version ever published by the Free Software
|
|
||||||
Foundation.
|
|
||||||
|
|
||||||
10. If you wish to incorporate parts of the Program into other free
|
The Licence and the rights granted hereunder will terminate automatically upon any breach by the Licensee of the terms of the Licence.
|
||||||
programs whose distribution conditions are different, write to the author
|
Such a termination will not terminate the licences of any person who has received the Work from the Licensee under the Licence, provided such persons remain in full compliance with the Licence.
|
||||||
to ask for permission. For software which is copyrighted by the Free
|
|
||||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
|
||||||
make exceptions for this. Our decision will be guided by the two goals
|
|
||||||
of preserving the free status of all derivatives of our free software and
|
|
||||||
of promoting the sharing and reuse of software generally.
|
|
||||||
|
|
||||||
NO WARRANTY
|
13. Miscellaneous
|
||||||
|
|
||||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
Without prejudice of Article 9 above, the Licence represents the complete agreement between the Parties as to the Work.
|
||||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
If any provision of the Licence is invalid or unenforceable under applicable law, this will not affect the validity or enforceability of the Licence as a whole. Such provision will be construed or reformed so as necessary to make it valid and enforceable.
|
||||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
The European Commission may publish other linguistic versions or new versions of this Licence or updated versions of the Appendix, so far this is required and reasonable, without reducing the scope of the rights granted by the Licence. New versions of the Licence will be published with a unique version number.
|
||||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
All linguistic versions of this Licence, approved by the European Commission, have identical value. Parties can take advantage of the linguistic version of their choice.
|
||||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
|
||||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
|
||||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
|
||||||
REPAIR OR CORRECTION.
|
|
||||||
|
|
||||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
14. Jurisdiction
|
||||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
|
||||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
|
||||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
|
||||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
|
||||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
|
||||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
|
||||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
|
||||||
POSSIBILITY OF SUCH DAMAGES.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
Without prejudice to specific agreement between parties,
|
||||||
|
- any litigation resulting from the interpretation of this License, arising between the European Union institutions, bodies, offices or agencies, as a Licensor, and any Licensee, will be subject to the jurisdiction of the Court of Justice of the European Union, as laid down in article 272 of the Treaty on the Functioning of the European Union,
|
||||||
|
- any litigation arising between other parties and resulting from the interpretation of this License, will be subject to the exclusive jurisdiction of the competent court where the Licensor resides or conducts its primary business.
|
||||||
|
|
||||||
How to Apply These Terms to Your New Programs
|
15. Applicable Law
|
||||||
|
|
||||||
If you develop a new program, and you want it to be of the greatest
|
Without prejudice to specific agreement between parties,
|
||||||
possible use to the public, the best way to achieve this is to make it
|
- this Licence shall be governed by the law of the European Union Member State where the Licensor has his seat, resides or has his registered office,
|
||||||
free software which everyone can redistribute and change under these terms.
|
- this licence shall be governed by Belgian law if the Licensor has no seat, residence or registered office inside a European Union Member State.
|
||||||
|
|
||||||
To do so, attach the following notices to the program. It is safest
|
===
|
||||||
to attach them to the start of each source file to most effectively
|
|
||||||
convey the exclusion of warranty; and each file should have at least
|
|
||||||
the "copyright" line and a pointer to where the full notice is found.
|
|
||||||
|
|
||||||
{description}
|
Appendix
|
||||||
Copyright (C) {year} {fullname}
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Compatible Licences according to Article 5 EUPL are:
|
||||||
it under the terms of the GNU General Public License as published by
|
- GNU General Public License (GPL) v. 2, v. 3
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
- GNU Affero General Public License (AGPL) v. 3
|
||||||
(at your option) any later version.
|
- Open Software License (OSL) v. 2.1, v. 3.0
|
||||||
|
- Eclipse Public License (EPL) v. 1.0
|
||||||
This program is distributed in the hope that it will be useful,
|
- CeCILL v. 2.0, v. 2.1
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
- Mozilla Public Licence (MPL) v. 2
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
- GNU Lesser General Public Licence (LGPL) v. 2.1, v. 3
|
||||||
GNU General Public License for more details.
|
- Creative Commons Attribution-ShareAlike v. 3.0 Unported (CC BY-SA 3.0) for works other than software
|
||||||
|
- European Union Public Licence (EUPL) v. 1.1, v. 1.2
|
||||||
You should have received a copy of the GNU General Public License along
|
- Québec Free and Open-Source Licence - Reciprocity (LiLiQ-R) or Strong Reciprocity (LiLiQ-R+)
|
||||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
- The European Commission may update this Appendix to later versions of the above licences without producing a new version of the EUPL, as long as they provide the rights granted in Article 2 of this Licence and protect the covered Source Code from exclusive appropriation.
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
- All other changes or additions to this Appendix require the production of a new EUPL version.
|
||||||
|
|
||||||
Also add information on how to contact you by electronic and paper mail.
|
|
||||||
|
|
||||||
If the program is interactive, make it output a short notice like this
|
|
||||||
when it starts in an interactive mode:
|
|
||||||
|
|
||||||
Gnomovision version 69, Copyright (C) year name of author
|
|
||||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
|
||||||
This is free software, and you are welcome to redistribute it
|
|
||||||
under certain conditions; type `show c' for details.
|
|
||||||
|
|
||||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
|
||||||
parts of the General Public License. Of course, the commands you use may
|
|
||||||
be called something other than `show w' and `show c'; they could even be
|
|
||||||
mouse-clicks or menu items--whatever suits your program.
|
|
||||||
|
|
||||||
You should also get your employer (if you work as a programmer) or your
|
|
||||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
|
||||||
necessary. Here is a sample; alter the names:
|
|
||||||
|
|
||||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
|
||||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
|
||||||
|
|
||||||
{signature of Ty Coon}, 1 April 1989
|
|
||||||
Ty Coon, President of Vice
|
|
||||||
|
|
||||||
This General Public License does not permit incorporating your program into
|
|
||||||
proprietary programs. If your program is a subroutine library, you may
|
|
||||||
consider it more useful to permit linking proprietary applications with the
|
|
||||||
library. If this is what you want to do, use the GNU Lesser General
|
|
||||||
Public License instead of this License.
|
|
||||||
|
|||||||
228
README.md
228
README.md
@@ -1,85 +1,171 @@
|
|||||||
# Automated Install
|
<!-- markdownlint-configure-file { "MD004": { "style": "consistent" } } -->
|
||||||
##### Designed For Raspberry Pi B, B+, 2, and Zero (with an Ethernet adapter)
|
<!-- markdownlint-disable MD033 -->
|
||||||
|
#
|
||||||
|
|
||||||
1. Install Raspbian
|
<p align="center">
|
||||||
2. Run the command below
|
<picture>
|
||||||
|
<source media="(prefers-color-scheme: dark)" srcset="https://pi-hole.github.io/graphics/Vortex/Vortex_Vertical_wordmark_darkmode.png">
|
||||||
|
<source media="(prefers-color-scheme: light)" srcset="https://pi-hole.github.io/graphics/Vortex/Vortex_Vertical_wordmark_lightmode.png">
|
||||||
|
<img src="https://pi-hole.github.io/graphics/Vortex/Vortex_Vertical_wordmark_lightmode.png" width="168" height="270" alt="Pi-hole website">
|
||||||
|
</picture>
|
||||||
|
<br>
|
||||||
|
<strong>Network-wide ad blocking via your own Linux hardware</strong>
|
||||||
|
</p>
|
||||||
|
|
||||||
### ```curl -L install.pi-hole.net | bash```
|
<!-- markdownlint-enable MD033 -->
|
||||||
|
|
||||||
Once installed, [configure your router to have **DHCP clients use the Pi as their DNS server**](http://pi-hole.net/faq/can-i-set-the-pi-hole-to-be-the-dns-server-at-my-router-so-i-dont-have-to-change-settings-for-my-devices/) and then any device that connects to your network will have ads blocked without any further configuration. Alternatively, you can manually set each device to [use the Raspberry Pi as its DNS server](http://pi-hole.net/faq/how-do-i-use-the-pi-hole-as-my-dns-server/).
|
The Pi-hole® is a [DNS sinkhole](https://en.wikipedia.org/wiki/DNS_Sinkhole) that protects your devices from unwanted content without installing any client-side software.
|
||||||
|
|
||||||
## Pi-hole Is Free, But Powered By Your Donations
|
- **Easy-to-install**: our dialogs walk you through the simple installation process in less than ten minutes
|
||||||
[](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=3J2L3Z4DHW9UY "Donate")
|
- **Resolute**: content is blocked in _non-browser locations_, such as ad-laden mobile apps and smart TVs
|
||||||
|
- **Responsive**: seamlessly speeds up the feel of everyday browsing by caching DNS queries
|
||||||
|
- **Lightweight**: runs smoothly with [minimal hardware and software requirements](https://docs.pi-hole.net/main/prerequisites/)
|
||||||
|
- **Robust**: a command-line interface that is quality assured for interoperability
|
||||||
|
- **Insightful**: a beautiful responsive Web Interface dashboard to view and control your Pi-hole
|
||||||
|
- **Versatile**: can optionally function as a [DHCP server](https://discourse.pi-hole.net/t/how-do-i-use-pi-holes-built-in-dhcp-server-and-why-would-i-want-to/3026), ensuring _all_ your devices are protected automatically
|
||||||
|
- **Scalable**: [capable of handling hundreds of millions of queries](https://pi-hole.net/2017/05/24/how-much-traffic-can-pi-hole-handle/) when installed on server-grade hardware
|
||||||
|
- **Modern**: blocks ads over both IPv4 and IPv6
|
||||||
|
- **Free**: open source software that helps ensure _you_ are the sole person in control of your privacy
|
||||||
|
|
||||||
## How Does It Work?
|
-----
|
||||||
**Watch the 60-second video below to get a quick overview**
|
|
||||||
|
|
||||||
[](https://vimeo.com/135965232)
|
## One-Step Automated Install
|
||||||
|
|
||||||
## Pi-hole Projects
|
Those who want to get started quickly and conveniently may install Pi-hole using the following command:
|
||||||
- [Pi-hole Chrome extension](https://chrome.google.com/webstore/detail/pi-hole-list-editor/hlnoeoejkllgkjbnnnhfolapllcnaglh) ([open source](https://github.com/packtloss/pihole-extension))
|
|
||||||
- [Go Bananas for CHiP-hole ad blocking](https://www.hackster.io/jacobsalmela/chip-hole-network-wide-ad-blocker-98e037)
|
|
||||||
- [Sky-Hole](http://dlaa.me/blog/post/skyhole)
|
|
||||||
- [Pi-hole in the Cloud!](http://blog.codybunch.com/2015/07/28/Pi-Hole-in-the-cloud/)
|
|
||||||
- [unRaid-hole](https://github.com/spants/unraidtemplates/blob/master/Spants/unRaid-hole.xml#L13)--[Repo and more info](http://lime-technology.com/forum/index.php?PHPSESSID=c0eae3e5ef7e521f7866034a3336489d&topic=38486.0)
|
|
||||||
- [Pi-hole on/off button](http://thetimmy.silvernight.org/pages/endisbutton/)
|
|
||||||
- [Minibian Pi-hole](http://munkjensen.net/wiki/index.php/See_my_Pi-Hole#Minibian_Pi-hole)
|
|
||||||
|
|
||||||
## Coverage
|
```bash
|
||||||
- [MacObserver Podcast 585](http://www.macobserver.com/tmo/podcast/macgeekgab-585)
|
curl -sSL https://install.pi-hole.net | bash
|
||||||
- [Medium: Block All Ads For $53](https://medium.com/@robleathern/block-ads-on-all-home-devices-for-53-18-a5f1ec139693#.gj1xpgr5d)
|
|
||||||
- [MakeUseOf: Adblock Everywhere, The Pi-hole Way](http://www.makeuseof.com/tag/adblock-everywhere-raspberry-pi-hole-way/)
|
|
||||||
- [Lifehacker: Turn Your Pi Into An Ad Blocker With A Single Command](http://lifehacker.com/turn-a-raspberry-pi-into-an-ad-blocker-with-a-single-co-1686093533)!
|
|
||||||
- [Pi-hole on TekThing](https://youtu.be/8Co59HU2gY0?t=2m)
|
|
||||||
- [Pi-hole on Security Now! Podcast](http://www.youtube.com/watch?v=p7-osq_y8i8&t=100m26s)
|
|
||||||
- [Foolish Tech Show](https://youtu.be/bYyena0I9yc?t=2m4s)
|
|
||||||
- [Pi-hole on Ubuntu](http://www.boyter.org/2015/12/pi-hole-ubuntu-14-04/)
|
|
||||||
- [Catchpoint: iOS 9 Ad Blocking](http://blog.catchpoint.com/2015/09/14/ad-blocking-apple/)
|
|
||||||
|
|
||||||
## Partnering With Optimal.com
|
|
||||||
|
|
||||||
Pi-hole will be teaming up with [Rob Leathern's subscription service to avoid ads](https://medium.com/@robleathern/block-ads-on-all-home-devices-for-53-18-a5f1ec139693#.gj1xpgr5d). This service is unique and will help content-creators and publishers [still make money from visitors who are using an ad ablocker](http://techcrunch.com/2015/12/17/the-new-optimal/).
|
|
||||||
|
|
||||||
## Technical Details
|
|
||||||
|
|
||||||
The Pi-hole is an **advertising-aware DNS/Web server**. If an ad domain is queried, a small Web page or GIF is delivered in place of the advertisement. You can also [replace ads with any image you want](http://pi-hole.net/faq/is-it-possible-to-change-the-blank-page-that-takes-place-of-the-ads-to-something-else/) since it is just a simple Webpage taking place of the ads.
|
|
||||||
|
|
||||||
A more detailed explanation of the installation can be found [here](http://jacobsalmela.com/block-millions-ads-network-wide-with-a-raspberry-pi-hole-2-0).
|
|
||||||
|
|
||||||
## Gravity
|
|
||||||
The [gravity.sh](https://github.com/pi-hole/pi-hole/blob/master/gravity.sh) does most of the magic. The script pulls in ad domains from many sources and compiles them into a single list of [over 1.6 million entries](http://jacobsalmela.com/block-millions-ads-network-wide-with-a-raspberry-pi-hole-2-0) (if you decide to use the [mahakala list](https://github.com/pi-hole/pi-hole/commit/963eacfe0537a7abddf30441c754c67ca1e40965)).
|
|
||||||
|
|
||||||
## Whitelist and blacklist
|
|
||||||
Domains can be whitelisted and blacklisted using two pre-installed scripts. See [the wiki page](https://github.com/pi-hole/pi-hole/wiki/Whitelisting-and-Blacklisting) for more details
|
|
||||||
|
|
||||||
## Web Interface
|
|
||||||
The [Web interface](https://github.com/jacobsalmela/AdminLTE#pi-hole-admin-dashboard) will be installed automatically so you can view stats and change settings. You can find it at:
|
|
||||||
|
|
||||||
`http://192.168.1.x/admin/index.php`
|
|
||||||
|
|
||||||
### API
|
|
||||||
|
|
||||||
A basic read-only API can be accessed at `/admin/api.php`. It returns the following JSON:
|
|
||||||
```JSON
|
|
||||||
{
|
|
||||||
"domains_being_blocked": "136708",
|
|
||||||
"dns_queries_today": "18108",
|
|
||||||
"ads_blocked_today": "14648",
|
|
||||||
"ads_percentage_today": "80.89"
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
The same output can be acheived on the CLI by running `chronometer.sh -j`
|
|
||||||
|
|
||||||

|
## Alternative Install Methods
|
||||||
|
|
||||||
## Real-time Statistics
|
Piping to `bash` is [controversial](https://pi-hole.net/2016/07/25/curling-and-piping-to-bash), as it prevents you from [reading code that is about to run](https://github.com/pi-hole/pi-hole/blob/master/automated%20install/basic-install.sh) on your system. Therefore, we provide these alternative installation methods which allow code review before installation:
|
||||||
|
|
||||||
You can view [real-time stats](http://pi-hole.net/faq/install-the-real-time-lcd-monitor-chronometer/) via `ssh` or on an [2.8" LCD screen](http://amzn.to/1P0q1Fj). This is accomplished via [`chronometer.sh`](https://github.com/pi-hole/pi-hole/blob/master/advanced/Scripts/chronometer.sh).
|
### Method 1: Clone our repository and run
|
||||||

|
|
||||||
|
|
||||||
## Help
|
```bash
|
||||||
- See the [Wiki](https://github.com/pi-hole/pi-hole/wiki/Customization) entry for more details
|
git clone --depth 1 https://github.com/pi-hole/pi-hole.git Pi-hole
|
||||||
- There is also an [FAQ section on pi-hole.net](http://pi-hole.net)
|
cd "Pi-hole/automated install/"
|
||||||
|
sudo bash basic-install.sh
|
||||||
|
```
|
||||||
|
|
||||||
## Other Operating Systems
|
### Method 2: Manually download the installer and run
|
||||||
This script will work for other UNIX-like systems with some slight **modifications**. As long as you can install `dnsmasq` and a Webserver, it should work OK. The automated install only works for a clean install of Raspiban right now since that is how the project originated.
|
|
||||||
|
```bash
|
||||||
|
wget -O basic-install.sh https://install.pi-hole.net
|
||||||
|
sudo bash basic-install.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
### Method 3: Using Docker to deploy Pi-hole
|
||||||
|
|
||||||
|
Please refer to the [Pi-hole docker repo](https://github.com/pi-hole/docker-pi-hole) to use the Official Docker Images.
|
||||||
|
|
||||||
|
## [Post-install: Make your network take advantage of Pi-hole](https://docs.pi-hole.net/main/post-install/)
|
||||||
|
|
||||||
|
Once the installer has been run, you will need to [configure your router to have **DHCP clients use Pi-hole as their DNS server**](https://discourse.pi-hole.net/t/how-do-i-configure-my-devices-to-use-pi-hole-as-their-dns-server/245). This router configuration will ensure that all devices connecting to your network will have content blocked without any further intervention.
|
||||||
|
|
||||||
|
If your router does not support setting the DNS server, you can [use Pi-hole's built-in DHCP server](https://discourse.pi-hole.net/t/how-do-i-use-pi-holes-built-in-dhcp-server-and-why-would-i-want-to/3026); be sure to disable DHCP on your router first (if it has that feature available).
|
||||||
|
|
||||||
|
As a last resort, you can manually set each device to use Pi-hole as their DNS server.
|
||||||
|
|
||||||
|
-----
|
||||||
|
|
||||||
|
## Pi-hole is free but powered by your support
|
||||||
|
|
||||||
|
There are many reoccurring costs involved with maintaining free, open-source, and privacy-respecting software; expenses which [our volunteer developers](https://github.com/orgs/pi-hole/people) pitch in to cover out-of-pocket. This is just one example of how strongly we feel about our software and the importance of keeping it maintained.
|
||||||
|
|
||||||
|
Make no mistake: **your support is absolutely vital to help keep us innovating!**
|
||||||
|
|
||||||
|
### [Donations](https://pi-hole.net/donate)
|
||||||
|
|
||||||
|
Donating using our Sponsor Button is **extremely helpful** in offsetting a portion of our monthly expenses:
|
||||||
|
|
||||||
|
### Alternative support
|
||||||
|
|
||||||
|
If you'd rather not donate (_which is okay!_), there are other ways you can help support us:
|
||||||
|
|
||||||
|
- [GitHub Sponsors](https://github.com/sponsors/pi-hole/)
|
||||||
|
- [Patreon](https://patreon.com/pihole)
|
||||||
|
- [Hetzner Cloud](https://hetzner.cloud/?ref=7aceisRX3AzA) _affiliate link_
|
||||||
|
- [Digital Ocean](https://www.digitalocean.com/?refcode=344d234950e1) _affiliate link_
|
||||||
|
- [Stickermule](https://www.stickermule.com/unlock?ref_id=9127301701&utm_medium=link&utm_source=invite) _earn a $10 credit after your first purchase_
|
||||||
|
- [Amazon US](https://www.amazon.com/exec/obidos/redirect-home/pihole09-20) _affiliate link_
|
||||||
|
- Spreading the word about our software and how you have benefited from it
|
||||||
|
|
||||||
|
### Contributing via GitHub
|
||||||
|
|
||||||
|
We welcome _everyone_ to contribute to issue reports, suggest new features, and create pull requests.
|
||||||
|
|
||||||
|
If you have something to add - anything from a typo through to a whole new feature, we're happy to check it out! Just make sure to fill out our template when submitting your request; the questions it asks will help the volunteers quickly understand what you're aiming to achieve.
|
||||||
|
|
||||||
|
You'll find that the [install script](https://github.com/pi-hole/pi-hole/blob/master/automated%20install/basic-install.sh) and the [debug script](https://github.com/pi-hole/pi-hole/blob/master/advanced/Scripts/piholeDebug.sh) have an abundance of comments, which will help you better understand how Pi-hole works. They're also a valuable resource to those who want to learn how to write scripts or code a program! We encourage anyone who likes to tinker to read through it and submit a pull request for us to review.
|
||||||
|
|
||||||
|
-----
|
||||||
|
|
||||||
|
## Getting in touch with us
|
||||||
|
|
||||||
|
While we are primarily reachable on our [Discourse User Forum](https://discourse.pi-hole.net/), we can also be found on various social media outlets.
|
||||||
|
|
||||||
|
**Please be sure to check the FAQs** before starting a new discussion, as we do not have the spare time to reply to every request for assistance.
|
||||||
|
|
||||||
|
- [Frequently Asked Questions](https://discourse.pi-hole.net/c/faqs)
|
||||||
|
- [Feature Requests](https://discourse.pi-hole.net/c/feature-requests?order=votes)
|
||||||
|
- [Reddit](https://www.reddit.com/r/pihole/)
|
||||||
|
- [Twitter](https://twitter.com/The_Pi_hole)
|
||||||
|
|
||||||
|
-----
|
||||||
|
|
||||||
|
## Breakdown of Features
|
||||||
|
|
||||||
|
### [Faster-than-light Engine](https://github.com/pi-hole/ftl)
|
||||||
|
|
||||||
|
[FTLDNS](https://github.com/pi-hole/ftl) is a lightweight, purpose-built daemon used to provide statistics needed for the Web Interface, and its API can be easily integrated into your own projects. As the name implies, FTLDNS does this all _very quickly_!
|
||||||
|
|
||||||
|
Some of the statistics you can integrate include:
|
||||||
|
|
||||||
|
- Total number of domains being blocked
|
||||||
|
- Total number of DNS queries today
|
||||||
|
- Total number of ads blocked today
|
||||||
|
- Percentage of ads blocked
|
||||||
|
- Unique domains
|
||||||
|
- Queries forwarded (to your chosen upstream DNS server)
|
||||||
|
- Queries cached
|
||||||
|
- Unique clients
|
||||||
|
|
||||||
|
Access the API via [`telnet`](https://github.com/pi-hole/FTL), the Web (`admin/api.php`) and Command Line (`pihole -c -j`). You can find out [more details over here](https://discourse.pi-hole.net/t/pi-hole-api/1863).
|
||||||
|
|
||||||
|
### The Command-Line Interface
|
||||||
|
|
||||||
|
The [pihole](https://docs.pi-hole.net/core/pihole-command/) command has all the functionality necessary to fully administer the Pi-hole, without the need for the Web Interface. It's fast, user-friendly, and auditable by anyone with an understanding of `bash`.
|
||||||
|
|
||||||
|
Some notable features include:
|
||||||
|
|
||||||
|
- [Whitelisting, Blacklisting, and Regex](https://docs.pi-hole.net/core/pihole-command/#whitelisting-blacklisting-and-regex)
|
||||||
|
- [Debugging utility](https://docs.pi-hole.net/core/pihole-command/#debugger)
|
||||||
|
- [Viewing the live log file](https://docs.pi-hole.net/core/pihole-command/#tail)
|
||||||
|
- [Updating Ad Lists](https://docs.pi-hole.net/core/pihole-command/#gravity)
|
||||||
|
- [Querying Ad Lists for blocked domains](https://docs.pi-hole.net/core/pihole-command/#query)
|
||||||
|
- [Enabling and Disabling Pi-hole](https://docs.pi-hole.net/core/pihole-command/#enable-disable)
|
||||||
|
- ... and _many_ more!
|
||||||
|
|
||||||
|
You can read our [Core Feature Breakdown](https://docs.pi-hole.net/core/pihole-command/#pi-hole-core) for more information.
|
||||||
|
|
||||||
|
### The Web Interface Dashboard
|
||||||
|
|
||||||
|
This [optional dashboard](https://github.com/pi-hole/web) allows you to view stats, change settings, and configure your Pi-hole. It's the power of the Command Line Interface, with none of the learning curve!
|
||||||
|
|
||||||
|
Some notable features include:
|
||||||
|
|
||||||
|
- Mobile-friendly interface
|
||||||
|
- Password protection
|
||||||
|
- Detailed graphs and doughnut charts
|
||||||
|
- Top lists of domains and clients
|
||||||
|
- A filterable and sortable query log
|
||||||
|
- Long Term Statistics to view data over user-defined time ranges
|
||||||
|
- The ability to easily manage and configure Pi-hole features
|
||||||
|
- ... and all the main features of the Command Line Interface!
|
||||||
|
|
||||||
|
There are several ways to [access the dashboard](https://discourse.pi-hole.net/t/how-do-i-access-pi-holes-dashboard-admin-interface/3168):
|
||||||
|
|
||||||
|
1. `http://pi.hole/admin/` (when using Pi-hole as your DNS server)
|
||||||
|
2. `http://<IP_ADDRESS_OF_YOUR_PI_HOLE>/admin/`
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 35 B |
Binary file not shown.
|
Before Width: | Height: | Size: 26 B |
Binary file not shown.
|
Before Width: | Height: | Size: 37 B |
Binary file not shown.
|
Before Width: | Height: | Size: 43 B |
49
advanced/Scripts/COL_TABLE
Normal file
49
advanced/Scripts/COL_TABLE
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
# Determine if terminal is capable of showing colors
|
||||||
|
if ([ -t 1 ] && [ $(tput colors) -ge 8 ]) || [ "${WEBCALL}" ]; then
|
||||||
|
# Bold and underline may not show up on all clients
|
||||||
|
# If something MUST be emphasized, use both
|
||||||
|
COL_BOLD='[1m'
|
||||||
|
COL_ULINE='[4m'
|
||||||
|
|
||||||
|
COL_NC='[0m'
|
||||||
|
COL_GRAY='[90m'
|
||||||
|
COL_RED='[91m'
|
||||||
|
COL_GREEN='[32m'
|
||||||
|
COL_YELLOW='[33m'
|
||||||
|
COL_BLUE='[94m'
|
||||||
|
COL_PURPLE='[95m'
|
||||||
|
COL_CYAN='[96m'
|
||||||
|
else
|
||||||
|
# Provide empty variables for `set -u`
|
||||||
|
COL_BOLD=""
|
||||||
|
COL_ULINE=""
|
||||||
|
|
||||||
|
COL_NC=""
|
||||||
|
COL_GRAY=""
|
||||||
|
COL_RED=""
|
||||||
|
COL_GREEN=""
|
||||||
|
COL_YELLOW=""
|
||||||
|
COL_BLUE=""
|
||||||
|
COL_PURPLE=""
|
||||||
|
COL_CYAN=""
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Deprecated variables
|
||||||
|
COL_WHITE="${COL_BOLD}"
|
||||||
|
COL_BLACK="${COL_NC}"
|
||||||
|
COL_LIGHT_BLUE="${COL_BLUE}"
|
||||||
|
COL_LIGHT_GREEN="${COL_GREEN}"
|
||||||
|
COL_LIGHT_CYAN="${COL_CYAN}"
|
||||||
|
COL_LIGHT_RED="${COL_RED}"
|
||||||
|
COL_URG_RED="${COL_RED}${COL_BOLD}${COL_ULINE}"
|
||||||
|
COL_LIGHT_PURPLE="${COL_PURPLE}"
|
||||||
|
COL_BROWN="${COL_YELLOW}"
|
||||||
|
COL_LIGHT_GRAY="${COL_GRAY}"
|
||||||
|
COL_DARK_GRAY="${COL_GRAY}"
|
||||||
|
|
||||||
|
TICK="[${COL_GREEN}✓${COL_NC}]"
|
||||||
|
CROSS="[${COL_RED}✗${COL_NC}]"
|
||||||
|
INFO="[i]"
|
||||||
|
QST="[?]"
|
||||||
|
DONE="${COL_GREEN} done!${COL_NC}"
|
||||||
|
OVER="\\r[K"
|
||||||
290
advanced/Scripts/api.sh
Executable file
290
advanced/Scripts/api.sh
Executable file
@@ -0,0 +1,290 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
# shellcheck disable=SC3043 #https://github.com/koalaman/shellcheck/wiki/SC3043#exceptions
|
||||||
|
|
||||||
|
# Pi-hole: A black hole for Internet advertisements
|
||||||
|
# (c) 2017 Pi-hole, LLC (https://pi-hole.net)
|
||||||
|
# Network-wide ad blocking via your own hardware.
|
||||||
|
#
|
||||||
|
# Script to hold api functions for use in other scripts
|
||||||
|
#
|
||||||
|
# This file is copyright under the latest version of the EUPL.
|
||||||
|
# Please see LICENSE file for your rights under this license.
|
||||||
|
|
||||||
|
|
||||||
|
# The basic usage steps are
|
||||||
|
# 1) Test Availability of the API
|
||||||
|
# 2) Try to authenticate (read password if needed)
|
||||||
|
# 3) Get the data from the API endpoint
|
||||||
|
# 4) Delete the session
|
||||||
|
|
||||||
|
|
||||||
|
TestAPIAvailability() {
|
||||||
|
|
||||||
|
# as we are running locally, we can get the port value from FTL directly
|
||||||
|
local chaos_api_list availabilityResponse
|
||||||
|
|
||||||
|
# Query the API URLs from FTL using CHAOS TXT local.api.ftl
|
||||||
|
# The result is a space-separated enumeration of full URLs
|
||||||
|
# e.g., "http://localhost:80/api/" "https://localhost:443/api/"
|
||||||
|
chaos_api_list="$(dig +short chaos txt local.api.ftl @127.0.0.1)"
|
||||||
|
|
||||||
|
# If the query was not successful, the variable is empty
|
||||||
|
if [ -z "${chaos_api_list}" ]; then
|
||||||
|
echo "API not available. Please check connectivity"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Iterate over space-separated list of URLs
|
||||||
|
while [ -n "${chaos_api_list}" ]; do
|
||||||
|
# Get the first URL
|
||||||
|
API_URL="${chaos_api_list%% *}"
|
||||||
|
# Strip leading and trailing quotes
|
||||||
|
API_URL="${API_URL%\"}"
|
||||||
|
API_URL="${API_URL#\"}"
|
||||||
|
|
||||||
|
# Test if the API is available at this URL
|
||||||
|
availabilityResponse=$(curl -skS -o /dev/null -w "%{http_code}" "${API_URL}auth")
|
||||||
|
|
||||||
|
# Test if http status code was 200 (OK) or 401 (authentication required)
|
||||||
|
if [ ! "${availabilityResponse}" = 200 ] && [ ! "${availabilityResponse}" = 401 ]; then
|
||||||
|
# API is not available at this port/protocol combination
|
||||||
|
API_PORT=""
|
||||||
|
else
|
||||||
|
# API is available at this URL combination
|
||||||
|
|
||||||
|
if [ "${availabilityResponse}" = 200 ]; then
|
||||||
|
# API is available without authentication
|
||||||
|
needAuth=false
|
||||||
|
fi
|
||||||
|
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Remove the first URL from the list
|
||||||
|
local last_api_list
|
||||||
|
last_api_list="${chaos_api_list}"
|
||||||
|
chaos_api_list="${chaos_api_list#* }"
|
||||||
|
|
||||||
|
# If the list did not change, we are at the last element
|
||||||
|
if [ "${last_api_list}" = "${chaos_api_list}" ]; then
|
||||||
|
# Remove the last element
|
||||||
|
chaos_api_list=""
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# if API_PORT is empty, no working API port was found
|
||||||
|
if [ -n "${API_PORT}" ]; then
|
||||||
|
echo "API not available at: ${API_URL}"
|
||||||
|
echo "Exiting."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
LoginAPI() {
|
||||||
|
# If the API URL is not set, test the availability
|
||||||
|
if [ -z "${API_URL}" ]; then
|
||||||
|
TestAPIAvailability
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Exit early if authentication is not needed
|
||||||
|
if [ "${needAuth}" = false ]; then
|
||||||
|
if [ "${1}" = "verbose" ]; then
|
||||||
|
echo "API Authentication: Not needed"
|
||||||
|
fi
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Try to read the CLI password (if enabled and readable by the current user)
|
||||||
|
if [ -r /etc/pihole/cli_pw ]; then
|
||||||
|
password=$(cat /etc/pihole/cli_pw)
|
||||||
|
|
||||||
|
if [ "${1}" = "verbose" ]; then
|
||||||
|
echo "API Authentication: Trying to use CLI password"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Try to authenticate using the CLI password
|
||||||
|
Authentication "${1}"
|
||||||
|
|
||||||
|
elif [ "${1}" = "verbose" ]; then
|
||||||
|
echo "API Authentication: CLI password not available"
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# If this did not work, ask the user for the password
|
||||||
|
while [ "${validSession}" = false ] || [ -z "${validSession}" ] ; do
|
||||||
|
echo "Authentication failed. Please enter your Pi-hole password"
|
||||||
|
|
||||||
|
# secretly read the password
|
||||||
|
secretRead; printf '\n'
|
||||||
|
|
||||||
|
# Try to authenticate again
|
||||||
|
Authentication "${1}"
|
||||||
|
done
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Authentication() {
|
||||||
|
sessionResponse="$(curl -skS -X POST "${API_URL}auth" --user-agent "Pi-hole cli " --data "{\"password\":\"${password}\"}" )"
|
||||||
|
|
||||||
|
if [ -z "${sessionResponse}" ]; then
|
||||||
|
echo "No response from FTL server. Please check connectivity"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
# obtain validity and session ID from session response
|
||||||
|
validSession=$(echo "${sessionResponse}"| jq .session.valid 2>/dev/null)
|
||||||
|
SID=$(echo "${sessionResponse}"| jq --raw-output .session.sid 2>/dev/null)
|
||||||
|
|
||||||
|
if [ "${1}" = "verbose" ]; then
|
||||||
|
if [ "${validSession}" = true ]; then
|
||||||
|
echo "API Authentication: ${COL_GREEN}Success${COL_NC}"
|
||||||
|
else
|
||||||
|
echo "API Authentication: ${COL_RED}Failed${COL_NC}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
LogoutAPI() {
|
||||||
|
# if a valid Session exists (no password required or successful Authentication) and
|
||||||
|
# SID is not null (successful Authentication only), delete the session
|
||||||
|
if [ "${validSession}" = true ] && [ ! "${SID}" = null ]; then
|
||||||
|
# Try to delete the session. Omit the output, but get the http status code
|
||||||
|
deleteResponse=$(curl -skS -o /dev/null -w "%{http_code}" -X DELETE "${API_URL}auth" -H "Accept: application/json" -H "sid: ${SID}")
|
||||||
|
|
||||||
|
case "${deleteResponse}" in
|
||||||
|
"401") echo "Logout attempt without a valid session. Unauthorized!";;
|
||||||
|
"204") if [ "${1}" = "verbose" ]; then echo "API Logout: ${COL_GREEN}Success${COL_NC} (session deleted)"; fi;;
|
||||||
|
esac;
|
||||||
|
elif [ "${1}" = "verbose" ]; then
|
||||||
|
echo "API Logout: ${COL_GREEN}Success${COL_NC} (no valid session)"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
GetFTLData() {
|
||||||
|
local data response status
|
||||||
|
# get the data from querying the API as well as the http status code
|
||||||
|
response=$(curl -skS -w "%{http_code}" -X GET "${API_URL}$1" -H "Accept: application/json" -H "sid: ${SID}" )
|
||||||
|
|
||||||
|
# status are the last 3 characters
|
||||||
|
status="${response#"${response%???}"}"
|
||||||
|
# data is everything from response without the last 3 characters
|
||||||
|
data="${response%???}"
|
||||||
|
|
||||||
|
if [ "${2}" = "raw" ]; then
|
||||||
|
# return the raw response
|
||||||
|
echo "${response}"
|
||||||
|
else
|
||||||
|
# return only the data
|
||||||
|
if [ "${status}" = 200 ]; then
|
||||||
|
# response OK
|
||||||
|
echo "${data}"
|
||||||
|
else
|
||||||
|
# connection lost
|
||||||
|
echo "${status}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
PostFTLData() {
|
||||||
|
local data response status
|
||||||
|
# send the data to the API
|
||||||
|
response=$(curl -skS -w "%{http_code}" -X POST "${API_URL}$1" --data-raw "$2" -H "Accept: application/json" -H "sid: ${SID}" )
|
||||||
|
# data is everything from response without the last 3 characters
|
||||||
|
if [ "${3}" = "status" ]; then
|
||||||
|
# Keep the status code appended if requested
|
||||||
|
printf %s "${response}"
|
||||||
|
else
|
||||||
|
# Strip the status code
|
||||||
|
printf %s "${response%???}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
secretRead() {
|
||||||
|
|
||||||
|
# POSIX compliant function to read user-input and
|
||||||
|
# mask every character entered by (*)
|
||||||
|
#
|
||||||
|
# This is challenging, because in POSIX, `read` does not support
|
||||||
|
# `-s` option (suppressing the input) or
|
||||||
|
# `-n` option (reading n chars)
|
||||||
|
|
||||||
|
|
||||||
|
# This workaround changes the terminal characteristics to not echo input and later resets this option
|
||||||
|
# credits https://stackoverflow.com/a/4316765
|
||||||
|
# showing asterisk instead of password
|
||||||
|
# https://stackoverflow.com/a/24600839
|
||||||
|
# https://unix.stackexchange.com/a/464963
|
||||||
|
|
||||||
|
|
||||||
|
# Save current terminal settings (needed for later restore after password prompt)
|
||||||
|
stty_orig=$(stty -g)
|
||||||
|
|
||||||
|
stty -echo # do not echo user input
|
||||||
|
stty -icanon min 1 time 0 # disable canonical mode https://man7.org/linux/man-pages/man3/termios.3.html
|
||||||
|
|
||||||
|
unset password
|
||||||
|
unset key
|
||||||
|
unset charcount
|
||||||
|
charcount=0
|
||||||
|
while key=$(dd ibs=1 count=1 2>/dev/null); do #read one byte of input
|
||||||
|
if [ "${key}" = "$(printf '\0' | tr -d '\0')" ] ; then
|
||||||
|
# Enter - accept password
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
if [ "${key}" = "$(printf '\177')" ] ; then
|
||||||
|
# Backspace
|
||||||
|
if [ $charcount -gt 0 ] ; then
|
||||||
|
charcount=$((charcount-1))
|
||||||
|
printf '\b \b'
|
||||||
|
password="${password%?}"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# any other character
|
||||||
|
charcount=$((charcount+1))
|
||||||
|
printf '*'
|
||||||
|
password="$password$key"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# restore original terminal settings
|
||||||
|
stty "${stty_orig}"
|
||||||
|
}
|
||||||
|
|
||||||
|
apiFunc() {
|
||||||
|
local data response status status_col
|
||||||
|
|
||||||
|
# Authenticate with the API
|
||||||
|
LoginAPI verbose
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "Requesting: ${COL_PURPLE}GET ${COL_CYAN}${API_URL}${COL_YELLOW}$1${COL_NC}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Get the data from the API
|
||||||
|
response=$(GetFTLData "$1" raw)
|
||||||
|
|
||||||
|
# status are the last 3 characters
|
||||||
|
status="${response#"${response%???}"}"
|
||||||
|
# data is everything from response without the last 3 characters
|
||||||
|
data="${response%???}"
|
||||||
|
|
||||||
|
# Output the status (200 -> green, else red)
|
||||||
|
if [ "${status}" = 200 ]; then
|
||||||
|
status_col="${COL_GREEN}"
|
||||||
|
else
|
||||||
|
status_col="${COL_RED}"
|
||||||
|
fi
|
||||||
|
echo "Status: ${status_col}${status}${COL_NC}"
|
||||||
|
|
||||||
|
# Output the data. Format it with jq if available and data is actually JSON.
|
||||||
|
# Otherwise just print it
|
||||||
|
echo "Data:"
|
||||||
|
if command -v jq >/dev/null && echo "${data}" | jq . >/dev/null 2>&1; then
|
||||||
|
echo "${data}" | jq .
|
||||||
|
else
|
||||||
|
echo "${data}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Delete the session
|
||||||
|
LogoutAPI verbose
|
||||||
|
}
|
||||||
@@ -1,191 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
# (c) 2015 by Jacob Salmela
|
|
||||||
# This file is part of Pi-hole.
|
|
||||||
#
|
|
||||||
# Pi-hole is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation, either version 2 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
|
|
||||||
if [[ $# = 0 ]]; then
|
|
||||||
echo "Immediately blacklists one or more domains in the hosts file"
|
|
||||||
echo " "
|
|
||||||
echo "Usage: blacklist.sh domain1 [domain2 ...]"
|
|
||||||
echo " "
|
|
||||||
echo "Options:"
|
|
||||||
echo " -d, --delmode Remove domains from the blacklist"
|
|
||||||
echo " -nr, --noreload Update blacklist without refreshing dnsmasq"
|
|
||||||
echo " -f, --force Force updating of the hosts files, even if there are no changes"
|
|
||||||
echo " -q, --quiet output is less verbose"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
#globals
|
|
||||||
blacklist=/etc/pihole/blacklist.txt
|
|
||||||
adList=/etc/pihole/gravity.list
|
|
||||||
reload=true
|
|
||||||
addmode=true
|
|
||||||
force=false
|
|
||||||
versbose=true
|
|
||||||
domList=()
|
|
||||||
domToRemoveList=()
|
|
||||||
|
|
||||||
|
|
||||||
piholeIPfile=/tmp/piholeIP
|
|
||||||
piholeIPv6file=/etc/pihole/.useIPv6
|
|
||||||
|
|
||||||
# Otherwise, the IP address can be taken directly from the machine, which will happen when the script is run by the user and not the installation script
|
|
||||||
IPv4dev=$(ip route get 8.8.8.8 | awk '{for(i=1;i<=NF;i++)if($i~/dev/)print $(i+1)}')
|
|
||||||
piholeIPCIDR=$(ip -o -f inet addr show dev $IPv4dev | awk '{print $4}' | awk 'END {print}')
|
|
||||||
piholeIP=${piholeIPCIDR%/*}
|
|
||||||
|
|
||||||
modifyHost=false
|
|
||||||
|
|
||||||
|
|
||||||
if [[ -f $piholeIPv6file ]];then
|
|
||||||
# If the file exists, then the user previously chose to use IPv6 in the automated installer
|
|
||||||
piholeIPv6=$(ip -6 route get 2001:4860:4860::8888 | awk -F " " '{ for(i=1;i<=NF;i++) if ($i == "src") print $(i+1) }')
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
function HandleOther(){
|
|
||||||
#check validity of domain
|
|
||||||
validDomain=$(echo $1 | perl -ne'print if /\b((?=[a-z0-9-]{1,63}\.)(xn--)?[a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,63}\b/')
|
|
||||||
|
|
||||||
if [ -z "$validDomain" ]; then
|
|
||||||
echo $1 is not a valid argument or domain name
|
|
||||||
else
|
|
||||||
domList=("${domList[@]}" $validDomain)
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
function PopBlacklistFile(){
|
|
||||||
#check blacklist file exists, and if not, create it
|
|
||||||
if [[ ! -f $blacklist ]];then
|
|
||||||
touch $blacklist
|
|
||||||
fi
|
|
||||||
for dom in "${domList[@]}"
|
|
||||||
do
|
|
||||||
if $addmode; then
|
|
||||||
AddDomain $dom
|
|
||||||
else
|
|
||||||
RemoveDomain $dom
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
function AddDomain(){
|
|
||||||
#| sed 's/\./\\./g'
|
|
||||||
bool=false
|
|
||||||
grep -Ex -q "$1" $blacklist || bool=true
|
|
||||||
if $bool; then
|
|
||||||
#domain not found in the blacklist file, add it!
|
|
||||||
if $versbose; then
|
|
||||||
echo -n "::: Adding $1 to blacklist file..."
|
|
||||||
fi
|
|
||||||
echo $1 >> $blacklist
|
|
||||||
modifyHost=true
|
|
||||||
echo " done!"
|
|
||||||
else
|
|
||||||
if $versbose; then
|
|
||||||
echo "::: $1 already exists in blacklist.txt! No need to add"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
function RemoveDomain(){
|
|
||||||
|
|
||||||
bool=false
|
|
||||||
grep -Ex -q "$1" $blacklist || bool=true
|
|
||||||
if $bool; then
|
|
||||||
#Domain is not in the blacklist file, no need to Remove
|
|
||||||
if $versbose; then
|
|
||||||
echo "::: $1 is NOT blacklisted! No need to remove"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
#Domain is in the blacklist file, add to a temporary array
|
|
||||||
if $versbose; then
|
|
||||||
echo "::: Un-blacklisting $dom..."
|
|
||||||
fi
|
|
||||||
domToRemoveList=("${domToRemoveList[@]}" $1)
|
|
||||||
modifyHost=true
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
function ModifyHostFile(){
|
|
||||||
if $addmode; then
|
|
||||||
#add domains to the hosts file
|
|
||||||
if [[ -r $blacklist ]];then
|
|
||||||
numberOf=$(cat $blacklist | sed '/^\s*$/d' | wc -l)
|
|
||||||
plural=; [[ "$numberOf" != "1" ]] && plural=s
|
|
||||||
echo ":::"
|
|
||||||
echo -n "::: Modifying HOSTS file to blacklist $numberOf domain${plural}..."
|
|
||||||
if [[ -n $piholeIPv6 ]];then
|
|
||||||
cat $blacklist | awk -v ipv4addr="$piholeIP" -v ipv6addr="$piholeIPv6" '{sub(/\r$/,""); print ipv4addr" "$0"\n"ipv6addr" "$0}' >> $adList
|
|
||||||
else
|
|
||||||
cat $blacklist | awk -v ipv4addr="$piholeIP" '{sub(/\r$/,""); print ipv4addr" "$0}' >>$adList
|
|
||||||
fi
|
|
||||||
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
|
|
||||||
echo ":::"
|
|
||||||
for dom in "${domToRemoveList[@]}"
|
|
||||||
do
|
|
||||||
#we need to remove the domains from the blacklist file and the host file
|
|
||||||
echo "::: $dom"
|
|
||||||
echo -n "::: removing from HOSTS file..."
|
|
||||||
echo $dom | sed 's/\./\\./g' | xargs -I {} perl -i -ne'print unless /[^.]'{}'(?!.)/;' $adList
|
|
||||||
echo " done!"
|
|
||||||
echo -n "::: removing from blackist.txt..."
|
|
||||||
echo $dom | sed 's/\./\\./g' | xargs -I {} perl -i -ne'print unless /'{}'(?!.)/;' $blacklist
|
|
||||||
echo " done!"
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function Reload() {
|
|
||||||
# Reload hosts file
|
|
||||||
echo ":::"
|
|
||||||
echo -n "::: Refresh lists in dnsmasq..."
|
|
||||||
|
|
||||||
dnsmasqPid=$(pidof dnsmasq)
|
|
||||||
|
|
||||||
if [[ $dnsmasqPid ]]; then
|
|
||||||
# service already running - reload config
|
|
||||||
sudo kill -HUP $dnsmasqPid
|
|
||||||
else
|
|
||||||
# service not running, start it up
|
|
||||||
sudo service dnsmasq start
|
|
||||||
fi
|
|
||||||
echo " done!"
|
|
||||||
}
|
|
||||||
|
|
||||||
###################################################
|
|
||||||
|
|
||||||
for var in "$@"
|
|
||||||
do
|
|
||||||
case "$var" in
|
|
||||||
"-nr"| "--noreload" ) reload=false;;
|
|
||||||
"-d" | "--delmode" ) addmode=false;;
|
|
||||||
"-f" | "--force" ) force=true;;
|
|
||||||
"-q" | "--quiet" ) versbose=false;;
|
|
||||||
* ) HandleOther $var;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
PopBlacklistFile
|
|
||||||
|
|
||||||
if $modifyHost || $force; then
|
|
||||||
ModifyHostFile
|
|
||||||
else
|
|
||||||
if $versbose; then
|
|
||||||
echo "::: No changes need to be made"
|
|
||||||
fi
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if $reload; then
|
|
||||||
Reload
|
|
||||||
fi
|
|
||||||
@@ -1,135 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
# (c) 2015 by Jacob Salmela
|
|
||||||
# This file is part of Pi-hole.
|
|
||||||
#
|
|
||||||
# Pi-hole is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation, either version 2 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
|
|
||||||
|
|
||||||
#Functions##############################################################################################################
|
|
||||||
piLog="/var/log/pihole.log"
|
|
||||||
gravity="/etc/pihole/gravity.list"
|
|
||||||
|
|
||||||
today=$(date "+%b %e")
|
|
||||||
|
|
||||||
function CalcBlockedDomains(){
|
|
||||||
CheckIPv6
|
|
||||||
if [ -e "$gravity" ]; then
|
|
||||||
#Are we IPV6 or IPV4?
|
|
||||||
if [[ -n $piholeIPv6 ]];then
|
|
||||||
#We are IPV6
|
|
||||||
blockedDomainsTotal=$(wc -l /etc/pihole/gravity.list | awk '{print $1/2}')
|
|
||||||
else
|
|
||||||
#We are IPV4
|
|
||||||
blockedDomainsTotal=$(wc -l /etc/pihole/gravity.list | awk '{print $1}')
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
blockedDomainsTotal="Err."
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
function CalcQueriesToday(){
|
|
||||||
if [ -e "$piLog" ];then
|
|
||||||
queriesToday=$(cat "$piLog" | grep "$today" | awk '/query/ {print $6}' | wc -l)
|
|
||||||
else
|
|
||||||
queriesToday="Err."
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
function CalcblockedToday(){
|
|
||||||
if [ -e "$piLog" ] && [ -e "$gravity" ];then
|
|
||||||
blockedToday=$(cat $piLog | awk '/\/etc\/pihole\/gravity.list/ && !/address/ {print $6}' | wc -l)
|
|
||||||
else
|
|
||||||
blockedToday="Err."
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
function CalcPercentBlockedToday(){
|
|
||||||
if [ "$queriesToday" != "Err." ] && [ "$blockedToday" != "Err." ]; then
|
|
||||||
#scale 2 rounds the number down, so we'll do scale 4 and then trim the last 2 zeros
|
|
||||||
percentBlockedToday=$(echo "scale=4; $blockedToday/$queriesToday*100" | bc)
|
|
||||||
percentBlockedToday=$(sed 's/.\{2\}$//' <<< "$percentBlockedToday")
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
function CheckIPv6(){
|
|
||||||
piholeIPv6file="/etc/pihole/.useIPv6"
|
|
||||||
if [[ -f $piholeIPv6file ]];then
|
|
||||||
# If the file exists, then the user previously chose to use IPv6 in the automated installer
|
|
||||||
piholeIPv6=$(ip -6 route get 2001:4860:4860::8888 | awk -F " " '{ for(i=1;i<=NF;i++) if ($i == "src") print $(i+1) }')
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
function outputJSON(){
|
|
||||||
CalcQueriesToday
|
|
||||||
CalcblockedToday
|
|
||||||
CalcPercentBlockedToday
|
|
||||||
|
|
||||||
CalcBlockedDomains
|
|
||||||
|
|
||||||
printf '{"domains_being_blocked":"%s","dns_queries_today":"%s","ads_blocked_today":"%s","ads_percentage_today":"%s"}\n' "$blockedDomainsTotal" "$queriesToday" "$blockedToday" "$percentBlockedToday"
|
|
||||||
}
|
|
||||||
|
|
||||||
function normalChrono(){
|
|
||||||
for (( ; ; ))
|
|
||||||
do
|
|
||||||
clear
|
|
||||||
# Displays a colorful Pi-hole logo
|
|
||||||
toilet -f small -F gay Pi-hole
|
|
||||||
echo " $(ifconfig eth0 | awk '/inet addr/ {print $2}' | cut -d':' -f2)"
|
|
||||||
echo ""
|
|
||||||
uptime | cut -d' ' -f11-
|
|
||||||
echo "-------------------------------"
|
|
||||||
# Uncomment to continually read the log file and display the current domain being blocked
|
|
||||||
#tail -f /var/log/pihole.log | awk '/\/etc\/pihole\/gravity.list/ {if ($7 != "address" && $7 != "name" && $7 != "/etc/pihole/gravity.list") print $7; else;}'
|
|
||||||
|
|
||||||
#uncomment next 4 lines to use original query count calculation
|
|
||||||
#today=$(date "+%b %e")
|
|
||||||
#todaysQueryCount=$(cat /var/log/pihole.log | grep "$today" | awk '/query/ {print $7}' | wc -l)
|
|
||||||
#todaysQueryCountV4=$(cat /var/log/pihole.log | grep "$today" | awk '/query/ && /\[A\]/ {print $7}' | wc -l)
|
|
||||||
#todaysQueryCountV6=$(cat /var/log/pihole.log | grep "$today" | awk '/query/ && /\[AAAA\]/ {print $7}' | wc -l)
|
|
||||||
|
|
||||||
|
|
||||||
CalcQueriesToday
|
|
||||||
CalcblockedToday
|
|
||||||
CalcPercentBlockedToday
|
|
||||||
|
|
||||||
CalcBlockedDomains
|
|
||||||
|
|
||||||
echo "Blocking: $blockedDomainsTotal"
|
|
||||||
#below commented line does not add up to todaysQueryCount
|
|
||||||
#echo "Queries: $todaysQueryCountV4 / $todaysQueryCountV6"
|
|
||||||
echo "Queries: $queriesToday" #same total calculation as dashboard
|
|
||||||
echo "Pi-holed: $blockedToday ($percentBlockedToday%)"
|
|
||||||
|
|
||||||
sleep 5
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
function displayHelp(){
|
|
||||||
echo "Displays stats about your piHole!"
|
|
||||||
echo " "
|
|
||||||
echo "Usage: chronometer.sh [optional:-j]"
|
|
||||||
echo "Note: If no option is passed, then stats are displayed on screen, updated every 5 seconds"
|
|
||||||
echo " "
|
|
||||||
echo "Options:"
|
|
||||||
echo " -j, --json output stats as JSON formatted string"
|
|
||||||
echo " -h, --help display this help text"
|
|
||||||
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
if [[ $# = 0 ]]; then
|
|
||||||
normalChrono
|
|
||||||
fi
|
|
||||||
|
|
||||||
for var in "$@"
|
|
||||||
do
|
|
||||||
case "$var" in
|
|
||||||
"-j" | "--json" ) outputJSON;;
|
|
||||||
"-h" | "--help" ) displayHelp;;
|
|
||||||
* ) exit 1;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
154
advanced/Scripts/database_migration/gravity-db.sh
Executable file
154
advanced/Scripts/database_migration/gravity-db.sh
Executable file
@@ -0,0 +1,154 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# shellcheck disable=SC1090
|
||||||
|
|
||||||
|
# Pi-hole: A black hole for Internet advertisements
|
||||||
|
# (c) 2019 Pi-hole, LLC (https://pi-hole.net)
|
||||||
|
# Network-wide ad blocking via your own hardware.
|
||||||
|
#
|
||||||
|
# Updates gravity.db database
|
||||||
|
#
|
||||||
|
# This file is copyright under the latest version of the EUPL.
|
||||||
|
# Please see LICENSE file for your rights under this license.
|
||||||
|
|
||||||
|
readonly scriptPath="/etc/.pihole/advanced/Scripts/database_migration/gravity"
|
||||||
|
|
||||||
|
upgrade_gravityDB(){
|
||||||
|
local database piholeDir version
|
||||||
|
database="${1}"
|
||||||
|
piholeDir="${2}"
|
||||||
|
|
||||||
|
# Exit early if the database does not exist (e.g. in CI tests)
|
||||||
|
if [[ ! -f "${database}" ]]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Get database version
|
||||||
|
version="$(pihole-FTL sqlite3 -ni "${database}" "SELECT \"value\" FROM \"info\" WHERE \"property\" = 'version';")"
|
||||||
|
|
||||||
|
if [[ "$version" == "1" ]]; then
|
||||||
|
# This migration script upgraded the gravity.db file by
|
||||||
|
# adding the domain_audit table. It is now a no-op
|
||||||
|
echo -e " ${INFO} Upgrading gravity database from version 1 to 2"
|
||||||
|
pihole-FTL sqlite3 -ni "${database}" < "${scriptPath}/1_to_2.sql"
|
||||||
|
version=2
|
||||||
|
fi
|
||||||
|
if [[ "$version" == "2" ]]; then
|
||||||
|
# This migration script upgrades the gravity.db file by
|
||||||
|
# renaming the regex table to regex_blacklist, and
|
||||||
|
# creating a new regex_whitelist table + corresponding linking table and views
|
||||||
|
echo -e " ${INFO} Upgrading gravity database from version 2 to 3"
|
||||||
|
pihole-FTL sqlite3 -ni "${database}" < "${scriptPath}/2_to_3.sql"
|
||||||
|
version=3
|
||||||
|
fi
|
||||||
|
if [[ "$version" == "3" ]]; then
|
||||||
|
# This migration script unifies the formally separated domain
|
||||||
|
# lists into a single table with a UNIQUE domain constraint
|
||||||
|
echo -e " ${INFO} Upgrading gravity database from version 3 to 4"
|
||||||
|
pihole-FTL sqlite3 -ni "${database}" < "${scriptPath}/3_to_4.sql"
|
||||||
|
version=4
|
||||||
|
fi
|
||||||
|
if [[ "$version" == "4" ]]; then
|
||||||
|
# This migration script upgrades the gravity and list views
|
||||||
|
# implementing necessary changes for per-client blocking
|
||||||
|
echo -e " ${INFO} Upgrading gravity database from version 4 to 5"
|
||||||
|
pihole-FTL sqlite3 -ni "${database}" < "${scriptPath}/4_to_5.sql"
|
||||||
|
version=5
|
||||||
|
fi
|
||||||
|
if [[ "$version" == "5" ]]; then
|
||||||
|
# This migration script upgrades the adlist view
|
||||||
|
# to return an ID used in gravity.sh
|
||||||
|
echo -e " ${INFO} Upgrading gravity database from version 5 to 6"
|
||||||
|
pihole-FTL sqlite3 -ni "${database}" < "${scriptPath}/5_to_6.sql"
|
||||||
|
version=6
|
||||||
|
fi
|
||||||
|
if [[ "$version" == "6" ]]; then
|
||||||
|
# This migration script adds a special group with ID 0
|
||||||
|
# which is automatically associated to all clients not
|
||||||
|
# having their own group assignments
|
||||||
|
echo -e " ${INFO} Upgrading gravity database from version 6 to 7"
|
||||||
|
pihole-FTL sqlite3 -ni "${database}" < "${scriptPath}/6_to_7.sql"
|
||||||
|
version=7
|
||||||
|
fi
|
||||||
|
if [[ "$version" == "7" ]]; then
|
||||||
|
# This migration script recreated the group table
|
||||||
|
# to ensure uniqueness on the group name
|
||||||
|
# We also add date_added and date_modified columns
|
||||||
|
echo -e " ${INFO} Upgrading gravity database from version 7 to 8"
|
||||||
|
pihole-FTL sqlite3 -ni "${database}" < "${scriptPath}/7_to_8.sql"
|
||||||
|
version=8
|
||||||
|
fi
|
||||||
|
if [[ "$version" == "8" ]]; then
|
||||||
|
# This migration fixes some issues that were introduced
|
||||||
|
# in the previous migration script.
|
||||||
|
echo -e " ${INFO} Upgrading gravity database from version 8 to 9"
|
||||||
|
pihole-FTL sqlite3 -ni "${database}" < "${scriptPath}/8_to_9.sql"
|
||||||
|
version=9
|
||||||
|
fi
|
||||||
|
if [[ "$version" == "9" ]]; then
|
||||||
|
# This migration drops unused tables and creates triggers to remove
|
||||||
|
# obsolete groups assignments when the linked items are deleted
|
||||||
|
echo -e " ${INFO} Upgrading gravity database from version 9 to 10"
|
||||||
|
pihole-FTL sqlite3 -ni "${database}" < "${scriptPath}/9_to_10.sql"
|
||||||
|
version=10
|
||||||
|
fi
|
||||||
|
if [[ "$version" == "10" ]]; then
|
||||||
|
# This adds timestamp and an optional comment field to the client table
|
||||||
|
# These fields are only temporary and will be replaces by the columns
|
||||||
|
# defined in gravity.db.sql during gravity swapping. We add them here
|
||||||
|
# to keep the copying process generic (needs the same columns in both the
|
||||||
|
# source and the destination databases).
|
||||||
|
echo -e " ${INFO} Upgrading gravity database from version 10 to 11"
|
||||||
|
pihole-FTL sqlite3 -ni "${database}" < "${scriptPath}/10_to_11.sql"
|
||||||
|
version=11
|
||||||
|
fi
|
||||||
|
if [[ "$version" == "11" ]]; then
|
||||||
|
# Rename group 0 from "Unassociated" to "Default"
|
||||||
|
echo -e " ${INFO} Upgrading gravity database from version 11 to 12"
|
||||||
|
pihole-FTL sqlite3 -ni "${database}" < "${scriptPath}/11_to_12.sql"
|
||||||
|
version=12
|
||||||
|
fi
|
||||||
|
if [[ "$version" == "12" ]]; then
|
||||||
|
# Add column date_updated to adlist table
|
||||||
|
echo -e " ${INFO} Upgrading gravity database from version 12 to 13"
|
||||||
|
pihole-FTL sqlite3 -ni "${database}" < "${scriptPath}/12_to_13.sql"
|
||||||
|
version=13
|
||||||
|
fi
|
||||||
|
if [[ "$version" == "13" ]]; then
|
||||||
|
# Add columns number and status to adlist table
|
||||||
|
echo -e " ${INFO} Upgrading gravity database from version 13 to 14"
|
||||||
|
pihole-FTL sqlite3 -ni "${database}" < "${scriptPath}/13_to_14.sql"
|
||||||
|
version=14
|
||||||
|
fi
|
||||||
|
if [[ "$version" == "14" ]]; then
|
||||||
|
# Changes the vw_adlist created in 5_to_6
|
||||||
|
echo -e " ${INFO} Upgrading gravity database from version 14 to 15"
|
||||||
|
pihole-FTL sqlite3 -ni "${database}" < "${scriptPath}/14_to_15.sql"
|
||||||
|
version=15
|
||||||
|
fi
|
||||||
|
if [[ "$version" == "15" ]]; then
|
||||||
|
# Add column abp_entries to adlist table
|
||||||
|
echo -e " ${INFO} Upgrading gravity database from version 15 to 16"
|
||||||
|
pihole-FTL sqlite3 -ni "${database}" < "${scriptPath}/15_to_16.sql"
|
||||||
|
version=16
|
||||||
|
fi
|
||||||
|
if [[ "$version" == "16" ]]; then
|
||||||
|
# Add antigravity table
|
||||||
|
# Add column type to adlist table (to support adlist types)
|
||||||
|
echo -e " ${INFO} Upgrading gravity database from version 16 to 17"
|
||||||
|
pihole-FTL sqlite3 -ni "${database}" < "${scriptPath}/16_to_17.sql"
|
||||||
|
version=17
|
||||||
|
fi
|
||||||
|
if [[ "$version" == "17" ]]; then
|
||||||
|
# Add adlist.id to vw_gravity and vw_antigravity
|
||||||
|
echo -e " ${INFO} Upgrading gravity database from version 17 to 18"
|
||||||
|
pihole-FTL sqlite3 -ni "${database}" < "${scriptPath}/17_to_18.sql"
|
||||||
|
version=18
|
||||||
|
fi
|
||||||
|
if [[ "$version" == "18" ]]; then
|
||||||
|
# Modify DELETE triggers to delete BEFORE instead of AFTER to prevent
|
||||||
|
# foreign key constraint violations
|
||||||
|
echo -e " ${INFO} Upgrading gravity database from version 18 to 19"
|
||||||
|
pihole-FTL sqlite3 -ni "${database}" < "${scriptPath}/18_to_19.sql"
|
||||||
|
version=19
|
||||||
|
fi
|
||||||
|
}
|
||||||
16
advanced/Scripts/database_migration/gravity/10_to_11.sql
Normal file
16
advanced/Scripts/database_migration/gravity/10_to_11.sql
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
.timeout 30000
|
||||||
|
|
||||||
|
BEGIN TRANSACTION;
|
||||||
|
|
||||||
|
ALTER TABLE client ADD COLUMN date_added INTEGER;
|
||||||
|
ALTER TABLE client ADD COLUMN date_modified INTEGER;
|
||||||
|
ALTER TABLE client ADD COLUMN comment TEXT;
|
||||||
|
|
||||||
|
CREATE TRIGGER tr_client_update AFTER UPDATE ON client
|
||||||
|
BEGIN
|
||||||
|
UPDATE client SET date_modified = (cast(strftime('%s', 'now') as int)) WHERE id = NEW.id;
|
||||||
|
END;
|
||||||
|
|
||||||
|
UPDATE info SET value = 11 WHERE property = 'version';
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
19
advanced/Scripts/database_migration/gravity/11_to_12.sql
Normal file
19
advanced/Scripts/database_migration/gravity/11_to_12.sql
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
.timeout 30000
|
||||||
|
|
||||||
|
PRAGMA FOREIGN_KEYS=OFF;
|
||||||
|
|
||||||
|
BEGIN TRANSACTION;
|
||||||
|
|
||||||
|
UPDATE "group" SET name = 'Default' WHERE id = 0;
|
||||||
|
UPDATE "group" SET description = 'The default group' WHERE id = 0;
|
||||||
|
|
||||||
|
DROP TRIGGER IF EXISTS tr_group_zero;
|
||||||
|
|
||||||
|
CREATE TRIGGER tr_group_zero AFTER DELETE ON "group"
|
||||||
|
BEGIN
|
||||||
|
INSERT OR IGNORE INTO "group" (id,enabled,name,description) VALUES (0,1,'Default','The default group');
|
||||||
|
END;
|
||||||
|
|
||||||
|
UPDATE info SET value = 12 WHERE property = 'version';
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
18
advanced/Scripts/database_migration/gravity/12_to_13.sql
Normal file
18
advanced/Scripts/database_migration/gravity/12_to_13.sql
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
.timeout 30000
|
||||||
|
|
||||||
|
PRAGMA FOREIGN_KEYS=OFF;
|
||||||
|
|
||||||
|
BEGIN TRANSACTION;
|
||||||
|
|
||||||
|
ALTER TABLE adlist ADD COLUMN date_updated INTEGER;
|
||||||
|
|
||||||
|
DROP TRIGGER tr_adlist_update;
|
||||||
|
|
||||||
|
CREATE TRIGGER tr_adlist_update AFTER UPDATE OF address,enabled,comment ON adlist
|
||||||
|
BEGIN
|
||||||
|
UPDATE adlist SET date_modified = (cast(strftime('%s', 'now') as int)) WHERE id = NEW.id;
|
||||||
|
END;
|
||||||
|
|
||||||
|
UPDATE info SET value = 13 WHERE property = 'version';
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
13
advanced/Scripts/database_migration/gravity/13_to_14.sql
Normal file
13
advanced/Scripts/database_migration/gravity/13_to_14.sql
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
.timeout 30000
|
||||||
|
|
||||||
|
PRAGMA FOREIGN_KEYS=OFF;
|
||||||
|
|
||||||
|
BEGIN TRANSACTION;
|
||||||
|
|
||||||
|
ALTER TABLE adlist ADD COLUMN number INTEGER NOT NULL DEFAULT 0;
|
||||||
|
ALTER TABLE adlist ADD COLUMN invalid_domains INTEGER NOT NULL DEFAULT 0;
|
||||||
|
ALTER TABLE adlist ADD COLUMN status INTEGER NOT NULL DEFAULT 0;
|
||||||
|
|
||||||
|
UPDATE info SET value = 14 WHERE property = 'version';
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
15
advanced/Scripts/database_migration/gravity/14_to_15.sql
Normal file
15
advanced/Scripts/database_migration/gravity/14_to_15.sql
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
.timeout 30000
|
||||||
|
|
||||||
|
PRAGMA FOREIGN_KEYS=OFF;
|
||||||
|
|
||||||
|
BEGIN TRANSACTION;
|
||||||
|
DROP VIEW vw_adlist;
|
||||||
|
|
||||||
|
CREATE VIEW vw_adlist AS SELECT DISTINCT address, id
|
||||||
|
FROM adlist
|
||||||
|
WHERE enabled = 1
|
||||||
|
ORDER BY id;
|
||||||
|
|
||||||
|
UPDATE info SET value = 15 WHERE property = 'version';
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
11
advanced/Scripts/database_migration/gravity/15_to_16.sql
Normal file
11
advanced/Scripts/database_migration/gravity/15_to_16.sql
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
.timeout 30000
|
||||||
|
|
||||||
|
PRAGMA FOREIGN_KEYS=OFF;
|
||||||
|
|
||||||
|
BEGIN TRANSACTION;
|
||||||
|
|
||||||
|
ALTER TABLE adlist ADD COLUMN abp_entries INTEGER NOT NULL DEFAULT 0;
|
||||||
|
|
||||||
|
UPDATE info SET value = 16 WHERE property = 'version';
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
33
advanced/Scripts/database_migration/gravity/16_to_17.sql
Normal file
33
advanced/Scripts/database_migration/gravity/16_to_17.sql
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
.timeout 30000
|
||||||
|
|
||||||
|
PRAGMA FOREIGN_KEYS=OFF;
|
||||||
|
|
||||||
|
BEGIN TRANSACTION;
|
||||||
|
|
||||||
|
ALTER TABLE adlist ADD COLUMN type INTEGER NOT NULL DEFAULT 0;
|
||||||
|
|
||||||
|
UPDATE adlist SET type = 0;
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS antigravity
|
||||||
|
(
|
||||||
|
domain TEXT NOT NULL,
|
||||||
|
adlist_id INTEGER NOT NULL REFERENCES adlist (id)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE VIEW vw_antigravity AS SELECT domain, adlist_by_group.group_id AS group_id
|
||||||
|
FROM antigravity
|
||||||
|
LEFT JOIN adlist_by_group ON adlist_by_group.adlist_id = antigravity.adlist_id
|
||||||
|
LEFT JOIN adlist ON adlist.id = antigravity.adlist_id
|
||||||
|
LEFT JOIN "group" ON "group".id = adlist_by_group.group_id
|
||||||
|
WHERE adlist.enabled = 1 AND (adlist_by_group.group_id IS NULL OR "group".enabled = 1) AND adlist.type = 1;
|
||||||
|
|
||||||
|
DROP VIEW vw_adlist;
|
||||||
|
|
||||||
|
CREATE VIEW vw_adlist AS SELECT DISTINCT address, id, type
|
||||||
|
FROM adlist
|
||||||
|
WHERE enabled = 1
|
||||||
|
ORDER BY id;
|
||||||
|
|
||||||
|
UPDATE info SET value = 17 WHERE property = 'version';
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
25
advanced/Scripts/database_migration/gravity/17_to_18.sql
Normal file
25
advanced/Scripts/database_migration/gravity/17_to_18.sql
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
.timeout 30000
|
||||||
|
|
||||||
|
PRAGMA FOREIGN_KEYS=OFF;
|
||||||
|
|
||||||
|
BEGIN TRANSACTION;
|
||||||
|
|
||||||
|
DROP VIEW vw_gravity;
|
||||||
|
CREATE VIEW vw_gravity AS SELECT domain, adlist.id AS adlist_id, adlist_by_group.group_id AS group_id
|
||||||
|
FROM gravity
|
||||||
|
LEFT JOIN adlist_by_group ON adlist_by_group.adlist_id = gravity.adlist_id
|
||||||
|
LEFT JOIN adlist ON adlist.id = gravity.adlist_id
|
||||||
|
LEFT JOIN "group" ON "group".id = adlist_by_group.group_id
|
||||||
|
WHERE adlist.enabled = 1 AND (adlist_by_group.group_id IS NULL OR "group".enabled = 1);
|
||||||
|
|
||||||
|
DROP VIEW vw_antigravity;
|
||||||
|
CREATE VIEW vw_antigravity AS SELECT domain, adlist.id AS adlist_id, adlist_by_group.group_id AS group_id
|
||||||
|
FROM antigravity
|
||||||
|
LEFT JOIN adlist_by_group ON adlist_by_group.adlist_id = antigravity.adlist_id
|
||||||
|
LEFT JOIN adlist ON adlist.id = antigravity.adlist_id
|
||||||
|
LEFT JOIN "group" ON "group".id = adlist_by_group.group_id
|
||||||
|
WHERE adlist.enabled = 1 AND (adlist_by_group.group_id IS NULL OR "group".enabled = 1) AND adlist.type = 1;
|
||||||
|
|
||||||
|
UPDATE info SET value = 18 WHERE property = 'version';
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
27
advanced/Scripts/database_migration/gravity/18_to_19.sql
Normal file
27
advanced/Scripts/database_migration/gravity/18_to_19.sql
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
.timeout 30000
|
||||||
|
|
||||||
|
PRAGMA FOREIGN_KEYS=OFF;
|
||||||
|
|
||||||
|
BEGIN TRANSACTION;
|
||||||
|
|
||||||
|
DROP TRIGGER tr_domainlist_delete;
|
||||||
|
CREATE TRIGGER tr_domainlist_delete BEFORE DELETE ON domainlist
|
||||||
|
BEGIN
|
||||||
|
DELETE FROM domainlist_by_group WHERE domainlist_id = OLD.id;
|
||||||
|
END;
|
||||||
|
|
||||||
|
DROP TRIGGER tr_adlist_delete;
|
||||||
|
CREATE TRIGGER tr_adlist_delete BEFORE DELETE ON adlist
|
||||||
|
BEGIN
|
||||||
|
DELETE FROM adlist_by_group WHERE adlist_id = OLD.id;
|
||||||
|
END;
|
||||||
|
|
||||||
|
DROP TRIGGER tr_client_delete;
|
||||||
|
CREATE TRIGGER tr_client_delete BEFORE DELETE ON client
|
||||||
|
BEGIN
|
||||||
|
DELETE FROM client_by_group WHERE client_id = OLD.id;
|
||||||
|
END;
|
||||||
|
|
||||||
|
UPDATE info SET value = 19 WHERE property = 'version';
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
7
advanced/Scripts/database_migration/gravity/1_to_2.sql
Normal file
7
advanced/Scripts/database_migration/gravity/1_to_2.sql
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
.timeout 30000
|
||||||
|
|
||||||
|
BEGIN TRANSACTION;
|
||||||
|
|
||||||
|
UPDATE info SET value = 2 WHERE property = 'version';
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
65
advanced/Scripts/database_migration/gravity/2_to_3.sql
Normal file
65
advanced/Scripts/database_migration/gravity/2_to_3.sql
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
.timeout 30000
|
||||||
|
|
||||||
|
PRAGMA FOREIGN_KEYS=OFF;
|
||||||
|
|
||||||
|
BEGIN TRANSACTION;
|
||||||
|
|
||||||
|
ALTER TABLE regex RENAME TO regex_blacklist;
|
||||||
|
|
||||||
|
CREATE TABLE regex_blacklist_by_group
|
||||||
|
(
|
||||||
|
regex_blacklist_id INTEGER NOT NULL REFERENCES regex_blacklist (id),
|
||||||
|
group_id INTEGER NOT NULL REFERENCES "group" (id),
|
||||||
|
PRIMARY KEY (regex_blacklist_id, group_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO regex_blacklist_by_group SELECT * FROM regex_by_group;
|
||||||
|
DROP TABLE regex_by_group;
|
||||||
|
DROP VIEW vw_regex;
|
||||||
|
DROP TRIGGER tr_regex_update;
|
||||||
|
|
||||||
|
CREATE VIEW vw_regex_blacklist AS SELECT DISTINCT domain
|
||||||
|
FROM regex_blacklist
|
||||||
|
LEFT JOIN regex_blacklist_by_group ON regex_blacklist_by_group.regex_blacklist_id = regex_blacklist.id
|
||||||
|
LEFT JOIN "group" ON "group".id = regex_blacklist_by_group.group_id
|
||||||
|
WHERE regex_blacklist.enabled = 1 AND (regex_blacklist_by_group.group_id IS NULL OR "group".enabled = 1)
|
||||||
|
ORDER BY regex_blacklist.id;
|
||||||
|
|
||||||
|
CREATE TRIGGER tr_regex_blacklist_update AFTER UPDATE ON regex_blacklist
|
||||||
|
BEGIN
|
||||||
|
UPDATE regex_blacklist SET date_modified = (cast(strftime('%s', 'now') as int)) WHERE domain = NEW.domain;
|
||||||
|
END;
|
||||||
|
|
||||||
|
CREATE TABLE regex_whitelist
|
||||||
|
(
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
domain TEXT UNIQUE NOT NULL,
|
||||||
|
enabled BOOLEAN NOT NULL DEFAULT 1,
|
||||||
|
date_added INTEGER NOT NULL DEFAULT (cast(strftime('%s', 'now') as int)),
|
||||||
|
date_modified INTEGER NOT NULL DEFAULT (cast(strftime('%s', 'now') as int)),
|
||||||
|
comment TEXT
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE regex_whitelist_by_group
|
||||||
|
(
|
||||||
|
regex_whitelist_id INTEGER NOT NULL REFERENCES regex_whitelist (id),
|
||||||
|
group_id INTEGER NOT NULL REFERENCES "group" (id),
|
||||||
|
PRIMARY KEY (regex_whitelist_id, group_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE VIEW vw_regex_whitelist AS SELECT DISTINCT domain
|
||||||
|
FROM regex_whitelist
|
||||||
|
LEFT JOIN regex_whitelist_by_group ON regex_whitelist_by_group.regex_whitelist_id = regex_whitelist.id
|
||||||
|
LEFT JOIN "group" ON "group".id = regex_whitelist_by_group.group_id
|
||||||
|
WHERE regex_whitelist.enabled = 1 AND (regex_whitelist_by_group.group_id IS NULL OR "group".enabled = 1)
|
||||||
|
ORDER BY regex_whitelist.id;
|
||||||
|
|
||||||
|
CREATE TRIGGER tr_regex_whitelist_update AFTER UPDATE ON regex_whitelist
|
||||||
|
BEGIN
|
||||||
|
UPDATE regex_whitelist SET date_modified = (cast(strftime('%s', 'now') as int)) WHERE domain = NEW.domain;
|
||||||
|
END;
|
||||||
|
|
||||||
|
|
||||||
|
UPDATE info SET value = 3 WHERE property = 'version';
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
96
advanced/Scripts/database_migration/gravity/3_to_4.sql
Normal file
96
advanced/Scripts/database_migration/gravity/3_to_4.sql
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
.timeout 30000
|
||||||
|
|
||||||
|
PRAGMA FOREIGN_KEYS=OFF;
|
||||||
|
|
||||||
|
BEGIN TRANSACTION;
|
||||||
|
|
||||||
|
CREATE TABLE domainlist
|
||||||
|
(
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
type INTEGER NOT NULL DEFAULT 0,
|
||||||
|
domain TEXT UNIQUE NOT NULL,
|
||||||
|
enabled BOOLEAN NOT NULL DEFAULT 1,
|
||||||
|
date_added INTEGER NOT NULL DEFAULT (cast(strftime('%s', 'now') as int)),
|
||||||
|
date_modified INTEGER NOT NULL DEFAULT (cast(strftime('%s', 'now') as int)),
|
||||||
|
comment TEXT
|
||||||
|
);
|
||||||
|
|
||||||
|
ALTER TABLE whitelist ADD COLUMN type INTEGER;
|
||||||
|
UPDATE whitelist SET type = 0;
|
||||||
|
INSERT INTO domainlist (type,domain,enabled,date_added,date_modified,comment)
|
||||||
|
SELECT type,domain,enabled,date_added,date_modified,comment FROM whitelist;
|
||||||
|
|
||||||
|
ALTER TABLE blacklist ADD COLUMN type INTEGER;
|
||||||
|
UPDATE blacklist SET type = 1;
|
||||||
|
INSERT INTO domainlist (type,domain,enabled,date_added,date_modified,comment)
|
||||||
|
SELECT type,domain,enabled,date_added,date_modified,comment FROM blacklist;
|
||||||
|
|
||||||
|
ALTER TABLE regex_whitelist ADD COLUMN type INTEGER;
|
||||||
|
UPDATE regex_whitelist SET type = 2;
|
||||||
|
INSERT INTO domainlist (type,domain,enabled,date_added,date_modified,comment)
|
||||||
|
SELECT type,domain,enabled,date_added,date_modified,comment FROM regex_whitelist;
|
||||||
|
|
||||||
|
ALTER TABLE regex_blacklist ADD COLUMN type INTEGER;
|
||||||
|
UPDATE regex_blacklist SET type = 3;
|
||||||
|
INSERT INTO domainlist (type,domain,enabled,date_added,date_modified,comment)
|
||||||
|
SELECT type,domain,enabled,date_added,date_modified,comment FROM regex_blacklist;
|
||||||
|
|
||||||
|
DROP TABLE whitelist_by_group;
|
||||||
|
DROP TABLE blacklist_by_group;
|
||||||
|
DROP TABLE regex_whitelist_by_group;
|
||||||
|
DROP TABLE regex_blacklist_by_group;
|
||||||
|
CREATE TABLE domainlist_by_group
|
||||||
|
(
|
||||||
|
domainlist_id INTEGER NOT NULL REFERENCES domainlist (id),
|
||||||
|
group_id INTEGER NOT NULL REFERENCES "group" (id),
|
||||||
|
PRIMARY KEY (domainlist_id, group_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
DROP TRIGGER tr_whitelist_update;
|
||||||
|
DROP TRIGGER tr_blacklist_update;
|
||||||
|
DROP TRIGGER tr_regex_whitelist_update;
|
||||||
|
DROP TRIGGER tr_regex_blacklist_update;
|
||||||
|
CREATE TRIGGER tr_domainlist_update AFTER UPDATE ON domainlist
|
||||||
|
BEGIN
|
||||||
|
UPDATE domainlist SET date_modified = (cast(strftime('%s', 'now') as int)) WHERE domain = NEW.domain;
|
||||||
|
END;
|
||||||
|
|
||||||
|
DROP VIEW vw_whitelist;
|
||||||
|
CREATE VIEW vw_whitelist AS SELECT domain, domainlist.id AS id, domainlist_by_group.group_id AS group_id
|
||||||
|
FROM domainlist
|
||||||
|
LEFT JOIN domainlist_by_group ON domainlist_by_group.domainlist_id = domainlist.id
|
||||||
|
LEFT JOIN "group" ON "group".id = domainlist_by_group.group_id
|
||||||
|
WHERE domainlist.enabled = 1 AND (domainlist_by_group.group_id IS NULL OR "group".enabled = 1)
|
||||||
|
AND domainlist.type = 0
|
||||||
|
ORDER BY domainlist.id;
|
||||||
|
|
||||||
|
DROP VIEW vw_blacklist;
|
||||||
|
CREATE VIEW vw_blacklist AS SELECT domain, domainlist.id AS id, domainlist_by_group.group_id AS group_id
|
||||||
|
FROM domainlist
|
||||||
|
LEFT JOIN domainlist_by_group ON domainlist_by_group.domainlist_id = domainlist.id
|
||||||
|
LEFT JOIN "group" ON "group".id = domainlist_by_group.group_id
|
||||||
|
WHERE domainlist.enabled = 1 AND (domainlist_by_group.group_id IS NULL OR "group".enabled = 1)
|
||||||
|
AND domainlist.type = 1
|
||||||
|
ORDER BY domainlist.id;
|
||||||
|
|
||||||
|
DROP VIEW vw_regex_whitelist;
|
||||||
|
CREATE VIEW vw_regex_whitelist AS SELECT domain, domainlist.id AS id, domainlist_by_group.group_id AS group_id
|
||||||
|
FROM domainlist
|
||||||
|
LEFT JOIN domainlist_by_group ON domainlist_by_group.domainlist_id = domainlist.id
|
||||||
|
LEFT JOIN "group" ON "group".id = domainlist_by_group.group_id
|
||||||
|
WHERE domainlist.enabled = 1 AND (domainlist_by_group.group_id IS NULL OR "group".enabled = 1)
|
||||||
|
AND domainlist.type = 2
|
||||||
|
ORDER BY domainlist.id;
|
||||||
|
|
||||||
|
DROP VIEW vw_regex_blacklist;
|
||||||
|
CREATE VIEW vw_regex_blacklist AS SELECT domain, domainlist.id AS id, domainlist_by_group.group_id AS group_id
|
||||||
|
FROM domainlist
|
||||||
|
LEFT JOIN domainlist_by_group ON domainlist_by_group.domainlist_id = domainlist.id
|
||||||
|
LEFT JOIN "group" ON "group".id = domainlist_by_group.group_id
|
||||||
|
WHERE domainlist.enabled = 1 AND (domainlist_by_group.group_id IS NULL OR "group".enabled = 1)
|
||||||
|
AND domainlist.type = 3
|
||||||
|
ORDER BY domainlist.id;
|
||||||
|
|
||||||
|
UPDATE info SET value = 4 WHERE property = 'version';
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
38
advanced/Scripts/database_migration/gravity/4_to_5.sql
Normal file
38
advanced/Scripts/database_migration/gravity/4_to_5.sql
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
.timeout 30000
|
||||||
|
|
||||||
|
PRAGMA FOREIGN_KEYS=OFF;
|
||||||
|
|
||||||
|
BEGIN TRANSACTION;
|
||||||
|
|
||||||
|
DROP TABLE gravity;
|
||||||
|
CREATE TABLE gravity
|
||||||
|
(
|
||||||
|
domain TEXT NOT NULL,
|
||||||
|
adlist_id INTEGER NOT NULL REFERENCES adlist (id),
|
||||||
|
PRIMARY KEY(domain, adlist_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
DROP VIEW vw_gravity;
|
||||||
|
CREATE VIEW vw_gravity AS SELECT domain, adlist_by_group.group_id AS group_id
|
||||||
|
FROM gravity
|
||||||
|
LEFT JOIN adlist_by_group ON adlist_by_group.adlist_id = gravity.adlist_id
|
||||||
|
LEFT JOIN adlist ON adlist.id = gravity.adlist_id
|
||||||
|
LEFT JOIN "group" ON "group".id = adlist_by_group.group_id
|
||||||
|
WHERE adlist.enabled = 1 AND (adlist_by_group.group_id IS NULL OR "group".enabled = 1);
|
||||||
|
|
||||||
|
CREATE TABLE client
|
||||||
|
(
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
ip TEXT NOL NULL UNIQUE
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE client_by_group
|
||||||
|
(
|
||||||
|
client_id INTEGER NOT NULL REFERENCES client (id),
|
||||||
|
group_id INTEGER NOT NULL REFERENCES "group" (id),
|
||||||
|
PRIMARY KEY (client_id, group_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
UPDATE info SET value = 5 WHERE property = 'version';
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
17
advanced/Scripts/database_migration/gravity/5_to_6.sql
Normal file
17
advanced/Scripts/database_migration/gravity/5_to_6.sql
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
.timeout 30000
|
||||||
|
|
||||||
|
PRAGMA FOREIGN_KEYS=OFF;
|
||||||
|
|
||||||
|
BEGIN TRANSACTION;
|
||||||
|
|
||||||
|
DROP VIEW vw_adlist;
|
||||||
|
CREATE VIEW vw_adlist AS SELECT DISTINCT address, adlist.id AS id
|
||||||
|
FROM adlist
|
||||||
|
LEFT JOIN adlist_by_group ON adlist_by_group.adlist_id = adlist.id
|
||||||
|
LEFT JOIN "group" ON "group".id = adlist_by_group.group_id
|
||||||
|
WHERE adlist.enabled = 1 AND (adlist_by_group.group_id IS NULL OR "group".enabled = 1)
|
||||||
|
ORDER BY adlist.id;
|
||||||
|
|
||||||
|
UPDATE info SET value = 6 WHERE property = 'version';
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
35
advanced/Scripts/database_migration/gravity/6_to_7.sql
Normal file
35
advanced/Scripts/database_migration/gravity/6_to_7.sql
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
.timeout 30000
|
||||||
|
|
||||||
|
PRAGMA FOREIGN_KEYS=OFF;
|
||||||
|
|
||||||
|
BEGIN TRANSACTION;
|
||||||
|
|
||||||
|
INSERT OR REPLACE INTO "group" (id,enabled,name) VALUES (0,1,'Unassociated');
|
||||||
|
|
||||||
|
INSERT INTO domainlist_by_group (domainlist_id, group_id) SELECT id, 0 FROM domainlist;
|
||||||
|
INSERT INTO client_by_group (client_id, group_id) SELECT id, 0 FROM client;
|
||||||
|
INSERT INTO adlist_by_group (adlist_id, group_id) SELECT id, 0 FROM adlist;
|
||||||
|
|
||||||
|
CREATE TRIGGER tr_domainlist_add AFTER INSERT ON domainlist
|
||||||
|
BEGIN
|
||||||
|
INSERT INTO domainlist_by_group (domainlist_id, group_id) VALUES (NEW.id, 0);
|
||||||
|
END;
|
||||||
|
|
||||||
|
CREATE TRIGGER tr_client_add AFTER INSERT ON client
|
||||||
|
BEGIN
|
||||||
|
INSERT INTO client_by_group (client_id, group_id) VALUES (NEW.id, 0);
|
||||||
|
END;
|
||||||
|
|
||||||
|
CREATE TRIGGER tr_adlist_add AFTER INSERT ON adlist
|
||||||
|
BEGIN
|
||||||
|
INSERT INTO adlist_by_group (adlist_id, group_id) VALUES (NEW.id, 0);
|
||||||
|
END;
|
||||||
|
|
||||||
|
CREATE TRIGGER tr_group_zero AFTER DELETE ON "group"
|
||||||
|
BEGIN
|
||||||
|
INSERT OR REPLACE INTO "group" (id,enabled,name) VALUES (0,1,'Unassociated');
|
||||||
|
END;
|
||||||
|
|
||||||
|
UPDATE info SET value = 7 WHERE property = 'version';
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
35
advanced/Scripts/database_migration/gravity/7_to_8.sql
Normal file
35
advanced/Scripts/database_migration/gravity/7_to_8.sql
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
.timeout 30000
|
||||||
|
|
||||||
|
PRAGMA FOREIGN_KEYS=OFF;
|
||||||
|
|
||||||
|
BEGIN TRANSACTION;
|
||||||
|
|
||||||
|
ALTER TABLE "group" RENAME TO "group__";
|
||||||
|
|
||||||
|
CREATE TABLE "group"
|
||||||
|
(
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
enabled BOOLEAN NOT NULL DEFAULT 1,
|
||||||
|
name TEXT UNIQUE NOT NULL,
|
||||||
|
date_added INTEGER NOT NULL DEFAULT (cast(strftime('%s', 'now') as int)),
|
||||||
|
date_modified INTEGER NOT NULL DEFAULT (cast(strftime('%s', 'now') as int)),
|
||||||
|
description TEXT
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TRIGGER tr_group_update AFTER UPDATE ON "group"
|
||||||
|
BEGIN
|
||||||
|
UPDATE "group" SET date_modified = (cast(strftime('%s', 'now') as int)) WHERE id = NEW.id;
|
||||||
|
END;
|
||||||
|
|
||||||
|
INSERT OR IGNORE INTO "group" (id,enabled,name,description) SELECT id,enabled,name,description FROM "group__";
|
||||||
|
|
||||||
|
DROP TABLE "group__";
|
||||||
|
|
||||||
|
CREATE TRIGGER tr_group_zero AFTER DELETE ON "group"
|
||||||
|
BEGIN
|
||||||
|
INSERT OR IGNORE INTO "group" (id,enabled,name) VALUES (0,1,'Unassociated');
|
||||||
|
END;
|
||||||
|
|
||||||
|
UPDATE info SET value = 8 WHERE property = 'version';
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
27
advanced/Scripts/database_migration/gravity/8_to_9.sql
Normal file
27
advanced/Scripts/database_migration/gravity/8_to_9.sql
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
.timeout 30000
|
||||||
|
|
||||||
|
PRAGMA FOREIGN_KEYS=OFF;
|
||||||
|
|
||||||
|
BEGIN TRANSACTION;
|
||||||
|
|
||||||
|
DROP TRIGGER IF EXISTS tr_group_update;
|
||||||
|
DROP TRIGGER IF EXISTS tr_group_zero;
|
||||||
|
|
||||||
|
PRAGMA legacy_alter_table=ON;
|
||||||
|
ALTER TABLE "group" RENAME TO "group__";
|
||||||
|
PRAGMA legacy_alter_table=OFF;
|
||||||
|
ALTER TABLE "group__" RENAME TO "group";
|
||||||
|
|
||||||
|
CREATE TRIGGER tr_group_update AFTER UPDATE ON "group"
|
||||||
|
BEGIN
|
||||||
|
UPDATE "group" SET date_modified = (cast(strftime('%s', 'now') as int)) WHERE id = NEW.id;
|
||||||
|
END;
|
||||||
|
|
||||||
|
CREATE TRIGGER tr_group_zero AFTER DELETE ON "group"
|
||||||
|
BEGIN
|
||||||
|
INSERT OR IGNORE INTO "group" (id,enabled,name) VALUES (0,1,'Unassociated');
|
||||||
|
END;
|
||||||
|
|
||||||
|
UPDATE info SET value = 9 WHERE property = 'version';
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
29
advanced/Scripts/database_migration/gravity/9_to_10.sql
Normal file
29
advanced/Scripts/database_migration/gravity/9_to_10.sql
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
.timeout 30000
|
||||||
|
|
||||||
|
PRAGMA FOREIGN_KEYS=OFF;
|
||||||
|
|
||||||
|
BEGIN TRANSACTION;
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS whitelist;
|
||||||
|
DROP TABLE IF EXISTS blacklist;
|
||||||
|
DROP TABLE IF EXISTS regex_whitelist;
|
||||||
|
DROP TABLE IF EXISTS regex_blacklist;
|
||||||
|
|
||||||
|
CREATE TRIGGER tr_domainlist_delete AFTER DELETE ON domainlist
|
||||||
|
BEGIN
|
||||||
|
DELETE FROM domainlist_by_group WHERE domainlist_id = OLD.id;
|
||||||
|
END;
|
||||||
|
|
||||||
|
CREATE TRIGGER tr_adlist_delete AFTER DELETE ON adlist
|
||||||
|
BEGIN
|
||||||
|
DELETE FROM adlist_by_group WHERE adlist_id = OLD.id;
|
||||||
|
END;
|
||||||
|
|
||||||
|
CREATE TRIGGER tr_client_delete AFTER DELETE ON client
|
||||||
|
BEGIN
|
||||||
|
DELETE FROM client_by_group WHERE client_id = OLD.id;
|
||||||
|
END;
|
||||||
|
|
||||||
|
UPDATE info SET value = 10 WHERE property = 'version';
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
227
advanced/Scripts/list.sh
Executable file
227
advanced/Scripts/list.sh
Executable file
@@ -0,0 +1,227 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# shellcheck disable=SC1090
|
||||||
|
|
||||||
|
# Pi-hole: A black hole for Internet advertisements
|
||||||
|
# (c) 2017 Pi-hole, LLC (https://pi-hole.net)
|
||||||
|
# Network-wide ad blocking via your own hardware.
|
||||||
|
#
|
||||||
|
# allowlist and denylist domains
|
||||||
|
#
|
||||||
|
# This file is copyright under the latest version of the EUPL.
|
||||||
|
# Please see LICENSE file for your rights under this license.
|
||||||
|
|
||||||
|
readonly PI_HOLE_SCRIPT_DIR="/opt/pihole"
|
||||||
|
readonly utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh"
|
||||||
|
source "${utilsfile}"
|
||||||
|
|
||||||
|
readonly apifile="${PI_HOLE_SCRIPT_DIR}/api.sh"
|
||||||
|
source "${apifile}"
|
||||||
|
|
||||||
|
# Determine database location
|
||||||
|
DBFILE=$(getFTLConfigValue "files.database")
|
||||||
|
if [ -z "$DBFILE" ]; then
|
||||||
|
DBFILE="/etc/pihole/pihole-FTL.db"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Determine gravity database location
|
||||||
|
GRAVITYDB=$(getFTLConfigValue "files.gravity")
|
||||||
|
if [ -z "$GRAVITYDB" ]; then
|
||||||
|
GRAVITYDB="/etc/pihole/gravity.db"
|
||||||
|
fi
|
||||||
|
|
||||||
|
addmode=true
|
||||||
|
verbose=true
|
||||||
|
wildcard=false
|
||||||
|
|
||||||
|
domList=()
|
||||||
|
|
||||||
|
typeId=""
|
||||||
|
comment=""
|
||||||
|
|
||||||
|
colfile="/opt/pihole/COL_TABLE"
|
||||||
|
source ${colfile}
|
||||||
|
|
||||||
|
helpFunc() {
|
||||||
|
echo "Usage: pihole ${abbrv} [options] <domain> <domain2 ...>
|
||||||
|
Example: 'pihole ${abbrv} site.com', or 'pihole ${abbrv} site1.com site2.com'
|
||||||
|
${typeId^} one or more ${kindId} domains
|
||||||
|
|
||||||
|
Options:
|
||||||
|
remove, delete, -d Remove domain(s)
|
||||||
|
-q, --quiet Make output less verbose
|
||||||
|
-h, --help Show this help dialog
|
||||||
|
-l, --list Display domains
|
||||||
|
--comment \"text\" Add a comment to the domain. If adding multiple domains the same comment will be used for all"
|
||||||
|
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
CreateDomainList() {
|
||||||
|
# Format domain into regex filter if requested
|
||||||
|
local dom=${1}
|
||||||
|
if [[ "${wildcard}" == true ]]; then
|
||||||
|
dom="(\\.|^)${dom//\./\\.}$"
|
||||||
|
fi
|
||||||
|
domList=("${domList[@]}" "${dom}")
|
||||||
|
}
|
||||||
|
|
||||||
|
AddDomain() {
|
||||||
|
local json num data
|
||||||
|
|
||||||
|
# Authenticate with the API
|
||||||
|
LoginAPI
|
||||||
|
|
||||||
|
# Prepare request to POST /api/domains/{type}/{kind}
|
||||||
|
# Build JSON object of the following form
|
||||||
|
# {
|
||||||
|
# "domain": [ <domains> ],
|
||||||
|
# "comment": <comment>
|
||||||
|
# }
|
||||||
|
# where <domains> is an array of domain strings and <comment> is a string
|
||||||
|
# We use jq to build the JSON object
|
||||||
|
json=$(jq --null-input --compact-output --arg domains "${domList[*]}" --arg comment "${comment}" '{domain: $domains | split(" "), comment: $comment}')
|
||||||
|
|
||||||
|
# Send the request
|
||||||
|
data=$(PostFTLData "domains/${typeId}/${kindId}" "${json}")
|
||||||
|
|
||||||
|
# Display domain(s) added
|
||||||
|
# (they are listed in .processed.success, use jq)
|
||||||
|
num=$(echo "${data}" | jq '.processed.success | length')
|
||||||
|
if [[ "${num}" -gt 0 ]] && [[ "${verbose}" == true ]]; then
|
||||||
|
echo -e " ${TICK} Added ${num} domain(s):"
|
||||||
|
for i in $(seq 0 $((num-1))); do
|
||||||
|
echo -e " - ${COL_BLUE}$(echo "${data}" | jq --raw-output ".processed.success[$i].item")${COL_NC}"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
# Display failed domain(s)
|
||||||
|
# (they are listed in .processed.errors, use jq)
|
||||||
|
num=$(echo "${data}" | jq '.processed.errors | length')
|
||||||
|
if [[ "${num}" -gt 0 ]] && [[ "${verbose}" == true ]]; then
|
||||||
|
echo -e " ${CROSS} Failed to add ${num} domain(s):"
|
||||||
|
for i in $(seq 0 $((num-1))); do
|
||||||
|
echo -e " - ${COL_BLUE}$(echo "${data}" | jq --raw-output ".processed.errors[$i].item")${COL_NC}"
|
||||||
|
error=$(echo "${data}" | jq --raw-output ".processed.errors[$i].error")
|
||||||
|
if [[ "${error}" == "UNIQUE constraint failed: domainlist.domain, domainlist.type" ]]; then
|
||||||
|
error="Domain already in the specified list"
|
||||||
|
fi
|
||||||
|
echo -e " ${error}"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Log out
|
||||||
|
LogoutAPI
|
||||||
|
}
|
||||||
|
|
||||||
|
RemoveDomain() {
|
||||||
|
local json num data status
|
||||||
|
|
||||||
|
# Authenticate with the API
|
||||||
|
LoginAPI
|
||||||
|
|
||||||
|
# Prepare request to POST /api/domains:batchDelete
|
||||||
|
# Build JSON object of the following form
|
||||||
|
# [{
|
||||||
|
# "item": <domain>,
|
||||||
|
# "type": "${typeId}",
|
||||||
|
# "kind": "${kindId}",
|
||||||
|
# }]
|
||||||
|
# where <domain> is the domain string and ${typeId} and ${kindId} are the type and kind IDs
|
||||||
|
# We use jq to build the JSON object)
|
||||||
|
json=$(jq --null-input --compact-output --arg domains "${domList[*]}" --arg typeId "${typeId}" --arg kindId "${kindId}" '[ $domains | split(" ")[] as $item | {item: $item, type: $typeId, kind: $kindId} ]')
|
||||||
|
|
||||||
|
# Send the request
|
||||||
|
data=$(PostFTLData "domains:batchDelete" "${json}" "status")
|
||||||
|
# Separate the status from the data
|
||||||
|
status=$(printf %s "${data#"${data%???}"}")
|
||||||
|
data=$(printf %s "${data%???}")
|
||||||
|
|
||||||
|
# If there is an .error object in the returned data, display it
|
||||||
|
local error
|
||||||
|
error=$(jq --compact-output <<< "${data}" '.error')
|
||||||
|
if [[ $error != "null" && $error != "" ]]; then
|
||||||
|
echo -e " ${CROSS} Failed to remove domain(s):"
|
||||||
|
echo -e " $(jq <<< "${data}" '.error')"
|
||||||
|
elif [[ "${verbose}" == true && "${status}" == "204" ]]; then
|
||||||
|
echo -e " ${TICK} Domain(s) removed from the ${kindId} ${typeId}list"
|
||||||
|
elif [[ "${verbose}" == true && "${status}" == "404" ]]; then
|
||||||
|
echo -e " ${TICK} Requested domain(s) not found on ${kindId} ${typeId}list"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Log out
|
||||||
|
LogoutAPI
|
||||||
|
}
|
||||||
|
|
||||||
|
Displaylist() {
|
||||||
|
local data
|
||||||
|
|
||||||
|
# if either typeId or kindId is empty, we cannot display the list
|
||||||
|
if [[ -z "${typeId}" ]] || [[ -z "${kindId}" ]]; then
|
||||||
|
echo " ${CROSS} Unable to display list. Please specify a list type and kind."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Authenticate with the API
|
||||||
|
LoginAPI
|
||||||
|
|
||||||
|
# Send the request
|
||||||
|
data=$(GetFTLData "domains/${typeId}/${kindId}")
|
||||||
|
|
||||||
|
# Display the list
|
||||||
|
num=$(echo "${data}" | jq '.domains | length')
|
||||||
|
if [[ "${num}" -gt 0 ]]; then
|
||||||
|
echo -e " ${TICK} Found ${num} domain(s) in the ${kindId} ${typeId}list:"
|
||||||
|
for i in $(seq 0 $((num-1))); do
|
||||||
|
echo -e " - ${COL_BLUE}$(echo "${data}" | jq --compact-output ".domains[$i].domain")${COL_NC}"
|
||||||
|
echo -e " Comment: $(echo "${data}" | jq --compact-output ".domains[$i].comment")"
|
||||||
|
echo -e " Groups: $(echo "${data}" | jq --compact-output ".domains[$i].groups")"
|
||||||
|
echo -e " Added: $(date -d @"$(echo "${data}" | jq --compact-output ".domains[$i].date_added")")"
|
||||||
|
echo -e " Last modified: $(date -d @"$(echo "${data}" | jq --compact-output ".domains[$i].date_modified")")"
|
||||||
|
done
|
||||||
|
else
|
||||||
|
echo -e " ${INFO} No domains found in the ${kindId} ${typeId}list"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Log out
|
||||||
|
LogoutAPI
|
||||||
|
|
||||||
|
# Return early without adding/deleting domains
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
GetComment() {
|
||||||
|
comment="$1"
|
||||||
|
if [[ "${comment}" =~ [^a-zA-Z0-9_\#:/\.,\ -] ]]; then
|
||||||
|
echo " ${CROSS} Found invalid characters in domain comment!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
while (( "$#" )); do
|
||||||
|
case "${1}" in
|
||||||
|
"allow" | "allowlist" ) kindId="exact"; typeId="allow"; abbrv="allow";;
|
||||||
|
"deny" | "denylist" ) kindId="exact"; typeId="deny"; abbrv="deny";;
|
||||||
|
"--allow-regex" | "allow-regex" ) kindId="regex"; typeId="allow"; abbrv="--allow-regex";;
|
||||||
|
"--allow-wild" | "allow-wild" ) kindId="regex"; typeId="allow"; wildcard=true; abbrv="--allow-wild";;
|
||||||
|
"--regex" | "regex" ) kindId="regex"; typeId="deny"; abbrv="--regex";;
|
||||||
|
"--wild" | "wildcard" ) kindId="regex"; typeId="deny"; wildcard=true; abbrv="--wild";;
|
||||||
|
"-d" | "remove" | "delete" ) addmode=false;;
|
||||||
|
"-q" | "--quiet" ) verbose=false;;
|
||||||
|
"-h" | "--help" ) helpFunc;;
|
||||||
|
"-l" | "--list" ) Displaylist;;
|
||||||
|
"--comment" ) GetComment "${2}"; shift;;
|
||||||
|
* ) CreateDomainList "${1}";;
|
||||||
|
esac
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
shift
|
||||||
|
|
||||||
|
if [[ ${#domList[@]} == 0 ]]; then
|
||||||
|
helpFunc
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ${addmode}; then
|
||||||
|
AddDomain
|
||||||
|
else
|
||||||
|
RemoveDomain
|
||||||
|
fi
|
||||||
82
advanced/Scripts/piholeARPTable.sh
Executable file
82
advanced/Scripts/piholeARPTable.sh
Executable file
@@ -0,0 +1,82 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# shellcheck disable=SC1090
|
||||||
|
|
||||||
|
# Pi-hole: A black hole for Internet advertisements
|
||||||
|
# (c) 2019 Pi-hole, LLC (https://pi-hole.net)
|
||||||
|
# Network-wide ad blocking via your own hardware.
|
||||||
|
#
|
||||||
|
# ARP table interaction
|
||||||
|
#
|
||||||
|
# This file is copyright under the latest version of the EUPL.
|
||||||
|
# Please see LICENSE file for your rights under this license.
|
||||||
|
|
||||||
|
coltable="/opt/pihole/COL_TABLE"
|
||||||
|
if [[ -f ${coltable} ]]; then
|
||||||
|
source ${coltable}
|
||||||
|
fi
|
||||||
|
|
||||||
|
readonly PI_HOLE_SCRIPT_DIR="/opt/pihole"
|
||||||
|
utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh"
|
||||||
|
source "${utilsfile}"
|
||||||
|
|
||||||
|
# Determine database location
|
||||||
|
DBFILE=$(getFTLConfigValue "files.database")
|
||||||
|
if [ -z "$DBFILE" ]; then
|
||||||
|
DBFILE="/etc/pihole/pihole-FTL.db"
|
||||||
|
fi
|
||||||
|
|
||||||
|
flushARP(){
|
||||||
|
local output
|
||||||
|
if [[ "${args[1]}" != "quiet" ]]; then
|
||||||
|
echo -ne " ${INFO} Flushing network table ..."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Stop FTL to prevent database access
|
||||||
|
if ! output=$(service pihole-FTL stop 2>&1); then
|
||||||
|
echo -e "${OVER} ${CROSS} Failed to stop FTL"
|
||||||
|
echo " Output: ${output}"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Truncate network_addresses table in pihole-FTL.db
|
||||||
|
# This needs to be done before we can truncate the network table due to
|
||||||
|
# foreign key constraints
|
||||||
|
if ! output=$(pihole-FTL sqlite3 -ni "${DBFILE}" "DELETE FROM network_addresses" 2>&1); then
|
||||||
|
echo -e "${OVER} ${CROSS} Failed to truncate network_addresses table"
|
||||||
|
echo " Database location: ${DBFILE}"
|
||||||
|
echo " Output: ${output}"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Truncate network table in pihole-FTL.db
|
||||||
|
if ! output=$(pihole-FTL sqlite3 -ni "${DBFILE}" "DELETE FROM network" 2>&1); then
|
||||||
|
echo -e "${OVER} ${CROSS} Failed to truncate network table"
|
||||||
|
echo " Database location: ${DBFILE}"
|
||||||
|
echo " Output: ${output}"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Flush ARP cache of the host
|
||||||
|
if ! output=$(ip -s -s neigh flush all 2>&1); then
|
||||||
|
echo -e "${OVER} ${CROSS} Failed to flush ARP cache"
|
||||||
|
echo " Output: ${output}"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Start FTL again
|
||||||
|
if ! output=$(service pihole-FTL restart 2>&1); then
|
||||||
|
echo -e "${OVER} ${CROSS} Failed to restart FTL"
|
||||||
|
echo " Output: ${output}"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "${args[1]}" != "quiet" ]]; then
|
||||||
|
echo -e "${OVER} ${TICK} Flushed network table"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
args=("$@")
|
||||||
|
|
||||||
|
case "${args[0]}" in
|
||||||
|
"arpflush" ) flushARP;;
|
||||||
|
esac
|
||||||
242
advanced/Scripts/piholeCheckout.sh
Executable file
242
advanced/Scripts/piholeCheckout.sh
Executable file
@@ -0,0 +1,242 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Pi-hole: A black hole for Internet advertisements
|
||||||
|
# (c) 2017 Pi-hole, LLC (https://pi-hole.net)
|
||||||
|
# Network-wide ad blocking via your own hardware.
|
||||||
|
#
|
||||||
|
# Switch Pi-hole subsystems to a different GitHub branch.
|
||||||
|
#
|
||||||
|
# This file is copyright under the latest version of the EUPL.
|
||||||
|
# Please see LICENSE file for your rights under this license.
|
||||||
|
|
||||||
|
readonly PI_HOLE_FILES_DIR="/etc/.pihole"
|
||||||
|
SKIP_INSTALL="true"
|
||||||
|
source "${PI_HOLE_FILES_DIR}/automated install/basic-install.sh"
|
||||||
|
|
||||||
|
# webInterfaceGitUrl set in basic-install.sh
|
||||||
|
# webInterfaceDir set in basic-install.sh
|
||||||
|
# piholeGitURL set in basic-install.sh
|
||||||
|
# is_repo() sourced from basic-install.sh
|
||||||
|
# check_download_exists sourced from basic-install.sh
|
||||||
|
# fully_fetch_repo sourced from basic-install.sh
|
||||||
|
# get_available_branches sourced from basic-install.sh
|
||||||
|
# fetch_checkout_pull_branch sourced from basic-install.sh
|
||||||
|
# checkout_pull_branch sourced from basic-install.sh
|
||||||
|
|
||||||
|
warning1() {
|
||||||
|
echo " Please note that changing branches severely alters your Pi-hole subsystems"
|
||||||
|
echo " Features that work on the master branch, may not on a development branch"
|
||||||
|
echo -e " ${COL_LIGHT_RED}This feature is NOT supported unless a Pi-hole developer explicitly asks!${COL_NC}"
|
||||||
|
read -r -p " Have you read and understood this? [y/N] " response
|
||||||
|
case "${response}" in
|
||||||
|
[yY][eE][sS]|[yY])
|
||||||
|
echo ""
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo -e "\\n ${INFO} Branch change has been canceled"
|
||||||
|
return 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
checkout() {
|
||||||
|
local corebranches
|
||||||
|
local webbranches
|
||||||
|
|
||||||
|
# Check if FTL is installed - do this early on as FTL is a hard dependency for Pi-hole
|
||||||
|
local funcOutput
|
||||||
|
funcOutput=$(get_binary_name) #Store output of get_binary_name here
|
||||||
|
local binary
|
||||||
|
binary="pihole-FTL${funcOutput##*pihole-FTL}" #binary name will be the last line of the output of get_binary_name (it always begins with pihole-FTL)
|
||||||
|
|
||||||
|
# Avoid globbing
|
||||||
|
set -f
|
||||||
|
|
||||||
|
# This is unlikely
|
||||||
|
if ! is_repo "${PI_HOLE_FILES_DIR}" ; then
|
||||||
|
echo -e " ${COL_LIGHT_RED}Error: Core Pi-hole repo is missing from system!"
|
||||||
|
echo -e " Please re-run install script from https://github.com/pi-hole/pi-hole${COL_NC}"
|
||||||
|
exit 1;
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! is_repo "${webInterfaceDir}" ; then
|
||||||
|
echo -e " ${COL_LIGHT_RED}Error: Web Admin repo is missing from system!"
|
||||||
|
echo -e " Please re-run install script from https://github.com/pi-hole/pi-hole${COL_NC}"
|
||||||
|
exit 1;
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "${1}" ]]; then
|
||||||
|
echo -e " ${COL_LIGHT_RED}Invalid option${COL_NC}"
|
||||||
|
echo -e " Try 'pihole checkout --help' for more information."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! warning1 ; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "${1}" == "dev" ]] ; then
|
||||||
|
# Shortcut to check out development branches
|
||||||
|
echo -e " ${INFO} Shortcut \"${COL_YELLOW}dev${COL_NC}\" detected - checking out development branches..."
|
||||||
|
echo ""
|
||||||
|
echo -e " ${INFO} Pi-hole Core"
|
||||||
|
fetch_checkout_pull_branch "${PI_HOLE_FILES_DIR}" "development" || { echo " ${CROSS} Unable to pull Core development branch"; exit 1; }
|
||||||
|
echo ""
|
||||||
|
echo -e " ${INFO} Web interface"
|
||||||
|
fetch_checkout_pull_branch "${webInterfaceDir}" "development" || { echo " ${CROSS} Unable to pull Web development branch"; exit 1; }
|
||||||
|
#echo -e " ${TICK} Pi-hole Core"
|
||||||
|
|
||||||
|
local path
|
||||||
|
path="development/${binary}"
|
||||||
|
echo "development" > /etc/pihole/ftlbranch
|
||||||
|
chmod 644 /etc/pihole/ftlbranch
|
||||||
|
elif [[ "${1}" == "master" ]] ; then
|
||||||
|
# Shortcut to check out master branches
|
||||||
|
echo -e " ${INFO} Shortcut \"${COL_YELLOW}master${COL_NC}\" detected - checking out master branches..."
|
||||||
|
echo -e " ${INFO} Pi-hole core"
|
||||||
|
fetch_checkout_pull_branch "${PI_HOLE_FILES_DIR}" "master" || { echo " ${CROSS} Unable to pull Core master branch"; exit 1; }
|
||||||
|
echo -e " ${INFO} Web interface"
|
||||||
|
fetch_checkout_pull_branch "${webInterfaceDir}" "master" || { echo " ${CROSS} Unable to pull Web master branch"; exit 1; }
|
||||||
|
#echo -e " ${TICK} Web Interface"
|
||||||
|
local path
|
||||||
|
path="master/${binary}"
|
||||||
|
echo "master" > /etc/pihole/ftlbranch
|
||||||
|
chmod 644 /etc/pihole/ftlbranch
|
||||||
|
elif [[ "${1}" == "core" ]] ; then
|
||||||
|
str="Fetching branches from ${piholeGitUrl}"
|
||||||
|
echo -ne " ${INFO} $str"
|
||||||
|
if ! fully_fetch_repo "${PI_HOLE_FILES_DIR}" ; then
|
||||||
|
echo -e "${OVER} ${CROSS} $str"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
corebranches=($(get_available_branches "${PI_HOLE_FILES_DIR}"))
|
||||||
|
|
||||||
|
if [[ "${corebranches[*]}" == *"master"* ]]; then
|
||||||
|
echo -e "${OVER} ${TICK} $str"
|
||||||
|
echo -e " ${INFO} ${#corebranches[@]} branches available for Pi-hole Core"
|
||||||
|
else
|
||||||
|
# Print STDERR output from get_available_branches
|
||||||
|
echo -e "${OVER} ${CROSS} $str\\n\\n${corebranches[*]}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
# Have the user choose the branch they want
|
||||||
|
if ! (for e in "${corebranches[@]}"; do [[ "$e" == "${2}" ]] && exit 0; done); then
|
||||||
|
echo -e " ${INFO} Requested branch \"${COL_CYAN}${2}${COL_NC}\" is not available"
|
||||||
|
echo -e " ${INFO} Available branches for Core are:"
|
||||||
|
for e in "${corebranches[@]}"; do echo " - $e"; done
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
checkout_pull_branch "${PI_HOLE_FILES_DIR}" "${2}"
|
||||||
|
elif [[ "${1}" == "web" ]] ; then
|
||||||
|
str="Fetching branches from ${webInterfaceGitUrl}"
|
||||||
|
echo -ne " ${INFO} $str"
|
||||||
|
if ! fully_fetch_repo "${webInterfaceDir}" ; then
|
||||||
|
echo -e "${OVER} ${CROSS} $str"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
webbranches=($(get_available_branches "${webInterfaceDir}"))
|
||||||
|
|
||||||
|
if [[ "${webbranches[*]}" == *"master"* ]]; then
|
||||||
|
echo -e "${OVER} ${TICK} $str"
|
||||||
|
echo -e " ${INFO} ${#webbranches[@]} branches available for Web Admin"
|
||||||
|
else
|
||||||
|
# Print STDERR output from get_available_branches
|
||||||
|
echo -e "${OVER} ${CROSS} $str\\n\\n${webbranches[*]}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
# Have the user choose the branch they want
|
||||||
|
if ! (for e in "${webbranches[@]}"; do [[ "$e" == "${2}" ]] && exit 0; done); then
|
||||||
|
echo -e " ${INFO} Requested branch \"${COL_CYAN}${2}${COL_NC}\" is not available"
|
||||||
|
echo -e " ${INFO} Available branches for Web Admin are:"
|
||||||
|
for e in "${webbranches[@]}"; do echo " - $e"; done
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
checkout_pull_branch "${webInterfaceDir}" "${2}"
|
||||||
|
# Update local and remote versions via updatechecker
|
||||||
|
/opt/pihole/updatecheck.sh
|
||||||
|
elif [[ "${1}" == "ftl" ]] ; then
|
||||||
|
local path
|
||||||
|
local oldbranch
|
||||||
|
local existing=false
|
||||||
|
path="${2}/${binary}"
|
||||||
|
oldbranch="$(pihole-FTL -b)"
|
||||||
|
|
||||||
|
# Check if requested branch is available
|
||||||
|
echo -e " ${INFO} Checking for availability of branch ${COL_CYAN}${2}${COL_NC} on GitHub"
|
||||||
|
ftlbranches=( $(git ls-remote https://github.com/pi-hole/ftl | grep "refs/heads" | cut -d'/' -f3- -) )
|
||||||
|
# If returned array is empty -> connectivity issue
|
||||||
|
if [[ ${#ftlbranches[@]} -eq 0 ]]; then
|
||||||
|
echo -e " ${CROSS} Unable to fetch branches from GitHub. Please check your Internet connection and try again later."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
for e in "${ftlbranches[@]}"; do [[ "$e" == "${2}" ]] && existing=true; done
|
||||||
|
if [[ "${existing}" == false ]]; then
|
||||||
|
echo -e " ${CROSS} Requested branch is not available\n"
|
||||||
|
echo -e " ${INFO} Available branches are:"
|
||||||
|
for e in "${ftlbranches[@]}"; do echo " - $e"; done
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo -e " ${TICK} Branch ${2} exists on GitHub"
|
||||||
|
|
||||||
|
echo -e " ${INFO} Checking for ${COL_YELLOW}${binary}${COL_NC} binary on https://ftl.pi-hole.net"
|
||||||
|
|
||||||
|
if check_download_exists "$path"; then
|
||||||
|
echo " ${TICK} Binary exists"
|
||||||
|
echo "${2}" > /etc/pihole/ftlbranch
|
||||||
|
chmod 644 /etc/pihole/ftlbranch
|
||||||
|
echo -e " ${INFO} Switching to branch: ${COL_CYAN}${2}${COL_NC} from ${COL_CYAN}${oldbranch}${COL_NC}"
|
||||||
|
FTLinstall "${binary}"
|
||||||
|
restart_service pihole-FTL
|
||||||
|
enable_service pihole-FTL
|
||||||
|
str="Restarting FTL..."
|
||||||
|
echo -ne " ${INFO} ${str}"
|
||||||
|
# Wait until name resolution is working again after restarting FTL,
|
||||||
|
# so that the updatechecker can run successfully and does not fail
|
||||||
|
# trying to resolve github.com
|
||||||
|
until getent hosts github.com &> /dev/null; do
|
||||||
|
# Append one dot for each second waiting
|
||||||
|
str="${str}."
|
||||||
|
echo -ne " ${OVER} ${INFO} ${str}"
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
echo -e " ${OVER} ${TICK} Restarted FTL service"
|
||||||
|
|
||||||
|
# Update local and remote versions via updatechecker
|
||||||
|
/opt/pihole/updatecheck.sh
|
||||||
|
else
|
||||||
|
if [ $? -eq 1 ]; then
|
||||||
|
# Binary for requested branch is not available, may still be
|
||||||
|
# int he process of being built or CI build job failed
|
||||||
|
printf " %b Binary for requested branch is not available, please try again later.\\n" ${CROSS}
|
||||||
|
printf " If the issue persists, please contact Pi-hole Support and ask them to re-generate the binary.\\n"
|
||||||
|
exit 1
|
||||||
|
elif [ $? -eq 2 ]; then
|
||||||
|
printf " %b Unable to download from ftl.pi-hole.net. Please check your Internet connection and try again later.\\n" "${CROSS}"
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
printf " %b Unknown checkout error. Please contact Pi-hole Support\\n" "${CROSS}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
else
|
||||||
|
echo -e " ${CROSS} Requested option \"${1}\" is not available"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Force updating everything
|
||||||
|
if [[ ! "${1}" == "web" && ! "${1}" == "ftl" ]]; then
|
||||||
|
echo -e " ${INFO} Running installer to upgrade your installation"
|
||||||
|
if "${PI_HOLE_FILES_DIR}/automated install/basic-install.sh" --unattended; then
|
||||||
|
exit 0
|
||||||
|
else
|
||||||
|
echo -e " ${COL_LIGHT_RED} Error: Unable to complete update, please contact support${COL_NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
1391
advanced/Scripts/piholeDebug.sh
Executable file
1391
advanced/Scripts/piholeDebug.sh
Executable file
File diff suppressed because it is too large
Load Diff
@@ -1,11 +1,122 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# Flushes /var/log/pihole.log
|
# Pi-hole: A black hole for Internet advertisements
|
||||||
# (c) 2015 by Jacob Salmela
|
# (c) 2017 Pi-hole, LLC (https://pi-hole.net)
|
||||||
# This file is part of Pi-hole.
|
# Network-wide ad blocking via your own hardware.
|
||||||
#
|
#
|
||||||
#Pi-hole is free software: you can redistribute it and/or modify
|
# Flushes Pi-hole's log file
|
||||||
#it under the terms of the GNU General Public License as published by
|
#
|
||||||
#the Free Software Foundation, either version 2 of the License, or
|
# This file is copyright under the latest version of the EUPL.
|
||||||
#(at your option) any later version.
|
# Please see LICENSE file for your rights under this license.
|
||||||
|
|
||||||
|
colfile="/opt/pihole/COL_TABLE"
|
||||||
|
source ${colfile}
|
||||||
|
|
||||||
|
readonly PI_HOLE_SCRIPT_DIR="/opt/pihole"
|
||||||
|
utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh"
|
||||||
|
source "${utilsfile}"
|
||||||
|
|
||||||
|
# In case we're running at the same time as a system logrotate, use a
|
||||||
|
# separate logrotate state file to prevent stepping on each other's
|
||||||
|
# toes.
|
||||||
|
STATEFILE="/var/lib/logrotate/pihole"
|
||||||
|
|
||||||
|
# Determine database location
|
||||||
|
DBFILE=$(getFTLConfigValue "files.database")
|
||||||
|
if [ -z "$DBFILE" ]; then
|
||||||
|
DBFILE="/etc/pihole/pihole-FTL.db"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Determine log file location
|
||||||
|
LOGFILE=$(getFTLConfigValue "files.log.dnsmasq")
|
||||||
|
if [ -z "$LOGFILE" ]; then
|
||||||
|
LOGFILE="/var/log/pihole/pihole.log"
|
||||||
|
fi
|
||||||
|
FTLFILE=$(getFTLConfigValue "files.log.ftl")
|
||||||
|
if [ -z "$FTLFILE" ]; then
|
||||||
|
FTLFILE="/var/log/pihole/FTL.log"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$*" == *"once"* ]]; then
|
||||||
|
# Nightly logrotation
|
||||||
|
if command -v /usr/sbin/logrotate >/dev/null; then
|
||||||
|
# Logrotate once
|
||||||
|
|
||||||
|
if [[ "$*" != *"quiet"* ]]; then
|
||||||
|
echo -ne " ${INFO} Running logrotate ..."
|
||||||
|
fi
|
||||||
|
/usr/sbin/logrotate --force --state "${STATEFILE}" /etc/pihole/logrotate
|
||||||
|
else
|
||||||
|
# Copy pihole.log over to pihole.log.1
|
||||||
|
# and empty out pihole.log
|
||||||
|
# Note that moving the file is not an option, as
|
||||||
|
# dnsmasq would happily continue writing into the
|
||||||
|
# moved file (it will have the same file handler)
|
||||||
|
if [[ "$*" != *"quiet"* ]]; then
|
||||||
|
echo -ne " ${INFO} Rotating ${LOGFILE} ..."
|
||||||
|
fi
|
||||||
|
cp -p "${LOGFILE}" "${LOGFILE}.1"
|
||||||
|
echo " " > "${LOGFILE}"
|
||||||
|
chmod 640 "${LOGFILE}"
|
||||||
|
if [[ "$*" != *"quiet"* ]]; then
|
||||||
|
echo -e "${OVER} ${TICK} Rotated ${LOGFILE} ..."
|
||||||
|
fi
|
||||||
|
# Copy FTL.log over to FTL.log.1
|
||||||
|
# and empty out FTL.log
|
||||||
|
if [[ "$*" != *"quiet"* ]]; then
|
||||||
|
echo -ne " ${INFO} Rotating ${FTLFILE} ..."
|
||||||
|
fi
|
||||||
|
cp -p "${FTLFILE}" "${FTLFILE}.1"
|
||||||
|
echo " " > "${FTLFILE}"
|
||||||
|
chmod 640 "${FTLFILE}"
|
||||||
|
if [[ "$*" != *"quiet"* ]]; then
|
||||||
|
echo -e "${OVER} ${TICK} Rotated ${FTLFILE} ..."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# Manual flushing
|
||||||
|
|
||||||
|
# Flush both pihole.log and pihole.log.1 (if existing)
|
||||||
|
if [[ "$*" != *"quiet"* ]]; then
|
||||||
|
echo -ne " ${INFO} Flushing ${LOGFILE} ..."
|
||||||
|
fi
|
||||||
|
echo " " > "${LOGFILE}"
|
||||||
|
chmod 640 "${LOGFILE}"
|
||||||
|
if [ -f "${LOGFILE}.1" ]; then
|
||||||
|
echo " " > "${LOGFILE}.1"
|
||||||
|
chmod 640 "${LOGFILE}.1"
|
||||||
|
fi
|
||||||
|
if [[ "$*" != *"quiet"* ]]; then
|
||||||
|
echo -e "${OVER} ${TICK} Flushed ${LOGFILE} ..."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Flush both FTL.log and FTL.log.1 (if existing)
|
||||||
|
if [[ "$*" != *"quiet"* ]]; then
|
||||||
|
echo -ne " ${INFO} Flushing ${FTLFILE} ..."
|
||||||
|
fi
|
||||||
|
echo " " > "${FTLFILE}"
|
||||||
|
chmod 640 "${FTLFILE}"
|
||||||
|
if [ -f "${FTLFILE}.1" ]; then
|
||||||
|
echo " " > "${FTLFILE}.1"
|
||||||
|
chmod 640 "${FTLFILE}.1"
|
||||||
|
fi
|
||||||
|
if [[ "$*" != *"quiet"* ]]; then
|
||||||
|
echo -e "${OVER} ${TICK} Flushed ${FTLFILE} ..."
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$*" != *"quiet"* ]]; then
|
||||||
|
echo -ne " ${INFO} Flushing database, DNS resolution temporarily unavailable ..."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Stop FTL to make sure it doesn't write to the database while we're deleting data
|
||||||
|
service pihole-FTL stop
|
||||||
|
|
||||||
|
# Delete most recent 24 hours from FTL's database, leave even older data intact (don't wipe out all history)
|
||||||
|
deleted=$(pihole-FTL sqlite3 -ni "${DBFILE}" "DELETE FROM query_storage WHERE timestamp >= strftime('%s','now')-86400; select changes() from query_storage limit 1")
|
||||||
|
|
||||||
|
# Restart FTL
|
||||||
|
service pihole-FTL restart
|
||||||
|
if [[ "$*" != *"quiet"* ]]; then
|
||||||
|
echo -e "${OVER} ${TICK} Deleted ${deleted} queries from long-term query database"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
truncate -s 0 /var/log/pihole.log
|
|
||||||
|
|||||||
157
advanced/Scripts/query.sh
Executable file
157
advanced/Scripts/query.sh
Executable file
@@ -0,0 +1,157 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
# shellcheck disable=SC1090
|
||||||
|
|
||||||
|
# Ignore warning about `local` being undefinded in POSIX
|
||||||
|
# shellcheck disable=SC3043
|
||||||
|
# https://github.com/koalaman/shellcheck/wiki/SC3043#exceptions
|
||||||
|
|
||||||
|
# Pi-hole: A black hole for Internet advertisements
|
||||||
|
# (c) 2023 Pi-hole, LLC (https://pi-hole.net)
|
||||||
|
# Network-wide ad blocking via your own hardware.
|
||||||
|
#
|
||||||
|
# Search Adlists
|
||||||
|
#
|
||||||
|
# This file is copyright under the latest version of the EUPL.
|
||||||
|
# Please see LICENSE file for your rights under this license.
|
||||||
|
|
||||||
|
# Globals
|
||||||
|
PI_HOLE_INSTALL_DIR="/opt/pihole"
|
||||||
|
max_results="20"
|
||||||
|
partial="false"
|
||||||
|
domain=""
|
||||||
|
|
||||||
|
# Source color table
|
||||||
|
colfile="/opt/pihole/COL_TABLE"
|
||||||
|
. "${colfile}"
|
||||||
|
|
||||||
|
# Source api functions
|
||||||
|
. "${PI_HOLE_INSTALL_DIR}/api.sh"
|
||||||
|
|
||||||
|
Help() {
|
||||||
|
echo "Usage: pihole -q [option] <domain>
|
||||||
|
Example: 'pihole -q --partial domain.com'
|
||||||
|
Query the adlists for a specified domain
|
||||||
|
|
||||||
|
Options:
|
||||||
|
--partial Search the adlists for partially matching domains
|
||||||
|
--all Return all query matches within the adlists
|
||||||
|
-h, --help Show this help dialog"
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
GenerateOutput() {
|
||||||
|
local data gravity_data lists_data num_gravity num_lists search_type_str
|
||||||
|
local gravity_data_csv lists_data_csv line current_domain url type color
|
||||||
|
data="${1}"
|
||||||
|
|
||||||
|
# construct a new json for the list results where each object contains the domain and the related type
|
||||||
|
lists_data=$(printf %s "${data}" | jq '.search.domains | [.[] | {domain: .domain, type: .type}]')
|
||||||
|
|
||||||
|
# construct a new json for the gravity results where each object contains the adlist URL and the related domains
|
||||||
|
gravity_data=$(printf %s "${data}" | jq '.search.gravity | group_by(.address,.type) | map({ address: (.[0].address), type: (.[0].type), domains: [.[] | .domain] })')
|
||||||
|
|
||||||
|
# number of objects in each json
|
||||||
|
num_gravity=$(printf %s "${gravity_data}" | jq length)
|
||||||
|
num_lists=$(printf %s "${lists_data}" | jq length)
|
||||||
|
|
||||||
|
if [ "${partial}" = true ]; then
|
||||||
|
search_type_str="partially"
|
||||||
|
else
|
||||||
|
search_type_str="exactly"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Results from allow/deny list
|
||||||
|
printf "%s\n\n" "Found ${num_lists} domains ${search_type_str} matching '${COL_BLUE}${domain}${COL_NC}'."
|
||||||
|
if [ "${num_lists}" -gt 0 ]; then
|
||||||
|
# Convert the data to a csv, each line is a "domain,type" string
|
||||||
|
# not using jq's @csv here as it quotes each value individually
|
||||||
|
lists_data_csv=$(printf %s "${lists_data}" | jq --raw-output '.[] | [.domain, .type] | join(",")')
|
||||||
|
|
||||||
|
# Generate output for each csv line, separating line in a domain and type substring at the ','
|
||||||
|
echo "${lists_data_csv}" | while read -r line; do
|
||||||
|
printf "%s\n\n" " - ${COL_GREEN}${line%,*}${COL_NC} (type: exact ${line#*,} domain)"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Results from gravity
|
||||||
|
printf "%s\n\n" "Found ${num_gravity} adlists ${search_type_str} matching '${COL_BLUE}${domain}${COL_NC}'."
|
||||||
|
if [ "${num_gravity}" -gt 0 ]; then
|
||||||
|
# Convert the data to a csv, each line is a "URL,domain,domain,...." string
|
||||||
|
# not using jq's @csv here as it quotes each value individually
|
||||||
|
gravity_data_csv=$(printf %s "${gravity_data}" | jq --raw-output '.[] | [.address, .type, .domains[]] | join(",")')
|
||||||
|
|
||||||
|
# Generate line-by-line output for each csv line
|
||||||
|
echo "${gravity_data_csv}" | while read -r line; do
|
||||||
|
# Get first part of the line, the URL
|
||||||
|
url=${line%%,*}
|
||||||
|
|
||||||
|
# cut off URL, leaving "type,domain,domain,...."
|
||||||
|
line=${line#*,}
|
||||||
|
type=${line%%,*}
|
||||||
|
# type == "block" -> red, type == "allow" -> green
|
||||||
|
if [ "${type}" = "block" ]; then
|
||||||
|
color="${COL_RED}"
|
||||||
|
else
|
||||||
|
color="${COL_GREEN}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# print adlist URL
|
||||||
|
printf "%s (%s)\n\n" " - ${COL_BLUE}${url}${COL_NC}" "${color}${type}${COL_NC}"
|
||||||
|
|
||||||
|
# cut off type, leaving "domain,domain,...."
|
||||||
|
line=${line#*,}
|
||||||
|
# print each domain and remove it from the string until nothing is left
|
||||||
|
while [ ${#line} -gt 0 ]; do
|
||||||
|
current_domain=${line%%,*}
|
||||||
|
printf ' - %s\n' "${COL_GREEN}${current_domain}${COL_NC}"
|
||||||
|
# we need to remove the current_domain and the comma in two steps because
|
||||||
|
# the last domain won't have a trailing comma and the while loop wouldn't exit
|
||||||
|
line=${line#"${current_domain}"}
|
||||||
|
line=${line#,}
|
||||||
|
done
|
||||||
|
printf "\n\n"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If no exact results were found, suggest using partial matching
|
||||||
|
if [ "${num_lists}" -eq 0 ] && [ "${num_gravity}" -eq 0 ] && [ "${partial}" = false ]; then
|
||||||
|
printf "%s\n" "Hint: Try partial matching with"
|
||||||
|
printf "%s\n\n" " ${COL_GREEN}pihole -q --partial ${domain}${COL_NC}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
Main() {
|
||||||
|
local data
|
||||||
|
|
||||||
|
if [ -z "${domain}" ]; then
|
||||||
|
echo "No domain specified"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
# domains are lowercased and converted to punycode by FTL since
|
||||||
|
# https://github.com/pi-hole/FTL/pull/1715
|
||||||
|
# no need to do it here
|
||||||
|
|
||||||
|
# Authenticate with FTL
|
||||||
|
LoginAPI
|
||||||
|
|
||||||
|
# send query again
|
||||||
|
data=$(GetFTLData "search/${domain}?N=${max_results}&partial=${partial}")
|
||||||
|
|
||||||
|
GenerateOutput "${data}"
|
||||||
|
|
||||||
|
# Delete session
|
||||||
|
LogoutAPI
|
||||||
|
}
|
||||||
|
|
||||||
|
# Process all options (if present)
|
||||||
|
while [ "$#" -gt 0 ]; do
|
||||||
|
case "$1" in
|
||||||
|
"-h" | "--help") Help ;;
|
||||||
|
"--partial") partial="true" ;;
|
||||||
|
"--all") max_results=10000 ;; # hard-coded FTL limit
|
||||||
|
*) domain=$1 ;;
|
||||||
|
esac
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
Main "${domain}"
|
||||||
242
advanced/Scripts/update.sh
Executable file
242
advanced/Scripts/update.sh
Executable file
@@ -0,0 +1,242 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Pi-hole: A black hole for Internet advertisements
|
||||||
|
# (c) 2017 Pi-hole, LLC (https://pi-hole.net)
|
||||||
|
# Network-wide ad blocking via your own hardware.
|
||||||
|
#
|
||||||
|
# Check Pi-hole core and admin pages versions and determine what
|
||||||
|
# upgrade (if any) is required. Automatically updates and reinstalls
|
||||||
|
# application if update is detected.
|
||||||
|
#
|
||||||
|
# This file is copyright under the latest version of the EUPL.
|
||||||
|
# Please see LICENSE file for your rights under this license.
|
||||||
|
|
||||||
|
# Variables
|
||||||
|
readonly ADMIN_INTERFACE_GIT_URL="https://github.com/pi-hole/web.git"
|
||||||
|
readonly ADMIN_INTERFACE_DIR="/var/www/html/admin"
|
||||||
|
readonly PI_HOLE_GIT_URL="https://github.com/pi-hole/pi-hole.git"
|
||||||
|
readonly PI_HOLE_FILES_DIR="/etc/.pihole"
|
||||||
|
|
||||||
|
# shellcheck disable=SC2034
|
||||||
|
SKIP_INSTALL=true
|
||||||
|
|
||||||
|
# when --check-only is passed to this script, it will not perform the actual update
|
||||||
|
CHECK_ONLY=false
|
||||||
|
|
||||||
|
# shellcheck disable=SC1090
|
||||||
|
source "${PI_HOLE_FILES_DIR}/automated install/basic-install.sh"
|
||||||
|
# shellcheck disable=SC1091
|
||||||
|
source "/opt/pihole/COL_TABLE"
|
||||||
|
|
||||||
|
# is_repo() sourced from basic-install.sh
|
||||||
|
# make_repo() sourced from basic-install.sh
|
||||||
|
# update_repo() source from basic-install.sh
|
||||||
|
# getGitFiles() sourced from basic-install.sh
|
||||||
|
# FTLcheckUpdate() sourced from basic-install.sh
|
||||||
|
|
||||||
|
GitCheckUpdateAvail() {
|
||||||
|
local directory
|
||||||
|
local curBranch
|
||||||
|
directory="${1}"
|
||||||
|
curdir=$PWD
|
||||||
|
cd "${directory}" || exit 1
|
||||||
|
|
||||||
|
# Fetch latest changes in this repo
|
||||||
|
if ! git fetch --quiet origin ; then
|
||||||
|
echo -e "\\n ${COL_LIGHT_RED}Error: Unable to update local repository. Contact Pi-hole Support.${COL_NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check current branch. If it is master, then check for the latest available tag instead of latest commit.
|
||||||
|
curBranch=$(git rev-parse --abbrev-ref HEAD)
|
||||||
|
if [[ "${curBranch}" == "master" ]]; then
|
||||||
|
# get the latest local tag
|
||||||
|
LOCAL=$(git describe --abbrev=0 --tags master)
|
||||||
|
# get the latest tag from remote
|
||||||
|
REMOTE=$(git describe --abbrev=0 --tags origin/master)
|
||||||
|
|
||||||
|
else
|
||||||
|
# @ alone is a shortcut for HEAD. Older versions of git
|
||||||
|
# need @{0}
|
||||||
|
LOCAL="$(git rev-parse "@{0}")"
|
||||||
|
|
||||||
|
# The suffix @{upstream} to a branchname
|
||||||
|
# (short form <branchname>@{u}) refers
|
||||||
|
# to the branch that the branch specified
|
||||||
|
# by branchname is set to build on top of#
|
||||||
|
# (configured with branch.<name>.remote and
|
||||||
|
# branch.<name>.merge). A missing branchname
|
||||||
|
# defaults to the current one.
|
||||||
|
REMOTE="$(git rev-parse "@{upstream}")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
if [[ "${#LOCAL}" == 0 ]]; then
|
||||||
|
echo -e "\\n ${COL_LIGHT_RED}Error: Local revision could not be obtained, please contact Pi-hole Support"
|
||||||
|
echo -e " Additional debugging output:${COL_NC}"
|
||||||
|
git status
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [[ "${#REMOTE}" == 0 ]]; then
|
||||||
|
echo -e "\\n ${COL_LIGHT_RED}Error: Remote revision could not be obtained, please contact Pi-hole Support"
|
||||||
|
echo -e " Additional debugging output:${COL_NC}"
|
||||||
|
git status
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Change back to original directory
|
||||||
|
cd "${curdir}" || exit 1
|
||||||
|
|
||||||
|
if [[ "${LOCAL}" != "${REMOTE}" ]]; then
|
||||||
|
# Local branch is behind remote branch -> Update
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
# Local branch is up-to-date or in a situation
|
||||||
|
# where this updater cannot be used (like on a
|
||||||
|
# branch that exists only locally)
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
local basicError="\\n ${COL_LIGHT_RED}Unable to complete update, please contact Pi-hole Support${COL_NC}"
|
||||||
|
local core_update
|
||||||
|
local web_update
|
||||||
|
local FTL_update
|
||||||
|
|
||||||
|
core_update=false
|
||||||
|
web_update=false
|
||||||
|
FTL_update=false
|
||||||
|
|
||||||
|
# Install packages used by this installation script (necessary if users have removed e.g. git from their systems)
|
||||||
|
package_manager_detect
|
||||||
|
build_dependency_package
|
||||||
|
install_dependent_packages
|
||||||
|
|
||||||
|
# This is unlikely
|
||||||
|
if ! is_repo "${PI_HOLE_FILES_DIR}" ; then
|
||||||
|
echo -e "\\n ${COL_LIGHT_RED}Error: Core Pi-hole repo is missing from system!"
|
||||||
|
echo -e " Please re-run install script from https://pi-hole.net${COL_NC}"
|
||||||
|
exit 1;
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e " ${INFO} Checking for updates..."
|
||||||
|
|
||||||
|
if GitCheckUpdateAvail "${PI_HOLE_FILES_DIR}" ; then
|
||||||
|
core_update=true
|
||||||
|
echo -e " ${INFO} Pi-hole Core:\\t${COL_YELLOW}update available${COL_NC}"
|
||||||
|
else
|
||||||
|
core_update=false
|
||||||
|
echo -e " ${INFO} Pi-hole Core:\\t${COL_LIGHT_GREEN}up to date${COL_NC}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! is_repo "${ADMIN_INTERFACE_DIR}" ; then
|
||||||
|
echo -e "\\n ${COL_LIGHT_RED}Error: Web Admin repo is missing from system!"
|
||||||
|
echo -e " Please re-run install script from https://pi-hole.net${COL_NC}"
|
||||||
|
exit 1;
|
||||||
|
fi
|
||||||
|
|
||||||
|
if GitCheckUpdateAvail "${ADMIN_INTERFACE_DIR}" ; then
|
||||||
|
web_update=true
|
||||||
|
echo -e " ${INFO} Web Interface:\\t${COL_YELLOW}update available${COL_NC}"
|
||||||
|
else
|
||||||
|
web_update=false
|
||||||
|
echo -e " ${INFO} Web Interface:\\t${COL_LIGHT_GREEN}up to date${COL_NC}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
local funcOutput
|
||||||
|
funcOutput=$(get_binary_name) #Store output of get_binary_name here
|
||||||
|
local binary
|
||||||
|
binary="pihole-FTL${funcOutput##*pihole-FTL}" #binary name will be the last line of the output of get_binary_name (it always begins with pihole-FTL)
|
||||||
|
|
||||||
|
if FTLcheckUpdate "${binary}" &>/dev/null; then
|
||||||
|
FTL_update=true
|
||||||
|
echo -e " ${INFO} FTL:\\t\\t${COL_YELLOW}update available${COL_NC}"
|
||||||
|
else
|
||||||
|
case $? in
|
||||||
|
1)
|
||||||
|
echo -e " ${INFO} FTL:\\t\\t${COL_LIGHT_GREEN}up to date${COL_NC}"
|
||||||
|
;;
|
||||||
|
2)
|
||||||
|
echo -e " ${INFO} FTL:\\t\\t${COL_LIGHT_RED}Branch is not available.${COL_NC}\\n\\t\\t\\tUse ${COL_LIGHT_GREEN}pihole checkout ftl [branchname]${COL_NC} to switch to a valid branch."
|
||||||
|
;;
|
||||||
|
3)
|
||||||
|
echo -e " ${INFO} FTL:\\t\\t${COL_LIGHT_RED}Something has gone wrong, cannot reach download server${COL_NC}"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo -e " ${INFO} FTL:\\t\\t${COL_LIGHT_RED}Something has gone wrong, contact support${COL_NC}"
|
||||||
|
exit 1
|
||||||
|
esac
|
||||||
|
FTL_update=false
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Determine FTL branch
|
||||||
|
local ftlBranch
|
||||||
|
if [[ -f "/etc/pihole/ftlbranch" ]]; then
|
||||||
|
ftlBranch=$(</etc/pihole/ftlbranch)
|
||||||
|
else
|
||||||
|
ftlBranch="master"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! "${ftlBranch}" == "master" && ! "${ftlBranch}" == "development" ]]; then
|
||||||
|
# Notify user that they are on a custom branch which might mean they they are lost
|
||||||
|
# behind if a branch was merged to development and got abandoned
|
||||||
|
printf " %b %bWarning:%b You are using FTL from a custom branch (%s) and might be missing future releases.\\n" "${INFO}" "${COL_LIGHT_RED}" "${COL_NC}" "${ftlBranch}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "${core_update}" == false && "${web_update}" == false && "${FTL_update}" == false ]]; then
|
||||||
|
echo ""
|
||||||
|
echo -e " ${TICK} Everything is up to date!"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "${CHECK_ONLY}" == true ]]; then
|
||||||
|
echo ""
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "${core_update}" == true ]]; then
|
||||||
|
echo ""
|
||||||
|
echo -e " ${INFO} Pi-hole core files out of date, updating local repo."
|
||||||
|
getGitFiles "${PI_HOLE_FILES_DIR}" "${PI_HOLE_GIT_URL}"
|
||||||
|
echo -e " ${INFO} If you had made any changes in '/etc/.pihole/', they have been stashed using 'git stash'"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "${web_update}" == true ]]; then
|
||||||
|
echo ""
|
||||||
|
echo -e " ${INFO} Pi-hole Web Admin files out of date, updating local repo."
|
||||||
|
getGitFiles "${ADMIN_INTERFACE_DIR}" "${ADMIN_INTERFACE_GIT_URL}"
|
||||||
|
echo -e " ${INFO} If you had made any changes in '/var/www/html/admin/', they have been stashed using 'git stash'"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "${FTL_update}" == true ]]; then
|
||||||
|
echo ""
|
||||||
|
echo -e " ${INFO} FTL out of date, it will be updated by the installer."
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "${FTL_update}" == true || "${core_update}" == true ]]; then
|
||||||
|
${PI_HOLE_FILES_DIR}/automated\ install/basic-install.sh --reconfigure --unattended || \
|
||||||
|
echo -e "${basicError}" && exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "${FTL_update}" == true || "${core_update}" == true || "${web_update}" == true ]]; then
|
||||||
|
# Update local and remote versions via updatechecker
|
||||||
|
/opt/pihole/updatecheck.sh
|
||||||
|
echo -e " ${INFO} Local version file information updated."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# if there was only a web update, show the new versions
|
||||||
|
# (on core and FTL updates, this is done as part of the installer run)
|
||||||
|
if [[ "${web_update}" == true && "${FTL_update}" == false && "${core_update}" == false ]]; then
|
||||||
|
"${PI_HOLE_BIN_DIR}"/pihole version
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if [[ "$1" == "--check-only" ]]; then
|
||||||
|
CHECK_ONLY=true
|
||||||
|
fi
|
||||||
|
|
||||||
|
main
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
#
|
|
||||||
# this script will update the pihole web interface files.
|
|
||||||
#
|
|
||||||
# if this is the first time running this script after an
|
|
||||||
# existing installation, the existing web interface files
|
|
||||||
# will be removed and replaced with the latest master
|
|
||||||
# branch from github. subsequent executions of this script
|
|
||||||
# will pull the latest version of the web interface.
|
|
||||||
#
|
|
||||||
# @TODO: add git as requirement to basic-install.sh
|
|
||||||
#
|
|
||||||
|
|
||||||
WEB_INTERFACE_GIT_URL="https://github.com/pi-hole/AdminLTE.git"
|
|
||||||
WEB_INTERFACE_DIR="/var/www/html/admin"
|
|
||||||
|
|
||||||
main() {
|
|
||||||
prerequisites
|
|
||||||
if ! is_repo; then
|
|
||||||
make_repo
|
|
||||||
fi
|
|
||||||
update_repo
|
|
||||||
}
|
|
||||||
|
|
||||||
prerequisites() {
|
|
||||||
|
|
||||||
# must be root to update
|
|
||||||
if [[ $EUID -ne 0 ]]; then
|
|
||||||
sudo bash "$0" "$@"
|
|
||||||
exit $?
|
|
||||||
fi
|
|
||||||
|
|
||||||
# web interface must already exist. this is a (lazy)
|
|
||||||
# check to make sure pihole is actually installed.
|
|
||||||
if [ ! -d "$WEB_INTERFACE_DIR" ]; then
|
|
||||||
echo "$WEB_INTERFACE_DIR not found. Exiting."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ! type "git" > /dev/null; then
|
|
||||||
apt-get -y install git
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
is_repo() {
|
|
||||||
# if the web interface directory does not have a .git folder
|
|
||||||
# it means its using the master.zip archive from the install
|
|
||||||
# script.
|
|
||||||
if [ ! -d "$WEB_INTERFACE_DIR/.git" ]; then
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
# removes the web interface installed from the master.zip archive and
|
|
||||||
# replaces it with the current master branch from github
|
|
||||||
make_repo() {
|
|
||||||
# remove the non-repod interface and clone the interface
|
|
||||||
rm -rf $WEB_INTERFACE_DIR
|
|
||||||
git clone "$WEB_INTERFACE_GIT_URL" "$WEB_INTERFACE_DIR"
|
|
||||||
}
|
|
||||||
|
|
||||||
# pulls the latest master branch from github
|
|
||||||
update_repo() {
|
|
||||||
# pull the latest commits
|
|
||||||
cd "$WEB_INTERFACE_DIR"
|
|
||||||
git pull
|
|
||||||
}
|
|
||||||
|
|
||||||
main
|
|
||||||
133
advanced/Scripts/updatecheck.sh
Executable file
133
advanced/Scripts/updatecheck.sh
Executable file
@@ -0,0 +1,133 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Pi-hole: A black hole for Internet advertisements
|
||||||
|
# (c) 2017 Pi-hole, LLC (https://pi-hole.net)
|
||||||
|
# Network-wide ad blocking via your own hardware.
|
||||||
|
#
|
||||||
|
# Checks for local or remote versions and branches
|
||||||
|
#
|
||||||
|
# This file is copyright under the latest version of the EUPL.
|
||||||
|
# Please see LICENSE file for your rights under this license.
|
||||||
|
|
||||||
|
function get_local_branch() {
|
||||||
|
# Return active branch
|
||||||
|
cd "${1}" 2>/dev/null || return 1
|
||||||
|
git rev-parse --abbrev-ref HEAD || return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_local_version() {
|
||||||
|
# Return active version
|
||||||
|
cd "${1}" 2>/dev/null || return 1
|
||||||
|
git describe --tags --always 2>/dev/null || return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_local_hash() {
|
||||||
|
cd "${1}" 2>/dev/null || return 1
|
||||||
|
git rev-parse --short=8 HEAD || return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_remote_version() {
|
||||||
|
# if ${2} is = "master" we need to use the "latest" endpoint, otherwise, we simply return null
|
||||||
|
if [[ "${2}" == "master" ]]; then
|
||||||
|
curl -s "https://api.github.com/repos/pi-hole/${1}/releases/latest" 2>/dev/null | jq --raw-output .tag_name || return 1
|
||||||
|
else
|
||||||
|
echo "null"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_remote_hash() {
|
||||||
|
git ls-remote "https://github.com/pi-hole/${1}" --tags "${2}" | awk '{print substr($0, 1,8);}' || return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Source the utils file for addOrEditKeyValPair()
|
||||||
|
# shellcheck disable=SC1091
|
||||||
|
. /opt/pihole/utils.sh
|
||||||
|
|
||||||
|
# Remove the below three legacy files if they exist
|
||||||
|
rm -f "/etc/pihole/GitHubVersions"
|
||||||
|
rm -f "/etc/pihole/localbranches"
|
||||||
|
rm -f "/etc/pihole/localversions"
|
||||||
|
|
||||||
|
# Create new versions file if it does not exist
|
||||||
|
VERSION_FILE="/etc/pihole/versions"
|
||||||
|
touch "${VERSION_FILE}"
|
||||||
|
chmod 644 "${VERSION_FILE}"
|
||||||
|
|
||||||
|
# if /pihole.docker.tag file exists, we will use it's value later in this script
|
||||||
|
DOCKER_TAG=$(cat /pihole.docker.tag 2>/dev/null)
|
||||||
|
release_regex='^([0-9]+\.){1,2}(\*|[0-9]+)(-.*)?$'
|
||||||
|
regex=$release_regex'|(^nightly$)|(^dev.*$)'
|
||||||
|
if [[ ! "${DOCKER_TAG}" =~ $regex ]]; then
|
||||||
|
# DOCKER_TAG does not match the pattern (see https://regex101.com/r/RsENuz/1), so unset it.
|
||||||
|
unset DOCKER_TAG
|
||||||
|
fi
|
||||||
|
|
||||||
|
# used in cronjob
|
||||||
|
if [[ "$1" == "reboot" ]]; then
|
||||||
|
sleep 30
|
||||||
|
fi
|
||||||
|
|
||||||
|
# get Core versions
|
||||||
|
|
||||||
|
CORE_VERSION="$(get_local_version /etc/.pihole)"
|
||||||
|
addOrEditKeyValPair "${VERSION_FILE}" "CORE_VERSION" "${CORE_VERSION}"
|
||||||
|
|
||||||
|
CORE_BRANCH="$(get_local_branch /etc/.pihole)"
|
||||||
|
addOrEditKeyValPair "${VERSION_FILE}" "CORE_BRANCH" "${CORE_BRANCH}"
|
||||||
|
|
||||||
|
CORE_HASH="$(get_local_hash /etc/.pihole)"
|
||||||
|
addOrEditKeyValPair "${VERSION_FILE}" "CORE_HASH" "${CORE_HASH}"
|
||||||
|
|
||||||
|
GITHUB_CORE_VERSION="$(get_remote_version pi-hole "${CORE_BRANCH}")"
|
||||||
|
addOrEditKeyValPair "${VERSION_FILE}" "GITHUB_CORE_VERSION" "${GITHUB_CORE_VERSION}"
|
||||||
|
|
||||||
|
GITHUB_CORE_HASH="$(get_remote_hash pi-hole "${CORE_BRANCH}")"
|
||||||
|
addOrEditKeyValPair "${VERSION_FILE}" "GITHUB_CORE_HASH" "${GITHUB_CORE_HASH}"
|
||||||
|
|
||||||
|
# get Web versions
|
||||||
|
|
||||||
|
WEB_VERSION="$(get_local_version /var/www/html/admin)"
|
||||||
|
addOrEditKeyValPair "${VERSION_FILE}" "WEB_VERSION" "${WEB_VERSION}"
|
||||||
|
|
||||||
|
WEB_BRANCH="$(get_local_branch /var/www/html/admin)"
|
||||||
|
addOrEditKeyValPair "${VERSION_FILE}" "WEB_BRANCH" "${WEB_BRANCH}"
|
||||||
|
|
||||||
|
WEB_HASH="$(get_local_hash /var/www/html/admin)"
|
||||||
|
addOrEditKeyValPair "${VERSION_FILE}" "WEB_HASH" "${WEB_HASH}"
|
||||||
|
|
||||||
|
GITHUB_WEB_VERSION="$(get_remote_version web "${WEB_BRANCH}")"
|
||||||
|
addOrEditKeyValPair "${VERSION_FILE}" "GITHUB_WEB_VERSION" "${GITHUB_WEB_VERSION}"
|
||||||
|
|
||||||
|
GITHUB_WEB_HASH="$(get_remote_hash web "${WEB_BRANCH}")"
|
||||||
|
addOrEditKeyValPair "${VERSION_FILE}" "GITHUB_WEB_HASH" "${GITHUB_WEB_HASH}"
|
||||||
|
|
||||||
|
# get FTL versions
|
||||||
|
|
||||||
|
FTL_VERSION="$(pihole-FTL version)"
|
||||||
|
addOrEditKeyValPair "${VERSION_FILE}" "FTL_VERSION" "${FTL_VERSION}"
|
||||||
|
|
||||||
|
FTL_BRANCH="$(pihole-FTL branch)"
|
||||||
|
addOrEditKeyValPair "${VERSION_FILE}" "FTL_BRANCH" "${FTL_BRANCH}"
|
||||||
|
|
||||||
|
FTL_HASH="$(pihole-FTL --hash)"
|
||||||
|
addOrEditKeyValPair "${VERSION_FILE}" "FTL_HASH" "${FTL_HASH}"
|
||||||
|
|
||||||
|
GITHUB_FTL_VERSION="$(get_remote_version FTL "${FTL_BRANCH}")"
|
||||||
|
addOrEditKeyValPair "${VERSION_FILE}" "GITHUB_FTL_VERSION" "${GITHUB_FTL_VERSION}"
|
||||||
|
|
||||||
|
GITHUB_FTL_HASH="$(get_remote_hash FTL "${FTL_BRANCH}")"
|
||||||
|
addOrEditKeyValPair "${VERSION_FILE}" "GITHUB_FTL_HASH" "${GITHUB_FTL_HASH}"
|
||||||
|
|
||||||
|
# get Docker versions
|
||||||
|
|
||||||
|
if [[ "${DOCKER_TAG}" ]]; then
|
||||||
|
addOrEditKeyValPair "${VERSION_FILE}" "DOCKER_VERSION" "${DOCKER_TAG}"
|
||||||
|
|
||||||
|
# Remote version check only if the tag is a valid release version
|
||||||
|
docker_branch=""
|
||||||
|
if [[ "${DOCKER_TAG}" =~ $release_regex ]]; then
|
||||||
|
docker_branch="master"
|
||||||
|
fi
|
||||||
|
|
||||||
|
GITHUB_DOCKER_VERSION="$(get_remote_version docker-pi-hole "${docker_branch}")"
|
||||||
|
addOrEditKeyValPair "${VERSION_FILE}" "GITHUB_DOCKER_VERSION" "${GITHUB_DOCKER_VERSION}"
|
||||||
|
fi
|
||||||
95
advanced/Scripts/utils.sh
Executable file
95
advanced/Scripts/utils.sh
Executable file
@@ -0,0 +1,95 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
# shellcheck disable=SC3043 #https://github.com/koalaman/shellcheck/wiki/SC3043#exceptions
|
||||||
|
|
||||||
|
# Pi-hole: A black hole for Internet advertisements
|
||||||
|
# (c) 2017 Pi-hole, LLC (https://pi-hole.net)
|
||||||
|
# Network-wide ad blocking via your own hardware.
|
||||||
|
#
|
||||||
|
# Script to hold utility functions for use in other scripts
|
||||||
|
#
|
||||||
|
# This file is copyright under the latest version of the EUPL.
|
||||||
|
# Please see LICENSE file for your rights under this license.
|
||||||
|
|
||||||
|
# Basic Housekeeping rules
|
||||||
|
# - Functions must be self contained
|
||||||
|
# - Functions should be grouped with other similar functions
|
||||||
|
# - Functions must be documented
|
||||||
|
# - New functions must have a test added for them in test/test_any_utils.py
|
||||||
|
|
||||||
|
#######################
|
||||||
|
# Takes Three arguments: file, key, and value.
|
||||||
|
#
|
||||||
|
# Checks the target file for the existence of the key
|
||||||
|
# - If it exists, it changes the value
|
||||||
|
# - If it does not exist, it adds the value
|
||||||
|
#
|
||||||
|
# Example usage:
|
||||||
|
# addOrEditKeyValPair "/etc/pihole/setupVars.conf" "BLOCKING_ENABLED" "true"
|
||||||
|
#######################
|
||||||
|
addOrEditKeyValPair() {
|
||||||
|
local file="${1}"
|
||||||
|
local key="${2}"
|
||||||
|
local value="${3}"
|
||||||
|
|
||||||
|
# touch file to prevent grep error if file does not exist yet
|
||||||
|
touch "${file}"
|
||||||
|
|
||||||
|
if grep -q "^${key}=" "${file}"; then
|
||||||
|
# Key already exists in file, modify the value
|
||||||
|
sed -i "/^${key}=/c\\${key}=${value}" "${file}"
|
||||||
|
else
|
||||||
|
# Key does not already exist, add it and it's value
|
||||||
|
echo "${key}=${value}" >> "${file}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
#######################
|
||||||
|
# returns FTL's PID based on the content of the pihole-FTL.pid file
|
||||||
|
#
|
||||||
|
# Takes one argument: path to pihole-FTL.pid
|
||||||
|
# Example getFTLPID "/run/pihole-FTL.pid"
|
||||||
|
#######################
|
||||||
|
getFTLPID() {
|
||||||
|
local FTL_PID_FILE="${1}"
|
||||||
|
local FTL_PID
|
||||||
|
|
||||||
|
if [ -s "${FTL_PID_FILE}" ]; then
|
||||||
|
# -s: FILE exists and has a size greater than zero
|
||||||
|
FTL_PID="$(cat "${FTL_PID_FILE}")"
|
||||||
|
# Exploit prevention: unset the variable if there is malicious content
|
||||||
|
# Verify that the value read from the file is numeric
|
||||||
|
expr "${FTL_PID}" : "[^[:digit:]]" > /dev/null && unset FTL_PID
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If FTL is not running, or the PID file contains malicious stuff, substitute
|
||||||
|
# negative PID to signal this
|
||||||
|
FTL_PID=${FTL_PID:=-1}
|
||||||
|
echo "${FTL_PID}"
|
||||||
|
}
|
||||||
|
|
||||||
|
#######################
|
||||||
|
# returns value from FTLs config file using pihole-FTL --config
|
||||||
|
#
|
||||||
|
# Takes one argument: key
|
||||||
|
# Example getFTLConfigValue dns.piholePTR
|
||||||
|
#######################
|
||||||
|
getFTLConfigValue(){
|
||||||
|
pihole-FTL --config -q "${1}"
|
||||||
|
}
|
||||||
|
|
||||||
|
#######################
|
||||||
|
# sets value in FTLs config file using pihole-FTL --config
|
||||||
|
#
|
||||||
|
# Takes two arguments: key and value
|
||||||
|
# Example setFTLConfigValue dns.piholePTR PI.HOLE
|
||||||
|
#
|
||||||
|
# Note, for complex values such as dns.upstreams, you should wrap the value in single quotes:
|
||||||
|
# setFTLConfigValue dns.upstreams '[ "8.8.8.8" , "8.8.4.4" ]'
|
||||||
|
#######################
|
||||||
|
setFTLConfigValue(){
|
||||||
|
pihole-FTL --config "${1}" "${2}" >/dev/null
|
||||||
|
if [[ $? -eq 5 ]]; then
|
||||||
|
echo -e " ${CROSS} ${1} set by environment variable. Please unset it to use this function"
|
||||||
|
exit 5
|
||||||
|
fi
|
||||||
|
}
|
||||||
58
advanced/Scripts/version.sh
Executable file
58
advanced/Scripts/version.sh
Executable file
@@ -0,0 +1,58 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
# Pi-hole: A black hole for Internet advertisements
|
||||||
|
# (c) 2017 Pi-hole, LLC (https://pi-hole.net)
|
||||||
|
# Network-wide ad blocking via your own hardware.
|
||||||
|
#
|
||||||
|
# Show version numbers
|
||||||
|
#
|
||||||
|
# This file is copyright under the latest version of the EUPL.
|
||||||
|
# Please see LICENSE file for your rights under this license.
|
||||||
|
|
||||||
|
# Ignore warning about `local` being undefinded in POSIX
|
||||||
|
# shellcheck disable=SC3043
|
||||||
|
# https://github.com/koalaman/shellcheck/wiki/SC3043#exceptions
|
||||||
|
|
||||||
|
# Source the versions file poupulated by updatechecker.sh
|
||||||
|
cachedVersions="/etc/pihole/versions"
|
||||||
|
|
||||||
|
if [ -f ${cachedVersions} ]; then
|
||||||
|
# shellcheck disable=SC1090
|
||||||
|
. "$cachedVersions"
|
||||||
|
else
|
||||||
|
echo "Could not find /etc/pihole/versions. Running update now."
|
||||||
|
pihole updatechecker
|
||||||
|
# shellcheck disable=SC1090
|
||||||
|
. "$cachedVersions"
|
||||||
|
fi
|
||||||
|
|
||||||
|
main() {
|
||||||
|
local details
|
||||||
|
details=false
|
||||||
|
|
||||||
|
# Automatically show detailed information if
|
||||||
|
# at least one of the components is not on master branch
|
||||||
|
if [ ! "${CORE_BRANCH}" = "master" ] || [ ! "${WEB_BRANCH}" = "master" ] || [ ! "${FTL_BRANCH}" = "master" ]; then
|
||||||
|
details=true
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "${details}" = true ]; then
|
||||||
|
echo "Core"
|
||||||
|
echo " Version is ${CORE_VERSION:=N/A} (Latest: ${GITHUB_CORE_VERSION:=N/A})"
|
||||||
|
echo " Branch is ${CORE_BRANCH:=N/A}"
|
||||||
|
echo " Hash is ${CORE_HASH:=N/A} (Latest: ${GITHUB_CORE_HASH:=N/A})"
|
||||||
|
echo "Web"
|
||||||
|
echo " Version is ${WEB_VERSION:=N/A} (Latest: ${GITHUB_WEB_VERSION:=N/A})"
|
||||||
|
echo " Branch is ${WEB_BRANCH:=N/A}"
|
||||||
|
echo " Hash is ${WEB_HASH:=N/A} (Latest: ${GITHUB_WEB_HASH:=N/A})"
|
||||||
|
echo "FTL"
|
||||||
|
echo " Version is ${FTL_VERSION:=N/A} (Latest: ${GITHUB_FTL_VERSION:=N/A})"
|
||||||
|
echo " Branch is ${FTL_BRANCH:=N/A}"
|
||||||
|
echo " Hash is ${FTL_HASH:=N/A} (Latest: ${GITHUB_FTL_HASH:=N/A})"
|
||||||
|
else
|
||||||
|
echo "Core version is ${CORE_VERSION:=N/A} (Latest: ${GITHUB_CORE_VERSION:=N/A})"
|
||||||
|
echo "Web version is ${WEB_VERSION:=N/A} (Latest: ${GITHUB_WEB_VERSION:=N/A})"
|
||||||
|
echo "FTL version is ${FTL_VERSION:=N/A} (Latest: ${GITHUB_FTL_VERSION:=N/A})"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
main
|
||||||
@@ -1,201 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
# (c) 2015 by Jacob Salmela
|
|
||||||
# This file is part of Pi-hole.
|
|
||||||
#
|
|
||||||
# Pi-hole is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation, either version 2 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
|
|
||||||
if [[ $# = 0 ]]; then
|
|
||||||
echo "Immediately whitelists one or more domains in the hosts file"
|
|
||||||
echo " "
|
|
||||||
echo "Usage: whitelist.sh domain1 [domain2 ...]"
|
|
||||||
echo " "
|
|
||||||
echo "Options:"
|
|
||||||
echo " -d, --delmode Remove domains from the whitelist"
|
|
||||||
echo " -nr, --noreload Update Whitelist without refreshing dnsmasq"
|
|
||||||
echo " -f, --force Force updating of the hosts files, even if there are no changes"
|
|
||||||
echo " -q, --quiet output is less verbose"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
#globals
|
|
||||||
whitelist=/etc/pihole/whitelist.txt
|
|
||||||
adList=/etc/pihole/gravity.list
|
|
||||||
reload=true
|
|
||||||
addmode=true
|
|
||||||
force=false
|
|
||||||
versbose=true
|
|
||||||
domList=()
|
|
||||||
domToRemoveList=()
|
|
||||||
|
|
||||||
piholeIPfile=/tmp/piholeIP
|
|
||||||
piholeIPv6file=/etc/pihole/.useIPv6
|
|
||||||
|
|
||||||
# Otherwise, the IP address can be taken directly from the machine, which will happen when the script is run by the user and not the installation script
|
|
||||||
IPv4dev=$(ip route get 8.8.8.8 | awk '{for(i=1;i<=NF;i++)if($i~/dev/)print $(i+1)}')
|
|
||||||
piholeIPCIDR=$(ip -o -f inet addr show dev $IPv4dev | awk '{print $4}' | awk 'END {print}')
|
|
||||||
piholeIP=${piholeIPCIDR%/*}
|
|
||||||
|
|
||||||
modifyHost=false
|
|
||||||
|
|
||||||
|
|
||||||
if [[ -f $piholeIPv6file ]];then
|
|
||||||
# If the file exists, then the user previously chose to use IPv6 in the automated installer
|
|
||||||
piholeIPv6=$(ip -6 route get 2001:4860:4860::8888 | awk -F " " '{ for(i=1;i<=NF;i++) if ($i == "src") print $(i+1) }')
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
function HandleOther(){
|
|
||||||
#check validity of domain
|
|
||||||
validDomain=$(echo $1 | perl -ne'print if /\b((?=[a-z0-9-]{1,63}\.)(xn--)?[a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,63}\b/')
|
|
||||||
|
|
||||||
if [ -z "$validDomain" ]; then
|
|
||||||
echo "::: $1 is not a valid argument or domain name"
|
|
||||||
else
|
|
||||||
domList=("${domList[@]}" $validDomain)
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
function PopWhitelistFile(){
|
|
||||||
#check whitelist file exists, and if not, create it
|
|
||||||
if [[ ! -f $whitelist ]];then
|
|
||||||
touch $whitelist
|
|
||||||
fi
|
|
||||||
for dom in "${domList[@]}"
|
|
||||||
do
|
|
||||||
if $addmode; then
|
|
||||||
AddDomain $dom
|
|
||||||
else
|
|
||||||
RemoveDomain $dom
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
function AddDomain(){
|
|
||||||
#| sed 's/\./\\./g'
|
|
||||||
bool=false
|
|
||||||
|
|
||||||
grep -Ex -q "$1" $whitelist || bool=true
|
|
||||||
if $bool; then
|
|
||||||
#domain not found in the whitelist file, add it!
|
|
||||||
if $versbose; then
|
|
||||||
echo -n "::: Adding $1 to whitelist.txt..."
|
|
||||||
fi
|
|
||||||
echo $1 >> $whitelist
|
|
||||||
modifyHost=true
|
|
||||||
if $versbose; then
|
|
||||||
echo " done!"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
if $versbose; then
|
|
||||||
echo "::: $1 already exists in whitelist.txt, no need to add!"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
function RemoveDomain(){
|
|
||||||
|
|
||||||
bool=false
|
|
||||||
grep -Ex -q "$1" $whitelist || bool=true
|
|
||||||
if $bool; then
|
|
||||||
#Domain is not in the whitelist file, no need to Remove
|
|
||||||
if $versbose; then
|
|
||||||
echo "::: $1 is NOT whitelisted! No need to remove"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
#Domain is in the whitelist file, add to a temporary array and remove from whitelist file
|
|
||||||
#if $versbose; then
|
|
||||||
#echo "::: Un-whitelisting $dom..."
|
|
||||||
#fi
|
|
||||||
domToRemoveList=("${domToRemoveList[@]}" $1)
|
|
||||||
modifyHost=true
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
function ModifyHostFile(){
|
|
||||||
if $addmode; then
|
|
||||||
#remove domains in from hosts file
|
|
||||||
if [[ -r $whitelist ]];then
|
|
||||||
# Remove whitelist entries
|
|
||||||
numberOf=$(cat $whitelist | sed '/^\s*$/d' | wc -l)
|
|
||||||
plural=; [[ "$numberOf" != "1" ]] && plural=s
|
|
||||||
echo ":::"
|
|
||||||
echo -n "::: Modifying HOSTS file to whitelist $numberOf domain${plural}..."
|
|
||||||
awk -F':' '{print $1}' $whitelist | while read line; do echo "$piholeIP $line"; done > /etc/pihole/whitelist.tmp
|
|
||||||
awk -F':' '{print $1}' $whitelist | while read line; do echo "$piholeIPv6 $line"; done >> /etc/pihole/whitelist.tmp
|
|
||||||
echo "l" >> /etc/pihole/whitelist.tmp
|
|
||||||
grep -F -x -v -f /etc/pihole/whitelist.tmp /etc/pihole/gravity.list > /etc/pihole/gravity.tmp
|
|
||||||
rm /etc/pihole/gravity.list
|
|
||||||
mv /etc/pihole/gravity.tmp /etc/pihole/gravity.list
|
|
||||||
rm /etc/pihole/whitelist.tmp
|
|
||||||
echo " done!"
|
|
||||||
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
#we need to add the removed domains to the hosts file
|
|
||||||
echo ":::"
|
|
||||||
echo "::: Modifying HOSTS file to un-whitelist domains..."
|
|
||||||
for rdom in "${domToRemoveList[@]}"
|
|
||||||
do
|
|
||||||
if [[ -n $piholeIPv6 ]];then
|
|
||||||
echo -n "::: Un-whitelisting $rdom on IPv4 and IPv6..."
|
|
||||||
echo $rdom | awk -v ipv4addr="$piholeIP" -v ipv6addr="$piholeIPv6" '{sub(/\r$/,""); print ipv4addr" "$0"\n"ipv6addr" "$0}' >> $adList
|
|
||||||
echo " done!"
|
|
||||||
else
|
|
||||||
echo -n "::: Un-whitelisting $rdom on IPv4"
|
|
||||||
echo $rdom | awk -v ipv4addr="$piholeIP" '{sub(/\r$/,""); print ipv4addr" "$0}' >>$adList
|
|
||||||
echo " done!"
|
|
||||||
fi
|
|
||||||
echo -n "::: Removing $rdom from whitelist.txt..."
|
|
||||||
echo $rdom| sed 's/\./\\./g' | xargs -I {} perl -i -ne'print unless /'{}'(?!.)/;' $whitelist
|
|
||||||
echo " done!"
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
function Reload() {
|
|
||||||
# Reload hosts file
|
|
||||||
echo ":::"
|
|
||||||
echo -n "::: Refresh lists in dnsmasq..."
|
|
||||||
dnsmasqPid=$(pidof dnsmasq)
|
|
||||||
|
|
||||||
if [[ $dnsmasqPid ]]; then
|
|
||||||
# service already running - reload config
|
|
||||||
sudo kill -HUP $dnsmasqPid
|
|
||||||
else
|
|
||||||
# service not running, start it up
|
|
||||||
sudo service dnsmasq start
|
|
||||||
fi
|
|
||||||
echo " done!"
|
|
||||||
}
|
|
||||||
|
|
||||||
###################################################
|
|
||||||
|
|
||||||
for var in "$@"
|
|
||||||
do
|
|
||||||
case "$var" in
|
|
||||||
"-nr"| "--noreload" ) reload=false;;
|
|
||||||
"-d" | "--delmode" ) addmode=false;;
|
|
||||||
"-f" | "--force" ) force=true;;
|
|
||||||
"-q" | "--quiet" ) versbose=false;;
|
|
||||||
* ) HandleOther $var;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
PopWhitelistFile
|
|
||||||
|
|
||||||
if $modifyHost || $force; then
|
|
||||||
ModifyHostFile
|
|
||||||
else
|
|
||||||
if $versbose; then
|
|
||||||
echo ":::"
|
|
||||||
echo "::: No changes need to be made"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if $reload; then
|
|
||||||
Reload
|
|
||||||
fi
|
|
||||||
200
advanced/Templates/gravity.db.sql
Normal file
200
advanced/Templates/gravity.db.sql
Normal file
@@ -0,0 +1,200 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN TRANSACTION;
|
||||||
|
|
||||||
|
CREATE TABLE "group"
|
||||||
|
(
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
enabled BOOLEAN NOT NULL DEFAULT 1,
|
||||||
|
name TEXT UNIQUE NOT NULL,
|
||||||
|
date_added INTEGER NOT NULL DEFAULT (cast(strftime('%s', 'now') as int)),
|
||||||
|
date_modified INTEGER NOT NULL DEFAULT (cast(strftime('%s', 'now') as int)),
|
||||||
|
description TEXT
|
||||||
|
);
|
||||||
|
INSERT INTO "group" (id,enabled,name,description) VALUES (0,1,'Default','The default group');
|
||||||
|
|
||||||
|
CREATE TABLE domainlist
|
||||||
|
(
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
type INTEGER NOT NULL DEFAULT 0,
|
||||||
|
domain TEXT NOT NULL,
|
||||||
|
enabled BOOLEAN NOT NULL DEFAULT 1,
|
||||||
|
date_added INTEGER NOT NULL DEFAULT (cast(strftime('%s', 'now') as int)),
|
||||||
|
date_modified INTEGER NOT NULL DEFAULT (cast(strftime('%s', 'now') as int)),
|
||||||
|
comment TEXT,
|
||||||
|
UNIQUE(domain, type)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE adlist
|
||||||
|
(
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
address TEXT NOT NULL,
|
||||||
|
enabled BOOLEAN NOT NULL DEFAULT 1,
|
||||||
|
date_added INTEGER NOT NULL DEFAULT (cast(strftime('%s', 'now') as int)),
|
||||||
|
date_modified INTEGER NOT NULL DEFAULT (cast(strftime('%s', 'now') as int)),
|
||||||
|
comment TEXT,
|
||||||
|
date_updated INTEGER,
|
||||||
|
number INTEGER NOT NULL DEFAULT 0,
|
||||||
|
invalid_domains INTEGER NOT NULL DEFAULT 0,
|
||||||
|
status INTEGER NOT NULL DEFAULT 0,
|
||||||
|
abp_entries INTEGER NOT NULL DEFAULT 0,
|
||||||
|
type INTEGER NOT NULL DEFAULT 0,
|
||||||
|
UNIQUE(address, type)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE adlist_by_group
|
||||||
|
(
|
||||||
|
adlist_id INTEGER NOT NULL REFERENCES adlist (id),
|
||||||
|
group_id INTEGER NOT NULL REFERENCES "group" (id),
|
||||||
|
PRIMARY KEY (adlist_id, group_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE gravity
|
||||||
|
(
|
||||||
|
domain TEXT NOT NULL,
|
||||||
|
adlist_id INTEGER NOT NULL REFERENCES adlist (id)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE antigravity
|
||||||
|
(
|
||||||
|
domain TEXT NOT NULL,
|
||||||
|
adlist_id INTEGER NOT NULL REFERENCES adlist (id)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE info
|
||||||
|
(
|
||||||
|
property TEXT PRIMARY KEY,
|
||||||
|
value TEXT NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO "info" VALUES('version','19');
|
||||||
|
|
||||||
|
CREATE TABLE domainlist_by_group
|
||||||
|
(
|
||||||
|
domainlist_id INTEGER NOT NULL REFERENCES domainlist (id),
|
||||||
|
group_id INTEGER NOT NULL REFERENCES "group" (id),
|
||||||
|
PRIMARY KEY (domainlist_id, group_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE client
|
||||||
|
(
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
ip TEXT NOT NULL UNIQUE,
|
||||||
|
date_added INTEGER NOT NULL DEFAULT (cast(strftime('%s', 'now') as int)),
|
||||||
|
date_modified INTEGER NOT NULL DEFAULT (cast(strftime('%s', 'now') as int)),
|
||||||
|
comment TEXT
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE client_by_group
|
||||||
|
(
|
||||||
|
client_id INTEGER NOT NULL REFERENCES client (id),
|
||||||
|
group_id INTEGER NOT NULL REFERENCES "group" (id),
|
||||||
|
PRIMARY KEY (client_id, group_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TRIGGER tr_adlist_update AFTER UPDATE OF address,enabled,comment ON adlist
|
||||||
|
BEGIN
|
||||||
|
UPDATE adlist SET date_modified = (cast(strftime('%s', 'now') as int)) WHERE id = NEW.id;
|
||||||
|
END;
|
||||||
|
|
||||||
|
CREATE TRIGGER tr_client_update AFTER UPDATE ON client
|
||||||
|
BEGIN
|
||||||
|
UPDATE client SET date_modified = (cast(strftime('%s', 'now') as int)) WHERE ip = NEW.ip;
|
||||||
|
END;
|
||||||
|
|
||||||
|
CREATE TRIGGER tr_domainlist_update AFTER UPDATE ON domainlist
|
||||||
|
BEGIN
|
||||||
|
UPDATE domainlist SET date_modified = (cast(strftime('%s', 'now') as int)) WHERE domain = NEW.domain;
|
||||||
|
END;
|
||||||
|
|
||||||
|
CREATE VIEW vw_whitelist AS SELECT domain, domainlist.id AS id, domainlist_by_group.group_id AS group_id
|
||||||
|
FROM domainlist
|
||||||
|
LEFT JOIN domainlist_by_group ON domainlist_by_group.domainlist_id = domainlist.id
|
||||||
|
LEFT JOIN "group" ON "group".id = domainlist_by_group.group_id
|
||||||
|
WHERE domainlist.enabled = 1 AND (domainlist_by_group.group_id IS NULL OR "group".enabled = 1)
|
||||||
|
AND domainlist.type = 0
|
||||||
|
ORDER BY domainlist.id;
|
||||||
|
|
||||||
|
CREATE VIEW vw_blacklist AS SELECT domain, domainlist.id AS id, domainlist_by_group.group_id AS group_id
|
||||||
|
FROM domainlist
|
||||||
|
LEFT JOIN domainlist_by_group ON domainlist_by_group.domainlist_id = domainlist.id
|
||||||
|
LEFT JOIN "group" ON "group".id = domainlist_by_group.group_id
|
||||||
|
WHERE domainlist.enabled = 1 AND (domainlist_by_group.group_id IS NULL OR "group".enabled = 1)
|
||||||
|
AND domainlist.type = 1
|
||||||
|
ORDER BY domainlist.id;
|
||||||
|
|
||||||
|
CREATE VIEW vw_regex_whitelist AS SELECT domain, domainlist.id AS id, domainlist_by_group.group_id AS group_id
|
||||||
|
FROM domainlist
|
||||||
|
LEFT JOIN domainlist_by_group ON domainlist_by_group.domainlist_id = domainlist.id
|
||||||
|
LEFT JOIN "group" ON "group".id = domainlist_by_group.group_id
|
||||||
|
WHERE domainlist.enabled = 1 AND (domainlist_by_group.group_id IS NULL OR "group".enabled = 1)
|
||||||
|
AND domainlist.type = 2
|
||||||
|
ORDER BY domainlist.id;
|
||||||
|
|
||||||
|
CREATE VIEW vw_regex_blacklist AS SELECT domain, domainlist.id AS id, domainlist_by_group.group_id AS group_id
|
||||||
|
FROM domainlist
|
||||||
|
LEFT JOIN domainlist_by_group ON domainlist_by_group.domainlist_id = domainlist.id
|
||||||
|
LEFT JOIN "group" ON "group".id = domainlist_by_group.group_id
|
||||||
|
WHERE domainlist.enabled = 1 AND (domainlist_by_group.group_id IS NULL OR "group".enabled = 1)
|
||||||
|
AND domainlist.type = 3
|
||||||
|
ORDER BY domainlist.id;
|
||||||
|
|
||||||
|
CREATE VIEW vw_gravity AS SELECT domain, adlist.id AS adlist_id, adlist_by_group.group_id AS group_id
|
||||||
|
FROM gravity
|
||||||
|
LEFT JOIN adlist_by_group ON adlist_by_group.adlist_id = gravity.adlist_id
|
||||||
|
LEFT JOIN adlist ON adlist.id = gravity.adlist_id
|
||||||
|
LEFT JOIN "group" ON "group".id = adlist_by_group.group_id
|
||||||
|
WHERE adlist.enabled = 1 AND (adlist_by_group.group_id IS NULL OR "group".enabled = 1);
|
||||||
|
|
||||||
|
CREATE VIEW vw_antigravity AS SELECT domain, adlist.id AS adlist_id, adlist_by_group.group_id AS group_id
|
||||||
|
FROM antigravity
|
||||||
|
LEFT JOIN adlist_by_group ON adlist_by_group.adlist_id = antigravity.adlist_id
|
||||||
|
LEFT JOIN adlist ON adlist.id = antigravity.adlist_id
|
||||||
|
LEFT JOIN "group" ON "group".id = adlist_by_group.group_id
|
||||||
|
WHERE adlist.enabled = 1 AND (adlist_by_group.group_id IS NULL OR "group".enabled = 1) AND adlist.type = 1;
|
||||||
|
|
||||||
|
CREATE VIEW vw_adlist AS SELECT DISTINCT address, id, type
|
||||||
|
FROM adlist
|
||||||
|
WHERE enabled = 1
|
||||||
|
ORDER BY id;
|
||||||
|
|
||||||
|
CREATE TRIGGER tr_domainlist_add AFTER INSERT ON domainlist
|
||||||
|
BEGIN
|
||||||
|
INSERT INTO domainlist_by_group (domainlist_id, group_id) VALUES (NEW.id, 0);
|
||||||
|
END;
|
||||||
|
|
||||||
|
CREATE TRIGGER tr_client_add AFTER INSERT ON client
|
||||||
|
BEGIN
|
||||||
|
INSERT INTO client_by_group (client_id, group_id) VALUES (NEW.id, 0);
|
||||||
|
END;
|
||||||
|
|
||||||
|
CREATE TRIGGER tr_adlist_add AFTER INSERT ON adlist
|
||||||
|
BEGIN
|
||||||
|
INSERT INTO adlist_by_group (adlist_id, group_id) VALUES (NEW.id, 0);
|
||||||
|
END;
|
||||||
|
|
||||||
|
CREATE TRIGGER tr_group_update AFTER UPDATE ON "group"
|
||||||
|
BEGIN
|
||||||
|
UPDATE "group" SET date_modified = (cast(strftime('%s', 'now') as int)) WHERE id = NEW.id;
|
||||||
|
END;
|
||||||
|
|
||||||
|
CREATE TRIGGER tr_group_zero AFTER DELETE ON "group"
|
||||||
|
BEGIN
|
||||||
|
INSERT OR IGNORE INTO "group" (id,enabled,name) VALUES (0,1,'Default');
|
||||||
|
END;
|
||||||
|
|
||||||
|
CREATE TRIGGER tr_domainlist_delete AFTER DELETE ON domainlist
|
||||||
|
BEGIN
|
||||||
|
DELETE FROM domainlist_by_group WHERE domainlist_id = OLD.id;
|
||||||
|
END;
|
||||||
|
|
||||||
|
CREATE TRIGGER tr_adlist_delete AFTER DELETE ON adlist
|
||||||
|
BEGIN
|
||||||
|
DELETE FROM adlist_by_group WHERE adlist_id = OLD.id;
|
||||||
|
END;
|
||||||
|
|
||||||
|
CREATE TRIGGER tr_client_delete AFTER DELETE ON client
|
||||||
|
BEGIN
|
||||||
|
DELETE FROM client_by_group WHERE client_id = OLD.id;
|
||||||
|
END;
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
42
advanced/Templates/gravity_copy.sql
Normal file
42
advanced/Templates/gravity_copy.sql
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
.timeout 30000
|
||||||
|
|
||||||
|
ATTACH DATABASE '/etc/pihole/gravity.db' AS OLD;
|
||||||
|
|
||||||
|
BEGIN TRANSACTION;
|
||||||
|
|
||||||
|
DROP TRIGGER tr_domainlist_add;
|
||||||
|
DROP TRIGGER tr_client_add;
|
||||||
|
DROP TRIGGER tr_adlist_add;
|
||||||
|
|
||||||
|
INSERT OR REPLACE INTO "group" SELECT * FROM OLD."group";
|
||||||
|
|
||||||
|
INSERT OR REPLACE INTO domainlist SELECT * FROM OLD.domainlist;
|
||||||
|
DELETE FROM OLD.domainlist_by_group WHERE domainlist_id NOT IN (SELECT id FROM OLD.domainlist);
|
||||||
|
INSERT OR REPLACE INTO domainlist_by_group SELECT * FROM OLD.domainlist_by_group;
|
||||||
|
|
||||||
|
INSERT OR REPLACE INTO adlist SELECT * FROM OLD.adlist;
|
||||||
|
DELETE FROM OLD.adlist_by_group WHERE adlist_id NOT IN (SELECT id FROM OLD.adlist);
|
||||||
|
INSERT OR REPLACE INTO adlist_by_group SELECT * FROM OLD.adlist_by_group;
|
||||||
|
|
||||||
|
INSERT OR REPLACE INTO client SELECT * FROM OLD.client;
|
||||||
|
DELETE FROM OLD.client_by_group WHERE client_id NOT IN (SELECT id FROM OLD.client);
|
||||||
|
INSERT OR REPLACE INTO client_by_group SELECT * FROM OLD.client_by_group;
|
||||||
|
|
||||||
|
|
||||||
|
CREATE TRIGGER tr_domainlist_add AFTER INSERT ON domainlist
|
||||||
|
BEGIN
|
||||||
|
INSERT INTO domainlist_by_group (domainlist_id, group_id) VALUES (NEW.id, 0);
|
||||||
|
END;
|
||||||
|
|
||||||
|
CREATE TRIGGER tr_client_add AFTER INSERT ON client
|
||||||
|
BEGIN
|
||||||
|
INSERT INTO client_by_group (client_id, group_id) VALUES (NEW.id, 0);
|
||||||
|
END;
|
||||||
|
|
||||||
|
CREATE TRIGGER tr_adlist_add AFTER INSERT ON adlist
|
||||||
|
BEGIN
|
||||||
|
INSERT INTO adlist_by_group (adlist_id, group_id) VALUES (NEW.id, 0);
|
||||||
|
END;
|
||||||
|
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
32
advanced/Templates/logrotate
Normal file
32
advanced/Templates/logrotate
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
/var/log/pihole/pihole.log {
|
||||||
|
# su #
|
||||||
|
daily
|
||||||
|
copytruncate
|
||||||
|
rotate 5
|
||||||
|
compress
|
||||||
|
delaycompress
|
||||||
|
notifempty
|
||||||
|
nomail
|
||||||
|
}
|
||||||
|
|
||||||
|
/var/log/pihole/FTL.log {
|
||||||
|
# su #
|
||||||
|
weekly
|
||||||
|
copytruncate
|
||||||
|
rotate 3
|
||||||
|
compress
|
||||||
|
delaycompress
|
||||||
|
notifempty
|
||||||
|
nomail
|
||||||
|
}
|
||||||
|
|
||||||
|
/var/log/pihole/webserver.log {
|
||||||
|
# su #
|
||||||
|
weekly
|
||||||
|
copytruncate
|
||||||
|
rotate 3
|
||||||
|
compress
|
||||||
|
delaycompress
|
||||||
|
notifempty
|
||||||
|
nomail
|
||||||
|
}
|
||||||
13
advanced/Templates/pihole-FTL-poststop.sh
Executable file
13
advanced/Templates/pihole-FTL-poststop.sh
Executable file
@@ -0,0 +1,13 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
# Source utils.sh for getFTLConfigValue()
|
||||||
|
PI_HOLE_SCRIPT_DIR='/opt/pihole'
|
||||||
|
utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh"
|
||||||
|
# shellcheck disable=SC1090
|
||||||
|
. "${utilsfile}"
|
||||||
|
|
||||||
|
# Get file paths
|
||||||
|
FTL_PID_FILE="$(getFTLConfigValue files.pid)"
|
||||||
|
|
||||||
|
# Cleanup
|
||||||
|
rm -f /run/pihole/FTL.sock /dev/shm/FTL-* "${FTL_PID_FILE}"
|
||||||
34
advanced/Templates/pihole-FTL-prestart.sh
Executable file
34
advanced/Templates/pihole-FTL-prestart.sh
Executable file
@@ -0,0 +1,34 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
# Source utils.sh for getFTLConfigValue()
|
||||||
|
PI_HOLE_SCRIPT_DIR='/opt/pihole'
|
||||||
|
utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh"
|
||||||
|
# shellcheck disable=SC1090
|
||||||
|
. "${utilsfile}"
|
||||||
|
|
||||||
|
# Get file paths
|
||||||
|
FTL_PID_FILE="$(getFTLConfigValue files.pid)"
|
||||||
|
|
||||||
|
# Ensure that permissions are set so that pihole-FTL can edit all necessary files
|
||||||
|
# shellcheck disable=SC2174
|
||||||
|
mkdir -pm 0640 /var/log/pihole
|
||||||
|
chown -R pihole:pihole /etc/pihole /var/log/pihole
|
||||||
|
chmod -R 0640 /var/log/pihole
|
||||||
|
chmod -R 0660 /etc/pihole
|
||||||
|
|
||||||
|
# Logrotate config file need to be owned by root and must not be writable by group and others
|
||||||
|
chown root:root /etc/pihole/logrotate
|
||||||
|
chmod 0644 /etc/pihole/logrotate
|
||||||
|
|
||||||
|
# allow all users to enter the directories
|
||||||
|
chmod 0755 /etc/pihole /var/log/pihole
|
||||||
|
|
||||||
|
# allow pihole to access subdirs in /etc/pihole (sets execution bit on dirs)
|
||||||
|
# credits https://stackoverflow.com/a/11512211
|
||||||
|
find /etc/pihole -type d -exec chmod 0755 {} \;
|
||||||
|
|
||||||
|
# Touch files to ensure they exist (create if non-existing, preserve if existing)
|
||||||
|
[ -f "${FTL_PID_FILE}" ] || install -D -m 644 -o pihole -g pihole /dev/null "${FTL_PID_FILE}"
|
||||||
|
[ -f /var/log/pihole/FTL.log ] || install -m 640 -o pihole -g pihole /dev/null /var/log/pihole/FTL.log
|
||||||
|
[ -f /var/log/pihole/pihole.log ] || install -m 640 -o pihole -g pihole /dev/null /var/log/pihole/pihole.log
|
||||||
|
[ -f /etc/pihole/dhcp.leases ] || install -m 644 -o pihole -g pihole /dev/null /etc/pihole/dhcp.leases
|
||||||
122
advanced/Templates/pihole-FTL.service
Normal file
122
advanced/Templates/pihole-FTL.service
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
### BEGIN INIT INFO
|
||||||
|
# Provides: pihole-FTL
|
||||||
|
# Required-Start: $remote_fs $syslog $network
|
||||||
|
# Required-Stop: $remote_fs $syslog $network
|
||||||
|
# Default-Start: 2 3 4 5
|
||||||
|
# Default-Stop: 0 1 6
|
||||||
|
# Short-Description: pihole-FTL daemon
|
||||||
|
# Description: Enable service provided by pihole-FTL daemon
|
||||||
|
### END INIT INFO
|
||||||
|
|
||||||
|
# Source utils.sh for getFTLConfigValue(), getFTLPID()
|
||||||
|
PI_HOLE_SCRIPT_DIR="/opt/pihole"
|
||||||
|
utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh"
|
||||||
|
# shellcheck disable=SC1090
|
||||||
|
. "${utilsfile}"
|
||||||
|
|
||||||
|
|
||||||
|
is_running() {
|
||||||
|
if [ -d "/proc/${FTL_PID}" ]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup() {
|
||||||
|
# Run post-stop script, which does cleanup among runtime files
|
||||||
|
sh "${PI_HOLE_SCRIPT_DIR}/pihole-FTL-poststop.sh"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Start the service
|
||||||
|
start() {
|
||||||
|
if is_running; then
|
||||||
|
echo "pihole-FTL is already running"
|
||||||
|
else
|
||||||
|
# Run pre-start script, which pre-creates all expected files with correct permissions
|
||||||
|
sh "${PI_HOLE_SCRIPT_DIR}/pihole-FTL-prestart.sh"
|
||||||
|
|
||||||
|
if setcap CAP_NET_BIND_SERVICE,CAP_NET_RAW,CAP_NET_ADMIN,CAP_SYS_NICE,CAP_IPC_LOCK,CAP_CHOWN,CAP_SYS_TIME+eip "/usr/bin/pihole-FTL"; then
|
||||||
|
su -s /bin/sh -c "/usr/bin/pihole-FTL" pihole
|
||||||
|
else
|
||||||
|
echo "Warning: Starting pihole-FTL as root because setting capabilities is not supported on this system"
|
||||||
|
/usr/bin/pihole-FTL
|
||||||
|
fi
|
||||||
|
rc=$?
|
||||||
|
# Cleanup if startup failed
|
||||||
|
if [ "${rc}" != 0 ]; then
|
||||||
|
cleanup
|
||||||
|
exit $rc
|
||||||
|
fi
|
||||||
|
echo
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Stop the service
|
||||||
|
stop() {
|
||||||
|
if is_running; then
|
||||||
|
kill "${FTL_PID}"
|
||||||
|
for i in 1 2 3 4 5; do
|
||||||
|
if ! is_running; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
|
||||||
|
printf "."
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
echo
|
||||||
|
|
||||||
|
if is_running; then
|
||||||
|
echo "Not stopped; may still be shutting down or shutdown may have failed, killing now"
|
||||||
|
kill -9 "${FTL_PID}"
|
||||||
|
else
|
||||||
|
echo "Stopped"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "Not running"
|
||||||
|
fi
|
||||||
|
cleanup
|
||||||
|
echo
|
||||||
|
}
|
||||||
|
|
||||||
|
# Indicate the service status
|
||||||
|
status() {
|
||||||
|
if is_running; then
|
||||||
|
echo "[ ok ] pihole-FTL is running"
|
||||||
|
exit 0
|
||||||
|
else
|
||||||
|
echo "[ ] pihole-FTL is not running"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
### main logic ###
|
||||||
|
|
||||||
|
# catch sudden termination
|
||||||
|
trap 'cleanup; exit 1' INT HUP TERM ABRT
|
||||||
|
|
||||||
|
# Get FTL's PID file path
|
||||||
|
FTL_PID_FILE="$(getFTLConfigValue files.pid)"
|
||||||
|
|
||||||
|
# Get FTL's current PID
|
||||||
|
FTL_PID="$(getFTLPID "${FTL_PID_FILE}")"
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
stop)
|
||||||
|
stop
|
||||||
|
;;
|
||||||
|
status)
|
||||||
|
status
|
||||||
|
;;
|
||||||
|
start|restart|reload|condrestart)
|
||||||
|
stop
|
||||||
|
start
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Usage: $0 {start|stop|restart|reload|status}"
|
||||||
|
exit 1
|
||||||
|
esac
|
||||||
|
|
||||||
|
exit 0
|
||||||
41
advanced/Templates/pihole-FTL.systemd
Normal file
41
advanced/Templates/pihole-FTL.systemd
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Pi-hole FTL
|
||||||
|
# This unit is supposed to indicate when network functionality is available, but it is only
|
||||||
|
# very weakly defined what that is supposed to mean, with one exception: at shutdown, a unit
|
||||||
|
# that is ordered after network-online.target will be stopped before the network
|
||||||
|
Wants=network-online.target
|
||||||
|
After=network-online.target
|
||||||
|
# A target that should be used as synchronization point for all host/network name service lookups.
|
||||||
|
# All services for which the availability of full host/network name resolution is essential should
|
||||||
|
# be ordered after this target, but not pull it in.
|
||||||
|
Wants=nss-lookup.target
|
||||||
|
Before=nss-lookup.target
|
||||||
|
|
||||||
|
# Limit (re)start loop to 5 within 1 minute
|
||||||
|
StartLimitBurst=5
|
||||||
|
StartLimitIntervalSec=60s
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
User=pihole
|
||||||
|
PermissionsStartOnly=true
|
||||||
|
AmbientCapabilities=CAP_NET_BIND_SERVICE CAP_NET_RAW CAP_NET_ADMIN CAP_SYS_NICE CAP_IPC_LOCK CAP_CHOWN CAP_SYS_TIME
|
||||||
|
|
||||||
|
ExecStartPre=/opt/pihole/pihole-FTL-prestart.sh
|
||||||
|
ExecStart=/usr/bin/pihole-FTL -f
|
||||||
|
Restart=on-failure
|
||||||
|
RestartSec=5s
|
||||||
|
ExecReload=/bin/kill -HUP $MAINPID
|
||||||
|
ExecStopPost=/opt/pihole/pihole-FTL-poststop.sh
|
||||||
|
|
||||||
|
# Use graceful shutdown with a reasonable timeout
|
||||||
|
TimeoutStopSec=10s
|
||||||
|
|
||||||
|
# Make /usr, /boot, /etc and possibly some more folders read-only...
|
||||||
|
ProtectSystem=full
|
||||||
|
# ... except /etc/pihole
|
||||||
|
# This merely retains r/w access rights, it does not add any new.
|
||||||
|
# Must still be writable on the host!
|
||||||
|
ReadWriteDirectories=/etc/pihole
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
33
advanced/Templates/pihole.cron
Normal file
33
advanced/Templates/pihole.cron
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
# Pi-hole: A black hole for Internet advertisements
|
||||||
|
# (c) 2017 Pi-hole, LLC (https://pi-hole.net)
|
||||||
|
# Network-wide ad blocking via your own hardware.
|
||||||
|
#
|
||||||
|
# Updates ad sources every week
|
||||||
|
#
|
||||||
|
# This file is copyright under the latest version of the EUPL.
|
||||||
|
# Please see LICENSE file for your rights under this license.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# This file is under source-control of the Pi-hole installation and update
|
||||||
|
# scripts, any changes made to this file will be overwritten when the software
|
||||||
|
# is updated or re-installed. Please make any changes to the appropriate crontab
|
||||||
|
# or other cron file snippets.
|
||||||
|
|
||||||
|
# Pi-hole: Update the ad sources once a week on Sunday at a random time in the
|
||||||
|
# early morning. Download any updates from the adlists
|
||||||
|
# Squash output to log, then splat the log to stdout on error to allow for
|
||||||
|
# standard crontab job error handling.
|
||||||
|
59 1 * * 7 root PATH="$PATH:/usr/sbin:/usr/local/bin/" pihole updateGravity >/var/log/pihole/pihole_updateGravity.log || cat /var/log/pihole/pihole_updateGravity.log
|
||||||
|
|
||||||
|
# Pi-hole: Flush the log daily at 00:00
|
||||||
|
# The flush script will use logrotate if available
|
||||||
|
# parameter "once": logrotate only once (default is twice)
|
||||||
|
# parameter "quiet": don't print messages
|
||||||
|
00 00 * * * root PATH="$PATH:/usr/sbin:/usr/local/bin/" pihole flush once quiet
|
||||||
|
|
||||||
|
@reboot root /usr/sbin/logrotate --state /var/lib/logrotate/pihole /etc/pihole/logrotate
|
||||||
|
|
||||||
|
# Pi-hole: Grab remote and local version every 24 hours
|
||||||
|
59 17 * * * root PATH="$PATH:/usr/sbin:/usr/local/bin/" pihole updatechecker
|
||||||
|
@reboot root PATH="$PATH:/usr/sbin:/usr/local/bin/" pihole updatechecker reboot
|
||||||
51
advanced/bash-completion/pihole
Normal file
51
advanced/bash-completion/pihole
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
_pihole() {
|
||||||
|
local cur prev opts opts_checkout opts_debug opts_logging opts_query opts_update opts_version
|
||||||
|
COMPREPLY=()
|
||||||
|
cur="${COMP_WORDS[COMP_CWORD]}"
|
||||||
|
prev="${COMP_WORDS[COMP_CWORD-1]}"
|
||||||
|
prev2="${COMP_WORDS[COMP_CWORD-2]}"
|
||||||
|
|
||||||
|
case "${prev}" in
|
||||||
|
"pihole")
|
||||||
|
opts="allow allow-regex allow-wild deny checkout debug disable enable flush help logging query reconfigure regex reloaddns reloadlists status tail uninstall updateGravity updatePihole version wildcard arpflush api"
|
||||||
|
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
|
||||||
|
;;
|
||||||
|
"allow"|"deny"|"wildcard"|"regex"|"allow-regex"|"allow-wild")
|
||||||
|
opts_lists="\not \--delmode \--quiet \--list \--help"
|
||||||
|
COMPREPLY=( $(compgen -W "${opts_lists}" -- ${cur}) )
|
||||||
|
;;
|
||||||
|
"checkout")
|
||||||
|
opts_checkout="core ftl web master dev"
|
||||||
|
COMPREPLY=( $(compgen -W "${opts_checkout}" -- ${cur}) )
|
||||||
|
;;
|
||||||
|
"debug")
|
||||||
|
opts_debug="-a"
|
||||||
|
COMPREPLY=( $(compgen -W "${opts_debug}" -- ${cur}) )
|
||||||
|
;;
|
||||||
|
"logging")
|
||||||
|
opts_logging="on off 'off noflush'"
|
||||||
|
COMPREPLY=( $(compgen -W "${opts_logging}" -- ${cur}) )
|
||||||
|
;;
|
||||||
|
"query")
|
||||||
|
opts_query="--partial --all"
|
||||||
|
COMPREPLY=( $(compgen -W "${opts_query}" -- ${cur}) )
|
||||||
|
;;
|
||||||
|
"updatePihole"|"-up")
|
||||||
|
opts_update="--check-only"
|
||||||
|
COMPREPLY=( $(compgen -W "${opts_update}" -- ${cur}) )
|
||||||
|
;;
|
||||||
|
"core"|"admin"|"ftl")
|
||||||
|
if [[ "$prev2" == "checkout" ]]; then
|
||||||
|
opts_checkout="master dev"
|
||||||
|
COMPREPLY=( $(compgen -W "${opts_checkout}" -- ${cur}) )
|
||||||
|
else
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
return 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
complete -F _pihole pihole
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
# If you want dnsmasq to read another file, as well as /etc/hosts, use
|
|
||||||
# this.
|
|
||||||
addn-hosts=/etc/pihole/gravity.list
|
|
||||||
|
|
||||||
# The following two options make you a better netizen, since they
|
|
||||||
# tell dnsmasq to filter out queries which the public DNS cannot
|
|
||||||
# answer, and which load the servers (especially the root servers)
|
|
||||||
# unnecessarily. If you have a dial-on-demand link they also stop
|
|
||||||
# these requests from bringing up the link unnecessarily.
|
|
||||||
|
|
||||||
# Never forward plain names (without a dot or domain part)
|
|
||||||
domain-needed
|
|
||||||
# Never forward addresses in the non-routed address spaces.
|
|
||||||
bogus-priv
|
|
||||||
|
|
||||||
# If you don't want dnsmasq to read /etc/resolv.conf or any other
|
|
||||||
# file, getting its servers from this file instead (see below), then
|
|
||||||
# uncomment this.
|
|
||||||
no-resolv
|
|
||||||
|
|
||||||
# Add other name servers here, with domain specs if they are for
|
|
||||||
# non-public domains.
|
|
||||||
server=8.8.8.8
|
|
||||||
server=8.8.4.4
|
|
||||||
|
|
||||||
# If you want dnsmasq to listen for DHCP and DNS requests only on
|
|
||||||
# specified interfaces (and the loopback) give the name of the
|
|
||||||
# interface (eg eth0) here.
|
|
||||||
interface=@INT@
|
|
||||||
# Or which to listen on by address (remember to include 127.0.0.1 if
|
|
||||||
# you use this.)
|
|
||||||
listen-address=127.0.0.1
|
|
||||||
|
|
||||||
# Set the cachesize here.
|
|
||||||
cache-size=10000
|
|
||||||
|
|
||||||
# For debugging purposes, log each DNS query as it passes through
|
|
||||||
# dnsmasq.
|
|
||||||
log-queries
|
|
||||||
log-facility=/var/log/pihole.log
|
|
||||||
|
|
||||||
# Normally responses which come from /etc/hosts and the DHCP lease
|
|
||||||
# file have Time-To-Live set as zero, which conventionally means
|
|
||||||
# do not cache further. If you are happy to trade lower load on the
|
|
||||||
# server for potentially stale date, you can set a time-to-live (in
|
|
||||||
# seconds) here.
|
|
||||||
local-ttl=300
|
|
||||||
|
|
||||||
# This allows it to continue functioning without being blocked by syslog, and allows syslog to use dnsmasq for DNS queries without risking deadlock
|
|
||||||
log-async
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
CONF_SWAPSIZE=500
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
<html>
|
|
||||||
<body>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
server.modules = (
|
|
||||||
"mod_access",
|
|
||||||
"mod_accesslog",
|
|
||||||
"mod_expire",
|
|
||||||
"mod_compress",
|
|
||||||
"mod_redirect",
|
|
||||||
"mod_setenv",
|
|
||||||
"mod_rewrite"
|
|
||||||
)
|
|
||||||
|
|
||||||
server.document-root = "/var/www/html"
|
|
||||||
server.error-handler-404 = "pihole/index.html"
|
|
||||||
server.upload-dirs = ( "/var/cache/lighttpd/uploads" )
|
|
||||||
server.errorlog = "/var/log/lighttpd/error.log"
|
|
||||||
server.pid-file = "/var/run/lighttpd.pid"
|
|
||||||
server.username = "www-data"
|
|
||||||
server.groupname = "www-data"
|
|
||||||
server.port = 80
|
|
||||||
accesslog.filename = "/var/log/lighttpd/access.log"
|
|
||||||
accesslog.format = "%{%s}t|%V|%r|%s|%b"
|
|
||||||
|
|
||||||
|
|
||||||
index-file.names = ( "index.php", "index.html", "index.lighttpd.html" )
|
|
||||||
url.access-deny = ( "~", ".inc" )
|
|
||||||
static-file.exclude-extensions = ( ".php", ".pl", ".fcgi" )
|
|
||||||
|
|
||||||
compress.cache-dir = "/var/cache/lighttpd/compress/"
|
|
||||||
compress.filetype = ( "application/javascript", "text/css", "text/html", "text/plain" )
|
|
||||||
|
|
||||||
# default listening port for IPv6 falls back to the IPv4 port
|
|
||||||
include_shell "/usr/share/lighttpd/use-ipv6.pl " + server.port
|
|
||||||
include_shell "/usr/share/lighttpd/create-mime.assign.pl"
|
|
||||||
include_shell "/usr/share/lighttpd/include-conf-enabled.pl"
|
|
||||||
|
|
||||||
# If the URL starts with /admin, it is the Web interface
|
|
||||||
$HTTP["url"] =~ "^/admin/" {
|
|
||||||
# Create a response header for debugging using curl -I
|
|
||||||
setenv.add-response-header = ( "X-Pi-hole" => "The Pi-hole Web interface is working!" )
|
|
||||||
}
|
|
||||||
|
|
||||||
# If the URL does not start with /admin, then it is a query for an ad domain
|
|
||||||
$HTTP["url"] =~ "^(?!/admin)/.*" {
|
|
||||||
# Create a response header for debugging using curl -I
|
|
||||||
setenv.add-response-header = ( "X-Pi-hole" => "A black hole for Internet advertisements." )
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
# Pi-hole: Update the ad sources once a week on Sunday at 01:59
|
|
||||||
# Download any updates from the ad lists
|
|
||||||
59 1 * * 7 root /usr/local/bin/gravity.sh
|
|
||||||
|
|
||||||
# Pi-hole: Update the Web interface shortly after gravity runs
|
|
||||||
# This should also update the version number if it is changed in the dashboard repo
|
|
||||||
30 2 * * 7 root /usr/local/bin/updateDashboard.sh
|
|
||||||
|
|
||||||
# Pi-hole: Parse the log file before it is flushed and save the stats to a database
|
|
||||||
# This will be used for a historical view of your Pi-hole's performance
|
|
||||||
#50 23 * * * root /usr/local/bin/dailyLog.sh
|
|
||||||
|
|
||||||
# Pi-hole: Flush the log daily at 11:58 so it doesn't get out of control
|
|
||||||
# Stats will be viewable in the Web interface thanks to the cron job above
|
|
||||||
58 23 * * * root /usr/local/bin/piholeLogFlush.sh
|
|
||||||
File diff suppressed because it is too large
Load Diff
215
automated install/uninstall.sh
Normal file → Executable file
215
automated install/uninstall.sh
Normal file → Executable file
@@ -1,71 +1,162 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# Completely uninstalls the Pi-hole
|
# Pi-hole: A black hole for Internet advertisements
|
||||||
# (c) 2015 by Jacob Salmela
|
# (c) 2017 Pi-hole, LLC (https://pi-hole.net)
|
||||||
# This file is part of Pi-hole.
|
# Network-wide ad blocking via your own hardware.
|
||||||
#
|
#
|
||||||
# Pi-hole is free software: you can redistribute it and/or modify
|
# Completely uninstalls Pi-hole
|
||||||
# it under the terms of the GNU General Public License as published by
|
#
|
||||||
# the Free Software Foundation, either version 2 of the License, or
|
# This file is copyright under the latest version of the EUPL.
|
||||||
# (at your option) any later version.
|
# Please see LICENSE file for your rights under this license.
|
||||||
|
|
||||||
|
source "/opt/pihole/COL_TABLE"
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
read -rp " ${QST} Are you sure you would like to remove ${COL_WHITE}Pi-hole${COL_NC}? [y/N] " answer
|
||||||
|
case ${answer} in
|
||||||
|
[Yy]* ) break;;
|
||||||
|
* ) echo -e "${OVER} ${COL_LIGHT_GREEN}Uninstall has been canceled${COL_NC}"; exit 0;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
# Must be root to uninstall
|
# Must be root to uninstall
|
||||||
if [[ $EUID -eq 0 ]];then
|
str="Root user check"
|
||||||
echo "You are root."
|
if [[ ${EUID} -eq 0 ]]; then
|
||||||
|
echo -e " ${TICK} ${str}"
|
||||||
else
|
else
|
||||||
echo "sudo will be used for the install."
|
# Check if sudo is actually installed
|
||||||
# Check if it is actually installed
|
# If it isn't, exit because the uninstall can not complete
|
||||||
# If it isn't, exit because the unnstall cannot complete
|
if [ -x "$(command -v sudo)" ]; then
|
||||||
if [[ $(dpkg-query -s sudo) ]];then
|
export SUDO="sudo"
|
||||||
export SUDO="sudo"
|
else
|
||||||
else
|
echo -e " ${CROSS} ${str}
|
||||||
echo "Please install sudo or run this as root."
|
Script called with non-root privileges
|
||||||
exit 1
|
The Pi-hole requires elevated privileges to uninstall"
|
||||||
fi
|
exit 1
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
readonly PI_HOLE_FILES_DIR="/etc/.pihole"
|
||||||
|
SKIP_INSTALL="true"
|
||||||
|
source "${PI_HOLE_FILES_DIR}/automated install/basic-install.sh"
|
||||||
|
|
||||||
|
# package_manager_detect() sourced from basic-install.sh
|
||||||
|
package_manager_detect
|
||||||
|
|
||||||
|
|
||||||
|
removeMetaPackage() {
|
||||||
|
# Purge Pi-hole meta package
|
||||||
|
echo ""
|
||||||
|
echo -ne " ${INFO} Removing Pi-hole meta package...";
|
||||||
|
eval "${SUDO}" "${PKG_REMOVE}" "pihole-meta" &> /dev/null;
|
||||||
|
echo -e "${OVER} ${INFO} Removed Pi-hole meta package";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
removePiholeFiles() {
|
||||||
|
# Only web directories/files that are created by Pi-hole should be removed
|
||||||
|
echo -ne " ${INFO} Removing Web Interface..."
|
||||||
|
${SUDO} rm -rf /var/www/html/admin &> /dev/null
|
||||||
|
|
||||||
|
|
||||||
|
# If the web directory is empty after removing these files, then the parent html directory can be removed.
|
||||||
|
if [ -d "/var/www/html" ]; then
|
||||||
|
if [[ ! "$(ls -A /var/www/html)" ]]; then
|
||||||
|
${SUDO} rm -rf /var/www/html &> /dev/null
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echo -e "${OVER} ${TICK} Removed Web Interface"
|
||||||
|
|
||||||
|
# Attempt to preserve backwards compatibility with older versions
|
||||||
|
# to guarantee no additional changes were made to /etc/crontab after
|
||||||
|
# the installation of pihole, /etc/crontab.pihole should be permanently
|
||||||
|
# preserved.
|
||||||
|
if [[ -f /etc/crontab.orig ]]; then
|
||||||
|
${SUDO} mv /etc/crontab /etc/crontab.pihole
|
||||||
|
${SUDO} mv /etc/crontab.orig /etc/crontab
|
||||||
|
${SUDO} service cron restart
|
||||||
|
echo -e " ${TICK} Restored the default system cron"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Attempt to preserve backwards compatibility with older versions
|
||||||
|
if [[ -f /etc/cron.d/pihole ]];then
|
||||||
|
${SUDO} rm -f /etc/cron.d/pihole &> /dev/null
|
||||||
|
echo -e " ${TICK} Removed /etc/cron.d/pihole"
|
||||||
|
fi
|
||||||
|
|
||||||
|
${SUDO} rm -rf /var/log/*pihole* &> /dev/null
|
||||||
|
${SUDO} rm -rf /var/log/pihole/*pihole* &> /dev/null
|
||||||
|
${SUDO} rm -rf /etc/pihole/ &> /dev/null
|
||||||
|
${SUDO} rm -rf /etc/.pihole/ &> /dev/null
|
||||||
|
${SUDO} rm -rf /opt/pihole/ &> /dev/null
|
||||||
|
${SUDO} rm -f /usr/local/bin/pihole &> /dev/null
|
||||||
|
${SUDO} rm -f /etc/bash_completion.d/pihole &> /dev/null
|
||||||
|
${SUDO} rm -f /etc/sudoers.d/pihole &> /dev/null
|
||||||
|
echo -e " ${TICK} Removed config files"
|
||||||
|
|
||||||
|
# Restore Resolved
|
||||||
|
if [[ -e /etc/systemd/resolved.conf.orig ]]; then
|
||||||
|
${SUDO} cp -p /etc/systemd/resolved.conf.orig /etc/systemd/resolved.conf
|
||||||
|
systemctl reload-or-restart systemd-resolved
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Remove FTL
|
||||||
|
if command -v pihole-FTL &> /dev/null; then
|
||||||
|
echo -ne " ${INFO} Removing pihole-FTL..."
|
||||||
|
if [[ -x "$(command -v systemctl)" ]]; then
|
||||||
|
systemctl stop pihole-FTL
|
||||||
|
else
|
||||||
|
service pihole-FTL stop
|
||||||
|
fi
|
||||||
|
${SUDO} rm -f /etc/systemd/system/pihole-FTL.service
|
||||||
|
if [[ -d '/etc/systemd/system/pihole-FTL.service.d' ]]; then
|
||||||
|
read -rp " ${QST} FTL service override directory /etc/systemd/system/pihole-FTL.service.d detected. Do you wish to remove this from your system? [y/N] " answer
|
||||||
|
case $answer in
|
||||||
|
[yY]*)
|
||||||
|
echo -ne " ${INFO} Removing /etc/systemd/system/pihole-FTL.service.d..."
|
||||||
|
${SUDO} rm -R /etc/systemd/system/pihole-FTL.service.d
|
||||||
|
echo -e "${OVER} ${INFO} Removed /etc/systemd/system/pihole-FTL.service.d"
|
||||||
|
;;
|
||||||
|
*) echo -e " ${INFO} Leaving /etc/systemd/system/pihole-FTL.service.d in place.";;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
${SUDO} rm -f /etc/init.d/pihole-FTL
|
||||||
|
${SUDO} rm -f /usr/bin/pihole-FTL
|
||||||
|
echo -e "${OVER} ${TICK} Removed pihole-FTL"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If the pihole manpage exists, then delete and rebuild man-db
|
||||||
|
if [[ -f /usr/local/share/man/man8/pihole.8 ]]; then
|
||||||
|
${SUDO} rm -f /usr/local/share/man/man8/pihole.8 /usr/local/share/man/man8/pihole-FTL.8 /usr/local/share/man/man5/pihole-FTL.conf.5
|
||||||
|
${SUDO} mandb -q &>/dev/null
|
||||||
|
echo -e " ${TICK} Removed pihole man page"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If the pihole user exists, then remove
|
||||||
|
if id "pihole" &> /dev/null; then
|
||||||
|
if ${SUDO} userdel -r pihole 2> /dev/null; then
|
||||||
|
echo -e " ${TICK} Removed 'pihole' user"
|
||||||
|
else
|
||||||
|
echo -e " ${CROSS} Unable to remove 'pihole' user"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
# If the pihole group exists, then remove
|
||||||
|
if getent group "pihole" &> /dev/null; then
|
||||||
|
if ${SUDO} groupdel pihole 2> /dev/null; then
|
||||||
|
echo -e " ${TICK} Removed 'pihole' group"
|
||||||
|
else
|
||||||
|
echo -e " ${CROSS} Unable to remove 'pihole' group"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "\\n We're sorry to see you go, but thanks for checking out Pi-hole!
|
||||||
|
If you need help, reach out to us on GitHub, Discourse, Reddit or Twitter
|
||||||
|
Reinstall at any time: ${COL_WHITE}curl -sSL https://install.pi-hole.net | bash${COL_NC}
|
||||||
|
|
||||||
|
${COL_LIGHT_RED}Please reset the DNS on your router/clients to restore internet connectivity${COL_NC}
|
||||||
|
${INFO} Pi-hole's meta package has been removed, use the 'autoremove' function from your package manager to remove unused dependencies${COL_NC}
|
||||||
|
${COL_LIGHT_GREEN}Uninstallation Complete! ${COL_NC}"
|
||||||
|
}
|
||||||
|
|
||||||
######### SCRIPT ###########
|
######### SCRIPT ###########
|
||||||
$SUDO apt-get -y remove --purge dnsutils bc toilet
|
removeMetaPackage
|
||||||
$SUDO apt-get -y remove --purge dnsmasq
|
removePiholeFiles
|
||||||
$SUDO apt-get -y remove --purge lighttpd php5-common php5-cgi php5
|
|
||||||
|
|
||||||
# Only web directories/files that are created by pihole should be removed.
|
|
||||||
echo "Removing the Pi-hole Web server files..."
|
|
||||||
$SUDO rm -rf /var/www/html/admin
|
|
||||||
$SUDO rm -rf /var/www/html/pihole
|
|
||||||
$SUDO rm /var/www/html/index.lighttpd.orig
|
|
||||||
|
|
||||||
# If the web directory is empty after removing these files, then the parent html folder can be removed.
|
|
||||||
if [[ ! "$(ls -A /var/www/html)" ]]; then
|
|
||||||
$SUDO rm -rf /var/www/html
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Removing dnsmasq config files..."
|
|
||||||
$SUDO rm /etc/dnsmasq.conf /etc/dnsmasq.conf.orig
|
|
||||||
|
|
||||||
# Attempt to preserve backwards compatibility with older versions
|
|
||||||
# to guarantee no additional changes were made to /etc/crontab after
|
|
||||||
# the installation of pihole, /etc/crontab.pihole should be permanently
|
|
||||||
# preserved.
|
|
||||||
if [[ -f /etc/crontab.orig ]]; then
|
|
||||||
echo "Initial Pi-hole cron detected. Restoring the default system cron..."
|
|
||||||
$SUDO mv /etc/crontab /etc/crontab.pihole
|
|
||||||
$SUDO mv /etc/crontab.orig /etc/crontab
|
|
||||||
$SUDO service cron restart
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Attempt to preserve backwards compatibility with older versions
|
|
||||||
if [[ -f /etc/cron.d/pihole ]];then
|
|
||||||
echo "Removing cron.d/pihole..."
|
|
||||||
$SUDO rm /etc/cron.d/pihole
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Removing config files and scripts..."
|
|
||||||
$SUDO rm /etc/dnsmasq.conf
|
|
||||||
$SUDO rm -rf /etc/lighttpd/
|
|
||||||
$SUDO rm /var/log/pihole.log
|
|
||||||
$SUDO rm /usr/local/bin/gravity.sh
|
|
||||||
$SUDO rm /usr/local/bin/chronometer.sh
|
|
||||||
$SUDO rm /usr/local/bin/whitelist.sh
|
|
||||||
$SUDO rm /usr/local/bin/piholeLogFlush.sh
|
|
||||||
$SUDO rm -rf /etc/pihole/
|
|
||||||
|
|||||||
@@ -1,32 +0,0 @@
|
|||||||
server.modules = (
|
|
||||||
"mod_access",
|
|
||||||
"mod_alias",
|
|
||||||
"mod_compress",
|
|
||||||
"mod_redirect",
|
|
||||||
"mod_rewrite"
|
|
||||||
)
|
|
||||||
|
|
||||||
server.document-root = "/var/www"
|
|
||||||
server.upload-dirs = ( "/var/cache/lighttpd/uploads" )
|
|
||||||
server.errorlog = "/var/log/lighttpd/error.log"
|
|
||||||
server.pid-file = "/var/run/lighttpd.pid"
|
|
||||||
server.username = "www-data"
|
|
||||||
server.groupname = "www-data"
|
|
||||||
server.port = 80
|
|
||||||
|
|
||||||
|
|
||||||
index-file.names = ( "index.php", "index.html", "index.lighttpd.html" )
|
|
||||||
url.access-deny = ( "~", ".inc" )
|
|
||||||
static-file.exclude-extensions = ( ".php", ".pl", ".fcgi" )
|
|
||||||
|
|
||||||
compress.cache-dir = "/var/cache/lighttpd/compress/"
|
|
||||||
compress.filetype = ( "application/javascript", "text/css", "text/html", "text/plain" )
|
|
||||||
|
|
||||||
# default listening port for IPv6 falls back to the IPv4 port
|
|
||||||
include_shell "/usr/share/lighttpd/use-ipv6.pl " + server.port
|
|
||||||
include_shell "/usr/share/lighttpd/create-mime.assign.pl"
|
|
||||||
include_shell "/usr/share/lighttpd/include-conf-enabled.pl"
|
|
||||||
|
|
||||||
$HTTP["host"] =~ "ads.hulu.com|ads-v-darwin.hulu.com" {
|
|
||||||
url.redirect = ( ".*" => "http://192.168.1.101:8200/MediaItems/19.mov")
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
media_dir=V,/var/lib/minidlna/videos/
|
|
||||||
port=8200
|
|
||||||
friendly_name=pihole
|
|
||||||
serial=12345678
|
|
||||||
model_number=1
|
|
||||||
inotify=yes
|
|
||||||
1326
gravity.sh
1326
gravity.sh
File diff suppressed because it is too large
Load Diff
329
manpages/pihole.8
Normal file
329
manpages/pihole.8
Normal file
@@ -0,0 +1,329 @@
|
|||||||
|
.TH "Pi-hole" "8" "Pi-hole" "Pi-hole" "April 2020"
|
||||||
|
.SH "NAME"
|
||||||
|
|
||||||
|
Pi-hole : A black-hole for internet advertisements
|
||||||
|
.br
|
||||||
|
.SH "SYNOPSIS"
|
||||||
|
|
||||||
|
\fBpihole\fR (\fB-allow\fR|\fB-deny\fR) [options] domain(s)
|
||||||
|
.br
|
||||||
|
\fBpihole\fR (\fB--allow-regex\fR|\fB--regex\fR) [options] domain(s)
|
||||||
|
.br
|
||||||
|
\fBpihole\fR (\fB--allow-wild\fR|\fB--wild\fR) [options] domain(s)
|
||||||
|
.br
|
||||||
|
\fBpihole setpassword\fR password
|
||||||
|
.br
|
||||||
|
\fBpihole\fR \fB-d\fR [-a] [-c]
|
||||||
|
.br
|
||||||
|
\fBpihole -f
|
||||||
|
.br
|
||||||
|
pihole -r
|
||||||
|
.br
|
||||||
|
\fBpihole\fR \fB-t\fR [arg]
|
||||||
|
.br
|
||||||
|
\fBpihole -g\fR
|
||||||
|
.br
|
||||||
|
\fBpihole\fR -\fBq\fR [options]
|
||||||
|
.br
|
||||||
|
\fBpihole\fR \fB-l\fR (\fBon|off|off noflush\fR)
|
||||||
|
.br
|
||||||
|
\fBpihole -up \fR[--check-only]
|
||||||
|
.br
|
||||||
|
\fBpihole -v\fR
|
||||||
|
.br
|
||||||
|
\fBpihole uninstall\fR
|
||||||
|
.br
|
||||||
|
\fBpihole status\fR
|
||||||
|
.br
|
||||||
|
\fBpihole reloaddns\fR
|
||||||
|
.br
|
||||||
|
\fBpihole reloadlists\fR
|
||||||
|
.br
|
||||||
|
\fBpihole\fR (\fBenable\fR|\fBdisable\fR [time])
|
||||||
|
.br
|
||||||
|
\fBpihole\fR \fBcheckout\fR repo [branch]
|
||||||
|
.br
|
||||||
|
\fBpihole\fR \api\fR endpoint
|
||||||
|
.br
|
||||||
|
\fBpihole\fR \fBhelp\fR
|
||||||
|
.br
|
||||||
|
.SH "DESCRIPTION"
|
||||||
|
|
||||||
|
Available commands and options:
|
||||||
|
.br
|
||||||
|
|
||||||
|
\fBallow, allowlist\fR [options] [<domain1> <domain2 ...>]
|
||||||
|
.br
|
||||||
|
Adds or removes specified domain or domains to the Allowlist
|
||||||
|
.br
|
||||||
|
|
||||||
|
\fBdeny, denylist\fR [options] [<domain1> <domain2 ...>]
|
||||||
|
.br
|
||||||
|
Adds or removes specified domain or domains to the denylist
|
||||||
|
.br
|
||||||
|
|
||||||
|
\fB--regex, regex\fR [options] [<regex1> <regex2 ...>]
|
||||||
|
.br
|
||||||
|
Add or removes specified regex filter to the regex denylist
|
||||||
|
.br
|
||||||
|
|
||||||
|
\fB--allow-regex\fR [options] [<regex1> <regex2 ...>]
|
||||||
|
.br
|
||||||
|
Add or removes specified regex filter to the regex allowlist
|
||||||
|
.br
|
||||||
|
|
||||||
|
\fB--wild, wildcard\fR [options] [<domain1> <domain2 ...>]
|
||||||
|
.br
|
||||||
|
Add or removes specified domain to the wildcard denylist
|
||||||
|
.br
|
||||||
|
|
||||||
|
\fB--allow-wild\fR [options] [<domain1> <domain2 ...>]
|
||||||
|
.br
|
||||||
|
Add or removes specified domain to the wildcard allowlist
|
||||||
|
.br
|
||||||
|
|
||||||
|
(Allow-/denylist manipulation options):
|
||||||
|
.br
|
||||||
|
not, -d, --delmode Remove domain(s) from the list
|
||||||
|
.br
|
||||||
|
-q, --quiet Make output less verbose
|
||||||
|
.br
|
||||||
|
-l, --list Display all your listed domains
|
||||||
|
.br
|
||||||
|
|
||||||
|
\fB-d, debug\fR [-a]
|
||||||
|
.br
|
||||||
|
Start a debugging session
|
||||||
|
.br
|
||||||
|
|
||||||
|
-a Enable automated debugging
|
||||||
|
-c Include a Pi-hole database integrity check
|
||||||
|
.br
|
||||||
|
|
||||||
|
\fB-f, flush\fR
|
||||||
|
.br
|
||||||
|
Flush the Pi-hole log
|
||||||
|
.br
|
||||||
|
|
||||||
|
\fB-r, reconfigure\fR
|
||||||
|
.br
|
||||||
|
Reconfigure or Repair Pi-hole subsystems
|
||||||
|
.br
|
||||||
|
|
||||||
|
\fB-t, tail\fR [arg]
|
||||||
|
.br
|
||||||
|
View the live output of the Pi-hole log
|
||||||
|
.br
|
||||||
|
|
||||||
|
[arg] Optional argument to filter the log for
|
||||||
|
(regular expressions are supported)
|
||||||
|
.br
|
||||||
|
|
||||||
|
\fB-g, updateGravity\fR
|
||||||
|
.br
|
||||||
|
Update the list of ad-serving domains
|
||||||
|
.br
|
||||||
|
|
||||||
|
\fB-q, query\fR [option]
|
||||||
|
.br
|
||||||
|
Query the adlists for a specified domain
|
||||||
|
.br
|
||||||
|
|
||||||
|
(Query options):
|
||||||
|
.br
|
||||||
|
-partial Search the adlists for partially matching domains
|
||||||
|
.br
|
||||||
|
-all Return all query matches within a adlists
|
||||||
|
.br
|
||||||
|
|
||||||
|
\fB-h, --help, help\fR
|
||||||
|
.br
|
||||||
|
Show a help dialog
|
||||||
|
.br
|
||||||
|
|
||||||
|
\fB-l, logging\fR [on|off|off noflush]
|
||||||
|
.br
|
||||||
|
Specify whether the Pi-hole log should be used
|
||||||
|
.br
|
||||||
|
|
||||||
|
(Logging options):
|
||||||
|
.br
|
||||||
|
on Enable the Pi-hole log at /var/log/pihole/pihole.log
|
||||||
|
.br
|
||||||
|
off Disable and flush the Pi-hole log at
|
||||||
|
/var/log/pihole/pihole.log
|
||||||
|
.br
|
||||||
|
off noflush Disable the Pi-hole log at /var/log/pihole/pihole.log
|
||||||
|
.br
|
||||||
|
|
||||||
|
\fB-up, updatePihole\fR [--check-only]
|
||||||
|
.br
|
||||||
|
Update Pi-hole subsystems
|
||||||
|
.br
|
||||||
|
|
||||||
|
--check-only Exit script before update is performed.
|
||||||
|
.br
|
||||||
|
|
||||||
|
\fB-v, version\fR
|
||||||
|
.br
|
||||||
|
Show installed versions of Pi-hole, Web Interface & FTL
|
||||||
|
.br
|
||||||
|
|
||||||
|
\fBsetpassword\fR
|
||||||
|
.br
|
||||||
|
Set Web Interface password
|
||||||
|
.br
|
||||||
|
|
||||||
|
\fBuninstall\fR
|
||||||
|
.br
|
||||||
|
Uninstall Pi-hole from your system
|
||||||
|
.br
|
||||||
|
|
||||||
|
\fBstatus\fR
|
||||||
|
.br
|
||||||
|
Display the running status of Pi-hole subsystems
|
||||||
|
.br
|
||||||
|
|
||||||
|
\fBenable\fR [time]
|
||||||
|
.br
|
||||||
|
Enable Pi-hole blocking, optionally for a set duration
|
||||||
|
.br
|
||||||
|
|
||||||
|
\fBdisable\fR [time]
|
||||||
|
.br
|
||||||
|
Disable Pi-hole blocking, optionally for a set duration
|
||||||
|
.br
|
||||||
|
|
||||||
|
(time options):
|
||||||
|
.br
|
||||||
|
#s Disable Pi-hole functionality for # second(s)
|
||||||
|
.br
|
||||||
|
#m Disable Pi-hole functionality for # minute(s)
|
||||||
|
.br
|
||||||
|
|
||||||
|
\fBreloaddns\fR
|
||||||
|
.br
|
||||||
|
Update the lists and flush the cache without restarting the DNS server
|
||||||
|
.br
|
||||||
|
|
||||||
|
\fBreloadlists\fR
|
||||||
|
.br
|
||||||
|
Update the lists WITHOUT flushing the cache or restarting the DNS server
|
||||||
|
.br
|
||||||
|
|
||||||
|
\fBcheckout\fR [repo] [branch]
|
||||||
|
.br
|
||||||
|
Switch Pi-hole subsystems to a different GitHub branch
|
||||||
|
.br
|
||||||
|
|
||||||
|
(repo options):
|
||||||
|
.br
|
||||||
|
core Change the branch of Pi-hole's core subsystem
|
||||||
|
.br
|
||||||
|
web Change the branch of Admin Console subsystem
|
||||||
|
.br
|
||||||
|
ftl Change the branch of Pi-hole's FTL subsystem
|
||||||
|
.br
|
||||||
|
(branch options):
|
||||||
|
.br
|
||||||
|
master Update subsystems to the latest stable release
|
||||||
|
.br
|
||||||
|
dev Update subsystems to the latest development
|
||||||
|
release
|
||||||
|
.br
|
||||||
|
branchname Update subsystems to the specified branchname
|
||||||
|
.br
|
||||||
|
|
||||||
|
\fBapi\fR endpoint
|
||||||
|
.br
|
||||||
|
Query the Pi-hole API at <endpoint>
|
||||||
|
.br
|
||||||
|
.SH "EXAMPLE"
|
||||||
|
|
||||||
|
Some usage examples
|
||||||
|
.br
|
||||||
|
|
||||||
|
Allow-/denylist manipulation
|
||||||
|
.br
|
||||||
|
|
||||||
|
\fBpihole allow iloveads.example.com\fR
|
||||||
|
.br
|
||||||
|
Allow "iloveads.example.com"
|
||||||
|
.br
|
||||||
|
|
||||||
|
\fBpihole deny remove noads.example.com\fR
|
||||||
|
.br
|
||||||
|
Removes "noads.example.com" from denylist
|
||||||
|
.br
|
||||||
|
|
||||||
|
\fBpihole --wild example.com\fR
|
||||||
|
.br
|
||||||
|
Adds example.com as a wildcard - would block all subdomains of
|
||||||
|
example.com, including example.com itself.
|
||||||
|
.br
|
||||||
|
|
||||||
|
\fBpihole --regex "ad.*\\.example\\.com$"\fR
|
||||||
|
.br
|
||||||
|
Adds "ad.*\\.example\\.com$" to the regex blacklist.
|
||||||
|
Would block all subdomains of example.com which start with "ad"
|
||||||
|
.br
|
||||||
|
|
||||||
|
Changing the Web Interface password
|
||||||
|
.br
|
||||||
|
|
||||||
|
\fBpihole setpassword ExamplePassword\fR
|
||||||
|
.br
|
||||||
|
Change the password to "ExamplePassword"
|
||||||
|
.br
|
||||||
|
|
||||||
|
Updating lists from internet sources
|
||||||
|
.br
|
||||||
|
|
||||||
|
\fBpihole -g\fR
|
||||||
|
.br
|
||||||
|
Update the list of ad-serving domains
|
||||||
|
.br
|
||||||
|
|
||||||
|
Displaying version information
|
||||||
|
.br
|
||||||
|
|
||||||
|
\fBpihole -v\fR
|
||||||
|
.br
|
||||||
|
Display the current version of Pi-hole
|
||||||
|
.br
|
||||||
|
|
||||||
|
Temporarily disabling Pi-hole
|
||||||
|
.br
|
||||||
|
|
||||||
|
\fBpihole disable 5m\fR
|
||||||
|
.br
|
||||||
|
Disable Pi-hole functionality for five minutes
|
||||||
|
.br
|
||||||
|
|
||||||
|
Switching Pi-hole subsystem branches
|
||||||
|
.br
|
||||||
|
|
||||||
|
\fBpihole checkout master\fR
|
||||||
|
.br
|
||||||
|
Switch to master branch
|
||||||
|
.br
|
||||||
|
|
||||||
|
\fBpihole checkout core dev\fR
|
||||||
|
.br
|
||||||
|
Switch to core development branch
|
||||||
|
.br
|
||||||
|
|
||||||
|
\fBpihole arpflush\fR
|
||||||
|
.br
|
||||||
|
Flush information stored in Pi-hole's network tables
|
||||||
|
.br
|
||||||
|
|
||||||
|
\fBpihole api stats/summary\fR
|
||||||
|
.br
|
||||||
|
Queries FTL for the stats/summary endpoint
|
||||||
|
.br
|
||||||
|
|
||||||
|
.SH "COLOPHON"
|
||||||
|
|
||||||
|
Get sucked into the latest news and community activity by entering Pi-hole's orbit. Information about Pi-hole, and the latest version of the software can be found at https://pi-hole.net.
|
||||||
|
.br
|
||||||
596
pihole
Executable file
596
pihole
Executable file
@@ -0,0 +1,596 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Pi-hole: A black hole for Internet advertisements
|
||||||
|
# (c) 2017 Pi-hole, LLC (https://pi-hole.net)
|
||||||
|
# Network-wide ad blocking via your own hardware.
|
||||||
|
#
|
||||||
|
# Controller for all pihole scripts and functions.
|
||||||
|
#
|
||||||
|
# This file is copyright under the latest version of the EUPL.
|
||||||
|
# Please see LICENSE file for your rights under this license.
|
||||||
|
|
||||||
|
readonly PI_HOLE_SCRIPT_DIR="/opt/pihole"
|
||||||
|
|
||||||
|
# PI_HOLE_BIN_DIR is not readonly here because in some functions (checkout),
|
||||||
|
# they might get set again when the installer is sourced. This causes an
|
||||||
|
# error due to modifying a readonly variable.
|
||||||
|
PI_HOLE_BIN_DIR="/usr/local/bin"
|
||||||
|
|
||||||
|
readonly colfile="${PI_HOLE_SCRIPT_DIR}/COL_TABLE"
|
||||||
|
source "${colfile}"
|
||||||
|
|
||||||
|
readonly utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh"
|
||||||
|
source "${utilsfile}"
|
||||||
|
|
||||||
|
# Source api functions
|
||||||
|
readonly apifile="${PI_HOLE_SCRIPT_DIR}/api.sh"
|
||||||
|
source "${apifile}"
|
||||||
|
|
||||||
|
versionsfile="/etc/pihole/versions"
|
||||||
|
if [ -f "${versionsfile}" ]; then
|
||||||
|
# Only source versionsfile if the file exits
|
||||||
|
# fixes a warning during installation where versionsfile does not exist yet
|
||||||
|
# but gravity calls `pihole -status` and thereby sourcing the file
|
||||||
|
source "${versionsfile}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# TODO: We can probably remove the reliance on this function too, just tell people to pihole-FTL --config webserver.api.password "password"
|
||||||
|
SetWebPassword() {
|
||||||
|
if [ -n "$2" ] ; then
|
||||||
|
readonly PASSWORD="$2"
|
||||||
|
readonly CONFIRM="${PASSWORD}"
|
||||||
|
else
|
||||||
|
# Prevents a bug if the user presses Ctrl+C and it continues to hide the text typed.
|
||||||
|
# So we reset the terminal via stty if the user does press Ctrl+C
|
||||||
|
trap '{ echo -e "\nNot changed" ; stty sane ; exit 1; }' INT
|
||||||
|
read -s -r -p "Enter New Password (Blank for no password): " PASSWORD
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
if [ "${PASSWORD}" == "" ]; then
|
||||||
|
setFTLConfigValue "webserver.api.password" ""
|
||||||
|
echo -e " ${TICK} Password Removed"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
read -s -r -p "Confirm Password: " CONFIRM
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "${PASSWORD}" == "${CONFIRM}" ] ; then
|
||||||
|
# pihole-FTL will automatically hash the password
|
||||||
|
setFTLConfigValue "webserver.api.password" "${PASSWORD}"
|
||||||
|
echo -e " ${TICK} New password set"
|
||||||
|
else
|
||||||
|
echo -e " ${CROSS} Passwords don't match. Your password has not been changed"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
listFunc() {
|
||||||
|
"${PI_HOLE_SCRIPT_DIR}"/list.sh "$@"
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
debugFunc() {
|
||||||
|
local automated
|
||||||
|
local web
|
||||||
|
local check_database_integrity
|
||||||
|
# Pull off the `debug` leaving passed call augmentation flags in $1
|
||||||
|
shift
|
||||||
|
|
||||||
|
for value in "$@"; do
|
||||||
|
[[ "$value" == *"-a"* ]] && automated="true"
|
||||||
|
[[ "$value" == *"-w"* ]] && web="true"
|
||||||
|
[[ "$value" == *"-c"* ]] && check_database_integrity="true"
|
||||||
|
[[ "$value" == *"--check_database"* ]] && check_database_integrity="true"
|
||||||
|
done
|
||||||
|
|
||||||
|
AUTOMATED=${automated:-} WEBCALL=${web:-} CHECK_DATABASE=${check_database_integrity:-} "${PI_HOLE_SCRIPT_DIR}"/piholeDebug.sh
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
flushFunc() {
|
||||||
|
"${PI_HOLE_SCRIPT_DIR}"/piholeLogFlush.sh "$@"
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
arpFunc() {
|
||||||
|
"${PI_HOLE_SCRIPT_DIR}"/piholeARPTable.sh "$@"
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
updatePiholeFunc() {
|
||||||
|
if [ -n "${DOCKER_VERSION}" ]; then
|
||||||
|
unsupportedFunc
|
||||||
|
else
|
||||||
|
shift
|
||||||
|
"${PI_HOLE_SCRIPT_DIR}"/update.sh "$@"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
reconfigurePiholeFunc() {
|
||||||
|
if [ -n "${DOCKER_VERSION}" ]; then
|
||||||
|
unsupportedFunc
|
||||||
|
else
|
||||||
|
/etc/.pihole/automated\ install/basic-install.sh --reconfigure
|
||||||
|
exit 0;
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
updateGravityFunc() {
|
||||||
|
exec "${PI_HOLE_SCRIPT_DIR}"/gravity.sh "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
queryFunc() {
|
||||||
|
shift
|
||||||
|
"${PI_HOLE_SCRIPT_DIR}"/query.sh "$@"
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
chronometerFunc() {
|
||||||
|
echo "Chronometer is gone, use PADD (https://github.com/pi-hole/PADD)"
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uninstallFunc() {
|
||||||
|
if [ -n "${DOCKER_VERSION}" ]; then
|
||||||
|
unsupportedFunc
|
||||||
|
else
|
||||||
|
"${PI_HOLE_SCRIPT_DIR}"/uninstall.sh
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
versionFunc() {
|
||||||
|
exec "${PI_HOLE_SCRIPT_DIR}"/version.sh
|
||||||
|
}
|
||||||
|
|
||||||
|
reloadDNS() {
|
||||||
|
local svcOption svc str output status pid icon FTL_PID_FILE
|
||||||
|
svcOption="${1:-reload}"
|
||||||
|
|
||||||
|
# get the current path to the pihole-FTL.pid
|
||||||
|
FTL_PID_FILE="$(getFTLConfigValue files.pid)"
|
||||||
|
|
||||||
|
# Determine if we should reload or restart
|
||||||
|
if [[ "${svcOption}" =~ "reload-lists" ]]; then
|
||||||
|
# Reloading of the lists has been requested
|
||||||
|
# Note 1: This will NOT re-read any *.conf files
|
||||||
|
# Note 2: We cannot use killall here as it does
|
||||||
|
# not know about real-time signals
|
||||||
|
|
||||||
|
pid="$(getFTLPID ${FTL_PID_FILE})"
|
||||||
|
if [[ "$pid" -eq "-1" ]]; then
|
||||||
|
svc="true"
|
||||||
|
str="FTL is not running"
|
||||||
|
icon="${INFO}"
|
||||||
|
else
|
||||||
|
svc="kill -RTMIN ${pid}"
|
||||||
|
str="Reloading DNS lists"
|
||||||
|
icon="${TICK}"
|
||||||
|
fi
|
||||||
|
elif [[ "${svcOption}" =~ "reload" ]]; then
|
||||||
|
# Reloading of the DNS cache has been requested
|
||||||
|
# Note: This will NOT re-read any *.conf files
|
||||||
|
pid="$(getFTLPID ${FTL_PID_FILE})"
|
||||||
|
if [[ "$pid" -eq "-1" ]]; then
|
||||||
|
svc="true"
|
||||||
|
str="FTL is not running"
|
||||||
|
icon="${INFO}"
|
||||||
|
else
|
||||||
|
svc="kill -HUP ${pid}"
|
||||||
|
str="Flushing DNS cache"
|
||||||
|
icon="${TICK}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Print output to Terminal, but not to Web Admin
|
||||||
|
[[ -t 1 ]] && echo -ne " ${INFO} ${str}..."
|
||||||
|
|
||||||
|
output=$( { ${svc}; } 2>&1 )
|
||||||
|
status="$?"
|
||||||
|
|
||||||
|
if [[ "${status}" -eq 0 ]]; then
|
||||||
|
[[ -t 1 ]] && echo -e "${OVER} ${icon} ${str}"
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
[[ ! -t 1 ]] && local OVER=""
|
||||||
|
echo -e "${OVER} ${CROSS} ${output}"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
piholeEnable() {
|
||||||
|
if [[ "${2}" == "-h" ]] || [[ "${2}" == "--help" ]]; then
|
||||||
|
echo "Usage: pihole enable/disable [time]
|
||||||
|
Example: 'pihole enable', or 'pihole disable 5m'
|
||||||
|
En- or disable Pi-hole subsystems
|
||||||
|
|
||||||
|
Time:
|
||||||
|
#s En-/disable Pi-hole functionality for # second(s)
|
||||||
|
#m En-/disable Pi-hole functionality for # minute(s)"
|
||||||
|
exit 0
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Get timer
|
||||||
|
local tt="null"
|
||||||
|
if [[ $# -gt 1 ]]; then
|
||||||
|
local error=false
|
||||||
|
if [[ "${2}" == *"s" ]]; then
|
||||||
|
tt=${2%"s"}
|
||||||
|
if [[ ! "${tt}" =~ ^-?[0-9]+$ ]];then
|
||||||
|
local error=true
|
||||||
|
fi
|
||||||
|
elif [[ "${2}" == *"m" ]]; then
|
||||||
|
tt=${2%"m"}
|
||||||
|
if [[ "${tt}" =~ ^-?[0-9]+$ ]];then
|
||||||
|
tt=$((${tt}*60))
|
||||||
|
else
|
||||||
|
local error=true
|
||||||
|
fi
|
||||||
|
elif [[ -n "${2}" ]]; then
|
||||||
|
local error=true
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ${error} == true ]];then
|
||||||
|
echo -e " ${COL_LIGHT_RED}Unknown format for blocking timer!${COL_NC}"
|
||||||
|
echo -e " Try 'pihole disable --help' for more information."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Authenticate with the API
|
||||||
|
LoginAPI
|
||||||
|
|
||||||
|
# Send the request
|
||||||
|
data=$(PostFTLData "dns/blocking" "{ \"blocking\": ${1}, \"timer\": ${tt} }")
|
||||||
|
|
||||||
|
# Check the response
|
||||||
|
local extra=" forever"
|
||||||
|
local timer="$(echo "${data}"| jq --raw-output '.timer' )"
|
||||||
|
if [[ "${timer}" != "null" ]]; then
|
||||||
|
extra=" for ${timer}s"
|
||||||
|
fi
|
||||||
|
local str="Pi-hole $(echo "${data}" | jq --raw-output '.blocking')${extra}"
|
||||||
|
|
||||||
|
# Logout from the API
|
||||||
|
LogoutAPI
|
||||||
|
|
||||||
|
echo -e "${OVER} ${TICK} ${str}"
|
||||||
|
}
|
||||||
|
|
||||||
|
piholeLogging() {
|
||||||
|
shift
|
||||||
|
if [[ "${1}" == "-h" ]] || [[ "${1}" == "--help" ]]; then
|
||||||
|
echo "Usage: pihole logging [options]
|
||||||
|
Example: 'pihole logging on'
|
||||||
|
Specify whether the Pi-hole log should be used
|
||||||
|
|
||||||
|
Options:
|
||||||
|
on Enable the Pi-hole log at /var/log/pihole/pihole.log
|
||||||
|
off Disable and flush the Pi-hole log at /var/log/pihole/pihole.log
|
||||||
|
off noflush Disable the Pi-hole log at /var/log/pihole/pihole.log"
|
||||||
|
exit 0
|
||||||
|
elif [[ "${1}" == "off" ]]; then
|
||||||
|
# Disable logging
|
||||||
|
setFTLConfigValue dns.queryLogging false
|
||||||
|
if [[ "${2}" != "noflush" ]]; then
|
||||||
|
# Flush logs
|
||||||
|
"${PI_HOLE_BIN_DIR}"/pihole -f
|
||||||
|
fi
|
||||||
|
echo -e " ${INFO} Disabling logging..."
|
||||||
|
local str="Logging has been disabled!"
|
||||||
|
elif [[ "${1}" == "on" ]]; then
|
||||||
|
# Enable logging
|
||||||
|
setFTLConfigValue dns.queryLogging true
|
||||||
|
echo -e " ${INFO} Enabling logging..."
|
||||||
|
local str="Logging has been enabled!"
|
||||||
|
else
|
||||||
|
echo -e " ${COL_LIGHT_RED}Invalid option${COL_NC}
|
||||||
|
Try 'pihole logging --help' for more information."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo -e "${OVER} ${TICK} ${str}"
|
||||||
|
}
|
||||||
|
|
||||||
|
analyze_ports() {
|
||||||
|
local lv4 lv6 port=${1}
|
||||||
|
# FTL is listening at least on at least one port when this
|
||||||
|
# function is getting called
|
||||||
|
# Check individual address family/protocol combinations
|
||||||
|
# For a healthy Pi-hole, they should all be up (nothing printed)
|
||||||
|
lv4="$(ss --ipv4 --listening --numeric --tcp --udp src :${port})"
|
||||||
|
if grep -q "udp " <<< "${lv4}"; then
|
||||||
|
echo -e " ${TICK} UDP (IPv4)"
|
||||||
|
else
|
||||||
|
echo -e " ${CROSS} UDP (IPv4)"
|
||||||
|
fi
|
||||||
|
if grep -q "tcp " <<< "${lv4}"; then
|
||||||
|
echo -e " ${TICK} TCP (IPv4)"
|
||||||
|
else
|
||||||
|
echo -e " ${CROSS} TCP (IPv4)"
|
||||||
|
fi
|
||||||
|
lv6="$(ss --ipv6 --listening --numeric --tcp --udp src :${port})"
|
||||||
|
if grep -q "udp " <<< "${lv6}"; then
|
||||||
|
echo -e " ${TICK} UDP (IPv6)"
|
||||||
|
else
|
||||||
|
echo -e " ${CROSS} UDP (IPv6)"
|
||||||
|
fi
|
||||||
|
if grep -q "tcp " <<< "${lv6}"; then
|
||||||
|
echo -e " ${TICK} TCP (IPv6)"
|
||||||
|
else
|
||||||
|
echo -e " ${CROSS} TCP (IPv6)"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
}
|
||||||
|
|
||||||
|
statusFunc() {
|
||||||
|
# Determine if there is pihole-FTL service is listening
|
||||||
|
local pid port ftl_pid_file block_status
|
||||||
|
|
||||||
|
ftl_pid_file="$(getFTLConfigValue files.pid)"
|
||||||
|
|
||||||
|
pid="$(getFTLPID ${ftl_pid_file})"
|
||||||
|
|
||||||
|
if [[ "$pid" -eq "-1" ]]; then
|
||||||
|
case "${1}" in
|
||||||
|
"web") echo "-1";;
|
||||||
|
*) echo -e " ${CROSS} DNS service is NOT running";;
|
||||||
|
esac
|
||||||
|
exit 0
|
||||||
|
else
|
||||||
|
# get the DNS port pihole-FTL is listening on
|
||||||
|
port="$(getFTLConfigValue dns.port)"
|
||||||
|
if [[ "${port}" == "0" ]]; then
|
||||||
|
case "${1}" in
|
||||||
|
"web") echo "-1";;
|
||||||
|
*) echo -e " ${CROSS} DNS service is NOT listening";;
|
||||||
|
esac
|
||||||
|
exit 0
|
||||||
|
else
|
||||||
|
if [[ "${1}" != "web" ]]; then
|
||||||
|
echo -e " ${TICK} FTL is listening on port ${port}"
|
||||||
|
analyze_ports "${port}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Determine if Pi-hole's blocking is enabled
|
||||||
|
block_status=$(getFTLConfigValue dns.blocking.active)
|
||||||
|
if [ ${block_status} == "true" ]; then
|
||||||
|
case "${1}" in
|
||||||
|
"web") echo "$port";;
|
||||||
|
*) echo -e " ${TICK} Pi-hole blocking is enabled";;
|
||||||
|
esac
|
||||||
|
else
|
||||||
|
case "${1}" in
|
||||||
|
"web") echo 0;;
|
||||||
|
*) echo -e " ${CROSS} Pi-hole blocking is disabled";;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
tailFunc() {
|
||||||
|
# Warn user if Pi-hole's logging is disabled
|
||||||
|
local logging_enabled=$(getFTLConfigValue dns.queryLogging)
|
||||||
|
if [[ "${logging_enabled}" != "true" ]]; then
|
||||||
|
echo " ${CROSS} Warning: Query logging is disabled"
|
||||||
|
fi
|
||||||
|
echo -e " ${INFO} Press Ctrl-C to exit"
|
||||||
|
|
||||||
|
# Get logfile path
|
||||||
|
readonly LOGFILE=$(getFTLConfigValue files.log.dnsmasq)
|
||||||
|
|
||||||
|
# Strip date from each line
|
||||||
|
# Color blocklist/denylist/wildcard entries as red
|
||||||
|
# Color A/AAAA/DHCP strings as white
|
||||||
|
# Color everything else as gray
|
||||||
|
tail -f $LOGFILE | grep --line-buffered "${1}" | sed -E \
|
||||||
|
-e "s,($(date +'%b %d ')| dnsmasq\[[0-9]*\]),,g" \
|
||||||
|
-e "s,(.*(denied |gravity blocked ).*),${COL_RED}&${COL_NC}," \
|
||||||
|
-e "s,.*(query\\[A|DHCP).*,${COL_NC}&${COL_NC}," \
|
||||||
|
-e "s,.*,${COL_GRAY}&${COL_NC},"
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
piholeCheckoutFunc() {
|
||||||
|
if [ -n "${DOCKER_VERSION}" ]; then
|
||||||
|
unsupportedFunc
|
||||||
|
else
|
||||||
|
if [[ "$2" == "-h" ]] || [[ "$2" == "--help" ]]; then
|
||||||
|
echo "Switch Pi-hole subsystems to a different GitHub branch
|
||||||
|
Usage: ${COL_GREEN}pihole checkout${COL_NC} ${COL_YELLOW}shortcut${COL_NC}
|
||||||
|
or ${COL_GREEN}pihole checkout${COL_NC} ${COL_PURPLE}repo${COL_NC} ${COL_CYAN}branch${COL_NC}
|
||||||
|
|
||||||
|
Example: ${COL_GREEN}pihole checkout${COL_NC} ${COL_YELLOW}master${COL_NC}
|
||||||
|
or ${COL_GREEN}pihole checkout${COL_NC} ${COL_PURPLE}ftl ${COL_CYAN}development${COL_NC}
|
||||||
|
|
||||||
|
Shortcuts:
|
||||||
|
${COL_YELLOW}master${COL_NC} Update all subsystems to the latest stable release
|
||||||
|
${COL_YELLOW}dev${COL_NC} Update all subsystems to the latest development release
|
||||||
|
|
||||||
|
Individual components:
|
||||||
|
${COL_PURPLE}core${COL_NC} ${COL_CYAN}branch${COL_NC} Change the branch of Pi-hole's core subsystem
|
||||||
|
${COL_PURPLE}web${COL_NC} ${COL_CYAN}branch${COL_NC} Change the branch of the web interface subsystem
|
||||||
|
${COL_PURPLE}ftl${COL_NC} ${COL_CYAN}branch${COL_NC} Change the branch of Pi-hole's FTL subsystem"
|
||||||
|
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
source "${PI_HOLE_SCRIPT_DIR}"/piholeCheckout.sh
|
||||||
|
shift
|
||||||
|
checkout "$@"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
tricorderFunc() {
|
||||||
|
local tricorder_token
|
||||||
|
if [[ ! -p "/dev/stdin" ]]; then
|
||||||
|
echo -e " ${INFO} Please do not call Tricorder directly"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
tricorder_token=$(curl --silent --fail --show-error --upload-file "-" https://tricorder.pi-hole.net/upload < /dev/stdin 2>&1)
|
||||||
|
if [[ "${tricorder_token}" != "https://tricorder.pi-hole.net/"* ]]; then
|
||||||
|
echo -e "${CROSS} uploading failed, contact Pi-hole support for assistance."
|
||||||
|
# Log curl error (if available)
|
||||||
|
if [ -n "${tricorder_token}" ]; then
|
||||||
|
echo -e "${INFO} Error message: ${COL_RED}${tricorder_token}${COL_NC}\\n"
|
||||||
|
tricorder_token=""
|
||||||
|
fi
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "Upload successful, your token is: ${COL_GREEN}${tricorder_token}${COL_NC}"
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
updateCheckFunc() {
|
||||||
|
"${PI_HOLE_SCRIPT_DIR}"/updatecheck.sh "$@"
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
unsupportedFunc(){
|
||||||
|
echo "Function not supported in Docker images"
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
helpFunc() {
|
||||||
|
echo "Usage: pihole [options]
|
||||||
|
Example: 'pihole allow -h'
|
||||||
|
Add '-h' after specific commands for more information on usage
|
||||||
|
|
||||||
|
Domain Options:
|
||||||
|
allow, allowlist Allow domain(s)
|
||||||
|
deny, denylist Deny domain(s)
|
||||||
|
--regex, regex Regex deny domains(s)
|
||||||
|
--allow-regex Regex allow domains(s)
|
||||||
|
--wild, wildcard Wildcard deny domain(s)
|
||||||
|
--allow-wild Wildcard allow domain(s)
|
||||||
|
Add '-h' for more info on allow/deny usage
|
||||||
|
|
||||||
|
Debugging Options:
|
||||||
|
-d, debug Start a debugging session
|
||||||
|
Add '-c' or '--check-database' to include a Pi-hole database integrity check
|
||||||
|
Add '-a' to automatically upload the log to tricorder.pi-hole.net
|
||||||
|
-f, flush Flush the Pi-hole log
|
||||||
|
-r, reconfigure Reconfigure or Repair Pi-hole subsystems
|
||||||
|
-t, tail [arg] View the live output of the Pi-hole log.
|
||||||
|
Add an optional argument to filter the log
|
||||||
|
(regular expressions are supported)
|
||||||
|
api <endpoint> Query the Pi-hole API at <endpoint>
|
||||||
|
|
||||||
|
|
||||||
|
Options:
|
||||||
|
setpassword [pwd] Set the password for the web interface
|
||||||
|
Without optional argument, password is read interactively.
|
||||||
|
When specifying a password directly, enclose it in single quotes.
|
||||||
|
-g, updateGravity Update the list of ad-serving domains
|
||||||
|
-h, --help, help Show this help dialog
|
||||||
|
-l, logging Specify whether the Pi-hole log should be used
|
||||||
|
Add '-h' for more info on logging usage
|
||||||
|
-q, query Query the adlists for a specified domain
|
||||||
|
Add '-h' for more info on query usage
|
||||||
|
-up, updatePihole Update Pi-hole subsystems
|
||||||
|
Add '--check-only' to exit script before update is performed.
|
||||||
|
-v, version Show installed versions of Pi-hole, Web Interface & FTL
|
||||||
|
uninstall Uninstall Pi-hole from your system
|
||||||
|
status Display the running status of Pi-hole subsystems
|
||||||
|
enable Enable Pi-hole subsystems
|
||||||
|
Add '-h' for more info on enable usage
|
||||||
|
disable Disable Pi-hole subsystems
|
||||||
|
Add '-h' for more info on disable usage
|
||||||
|
reloaddns Update the lists and flush the cache without restarting the DNS server
|
||||||
|
reloadlists Update the lists WITHOUT flushing the cache or restarting the DNS server
|
||||||
|
checkout Switch Pi-hole subsystems to a different GitHub branch
|
||||||
|
Add '-h' for more info on checkout usage
|
||||||
|
arpflush Flush information stored in Pi-hole's network tables";
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if [[ $# = 0 ]]; then
|
||||||
|
helpFunc
|
||||||
|
fi
|
||||||
|
|
||||||
|
# functions that do not require sudo power
|
||||||
|
need_root=1
|
||||||
|
case "${1}" in
|
||||||
|
"-h" | "help" | "--help" ) helpFunc;;
|
||||||
|
"-v" | "version" ) versionFunc;;
|
||||||
|
"-c" | "chronometer" ) chronometerFunc "$@";;
|
||||||
|
"-q" | "query" ) queryFunc "$@";;
|
||||||
|
"status" ) statusFunc "$2";;
|
||||||
|
"tricorder" ) tricorderFunc;;
|
||||||
|
|
||||||
|
# we need to add all arguments that require sudo power to not trigger the * argument
|
||||||
|
"allow" | "allowlist" ) need_root=0;;
|
||||||
|
"deny" | "denylist" ) need_root=0;;
|
||||||
|
"--wild" | "wildcard" ) need_root=0;;
|
||||||
|
"--regex" | "regex" ) need_root=0;;
|
||||||
|
"--allow-regex" | "allow-regex" ) need_root=0;;
|
||||||
|
"--allow-wild" | "allow-wild" ) need_root=0;;
|
||||||
|
"-f" | "flush" ) ;;
|
||||||
|
"-up" | "updatePihole" ) ;;
|
||||||
|
"-r" | "reconfigure" ) ;;
|
||||||
|
"-l" | "logging" ) ;;
|
||||||
|
"uninstall" ) ;;
|
||||||
|
"enable" ) need_root=0;;
|
||||||
|
"disable" ) need_root=0;;
|
||||||
|
"-d" | "debug" ) ;;
|
||||||
|
"-g" | "updateGravity" ) ;;
|
||||||
|
"reloaddns" ) ;;
|
||||||
|
"reloadlists" ) ;;
|
||||||
|
"setpassword" ) ;;
|
||||||
|
"checkout" ) ;;
|
||||||
|
"updatechecker" ) ;;
|
||||||
|
"arpflush" ) ;;
|
||||||
|
"-t" | "tail" ) ;;
|
||||||
|
"api" ) need_root=0;;
|
||||||
|
* ) helpFunc;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# In the case of alpine running in a container, the USER variable appears to be blank
|
||||||
|
# which prevents the next trap from working correctly. Set it by running whoami
|
||||||
|
if [[ -z ${USER} ]]; then
|
||||||
|
USER=$(whoami)
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if the current user is neither root nor pihole and if the command
|
||||||
|
# requires root. If so, exit with an error message.
|
||||||
|
if [[ $EUID -ne 0 && ${USER} != "pihole" && need_root -eq 1 ]];then
|
||||||
|
echo -e " ${CROSS} The Pi-hole command requires root privileges, try:"
|
||||||
|
echo -e " ${COL_GREEN}sudo pihole $*${COL_NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Handle redirecting to specific functions based on arguments
|
||||||
|
case "${1}" in
|
||||||
|
"allow" | "allowlist" ) listFunc "$@";;
|
||||||
|
"deny" | "denylist" ) listFunc "$@";;
|
||||||
|
"--wild" | "wildcard" ) listFunc "$@";;
|
||||||
|
"--regex" | "regex" ) listFunc "$@";;
|
||||||
|
"--allow-regex" | "allow-regex" ) listFunc "$@";;
|
||||||
|
"--allow-wild" | "allow-wild" ) listFunc "$@";;
|
||||||
|
"-d" | "debug" ) debugFunc "$@";;
|
||||||
|
"-f" | "flush" ) flushFunc "$@";;
|
||||||
|
"-up" | "updatePihole" ) updatePiholeFunc "$@";;
|
||||||
|
"-r" | "reconfigure" ) reconfigurePiholeFunc;;
|
||||||
|
"-g" | "updateGravity" ) updateGravityFunc "$@";;
|
||||||
|
"-l" | "logging" ) piholeLogging "$@";;
|
||||||
|
"uninstall" ) uninstallFunc;;
|
||||||
|
"enable" ) piholeEnable true "$2";;
|
||||||
|
"disable" ) piholeEnable false "$2";;
|
||||||
|
"reloaddns" ) reloadDNS "reload";;
|
||||||
|
"reloadlists" ) reloadDNS "reload-lists";;
|
||||||
|
"setpassword" ) SetWebPassword "$@";;
|
||||||
|
"checkout" ) piholeCheckoutFunc "$@";;
|
||||||
|
"updatechecker" ) shift; updateCheckFunc "$@";;
|
||||||
|
"arpflush" ) arpFunc "$@";;
|
||||||
|
"-t" | "tail" ) tailFunc "$2";;
|
||||||
|
"api" ) apiFunc "$2";;
|
||||||
|
* ) helpFunc;;
|
||||||
|
esac
|
||||||
25
test/README.md
Normal file
25
test/README.md
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
# Recommended way to run tests
|
||||||
|
|
||||||
|
Make sure you have Docker and Python w/pip package manager.
|
||||||
|
|
||||||
|
From command line all you need to do is:
|
||||||
|
|
||||||
|
- `pip install tox`
|
||||||
|
- `tox`
|
||||||
|
|
||||||
|
Tox handles setting up a virtual environment for python dependencies, installing dependencies, building the docker images used by tests, and finally running tests. It's an easy way to have travis-ci like build behavior locally.
|
||||||
|
|
||||||
|
## Alternative py.test method of running tests
|
||||||
|
|
||||||
|
You're responsible for setting up your virtual env and dependencies in this situation.
|
||||||
|
|
||||||
|
```
|
||||||
|
py.test -vv -n auto -m "build_stage"
|
||||||
|
py.test -vv -n auto -m "not build_stage"
|
||||||
|
```
|
||||||
|
|
||||||
|
The build_stage tests have to run first to create the docker images, followed by the actual tests which utilize said images. Unless you're changing your dockerfiles you shouldn't have to run the build_stage every time - but it's a good idea to rebuild at least once a day in case the base Docker images or packages change.
|
||||||
|
|
||||||
|
# How do I debug python?
|
||||||
|
|
||||||
|
Highly recommended: Setup PyCharm on a **Docker enabled** machine. Having a python debugger like PyCharm changes your life if you've never used it :)
|
||||||
0
test/__init__.py
Normal file
0
test/__init__.py
Normal file
20
test/_centos_9.Dockerfile
Normal file
20
test/_centos_9.Dockerfile
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
FROM quay.io/centos/centos:stream9
|
||||||
|
# Disable SELinux
|
||||||
|
RUN echo "SELINUX=disabled" > /etc/selinux/config
|
||||||
|
RUN yum install -y --allowerasing curl git initscripts
|
||||||
|
|
||||||
|
ENV GITDIR=/etc/.pihole
|
||||||
|
ENV SCRIPTDIR=/opt/pihole
|
||||||
|
|
||||||
|
RUN mkdir -p $GITDIR $SCRIPTDIR /etc/pihole
|
||||||
|
ADD . $GITDIR
|
||||||
|
RUN cp $GITDIR/advanced/Scripts/*.sh $GITDIR/gravity.sh $GITDIR/pihole $GITDIR/automated\ install/*.sh $GITDIR/advanced/Scripts/COL_TABLE $SCRIPTDIR/
|
||||||
|
ENV PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$SCRIPTDIR
|
||||||
|
|
||||||
|
RUN true && \
|
||||||
|
chmod +x $SCRIPTDIR/*
|
||||||
|
|
||||||
|
ENV SKIP_INSTALL=true
|
||||||
|
ENV OS_CHECK_DOMAIN_NAME=dev-supportedos.pi-hole.net
|
||||||
|
|
||||||
|
#sed '/# Start the installer/Q' /opt/pihole/basic-install.sh > /opt/pihole/stub_basic-install.sh && \
|
||||||
17
test/_debian_11.Dockerfile
Normal file
17
test/_debian_11.Dockerfile
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
FROM buildpack-deps:bullseye-scm
|
||||||
|
|
||||||
|
ENV GITDIR=/etc/.pihole
|
||||||
|
ENV SCRIPTDIR=/opt/pihole
|
||||||
|
|
||||||
|
RUN mkdir -p $GITDIR $SCRIPTDIR /etc/pihole
|
||||||
|
ADD . $GITDIR
|
||||||
|
RUN cp $GITDIR/advanced/Scripts/*.sh $GITDIR/gravity.sh $GITDIR/pihole $GITDIR/automated\ install/*.sh $GITDIR/advanced/Scripts/COL_TABLE $SCRIPTDIR/
|
||||||
|
ENV PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$SCRIPTDIR
|
||||||
|
|
||||||
|
RUN true && \
|
||||||
|
chmod +x $SCRIPTDIR/*
|
||||||
|
|
||||||
|
ENV SKIP_INSTALL=true
|
||||||
|
ENV OS_CHECK_DOMAIN_NAME=dev-supportedos.pi-hole.net
|
||||||
|
|
||||||
|
#sed '/# Start the installer/Q' /opt/pihole/basic-install.sh > /opt/pihole/stub_basic-install.sh && \
|
||||||
17
test/_debian_12.Dockerfile
Normal file
17
test/_debian_12.Dockerfile
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
FROM buildpack-deps:bookworm-scm
|
||||||
|
|
||||||
|
ENV GITDIR=/etc/.pihole
|
||||||
|
ENV SCRIPTDIR=/opt/pihole
|
||||||
|
|
||||||
|
RUN mkdir -p $GITDIR $SCRIPTDIR /etc/pihole
|
||||||
|
ADD . $GITDIR
|
||||||
|
RUN cp $GITDIR/advanced/Scripts/*.sh $GITDIR/gravity.sh $GITDIR/pihole $GITDIR/automated\ install/*.sh $GITDIR/advanced/Scripts/COL_TABLE $SCRIPTDIR/
|
||||||
|
ENV PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$SCRIPTDIR
|
||||||
|
|
||||||
|
RUN true && \
|
||||||
|
chmod +x $SCRIPTDIR/*
|
||||||
|
|
||||||
|
ENV SKIP_INSTALL=true
|
||||||
|
ENV OS_CHECK_DOMAIN_NAME=dev-supportedos.pi-hole.net
|
||||||
|
|
||||||
|
#sed '/# Start the installer/Q' /opt/pihole/basic-install.sh > /opt/pihole/stub_basic-install.sh && \
|
||||||
18
test/_fedora_40.Dockerfile
Normal file
18
test/_fedora_40.Dockerfile
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
FROM fedora:40
|
||||||
|
RUN dnf install -y git initscripts
|
||||||
|
|
||||||
|
ENV GITDIR=/etc/.pihole
|
||||||
|
ENV SCRIPTDIR=/opt/pihole
|
||||||
|
|
||||||
|
RUN mkdir -p $GITDIR $SCRIPTDIR /etc/pihole
|
||||||
|
ADD . $GITDIR
|
||||||
|
RUN cp $GITDIR/advanced/Scripts/*.sh $GITDIR/gravity.sh $GITDIR/pihole $GITDIR/automated\ install/*.sh $GITDIR/advanced/Scripts/COL_TABLE $SCRIPTDIR/
|
||||||
|
ENV PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$SCRIPTDIR
|
||||||
|
|
||||||
|
RUN true && \
|
||||||
|
chmod +x $SCRIPTDIR/*
|
||||||
|
|
||||||
|
ENV SKIP_INSTALL=true
|
||||||
|
ENV OS_CHECK_DOMAIN_NAME=dev-supportedos.pi-hole.net
|
||||||
|
|
||||||
|
#sed '/# Start the installer/Q' /opt/pihole/basic-install.sh > /opt/pihole/stub_basic-install.sh && \
|
||||||
18
test/_fedora_41.Dockerfile
Normal file
18
test/_fedora_41.Dockerfile
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
FROM fedora:41
|
||||||
|
RUN dnf install -y git initscripts
|
||||||
|
|
||||||
|
ENV GITDIR=/etc/.pihole
|
||||||
|
ENV SCRIPTDIR=/opt/pihole
|
||||||
|
|
||||||
|
RUN mkdir -p $GITDIR $SCRIPTDIR /etc/pihole
|
||||||
|
ADD . $GITDIR
|
||||||
|
RUN cp $GITDIR/advanced/Scripts/*.sh $GITDIR/gravity.sh $GITDIR/pihole $GITDIR/automated\ install/*.sh $GITDIR/advanced/Scripts/COL_TABLE $SCRIPTDIR/
|
||||||
|
ENV PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$SCRIPTDIR
|
||||||
|
|
||||||
|
RUN true && \
|
||||||
|
chmod +x $SCRIPTDIR/*
|
||||||
|
|
||||||
|
ENV SKIP_INSTALL=true
|
||||||
|
ENV OS_CHECK_DOMAIN_NAME=dev-supportedos.pi-hole.net
|
||||||
|
|
||||||
|
#sed '/# Start the installer/Q' /opt/pihole/basic-install.sh > /opt/pihole/stub_basic-install.sh && \
|
||||||
17
test/_ubuntu_20.Dockerfile
Normal file
17
test/_ubuntu_20.Dockerfile
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
FROM buildpack-deps:focal-scm
|
||||||
|
|
||||||
|
ENV GITDIR=/etc/.pihole
|
||||||
|
ENV SCRIPTDIR=/opt/pihole
|
||||||
|
|
||||||
|
RUN mkdir -p $GITDIR $SCRIPTDIR /etc/pihole
|
||||||
|
ADD . $GITDIR
|
||||||
|
RUN cp $GITDIR/advanced/Scripts/*.sh $GITDIR/gravity.sh $GITDIR/pihole $GITDIR/automated\ install/*.sh $GITDIR/advanced/Scripts/COL_TABLE $SCRIPTDIR/
|
||||||
|
ENV PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$SCRIPTDIR
|
||||||
|
|
||||||
|
RUN true && \
|
||||||
|
chmod +x $SCRIPTDIR/*
|
||||||
|
|
||||||
|
ENV SKIP_INSTALL=true
|
||||||
|
ENV OS_CHECK_DOMAIN_NAME=dev-supportedos.pi-hole.net
|
||||||
|
|
||||||
|
#sed '/# Start the installer/Q' /opt/pihole/basic-install.sh > /opt/pihole/stub_basic-install.sh && \
|
||||||
18
test/_ubuntu_22.Dockerfile
Normal file
18
test/_ubuntu_22.Dockerfile
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
FROM buildpack-deps:jammy-scm
|
||||||
|
|
||||||
|
ENV GITDIR=/etc/.pihole
|
||||||
|
ENV SCRIPTDIR=/opt/pihole
|
||||||
|
|
||||||
|
RUN mkdir -p $GITDIR $SCRIPTDIR /etc/pihole
|
||||||
|
ADD . $GITDIR
|
||||||
|
RUN cp $GITDIR/advanced/Scripts/*.sh $GITDIR/gravity.sh $GITDIR/pihole $GITDIR/automated\ install/*.sh $GITDIR/advanced/Scripts/COL_TABLE $SCRIPTDIR/
|
||||||
|
ENV PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$SCRIPTDIR
|
||||||
|
ENV DEBIAN_FRONTEND=noninteractive
|
||||||
|
|
||||||
|
RUN true && \
|
||||||
|
chmod +x $SCRIPTDIR/*
|
||||||
|
|
||||||
|
ENV SKIP_INSTALL=true
|
||||||
|
ENV OS_CHECK_DOMAIN_NAME=dev-supportedos.pi-hole.net
|
||||||
|
|
||||||
|
#sed '/# Start the installer/Q' /opt/pihole/basic-install.sh > /opt/pihole/stub_basic-install.sh && \
|
||||||
18
test/_ubuntu_23.Dockerfile
Normal file
18
test/_ubuntu_23.Dockerfile
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
FROM buildpack-deps:lunar-scm
|
||||||
|
|
||||||
|
ENV GITDIR=/etc/.pihole
|
||||||
|
ENV SCRIPTDIR=/opt/pihole
|
||||||
|
|
||||||
|
RUN mkdir -p $GITDIR $SCRIPTDIR /etc/pihole
|
||||||
|
ADD . $GITDIR
|
||||||
|
RUN cp $GITDIR/advanced/Scripts/*.sh $GITDIR/gravity.sh $GITDIR/pihole $GITDIR/automated\ install/*.sh $GITDIR/advanced/Scripts/COL_TABLE $SCRIPTDIR/
|
||||||
|
ENV PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$SCRIPTDIR
|
||||||
|
ENV DEBIAN_FRONTEND=noninteractive
|
||||||
|
|
||||||
|
RUN true && \
|
||||||
|
chmod +x $SCRIPTDIR/*
|
||||||
|
|
||||||
|
ENV SKIP_INSTALL=true
|
||||||
|
ENV OS_CHECK_DOMAIN_NAME=dev-supportedos.pi-hole.net
|
||||||
|
|
||||||
|
#sed '/# Start the installer/Q' /opt/pihole/basic-install.sh > /opt/pihole/stub_basic-install.sh && \
|
||||||
18
test/_ubuntu_24.Dockerfile
Normal file
18
test/_ubuntu_24.Dockerfile
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
FROM buildpack-deps:24.04-scm
|
||||||
|
|
||||||
|
ENV GITDIR=/etc/.pihole
|
||||||
|
ENV SCRIPTDIR=/opt/pihole
|
||||||
|
|
||||||
|
RUN mkdir -p $GITDIR $SCRIPTDIR /etc/pihole
|
||||||
|
ADD . $GITDIR
|
||||||
|
RUN cp $GITDIR/advanced/Scripts/*.sh $GITDIR/gravity.sh $GITDIR/pihole $GITDIR/automated\ install/*.sh $GITDIR/advanced/Scripts/COL_TABLE $SCRIPTDIR/
|
||||||
|
ENV PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$SCRIPTDIR
|
||||||
|
ENV DEBIAN_FRONTEND=noninteractive
|
||||||
|
|
||||||
|
RUN true && \
|
||||||
|
chmod +x $SCRIPTDIR/*
|
||||||
|
|
||||||
|
ENV SKIP_INSTALL=true
|
||||||
|
ENV OS_CHECK_DOMAIN_NAME=dev-supportedos.pi-hole.net
|
||||||
|
|
||||||
|
#sed '/# Start the installer/Q' /opt/pihole/basic-install.sh > /opt/pihole/stub_basic-install.sh && \
|
||||||
219
test/conftest.py
Normal file
219
test/conftest.py
Normal file
@@ -0,0 +1,219 @@
|
|||||||
|
import pytest
|
||||||
|
import testinfra
|
||||||
|
import testinfra.backend.docker
|
||||||
|
import subprocess
|
||||||
|
from textwrap import dedent
|
||||||
|
|
||||||
|
IMAGE = "pytest_pihole:test_container"
|
||||||
|
tick_box = "[✓]"
|
||||||
|
cross_box = "[✗]"
|
||||||
|
info_box = "[i]"
|
||||||
|
|
||||||
|
|
||||||
|
# Monkeypatch sh to bash, if they ever support non hard code /bin/sh this can go away
|
||||||
|
# https://github.com/pytest-dev/pytest-testinfra/blob/master/testinfra/backend/docker.py
|
||||||
|
def run_bash(self, command, *args, **kwargs):
|
||||||
|
cmd = self.get_command(command, *args)
|
||||||
|
if self.user is not None:
|
||||||
|
out = self.run_local(
|
||||||
|
"docker exec -u %s %s /bin/bash -c %s", self.user, self.name, cmd
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
out = self.run_local("docker exec %s /bin/bash -c %s", self.name, cmd)
|
||||||
|
out.command = self.encode(cmd)
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
testinfra.backend.docker.DockerBackend.run = run_bash
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def host():
|
||||||
|
# run a container
|
||||||
|
docker_id = (
|
||||||
|
subprocess.check_output(["docker", "run", "-t", "-d", "--cap-add=ALL", IMAGE])
|
||||||
|
.decode()
|
||||||
|
.strip()
|
||||||
|
)
|
||||||
|
|
||||||
|
# return a testinfra connection to the container
|
||||||
|
docker_host = testinfra.get_host("docker://" + docker_id)
|
||||||
|
|
||||||
|
yield docker_host
|
||||||
|
# at the end of the test suite, destroy the container
|
||||||
|
subprocess.check_call(["docker", "rm", "-f", docker_id])
|
||||||
|
|
||||||
|
|
||||||
|
# Helper functions
|
||||||
|
def mock_command(script, args, container):
|
||||||
|
"""
|
||||||
|
Allows for setup of commands we don't really want to have to run for real
|
||||||
|
in unit tests
|
||||||
|
"""
|
||||||
|
full_script_path = "/usr/local/bin/{}".format(script)
|
||||||
|
mock_script = dedent(
|
||||||
|
r"""\
|
||||||
|
#!/bin/bash -e
|
||||||
|
echo "\$0 \$@" >> /var/log/{script}
|
||||||
|
case "\$1" in""".format(
|
||||||
|
script=script
|
||||||
|
)
|
||||||
|
)
|
||||||
|
for k, v in args.items():
|
||||||
|
case = dedent(
|
||||||
|
"""
|
||||||
|
{arg})
|
||||||
|
echo {res}
|
||||||
|
exit {retcode}
|
||||||
|
;;""".format(
|
||||||
|
arg=k, res=v[0], retcode=v[1]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
mock_script += case
|
||||||
|
mock_script += dedent(
|
||||||
|
"""
|
||||||
|
esac"""
|
||||||
|
)
|
||||||
|
container.run(
|
||||||
|
"""
|
||||||
|
cat <<EOF> {script}\n{content}\nEOF
|
||||||
|
chmod +x {script}
|
||||||
|
rm -f /var/log/{scriptlog}""".format(
|
||||||
|
script=full_script_path, content=mock_script, scriptlog=script
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def mock_command_passthrough(script, args, container):
|
||||||
|
"""
|
||||||
|
Per other mock_command* functions, allows intercepting of commands we don't want to run for real
|
||||||
|
in unit tests, however also allows only specific arguments to be mocked. Anything not defined will
|
||||||
|
be passed through to the actual command.
|
||||||
|
|
||||||
|
Example use-case: mocking `git pull` but still allowing `git clone` to work as intended
|
||||||
|
"""
|
||||||
|
orig_script_path = container.check_output("command -v {}".format(script))
|
||||||
|
full_script_path = "/usr/local/bin/{}".format(script)
|
||||||
|
mock_script = dedent(
|
||||||
|
r"""\
|
||||||
|
#!/bin/bash -e
|
||||||
|
echo "\$0 \$@" >> /var/log/{script}
|
||||||
|
case "\$1" in""".format(
|
||||||
|
script=script
|
||||||
|
)
|
||||||
|
)
|
||||||
|
for k, v in args.items():
|
||||||
|
case = dedent(
|
||||||
|
"""
|
||||||
|
{arg})
|
||||||
|
echo {res}
|
||||||
|
exit {retcode}
|
||||||
|
;;""".format(
|
||||||
|
arg=k, res=v[0], retcode=v[1]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
mock_script += case
|
||||||
|
mock_script += dedent(
|
||||||
|
r"""
|
||||||
|
*)
|
||||||
|
{orig_script_path} "\$@"
|
||||||
|
;;""".format(
|
||||||
|
orig_script_path=orig_script_path
|
||||||
|
)
|
||||||
|
)
|
||||||
|
mock_script += dedent(
|
||||||
|
"""
|
||||||
|
esac"""
|
||||||
|
)
|
||||||
|
container.run(
|
||||||
|
"""
|
||||||
|
cat <<EOF> {script}\n{content}\nEOF
|
||||||
|
chmod +x {script}
|
||||||
|
rm -f /var/log/{scriptlog}""".format(
|
||||||
|
script=full_script_path, content=mock_script, scriptlog=script
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def mock_command_run(script, args, container):
|
||||||
|
"""
|
||||||
|
Allows for setup of commands we don't really want to have to run for real
|
||||||
|
in unit tests
|
||||||
|
"""
|
||||||
|
full_script_path = "/usr/local/bin/{}".format(script)
|
||||||
|
mock_script = dedent(
|
||||||
|
r"""\
|
||||||
|
#!/bin/bash -e
|
||||||
|
echo "\$0 \$@" >> /var/log/{script}
|
||||||
|
case "\$1 \$2" in""".format(
|
||||||
|
script=script
|
||||||
|
)
|
||||||
|
)
|
||||||
|
for k, v in args.items():
|
||||||
|
case = dedent(
|
||||||
|
"""
|
||||||
|
\"{arg}\")
|
||||||
|
echo {res}
|
||||||
|
exit {retcode}
|
||||||
|
;;""".format(
|
||||||
|
arg=k, res=v[0], retcode=v[1]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
mock_script += case
|
||||||
|
mock_script += dedent(
|
||||||
|
"""
|
||||||
|
esac"""
|
||||||
|
)
|
||||||
|
container.run(
|
||||||
|
"""
|
||||||
|
cat <<EOF> {script}\n{content}\nEOF
|
||||||
|
chmod +x {script}
|
||||||
|
rm -f /var/log/{scriptlog}""".format(
|
||||||
|
script=full_script_path, content=mock_script, scriptlog=script
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def mock_command_2(script, args, container):
|
||||||
|
"""
|
||||||
|
Allows for setup of commands we don't really want to have to run for real
|
||||||
|
in unit tests
|
||||||
|
"""
|
||||||
|
full_script_path = "/usr/local/bin/{}".format(script)
|
||||||
|
mock_script = dedent(
|
||||||
|
r"""\
|
||||||
|
#!/bin/bash -e
|
||||||
|
echo "\$0 \$@" >> /var/log/{script}
|
||||||
|
case "\$1 \$2" in""".format(
|
||||||
|
script=script
|
||||||
|
)
|
||||||
|
)
|
||||||
|
for k, v in args.items():
|
||||||
|
case = dedent(
|
||||||
|
"""
|
||||||
|
\"{arg}\")
|
||||||
|
echo \"{res}\"
|
||||||
|
exit {retcode}
|
||||||
|
;;""".format(
|
||||||
|
arg=k, res=v[0], retcode=v[1]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
mock_script += case
|
||||||
|
mock_script += dedent(
|
||||||
|
"""
|
||||||
|
esac"""
|
||||||
|
)
|
||||||
|
container.run(
|
||||||
|
"""
|
||||||
|
cat <<EOF> {script}\n{content}\nEOF
|
||||||
|
chmod +x {script}
|
||||||
|
rm -f /var/log/{scriptlog}""".format(
|
||||||
|
script=full_script_path, content=mock_script, scriptlog=script
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def run_script(Pihole, script):
|
||||||
|
result = Pihole.run(script)
|
||||||
|
assert result.rc == 0
|
||||||
|
return result
|
||||||
6
test/requirements.txt
Normal file
6
test/requirements.txt
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
pyyaml == 6.0.2
|
||||||
|
pytest == 8.3.4
|
||||||
|
pytest-xdist == 3.6.1
|
||||||
|
pytest-testinfra == 10.1.1
|
||||||
|
tox == 4.23.2
|
||||||
|
pytest-clarity == 1.0.1
|
||||||
7
test/setup.py
Normal file
7
test/setup.py
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
from setuptools import setup
|
||||||
|
|
||||||
|
setup(
|
||||||
|
py_modules=[],
|
||||||
|
setup_requires=["pytest-runner"],
|
||||||
|
tests_require=["pytest"],
|
||||||
|
)
|
||||||
556
test/test_any_automated_install.py
Normal file
556
test/test_any_automated_install.py
Normal file
@@ -0,0 +1,556 @@
|
|||||||
|
import pytest
|
||||||
|
from textwrap import dedent
|
||||||
|
import re
|
||||||
|
from .conftest import (
|
||||||
|
tick_box,
|
||||||
|
info_box,
|
||||||
|
cross_box,
|
||||||
|
mock_command,
|
||||||
|
mock_command_run,
|
||||||
|
mock_command_2,
|
||||||
|
mock_command_passthrough,
|
||||||
|
run_script,
|
||||||
|
)
|
||||||
|
|
||||||
|
FTL_BRANCH = "development"
|
||||||
|
|
||||||
|
|
||||||
|
def test_supported_package_manager(host):
|
||||||
|
"""
|
||||||
|
confirm installer exits when no supported package manager found
|
||||||
|
"""
|
||||||
|
# break supported package managers
|
||||||
|
host.run("rm -rf /usr/bin/apt-get")
|
||||||
|
host.run("rm -rf /usr/bin/rpm")
|
||||||
|
package_manager_detect = host.run(
|
||||||
|
"""
|
||||||
|
source /opt/pihole/basic-install.sh
|
||||||
|
package_manager_detect
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
expected_stdout = cross_box + " No supported package manager found"
|
||||||
|
assert expected_stdout in package_manager_detect.stdout
|
||||||
|
# assert package_manager_detect.rc == 1
|
||||||
|
|
||||||
|
|
||||||
|
def test_selinux_not_detected(host):
|
||||||
|
"""
|
||||||
|
confirms installer continues when SELinux configuration file does not exist
|
||||||
|
"""
|
||||||
|
check_selinux = host.run(
|
||||||
|
"""
|
||||||
|
rm -f /etc/selinux/config
|
||||||
|
source /opt/pihole/basic-install.sh
|
||||||
|
checkSelinux
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
expected_stdout = info_box + " SELinux not detected"
|
||||||
|
assert expected_stdout in check_selinux.stdout
|
||||||
|
assert check_selinux.rc == 0
|
||||||
|
|
||||||
|
|
||||||
|
def get_directories_recursive(host, directory):
|
||||||
|
if directory is None:
|
||||||
|
return directory
|
||||||
|
# returns all non-hidden subdirs of 'directory'
|
||||||
|
dirs_raw = host.run("find {} -type d -not -path '*/.*'".format(directory))
|
||||||
|
dirs = list(filter(bool, dirs_raw.stdout.splitlines()))
|
||||||
|
return dirs
|
||||||
|
|
||||||
|
|
||||||
|
def test_installPihole_fresh_install_readableFiles(host):
|
||||||
|
"""
|
||||||
|
confirms all necessary files are readable by pihole user
|
||||||
|
"""
|
||||||
|
# dialog returns Cancel for user prompt
|
||||||
|
mock_command("dialog", {"*": ("", "0")}, host)
|
||||||
|
# mock git pull
|
||||||
|
mock_command_passthrough("git", {"pull": ("", "0")}, host)
|
||||||
|
# mock systemctl to not start FTL
|
||||||
|
mock_command_2(
|
||||||
|
"systemctl",
|
||||||
|
{
|
||||||
|
"enable pihole-FTL": ("", "0"),
|
||||||
|
"restart pihole-FTL": ("", "0"),
|
||||||
|
"start pihole-FTL": ("", "0"),
|
||||||
|
"*": ('echo "systemctl call with $@"', "0"),
|
||||||
|
},
|
||||||
|
host,
|
||||||
|
)
|
||||||
|
# try to install man
|
||||||
|
host.run("command -v apt-get > /dev/null && apt-get install -qq man")
|
||||||
|
host.run("command -v dnf > /dev/null && dnf install -y man")
|
||||||
|
host.run("command -v yum > /dev/null && yum install -y man")
|
||||||
|
# Workaround to get FTLv6 installed until it reaches master branch
|
||||||
|
host.run('echo "' + FTL_BRANCH + '" > /etc/pihole/ftlbranch')
|
||||||
|
install = host.run(
|
||||||
|
"""
|
||||||
|
export TERM=xterm
|
||||||
|
export DEBIAN_FRONTEND=noninteractive
|
||||||
|
umask 0027
|
||||||
|
runUnattended=true
|
||||||
|
useUpdateVars=true
|
||||||
|
source /opt/pihole/basic-install.sh > /dev/null
|
||||||
|
runUnattended=true
|
||||||
|
useUpdateVars=true
|
||||||
|
main
|
||||||
|
/opt/pihole/pihole-FTL-prestart.sh
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
assert 0 == install.rc
|
||||||
|
maninstalled = True
|
||||||
|
if (info_box + " man not installed") in install.stdout:
|
||||||
|
maninstalled = False
|
||||||
|
if (info_box + " man pages not installed") in install.stdout:
|
||||||
|
maninstalled = False
|
||||||
|
piholeuser = "pihole"
|
||||||
|
exit_status_success = 0
|
||||||
|
test_cmd = 'su --shell /bin/bash --command "test -{0} {1}" -p {2}'
|
||||||
|
# check files in /etc/pihole for read, write and execute permission
|
||||||
|
check_etc = test_cmd.format("r", "/etc/pihole", piholeuser)
|
||||||
|
actual_rc = host.run(check_etc).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
check_etc = test_cmd.format("x", "/etc/pihole", piholeuser)
|
||||||
|
actual_rc = host.run(check_etc).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
# readable and writable dhcp.leases
|
||||||
|
check_leases = test_cmd.format("r", "/etc/pihole/dhcp.leases", piholeuser)
|
||||||
|
actual_rc = host.run(check_leases).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
check_leases = test_cmd.format("w", "/etc/pihole/dhcp.leases", piholeuser)
|
||||||
|
actual_rc = host.run(check_leases).rc
|
||||||
|
# readable dns-servers.conf
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
check_servers = test_cmd.format("r", "/etc/pihole/dns-servers.conf", piholeuser)
|
||||||
|
actual_rc = host.run(check_servers).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
# readable install.log
|
||||||
|
check_install = test_cmd.format("r", "/etc/pihole/install.log", piholeuser)
|
||||||
|
actual_rc = host.run(check_install).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
# readable versions
|
||||||
|
check_localversion = test_cmd.format("r", "/etc/pihole/versions", piholeuser)
|
||||||
|
actual_rc = host.run(check_localversion).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
# readable logrotate
|
||||||
|
check_logrotate = test_cmd.format("r", "/etc/pihole/logrotate", piholeuser)
|
||||||
|
actual_rc = host.run(check_logrotate).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
# readable macvendor.db
|
||||||
|
check_macvendor = test_cmd.format("r", "/etc/pihole/macvendor.db", piholeuser)
|
||||||
|
actual_rc = host.run(check_macvendor).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
# check readable and executable /etc/init.d/pihole-FTL
|
||||||
|
check_init = test_cmd.format("x", "/etc/init.d/pihole-FTL", piholeuser)
|
||||||
|
actual_rc = host.run(check_init).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
check_init = test_cmd.format("r", "/etc/init.d/pihole-FTL", piholeuser)
|
||||||
|
actual_rc = host.run(check_init).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
# check readable and executable manpages
|
||||||
|
if maninstalled is True:
|
||||||
|
check_man = test_cmd.format("x", "/usr/local/share/man", piholeuser)
|
||||||
|
actual_rc = host.run(check_man).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
check_man = test_cmd.format("r", "/usr/local/share/man", piholeuser)
|
||||||
|
actual_rc = host.run(check_man).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
check_man = test_cmd.format("x", "/usr/local/share/man/man8", piholeuser)
|
||||||
|
actual_rc = host.run(check_man).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
check_man = test_cmd.format("r", "/usr/local/share/man/man8", piholeuser)
|
||||||
|
actual_rc = host.run(check_man).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
check_man = test_cmd.format("x", "/usr/local/share/man/man5", piholeuser)
|
||||||
|
actual_rc = host.run(check_man).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
check_man = test_cmd.format("r", "/usr/local/share/man/man5", piholeuser)
|
||||||
|
actual_rc = host.run(check_man).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
check_man = test_cmd.format(
|
||||||
|
"r", "/usr/local/share/man/man8/pihole.8", piholeuser
|
||||||
|
)
|
||||||
|
actual_rc = host.run(check_man).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
# check not readable cron file
|
||||||
|
check_sudo = test_cmd.format("x", "/etc/cron.d/", piholeuser)
|
||||||
|
actual_rc = host.run(check_sudo).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
check_sudo = test_cmd.format("r", "/etc/cron.d/", piholeuser)
|
||||||
|
actual_rc = host.run(check_sudo).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
check_sudo = test_cmd.format("r", "/etc/cron.d/pihole", piholeuser)
|
||||||
|
actual_rc = host.run(check_sudo).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
directories = get_directories_recursive(host, "/etc/.pihole/")
|
||||||
|
for directory in directories:
|
||||||
|
check_pihole = test_cmd.format("r", directory, piholeuser)
|
||||||
|
actual_rc = host.run(check_pihole).rc
|
||||||
|
check_pihole = test_cmd.format("x", directory, piholeuser)
|
||||||
|
actual_rc = host.run(check_pihole).rc
|
||||||
|
findfiles = 'find "{}" -maxdepth 1 -type f -exec echo {{}} \\;;'
|
||||||
|
filelist = host.run(findfiles.format(directory))
|
||||||
|
files = list(filter(bool, filelist.stdout.splitlines()))
|
||||||
|
for file in files:
|
||||||
|
check_pihole = test_cmd.format("r", file, piholeuser)
|
||||||
|
actual_rc = host.run(check_pihole).rc
|
||||||
|
|
||||||
|
|
||||||
|
def test_update_package_cache_success_no_errors(host):
|
||||||
|
"""
|
||||||
|
confirms package cache was updated without any errors
|
||||||
|
"""
|
||||||
|
updateCache = host.run(
|
||||||
|
"""
|
||||||
|
source /opt/pihole/basic-install.sh
|
||||||
|
package_manager_detect
|
||||||
|
update_package_cache
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
expected_stdout = tick_box + " Update local cache of available packages"
|
||||||
|
assert expected_stdout in updateCache.stdout
|
||||||
|
assert "error" not in updateCache.stdout.lower()
|
||||||
|
|
||||||
|
|
||||||
|
def test_update_package_cache_failure_no_errors(host):
|
||||||
|
"""
|
||||||
|
confirms package cache was not updated
|
||||||
|
"""
|
||||||
|
mock_command("apt-get", {"update": ("", "1")}, host)
|
||||||
|
updateCache = host.run(
|
||||||
|
"""
|
||||||
|
source /opt/pihole/basic-install.sh
|
||||||
|
package_manager_detect
|
||||||
|
update_package_cache
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
expected_stdout = cross_box + " Update local cache of available packages"
|
||||||
|
assert expected_stdout in updateCache.stdout
|
||||||
|
assert "Error: Unable to update package cache." in updateCache.stdout
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"arch,detected_string,supported",
|
||||||
|
[
|
||||||
|
("aarch64", "AArch64 (64 Bit ARM)", True),
|
||||||
|
("armv6", "ARMv6", True),
|
||||||
|
("armv7l", "ARMv7 (or newer)", True),
|
||||||
|
("armv7", "ARMv7 (or newer)", True),
|
||||||
|
("armv8a", "ARMv7 (or newer)", True),
|
||||||
|
("x86_64", "x86_64", True),
|
||||||
|
("riscv64", "riscv64", True),
|
||||||
|
("mips", "mips", False),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_FTL_detect_no_errors(host, arch, detected_string, supported):
|
||||||
|
"""
|
||||||
|
confirms only correct package is downloaded for FTL engine
|
||||||
|
"""
|
||||||
|
# mock uname to return passed platform
|
||||||
|
mock_command("uname", {"-m": (arch, "0")}, host)
|
||||||
|
# mock readelf to respond with passed CPU architecture
|
||||||
|
mock_command_2(
|
||||||
|
"readelf",
|
||||||
|
{
|
||||||
|
"-A /bin/sh": ("Tag_CPU_arch: " + arch, "0"),
|
||||||
|
"-A /usr/bin/sh": ("Tag_CPU_arch: " + arch, "0"),
|
||||||
|
},
|
||||||
|
host,
|
||||||
|
)
|
||||||
|
host.run('echo "' + FTL_BRANCH + '" > /etc/pihole/ftlbranch')
|
||||||
|
detectPlatform = host.run(
|
||||||
|
"""
|
||||||
|
source /opt/pihole/basic-install.sh
|
||||||
|
create_pihole_user
|
||||||
|
funcOutput=$(get_binary_name)
|
||||||
|
binary="pihole-FTL${funcOutput##*pihole-FTL}"
|
||||||
|
theRest="${funcOutput%pihole-FTL*}"
|
||||||
|
FTLdetect "${binary}" "${theRest}"
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
if supported:
|
||||||
|
expected_stdout = info_box + " FTL Checks..."
|
||||||
|
assert expected_stdout in detectPlatform.stdout
|
||||||
|
expected_stdout = tick_box + " Detected " + detected_string + " architecture"
|
||||||
|
assert expected_stdout in detectPlatform.stdout
|
||||||
|
expected_stdout = tick_box + " Downloading and Installing FTL"
|
||||||
|
assert expected_stdout in detectPlatform.stdout
|
||||||
|
else:
|
||||||
|
expected_stdout = (
|
||||||
|
"Not able to detect architecture (unknown: " + detected_string + ")"
|
||||||
|
)
|
||||||
|
assert expected_stdout in detectPlatform.stdout
|
||||||
|
|
||||||
|
|
||||||
|
def test_FTL_development_binary_installed_and_responsive_no_errors(host):
|
||||||
|
"""
|
||||||
|
confirms FTL development binary is copied and functional in installed location
|
||||||
|
"""
|
||||||
|
host.run('echo "' + FTL_BRANCH + '" > /etc/pihole/ftlbranch')
|
||||||
|
host.run(
|
||||||
|
"""
|
||||||
|
source /opt/pihole/basic-install.sh
|
||||||
|
create_pihole_user
|
||||||
|
funcOutput=$(get_binary_name)
|
||||||
|
binary="pihole-FTL${funcOutput##*pihole-FTL}"
|
||||||
|
theRest="${funcOutput%pihole-FTL*}"
|
||||||
|
FTLdetect "${binary}" "${theRest}"
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
version_check = host.run(
|
||||||
|
"""
|
||||||
|
VERSION=$(pihole-FTL version)
|
||||||
|
echo ${VERSION:0:1}
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
expected_stdout = "v"
|
||||||
|
assert expected_stdout in version_check.stdout
|
||||||
|
|
||||||
|
|
||||||
|
def test_IPv6_only_link_local(host):
|
||||||
|
"""
|
||||||
|
confirms IPv6 blocking is disabled for Link-local address
|
||||||
|
"""
|
||||||
|
# mock ip -6 address to return Link-local address
|
||||||
|
mock_command_2(
|
||||||
|
"ip",
|
||||||
|
{"-6 address": ("inet6 fe80::d210:52fa:fe00:7ad7/64 scope link", "0")},
|
||||||
|
host,
|
||||||
|
)
|
||||||
|
detectPlatform = host.run(
|
||||||
|
"""
|
||||||
|
source /opt/pihole/basic-install.sh
|
||||||
|
find_IPv6_information
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
expected_stdout = "Unable to find IPv6 ULA/GUA address"
|
||||||
|
assert expected_stdout in detectPlatform.stdout
|
||||||
|
|
||||||
|
|
||||||
|
def test_IPv6_only_ULA(host):
|
||||||
|
"""
|
||||||
|
confirms IPv6 blocking is enabled for ULA addresses
|
||||||
|
"""
|
||||||
|
# mock ip -6 address to return ULA address
|
||||||
|
mock_command_2(
|
||||||
|
"ip",
|
||||||
|
{
|
||||||
|
"-6 address": (
|
||||||
|
"inet6 fda2:2001:5555:0:d210:52fa:fe00:7ad7/64 scope global",
|
||||||
|
"0",
|
||||||
|
)
|
||||||
|
},
|
||||||
|
host,
|
||||||
|
)
|
||||||
|
detectPlatform = host.run(
|
||||||
|
"""
|
||||||
|
source /opt/pihole/basic-install.sh
|
||||||
|
find_IPv6_information
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
expected_stdout = "Found IPv6 ULA address"
|
||||||
|
assert expected_stdout in detectPlatform.stdout
|
||||||
|
|
||||||
|
|
||||||
|
def test_IPv6_only_GUA(host):
|
||||||
|
"""
|
||||||
|
confirms IPv6 blocking is enabled for GUA addresses
|
||||||
|
"""
|
||||||
|
# mock ip -6 address to return GUA address
|
||||||
|
mock_command_2(
|
||||||
|
"ip",
|
||||||
|
{
|
||||||
|
"-6 address": (
|
||||||
|
"inet6 2003:12:1e43:301:d210:52fa:fe00:7ad7/64 scope global",
|
||||||
|
"0",
|
||||||
|
)
|
||||||
|
},
|
||||||
|
host,
|
||||||
|
)
|
||||||
|
detectPlatform = host.run(
|
||||||
|
"""
|
||||||
|
source /opt/pihole/basic-install.sh
|
||||||
|
find_IPv6_information
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
expected_stdout = "Found IPv6 GUA address"
|
||||||
|
assert expected_stdout in detectPlatform.stdout
|
||||||
|
|
||||||
|
|
||||||
|
def test_IPv6_GUA_ULA_test(host):
|
||||||
|
"""
|
||||||
|
confirms IPv6 blocking is enabled for GUA and ULA addresses
|
||||||
|
"""
|
||||||
|
# mock ip -6 address to return GUA and ULA addresses
|
||||||
|
mock_command_2(
|
||||||
|
"ip",
|
||||||
|
{
|
||||||
|
"-6 address": (
|
||||||
|
"inet6 2003:12:1e43:301:d210:52fa:fe00:7ad7/64 scope global\n"
|
||||||
|
"inet6 fda2:2001:5555:0:d210:52fa:fe00:7ad7/64 scope global",
|
||||||
|
"0",
|
||||||
|
)
|
||||||
|
},
|
||||||
|
host,
|
||||||
|
)
|
||||||
|
detectPlatform = host.run(
|
||||||
|
"""
|
||||||
|
source /opt/pihole/basic-install.sh
|
||||||
|
find_IPv6_information
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
expected_stdout = "Found IPv6 ULA address"
|
||||||
|
assert expected_stdout in detectPlatform.stdout
|
||||||
|
|
||||||
|
|
||||||
|
def test_IPv6_ULA_GUA_test(host):
|
||||||
|
"""
|
||||||
|
confirms IPv6 blocking is enabled for GUA and ULA addresses
|
||||||
|
"""
|
||||||
|
# mock ip -6 address to return ULA and GUA addresses
|
||||||
|
mock_command_2(
|
||||||
|
"ip",
|
||||||
|
{
|
||||||
|
"-6 address": (
|
||||||
|
"inet6 fda2:2001:5555:0:d210:52fa:fe00:7ad7/64 scope global\n"
|
||||||
|
"inet6 2003:12:1e43:301:d210:52fa:fe00:7ad7/64 scope global",
|
||||||
|
"0",
|
||||||
|
)
|
||||||
|
},
|
||||||
|
host,
|
||||||
|
)
|
||||||
|
detectPlatform = host.run(
|
||||||
|
"""
|
||||||
|
source /opt/pihole/basic-install.sh
|
||||||
|
find_IPv6_information
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
expected_stdout = "Found IPv6 ULA address"
|
||||||
|
assert expected_stdout in detectPlatform.stdout
|
||||||
|
|
||||||
|
|
||||||
|
def test_validate_ip(host):
|
||||||
|
"""
|
||||||
|
Tests valid_ip for various IP addresses
|
||||||
|
"""
|
||||||
|
|
||||||
|
def test_address(addr, success=True):
|
||||||
|
output = host.run(
|
||||||
|
"""
|
||||||
|
source /opt/pihole/basic-install.sh
|
||||||
|
valid_ip "{addr}"
|
||||||
|
""".format(
|
||||||
|
addr=addr
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
assert output.rc == 0 if success else 1
|
||||||
|
|
||||||
|
test_address("192.168.1.1")
|
||||||
|
test_address("127.0.0.1")
|
||||||
|
test_address("255.255.255.255")
|
||||||
|
test_address("255.255.255.256", False)
|
||||||
|
test_address("255.255.256.255", False)
|
||||||
|
test_address("255.256.255.255", False)
|
||||||
|
test_address("256.255.255.255", False)
|
||||||
|
test_address("1092.168.1.1", False)
|
||||||
|
test_address("not an IP", False)
|
||||||
|
test_address("8.8.8.8#", False)
|
||||||
|
test_address("8.8.8.8#0")
|
||||||
|
test_address("8.8.8.8#1")
|
||||||
|
test_address("8.8.8.8#42")
|
||||||
|
test_address("8.8.8.8#888")
|
||||||
|
test_address("8.8.8.8#1337")
|
||||||
|
test_address("8.8.8.8#65535")
|
||||||
|
test_address("8.8.8.8#65536", False)
|
||||||
|
test_address("8.8.8.8#-1", False)
|
||||||
|
test_address("00.0.0.0", False)
|
||||||
|
test_address("010.0.0.0", False)
|
||||||
|
test_address("001.0.0.0", False)
|
||||||
|
test_address("0.0.0.0#00", False)
|
||||||
|
test_address("0.0.0.0#01", False)
|
||||||
|
test_address("0.0.0.0#001", False)
|
||||||
|
test_address("0.0.0.0#0001", False)
|
||||||
|
test_address("0.0.0.0#00001", False)
|
||||||
|
|
||||||
|
|
||||||
|
def test_os_check_fails(host):
|
||||||
|
"""Confirms install fails on unsupported OS"""
|
||||||
|
host.run(
|
||||||
|
"""
|
||||||
|
source /opt/pihole/basic-install.sh
|
||||||
|
package_manager_detect
|
||||||
|
build_dependency_package
|
||||||
|
install_dependent_packages
|
||||||
|
cat <<EOT > /etc/os-release
|
||||||
|
ID=UnsupportedOS
|
||||||
|
VERSION_ID="2"
|
||||||
|
EOT
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
detectOS = host.run(
|
||||||
|
"""t
|
||||||
|
source /opt/pihole/basic-install.sh
|
||||||
|
os_check
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
expected_stdout = "Unsupported OS detected: UnsupportedOS"
|
||||||
|
assert expected_stdout in detectOS.stdout
|
||||||
|
|
||||||
|
|
||||||
|
def test_os_check_passes(host):
|
||||||
|
"""Confirms OS meets the requirements"""
|
||||||
|
host.run(
|
||||||
|
"""
|
||||||
|
source /opt/pihole/basic-install.sh
|
||||||
|
package_manager_detect
|
||||||
|
build_dependency_package
|
||||||
|
install_dependent_packages
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
detectOS = host.run(
|
||||||
|
"""
|
||||||
|
source /opt/pihole/basic-install.sh
|
||||||
|
os_check
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
expected_stdout = "Supported OS detected"
|
||||||
|
assert expected_stdout in detectOS.stdout
|
||||||
|
|
||||||
|
|
||||||
|
def test_package_manager_has_pihole_deps(host):
|
||||||
|
"""Confirms OS is able to install the required packages for Pi-hole"""
|
||||||
|
mock_command("dialog", {"*": ("", "0")}, host)
|
||||||
|
output = host.run(
|
||||||
|
"""
|
||||||
|
source /opt/pihole/basic-install.sh
|
||||||
|
package_manager_detect
|
||||||
|
build_dependency_package
|
||||||
|
install_dependent_packages
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
assert "No package" not in output.stdout
|
||||||
|
assert output.rc == 0
|
||||||
|
|
||||||
|
|
||||||
|
def test_meta_package_uninstall(host):
|
||||||
|
"""Confirms OS is able to install and uninstall the Pi-hole meta package"""
|
||||||
|
mock_command("dialog", {"*": ("", "0")}, host)
|
||||||
|
install = host.run(
|
||||||
|
"""
|
||||||
|
source /opt/pihole/basic-install.sh
|
||||||
|
package_manager_detect
|
||||||
|
build_dependency_package
|
||||||
|
install_dependent_packages
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
assert install.rc == 0
|
||||||
|
|
||||||
|
uninstall = host.run(
|
||||||
|
"""
|
||||||
|
source /opt/pihole/uninstall.sh
|
||||||
|
removeMetaPackage
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
assert uninstall.rc == 0
|
||||||
59
test/test_any_utils.py
Normal file
59
test/test_any_utils.py
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
def test_key_val_replacement_works(host):
|
||||||
|
"""Confirms addOrEditKeyValPair either adds or replaces a key value pair in a given file"""
|
||||||
|
host.run(
|
||||||
|
"""
|
||||||
|
source /opt/pihole/utils.sh
|
||||||
|
addOrEditKeyValPair "./testoutput" "KEY_ONE" "value1"
|
||||||
|
addOrEditKeyValPair "./testoutput" "KEY_TWO" "value2"
|
||||||
|
addOrEditKeyValPair "./testoutput" "KEY_ONE" "value3"
|
||||||
|
addOrEditKeyValPair "./testoutput" "KEY_FOUR" "value4"
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
output = host.run(
|
||||||
|
"""
|
||||||
|
cat ./testoutput
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
expected_stdout = "KEY_ONE=value3\nKEY_TWO=value2\nKEY_FOUR=value4\n"
|
||||||
|
assert expected_stdout == output.stdout
|
||||||
|
|
||||||
|
|
||||||
|
def test_getFTLPID_default(host):
|
||||||
|
"""Confirms getFTLPID returns the default value if FTL is not running"""
|
||||||
|
output = host.run(
|
||||||
|
"""
|
||||||
|
source /opt/pihole/utils.sh
|
||||||
|
getFTLPID
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
expected_stdout = "-1\n"
|
||||||
|
assert expected_stdout == output.stdout
|
||||||
|
|
||||||
|
|
||||||
|
def test_setFTLConfigValue_getFTLConfigValue(host):
|
||||||
|
"""
|
||||||
|
Confirms getFTLConfigValue works (also assumes setFTLConfigValue works)
|
||||||
|
Requires FTL to be installed, so we do that first
|
||||||
|
(taken from test_FTL_development_binary_installed_and_responsive_no_errors)
|
||||||
|
"""
|
||||||
|
host.run(
|
||||||
|
"""
|
||||||
|
source /opt/pihole/basic-install.sh
|
||||||
|
create_pihole_user
|
||||||
|
funcOutput=$(get_binary_name)
|
||||||
|
echo "development" > /etc/pihole/ftlbranch
|
||||||
|
binary="pihole-FTL${funcOutput##*pihole-FTL}"
|
||||||
|
theRest="${funcOutput%pihole-FTL*}"
|
||||||
|
FTLdetect "${binary}" "${theRest}"
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
output = host.run(
|
||||||
|
"""
|
||||||
|
source /opt/pihole/utils.sh
|
||||||
|
setFTLConfigValue "dns.upstreams" '["9.9.9.9"]' > /dev/null
|
||||||
|
getFTLConfigValue "dns.upstreams"
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
assert "[ 9.9.9.9 ]" in output.stdout
|
||||||
75
test/test_centos_fedora_common_support.py
Normal file
75
test/test_centos_fedora_common_support.py
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
from .conftest import (
|
||||||
|
tick_box,
|
||||||
|
cross_box,
|
||||||
|
mock_command,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def mock_selinux_config(state, host):
|
||||||
|
"""
|
||||||
|
Creates a mock SELinux config file with expected content
|
||||||
|
"""
|
||||||
|
# validate state string
|
||||||
|
valid_states = ["enforcing", "permissive", "disabled"]
|
||||||
|
assert state in valid_states
|
||||||
|
# getenforce returns the running state of SELinux
|
||||||
|
mock_command("getenforce", {"*": (state.capitalize(), "0")}, host)
|
||||||
|
# create mock configuration with desired content
|
||||||
|
host.run(
|
||||||
|
"""
|
||||||
|
mkdir /etc/selinux
|
||||||
|
echo "SELINUX={state}" > /etc/selinux/config
|
||||||
|
""".format(
|
||||||
|
state=state.lower()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_selinux_enforcing_exit(host):
|
||||||
|
"""
|
||||||
|
confirms installer prompts to exit when SELinux is Enforcing by default
|
||||||
|
"""
|
||||||
|
mock_selinux_config("enforcing", host)
|
||||||
|
check_selinux = host.run(
|
||||||
|
"""
|
||||||
|
source /opt/pihole/basic-install.sh
|
||||||
|
checkSelinux
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
expected_stdout = cross_box + " Current SELinux: enforcing"
|
||||||
|
assert expected_stdout in check_selinux.stdout
|
||||||
|
expected_stdout = "SELinux Enforcing detected, exiting installer"
|
||||||
|
assert expected_stdout in check_selinux.stdout
|
||||||
|
assert check_selinux.rc == 1
|
||||||
|
|
||||||
|
|
||||||
|
def test_selinux_permissive(host):
|
||||||
|
"""
|
||||||
|
confirms installer continues when SELinux is Permissive
|
||||||
|
"""
|
||||||
|
mock_selinux_config("permissive", host)
|
||||||
|
check_selinux = host.run(
|
||||||
|
"""
|
||||||
|
source /opt/pihole/basic-install.sh
|
||||||
|
checkSelinux
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
expected_stdout = tick_box + " Current SELinux: permissive"
|
||||||
|
assert expected_stdout in check_selinux.stdout
|
||||||
|
assert check_selinux.rc == 0
|
||||||
|
|
||||||
|
|
||||||
|
def test_selinux_disabled(host):
|
||||||
|
"""
|
||||||
|
confirms installer continues when SELinux is Disabled
|
||||||
|
"""
|
||||||
|
mock_selinux_config("disabled", host)
|
||||||
|
check_selinux = host.run(
|
||||||
|
"""
|
||||||
|
source /opt/pihole/basic-install.sh
|
||||||
|
checkSelinux
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
expected_stdout = tick_box + " Current SELinux: disabled"
|
||||||
|
assert expected_stdout in check_selinux.stdout
|
||||||
|
assert check_selinux.rc == 0
|
||||||
10
test/tox.centos_9.ini
Normal file
10
test/tox.centos_9.ini
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
[tox]
|
||||||
|
envlist = py3
|
||||||
|
|
||||||
|
[testenv:py3]
|
||||||
|
allowlist_externals = docker
|
||||||
|
deps = -rrequirements.txt
|
||||||
|
setenv =
|
||||||
|
COLUMNS=120
|
||||||
|
commands = docker buildx build --load --progress plain -f _centos_9.Dockerfile -t pytest_pihole:test_container ../
|
||||||
|
pytest {posargs:-vv -n auto} ./test_any_automated_install.py ./test_any_utils.py ./test_centos_fedora_common_support.py
|
||||||
10
test/tox.debian_11.ini
Normal file
10
test/tox.debian_11.ini
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
[tox]
|
||||||
|
envlist = py3
|
||||||
|
|
||||||
|
[testenv:py3]
|
||||||
|
allowlist_externals = docker
|
||||||
|
deps = -rrequirements.txt
|
||||||
|
setenv =
|
||||||
|
COLUMNS=120
|
||||||
|
commands = docker buildx build --load --progress plain -f _debian_11.Dockerfile -t pytest_pihole:test_container ../
|
||||||
|
pytest {posargs:-vv -n auto} ./test_any_automated_install.py ./test_any_utils.py
|
||||||
10
test/tox.debian_12.ini
Normal file
10
test/tox.debian_12.ini
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
[tox]
|
||||||
|
envlist = py3
|
||||||
|
|
||||||
|
[testenv:py3]
|
||||||
|
allowlist_externals = docker
|
||||||
|
deps = -rrequirements.txt
|
||||||
|
setenv =
|
||||||
|
COLUMNS=120
|
||||||
|
commands = docker buildx build --load --progress plain -f _debian_12.Dockerfile -t pytest_pihole:test_container ../
|
||||||
|
pytest {posargs:-vv -n auto} ./test_any_automated_install.py ./test_any_utils.py
|
||||||
10
test/tox.fedora_40.ini
Normal file
10
test/tox.fedora_40.ini
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
[tox]
|
||||||
|
envlist = py3
|
||||||
|
|
||||||
|
[testenv]
|
||||||
|
allowlist_externals = docker
|
||||||
|
deps = -rrequirements.txt
|
||||||
|
setenv =
|
||||||
|
COLUMNS=120
|
||||||
|
commands = docker buildx build --load --progress plain -f _fedora_40.Dockerfile -t pytest_pihole:test_container ../
|
||||||
|
pytest {posargs:-vv -n auto} ./test_any_automated_install.py ./test_any_utils.py ./test_centos_fedora_common_support.py
|
||||||
10
test/tox.fedora_41.ini
Normal file
10
test/tox.fedora_41.ini
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
[tox]
|
||||||
|
envlist = py3
|
||||||
|
|
||||||
|
[testenv]
|
||||||
|
allowlist_externals = docker
|
||||||
|
deps = -rrequirements.txt
|
||||||
|
setenv =
|
||||||
|
COLUMNS=120
|
||||||
|
commands = docker buildx build --load --progress plain -f _fedora_41.Dockerfile -t pytest_pihole:test_container ../
|
||||||
|
pytest {posargs:-vv -n auto} ./test_any_automated_install.py ./test_any_utils.py ./test_centos_fedora_common_support.py
|
||||||
10
test/tox.ubuntu_20.ini
Normal file
10
test/tox.ubuntu_20.ini
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
[tox]
|
||||||
|
envlist = py3
|
||||||
|
|
||||||
|
[testenv:py3]
|
||||||
|
allowlist_externals = docker
|
||||||
|
deps = -rrequirements.txt
|
||||||
|
setenv =
|
||||||
|
COLUMNS=120
|
||||||
|
commands = docker buildx build --load --progress plain -f _ubuntu_20.Dockerfile -t pytest_pihole:test_container ../
|
||||||
|
pytest {posargs:-vv -n auto} ./test_any_automated_install.py ./test_any_utils.py
|
||||||
10
test/tox.ubuntu_22.ini
Normal file
10
test/tox.ubuntu_22.ini
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
[tox]
|
||||||
|
envlist = py3
|
||||||
|
|
||||||
|
[testenv:py3]
|
||||||
|
allowlist_externals = docker
|
||||||
|
deps = -rrequirements.txt
|
||||||
|
setenv =
|
||||||
|
COLUMNS=120
|
||||||
|
commands = docker buildx build --load --progress plain -f _ubuntu_22.Dockerfile -t pytest_pihole:test_container ../
|
||||||
|
pytest {posargs:-vv -n auto} ./test_any_automated_install.py ./test_any_utils.py
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user