mirror of
https://github.com/asterisk/asterisk.git
synced 2025-12-13 02:22:21 +00:00
Compare commits
4565 Commits
0.7.1
...
1.2.2-nets
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f7d5acbeea | ||
|
|
914ac7c596 | ||
|
|
c6b845fe98 | ||
|
|
7c29d1c571 | ||
|
|
1cc6f6d3bb | ||
|
|
ca0a371996 | ||
|
|
b0fd9f9b74 | ||
|
|
396f6561a4 | ||
|
|
f16619507a | ||
|
|
69ac155838 | ||
|
|
a6bae85952 | ||
|
|
494b9c486e | ||
|
|
d8c5d338cb | ||
|
|
417438fea0 | ||
|
|
5488ffb6d4 | ||
|
|
e8725ce940 | ||
|
|
0e734920e8 | ||
|
|
ad598a2060 | ||
|
|
bb47f95262 | ||
|
|
a7a2115b9c | ||
|
|
18429f2a69 | ||
|
|
7e6430787c | ||
|
|
dc3ba8c223 | ||
|
|
2fd6520a7e | ||
|
|
7a61b36104 | ||
|
|
2f4783a770 | ||
|
|
6056391a78 | ||
|
|
213b3575ce | ||
|
|
3821e18d08 | ||
|
|
224c6e3f7c | ||
|
|
18ab6f429c | ||
|
|
07f8542ce7 | ||
|
|
cf293c224d | ||
|
|
e234ad0011 | ||
|
|
229b778b0b | ||
|
|
66f484defe | ||
|
|
ed523e248a | ||
|
|
3c49f27bf4 | ||
|
|
226d146b25 | ||
|
|
1892289329 | ||
|
|
5529fc0355 | ||
|
|
73ef559240 | ||
|
|
b59a63c8cd | ||
|
|
c36927137f | ||
|
|
649aaad100 | ||
|
|
ea4c262482 | ||
|
|
89de6c9df6 | ||
|
|
4578bc3b0c | ||
|
|
8df1e4866a | ||
|
|
9f92220a9c | ||
|
|
09a9e7bcb7 | ||
|
|
a434f8877a | ||
|
|
ef891dc0a7 | ||
|
|
3ebe29c983 | ||
|
|
1028e43464 | ||
|
|
4979f66f28 | ||
|
|
a5e9fe97c8 | ||
|
|
2293cfaf84 | ||
|
|
d252dde933 | ||
|
|
37a49a5992 | ||
|
|
2783801610 | ||
|
|
82f19c9a91 | ||
|
|
71d9531e45 | ||
|
|
3bbeaefa57 | ||
|
|
4611be805a | ||
|
|
587493fdfc | ||
|
|
50079144e3 | ||
|
|
2ca80e76a0 | ||
|
|
68e6502484 | ||
|
|
1e91dfa5df | ||
|
|
e4e5f7c65b | ||
|
|
8ef66261f1 | ||
|
|
90812b536c | ||
|
|
2b880d3ef8 | ||
|
|
6ab729aeb3 | ||
|
|
c9f97f49c5 | ||
|
|
8b352fcb94 | ||
|
|
5a06af4d57 | ||
|
|
2ede900bfd | ||
|
|
fb0ffc7784 | ||
|
|
e69171dc06 | ||
|
|
8452f6b494 | ||
|
|
f9bc6f8afc | ||
|
|
f9f44d7d9b | ||
|
|
86bb1472cc | ||
|
|
ef09c506c8 | ||
|
|
af7b3b420e | ||
|
|
3b80a35a66 | ||
|
|
f59b27258c | ||
|
|
d38fff38f9 | ||
|
|
91c5b12f25 | ||
|
|
894bdd5cda | ||
|
|
d8c58ca6c8 | ||
|
|
43f7956422 | ||
|
|
96fcc02900 | ||
|
|
2e8b6e7f20 | ||
|
|
3ed93398e9 | ||
|
|
d84e0caea8 | ||
|
|
5c1da58b90 | ||
|
|
018c617199 | ||
|
|
a49f954f6a | ||
|
|
03a8791440 | ||
|
|
78ad17381e | ||
|
|
5b03803e2f | ||
|
|
ee1e461a57 | ||
|
|
a543725311 | ||
|
|
8c701a0861 | ||
|
|
5fbe566524 | ||
|
|
e14cf31bc9 | ||
|
|
0042c03c7e | ||
|
|
41023ecb9c | ||
|
|
fb8d0a544d | ||
|
|
acaf8c9cc9 | ||
|
|
0d3fc8d103 | ||
|
|
9bbfbacacc | ||
|
|
8e301c629f | ||
|
|
9576d8a081 | ||
|
|
7db96672bf | ||
|
|
0d8f099ca2 | ||
|
|
0a4d7e5068 | ||
|
|
a32f75b800 | ||
|
|
78f37c51ef | ||
|
|
d6e5eb75ee | ||
|
|
6f433a7e7b | ||
|
|
ce2ecb5582 | ||
|
|
45c15e8561 | ||
|
|
5e3f4186da | ||
|
|
d03694df19 | ||
|
|
d52e8fa7d2 | ||
|
|
77c6cd0bff | ||
|
|
463ebe8b4b | ||
|
|
a563eab49a | ||
|
|
bf9d4b103d | ||
|
|
7dc2449f3a | ||
|
|
27cc20db11 | ||
|
|
4e04f5f731 | ||
|
|
5ec3844077 | ||
|
|
f641c7cd0d | ||
|
|
49aa54cafc | ||
|
|
e3b81e66a1 | ||
|
|
7bb6b928b5 | ||
|
|
ad4dc7c4a9 | ||
|
|
feb9764721 | ||
|
|
8c74501001 | ||
|
|
5861d3fd64 | ||
|
|
08acdc6a86 | ||
|
|
3b50570c9b | ||
|
|
00d7e962a7 | ||
|
|
192f7413c2 | ||
|
|
5bdb8074aa | ||
|
|
6abe5e1b23 | ||
|
|
4612b4ccca | ||
|
|
3245bf61a1 | ||
|
|
9ee13167bb | ||
|
|
ca9633ca9b | ||
|
|
e04884545c | ||
|
|
aa2239a050 | ||
|
|
40a1b60cbd | ||
|
|
cccb11916f | ||
|
|
49641825eb | ||
|
|
c14c078405 | ||
|
|
f2af073588 | ||
|
|
b9a5eddb6d | ||
|
|
bffc815375 | ||
|
|
5c3f322364 | ||
|
|
3a6fae817c | ||
|
|
d8f74ecb94 | ||
|
|
f7f2b1b033 | ||
|
|
601ab7ff82 | ||
|
|
59fe845c6c | ||
|
|
af4301802d | ||
|
|
3dc12025c8 | ||
|
|
c86be56b3b | ||
|
|
6d0b8522d0 | ||
|
|
892978fb4b | ||
|
|
891569befc | ||
|
|
7953c3f407 | ||
|
|
60ebbb5744 | ||
|
|
544a2ecbd3 | ||
|
|
639104bbb2 | ||
|
|
2b656be753 | ||
|
|
492087f45f | ||
|
|
b9e2fcfdea | ||
|
|
296ca06e35 | ||
|
|
a31a587bc0 | ||
|
|
1fb64fa4bd | ||
|
|
9cdcba170e | ||
|
|
4331958422 | ||
|
|
c7c3fa1d53 | ||
|
|
3d599e6501 | ||
|
|
e88e390bb8 | ||
|
|
a14758518d | ||
|
|
a45b2019df | ||
|
|
6bfdf6f45a | ||
|
|
2e6475fd03 | ||
|
|
685e88645f | ||
|
|
2a53a89aa6 | ||
|
|
15705f94a7 | ||
|
|
d8dfa4434d | ||
|
|
0702130ed1 | ||
|
|
3fbcf6e3d0 | ||
|
|
8f965a06cb | ||
|
|
b05ff7c343 | ||
|
|
d5348b71c9 | ||
|
|
c9ceb15e1e | ||
|
|
2b547e1f9e | ||
|
|
266674e123 | ||
|
|
766d1a73b1 | ||
|
|
52da8d9862 | ||
|
|
3b8c82543d | ||
|
|
50ab28bd94 | ||
|
|
38c665bd67 | ||
|
|
51b54236de | ||
|
|
64aaaa1f4a | ||
|
|
8605bf0104 | ||
|
|
6f45949ca1 | ||
|
|
500dd158fe | ||
|
|
a7d794a0ac | ||
|
|
00de2bc78b | ||
|
|
36315b865b | ||
|
|
45c7589284 | ||
|
|
78d740290a | ||
|
|
91b616c9ba | ||
|
|
ed465f4a85 | ||
|
|
4606d74a66 | ||
|
|
c6e7b2a333 | ||
|
|
7e939cb273 | ||
|
|
9e4c207dd3 | ||
|
|
5545974c6a | ||
|
|
c79c0f97f1 | ||
|
|
f603eb0135 | ||
|
|
ba349963a8 | ||
|
|
b3ffb91539 | ||
|
|
adb02d0107 | ||
|
|
734034d824 | ||
|
|
1740d40182 | ||
|
|
8c9a32bd4b | ||
|
|
8fddeef1ac | ||
|
|
829447c811 | ||
|
|
608d63ac54 | ||
|
|
54dd7ac9fa | ||
|
|
ff364c3068 | ||
|
|
b124b6d649 | ||
|
|
14d426098e | ||
|
|
c3b6ac6004 | ||
|
|
642be05f09 | ||
|
|
f3b4e0291c | ||
|
|
9b037b4872 | ||
|
|
73b90d3b74 | ||
|
|
6dabdbc7cd | ||
|
|
ea70f31f2f | ||
|
|
0aa9429c96 | ||
|
|
a87d3f5c19 | ||
|
|
580d6f3482 | ||
|
|
bdda6254f4 | ||
|
|
cdf4031963 | ||
|
|
9a06a7c14c | ||
|
|
33c15f19fe | ||
|
|
9b03ffc513 | ||
|
|
3e4feebbd6 | ||
|
|
9433b7157f | ||
|
|
15b01f246c | ||
|
|
7b2e24777f | ||
|
|
c5f0a6db6f | ||
|
|
5efc81c789 | ||
|
|
a612ed5f72 | ||
|
|
987b87662c | ||
|
|
511c096592 | ||
|
|
0941c32d38 | ||
|
|
ebf04fc570 | ||
|
|
2251dd3723 | ||
|
|
eb24670aff | ||
|
|
869ae80f16 | ||
|
|
a4be983a63 | ||
|
|
77390dfeaf | ||
|
|
d56ce5d1f3 | ||
|
|
8f7c94ab0f | ||
|
|
52f25ae960 | ||
|
|
9061716644 | ||
|
|
e463c42ba7 | ||
|
|
00d3c31496 | ||
|
|
a0a9769616 | ||
|
|
2ea48ce114 | ||
|
|
be7cdd4cd1 | ||
|
|
6e27e24452 | ||
|
|
81bda951d2 | ||
|
|
0ac4bbfdd9 | ||
|
|
3a003e8714 | ||
|
|
6f4fabf043 | ||
|
|
145daf44d8 | ||
|
|
3fb2544a41 | ||
|
|
c6f312fdef | ||
|
|
5e0149d7cf | ||
|
|
24cc108694 | ||
|
|
5eceb92944 | ||
|
|
8f536c775e | ||
|
|
1ca8bccc2f | ||
|
|
608f5f7f45 | ||
|
|
018e8c8395 | ||
|
|
87c87fe158 | ||
|
|
f09c6bc78e | ||
|
|
4eb2c0d832 | ||
|
|
e8f2ad304a | ||
|
|
bb3e125ed4 | ||
|
|
e4ce764744 | ||
|
|
7d4a5abb1d | ||
|
|
bb7eb69c09 | ||
|
|
88cc39af74 | ||
|
|
f3d02da7d8 | ||
|
|
3cf2991be1 | ||
|
|
dd21a2b170 | ||
|
|
29dbc6c204 | ||
|
|
f477f462d3 | ||
|
|
31a804b97c | ||
|
|
75c812f26d | ||
|
|
314bdba709 | ||
|
|
1781e73435 | ||
|
|
3bd298f2dd | ||
|
|
4600902059 | ||
|
|
8e680521ec | ||
|
|
7c3efb156c | ||
|
|
b721635619 | ||
|
|
535ed63c6f | ||
|
|
34152c3abc | ||
|
|
5e17bb19d9 | ||
|
|
a67c2702c5 | ||
|
|
ddf63421f6 | ||
|
|
3d473eebbc | ||
|
|
994b9db081 | ||
|
|
da0d0f975a | ||
|
|
c103bc7806 | ||
|
|
5039ee0965 | ||
|
|
8f8fc4e57e | ||
|
|
929d7e6e9b | ||
|
|
3e2507a07a | ||
|
|
980887f8eb | ||
|
|
2bebbca579 | ||
|
|
8925c3834b | ||
|
|
426360e389 | ||
|
|
fc9612edad | ||
|
|
5b252b65e6 | ||
|
|
fa46248f9d | ||
|
|
27041dbda8 | ||
|
|
e9f5bd158b | ||
|
|
8f0a6a7d4f | ||
|
|
ce50837d70 | ||
|
|
150ff6393b | ||
|
|
5f50e4cb93 | ||
|
|
9693d05882 | ||
|
|
b2c2b5cd49 | ||
|
|
610f5614e3 | ||
|
|
e1bcf1d043 | ||
|
|
661a2b97af | ||
|
|
986a8ca089 | ||
|
|
9b6f887db5 | ||
|
|
7ffb604a2f | ||
|
|
b05e64ed12 | ||
|
|
631ee6670c | ||
|
|
da097c4f5e | ||
|
|
156470f895 | ||
|
|
ddaed942ee | ||
|
|
d6b64431b0 | ||
|
|
8839ff95df | ||
|
|
c24c35e5b6 | ||
|
|
bb47f9fdc3 | ||
|
|
cfced0420e | ||
|
|
03ceef35ac | ||
|
|
236ce8f796 | ||
|
|
eae43386f0 | ||
|
|
cb28ef70bc | ||
|
|
261e51b03a | ||
|
|
4468de1bd7 | ||
|
|
6eaca0ad8f | ||
|
|
033cd4d58f | ||
|
|
e86e9a9fe3 | ||
|
|
d8672874ef | ||
|
|
9c25f9d1d5 | ||
|
|
0ac988acaa | ||
|
|
b099701da9 | ||
|
|
3da6bf02c9 | ||
|
|
a15a52208d | ||
|
|
0a314b2454 | ||
|
|
b175ff39ef | ||
|
|
551ac9af04 | ||
|
|
c3f9388b23 | ||
|
|
f9c8bb8087 | ||
|
|
a40e852ed3 | ||
|
|
8fb55e2478 | ||
|
|
7ef0527a7d | ||
|
|
20a7a4ca96 | ||
|
|
39d27dbab8 | ||
|
|
ccc121825f | ||
|
|
06320f5790 | ||
|
|
388f958ecc | ||
|
|
754e28abaf | ||
|
|
a4c3f0ae61 | ||
|
|
d6a963c476 | ||
|
|
6b26826bab | ||
|
|
6be92affa2 | ||
|
|
15ac76178a | ||
|
|
80fb221f10 | ||
|
|
ed3be69bce | ||
|
|
e6fc49806d | ||
|
|
846b39a9f1 | ||
|
|
97c9900b59 | ||
|
|
8dad624c68 | ||
|
|
c24ba6ac5e | ||
|
|
fff6a2c159 | ||
|
|
69194e2bc2 | ||
|
|
f9a98f7110 | ||
|
|
a0cb07e467 | ||
|
|
ce6b727c2c | ||
|
|
79c0865338 | ||
|
|
0d34142f7e | ||
|
|
d47e839c32 | ||
|
|
59584f5744 | ||
|
|
aca0431935 | ||
|
|
de47e29d09 | ||
|
|
f8c90f03b8 | ||
|
|
7deac2300a | ||
|
|
395f81d734 | ||
|
|
9ddf0e4dce | ||
|
|
3332a8acd1 | ||
|
|
5187de9ab6 | ||
|
|
dbc5c06c94 | ||
|
|
a736096e0b | ||
|
|
b5326f99fc | ||
|
|
08e32630ad | ||
|
|
87d4ff6fcd | ||
|
|
d57fb0b655 | ||
|
|
f1b14773dd | ||
|
|
052db5af42 | ||
|
|
7810f546f3 | ||
|
|
f622612bee | ||
|
|
6262e9ec9f | ||
|
|
6324072247 | ||
|
|
c7db73070a | ||
|
|
0b36348b12 | ||
|
|
f2dcf45a98 | ||
|
|
f31f09bf53 | ||
|
|
3453e3efa5 | ||
|
|
c3226a226a | ||
|
|
60e9a6edf7 | ||
|
|
5f78c43950 | ||
|
|
c3c96a7461 | ||
|
|
4cc2618bd1 | ||
|
|
0f850c2ffb | ||
|
|
f5d5814f5f | ||
|
|
e60ab6d916 | ||
|
|
e973e76c9f | ||
|
|
5ef59963d0 | ||
|
|
56135f210f | ||
|
|
b4e0cedf94 | ||
|
|
e726a13036 | ||
|
|
4aa7912057 | ||
|
|
e5afdbbe16 | ||
|
|
e603dcedb5 | ||
|
|
44640b39cf | ||
|
|
29829640bf | ||
|
|
907fd55883 | ||
|
|
b1cee61174 | ||
|
|
65cb05b658 | ||
|
|
dbdd193e12 | ||
|
|
a3df4cdda2 | ||
|
|
5c8c0ef907 | ||
|
|
eace0101f2 | ||
|
|
a16432e294 | ||
|
|
e634c61ef8 | ||
|
|
37add4fee5 | ||
|
|
68c2c01b1c | ||
|
|
50d20994f8 | ||
|
|
82d7020516 | ||
|
|
463ad17f5d | ||
|
|
b59ab89e1a | ||
|
|
ff34fbd02b | ||
|
|
4e919f337c | ||
|
|
a863d2b280 | ||
|
|
07e6b5c19a | ||
|
|
7e890dd49c | ||
|
|
7a59bc42c8 | ||
|
|
43fd4d64b0 | ||
|
|
4d5c1aefb7 | ||
|
|
858e90fe57 | ||
|
|
d499a85f05 | ||
|
|
d2025ad2a1 | ||
|
|
f5a38b3871 | ||
|
|
1ceb04cfb7 | ||
|
|
4803298fe8 | ||
|
|
90cfc9e3bc | ||
|
|
a5dd6a1a14 | ||
|
|
754446e5ac | ||
|
|
ce16733e72 | ||
|
|
0aec4ef713 | ||
|
|
141d9f7156 | ||
|
|
9b69c79a36 | ||
|
|
69bc7e0900 | ||
|
|
4d1506e64d | ||
|
|
2fe49e7a5f | ||
|
|
9a85d06a64 | ||
|
|
cb5e5c1fd5 | ||
|
|
57a8f5d82c | ||
|
|
cc5f36d139 | ||
|
|
9ce40204d6 | ||
|
|
1e21c56426 | ||
|
|
ba7386ebed | ||
|
|
81932c6142 | ||
|
|
454061ec18 | ||
|
|
28dacd0815 | ||
|
|
7c936b8826 | ||
|
|
cc0d3c33ae | ||
|
|
d509e41078 | ||
|
|
7215e4179d | ||
|
|
0b265779b2 | ||
|
|
053326ac85 | ||
|
|
03eb870f3e | ||
|
|
bcb449e56b | ||
|
|
370f98e223 | ||
|
|
c05c0c7ce6 | ||
|
|
7734cca1c2 | ||
|
|
a74e947c59 | ||
|
|
d75fb48fb8 | ||
|
|
dee30a519e | ||
|
|
1f2943fc0a | ||
|
|
485e3e0801 | ||
|
|
04d7bcc757 | ||
|
|
dd11afca42 | ||
|
|
6fea13619e | ||
|
|
bb49ec837f | ||
|
|
7c99490b3a | ||
|
|
f48b822a20 | ||
|
|
42cb1956fc | ||
|
|
995b3973a2 | ||
|
|
8e5d45f3ac | ||
|
|
bdef480cdd | ||
|
|
7560605ebc | ||
|
|
522dfad107 | ||
|
|
4d9210f705 | ||
|
|
65afb68602 | ||
|
|
c07a31e4bc | ||
|
|
cc104b0066 | ||
|
|
33377538b0 | ||
|
|
c5a8178bb4 | ||
|
|
460655f31c | ||
|
|
1ae71d0b41 | ||
|
|
a5373b7e78 | ||
|
|
080cc2d4b6 | ||
|
|
65f586c866 | ||
|
|
c0119acc0e | ||
|
|
2aa0434048 | ||
|
|
350aaac04b | ||
|
|
6f869da9b0 | ||
|
|
b00e8e509b | ||
|
|
8496d5fe92 | ||
|
|
4807571648 | ||
|
|
d9f508c7f1 | ||
|
|
a755500ef8 | ||
|
|
d50adefa05 | ||
|
|
17b668e180 | ||
|
|
130bf3b9e0 | ||
|
|
0bffff1930 | ||
|
|
aeaf9f4cc6 | ||
|
|
7c1bbe6eef | ||
|
|
6fe572d1a9 | ||
|
|
b7c31babb0 | ||
|
|
f387421905 | ||
|
|
e338682949 | ||
|
|
b1a61a9672 | ||
|
|
0c886c21c2 | ||
|
|
f7d567fe85 | ||
|
|
e67a6e0344 | ||
|
|
a0a478a72c | ||
|
|
dea1d768f9 | ||
|
|
3f285f03e1 | ||
|
|
1406f660b6 | ||
|
|
d4bf5408a7 | ||
|
|
d167235344 | ||
|
|
9835bc4330 | ||
|
|
270b98d2f4 | ||
|
|
44a7b88d82 | ||
|
|
a08f3f75ff | ||
|
|
7f429e3b02 | ||
|
|
9d1fc454d4 | ||
|
|
834193c08a | ||
|
|
e0680525e7 | ||
|
|
2b883819be | ||
|
|
8e4697d8f2 | ||
|
|
62209ede0c | ||
|
|
7eb43aa05d | ||
|
|
6c54fa36dd | ||
|
|
d45b683bdd | ||
|
|
91b72f5ff0 | ||
|
|
3b7332c5e6 | ||
|
|
13519f72e7 | ||
|
|
35b5891b74 | ||
|
|
61a0f7a65e | ||
|
|
ea215f5b7d | ||
|
|
4287cb7f42 | ||
|
|
b450a235b2 | ||
|
|
f8f7d21252 | ||
|
|
eb91322494 | ||
|
|
2685a48e37 | ||
|
|
35c4afd0fd | ||
|
|
b40ba965d6 | ||
|
|
b5e6b8af98 | ||
|
|
9f0cf49bca | ||
|
|
90aec0b0e3 | ||
|
|
380005fea4 | ||
|
|
3c020accfd | ||
|
|
bca61024ca | ||
|
|
bc596e3543 | ||
|
|
626582a84c | ||
|
|
8af7725f98 | ||
|
|
266529a503 | ||
|
|
fdccf66d52 | ||
|
|
9bbf4c3854 | ||
|
|
da7ca691b2 | ||
|
|
02c80ab20b | ||
|
|
5156c0621f | ||
|
|
44aff84c2e | ||
|
|
f68285950b | ||
|
|
852bf07caa | ||
|
|
24cdb73f92 | ||
|
|
78fa3593b1 | ||
|
|
aae3bb3e48 | ||
|
|
9d63d731aa | ||
|
|
f0b4072039 | ||
|
|
43d43b8b46 | ||
|
|
d3f7c5fb74 | ||
|
|
051ddb97f3 | ||
|
|
5599da9581 | ||
|
|
d612e3bc27 | ||
|
|
43e0f52600 | ||
|
|
b151666d4c | ||
|
|
1097fc2d38 | ||
|
|
da7c542e29 | ||
|
|
168733a179 | ||
|
|
9804f96c0f | ||
|
|
fcc0b23e18 | ||
|
|
446d1eee3e | ||
|
|
96286be0ee | ||
|
|
1b3cb1e8a6 | ||
|
|
cfabcabae8 | ||
|
|
7470ddb6b2 | ||
|
|
7196493caa | ||
|
|
2e5537a4a0 | ||
|
|
a21c9058e0 | ||
|
|
eb4a86ee7b | ||
|
|
b3d871f223 | ||
|
|
779d033f21 | ||
|
|
afb00fce12 | ||
|
|
21eb11c40e | ||
|
|
8087701923 | ||
|
|
6f96370770 | ||
|
|
ff649ebc1b | ||
|
|
bcaaea9ce6 | ||
|
|
56ca94095a | ||
|
|
b28847320d | ||
|
|
9ce1402c8b | ||
|
|
59e784c96a | ||
|
|
29bdd1b424 | ||
|
|
b8f23573fa | ||
|
|
d6ef44afe0 | ||
|
|
1a0ceef2db | ||
|
|
3cba705808 | ||
|
|
777e97ab26 | ||
|
|
c1517d081a | ||
|
|
4fb8ce1fd9 | ||
|
|
981970c57b | ||
|
|
44e3b6feb1 | ||
|
|
5bd40f4e11 | ||
|
|
509c285380 | ||
|
|
c4d824cf71 | ||
|
|
f94a1d47d6 | ||
|
|
fadae17355 | ||
|
|
ff41d6ab6c | ||
|
|
b68657fcec | ||
|
|
eb332490ff | ||
|
|
02e5af9cf5 | ||
|
|
e30adc051f | ||
|
|
e84273f392 | ||
|
|
1ec15b9458 | ||
|
|
d62b19048a | ||
|
|
5da915dcfd | ||
|
|
f6dff3608d | ||
|
|
99b3d9206d | ||
|
|
4e7c01765f | ||
|
|
49ade5ed71 | ||
|
|
b42abc9ce0 | ||
|
|
f2e6ac45ca | ||
|
|
ee696945de | ||
|
|
77ed1394b6 | ||
|
|
aa92d9c1f8 | ||
|
|
fc0b625da1 | ||
|
|
16cd2019b1 | ||
|
|
e60671d5bf | ||
|
|
811ec06cfd | ||
|
|
07a06d83a4 | ||
|
|
8f537c4378 | ||
|
|
7b0c1cb275 | ||
|
|
0c8f0e8bdb | ||
|
|
72437b1dba | ||
|
|
67584e21c8 | ||
|
|
5600956db8 | ||
|
|
f16f81db05 | ||
|
|
6f49ab2dfa | ||
|
|
a1bdc4836a | ||
|
|
8da2550874 | ||
|
|
cabcfd8921 | ||
|
|
41bf6b42fd | ||
|
|
04e4a54ae8 | ||
|
|
8ac8621f40 | ||
|
|
064520786e | ||
|
|
f06a4016be | ||
|
|
391d8b0994 | ||
|
|
961cd50bba | ||
|
|
1541e97afe | ||
|
|
f406fe76a8 | ||
|
|
60ffafcc39 | ||
|
|
a2b177fcbb | ||
|
|
f49370c82f | ||
|
|
d95ad5b4d8 | ||
|
|
943e527d0a | ||
|
|
4794638c99 | ||
|
|
d0ff6c46f8 | ||
|
|
f2b293b8c4 | ||
|
|
b50f649446 | ||
|
|
f00e5c6d8d | ||
|
|
f77779b4fc | ||
|
|
4c2377ddd9 | ||
|
|
b9c919ca3e | ||
|
|
720272254b | ||
|
|
a51556ff3e | ||
|
|
19631cb588 | ||
|
|
03f39d5a1e | ||
|
|
9a4c8f8c9c | ||
|
|
1e854ea773 | ||
|
|
04a954ae16 | ||
|
|
6f78afbe00 | ||
|
|
c70e1d1674 | ||
|
|
836916dab4 | ||
|
|
a78f58b4e4 | ||
|
|
19a4e8fe6d | ||
|
|
e0f02b46f1 | ||
|
|
1bd1a35a9a | ||
|
|
721bd0aa59 | ||
|
|
40c5fa88a4 | ||
|
|
a833f4699a | ||
|
|
7d37750831 | ||
|
|
c842090c76 | ||
|
|
4e87243686 | ||
|
|
4b8de0713e | ||
|
|
8f21e3659b | ||
|
|
ff4ec53348 | ||
|
|
6a34f551ec | ||
|
|
35d9febc6e | ||
|
|
764cfe8f8e | ||
|
|
5fdc070109 | ||
|
|
2f67f66577 | ||
|
|
bcd06b8582 | ||
|
|
7348cba9c7 | ||
|
|
4daf98741a | ||
|
|
7d7090ef8f | ||
|
|
aa6883aba6 | ||
|
|
93a1922549 | ||
|
|
c5ca63efc9 | ||
|
|
5679500b31 | ||
|
|
3bad83e0f2 | ||
|
|
6a260b78fe | ||
|
|
6543de5620 | ||
|
|
f16cd5f39c | ||
|
|
0602837f4e | ||
|
|
5f6431a75a | ||
|
|
04ebc9b7db | ||
|
|
f5dd769dcc | ||
|
|
a2be145193 | ||
|
|
019310244e | ||
|
|
6b76015469 | ||
|
|
14c769230b | ||
|
|
37a3c098bf | ||
|
|
d3a76999d0 | ||
|
|
3a31b6ff2d | ||
|
|
16773c3d7c | ||
|
|
421ceff171 | ||
|
|
dd88d578fd | ||
|
|
8fc8505607 | ||
|
|
06e4ba227d | ||
|
|
253e6537df | ||
|
|
4f493d1126 | ||
|
|
56c27b5a14 | ||
|
|
d10c2c7ee7 | ||
|
|
0361052ae1 | ||
|
|
25f3403b21 | ||
|
|
c88ab78d47 | ||
|
|
66371e182a | ||
|
|
25d9051633 | ||
|
|
a99cc6b16d | ||
|
|
e04ba4a11f | ||
|
|
fc91dd1035 | ||
|
|
e86bb70642 | ||
|
|
050d6c7d34 | ||
|
|
b67fced7ae | ||
|
|
1480688582 | ||
|
|
3103fd6292 | ||
|
|
5b819fc101 | ||
|
|
81fd292e40 | ||
|
|
ac0eaaf1f2 | ||
|
|
e40361f803 | ||
|
|
22dc4f71fe | ||
|
|
561ab01345 | ||
|
|
e3ebb69fd1 | ||
|
|
f3c46f8f20 | ||
|
|
9614adc056 | ||
|
|
746efc536a | ||
|
|
bef3341975 | ||
|
|
102ff2d56e | ||
|
|
b74c9906d2 | ||
|
|
085ad00ee0 | ||
|
|
5f07eec58a | ||
|
|
6d19c704b7 | ||
|
|
d4e44d7c31 | ||
|
|
63ad336bbf | ||
|
|
1632d52795 | ||
|
|
a90915e4e9 | ||
|
|
76d34be89b | ||
|
|
98047ff61d | ||
|
|
60ef1dc9d1 | ||
|
|
9519f6c5f4 | ||
|
|
5d4d2fdfd4 | ||
|
|
538e160956 | ||
|
|
388e8bd9a8 | ||
|
|
b42b25b521 | ||
|
|
49b0098c4a | ||
|
|
ae1e51c857 | ||
|
|
022cf309e4 | ||
|
|
1824c2f630 | ||
|
|
0f03a734b1 | ||
|
|
8b331ab17d | ||
|
|
3ac4417753 | ||
|
|
830943cd0d | ||
|
|
464c3dca3c | ||
|
|
d996db1ae9 | ||
|
|
14fa6770e4 | ||
|
|
ba8b18ca83 | ||
|
|
d1ec6c80d1 | ||
|
|
99929b21e4 | ||
|
|
601e4bb78a | ||
|
|
8084c8d9d7 | ||
|
|
ffe23eb007 | ||
|
|
8e3af106db | ||
|
|
27dda09b0f | ||
|
|
ad21be9cc7 | ||
|
|
da627fc643 | ||
|
|
ed63297dfd | ||
|
|
6319baba24 | ||
|
|
66e69e0143 | ||
|
|
7fa558c71e | ||
|
|
f64c91537a | ||
|
|
fcc3a3ac32 | ||
|
|
7085e27835 | ||
|
|
866ae3cd53 | ||
|
|
39e8d87476 | ||
|
|
239d0bf4f7 | ||
|
|
9f13284f02 | ||
|
|
f51d313a94 | ||
|
|
529fcab374 | ||
|
|
37930961e1 | ||
|
|
aad6fbb85e | ||
|
|
1cb8d00523 | ||
|
|
bf6bc6d4fd | ||
|
|
5c4fa40a8f | ||
|
|
60718ec80b | ||
|
|
20e887d708 | ||
|
|
fa4b3f8416 | ||
|
|
e979e32374 | ||
|
|
0bd1861df8 | ||
|
|
7950e4216e | ||
|
|
a07997b961 | ||
|
|
0d7115e65c | ||
|
|
6aeb93a629 | ||
|
|
87f2acf15d | ||
|
|
61ef3c1c7c | ||
|
|
81c127758b | ||
|
|
d86ce557ef | ||
|
|
8a52a7cf10 | ||
|
|
4c6693f39d | ||
|
|
f52192183c | ||
|
|
98563fdb73 | ||
|
|
f07adb44c0 | ||
|
|
5473ad640b | ||
|
|
9a6618e8d8 | ||
|
|
3442368b28 | ||
|
|
460e8fc8b7 | ||
|
|
477f581889 | ||
|
|
9e9f3ace21 | ||
|
|
eb805b409f | ||
|
|
fd781b3174 | ||
|
|
0a3502b592 | ||
|
|
a5b640cb40 | ||
|
|
8b1077669e | ||
|
|
2cde73fddb | ||
|
|
dde23d5d0f | ||
|
|
a0ebefc915 | ||
|
|
0bf1d48e40 | ||
|
|
6755f0b642 | ||
|
|
d69e96de11 | ||
|
|
3480297607 | ||
|
|
c9287324ea | ||
|
|
3315ea79b9 | ||
|
|
fda760f7bd | ||
|
|
dffade452c | ||
|
|
09bd4cfb95 | ||
|
|
26ed14a7e4 | ||
|
|
9d899a2075 | ||
|
|
97b45d5d6d | ||
|
|
ff971379f4 | ||
|
|
69f9c479e7 | ||
|
|
26ea6ea391 | ||
|
|
971091a17c | ||
|
|
1b420b7696 | ||
|
|
6b2ff5db90 | ||
|
|
e6732b52d8 | ||
|
|
f76171a643 | ||
|
|
6e9eaaf217 | ||
|
|
47334c3193 | ||
|
|
8a2b540f0a | ||
|
|
71fcf66d1e | ||
|
|
8253780716 | ||
|
|
d39d277ada | ||
|
|
b353b1d6fb | ||
|
|
88ea13f07e | ||
|
|
3b12e18473 | ||
|
|
4e153882d7 | ||
|
|
ccb3b5d1d4 | ||
|
|
6f07e6cc4f | ||
|
|
5cd67220f4 | ||
|
|
1dfc0af171 | ||
|
|
129fd190a9 | ||
|
|
f448fd7703 | ||
|
|
079b24c53c | ||
|
|
436353205a | ||
|
|
8b7e1054fe | ||
|
|
e65f1c2a95 | ||
|
|
ab7ae00513 | ||
|
|
86c7ad9217 | ||
|
|
f2c72aca7b | ||
|
|
766acde0dc | ||
|
|
081aa86b0d | ||
|
|
82453465f0 | ||
|
|
d0ec4b9e94 | ||
|
|
f3c9715947 | ||
|
|
97e1ede292 | ||
|
|
95cf08ee92 | ||
|
|
957eed7682 | ||
|
|
ce7a1e4768 | ||
|
|
d9cb23cc90 | ||
|
|
ce49016c96 | ||
|
|
0462b845e2 | ||
|
|
99d6c05f13 | ||
|
|
6dde38ed52 | ||
|
|
13a0bec612 | ||
|
|
195a36afac | ||
|
|
ef753b53bd | ||
|
|
0e411496e1 | ||
|
|
4f37e6b4b0 | ||
|
|
e415ff3f87 | ||
|
|
82883698cc | ||
|
|
b870642ee9 | ||
|
|
f4a1a05205 | ||
|
|
149168f4a5 | ||
|
|
6b6ecee06d | ||
|
|
51c390db61 | ||
|
|
7564500552 | ||
|
|
f08acd7b45 | ||
|
|
52594b6b12 | ||
|
|
c2b31d45df | ||
|
|
d0cec3dd99 | ||
|
|
0a87b55fe8 | ||
|
|
c65f1a04ab | ||
|
|
c3c496512f | ||
|
|
6e2aa7c62a | ||
|
|
3c6e6c9c96 | ||
|
|
d8a7545a82 | ||
|
|
a9a91571a1 | ||
|
|
73e21b0ccc | ||
|
|
d07c47bac8 | ||
|
|
a384e30271 | ||
|
|
11258c02cb | ||
|
|
8712d1d7f1 | ||
|
|
6e825f933d | ||
|
|
c57bfc55cf | ||
|
|
6afb367b96 | ||
|
|
4f0d1b8428 | ||
|
|
033d64ba42 | ||
|
|
3a362c7839 | ||
|
|
e0b57f1fae | ||
|
|
50087d3467 | ||
|
|
d5a51058cc | ||
|
|
2d108b8826 | ||
|
|
5c9027a293 | ||
|
|
57fcfceddf | ||
|
|
65f426169d | ||
|
|
11a1ecabdb | ||
|
|
e6f1ea2782 | ||
|
|
6f312133ac | ||
|
|
5d350297b6 | ||
|
|
8efba1c127 | ||
|
|
5a7a8666a1 | ||
|
|
f49ff59c3f | ||
|
|
a5f0c99bb3 | ||
|
|
654ff10f8e | ||
|
|
86ec024624 | ||
|
|
9f136f57fe | ||
|
|
716a669818 | ||
|
|
9d880dd2b2 | ||
|
|
50a1d758d5 | ||
|
|
bbb33e5c41 | ||
|
|
80af1153bc | ||
|
|
5196d60538 | ||
|
|
adae4181f0 | ||
|
|
2fc8abd8ae | ||
|
|
11891d28da | ||
|
|
9080884688 | ||
|
|
f99dcb7586 | ||
|
|
b774d41660 | ||
|
|
531554d835 | ||
|
|
bafebbd909 | ||
|
|
c4c9401efd | ||
|
|
2c0f42361e | ||
|
|
5cc0413c54 | ||
|
|
a657d3a7fa | ||
|
|
4df19fa1c2 | ||
|
|
8703628608 | ||
|
|
f6c059d451 | ||
|
|
0d695659ca | ||
|
|
eb7f5e8d0b | ||
|
|
f358db3d43 | ||
|
|
307566933f | ||
|
|
e355c40279 | ||
|
|
ae95c5d7e1 | ||
|
|
9b8ee1f3e4 | ||
|
|
8b3f4e3022 | ||
|
|
1a5aa9c836 | ||
|
|
829a14ed07 | ||
|
|
6596f8496e | ||
|
|
8223580a4a | ||
|
|
6d7b939467 | ||
|
|
ff5409507c | ||
|
|
a0acccffa5 | ||
|
|
654f3909e2 | ||
|
|
f34930313c | ||
|
|
6074f3441a | ||
|
|
1aa875b656 | ||
|
|
cdf79750c0 | ||
|
|
1e9beaa1d2 | ||
|
|
a953eb06c3 | ||
|
|
1153f74259 | ||
|
|
eeb34ffd63 | ||
|
|
5238d544e9 | ||
|
|
36093d24f7 | ||
|
|
76b6344760 | ||
|
|
dd1cd37f11 | ||
|
|
cd17218e59 | ||
|
|
32a267db40 | ||
|
|
4f007c8192 | ||
|
|
6eb0ec533e | ||
|
|
0577cdd35f | ||
|
|
23d05a2ebb | ||
|
|
3f5035dce4 | ||
|
|
bd18858411 | ||
|
|
5589a1e387 | ||
|
|
075a8ad21c | ||
|
|
91e8442629 | ||
|
|
dc648f7334 | ||
|
|
1c30af0622 | ||
|
|
3db82d8597 | ||
|
|
9ecdab9452 | ||
|
|
a6b0f6074f | ||
|
|
3677a861c8 | ||
|
|
0be59a11de | ||
|
|
63b6795055 | ||
|
|
ddf5da66f7 | ||
|
|
be8e1d2381 | ||
|
|
4dd4428204 | ||
|
|
c8f5c38f66 | ||
|
|
11fae70fca | ||
|
|
324f7d150f | ||
|
|
4817bc599d | ||
|
|
de905a632a | ||
|
|
b134548d79 | ||
|
|
4c5fbc1583 | ||
|
|
0a4dd9a6b3 | ||
|
|
c3f1c4da4f | ||
|
|
088da8a0ab | ||
|
|
5f04f09e5a | ||
|
|
2c85f4862c | ||
|
|
7f88c9549f | ||
|
|
5af1098063 | ||
|
|
d7fdaa1f37 | ||
|
|
e380aa7452 | ||
|
|
25041974ef | ||
|
|
a9c7f50a09 | ||
|
|
22b0f5d306 | ||
|
|
60cd1fa57d | ||
|
|
11486c084a | ||
|
|
9d8d86e19d | ||
|
|
da1d0363ca | ||
|
|
38598f57b4 | ||
|
|
ee568be647 | ||
|
|
904beec507 | ||
|
|
7070dafdbf | ||
|
|
17fee8dc68 | ||
|
|
7dfba67f7d | ||
|
|
494d253efe | ||
|
|
937740bd89 | ||
|
|
b6486df40e | ||
|
|
dcfabce0e4 | ||
|
|
86e17a7487 | ||
|
|
3c7779c766 | ||
|
|
990bba90a7 | ||
|
|
1d731c6d2a | ||
|
|
ad1858bebc | ||
|
|
f50c27c355 | ||
|
|
9a7a5d5623 | ||
|
|
f62a613d24 | ||
|
|
aaa057778c | ||
|
|
1432749293 | ||
|
|
91f84f9098 | ||
|
|
709689f76e | ||
|
|
5b11473088 | ||
|
|
38717a75c6 | ||
|
|
79760d4802 | ||
|
|
85eb4c9afb | ||
|
|
676116f2e2 | ||
|
|
37184c4244 | ||
|
|
4bcf6f7806 | ||
|
|
b62623fdaa | ||
|
|
4f64fe03f0 | ||
|
|
24f9f8586b | ||
|
|
7276c684c4 | ||
|
|
c59c42e166 | ||
|
|
3916b7e41b | ||
|
|
0313d0b9c5 | ||
|
|
9985055fd7 | ||
|
|
2c79cc2fc6 | ||
|
|
99c29d7053 | ||
|
|
1ea58b4517 | ||
|
|
a803ef7af0 | ||
|
|
d7e09f233f | ||
|
|
b06daf5859 | ||
|
|
97671a2b05 | ||
|
|
e2d42d2551 | ||
|
|
16c5ee5d56 | ||
|
|
58d1d59cab | ||
|
|
3cfa36143e | ||
|
|
771f699cdd | ||
|
|
be9d72b11d | ||
|
|
e24821e1cf | ||
|
|
eb397f08df | ||
|
|
8079f53c01 | ||
|
|
e67bc60c40 | ||
|
|
9f210028d1 | ||
|
|
5df2640539 | ||
|
|
5bf8872b42 | ||
|
|
312122c113 | ||
|
|
4c531ca8c0 | ||
|
|
c18fd5cd8c | ||
|
|
206f712599 | ||
|
|
edbc500b77 | ||
|
|
80f67ad1fa | ||
|
|
45895f6fa7 | ||
|
|
87231c34a1 | ||
|
|
3c8dfe099d | ||
|
|
b4f7592ebb | ||
|
|
fb4106f357 | ||
|
|
47edc64ecd | ||
|
|
fe7c0b0cce | ||
|
|
d36d51f732 | ||
|
|
a913a5ce23 | ||
|
|
c13d601fb4 | ||
|
|
0111a38e4b | ||
|
|
f6f9cac028 | ||
|
|
f64717b556 | ||
|
|
ea346597bb | ||
|
|
b8e8cdc968 | ||
|
|
c65d75dac5 | ||
|
|
349a64ef8f | ||
|
|
91ee5d5ddd | ||
|
|
25f2cb8ec9 | ||
|
|
bebab80538 | ||
|
|
089e021868 | ||
|
|
64cf50c8e1 | ||
|
|
608eec66d6 | ||
|
|
d39c932f20 | ||
|
|
f268ea2b3c | ||
|
|
f1a18b8066 | ||
|
|
6b72557890 | ||
|
|
1bd88c387e | ||
|
|
8b19bdba36 | ||
|
|
9403a6e027 | ||
|
|
6797e6334f | ||
|
|
054317fb13 | ||
|
|
18cf6ee46a | ||
|
|
65e52f3ba9 | ||
|
|
750e8abd46 | ||
|
|
386f0e70b3 | ||
|
|
7d841b1885 | ||
|
|
232e7869e0 | ||
|
|
f8b140faa4 | ||
|
|
8f8d190b46 | ||
|
|
83878abdc7 | ||
|
|
52ef5c7d30 | ||
|
|
3c91556d2d | ||
|
|
3abe796aa8 | ||
|
|
253377c208 | ||
|
|
ca2f18839d | ||
|
|
bcc5eb829d | ||
|
|
4cac951c1c | ||
|
|
de87676975 | ||
|
|
cb8ba75284 | ||
|
|
220e24584a | ||
|
|
b83175862e | ||
|
|
3e44b65090 | ||
|
|
3ddc33f674 | ||
|
|
436a8474b0 | ||
|
|
f3e538205b | ||
|
|
6bf31cae9e | ||
|
|
19c1ac82a4 | ||
|
|
d8cea2c8d4 | ||
|
|
9f4ad3363d | ||
|
|
5769e90427 | ||
|
|
4803ab0bb2 | ||
|
|
8db7830293 | ||
|
|
8ed59c10e4 | ||
|
|
061caa34c1 | ||
|
|
d6715842fb | ||
|
|
7ec4d28296 | ||
|
|
dfe71e885e | ||
|
|
2f39b2c5ab | ||
|
|
34adab5d08 | ||
|
|
1f784b32d8 | ||
|
|
6a0fdb312f | ||
|
|
442f3b15a1 | ||
|
|
d69b5c74e5 | ||
|
|
32741dc1c6 | ||
|
|
9a56a10379 | ||
|
|
170c422a5e | ||
|
|
bd87915222 | ||
|
|
4358089aa7 | ||
|
|
eb19519c86 | ||
|
|
f764db2e5b | ||
|
|
5a80cd988f | ||
|
|
d50d485c49 | ||
|
|
369b421b78 | ||
|
|
b898cdcefb | ||
|
|
3e03366140 | ||
|
|
21332e531e | ||
|
|
85091ab68d | ||
|
|
d66913bea2 | ||
|
|
da4cf4e3e1 | ||
|
|
efe35e705f | ||
|
|
e3ddd96fec | ||
|
|
eea9249eda | ||
|
|
2f5da9a173 | ||
|
|
b68ffcd38d | ||
|
|
b7c4aa541a | ||
|
|
52e26805e7 | ||
|
|
54e74ff81b | ||
|
|
767f019264 | ||
|
|
4e6d610317 | ||
|
|
e49ea06442 | ||
|
|
5285af5631 | ||
|
|
c4be3dfb53 | ||
|
|
ede1fcba53 | ||
|
|
11ea6fe59f | ||
|
|
ffebf1f71b | ||
|
|
0e9d920a60 | ||
|
|
a752aeb4e8 | ||
|
|
f80df76143 | ||
|
|
b6ea1bcb29 | ||
|
|
0c61fc56be | ||
|
|
df909bed06 | ||
|
|
121a4d8c71 | ||
|
|
02998cb285 | ||
|
|
01c96e65f6 | ||
|
|
e74c288783 | ||
|
|
222b5695e0 | ||
|
|
2f7e984a31 | ||
|
|
33263739ca | ||
|
|
e4c22cea6b | ||
|
|
3b72686994 | ||
|
|
ddaf30b7bd | ||
|
|
7a8e125ff5 | ||
|
|
81d1a11ed6 | ||
|
|
9a80a7bc2c | ||
|
|
fb6f36387f | ||
|
|
3ba6894cd5 | ||
|
|
9e12e429f6 | ||
|
|
ac4ac37df1 | ||
|
|
10542f6145 | ||
|
|
e0f057820a | ||
|
|
80fe4e16b2 | ||
|
|
a64d79c196 | ||
|
|
b71be71262 | ||
|
|
86511f89fb | ||
|
|
fb12b92a43 | ||
|
|
bef7d9da16 | ||
|
|
0aae19259a | ||
|
|
0c082e7e62 | ||
|
|
20c26996ef | ||
|
|
79392ea53b | ||
|
|
f3efc756ad | ||
|
|
4d102efb7a | ||
|
|
439002c898 | ||
|
|
d617e890a6 | ||
|
|
4ec448cc76 | ||
|
|
5736270107 | ||
|
|
bd325f5219 | ||
|
|
ddaa0cc0dd | ||
|
|
d64c3d63fd | ||
|
|
aa0608cb34 | ||
|
|
706bf6d427 | ||
|
|
8c6c774ab6 | ||
|
|
e18a747172 | ||
|
|
f70c5e190b | ||
|
|
b6ae77bcdf | ||
|
|
304bc75cf1 | ||
|
|
178842ec27 | ||
|
|
93f5cbacf0 | ||
|
|
e5e64bfd41 | ||
|
|
7584fac64b | ||
|
|
0db4cee117 | ||
|
|
01251090f0 | ||
|
|
cf5b8dba96 | ||
|
|
fb16b5cb0a | ||
|
|
59a0f860bd | ||
|
|
adc9c81692 | ||
|
|
370e887fbf | ||
|
|
c0b1e88e8a | ||
|
|
2b8338cb52 | ||
|
|
005e436b57 | ||
|
|
0e6762dd5f | ||
|
|
6cbf69981d | ||
|
|
43cf15e339 | ||
|
|
ab206439d8 | ||
|
|
512a5a47c0 | ||
|
|
eaba80834c | ||
|
|
a02f56d8bc | ||
|
|
e26bd40d89 | ||
|
|
8726967435 | ||
|
|
4f299de252 | ||
|
|
236c05fc59 | ||
|
|
1bac31d6bd | ||
|
|
bccc1171f0 | ||
|
|
8ad230082e | ||
|
|
8a0ade1fd8 | ||
|
|
723d6b5be8 | ||
|
|
b972421945 | ||
|
|
50307c4e80 | ||
|
|
7a2d5cbb3e | ||
|
|
325602ff2b | ||
|
|
090f7d278b | ||
|
|
d6a2290eb2 | ||
|
|
740fabf66f | ||
|
|
420737f3ea | ||
|
|
a273ffa005 | ||
|
|
c9004afb94 | ||
|
|
68668b602d | ||
|
|
583ff43d60 | ||
|
|
b364c1b953 | ||
|
|
a198e5af5a | ||
|
|
115e45c7b0 | ||
|
|
860d7948ba | ||
|
|
37efff4481 | ||
|
|
fbe952ccb7 | ||
|
|
6107dfe927 | ||
|
|
fdbb400a0b | ||
|
|
f09bd8a677 | ||
|
|
23f14f839f | ||
|
|
4e8d2f60b1 | ||
|
|
ce89d985f2 | ||
|
|
db402ee5d6 | ||
|
|
23472dd2c0 | ||
|
|
0582912c5d | ||
|
|
30973879c1 | ||
|
|
050416ed29 | ||
|
|
c0ff0e340b | ||
|
|
6cb7849dcb | ||
|
|
5c33b52ced | ||
|
|
9f3372e3e3 | ||
|
|
2d76529279 | ||
|
|
c01873574a | ||
|
|
7b03b102c9 | ||
|
|
df349078da | ||
|
|
9950df1b49 | ||
|
|
59e98b5540 | ||
|
|
ed447c9cfe | ||
|
|
367fd1d3cf | ||
|
|
9d379a36d0 | ||
|
|
fc0f505c5f | ||
|
|
af9903eb05 | ||
|
|
04be319867 | ||
|
|
5b55f3600b | ||
|
|
586c677bc2 | ||
|
|
db99849187 | ||
|
|
ed233f7e82 | ||
|
|
f4d629f4ca | ||
|
|
4e329973eb | ||
|
|
8791d21995 | ||
|
|
a67bb4c8fc | ||
|
|
e596f53c9e | ||
|
|
2f1e6379b3 | ||
|
|
8adbac17df | ||
|
|
8b81d9e384 | ||
|
|
dc21f68a95 | ||
|
|
2cd9d4c676 | ||
|
|
a6f2f031b3 | ||
|
|
89de7daba9 | ||
|
|
43866b0ef2 | ||
|
|
70b3b8730e | ||
|
|
2df83a9298 | ||
|
|
9d9ec72719 | ||
|
|
41e7cc8154 | ||
|
|
9644f1dcfe | ||
|
|
5d5c4c97c7 | ||
|
|
fa46a46ec1 | ||
|
|
c055fcc9a7 | ||
|
|
e92b07d372 | ||
|
|
4fcf27b681 | ||
|
|
5a1d81ac57 | ||
|
|
d08dd1e1d8 | ||
|
|
91bfc89301 | ||
|
|
840a2ba5b4 | ||
|
|
2353f5925c | ||
|
|
39f884aaff | ||
|
|
ed76520002 | ||
|
|
102c76a9c8 | ||
|
|
dd0c01fc2f | ||
|
|
e65df4cc67 | ||
|
|
77284bfaa6 | ||
|
|
17e476378a | ||
|
|
f3cbf61cbf | ||
|
|
ebd2196ab7 | ||
|
|
9ebf63696a | ||
|
|
ec9ce8db9d | ||
|
|
9c83ec2f25 | ||
|
|
db988c5b3a | ||
|
|
793182ea7d | ||
|
|
b051cccb89 | ||
|
|
d5b50fc83d | ||
|
|
6ac98c6724 | ||
|
|
58a530eba8 | ||
|
|
041147243c | ||
|
|
c8889e6563 | ||
|
|
3dce570998 | ||
|
|
813f0b9653 | ||
|
|
d83eec795f | ||
|
|
3e7675e728 | ||
|
|
a1779650de | ||
|
|
3c98814bb5 | ||
|
|
53d655cf0a | ||
|
|
364e179b78 | ||
|
|
9d0a1ce4a8 | ||
|
|
9272e1f68a | ||
|
|
334fcaa369 | ||
|
|
503be4c93a | ||
|
|
ee8cbfa872 | ||
|
|
85d809903b | ||
|
|
28e5165284 | ||
|
|
d07421064b | ||
|
|
38b7f7b4a4 | ||
|
|
9f9fcca6c0 | ||
|
|
f03896d1fc | ||
|
|
5477aca22d | ||
|
|
376bc46af5 | ||
|
|
c4ebf00d48 | ||
|
|
5c1bad1114 | ||
|
|
ee296ae8a9 | ||
|
|
9b89127c75 | ||
|
|
252bf2d652 | ||
|
|
507ceb1a29 | ||
|
|
ab0c02acfb | ||
|
|
27a551a0eb | ||
|
|
1eecc81838 | ||
|
|
0dc3f6ee76 | ||
|
|
361109c377 | ||
|
|
68f6db3104 | ||
|
|
2a7d309deb | ||
|
|
0858dad2ad | ||
|
|
2638192439 | ||
|
|
9cea81b035 | ||
|
|
9bf21dbf58 | ||
|
|
eaececc920 | ||
|
|
fb59e4a857 | ||
|
|
882eea1390 | ||
|
|
e4e9f26cf0 | ||
|
|
ea4c054123 | ||
|
|
fa60672d58 | ||
|
|
bb1f05fba7 | ||
|
|
15f3cb303f | ||
|
|
f57d2825bc | ||
|
|
131ace2d70 | ||
|
|
ed223f7f90 | ||
|
|
99f890b746 | ||
|
|
3fbdf210ce | ||
|
|
4910637da7 | ||
|
|
7bcaa0caa2 | ||
|
|
acffa5d930 | ||
|
|
5c88a00280 | ||
|
|
0f6315b6b2 | ||
|
|
6cd4f9a8d3 | ||
|
|
977fd5a157 | ||
|
|
0356b70224 | ||
|
|
b5272684ee | ||
|
|
c382394360 | ||
|
|
219541b5e0 | ||
|
|
4515e94c39 | ||
|
|
e37adfa243 | ||
|
|
01424f1f05 | ||
|
|
11aa5825fd | ||
|
|
c936fc827c | ||
|
|
060b71e52f | ||
|
|
23d7376f4d | ||
|
|
d825e581f3 | ||
|
|
251e6bc2ed | ||
|
|
81643ec9c3 | ||
|
|
15623c07d1 | ||
|
|
5af8df2b98 | ||
|
|
ef254b7819 | ||
|
|
7d26776adc | ||
|
|
7d3f5785e9 | ||
|
|
04274f46c3 | ||
|
|
e82344f7e0 | ||
|
|
3a63967554 | ||
|
|
65a7d2ac76 | ||
|
|
1febd6c72d | ||
|
|
ba736889bf | ||
|
|
eae699533a | ||
|
|
567dd8c1ea | ||
|
|
c224da2948 | ||
|
|
e6be0236e5 | ||
|
|
f3f322c990 | ||
|
|
bd8ec48b6a | ||
|
|
31d5fab9cd | ||
|
|
2bdce17b5a | ||
|
|
e70d3db697 | ||
|
|
5f54bf2230 | ||
|
|
4bb4df2e94 | ||
|
|
af65be5a59 | ||
|
|
6f76e2b705 | ||
|
|
ea03a11e25 | ||
|
|
8b308bdb50 | ||
|
|
49a7a4809a | ||
|
|
ee79fe4036 | ||
|
|
b33a3aa3e2 | ||
|
|
fa2381c19c | ||
|
|
0e57cede55 | ||
|
|
f9417375dc | ||
|
|
087eb40b76 | ||
|
|
82d52ffe35 | ||
|
|
00bcbaaa05 | ||
|
|
fa0f44a347 | ||
|
|
45a92ba5c2 | ||
|
|
7e83b3a4b1 | ||
|
|
6ce084b7e2 | ||
|
|
fbbac7cd26 | ||
|
|
a48f36c3c5 | ||
|
|
cccca96058 | ||
|
|
852d05d94a | ||
|
|
cd6ad266b5 | ||
|
|
6b7677e842 | ||
|
|
b0685838db | ||
|
|
7cd4ac0ee1 | ||
|
|
6ec28c9f98 | ||
|
|
59bc293d15 | ||
|
|
f01e832eef | ||
|
|
4d2537ae11 | ||
|
|
e8bd5968ff | ||
|
|
0fddec0421 | ||
|
|
824763970b | ||
|
|
358238b170 | ||
|
|
0575c11d72 | ||
|
|
2fcda7000b | ||
|
|
582b0b0711 | ||
|
|
44b95a88d6 | ||
|
|
a0f2a2e7c4 | ||
|
|
ba9b384f58 | ||
|
|
6f118fe66a | ||
|
|
7d6ba573e5 | ||
|
|
9bd5c1d95b | ||
|
|
aba598c26f | ||
|
|
2be3c7ab57 | ||
|
|
b9bda6aa41 | ||
|
|
523911c9b0 | ||
|
|
135f392c62 | ||
|
|
54da34ff0a | ||
|
|
1518301885 | ||
|
|
38c513fd02 | ||
|
|
50b9f0e970 | ||
|
|
09ed70fcaf | ||
|
|
f0c47a88ba | ||
|
|
a813234dcd | ||
|
|
ba04eb12ef | ||
|
|
deb3c32a49 | ||
|
|
98a973007d | ||
|
|
cd9a1226b5 | ||
|
|
7b576dd5cf | ||
|
|
f2c734ba04 | ||
|
|
931e1debff | ||
|
|
9a7b3b0347 | ||
|
|
fe6517959e | ||
|
|
f0df8b7172 | ||
|
|
abec217a1b | ||
|
|
405000c897 | ||
|
|
dfd4f13f55 | ||
|
|
8c087b7d73 | ||
|
|
f07020fa1c | ||
|
|
6cd346ebe1 | ||
|
|
ce6a7846c0 | ||
|
|
b1826af735 | ||
|
|
7d4b53c57a | ||
|
|
fc619c1402 | ||
|
|
0a93667e9c | ||
|
|
82f888f457 | ||
|
|
4319ece167 | ||
|
|
9b1eb11a3a | ||
|
|
8634ef9e4a | ||
|
|
bef7a3ea37 | ||
|
|
ae90c1a014 | ||
|
|
57e4310265 | ||
|
|
bced63033d | ||
|
|
8cd6529426 | ||
|
|
1ebd942a88 | ||
|
|
45f7567d70 | ||
|
|
b2c3f0464f | ||
|
|
c295b46e4b | ||
|
|
cabd5e105a | ||
|
|
da9a73f4c9 | ||
|
|
7e058413fb | ||
|
|
1230770bb6 | ||
|
|
55a6d4c1b5 | ||
|
|
b99c287ef6 | ||
|
|
ac639e80c3 | ||
|
|
7acd3abe33 | ||
|
|
a9831e75ee | ||
|
|
5c735f4c68 | ||
|
|
22ef00edde | ||
|
|
14fba8d8be | ||
|
|
0fe9884e0b | ||
|
|
fefe2e8b4f | ||
|
|
cd932e2234 | ||
|
|
a1d24f740f | ||
|
|
2d643dbc42 | ||
|
|
57b1bfcc73 | ||
|
|
2a4265b406 | ||
|
|
aaee30edcc | ||
|
|
7bedf24c8c | ||
|
|
f9876ccfa8 | ||
|
|
fd4dbd6c5c | ||
|
|
d22b95c454 | ||
|
|
199add9567 | ||
|
|
e1dec7cda6 | ||
|
|
c2ef8373c7 | ||
|
|
06de953fbc | ||
|
|
5a6d5c1751 | ||
|
|
0687688042 | ||
|
|
e1d1a962c7 | ||
|
|
a729a57ba1 | ||
|
|
1f9ab2380a | ||
|
|
35f2e4b8ae | ||
|
|
f6ddf9b971 | ||
|
|
6d05d785be | ||
|
|
e1e893d3b9 | ||
|
|
f933db8c24 | ||
|
|
e3db569d62 | ||
|
|
3afbc3287f | ||
|
|
58172f4ff0 | ||
|
|
d3213d7f47 | ||
|
|
4c228c3f7a | ||
|
|
eea0213fe4 | ||
|
|
a3168fdc23 | ||
|
|
fdff1f69b5 | ||
|
|
b49f1a7dfa | ||
|
|
4b7e548d92 | ||
|
|
b5c7781d9f | ||
|
|
7bffc0459c | ||
|
|
8d1744dd29 | ||
|
|
42da18ec5f | ||
|
|
b90f35b24f | ||
|
|
559423d973 | ||
|
|
55eee86242 | ||
|
|
30de08c187 | ||
|
|
b32b3c1e50 | ||
|
|
b052fe894b | ||
|
|
18e2c2e468 | ||
|
|
700bf3772a | ||
|
|
f61b19eda8 | ||
|
|
b4cf0acd8e | ||
|
|
36833ce138 | ||
|
|
7b5e73c7a8 | ||
|
|
e3e62817fa | ||
|
|
71a99bab18 | ||
|
|
a915aa4b69 | ||
|
|
bb1abed78f | ||
|
|
922d62c39d | ||
|
|
16661cc58f | ||
|
|
0263e89354 | ||
|
|
700733784f | ||
|
|
a3c09af463 | ||
|
|
e87a53037e | ||
|
|
a0fdba74dc | ||
|
|
d0bca8cd77 | ||
|
|
3a57d2285a | ||
|
|
ff42a275f8 | ||
|
|
4b03dace5f | ||
|
|
b6f6544f3b | ||
|
|
0e941a8dfc | ||
|
|
110560781a | ||
|
|
d254db31c8 | ||
|
|
a7230de79a | ||
|
|
b3613d3e48 | ||
|
|
c66b66e45f | ||
|
|
3fd8f01d7c | ||
|
|
ea60d42f67 | ||
|
|
9cbc047b6a | ||
|
|
228f03ae87 | ||
|
|
307f862c23 | ||
|
|
e6628a8003 | ||
|
|
1c36c41f1e | ||
|
|
f5ac6f6c2e | ||
|
|
c7c20f8656 | ||
|
|
45c92426e3 | ||
|
|
864f6a50b8 | ||
|
|
2650a7f2ae | ||
|
|
d41e65cd0d | ||
|
|
c8f858f2aa | ||
|
|
a7e9416c89 | ||
|
|
f63923ae29 | ||
|
|
b6151c5141 | ||
|
|
5b41f40c31 | ||
|
|
8b2b938b7e | ||
|
|
f9f59ae89d | ||
|
|
6f86f6766b | ||
|
|
72ccf76581 | ||
|
|
4c736c3600 | ||
|
|
e06257cf2e | ||
|
|
0efb0da41f | ||
|
|
e7bbe31f8f | ||
|
|
bbc8c2ce6f | ||
|
|
9f5b92a27f | ||
|
|
b96ae79baa | ||
|
|
7e3e619497 | ||
|
|
be563d29a0 | ||
|
|
ee9c852b4d | ||
|
|
6ae8903fd8 | ||
|
|
b4f4e23000 | ||
|
|
7438526620 | ||
|
|
3c7c893e6e | ||
|
|
24a710bad2 | ||
|
|
d23b94c206 | ||
|
|
d2ad9e17c8 | ||
|
|
66568b0f66 | ||
|
|
71f2c0c6ec | ||
|
|
64ee493b54 | ||
|
|
4597c9a9e8 | ||
|
|
6ac2bb1e88 | ||
|
|
604ebd84aa | ||
|
|
4f0e5637a9 | ||
|
|
565398f5e8 | ||
|
|
33801137f8 | ||
|
|
3da361ee77 | ||
|
|
c4ca6bf492 | ||
|
|
c3ecb8741c | ||
|
|
2fb8143f3a | ||
|
|
0403510bbd | ||
|
|
793040a782 | ||
|
|
3cc8b20876 | ||
|
|
e07986caba | ||
|
|
3ca72cb08a | ||
|
|
b81f233e68 | ||
|
|
41c684c4a3 | ||
|
|
aef8538148 | ||
|
|
2059316463 | ||
|
|
661770497b | ||
|
|
2097977b7d | ||
|
|
93c8e08989 | ||
|
|
6e764dc097 | ||
|
|
07b9a5e800 | ||
|
|
5ed63ffc87 | ||
|
|
7d2b59410d | ||
|
|
f0380197a9 | ||
|
|
6ea8bf36f8 | ||
|
|
1e477ed10f | ||
|
|
642059b2e4 | ||
|
|
b6fd23d966 | ||
|
|
c318a06f14 | ||
|
|
3e6f5dfcae | ||
|
|
e03ed12e00 | ||
|
|
318406a0c5 | ||
|
|
13bdb56867 | ||
|
|
0beb05fac4 | ||
|
|
d4781cb4d1 | ||
|
|
c4ebbd5b2e | ||
|
|
886b082880 | ||
|
|
1c7fef7ece | ||
|
|
cb80b98c7d | ||
|
|
c02caf1e91 | ||
|
|
6afb37c9ae | ||
|
|
0cc737f9ac | ||
|
|
b8a9e7558f | ||
|
|
cadd117ed0 | ||
|
|
d3ba986fff | ||
|
|
3784f83bed | ||
|
|
f3b51061e4 | ||
|
|
c5df0c5e49 | ||
|
|
9a019128c6 | ||
|
|
6347ced74a | ||
|
|
b02fd7a66d | ||
|
|
eb91006b7c | ||
|
|
f966e5e186 | ||
|
|
bf940e8928 | ||
|
|
dc9faa21e4 | ||
|
|
5c12ec4755 | ||
|
|
200b967871 | ||
|
|
49ad55b85a | ||
|
|
74075be1c4 | ||
|
|
4fbb1a57c4 | ||
|
|
edf265741e | ||
|
|
4253cfd233 | ||
|
|
8fa566e5ed | ||
|
|
ff62953662 | ||
|
|
a0a2592025 | ||
|
|
b0b916c16c | ||
|
|
03da4fbf3b | ||
|
|
1ce96b63c0 | ||
|
|
df81f135e4 | ||
|
|
a35dab18bd | ||
|
|
32b3083ba8 | ||
|
|
fdc402153d | ||
|
|
cd0655bf89 | ||
|
|
eaa4b200d2 | ||
|
|
09d0d0181c | ||
|
|
41b5832562 | ||
|
|
c72d7a5c2c | ||
|
|
2bc067a740 | ||
|
|
e8a453e89d | ||
|
|
e6e2e59b4d | ||
|
|
c4f66c2c33 | ||
|
|
141b2b7d39 | ||
|
|
85cbfad384 | ||
|
|
6f85337227 | ||
|
|
39ca88f776 | ||
|
|
03f5290b89 | ||
|
|
78d9eee141 | ||
|
|
1398781ee7 | ||
|
|
122d0d8de6 | ||
|
|
c3b2a120d4 | ||
|
|
8aa722871d | ||
|
|
2a89687393 | ||
|
|
e7b18536c4 | ||
|
|
070f50ccc7 | ||
|
|
fee4bb4bab | ||
|
|
ba6613e769 | ||
|
|
4d48644182 | ||
|
|
e99e1fffde | ||
|
|
4264fb193d | ||
|
|
11e6204974 | ||
|
|
d8daf09817 | ||
|
|
ef6b032456 | ||
|
|
f5b6b2b953 | ||
|
|
29ce32912d | ||
|
|
f0c880d6f6 | ||
|
|
aa25b367d6 | ||
|
|
4e156d3435 | ||
|
|
730194d609 | ||
|
|
d5455abe17 | ||
|
|
ff47b7ec31 | ||
|
|
e93e62e29b | ||
|
|
6265cd3125 | ||
|
|
ea5228686c | ||
|
|
fea72cb65d | ||
|
|
6e420b3c38 | ||
|
|
4e70bbc3b2 | ||
|
|
c446ba8b76 | ||
|
|
ceadbd2d91 | ||
|
|
1507997410 | ||
|
|
ebc1c06835 | ||
|
|
00ffb24b83 | ||
|
|
b0fa3b6450 | ||
|
|
8085c618c0 | ||
|
|
c6822b3fb1 | ||
|
|
6f5e43a60f | ||
|
|
9312b0c81c | ||
|
|
e31fd63b35 | ||
|
|
51226db44f | ||
|
|
d0e9afeb2b | ||
|
|
87bbe6ee7a | ||
|
|
6d63970147 | ||
|
|
5c3c5fb65c | ||
|
|
7353c879b0 | ||
|
|
2af2747634 | ||
|
|
ef1b495d45 | ||
|
|
0d63eccb11 | ||
|
|
860eb98007 | ||
|
|
1205aaa664 | ||
|
|
a8e79d3830 | ||
|
|
f9cfe60312 | ||
|
|
4c4264a448 | ||
|
|
47979c3e73 | ||
|
|
1719cd39d3 | ||
|
|
e92efc3742 | ||
|
|
0b37575aac | ||
|
|
f146ecea99 | ||
|
|
7082d0584e | ||
|
|
6546acebfb | ||
|
|
ecec5ad9fc | ||
|
|
0b23f4a6a7 | ||
|
|
488595c759 | ||
|
|
3fa3e8539d | ||
|
|
48b6ab921b | ||
|
|
f0449777db | ||
|
|
288fc53399 | ||
|
|
72c039758c | ||
|
|
6b20a0f5db | ||
|
|
c6c9c0a3ed | ||
|
|
5e8a912baf | ||
|
|
cb9d518b3e | ||
|
|
31bc43c48b | ||
|
|
2dae49b723 | ||
|
|
4397ade80e | ||
|
|
62efe4f3b0 | ||
|
|
c44349ed1e | ||
|
|
2deba424d2 | ||
|
|
5dc4b018a4 | ||
|
|
dbd42a645f | ||
|
|
2e0cf7a00c | ||
|
|
f0c7729f81 | ||
|
|
1220a0e2fb | ||
|
|
26c7a07735 | ||
|
|
c246200ab0 | ||
|
|
a76b90bfef | ||
|
|
d18b2f29bf | ||
|
|
3334ab2653 | ||
|
|
4fabc80629 | ||
|
|
98a3c16be4 | ||
|
|
4e395aac8b | ||
|
|
e1459ede01 | ||
|
|
1a6a17aab8 | ||
|
|
1bb8d52938 | ||
|
|
77b8442606 | ||
|
|
b9027295d7 | ||
|
|
a397a88192 | ||
|
|
d42e070073 | ||
|
|
0eb1f2ec44 | ||
|
|
6f2ed85340 | ||
|
|
c6cb8f9239 | ||
|
|
badc4dec46 | ||
|
|
7f97f0a332 | ||
|
|
fe64d7eca6 | ||
|
|
2fbb559a70 | ||
|
|
bb3a461b49 | ||
|
|
18d9b26cf9 | ||
|
|
fba0b595ab | ||
|
|
c564c601bd | ||
|
|
d0d47362e3 | ||
|
|
9f553ef8ba | ||
|
|
686da4b054 | ||
|
|
50ef0504c6 | ||
|
|
418eefb9dc | ||
|
|
74a28969a4 | ||
|
|
50d09049e1 | ||
|
|
2a4ae392f0 | ||
|
|
b9a34d8634 | ||
|
|
592b27b17a | ||
|
|
f8fc683adc | ||
|
|
9f2a6c79c4 | ||
|
|
7dc293f58f | ||
|
|
0bad15d227 | ||
|
|
1ed8dd396f | ||
|
|
dc297cd02a | ||
|
|
a5a45131bb | ||
|
|
0eab1fabcf | ||
|
|
619528a3c3 | ||
|
|
f41813c782 | ||
|
|
dc0bfa2da4 | ||
|
|
9ac81e10ba | ||
|
|
45d7200427 | ||
|
|
3def26a0e4 | ||
|
|
df68d15aba | ||
|
|
34e8ed636d | ||
|
|
21e6e48a26 | ||
|
|
b216988746 | ||
|
|
85a0e13c73 | ||
|
|
78b9e92af9 | ||
|
|
618b325d73 | ||
|
|
6a79d3a18f | ||
|
|
c021ec56e3 | ||
|
|
8295c77e9c | ||
|
|
c96810b9d3 | ||
|
|
e8b3ac0c6e | ||
|
|
94800f4521 | ||
|
|
233e26b112 | ||
|
|
3188414261 | ||
|
|
84ad9b3a8a | ||
|
|
da2ac25552 | ||
|
|
1764051747 | ||
|
|
e330970fb9 | ||
|
|
8ea159cc2e | ||
|
|
5a9f337de0 | ||
|
|
a6a4d44176 | ||
|
|
6eea9479e7 | ||
|
|
927828d4d4 | ||
|
|
fdb35c46a4 | ||
|
|
b6c4282a03 | ||
|
|
7954654d15 | ||
|
|
7279b57216 | ||
|
|
ef864a5cf2 | ||
|
|
56e13139d4 | ||
|
|
8df2830434 | ||
|
|
25a08db0c0 | ||
|
|
37fcb4fc3f | ||
|
|
fccd0750b2 | ||
|
|
d10878282b | ||
|
|
0f10f4119f | ||
|
|
ef19fe6bef | ||
|
|
6360dec439 | ||
|
|
15b6cd5dec | ||
|
|
e840a63d68 | ||
|
|
9529e3ebb0 | ||
|
|
0126706cac | ||
|
|
f8aa020b3f | ||
|
|
f320936bbb | ||
|
|
5057e4898f | ||
|
|
a06c6bf412 | ||
|
|
5348d0d581 | ||
|
|
69061dec64 | ||
|
|
f2f3825130 | ||
|
|
ce18e66db2 | ||
|
|
367da10e08 | ||
|
|
f12c0bb3aa | ||
|
|
d5f8207a21 | ||
|
|
2127cf3c7b | ||
|
|
b0863c5e31 | ||
|
|
f9222e7e4b | ||
|
|
ad3558498f | ||
|
|
73a38e14d3 | ||
|
|
cea4a8e09e | ||
|
|
90267ab0ea | ||
|
|
7f5f113968 | ||
|
|
2887217560 | ||
|
|
9a43c29ca7 | ||
|
|
1ca9fb19e5 | ||
|
|
062733f106 | ||
|
|
e83c29f281 | ||
|
|
afc33139c4 | ||
|
|
6a181832bb | ||
|
|
3af7d5a342 | ||
|
|
cecb25eae5 | ||
|
|
ddcfe8d3af | ||
|
|
dd7e4ef47a | ||
|
|
2b914b7ebf | ||
|
|
54689b2f67 | ||
|
|
d44286366b | ||
|
|
5611ff040e | ||
|
|
188fdf9260 | ||
|
|
41453ebf74 | ||
|
|
9cd9198127 | ||
|
|
dcee71987e | ||
|
|
c52f076bca | ||
|
|
5d9bbe64c8 | ||
|
|
d2c0c613c8 | ||
|
|
3ed0a01068 | ||
|
|
6386563560 | ||
|
|
a175a7c2b7 | ||
|
|
0a02a13bb2 | ||
|
|
df460963fc | ||
|
|
847164efa0 | ||
|
|
fa48657020 | ||
|
|
07af9aa8f0 | ||
|
|
6776ea7a79 | ||
|
|
ad369fa974 | ||
|
|
08d9c1a10c | ||
|
|
97f589e6af | ||
|
|
aeaa181d74 | ||
|
|
0d23fed9ab | ||
|
|
89131204fd | ||
|
|
4b485062ee | ||
|
|
53060a3a44 | ||
|
|
cba23534f1 | ||
|
|
73b299843e | ||
|
|
82a9a22e99 | ||
|
|
88a49f727b | ||
|
|
9ec6b2a358 | ||
|
|
d771932983 | ||
|
|
e414807aaf | ||
|
|
03652112b3 | ||
|
|
1204348efa | ||
|
|
6345a74c22 | ||
|
|
662356e3d8 | ||
|
|
e75a91556c | ||
|
|
403d010294 | ||
|
|
64f2fb6f2c | ||
|
|
9790f6fa7e | ||
|
|
d271dfa7af | ||
|
|
6eca96c657 | ||
|
|
a678344264 | ||
|
|
e95da4b9f7 | ||
|
|
a43b8ec753 | ||
|
|
026c03b527 | ||
|
|
f286c413c0 | ||
|
|
746dbf2c53 | ||
|
|
d9020bb6fc | ||
|
|
b4f05e2c98 | ||
|
|
67f3a558e0 | ||
|
|
ab0566923b | ||
|
|
b96ba5cae3 | ||
|
|
c48522110f | ||
|
|
d93cfc416c | ||
|
|
e89fb66d79 | ||
|
|
3f306552dd | ||
|
|
4d92934e6e | ||
|
|
a6c065816a | ||
|
|
d77b6a6c8c | ||
|
|
9ae7f2430a | ||
|
|
6ed8f15260 | ||
|
|
1be7bf0881 | ||
|
|
f8d6b80b97 | ||
|
|
08f888a148 | ||
|
|
ca0a0a0daa | ||
|
|
c1becf7fe5 | ||
|
|
9774ddb9b5 | ||
|
|
87cf6b3ec2 | ||
|
|
7cd91c85fa | ||
|
|
fda3016dc8 | ||
|
|
0463f6b649 | ||
|
|
458f165c98 | ||
|
|
2491d3b75d | ||
|
|
0b04b3dfb2 | ||
|
|
f85cf0138c | ||
|
|
fe5c5ba3f8 | ||
|
|
3f80fd6bcc | ||
|
|
8f199888d5 | ||
|
|
48dd0fef1d | ||
|
|
aeb1002057 | ||
|
|
b5ecfdc179 | ||
|
|
259484a570 | ||
|
|
ccd7a7ac54 | ||
|
|
4e158e372c | ||
|
|
c3f8e1fe08 | ||
|
|
1be3670efe | ||
|
|
b1e0f0f102 | ||
|
|
976bdba2d1 | ||
|
|
dad010329b | ||
|
|
1f7c871993 | ||
|
|
7a250ebd34 | ||
|
|
17f19d921b | ||
|
|
0444580a77 | ||
|
|
d0a80c33d7 | ||
|
|
1d5641fc9a | ||
|
|
64127abd5c | ||
|
|
a9c26705e0 | ||
|
|
690bcfada2 | ||
|
|
5f726ad8c7 | ||
|
|
a611ce04f1 | ||
|
|
248c923284 | ||
|
|
b5f5e0762e | ||
|
|
3bafe1a8a5 | ||
|
|
91805d8f8e | ||
|
|
4a072a452e | ||
|
|
17c311c9b9 | ||
|
|
28efa96e0d | ||
|
|
d52d919a29 | ||
|
|
9dfb8aac36 | ||
|
|
0fcb7c72f8 | ||
|
|
155af741e5 | ||
|
|
d95c7d63d0 | ||
|
|
e969712c6f | ||
|
|
32ba309c68 | ||
|
|
11cac381b4 | ||
|
|
0c30452423 | ||
|
|
3758d31fa1 | ||
|
|
f5458639d4 | ||
|
|
9edab98b2c | ||
|
|
66cbe07029 | ||
|
|
4bd99a2bd2 | ||
|
|
2184f91230 | ||
|
|
9fc931366e | ||
|
|
361211d401 | ||
|
|
b27daee8b0 | ||
|
|
8a1906619f | ||
|
|
e3da507a44 | ||
|
|
677eedfe6a | ||
|
|
fb69d9c88d | ||
|
|
bec6aaf064 | ||
|
|
442747adb6 | ||
|
|
f342859fac | ||
|
|
191bf77082 | ||
|
|
01a2a2a19f | ||
|
|
581ae73586 | ||
|
|
2a1dff7ba2 | ||
|
|
bd29d3ccb6 | ||
|
|
e983edd221 | ||
|
|
d4c553c202 | ||
|
|
ee456ae10d | ||
|
|
a9bbac93a2 | ||
|
|
5373fc0d2b | ||
|
|
b2c110329f | ||
|
|
8b0d0923b4 | ||
|
|
5914c791bb | ||
|
|
44fbf78d78 | ||
|
|
cd2ef5b548 | ||
|
|
7f887cca90 | ||
|
|
840f035827 | ||
|
|
441c545ccc | ||
|
|
b7178fdce9 | ||
|
|
a00fad7d48 | ||
|
|
1496da97fb | ||
|
|
261b4a85e1 | ||
|
|
cb55bf96ef | ||
|
|
93629a3a89 | ||
|
|
b6b393c1b9 | ||
|
|
0b4862c822 | ||
|
|
b0772febde | ||
|
|
fd3845293b | ||
|
|
160c04b793 | ||
|
|
df4a69f7ce | ||
|
|
488845c2c6 | ||
|
|
96503a02c1 | ||
|
|
a0e6229adb | ||
|
|
c487ca43e6 | ||
|
|
26a40258cc | ||
|
|
c732690384 | ||
|
|
e2c9887aeb | ||
|
|
122b11ec21 | ||
|
|
99e2b961c2 | ||
|
|
924bc59162 | ||
|
|
1a8a7ff064 | ||
|
|
3519110944 | ||
|
|
8eab29c445 | ||
|
|
b1953951ac | ||
|
|
185461cfb6 | ||
|
|
7e209d3edf | ||
|
|
e4f6ef985e | ||
|
|
9811d4502f | ||
|
|
278a0a0891 | ||
|
|
7c048c0b65 | ||
|
|
5bb53baa0e | ||
|
|
b730f9435c | ||
|
|
5a69a332e5 | ||
|
|
74deb4f9e0 | ||
|
|
e536f91885 | ||
|
|
b72da3343c | ||
|
|
ea8e10e8bc | ||
|
|
820d525ac6 | ||
|
|
21f63cd4db | ||
|
|
cb06d1d954 | ||
|
|
010da5943a | ||
|
|
b846c71e0a | ||
|
|
60b57a20b7 | ||
|
|
186e36c403 | ||
|
|
96271267c9 | ||
|
|
c2bee5d802 | ||
|
|
ff6c09c775 | ||
|
|
2c1f9b84ff | ||
|
|
dcd583bbde | ||
|
|
41af0f753e | ||
|
|
e4d79daa75 | ||
|
|
92eb0c2018 | ||
|
|
e7cb975021 | ||
|
|
8c85a8461c | ||
|
|
34ff765820 | ||
|
|
b629af806e | ||
|
|
9a3304c65d | ||
|
|
77dafbed41 | ||
|
|
4fc6c2eb0d | ||
|
|
847de38584 | ||
|
|
a42fe2a4ea | ||
|
|
ca4c644403 | ||
|
|
13f514e143 | ||
|
|
9aba06cfed | ||
|
|
306a8662f7 | ||
|
|
82be2f2153 | ||
|
|
18ff12ba8b | ||
|
|
06292d1cf7 | ||
|
|
b705f19938 | ||
|
|
adc9e59e0b | ||
|
|
4038178ccb | ||
|
|
88979c2a4a | ||
|
|
7af0234fa7 | ||
|
|
03458dc73a | ||
|
|
89fb8c1037 | ||
|
|
0748d47164 | ||
|
|
2d8160ecd5 | ||
|
|
96d17b07a5 | ||
|
|
87c9e1db33 | ||
|
|
17acbf1e38 | ||
|
|
e163642ed1 | ||
|
|
3a49a959ca | ||
|
|
51cab9e7cc | ||
|
|
c5aedb3086 | ||
|
|
e5ad6907c5 | ||
|
|
e83f71679f | ||
|
|
14ed4bdf02 | ||
|
|
d3418aa14a | ||
|
|
238c12b67e | ||
|
|
11e6ed5eac | ||
|
|
50b11dab9e | ||
|
|
094f2cb611 | ||
|
|
97ad147395 | ||
|
|
cd3f85188a | ||
|
|
51880b7ddc | ||
|
|
9ff8416c79 | ||
|
|
71675d14f9 | ||
|
|
8db8179f97 | ||
|
|
45b4dbf298 | ||
|
|
6463533f80 | ||
|
|
95e75f4354 | ||
|
|
2cd8a11bf2 | ||
|
|
6097648bf0 | ||
|
|
8a92b798e9 | ||
|
|
8e3722ceee | ||
|
|
15307e3978 | ||
|
|
87b40b4d14 | ||
|
|
c31621bbec | ||
|
|
fd5cf4bdec | ||
|
|
9f232928dc | ||
|
|
e5b594c0e8 | ||
|
|
3092cb538e | ||
|
|
526622d6e0 | ||
|
|
68c634721a | ||
|
|
5ad345f6b0 | ||
|
|
7568d9a4ef | ||
|
|
5db0b8e31a | ||
|
|
8ddb3aba81 | ||
|
|
d481e22f29 | ||
|
|
2da38463da | ||
|
|
127c3c93d0 | ||
|
|
88721d2e74 | ||
|
|
c9d317ba1a | ||
|
|
66049c961b | ||
|
|
edd3fe50fb | ||
|
|
0b0bac6d92 | ||
|
|
ca40ab4b67 | ||
|
|
dfceae320d | ||
|
|
2f2783f231 | ||
|
|
e7d4ae8efa | ||
|
|
7754314450 | ||
|
|
3e8bdfc9c9 | ||
|
|
ef0a57efce | ||
|
|
4430b896fa | ||
|
|
4b5e3caa7d | ||
|
|
75d674dd9b | ||
|
|
056325aca6 | ||
|
|
0c3cea35f0 | ||
|
|
7b968f6151 | ||
|
|
86dada47fc | ||
|
|
1ea2b79b37 | ||
|
|
1e127d75d2 | ||
|
|
559cae8751 | ||
|
|
7abe9e6c16 | ||
|
|
b87a692804 | ||
|
|
c7306dce2b | ||
|
|
08f3c195f7 | ||
|
|
5924e61b40 | ||
|
|
3ead7cdb6e | ||
|
|
a2e70340b8 | ||
|
|
974ecf7830 | ||
|
|
a3d8377135 | ||
|
|
71ec46b4e9 | ||
|
|
981afbee6e | ||
|
|
a66d310f8d | ||
|
|
658000cc9a | ||
|
|
9d49aa6573 | ||
|
|
1b3af96143 | ||
|
|
ce2e6b28e8 | ||
|
|
91e1317f4a | ||
|
|
2f7b2aad34 | ||
|
|
ddcac96e9b | ||
|
|
d021bc7327 | ||
|
|
cc01517489 | ||
|
|
ccead56701 | ||
|
|
9fd51d4ef6 | ||
|
|
69d5139b36 | ||
|
|
90197dbbdc | ||
|
|
5d2654205d | ||
|
|
8ec0f8abf2 | ||
|
|
c19caed171 | ||
|
|
f3e9793826 | ||
|
|
8aff4b2d95 | ||
|
|
9c35e9a7d1 | ||
|
|
176b1061eb | ||
|
|
118b47674f | ||
|
|
ed18567073 | ||
|
|
8bf932bf27 | ||
|
|
5559a4c39c | ||
|
|
6ffeccbd4c | ||
|
|
9aace6da49 | ||
|
|
f19f4411e1 | ||
|
|
6884bd9758 | ||
|
|
d3f7d3a958 | ||
|
|
59e86b63b0 | ||
|
|
526fc0afe9 | ||
|
|
0255d5805f | ||
|
|
eda2d325b7 | ||
|
|
ce87d2977f | ||
|
|
b1b8802edd | ||
|
|
886ebab04a | ||
|
|
4c1332fb76 | ||
|
|
8bb060d8ac | ||
|
|
46ffd20c48 | ||
|
|
d331358a3b | ||
|
|
907ed4d346 | ||
|
|
aa01269484 | ||
|
|
cdbb9183d6 | ||
|
|
6cd0d316e2 | ||
|
|
7488a01ade | ||
|
|
33d2d312e2 | ||
|
|
a91b07d340 | ||
|
|
83728dbd79 | ||
|
|
1866e93ff6 | ||
|
|
a479a033a1 | ||
|
|
10a6e598ac | ||
|
|
802dbe4677 | ||
|
|
a84da8a0b9 | ||
|
|
713a2eb072 | ||
|
|
f72f506f34 | ||
|
|
9dd4fbe85a | ||
|
|
13f9166f7d | ||
|
|
cecda3fb67 | ||
|
|
b9c3f3567a | ||
|
|
d61401cde2 | ||
|
|
1395d93c0e | ||
|
|
8e1a2d57a6 | ||
|
|
a2775a6109 | ||
|
|
4752c18d08 | ||
|
|
7cda0babd2 | ||
|
|
3fde2e56b8 | ||
|
|
55a24aecad | ||
|
|
49eb667a95 | ||
|
|
93bbbc0b66 | ||
|
|
822807067f | ||
|
|
07c4def47c | ||
|
|
7f05fd2620 | ||
|
|
46c3db1169 | ||
|
|
414430d775 | ||
|
|
a9ebcff694 | ||
|
|
b2981a4430 | ||
|
|
ad3c50f656 | ||
|
|
ea8882067e | ||
|
|
a5b05e975b | ||
|
|
1d200d55bd | ||
|
|
9bf92ad7e4 | ||
|
|
946e66ef0e | ||
|
|
a519477534 | ||
|
|
217bc41c7b | ||
|
|
f4d1002166 | ||
|
|
9f6e3aed8a | ||
|
|
11b29650d5 | ||
|
|
e6db9fa895 | ||
|
|
a0af83a9c4 | ||
|
|
30a4094907 | ||
|
|
82a9214dce | ||
|
|
6516708b9b | ||
|
|
8b679b004a | ||
|
|
d87c4f7008 | ||
|
|
245541a8d7 | ||
|
|
ed2d0a0eb2 | ||
|
|
0570c6305f | ||
|
|
c85b38383c | ||
|
|
f58a5942cb | ||
|
|
d6471bec31 | ||
|
|
d6a415c262 | ||
|
|
bfaa2734a6 | ||
|
|
f81cf74784 | ||
|
|
775e0953be | ||
|
|
61f25c3e92 | ||
|
|
374c9c1789 | ||
|
|
933f3a22f4 | ||
|
|
b3a0ef24ed | ||
|
|
750c73a62f | ||
|
|
c14a82f2fe | ||
|
|
a9e69f2753 | ||
|
|
05e5da6083 | ||
|
|
d999f80dbe | ||
|
|
d2f64f963d | ||
|
|
f864477ba8 | ||
|
|
ab9a5820e8 | ||
|
|
c49adea89c | ||
|
|
cadb8d010b | ||
|
|
da6073e8c6 | ||
|
|
0155dee2fd | ||
|
|
4082e265d6 | ||
|
|
f08b28975b | ||
|
|
d1956e855d | ||
|
|
6e72bad3af | ||
|
|
e58083c1f9 | ||
|
|
77b39af6bf | ||
|
|
e399238ee3 | ||
|
|
b420a63e73 | ||
|
|
76de8d70a8 | ||
|
|
467c5dbf9f | ||
|
|
dd6a232277 | ||
|
|
54b418482f | ||
|
|
5d92e20876 | ||
|
|
77617f592e | ||
|
|
706bb6f067 | ||
|
|
dc636198ec | ||
|
|
9d40b8ee80 | ||
|
|
0f205bb079 | ||
|
|
7a5dfd65ba | ||
|
|
ac4b71a0ba | ||
|
|
c9bc9e135d | ||
|
|
ff740c1bd8 | ||
|
|
7d6a43c2bb | ||
|
|
8c68897d1e | ||
|
|
0e5cec5e09 | ||
|
|
9db0fbf879 | ||
|
|
7e036135be | ||
|
|
7d4a46d9d2 | ||
|
|
1297800175 | ||
|
|
fd0b9cc522 | ||
|
|
33cf4bcb0f | ||
|
|
f88fd2f9e4 | ||
|
|
bbbd682ed6 | ||
|
|
30bc3eec6e | ||
|
|
442e1403a8 | ||
|
|
bc92c225fb | ||
|
|
be9ec5833d | ||
|
|
c2d98239d2 | ||
|
|
3680db8630 | ||
|
|
343ef16d4f | ||
|
|
9470de1b49 | ||
|
|
1e51aa13af | ||
|
|
8ed07241cb | ||
|
|
be2505fef8 | ||
|
|
e245ef4b0d | ||
|
|
4bbdbf3a79 | ||
|
|
998621f76a | ||
|
|
9f1a7379cc | ||
|
|
5789ae4d18 | ||
|
|
78642a3ed2 | ||
|
|
40fbe50662 | ||
|
|
6e800f4797 | ||
|
|
52a39dd8c1 | ||
|
|
82a95912e6 | ||
|
|
8708f19e39 | ||
|
|
ab7bf9d4fd | ||
|
|
c18db950e5 | ||
|
|
c46e21252c | ||
|
|
53f5a568fb | ||
|
|
d685a19c9e | ||
|
|
77b5459c59 | ||
|
|
dc074b7029 | ||
|
|
4429bce838 | ||
|
|
0455688ea1 | ||
|
|
0ceb14b9a4 | ||
|
|
1b9c72655e | ||
|
|
50f65a4307 | ||
|
|
244dd57299 | ||
|
|
4820c2bb97 | ||
|
|
41306646ad | ||
|
|
07bce6f282 | ||
|
|
d069845b46 | ||
|
|
6bf1183922 | ||
|
|
3b7b130683 | ||
|
|
1a147cf804 | ||
|
|
f375ebee86 | ||
|
|
36928f0644 | ||
|
|
3253f72193 | ||
|
|
2e868d323f | ||
|
|
55b8c48960 | ||
|
|
374e04f6a5 | ||
|
|
dccc0214c1 | ||
|
|
50da413b63 | ||
|
|
6d8ef68057 | ||
|
|
34e56e8675 | ||
|
|
4a42b24900 | ||
|
|
3d4abcf751 | ||
|
|
8976d39051 | ||
|
|
15ba447e53 | ||
|
|
a8de8a68b4 | ||
|
|
bc47ead812 | ||
|
|
18051c0086 | ||
|
|
862cebad5c | ||
|
|
46927aa38b | ||
|
|
ebda286578 | ||
|
|
3050320746 | ||
|
|
aaf49c6f4c | ||
|
|
e95fa2a065 | ||
|
|
1406e38d8f | ||
|
|
62cf9a21ea | ||
|
|
f885e0a6cd | ||
|
|
dc78939d1a | ||
|
|
5a18fe243c | ||
|
|
5a3595c4f9 | ||
|
|
e7bc4fa3d7 | ||
|
|
8c42a49ec8 | ||
|
|
7ea9bd7b83 | ||
|
|
dff0090504 | ||
|
|
a56e3a0a9f | ||
|
|
8f2b687a95 | ||
|
|
2a1bf5efd9 | ||
|
|
5e650c8260 | ||
|
|
d92e62d4d4 | ||
|
|
893b238eff | ||
|
|
c0fc084559 | ||
|
|
239f1a0ef9 | ||
|
|
9cd104ff6f | ||
|
|
d456e6ba54 | ||
|
|
d7da317979 | ||
|
|
4562f0632a | ||
|
|
39be2d6244 | ||
|
|
a69c0016da | ||
|
|
23c2d6b12c | ||
|
|
b48d2563ae | ||
|
|
536d9d370e | ||
|
|
fdfd69cca0 | ||
|
|
0e35816160 | ||
|
|
7f445141f2 | ||
|
|
a50dd88d24 | ||
|
|
e4d1ada252 | ||
|
|
4c624caef3 | ||
|
|
77f36c6b87 | ||
|
|
53082f28e9 | ||
|
|
1c76c72ccb | ||
|
|
877dcd1aa5 | ||
|
|
cd4ff4ecb1 | ||
|
|
eca329c0d0 | ||
|
|
0351e3e37c | ||
|
|
c05c95b497 | ||
|
|
e584c9dab7 | ||
|
|
3884b05a0e | ||
|
|
066d22ae0d | ||
|
|
1632d45e85 | ||
|
|
a71e44bbdc | ||
|
|
a53765b55a | ||
|
|
ef74e24331 | ||
|
|
bb6493c861 | ||
|
|
c75879d64a | ||
|
|
0e5ecf4a0d | ||
|
|
834627669e | ||
|
|
07b19fad72 | ||
|
|
7cc2ae0e40 | ||
|
|
a085c07f89 | ||
|
|
09319f66a0 | ||
|
|
a465a8aef9 | ||
|
|
c513f7318c | ||
|
|
6b72043074 | ||
|
|
17d5d7bdb7 | ||
|
|
eedf47ac8f | ||
|
|
d1f802d254 | ||
|
|
387fbae462 | ||
|
|
ee47520f28 | ||
|
|
13814b20a1 | ||
|
|
6c16e5aa2b | ||
|
|
eb035201f8 | ||
|
|
e6a9e6f90c | ||
|
|
0c67840847 | ||
|
|
94f6f76fbe | ||
|
|
c86ee49fde | ||
|
|
351497ce36 | ||
|
|
11c51dd7e1 | ||
|
|
9dcb9a0000 | ||
|
|
8438e42858 | ||
|
|
4dbfcb6556 | ||
|
|
9b78337c6e | ||
|
|
8de7794637 | ||
|
|
9bf48f9ce7 | ||
|
|
0e3c6239fc | ||
|
|
419e5113e6 | ||
|
|
483146e034 | ||
|
|
3539a390fe | ||
|
|
ccff3cf375 | ||
|
|
015a3ca155 | ||
|
|
91dda91521 | ||
|
|
732337d1e6 | ||
|
|
61b70c7f36 | ||
|
|
05cbf44ba8 | ||
|
|
05bcdff586 | ||
|
|
e88b1ec532 | ||
|
|
f608394204 | ||
|
|
d7b3ef9b58 | ||
|
|
dffb2566bc | ||
|
|
c75b317757 | ||
|
|
dd43338425 | ||
|
|
a1cdeb6f80 | ||
|
|
3e1fa1f6ac | ||
|
|
ef6fc3ed74 | ||
|
|
d08bd95ac6 | ||
|
|
d5c7dd696e | ||
|
|
37a14d1de8 | ||
|
|
f2b31be954 | ||
|
|
be93d86b48 | ||
|
|
0543c58018 | ||
|
|
c5c331ab15 | ||
|
|
c4cca41a72 | ||
|
|
b1b95fe6f1 | ||
|
|
7563b0ab7d | ||
|
|
a17779bba8 | ||
|
|
7db49b3107 | ||
|
|
9ab27e3382 | ||
|
|
42cb459cce | ||
|
|
13d180bc66 | ||
|
|
7763920906 | ||
|
|
2840e351ad | ||
|
|
ec3dc05bf7 | ||
|
|
53d9aa13eb | ||
|
|
9690c20710 | ||
|
|
06221c4ec5 | ||
|
|
81a481d738 | ||
|
|
168d706b03 | ||
|
|
369d4bfae2 | ||
|
|
a5075fe0f8 | ||
|
|
1fd3b9976a | ||
|
|
0a2fff51c7 | ||
|
|
6e85376343 | ||
|
|
0364da8271 | ||
|
|
2f69aac45f | ||
|
|
dd7e72feca | ||
|
|
b6524df6c8 | ||
|
|
552b431691 | ||
|
|
bc60921076 | ||
|
|
36f1b37542 | ||
|
|
345742c6b9 | ||
|
|
5509371ffc | ||
|
|
06b5085b52 | ||
|
|
8aad8d2aa0 | ||
|
|
134e6180c5 | ||
|
|
b9b3841885 | ||
|
|
c732dd54e4 | ||
|
|
6cb38ac23a | ||
|
|
0f11b3b189 | ||
|
|
e89f4dab17 | ||
|
|
b5bea1c29d | ||
|
|
e3514814ba | ||
|
|
193cc5bb0d | ||
|
|
1bb19bec4b | ||
|
|
94994626b6 | ||
|
|
5718466917 | ||
|
|
50010fd3d0 | ||
|
|
506e44802d | ||
|
|
1f8baf8b09 | ||
|
|
798e1fde9a | ||
|
|
9941b34dd8 | ||
|
|
5d93698d99 | ||
|
|
fa161c49f1 | ||
|
|
6dce1a5a3f | ||
|
|
2f5cd4a95c | ||
|
|
fbc2051442 | ||
|
|
668001f9c8 | ||
|
|
a872c59003 | ||
|
|
37b375c21a | ||
|
|
219acbcc07 | ||
|
|
3c5099158d | ||
|
|
2b6344872f | ||
|
|
afd15388cc | ||
|
|
b8885530f4 | ||
|
|
c18dfe9bf6 | ||
|
|
3e9b079007 | ||
|
|
bec04aa020 | ||
|
|
18780395de | ||
|
|
b40c7e28a4 | ||
|
|
da13a5c885 | ||
|
|
f38c6ee7fa | ||
|
|
c46c83bc96 | ||
|
|
913f28a9c2 | ||
|
|
22384074d9 | ||
|
|
3895c7d599 | ||
|
|
cd7c8b1382 | ||
|
|
2bbb53147d | ||
|
|
ac558d5dbe | ||
|
|
3c12ea1c89 | ||
|
|
6b9d24b54a | ||
|
|
a15297d29f | ||
|
|
384bf5dc32 | ||
|
|
2781d38064 | ||
|
|
b7015cb9bc | ||
|
|
a82963fb1c | ||
|
|
4c0c0db318 | ||
|
|
a18f60f5e8 | ||
|
|
827df5e987 | ||
|
|
5e5c478934 | ||
|
|
8a13712e45 | ||
|
|
9efbc46301 | ||
|
|
dcb396b76b | ||
|
|
352f1f4e14 | ||
|
|
db58aec4f3 | ||
|
|
b8a02257a5 | ||
|
|
2486f30a41 | ||
|
|
286ea2461d | ||
|
|
5bdaba8193 | ||
|
|
73558b7492 | ||
|
|
d687e019e5 | ||
|
|
f8d3b1ad77 | ||
|
|
8009d53690 | ||
|
|
e14ae8b10b | ||
|
|
16e8f4ca35 | ||
|
|
8870947391 | ||
|
|
11dfba3120 | ||
|
|
49da32e637 | ||
|
|
76b5be4c87 | ||
|
|
73a820a93b | ||
|
|
382bbb68cc | ||
|
|
82cbf28993 | ||
|
|
4959fb958c | ||
|
|
69a8f90814 | ||
|
|
d309ffbd0a | ||
|
|
efd028f632 | ||
|
|
ee52c6062a | ||
|
|
cf764b8cba | ||
|
|
e21ed1865b | ||
|
|
9235f8bda3 | ||
|
|
3267c78539 | ||
|
|
73831ac046 | ||
|
|
584418a282 | ||
|
|
10dfeecffe | ||
|
|
1890e5d87e | ||
|
|
b31c4d7fb9 | ||
|
|
4f2438acab | ||
|
|
c4da80e6e0 | ||
|
|
9f0d70a9e6 | ||
|
|
031a65ee73 | ||
|
|
487dc0897a | ||
|
|
4eab504331 | ||
|
|
8c4657bddf | ||
|
|
28e37def56 | ||
|
|
3c8a994aed | ||
|
|
e5091a2b33 | ||
|
|
898a67b80e | ||
|
|
a73fc9a283 | ||
|
|
0a9fd1435b | ||
|
|
c7c92a9f15 | ||
|
|
91cdb43004 | ||
|
|
96a557c6bf | ||
|
|
7bcb9629fd | ||
|
|
17e80052e5 | ||
|
|
06dfca5d24 | ||
|
|
8405193cff | ||
|
|
e1dcf90094 | ||
|
|
12e2fe4d94 | ||
|
|
9f5f95fe87 | ||
|
|
f3ad3d0359 | ||
|
|
dfdf53c00d | ||
|
|
c646d9ce18 | ||
|
|
9b46246c2b | ||
|
|
06857dcdd9 | ||
|
|
3e5368b763 | ||
|
|
a3e8fa573c | ||
|
|
996c8e7126 | ||
|
|
eadd6c5509 | ||
|
|
787822b4c8 | ||
|
|
1e0c75701e | ||
|
|
94ba880548 | ||
|
|
ddd6a40a44 | ||
|
|
839d68586b | ||
|
|
def2962670 | ||
|
|
f8ee49646c | ||
|
|
4ff125c703 | ||
|
|
f84de658d4 | ||
|
|
1dfc11aec9 | ||
|
|
34e4f69f84 | ||
|
|
9695141c09 | ||
|
|
d4ff9abc61 | ||
|
|
7c4337dc91 | ||
|
|
0134b03b77 | ||
|
|
f9bd7c1e9e | ||
|
|
f12f0a7011 | ||
|
|
bb10f5af9f | ||
|
|
9a87d520b1 | ||
|
|
8b8d26f9bc | ||
|
|
3673eeb23f | ||
|
|
96dcc5de3d | ||
|
|
8fcc070d1d | ||
|
|
bf63baa047 | ||
|
|
9dde51a708 | ||
|
|
e0ff16cf78 | ||
|
|
7232819f11 | ||
|
|
73617495d2 | ||
|
|
da6ca93454 | ||
|
|
a9bcc5ed49 | ||
|
|
fd514b89f9 | ||
|
|
760dbbed48 | ||
|
|
a3b0b2d6a0 | ||
|
|
67cdd39162 | ||
|
|
34afeec2e7 | ||
|
|
f43e241593 | ||
|
|
67ad985735 | ||
|
|
b950439080 | ||
|
|
9b702cc543 | ||
|
|
513b6333fb | ||
|
|
0e76390736 | ||
|
|
07d1b22e81 | ||
|
|
37f4e037c5 | ||
|
|
0f15f042b9 | ||
|
|
1626a052bc | ||
|
|
6390872a5d | ||
|
|
befaca888d | ||
|
|
5ef0da8240 | ||
|
|
c991f6acf1 | ||
|
|
a1e87f11eb | ||
|
|
9209bc5e13 | ||
|
|
f869646706 | ||
|
|
d808177d50 | ||
|
|
b70b531699 | ||
|
|
eb2cd99a14 | ||
|
|
3ec18090b9 | ||
|
|
ed62f449a9 | ||
|
|
e1038e3090 | ||
|
|
973481807e | ||
|
|
c608e97005 | ||
|
|
d8cfe78b33 | ||
|
|
9202b378d9 | ||
|
|
37eeb4abd0 | ||
|
|
e2418b7008 | ||
|
|
5e134348dd | ||
|
|
6c20ceb717 | ||
|
|
fbbd30ca23 | ||
|
|
209d413c6b | ||
|
|
e54e28b631 | ||
|
|
4a6c4d41fc | ||
|
|
415d197da1 | ||
|
|
f3e54a41da | ||
|
|
dbdb058f31 | ||
|
|
32126398ef | ||
|
|
e27afd5b74 | ||
|
|
efdcabc2cb | ||
|
|
ebb18daf22 | ||
|
|
1a2ba48fa1 | ||
|
|
f927433a40 | ||
|
|
76172327f8 | ||
|
|
c0273110c4 | ||
|
|
9c65039c32 | ||
|
|
1688ea358b | ||
|
|
0ddbbd1785 | ||
|
|
c52e38d3be | ||
|
|
e8f0958d01 | ||
|
|
de1b42b6bf | ||
|
|
292e397759 | ||
|
|
b4142e0cd2 | ||
|
|
a17f53358c | ||
|
|
864d84e1a7 | ||
|
|
375162b4fb | ||
|
|
220623f88a | ||
|
|
c22c053f82 | ||
|
|
c26fb30f20 | ||
|
|
cc9f35f8c7 | ||
|
|
c1a5796446 | ||
|
|
027f79d840 | ||
|
|
cd4ebb34ec | ||
|
|
fce17976e9 | ||
|
|
34988d1ce9 | ||
|
|
c8673a011e | ||
|
|
7aef6a5b83 | ||
|
|
809166ff78 | ||
|
|
8249c40b7b | ||
|
|
4721dc5d1c | ||
|
|
702bd20b65 | ||
|
|
666dd0f75c | ||
|
|
15c6bf0860 | ||
|
|
856a9a528c | ||
|
|
8dd03ff284 | ||
|
|
04fc29c8b2 | ||
|
|
9b926b1d64 | ||
|
|
74786b8c58 | ||
|
|
3e2253a3c4 | ||
|
|
c82026012e | ||
|
|
b6f979100d | ||
|
|
aa5bf2bc6e | ||
|
|
1434bb9792 | ||
|
|
83f342776e | ||
|
|
d42c7aeede | ||
|
|
76485d3f02 | ||
|
|
250260064f | ||
|
|
678c1d90c0 | ||
|
|
e2318bdba9 | ||
|
|
ca88a7476f | ||
|
|
eda8998156 | ||
|
|
b1b4db95c2 | ||
|
|
01e406626e | ||
|
|
89da44223d | ||
|
|
ddf2648326 | ||
|
|
4c2148bea5 | ||
|
|
66bf105bbc | ||
|
|
1700f24dd3 | ||
|
|
aa2e435d82 | ||
|
|
2fc5fed79e | ||
|
|
efd42d2d5c | ||
|
|
2ff6a84a16 | ||
|
|
01c0938ddf | ||
|
|
fda8fa2367 | ||
|
|
998ef5948c | ||
|
|
cbc39f7d71 | ||
|
|
802a44a15b | ||
|
|
efbb88225c | ||
|
|
30d264ebda | ||
|
|
bf4ca23372 | ||
|
|
9ecfd9f33e | ||
|
|
255ce93616 | ||
|
|
4ffa6c246f | ||
|
|
a9db074776 | ||
|
|
7b10240bc3 | ||
|
|
9812bcc03c | ||
|
|
fb6e840213 | ||
|
|
2a896e5d3c | ||
|
|
ab67420c37 | ||
|
|
07a6cd4592 | ||
|
|
762cd4621d | ||
|
|
a23534c4e2 | ||
|
|
1597114535 | ||
|
|
aea667c7c8 | ||
|
|
e0f335a4eb | ||
|
|
78531a0f32 | ||
|
|
a2297d6776 | ||
|
|
ef889d6672 | ||
|
|
291ce3e839 | ||
|
|
42806dc1ac | ||
|
|
45a157ec0e | ||
|
|
49389bd690 | ||
|
|
a638a19ea2 | ||
|
|
199ec4356a | ||
|
|
5dad6f4319 | ||
|
|
27e4a2ee57 | ||
|
|
d7fb7e9ed7 | ||
|
|
528cf89739 | ||
|
|
b96abb803c | ||
|
|
574d3785ab | ||
|
|
d1be79cce2 | ||
|
|
9d8c71ee86 | ||
|
|
877f1f64c2 | ||
|
|
a9f5393bfe | ||
|
|
038cd054ae | ||
|
|
e228c88d2a | ||
|
|
4824ee8b20 | ||
|
|
0da1f7593d | ||
|
|
8fae88d368 | ||
|
|
5c32080a0c | ||
|
|
610d52b054 | ||
|
|
0aa4c95a89 | ||
|
|
d2385517ac | ||
|
|
3fc2609468 | ||
|
|
0eec8c8318 | ||
|
|
bdc00dae0e | ||
|
|
a1442538b5 | ||
|
|
ce68497243 | ||
|
|
9a387e5a7a | ||
|
|
c4aa1dadbd | ||
|
|
556f27ecf1 | ||
|
|
ef2cd744cf | ||
|
|
f5b1c6c27e | ||
|
|
5f93d06cf8 | ||
|
|
952a5e6dd9 | ||
|
|
238b9d24c6 | ||
|
|
7457c51bc2 | ||
|
|
a4437b1362 | ||
|
|
45b91a90e1 | ||
|
|
3cb1d7843b | ||
|
|
4d6b943ea4 | ||
|
|
d8aff59a9e | ||
|
|
e9dbd238c8 | ||
|
|
89447a99ec | ||
|
|
e499028440 | ||
|
|
2f82498995 | ||
|
|
71df4d92da | ||
|
|
ac1e884328 | ||
|
|
e31d4ee777 | ||
|
|
cc30079edd | ||
|
|
b76252d68e | ||
|
|
ce868ed5f5 | ||
|
|
8283811633 | ||
|
|
00f227a684 | ||
|
|
a6e748e491 | ||
|
|
8a12240f73 | ||
|
|
815318b12f | ||
|
|
5e0b84633e | ||
|
|
aa2a8ed77c | ||
|
|
9e96cb612b | ||
|
|
f54c287c73 | ||
|
|
14e1fe4795 | ||
|
|
81df8343d3 | ||
|
|
388ca07547 | ||
|
|
b3fdacf9cc | ||
|
|
cb896da998 | ||
|
|
879c401544 | ||
|
|
c6025e41c6 | ||
|
|
52647db120 | ||
|
|
5adfdcba1e | ||
|
|
550e8e56ba | ||
|
|
8d457d07c4 | ||
|
|
b3333ebc2e | ||
|
|
3454b5927f | ||
|
|
54e81f5ca0 | ||
|
|
c1e14143fa | ||
|
|
97904aee06 | ||
|
|
24e902d2a4 | ||
|
|
0da197d593 | ||
|
|
6b2e3f29f9 | ||
|
|
64b9a563f2 | ||
|
|
a703e927b1 | ||
|
|
8d0d386970 | ||
|
|
dc542971df | ||
|
|
8fb1ddeb5d | ||
|
|
e94fa076cb | ||
|
|
f83715ce9c | ||
|
|
b0970b9e33 | ||
|
|
f4b60a5c65 | ||
|
|
e7908a50e8 | ||
|
|
789c4f4587 | ||
|
|
19be63c4c3 | ||
|
|
04a9441769 | ||
|
|
a2da1f08bd | ||
|
|
eb57ea95d6 | ||
|
|
1e2db0e885 | ||
|
|
d77ae42896 | ||
|
|
2a2d65541b | ||
|
|
fd7577eed2 | ||
|
|
93818c761b | ||
|
|
bc72d7584a | ||
|
|
b813a5f3fa | ||
|
|
d952c7ed71 | ||
|
|
07166e63a3 | ||
|
|
9888487f9c | ||
|
|
3c7ab1ca5e | ||
|
|
08a8632ac7 | ||
|
|
4b2877834e | ||
|
|
344ec00439 | ||
|
|
082f628401 | ||
|
|
3cf360ae44 | ||
|
|
0c39d6de8e | ||
|
|
53262335c8 | ||
|
|
380b9a40a3 | ||
|
|
f6109b7b94 | ||
|
|
1db964ad95 | ||
|
|
416079db61 | ||
|
|
49ca05642a | ||
|
|
7d88098555 | ||
|
|
82db278716 | ||
|
|
cfb711bf57 | ||
|
|
471df8f512 | ||
|
|
9f1562a599 | ||
|
|
e2fe8ef485 | ||
|
|
4a19a2644f | ||
|
|
066a53df8a | ||
|
|
2a108b9b06 | ||
|
|
6749f1b8b5 | ||
|
|
8ff9c0d1b9 | ||
|
|
b48987922c | ||
|
|
5259155e52 | ||
|
|
2f753040ef | ||
|
|
bd7ca6bb69 | ||
|
|
0f88c702df | ||
|
|
28e5320ab4 | ||
|
|
47f8883942 | ||
|
|
4c133e47da | ||
|
|
0cf6b2ba31 | ||
|
|
7fffa6e20a | ||
|
|
ccdd86775f | ||
|
|
91d2e58d1b | ||
|
|
1327846518 | ||
|
|
11b1e81197 | ||
|
|
616780b64e | ||
|
|
90a497c3b8 | ||
|
|
de1d9a90dd | ||
|
|
516cd1ba8d | ||
|
|
c7541bd672 | ||
|
|
c3c13114fb | ||
|
|
2863202bed | ||
|
|
cab4557006 | ||
|
|
f1be7d7ffc | ||
|
|
c22fdb7232 | ||
|
|
bd1c5ac3cf | ||
|
|
fa814abe05 | ||
|
|
03cd30b746 | ||
|
|
7ede296efd | ||
|
|
264fead207 | ||
|
|
e5ad308a2b | ||
|
|
f31a210cb2 | ||
|
|
b27c9f26fe | ||
|
|
0ffa958fc4 | ||
|
|
e8483c021b | ||
|
|
5596c6a5da | ||
|
|
0a6f41cdf2 | ||
|
|
4219bdc2b4 | ||
|
|
fa9c265ce7 | ||
|
|
6d447004ea | ||
|
|
091c6c36b9 | ||
|
|
1f34a1dab4 | ||
|
|
ba55e8ae64 | ||
|
|
461596d9b1 | ||
|
|
0e3fc6a4fe | ||
|
|
6a589d5630 | ||
|
|
b8c18d6176 | ||
|
|
4210fd6ad9 | ||
|
|
1ddd0afe36 | ||
|
|
230d4b38a3 | ||
|
|
1afd98d916 | ||
|
|
60707a4172 | ||
|
|
f2dcfca9c4 | ||
|
|
d8436708c0 | ||
|
|
de3528f0be | ||
|
|
d0ab0358aa | ||
|
|
4f9f6df42c | ||
|
|
ed20af4517 | ||
|
|
3ca96a1317 | ||
|
|
3bcff2d2f9 | ||
|
|
3e85e4b82c | ||
|
|
299b26ae4a | ||
|
|
bbbbcaf73f | ||
|
|
37e789fd79 | ||
|
|
27f3c530ed | ||
|
|
534e44c599 | ||
|
|
1587fd6b84 | ||
|
|
ce51451ca6 | ||
|
|
3385ecc112 | ||
|
|
5d589eb866 | ||
|
|
039aad9ff4 | ||
|
|
a0b8879af4 | ||
|
|
e1c9ebc5b9 | ||
|
|
02ffc0eec8 | ||
|
|
a560227ccb | ||
|
|
87a7a3aaff | ||
|
|
6723ea3afb | ||
|
|
3ff53cd50b | ||
|
|
94f18868f1 | ||
|
|
e85d440f88 | ||
|
|
6910fd79f2 | ||
|
|
c14b405974 | ||
|
|
0125ed120f | ||
|
|
be2d39a1a5 | ||
|
|
cbe0264949 | ||
|
|
96e2c3a3aa | ||
|
|
7216081447 | ||
|
|
7acee329e1 | ||
|
|
916566ac11 | ||
|
|
785eaf01b3 | ||
|
|
ccbc7a6835 | ||
|
|
6193bc31b8 | ||
|
|
698820f4e3 | ||
|
|
34e40a3a59 | ||
|
|
a21e295c96 | ||
|
|
082d7ee4b8 | ||
|
|
bdd9753f1e | ||
|
|
0df4b4eb64 | ||
|
|
2ee29be0e8 | ||
|
|
172a45d603 | ||
|
|
27d0ebc686 | ||
|
|
be02813c26 | ||
|
|
85a15b4fc9 | ||
|
|
c16542c1d0 | ||
|
|
1de05fb7da | ||
|
|
a2e82071c5 | ||
|
|
cfba600eab | ||
|
|
99f901f065 | ||
|
|
f074b92823 | ||
|
|
07f349766c | ||
|
|
892b06e282 | ||
|
|
f3522b6c01 | ||
|
|
437f625786 | ||
|
|
8b364485a0 | ||
|
|
345dff63e9 | ||
|
|
76913125d8 | ||
|
|
f195e423f4 | ||
|
|
5abc3ecb56 | ||
|
|
87787b05ae | ||
|
|
4f2b8f8e9a | ||
|
|
c8170cf360 | ||
|
|
358ff9f7d6 | ||
|
|
e094bf07dc | ||
|
|
05e338ce75 | ||
|
|
fbe6024753 | ||
|
|
4d3f4f719a | ||
|
|
b240128ed4 | ||
|
|
70b3ab34a8 | ||
|
|
27e3cd9ca8 | ||
|
|
13a45232fa | ||
|
|
c4bfcdeec5 | ||
|
|
cfcc58d96e | ||
|
|
096feeeddd | ||
|
|
2de01f7b7e | ||
|
|
0369242c4c | ||
|
|
a70d444333 | ||
|
|
79a00a33f9 | ||
|
|
c542576190 | ||
|
|
725c352e94 | ||
|
|
64e1166e6f | ||
|
|
57b6515d82 | ||
|
|
e786eae3cd | ||
|
|
a322c6f411 | ||
|
|
943133953e | ||
|
|
f6717c92b2 | ||
|
|
9b0b4bf041 | ||
|
|
183fb08ee6 | ||
|
|
760bc42049 | ||
|
|
3329f8154e | ||
|
|
b4f6d91eda | ||
|
|
0f93207cda | ||
|
|
43866cf0d9 | ||
|
|
deb02a000f | ||
|
|
baef4818d2 | ||
|
|
bf70a01da6 | ||
|
|
5733f64bdd | ||
|
|
a57ad69b53 | ||
|
|
7b52e19b6d | ||
|
|
728e55e697 | ||
|
|
71f41a06dc | ||
|
|
e90022767d | ||
|
|
a395d75a91 | ||
|
|
42837cde4c | ||
|
|
1394a78bd6 | ||
|
|
e4d4c93bd8 | ||
|
|
00f3bf560b | ||
|
|
5bd8cf6cde | ||
|
|
9e789de703 | ||
|
|
d1ad2a695d | ||
|
|
d0c1882cf7 | ||
|
|
0abd9ec096 | ||
|
|
25afd9876c | ||
|
|
eb718e597d | ||
|
|
1bfdd45fca | ||
|
|
d189993f15 | ||
|
|
6f5eb3b8fa | ||
|
|
4eedf0cd2e | ||
|
|
630ca201d6 | ||
|
|
bf17aa1eca | ||
|
|
5ed7dc3590 | ||
|
|
0fc1ef8c9d | ||
|
|
d89ed4ab5f | ||
|
|
0905b587cf | ||
|
|
35ffb12ae8 | ||
|
|
4dba976a7f | ||
|
|
d3499da6fd | ||
|
|
a1531e0ae3 | ||
|
|
7f234dbc4e | ||
|
|
1a3ec0536c | ||
|
|
832da92bdc | ||
|
|
e85731555d | ||
|
|
7ab67c9fba | ||
|
|
0afbb8bcbf | ||
|
|
bb75fcc4db | ||
|
|
0bb8d95674 | ||
|
|
405d0be9fe | ||
|
|
b5ad8c24be | ||
|
|
e252af2152 | ||
|
|
a59c1d2ac4 | ||
|
|
e49aae74d0 | ||
|
|
c87d1f6309 | ||
|
|
a23fa08274 | ||
|
|
24a5704798 | ||
|
|
d3397cd37d | ||
|
|
f8594ac304 | ||
|
|
ed42d3074d | ||
|
|
eb80683222 | ||
|
|
5808760bf4 | ||
|
|
404485711e | ||
|
|
daf76979ca | ||
|
|
73f91fcc44 | ||
|
|
8a4967294f | ||
|
|
dc60239686 | ||
|
|
b600cf2232 | ||
|
|
d9be9eb5a8 | ||
|
|
449bef5a36 | ||
|
|
b53507021e | ||
|
|
463444b391 | ||
|
|
a1cf0fbd43 | ||
|
|
2f2122875a | ||
|
|
569b95352a | ||
|
|
ab7cd94b60 | ||
|
|
57217916f1 | ||
|
|
de4188df06 | ||
|
|
f10148d3e3 | ||
|
|
b1e841edab | ||
|
|
68070c82d0 | ||
|
|
823f4559c9 | ||
|
|
f202a8dbb3 | ||
|
|
09c3679e2d | ||
|
|
6b8ecfa35f | ||
|
|
3abd26bfdf | ||
|
|
03b1d1ea8c | ||
|
|
b1d55878a7 | ||
|
|
d5c614397a | ||
|
|
eac29e9814 | ||
|
|
bba1faf910 | ||
|
|
78117423fa | ||
|
|
5de01235b6 | ||
|
|
e167cc89f8 | ||
|
|
05d3d9c25f | ||
|
|
957782627c | ||
|
|
6e9d4faf61 | ||
|
|
0a4a5483ae | ||
|
|
bab6f6bdf2 | ||
|
|
fa0ca01ffe | ||
|
|
044ad2e2e7 | ||
|
|
9cd917c42a | ||
|
|
1b9251ad14 | ||
|
|
2f1c9c690f | ||
|
|
0c6b76f7c2 | ||
|
|
2a9d43407b | ||
|
|
8ed49644a6 | ||
|
|
872685d088 | ||
|
|
4d32c46126 | ||
|
|
4290558ec0 | ||
|
|
9b08305eae | ||
|
|
f78179c374 | ||
|
|
e42c11905e | ||
|
|
3fdbac912a | ||
|
|
3ba284094e | ||
|
|
634521b59b | ||
|
|
423fd40090 | ||
|
|
058f20179b | ||
|
|
dd293ed6fe | ||
|
|
3c7300d145 | ||
|
|
fb3f2062fa | ||
|
|
9e0e3799bf | ||
|
|
f107562f75 | ||
|
|
602d616726 | ||
|
|
611da9b699 | ||
|
|
34ed331f82 | ||
|
|
7ca6f85a41 | ||
|
|
069d045513 | ||
|
|
7c97de2611 | ||
|
|
11ee0b6a41 | ||
|
|
a40e6c115f | ||
|
|
4113c814c7 | ||
|
|
8426e454de | ||
|
|
c5e44cc3cb | ||
|
|
c793ab62ff | ||
|
|
decd0771ee | ||
|
|
68dd66c46d | ||
|
|
568ba9c398 | ||
|
|
e3d12a2ab2 | ||
|
|
c4a633a87b | ||
|
|
b5780eda44 | ||
|
|
65fc87b245 | ||
|
|
12b3b6c86e | ||
|
|
8ebfe337a7 | ||
|
|
28076a9c68 | ||
|
|
851fce9568 | ||
|
|
91a7960ad5 | ||
|
|
216fd6e249 | ||
|
|
18844270c3 | ||
|
|
fd9b6d13e6 | ||
|
|
5fa70e63a0 | ||
|
|
432bb121f3 | ||
|
|
52549b25cd | ||
|
|
fba5172e8a | ||
|
|
155d84a979 | ||
|
|
a7d2842beb | ||
|
|
70c530630a | ||
|
|
a722b0462e | ||
|
|
f63d46097d | ||
|
|
75d4369dfc | ||
|
|
3697f7dbcc | ||
|
|
9de6aed36b | ||
|
|
2e5873cb5d | ||
|
|
d2f22c57fe | ||
|
|
b1d9a040d4 | ||
|
|
fb8ebe6365 | ||
|
|
201849fb42 | ||
|
|
8e2e53c987 | ||
|
|
bd7418b625 | ||
|
|
3cf3edb14f | ||
|
|
3e2806114b | ||
|
|
2f911dfba6 | ||
|
|
64439e0692 | ||
|
|
b94f5ca495 | ||
|
|
1f1c915fea | ||
|
|
7be9c6e469 | ||
|
|
60ad539878 | ||
|
|
9b32ff1eeb | ||
|
|
074f8d9378 | ||
|
|
4b5f53d6a0 | ||
|
|
34208f76a5 | ||
|
|
e7bd1ce7b9 | ||
|
|
a8d8221357 | ||
|
|
ee4a248e6b | ||
|
|
4d0dd2775a | ||
|
|
eb6b35b75f | ||
|
|
9a478cb855 | ||
|
|
457528ae86 | ||
|
|
733c167528 | ||
|
|
f97df161f4 | ||
|
|
5bb0c3786d | ||
|
|
6195ae7453 | ||
|
|
779140b94c | ||
|
|
196112076c | ||
|
|
30910d48bc | ||
|
|
408ead2dda | ||
|
|
baa46147a5 | ||
|
|
3d0e3d3c0f | ||
|
|
560068617a | ||
|
|
ef0128ec41 | ||
|
|
5fec7176e0 | ||
|
|
a11c4965b7 | ||
|
|
b283a02a7d | ||
|
|
09c41b415d | ||
|
|
9b6bd35ed3 | ||
|
|
eb9adf42d6 | ||
|
|
6f0a7f7a15 | ||
|
|
614d878b04 | ||
|
|
a9da004305 | ||
|
|
88eede5218 | ||
|
|
9127ab071b | ||
|
|
05110e85d3 | ||
|
|
ca75adf9cb | ||
|
|
54dcc9bf56 | ||
|
|
ca7fc00ad5 | ||
|
|
df2394af02 | ||
|
|
c3af8944af | ||
|
|
b140eef0aa | ||
|
|
88bcbb2368 | ||
|
|
d9ed36059c | ||
|
|
1af31f2c64 | ||
|
|
b76935b95c | ||
|
|
03fbf171a7 | ||
|
|
3db853b428 | ||
|
|
a30ae193db | ||
|
|
a466fdbc40 | ||
|
|
2fb8ad79c2 | ||
|
|
9ab74af94f | ||
|
|
c9f168ed0f | ||
|
|
dbea1448bd | ||
|
|
e6de64a5a9 | ||
|
|
fe4b2401bd | ||
|
|
d37b6dd459 | ||
|
|
0a059f8ce1 | ||
|
|
80c9620612 | ||
|
|
2f421a55da | ||
|
|
42ad569376 | ||
|
|
bdbed69984 | ||
|
|
1d473f25dd | ||
|
|
b0972b8d1f | ||
|
|
f6f67727c6 | ||
|
|
8ef1f1ea2e | ||
|
|
df93792f9c | ||
|
|
08ac005489 | ||
|
|
27bb1601d3 | ||
|
|
da49f53b66 | ||
|
|
e9f2a805b9 | ||
|
|
74fdefdf1e | ||
|
|
68248b91f0 | ||
|
|
6729301b4d | ||
|
|
5e36feac27 | ||
|
|
7a363d3d17 | ||
|
|
2187465cae | ||
|
|
0f6db9f939 | ||
|
|
a03db324dd | ||
|
|
3f9c34f415 | ||
|
|
024f486810 | ||
|
|
f5c18f62a1 | ||
|
|
8801247d76 | ||
|
|
45ee2978cd | ||
|
|
f5de717d6e | ||
|
|
5546e32355 | ||
|
|
2f4a0dc3f5 | ||
|
|
652e085d0f | ||
|
|
8b2b0278c9 | ||
|
|
e66aef0c05 | ||
|
|
9cb185e126 | ||
|
|
2bd13db091 | ||
|
|
551e3ad719 | ||
|
|
df4ea0cec4 | ||
|
|
3ccf8627e0 | ||
|
|
aa63104784 | ||
|
|
2efcb2e331 | ||
|
|
76fe489c86 | ||
|
|
ec3f9d5041 | ||
|
|
7b0160ee51 | ||
|
|
b0991ab170 | ||
|
|
8c4cacbd58 | ||
|
|
502e74e5db | ||
|
|
b168dcdddf | ||
|
|
585afa7e8e | ||
|
|
737e9b2458 | ||
|
|
2ee28d0ccf | ||
|
|
bbe5ff18c2 | ||
|
|
ef4d9eb5b7 | ||
|
|
491e5d941c | ||
|
|
b72227e845 | ||
|
|
70167380a3 | ||
|
|
347f32ab97 | ||
|
|
3b3a042cef | ||
|
|
a054fec8ef | ||
|
|
bc9e475d6e | ||
|
|
18fef6deb1 | ||
|
|
133120aa38 | ||
|
|
e32c8f1ebe | ||
|
|
19d5ae6e8d | ||
|
|
3932d756d4 | ||
|
|
f75a3079e0 | ||
|
|
d11177774a | ||
|
|
e5629ea138 | ||
|
|
4f72a1da77 | ||
|
|
095b971fc6 | ||
|
|
2d78f0d53c | ||
|
|
4a4e1e348d | ||
|
|
702b8a96b0 | ||
|
|
dd4aba8022 | ||
|
|
e3c58c8ebe | ||
|
|
fdf586e416 | ||
|
|
88aec64bce | ||
|
|
db8da3c376 | ||
|
|
7538cee13b | ||
|
|
be9d4b4333 | ||
|
|
b3b931fab9 | ||
|
|
8fa9d75365 | ||
|
|
1f4eadaf6a | ||
|
|
ada1e768c4 | ||
|
|
7255d8797c | ||
|
|
46303772e5 | ||
|
|
d0e532a070 | ||
|
|
6c9b510d5d | ||
|
|
dc7ceb7fd8 | ||
|
|
d88a461764 | ||
|
|
db8da85266 | ||
|
|
bc80b3130d | ||
|
|
001623fa0a | ||
|
|
c53e76528d | ||
|
|
ee664e6ccd | ||
|
|
427be16475 | ||
|
|
5b9cab6c13 | ||
|
|
f70b57352b | ||
|
|
bec994b037 | ||
|
|
3cf5ea7383 | ||
|
|
d208532e6e | ||
|
|
800ad7f727 | ||
|
|
fd70e7920e | ||
|
|
d030752f72 | ||
|
|
319011b0e3 | ||
|
|
9e3a90e249 | ||
|
|
439e5eeeb4 | ||
|
|
1b23fce2bd | ||
|
|
a3355d9fe2 | ||
|
|
c359ec8f5c | ||
|
|
31b39fe85e | ||
|
|
c51934cd70 | ||
|
|
481a59e92e | ||
|
|
1bc96b7aab | ||
|
|
bad7cc9c14 | ||
|
|
c96b39a960 | ||
|
|
758f246390 | ||
|
|
b1a658f57e | ||
|
|
8800bd6b1f | ||
|
|
a53d260d5f | ||
|
|
3ef099dede | ||
|
|
1794aac9e1 | ||
|
|
de57be6bbd | ||
|
|
a23c43cefa | ||
|
|
727abcdec7 | ||
|
|
c96046b6c2 | ||
|
|
f105351643 | ||
|
|
5ae7b48700 | ||
|
|
8c2bc79b77 | ||
|
|
d3fd49f2cf | ||
|
|
68c45465c8 | ||
|
|
ad49896f6b | ||
|
|
8995f5d810 | ||
|
|
22de310e04 | ||
|
|
9bd9958722 | ||
|
|
dff7c80952 | ||
|
|
a14ba4f1b5 | ||
|
|
994c0a5573 | ||
|
|
a9b5a6cbb0 | ||
|
|
8699103fa1 | ||
|
|
469c7d6de9 | ||
|
|
9c42fa75a4 | ||
|
|
0f2e75a257 | ||
|
|
e115566669 | ||
|
|
65d5921dde | ||
|
|
e325aa312f | ||
|
|
7b7dbfb855 | ||
|
|
cc36c3d475 | ||
|
|
a550016fd6 | ||
|
|
df9b7608a9 | ||
|
|
b9d81ae6ad | ||
|
|
32ecea7b8c | ||
|
|
746d2e7f67 | ||
|
|
27578642b8 | ||
|
|
63b280e97c | ||
|
|
0062fe9588 | ||
|
|
103bb4a334 | ||
|
|
aa2795cc46 | ||
|
|
269507ad59 | ||
|
|
ca0c646539 | ||
|
|
8cc1ffe2ab | ||
|
|
dc7e5f5f03 | ||
|
|
799b876aa0 | ||
|
|
8f5498177e | ||
|
|
8f9ace9228 | ||
|
|
5a9ab574de | ||
|
|
ea2b6241fd | ||
|
|
ea70485e7b | ||
|
|
37ae3cd701 | ||
|
|
b6beb440cd | ||
|
|
bc86e5de2a | ||
|
|
2587e6faa4 | ||
|
|
ce82bfa75a | ||
|
|
31e427d775 | ||
|
|
a435f135b5 | ||
|
|
36b87b3b33 | ||
|
|
8164972e34 | ||
|
|
49257bafbc | ||
|
|
9286f2c6d3 | ||
|
|
fdcf41cef0 | ||
|
|
66fae27e3a | ||
|
|
c66bf9a326 | ||
|
|
8968d50976 | ||
|
|
b0f9569b5c | ||
|
|
514acf8dfc | ||
|
|
89561c6a29 | ||
|
|
c47538a24b | ||
|
|
5ee4f3048c | ||
|
|
0f5ed60d51 | ||
|
|
5ef2ef8a1d | ||
|
|
d34639a601 | ||
|
|
bf2ec2d6d0 | ||
|
|
f30d55fbf6 | ||
|
|
8136198e53 | ||
|
|
fa9a8d158a | ||
|
|
cc698e15cf | ||
|
|
4926908616 | ||
|
|
a2cc6b01be | ||
|
|
63074875d6 | ||
|
|
04887bcc3e | ||
|
|
5b53760717 | ||
|
|
ff2ba012d2 | ||
|
|
e446f4ca81 | ||
|
|
4d1706d05f | ||
|
|
4f5ddbc374 | ||
|
|
96117402b1 | ||
|
|
2cd1eb39b1 | ||
|
|
03cb980dc2 | ||
|
|
b820fd0075 | ||
|
|
cf57ba2310 | ||
|
|
fc7593e594 | ||
|
|
54780434a6 | ||
|
|
ec14976ac3 | ||
|
|
fdb8ffe20d | ||
|
|
f7a7158f3f | ||
|
|
b4a2ee6104 | ||
|
|
728cceca7e | ||
|
|
7baf86bc8b | ||
|
|
9432a1c19f | ||
|
|
1b5d2d4667 | ||
|
|
682913a1f3 | ||
|
|
82b3a5f417 | ||
|
|
8f9e2b6633 | ||
|
|
8161efd26a | ||
|
|
1799dd3641 | ||
|
|
1147ed1e8c | ||
|
|
0f966565af | ||
|
|
2cc7d3e8db | ||
|
|
67b3ab9ee5 | ||
|
|
7dee677799 | ||
|
|
9dbb2ef08c | ||
|
|
0e1e513d5a | ||
|
|
588801931f | ||
|
|
e3ad88c784 | ||
|
|
af69f68359 | ||
|
|
3377298b06 | ||
|
|
15b86b3afb | ||
|
|
776497fb6b | ||
|
|
9082b027ef | ||
|
|
bbce72c316 | ||
|
|
d7ba067af6 | ||
|
|
1798abd909 | ||
|
|
4b5f7f0ef6 | ||
|
|
5273e43919 | ||
|
|
316bffd061 | ||
|
|
ba264f8158 | ||
|
|
cf24f7ff7e | ||
|
|
5e29d3a518 | ||
|
|
25ca4c854c | ||
|
|
50449d5c87 | ||
|
|
740243552f | ||
|
|
9f14461cb7 | ||
|
|
194fe2a4a5 | ||
|
|
e300367ad8 | ||
|
|
15b2f1f635 | ||
|
|
47133fda31 | ||
|
|
a0486afb83 | ||
|
|
ad67680ed3 | ||
|
|
93da37619a | ||
|
|
0284bc4b99 | ||
|
|
7f1117a71f | ||
|
|
0004e8a4be | ||
|
|
41c995dd18 | ||
|
|
89dbeddcfc | ||
|
|
6195dd35e0 | ||
|
|
e1b72cf020 | ||
|
|
b1462cd593 | ||
|
|
868fec3692 | ||
|
|
a105455487 | ||
|
|
0882f61a8e | ||
|
|
eff9477388 | ||
|
|
fc6a82fcb8 | ||
|
|
2bc871a62e | ||
|
|
61ce929656 | ||
|
|
67e1c59427 | ||
|
|
3f6896acd3 | ||
|
|
17aeeda774 | ||
|
|
143b73ee7b | ||
|
|
260fcde6e2 | ||
|
|
ce55c480e9 | ||
|
|
5738da5225 | ||
|
|
457f4caf6f | ||
|
|
34347418e3 | ||
|
|
5d9aa86efa | ||
|
|
ff5851c685 | ||
|
|
7976579ef6 | ||
|
|
36f888e06e | ||
|
|
a73524874c | ||
|
|
1c445d44c5 | ||
|
|
a54a0e5ecb | ||
|
|
e0ab451084 | ||
|
|
2310261cbe | ||
|
|
99876da380 | ||
|
|
76a22457ce | ||
|
|
e36ed02083 | ||
|
|
1f506e55d0 | ||
|
|
a80bce7e58 | ||
|
|
4b56cf02f0 | ||
|
|
668f8161ab | ||
|
|
d117f2258f | ||
|
|
1a81758f1c | ||
|
|
655bce9e1f | ||
|
|
9242c5c05e | ||
|
|
adc4fbe921 | ||
|
|
95ef751780 | ||
|
|
e2dd1cc3da | ||
|
|
2dfb2d723f | ||
|
|
1feaac6a54 | ||
|
|
4fc75f6559 | ||
|
|
e37c73ef97 | ||
|
|
3c50e18f46 | ||
|
|
ed443d08cf | ||
|
|
3794c9bfef | ||
|
|
1081dc05c2 | ||
|
|
72ca19339d | ||
|
|
83c46fb83e | ||
|
|
b8190d0e92 | ||
|
|
103034acf2 | ||
|
|
2742f2ca72 | ||
|
|
f222665d1d | ||
|
|
70007e6095 | ||
|
|
694c1c0c9c | ||
|
|
d146b72e53 | ||
|
|
4d1137ded4 | ||
|
|
2293ad0b1f | ||
|
|
f59f077d27 | ||
|
|
28c55ae8e3 | ||
|
|
7254cca9f3 | ||
|
|
50b637d1f9 | ||
|
|
023939d65f | ||
|
|
83a8b6745f | ||
|
|
baeb134536 | ||
|
|
c1b3b1d5b1 | ||
|
|
beae1fb946 | ||
|
|
6b0805633b | ||
|
|
c9d3a81c3a | ||
|
|
dbb7b83ecc | ||
|
|
ed01d3b366 | ||
|
|
88fa72f892 | ||
|
|
1aba1bbca4 | ||
|
|
10c25aa6d9 | ||
|
|
34e400fe2b | ||
|
|
a7818fb1be | ||
|
|
e753e1a460 | ||
|
|
fb80a4a397 | ||
|
|
964565519c | ||
|
|
960c01e4c6 | ||
|
|
87e3b8b2ad | ||
|
|
230eb50e96 | ||
|
|
1bc23d416c | ||
|
|
4b84c43811 | ||
|
|
22243ee9ae | ||
|
|
2d8c703fa0 | ||
|
|
6ead43beb1 | ||
|
|
62eef7c695 | ||
|
|
f2e0152108 | ||
|
|
25b07915d6 | ||
|
|
811f5cff35 | ||
|
|
c00550f3ae | ||
|
|
8ef3b1544b | ||
|
|
3e3642433b | ||
|
|
aff78a98cf | ||
|
|
d2a4408930 | ||
|
|
9740f51d00 | ||
|
|
812b527dd8 | ||
|
|
297e62b8be | ||
|
|
3189e70baa | ||
|
|
dca37d634e | ||
|
|
29718a5001 | ||
|
|
0ce20fea8a | ||
|
|
46b24e8a27 | ||
|
|
66b96f417c | ||
|
|
b974395573 | ||
|
|
1057e70da0 | ||
|
|
1d7c058f08 | ||
|
|
36911830dd | ||
|
|
2fbee61fff | ||
|
|
76adf66390 | ||
|
|
c94e23b2f6 | ||
|
|
28f4e820f7 | ||
|
|
6f9829fa5e | ||
|
|
6d280193d6 | ||
|
|
bb8d1dbb3a | ||
|
|
f1d0d949dc | ||
|
|
efc8c74b9a | ||
|
|
5f2dc3fe14 | ||
|
|
05a87a441c | ||
|
|
9c5c609de2 | ||
|
|
ab3c603b1c | ||
|
|
be1efdbf89 | ||
|
|
960f681dec | ||
|
|
995468ea0a | ||
|
|
ecbd983648 | ||
|
|
2bda857bf7 | ||
|
|
6f3dd86f22 | ||
|
|
cc1da2eb5b | ||
|
|
cc9ffa5ac1 | ||
|
|
9cc62f6461 | ||
|
|
6ac10272bc | ||
|
|
19a080ddd7 | ||
|
|
fdec9012eb | ||
|
|
67c11acbbf | ||
|
|
a5ad1269ef | ||
|
|
958668f001 | ||
|
|
5acaa777b8 | ||
|
|
9bb1b64d48 | ||
|
|
cf0659f7af | ||
|
|
e158ab2fe9 | ||
|
|
5098302f2f | ||
|
|
e8ed258aa4 | ||
|
|
b4a674e0ac | ||
|
|
d4c439c61d | ||
|
|
9c683b7423 | ||
|
|
ca2069a246 | ||
|
|
07a40f5141 | ||
|
|
3b3674807b | ||
|
|
bbaf536f6a | ||
|
|
b50ecc25b2 | ||
|
|
f2ccbc81d9 | ||
|
|
5537e1ad17 | ||
|
|
0e89f839e1 | ||
|
|
131a8c8f53 | ||
|
|
603511ea6f | ||
|
|
ded7dae112 | ||
|
|
8c05e4677e | ||
|
|
73b389da6c | ||
|
|
09eeb42315 | ||
|
|
e05b6242a5 | ||
|
|
c3c38eeeaf | ||
|
|
6cdbd6903c | ||
|
|
503dbb3d8a | ||
|
|
35ca4404f0 | ||
|
|
ee0532702a | ||
|
|
44de97d496 | ||
|
|
9d1e203b3d | ||
|
|
cb59df7bed | ||
|
|
70d5cd0210 | ||
|
|
3c134b6549 | ||
|
|
511816a56d | ||
|
|
3ad6ed3e92 | ||
|
|
9144ad4883 | ||
|
|
00c2c1b70e | ||
|
|
307168cc0f | ||
|
|
58a42e51e2 | ||
|
|
5b34d11ce9 | ||
|
|
1dbc8e3f0e | ||
|
|
3d775d9286 | ||
|
|
faaef0fbe3 | ||
|
|
ff7f09ecc7 | ||
|
|
0a457907fe | ||
|
|
73b62ab0f6 | ||
|
|
0122a3ea08 | ||
|
|
c432265ab7 | ||
|
|
b773853b03 | ||
|
|
3d16691c9e | ||
|
|
770796275d | ||
|
|
a717d81cea | ||
|
|
ec6644c146 | ||
|
|
93fd179b4c | ||
|
|
a3803a3c93 | ||
|
|
489656458f | ||
|
|
30e9661919 | ||
|
|
3e48f862a7 | ||
|
|
722f92e834 | ||
|
|
d106797a26 | ||
|
|
6f9df58afe | ||
|
|
66498eee0b | ||
|
|
1f21ca187a | ||
|
|
c7df3b4b22 | ||
|
|
da010f1600 | ||
|
|
709e526ad9 | ||
|
|
cd788e2ab9 | ||
|
|
01f39a3e51 | ||
|
|
1622c57f07 | ||
|
|
a46999cf0d | ||
|
|
b34020d5a6 | ||
|
|
4f51ef7ab7 | ||
|
|
ec8a80b070 | ||
|
|
5192a1a054 | ||
|
|
7e79c52808 | ||
|
|
314877e155 | ||
|
|
da8f6a9acf | ||
|
|
e5059cb891 | ||
|
|
ebba5fd9af | ||
|
|
e6b464ed23 | ||
|
|
33faf463a0 | ||
|
|
ceb572a280 | ||
|
|
8ace87616e | ||
|
|
ffe885b21f | ||
|
|
b18913b338 | ||
|
|
fd9d8ca43b | ||
|
|
882411586a | ||
|
|
90a331f7a5 | ||
|
|
478474bcb1 | ||
|
|
19064660d2 | ||
|
|
0fe6d16e89 | ||
|
|
7ca96ea7e5 | ||
|
|
5f71712b8b | ||
|
|
6cbc92b760 | ||
|
|
286d0656e2 | ||
|
|
f34b684e0e | ||
|
|
f9226cd9cd | ||
|
|
7596de9ac8 | ||
|
|
5385ca0a0e | ||
|
|
f4b55b802c | ||
|
|
0d048dee56 | ||
|
|
6726488e48 | ||
|
|
3b64c4830f | ||
|
|
add7cf7ded | ||
|
|
6b55f06a23 | ||
|
|
2b5a352840 | ||
|
|
2a3fc7b8ea | ||
|
|
1511750650 | ||
|
|
cce37f8d32 | ||
|
|
69f5623a03 | ||
|
|
7567113e71 | ||
|
|
9c13bd8884 | ||
|
|
30a7162bd9 | ||
|
|
f85d0713cf | ||
|
|
64c9e859e0 | ||
|
|
ed360fcf57 | ||
|
|
c924d1a322 | ||
|
|
ce44c6ec41 | ||
|
|
459fda5e44 | ||
|
|
435e55958f | ||
|
|
0eca3cf384 | ||
|
|
b9604cde6c | ||
|
|
470f226d9d | ||
|
|
8a411edf9f | ||
|
|
243a3df832 | ||
|
|
90778ada6d | ||
|
|
7bf0c1bc45 | ||
|
|
f9aef7098f | ||
|
|
ba078042ba | ||
|
|
3534419f14 | ||
|
|
025ae183eb | ||
|
|
6534f4d668 | ||
|
|
0d9adb7294 | ||
|
|
d851db3cee | ||
|
|
a640df56e6 | ||
|
|
17563e2929 | ||
|
|
12bcd39583 | ||
|
|
e30e0c5135 | ||
|
|
d3f9887589 | ||
|
|
ca493a14e1 | ||
|
|
250c1d2068 | ||
|
|
65c3fe8b33 | ||
|
|
fe9255a816 | ||
|
|
0f3f7eee9a | ||
|
|
22411494aa | ||
|
|
fcf07fce61 | ||
|
|
87e84064d2 | ||
|
|
0134d2cc85 | ||
|
|
c984a64f3e | ||
|
|
f864caba2f | ||
|
|
0709926b82 | ||
|
|
8f86c8409d | ||
|
|
ef89a2709a | ||
|
|
c96b093a58 | ||
|
|
b54d2b2c38 | ||
|
|
50edb67fc4 | ||
|
|
776a66f5db | ||
|
|
8a7f4bcd7a | ||
|
|
8e0f9147b2 | ||
|
|
a84bb950fa | ||
|
|
e9ea9975de | ||
|
|
7a8ec5bea4 | ||
|
|
98533cbccc | ||
|
|
36a13f931a | ||
|
|
295ce9fc8d | ||
|
|
e7f819bed1 | ||
|
|
34e415222e | ||
|
|
d8a6763be4 | ||
|
|
2d232c4c57 | ||
|
|
1487d749fe | ||
|
|
74de37e81e | ||
|
|
ec6d3b535a | ||
|
|
698b0b090b | ||
|
|
a3d9d7b58b | ||
|
|
de51a91db3 | ||
|
|
97dd838cda | ||
|
|
02287658f7 | ||
|
|
083d9c8039 | ||
|
|
5ebb0b8c15 | ||
|
|
64d509a931 | ||
|
|
9cb2272494 | ||
|
|
d3f45d14b3 | ||
|
|
7ed519ba84 | ||
|
|
c512310934 | ||
|
|
e15b5a83d5 | ||
|
|
fec02c20a9 | ||
|
|
63702b9a78 | ||
|
|
a8fb88516a | ||
|
|
694cacc93d | ||
|
|
d2019972f7 | ||
|
|
f2ee5d3a80 | ||
|
|
43d7359221 | ||
|
|
ae07b8ee83 | ||
|
|
fcf76b36aa | ||
|
|
639438836b | ||
|
|
cbd5a0e6bb | ||
|
|
9cb145c44c | ||
|
|
4d7386fc5f | ||
|
|
8f591d1b71 | ||
|
|
e9c65d0c08 | ||
|
|
1b2dc7ef75 | ||
|
|
0f2bcccaba | ||
|
|
6cde9d87a3 | ||
|
|
61ff225f1d | ||
|
|
50edc08001 | ||
|
|
0b2a9dc297 | ||
|
|
f7b250f963 | ||
|
|
78641613c7 | ||
|
|
42034844dc | ||
|
|
d45addcc7a | ||
|
|
df9089d3f8 | ||
|
|
6938bb6109 | ||
|
|
5a2c606d94 | ||
|
|
a3d396b11b | ||
|
|
a1ffc320e4 | ||
|
|
512583709a | ||
|
|
13bca43aa8 | ||
|
|
d0037ea2fd | ||
|
|
6b09ce4336 | ||
|
|
584936aa9b | ||
|
|
672e3e49fb | ||
|
|
1d8f780f45 | ||
|
|
d3bcf405c2 | ||
|
|
426bf55df2 | ||
|
|
1bbf0d2cf6 | ||
|
|
8cfed866d3 | ||
|
|
852422f4ab | ||
|
|
528c513602 | ||
|
|
1cf4ea2eb3 | ||
|
|
70dfab8be0 | ||
|
|
f897350521 | ||
|
|
b5da1073b0 | ||
|
|
dc383a7ee7 | ||
|
|
09e0fc2074 | ||
|
|
940a5deb2e | ||
|
|
aacc5e108b | ||
|
|
1cf0d5ad9d | ||
|
|
9f726fce46 | ||
|
|
d051e2da43 | ||
|
|
94279f00c1 | ||
|
|
ef1f39d29e | ||
|
|
9c7ffa265e | ||
|
|
9cc3adbdd9 | ||
|
|
d42f7886ab | ||
|
|
e2b0f32c18 | ||
|
|
52f13283ea | ||
|
|
7d2624dd3c | ||
|
|
7ae1d61120 | ||
|
|
39c9375eef | ||
|
|
cdb1b1dba3 | ||
|
|
3d61f5f20e | ||
|
|
59859d8cc2 | ||
|
|
b285cd40b2 | ||
|
|
3415434e04 | ||
|
|
36a8fb3e4d | ||
|
|
a925c1b306 | ||
|
|
7f6b9ccb5b | ||
|
|
3cedced29a | ||
|
|
1d53342b18 | ||
|
|
1e87c2aa48 | ||
|
|
fbc5be2426 | ||
|
|
4b02c78aaa | ||
|
|
71e80e5f62 | ||
|
|
8b5bbe4673 | ||
|
|
c89cbd916d | ||
|
|
3c70509e9b | ||
|
|
e1112c64c9 | ||
|
|
8dec8d3632 | ||
|
|
722babe8d1 | ||
|
|
3e9c337946 | ||
|
|
2c0d0d836c | ||
|
|
dbbf64fdd4 | ||
|
|
1ccab64d86 | ||
|
|
4b234476bb | ||
|
|
6ce8fc0b15 | ||
|
|
9fca20acc1 | ||
|
|
eeb2ca5b26 | ||
|
|
4b4c55e328 | ||
|
|
3ee43dd572 | ||
|
|
a222dbe8c7 | ||
|
|
2ff5d7de53 | ||
|
|
c6aaaf438e | ||
|
|
fb0af47761 | ||
|
|
211afe3a4b | ||
|
|
ea1c68b666 | ||
|
|
82bf2663e3 | ||
|
|
638684636c | ||
|
|
3ec7218ffb | ||
|
|
96c7fb890e | ||
|
|
efd7427f33 | ||
|
|
b43c1f054b | ||
|
|
f8b04c4bb6 | ||
|
|
bb8b00dad8 | ||
|
|
8279f0eac5 | ||
|
|
61d1fd9a0e | ||
|
|
4f72330f5c | ||
|
|
3b6c8b3f77 | ||
|
|
a05ef35ca8 | ||
|
|
359430871f | ||
|
|
747a18f65d | ||
|
|
598d7963e5 | ||
|
|
484484ce89 | ||
|
|
6e15f28d6a | ||
|
|
b5d452b1c7 | ||
|
|
b46d67e301 | ||
|
|
3107d6d03b | ||
|
|
67af82457e | ||
|
|
2a16a0a30c | ||
|
|
b19cb95257 | ||
|
|
dc41c40eba | ||
|
|
71eafcf3da | ||
|
|
7555e69cdc | ||
|
|
284a5b3465 | ||
|
|
25d74e0334 | ||
|
|
c1c704c042 | ||
|
|
3f5277d57b | ||
|
|
98b59da9ad | ||
|
|
a8bbe997d2 | ||
|
|
893ed27f5b | ||
|
|
97c5b2b7d7 | ||
|
|
730ca5f9b1 | ||
|
|
7c35f68e29 | ||
|
|
79668f0624 | ||
|
|
4ba3ced42f | ||
|
|
21d31939d1 | ||
|
|
68e767078f | ||
|
|
ff9621e279 | ||
|
|
de20d2a179 | ||
|
|
6fb5ebfedb | ||
|
|
7132570353 | ||
|
|
92f6d077fd | ||
|
|
1498cc552f | ||
|
|
32bde5b009 | ||
|
|
af6016cfd0 | ||
|
|
f3d440a16f | ||
|
|
47b6495e9b | ||
|
|
7192fbfae7 | ||
|
|
be59053650 | ||
|
|
c36ec4f9d7 | ||
|
|
5191a04055 | ||
|
|
9ef542b3cb | ||
|
|
2414aeb4dd | ||
|
|
cd8bc46a15 | ||
|
|
b79b6aba5d | ||
|
|
fa308aa83b | ||
|
|
b90a103e22 | ||
|
|
0ddcb1f666 | ||
|
|
785ac43c84 | ||
|
|
7075b58ee1 | ||
|
|
a386f01a7c | ||
|
|
ce9e964c5f | ||
|
|
2524d2c413 | ||
|
|
687b0ebe6e | ||
|
|
8c232e1dbb | ||
|
|
bc2a510fb7 | ||
|
|
130c64e5d9 | ||
|
|
264bfb7121 | ||
|
|
d3b2cb19e4 | ||
|
|
e7ecf6accb | ||
|
|
4c06525432 | ||
|
|
bf5d593e71 | ||
|
|
29b7818ebf | ||
|
|
ce88c6dd08 | ||
|
|
1b05e77127 | ||
|
|
726d3cba43 | ||
|
|
b690dc13aa | ||
|
|
b0d28cedf7 | ||
|
|
b3f94c4c00 | ||
|
|
0753ca66ab | ||
|
|
e02fae664a | ||
|
|
2a75bbb711 | ||
|
|
9223055df1 | ||
|
|
4b0d26c93d | ||
|
|
0e90480d6b | ||
|
|
c30ff0935d | ||
|
|
200ae67551 | ||
|
|
89c55fe46c | ||
|
|
f997f9f139 | ||
|
|
0852f5a930 | ||
|
|
9e83daa3bb | ||
|
|
ea92b714f2 | ||
|
|
aa2bdcc078 | ||
|
|
7989800674 | ||
|
|
9d8952f3a8 | ||
|
|
51f004494a | ||
|
|
044aa4fa60 | ||
|
|
17e2416f68 | ||
|
|
8750f1c05f | ||
|
|
afab3c4151 | ||
|
|
3a2f0750cb | ||
|
|
4efa995ae1 | ||
|
|
f1330f7efd | ||
|
|
1e8ea5eece | ||
|
|
12a8e15227 | ||
|
|
a082f8d8c7 | ||
|
|
39c60235f8 | ||
|
|
f12928f700 | ||
|
|
8812409528 | ||
|
|
6406e07a79 | ||
|
|
6741234ec9 | ||
|
|
c0ef6a5d1b | ||
|
|
18b3da6bab | ||
|
|
fac46c078a | ||
|
|
21832436ec | ||
|
|
6c6bd28308 | ||
|
|
d298a73aab | ||
|
|
f82797006f | ||
|
|
6f0d8022d1 | ||
|
|
3edb8bfc21 | ||
|
|
f986561b62 | ||
|
|
d971478d75 | ||
|
|
b1718d715e | ||
|
|
674d81ce27 | ||
|
|
0d5dcf7358 | ||
|
|
653b86fa48 | ||
|
|
3461b2f5bb | ||
|
|
f2b52d46d0 | ||
|
|
d9359f8249 | ||
|
|
146469ab19 | ||
|
|
fa4ed416c7 | ||
|
|
7f2e23bb50 | ||
|
|
d97cc460b0 | ||
|
|
2bc6301e39 | ||
|
|
c07a37b91d | ||
|
|
94f3b5751a | ||
|
|
e42e998f76 | ||
|
|
5bf9b86aa4 | ||
|
|
1b37f94737 | ||
|
|
82a2a8b7eb | ||
|
|
359160d8a1 | ||
|
|
a1d8701369 | ||
|
|
b4ea3725da | ||
|
|
595049117c | ||
|
|
a51ca42b18 | ||
|
|
fa7454688b | ||
|
|
657056b114 | ||
|
|
16d9e65b32 | ||
|
|
9e21bc74ac | ||
|
|
0a103544e4 | ||
|
|
80904fddcf | ||
|
|
550785ba29 | ||
|
|
1f691912e1 | ||
|
|
bff0a94507 | ||
|
|
806bb3c63f | ||
|
|
534e78b372 | ||
|
|
4653b4bb79 | ||
|
|
e67f8a50f9 | ||
|
|
d260293f62 | ||
|
|
22b56f13cc | ||
|
|
6d799e9ff8 | ||
|
|
e141e7311c | ||
|
|
96e3d08787 | ||
|
|
b82aa22442 | ||
|
|
9d5fe279b6 | ||
|
|
231dbeea61 | ||
|
|
40ec19961c | ||
|
|
4cd13f4ebf | ||
|
|
5fafcdd73c | ||
|
|
7409bc052d | ||
|
|
8f73da1f79 | ||
|
|
4de0a2e30e | ||
|
|
32a11a2b20 | ||
|
|
a9d042db2c | ||
|
|
4160dfa6e1 | ||
|
|
b32c690175 | ||
|
|
064d7ffdb2 | ||
|
|
6a73e70663 | ||
|
|
5f68a5f70d | ||
|
|
ade75fecae | ||
|
|
43d758e630 | ||
|
|
0f111e2d3a | ||
|
|
a232d8e060 | ||
|
|
cf854246fa | ||
|
|
548d6bb6c0 | ||
|
|
6a0bc27b35 | ||
|
|
a303a83b92 | ||
|
|
e8c21dfe67 | ||
|
|
3439c08170 | ||
|
|
133748f004 | ||
|
|
35f3f86df4 | ||
|
|
462cfbe8ae | ||
|
|
38198d8cb3 | ||
|
|
500ebad7aa | ||
|
|
6de8d14b29 | ||
|
|
853ead07d4 | ||
|
|
8bfe5e86b4 | ||
|
|
ff976ce055 | ||
|
|
96abbad91d | ||
|
|
6023b736d9 | ||
|
|
066212158e | ||
|
|
2a9044d607 | ||
|
|
23eaf5c442 | ||
|
|
39a358ef56 | ||
|
|
f62061aa78 | ||
|
|
406e4283fd | ||
|
|
1f33e8b807 | ||
|
|
a23c89dd75 | ||
|
|
d1cb6a3aa9 | ||
|
|
d53b0d0643 | ||
|
|
a06b48ccc6 | ||
|
|
c278f09897 | ||
|
|
e08247218e | ||
|
|
84cbebcf17 | ||
|
|
d03dbf91a6 | ||
|
|
90594b5fc8 | ||
|
|
de6910a6b6 | ||
|
|
ce8778c01b | ||
|
|
6724dd1597 | ||
|
|
79500cdb9f | ||
|
|
0b8234edb4 | ||
|
|
b2a648b4da | ||
|
|
48496a930c | ||
|
|
43e312bd62 | ||
|
|
fb96473eb0 | ||
|
|
89c76a80f2 | ||
|
|
f285c61830 | ||
|
|
cc894e6100 | ||
|
|
e2ecedfa70 | ||
|
|
a1c6ac945d | ||
|
|
509e9a4d4e | ||
|
|
c28a51899f | ||
|
|
9028579d84 | ||
|
|
2cbef73a27 | ||
|
|
dbe3dea363 | ||
|
|
df987c2086 | ||
|
|
2655e5c7b9 | ||
|
|
52be37dd37 | ||
|
|
8a6dc0d0b4 | ||
|
|
7907a37002 | ||
|
|
4b26ec2372 | ||
|
|
2a31c91136 | ||
|
|
f49d75994e | ||
|
|
864fe70e35 | ||
|
|
98391c1324 | ||
|
|
e83acf8658 | ||
|
|
bac2215fb6 | ||
|
|
7cdb6d36f4 | ||
|
|
2671e3d9bb | ||
|
|
29571cfcb1 | ||
|
|
260072954e | ||
|
|
077975cba7 | ||
|
|
e1df8c9082 | ||
|
|
02f99cb631 | ||
|
|
ae4adad5c4 | ||
|
|
cf4825233d | ||
|
|
82e18770bc | ||
|
|
0dd66bd2e9 | ||
|
|
8baa1ed52e | ||
|
|
ba3b53d64a | ||
|
|
02858c574c | ||
|
|
1e4b334321 | ||
|
|
9a7374faf0 | ||
|
|
3f69c1b62d | ||
|
|
4bef006566 | ||
|
|
860f35a7ab | ||
|
|
9bd6034f9b | ||
|
|
694058ccb1 | ||
|
|
78602e0966 | ||
|
|
1a225306f8 | ||
|
|
2c9585e9f6 | ||
|
|
bc06fe3b51 | ||
|
|
5bb289262e | ||
|
|
8c339b9d63 | ||
|
|
904027f25f | ||
|
|
0068b8c823 | ||
|
|
d3ab1d50b5 | ||
|
|
9c2f131b66 | ||
|
|
1e3c163233 | ||
|
|
28d980de3d | ||
|
|
e2dddf3532 | ||
|
|
12934e17e6 | ||
|
|
87f28fa6dd | ||
|
|
83344af1c2 | ||
|
|
c7f703c476 | ||
|
|
48748b8f9a | ||
|
|
c33c9283f1 | ||
|
|
0cadef62c1 | ||
|
|
fc7311e94c | ||
|
|
068fd1d839 | ||
|
|
81cf763a97 | ||
|
|
2ad3e1428d | ||
|
|
9286665be5 | ||
|
|
c7f175309d | ||
|
|
917f50e737 | ||
|
|
15ba1fe530 | ||
|
|
ccf510188f | ||
|
|
eb97ef73fa | ||
|
|
8dbbc0e72b | ||
|
|
695422d698 | ||
|
|
c0eb1e6bfe | ||
|
|
32e131862d | ||
|
|
1c838758c3 | ||
|
|
f5c3a23a75 | ||
|
|
cf036062c4 | ||
|
|
c5deb0a325 | ||
|
|
aa4f316c14 | ||
|
|
b53e81786a | ||
|
|
80f23eb97d | ||
|
|
e7f46a4251 | ||
|
|
39f0e4b207 | ||
|
|
1b3e733e1c | ||
|
|
78e57f29bc | ||
|
|
1d02548e4a | ||
|
|
2078c0d1bf | ||
|
|
662e7238ef | ||
|
|
8face6c67c | ||
|
|
f2bb840936 | ||
|
|
01d62f822d | ||
|
|
0efa5c562a | ||
|
|
785da17231 | ||
|
|
a9b3a77cda | ||
|
|
e60848a65f | ||
|
|
1455d0211b | ||
|
|
1499f1e480 | ||
|
|
dbe6828978 | ||
|
|
4fa609e2be | ||
|
|
8d80f9c624 | ||
|
|
e26d9ae75e | ||
|
|
92aba71fb5 | ||
|
|
4393076c6c | ||
|
|
6a6814379f | ||
|
|
c23ffc045d | ||
|
|
8abe6ccb64 | ||
|
|
4718c784af | ||
|
|
616e31f795 | ||
|
|
dd96991005 | ||
|
|
fa0c31b864 | ||
|
|
a7154d73fe | ||
|
|
de08da1003 | ||
|
|
c6fb650a62 | ||
|
|
821643f30b | ||
|
|
3d40b1c03f | ||
|
|
e993855421 | ||
|
|
8a8b2d0684 | ||
|
|
94fe1c8b26 | ||
|
|
5f23eba1b0 | ||
|
|
036cb819d6 | ||
|
|
94da5ac1e8 | ||
|
|
e2db31c94b |
1
.cleancount
Normal file
1
.cleancount
Normal file
@@ -0,0 +1 @@
|
||||
8
|
||||
@@ -1,5 +0,0 @@
|
||||
asterisk
|
||||
build.h
|
||||
ast_expr.c
|
||||
.version
|
||||
.depend
|
||||
1
.lastclean
Normal file
1
.lastclean
Normal file
@@ -0,0 +1 @@
|
||||
8
|
||||
18
BUGS
Executable file → Normal file
18
BUGS
Executable file → Normal file
@@ -1,18 +1,22 @@
|
||||
Asterisk Bug Tracking Information
|
||||
=================================
|
||||
|
||||
To learn about and report Asterisk bugs or make feature
|
||||
requests, please visit the official Asterisk Bug Tracker
|
||||
at:
|
||||
To learn about and report Asterisk bugs, please visit
|
||||
the official Asterisk Bug Tracker at:
|
||||
|
||||
http://bugs.digium.com
|
||||
|
||||
For more information on using the bug tracker, or to
|
||||
learn how you can contribute by acting as a bug marshal
|
||||
learn how you can contribute by acting as a bug marshall
|
||||
please see:
|
||||
|
||||
http://www.digium.com/bugtracker.html
|
||||
http://www.digium.com/index.php?menu=bugguidelines
|
||||
|
||||
If you would like to submit a feature request, please
|
||||
resist the temptation to post it to the bug tracker.
|
||||
Feature requests should be posted to the asterisk-dev
|
||||
mailing list, located at:
|
||||
|
||||
http://lists.digium.com
|
||||
|
||||
Thank you!
|
||||
|
||||
Mark
|
||||
|
||||
460
CHANGES
Executable file → Normal file
460
CHANGES
Executable file → Normal file
@@ -1,333 +1,127 @@
|
||||
Asterisk 0.7.1
|
||||
-- Fixed timed include context's and GotoIfTime
|
||||
-- Fixed chan_h323 it now gets remote ip properly instead of 127.0.0.1
|
||||
Asterisk 0.7.0
|
||||
-- Removed MP3 format and codec
|
||||
-- Can now load and unload SIP,IAX,IAX2,H323 channels without core
|
||||
-- Fixed various compiler warnings and clean up source tree
|
||||
-- Preliminary AES Support
|
||||
-- Fix SIP REINVITE
|
||||
-- Outbound SIP registration behind NAT using externip
|
||||
-- More CLI documentation and clean up
|
||||
-- Pin numbers on MeeMe
|
||||
-- Dynamic MeetMe conferences are more consistent with static conferences
|
||||
-- Added channel variables ${HANGUPCAUSE}, ${SIPDOMAIN}, ${TIMESTAMP}, ${ACCONTCODE}
|
||||
-- ODBC support for logging CDRs
|
||||
-- Indications for Norway and New Zeland
|
||||
-- Major redesign of app_voicemail
|
||||
-- Syslog support
|
||||
-- Reload logfiles with CLI command 'logger reload' and rotate logs with "logger rotate'
|
||||
-- Configurable DEBUG, NOTICE, WARNING, ERROR and ast_verbose messages now appear on remote console
|
||||
-- Properly reaping any zombie processes
|
||||
-- Added applications SayUnixTime, SetCDRUserField, HasNewVoicemail, ZapScan, Random, ResetCDR, NoCDR
|
||||
-- Make PRI Hangup Cause available to the dialplan
|
||||
-- Verify included contexts in extensions.conf
|
||||
-- Add DESTDIR support for building RPMs and packages
|
||||
-- Do route lookups on OpenBSD
|
||||
-- Add support for building on FreeBSD and OS X
|
||||
-- Add support for PostgreSQL in Voicemail
|
||||
-- Translate SIP hangup cause to PRI hangup cause where needed
|
||||
-- Better support for MOH in IAX2
|
||||
-- Fix SIP problem where channels were not removed on BYE
|
||||
-- Display codecs by name
|
||||
-- Remove MySQL and put PGSql instead for licensing reasons
|
||||
-- Better capability matching in SIP
|
||||
-- Full IBR4 compliance for chan_zap
|
||||
-- More flexible CDR handling
|
||||
-- Distinguish between BUSY and FAILURE on outbound calls
|
||||
-- Add initial support for SCCP via chan_skinny
|
||||
-- Better support for Future Group B signaling
|
||||
Asterisk 0.5.0
|
||||
-- Retain IAX2 and SIP registrations past shutdown/crash and restart
|
||||
-- True data mode bridging when possible
|
||||
-- H.323 build improvements
|
||||
-- Agent Callback-login support
|
||||
-- RFC2833 Improvements
|
||||
-- Add thread debugging
|
||||
-- Add optional pedantic SIP checking for Pingtel
|
||||
-- Allow extension names, include context, switch to use global vars.
|
||||
-- Allow variables in extensions.conf to reference previously defined ones
|
||||
-- Merge voicemail enhancements (app_voicemail2)
|
||||
-- Add multiple queueing strategies
|
||||
-- Merge support for 'T'
|
||||
-- Allow pending agent calling (Agent/:1)
|
||||
-- Add groupings to agents.conf
|
||||
-- Add video support to IAX2
|
||||
-- Zaptel optimize playback
|
||||
-- Add video support to SIP
|
||||
-- Make RTP ports configurable
|
||||
-- Add RDNIS support to SIP and IAX2
|
||||
-- Add transfer app (implement in SIP and IAX2)
|
||||
-- Make voicemail segmentable by context (app_voicemail2)
|
||||
-- Major restructuring of voicemail (app_voicemail2)
|
||||
-- Add initial ENUM support
|
||||
-- Add malloc debugging support
|
||||
-- Add preliminary Voicetronix support
|
||||
-- Add iLBC codec
|
||||
Asterisk 0.4.0
|
||||
-- Merge and edit Nick's FXO dial support
|
||||
-- Reengineer SIP registration (outbound)
|
||||
-- Support call pickup on SIP and compatibly with ZAP
|
||||
-- Support 302 Redirect on SIP
|
||||
-- Management interface improvements
|
||||
-- Add "hint" support
|
||||
-- Improve call forwarding using new "Local" channel driver.
|
||||
-- Add "Local" channel
|
||||
-- Substantial SIP enhancements including retransmissions
|
||||
-- Enforce case sensitivity on extension/context names
|
||||
-- Add monitor support (Thanks, Mahmut)
|
||||
-- Add experimental "trunk" option to IAX2 for high density VoIP
|
||||
-- Add experimental "debug channel" command
|
||||
-- Add 'C' flag to dial command to reset call detail record (handy for calling cards)
|
||||
-- Add NAT and dynamic support to MGCP
|
||||
-- Allow selection of in-band, out-of-band, or INFO based DTMF
|
||||
-- Add contributed "*80" support to blacklist numbers (Thanks James!)
|
||||
-- Add "NAT" option to sip user, peer, friend
|
||||
-- Add experimental "IAX2" protocol
|
||||
-- Change special variable "EXTEN-n" to "EXTEN:n" to follow Bash syntax
|
||||
-- Add "Enhanced" AGI with audio pass-through (voice recognition anyone?)
|
||||
-- Choose best priority from codec from allow/disallow
|
||||
-- Reject SIP calls to self
|
||||
-- Allow SIP registration to provide an alternative contact
|
||||
-- Make HOLD on SIP make use of asterisk MOH
|
||||
-- Add supervised transfer (tested with Pingtel only)
|
||||
-- Allow maxexpirey and defaultexpirey to be runtime configurable for SIP
|
||||
-- Preliminary codec 13 support (RFC3389)
|
||||
-- Add app_authenticate for general purpose authentication
|
||||
-- Optimize RTP and smoother
|
||||
-- Create special variable "EXTEN-n" where it is extension stripped by n MSD
|
||||
-- Fix uninitialized frame pointer in channel.c
|
||||
-- Add global variables support under [globals] of extensions.conf
|
||||
-- Add macro support (show application Macro)
|
||||
-- Allow [123-5] etc in extensions
|
||||
-- Allow format of App(arg1,arg2,...) instead of just App,arg1|arg2 in dialplan
|
||||
-- Add message waiting indicator to SIP
|
||||
-- Fix double free bug in channel.c
|
||||
Asterisk 0.3.0
|
||||
-- Add fastfoward, rewind, seek, and truncate functions to streams
|
||||
-- Support registration
|
||||
-- Add G729 format
|
||||
-- Permit applications to return a digit indicating new extension
|
||||
-- Change "SHUTDOWN" to "STOP" in commands
|
||||
-- SIP "Hold" fixes and VXML URI support
|
||||
-- New chan_zap with 160 sample chunk size
|
||||
-- Add DTMF, MF, and Fax tone detector to dsp routines
|
||||
-- Allow overlap dialing (inbound) on PRI
|
||||
-- Enable tone detection with PRI
|
||||
-- Add special information tone detection
|
||||
-- Add Asterisk DB support
|
||||
-- Add pulse dialing
|
||||
-- Re-record all system prompts
|
||||
-- Change "timelen" to samples for better accuracy
|
||||
-- Move to editline, eliminating readline dependency
|
||||
-- Add peer "poke" support to SIP and IAX
|
||||
-- Add experimental call progress detection
|
||||
-- Add SIP authentication (digest)
|
||||
-- Add RDNIS
|
||||
-- Reroute faxes to "fax" extension
|
||||
-- Create ISDN/modem group concept
|
||||
-- Centralize indication
|
||||
-- Add initial MGCP support
|
||||
-- SIP debugging cleanup
|
||||
-- SIP reload
|
||||
-- SIP commands (show channels, etc)
|
||||
-- Add optional busy detection
|
||||
-- Add Visual Message Waiting Indicator (MDMF and SDMF)
|
||||
-- Add ambiguous extension matching
|
||||
-- Add *69
|
||||
-- Major SIP enhancements from SIPit
|
||||
-- Rewrite of ZAP CLASS features using subchannels
|
||||
-- Enhanced call parking
|
||||
-- Add extended outgoing spool support (pbx_spool)
|
||||
Asterisk 0.2.0
|
||||
-- Outbound origination API
|
||||
-- Call management improvements
|
||||
-- Add Do Not Disturb (*78, *79)
|
||||
-- Add agents
|
||||
-- Document variables
|
||||
-- Add transfer capability on the console
|
||||
-- Add SpeeX codec translator
|
||||
-- Add call queues
|
||||
-- Add setcallerid functionality (AGI, application)
|
||||
-- Add special variables ${CALLERID}, ${EXTEN}, ${CONTEXT}, ${PRIORITY}
|
||||
-- Don't echo cancel on pure TDM connections by default
|
||||
-- Implement Async GOTO
|
||||
-- Differentiate softhangups
|
||||
-- Add date/time
|
||||
Asterisk 0.1.12
|
||||
-- Fix for Big Endian machines
|
||||
-- MySQL CDR Engine
|
||||
-- Various SIP fixes and enhancements
|
||||
-- Add "zapateller application and arbitrary tone pairs
|
||||
-- Don't always start at "s"
|
||||
-- Separate linear mode for pseudo and real
|
||||
-- Add initial RTP and SIP support (no jitter buffer yet, unknown stability)
|
||||
-- Add 'h' extension, executed on hangup
|
||||
-- Add duration timer to message info
|
||||
-- Add web based voicemail checking ("make webvmail")
|
||||
-- Add ast_queue_frame function and eliminate frame pipes in most drivers
|
||||
-- Centralize host access (and possibly future ACL's)
|
||||
-- Add Caller*ID on PhoneJack (Thanks Nathan)
|
||||
-- Add "safe_asterisk" wrapper script to auto-restart Asterisk
|
||||
-- Indicate ringback on chan_phone
|
||||
-- Add answer confirmation (press '#' to confirm answer)
|
||||
-- Add distinctive ring support (e.g. Dial,Zap/4r2)
|
||||
-- Add ANSI/vt100 color support
|
||||
-- Make parking configurable through parking.conf
|
||||
-- Fix the empty voicemail problem
|
||||
-- Add Music On Hold
|
||||
-- Add ADSI Compiler (app_adsiprog)
|
||||
-- Extensive DISA re-work to improve tone generation
|
||||
-- Reset all idle channels every 10 minutes on a PRI
|
||||
-- Reset channels which are hungup with "channel in use"
|
||||
-- Implement VNAK support in chan_iax
|
||||
-- Fix chan_oss to support proper hangups and autoanswer
|
||||
-- Make shutdown properly hangup channels
|
||||
-- Add idling capability to chan_zap for idle-net
|
||||
-- Add "MeetMe" conferencing app (app_meetme)
|
||||
-- Add timing information to include
|
||||
Asterisk 0.1.11
|
||||
-- Add ISDN RAS capability
|
||||
-- Add stutter dialtone to Chan Zap
|
||||
-- Add "#include" capability to config files.
|
||||
-- Add call-forward variable to Chan Zap (*72, *73)
|
||||
-- Optimize IAX flow when transfer isn't possible
|
||||
-- Allow transmission of ANI over IAX
|
||||
Asterisk 0.1.10
|
||||
-- Make ast_readstring parameter be the max # of digits, not the max size with \0
|
||||
-- Make up any missing messages on the fly
|
||||
-- Add support for specific DTMF interruption to saying numbers
|
||||
-- Add new "u" and "b" options to condense busy/unavail handling
|
||||
-- Add support for RSA authentication on IAX calls
|
||||
-- Add support for ADSI compatible CPE
|
||||
-- Outgoing call queue
|
||||
-- Remote dialplan fixes for Quicknet
|
||||
-- Added AGI commands supporting TDD functions (RECEIVE CHAR & TDD MODE)
|
||||
-- Added TDD support (send/receive text in chan_zap)
|
||||
-- Fix all strncpy references
|
||||
-- Implement CSV CDR backend
|
||||
-- Implement Call Detail Records
|
||||
Asterisk 0.1.9
|
||||
-- Implement IAX quelching
|
||||
-- Allow Caller*ID to be overridden and suggested
|
||||
-- Configure defaults to use IAXTEL
|
||||
-- Allow remote dialplan polling via IAX
|
||||
-- Eliminate ast_longest_extension
|
||||
-- Implement dialplan request/reply
|
||||
-- Let peers have allow/disallow for codecs
|
||||
-- Change allow/deny to permit/deny in IAX
|
||||
-- Allow dialplan entries to match Caller*ID as well
|
||||
-- Added AGI (Asterisk Gateway Interface) scripting interface (app_agi)
|
||||
-- Added chan_zap for zapata telephony kernel interface, removed chan_tor
|
||||
-- Add convenience functions
|
||||
-- Fix race condition in channel hangup
|
||||
-- Fix memory leaks in both asterisk and iax frame allocations
|
||||
-- Add "iax show stats" command and -DTRACE_FRAMES (for frame tracing)
|
||||
-- Add DISA application (Thanks to Jim Dixon)
|
||||
-- Add IAX transfer support
|
||||
-- Add URL and HTML transmission
|
||||
-- Add application for sending images
|
||||
-- Add RedHat RPM spec file and build capability
|
||||
-- Fix GSM WAV file format bug
|
||||
-- Move ignorepat to main dialplan
|
||||
-- Add ability to specificy TOS bits in IAX
|
||||
-- Allow username:password in IAX strings
|
||||
-- Updates to PhoneJack interface
|
||||
-- Allow "servermail" in voicemail.conf to override e-mail in "from" line
|
||||
-- Add 'skip' option to app_playback
|
||||
-- Reject IAX calls on unknown extensions
|
||||
-- Fix version stuff
|
||||
Asterisk 0.1.8
|
||||
-- Keep track of version information
|
||||
-- Add -f to cause Asterisk not to fork
|
||||
-- Keep important information in voicemail .txt file
|
||||
-- Adtran Voice over Frame Relay updates
|
||||
-- Implement option setting/querying of channel drivers
|
||||
-- IAX performance improvements and protocol fixes
|
||||
-- Substantial enhancement of console channel driver
|
||||
-- Add IAX registration. Now IAX can dynamically register
|
||||
-- Add flash-hook transfer on tormenta channels
|
||||
-- Added Three Way Calling on tormenta channels
|
||||
-- Start on concept of zombie channel
|
||||
-- Add Call Waiting CallerID
|
||||
-- Keep track of who registeres contexts, includes, and extensions
|
||||
-- Added Call Waiting(tm), *67, *70, and *82 codes
|
||||
-- Move parked calls into "parkedcalls" context by default
|
||||
-- Allow dialplan to be displayed
|
||||
-- Allow "=>" instead of just "=" to make instantiation clearer
|
||||
-- Asterisk forks if called with no arguments
|
||||
-- Add remote control by running asterisk -vvvc
|
||||
-- Adjust verboseness with "set verbose" now
|
||||
-- No longer requires libaudiofile
|
||||
-- Install beep
|
||||
-- Make PBX Config module reload extensions on SIGHUP
|
||||
-- Allow modules to be reloaded when SIGHUP is received
|
||||
-- Variables now contain line numbers
|
||||
-- Make dialer send in band signalling
|
||||
-- Add record application
|
||||
-- Added PRI signalling to Tormenta driver
|
||||
-- Allow use of BYEXTENSION in "Goto"
|
||||
-- Allow adjustment of gains on tormenta channels
|
||||
-- Added raw PCM file format support
|
||||
-- Add U-law translator
|
||||
-- Fix DTMF handling in bridge code
|
||||
-- Fix access control with IAX
|
||||
* Asterisk 0.1.7
|
||||
-- Update configuration files and add some missing sounds
|
||||
-- Added ability to include one context in another
|
||||
-- Rewrite of PBX switching
|
||||
-- Major mods to dialler application
|
||||
-- Added Caller*ID spill reception
|
||||
-- Added Dialogic VOX file format support
|
||||
-- Added ADPCM Codec
|
||||
-- Add Tormenta driver (RBS signalling)
|
||||
-- Add Caller*ID spill creation
|
||||
-- Rewrite of translation layer entirely
|
||||
-- Add ability to run PBX without additional thread
|
||||
* Asterisk 0.1.6
|
||||
-- Make app_dial handle a lack of translators smoothly
|
||||
-- Add ISDN4Linux support -- dtmf is weird...
|
||||
-- Minor bug fixes
|
||||
* Asterisk 0.1.5
|
||||
-- Fix a small mistake in IAX
|
||||
-- Fix the QuickNet driver to work with newer cards
|
||||
* Asterisk 0.1.4
|
||||
-- Update VoFR some more
|
||||
-- Fix the QuickNet driver to work with LineJack
|
||||
-- Add ability to pass images for IAX.
|
||||
* Asterisk 0.1.3
|
||||
-- Update VoFR for latest sangoma code
|
||||
-- Update QuickNet Driver
|
||||
-- Add text message handling
|
||||
-- Fix transfers to use "default" if not in current context
|
||||
-- Add call parking
|
||||
-- Improve format/content negotiation
|
||||
-- Added support for multiple languages
|
||||
-- Bug fixes, as always...
|
||||
* Asterisk 0.1.2
|
||||
-- Updated README file with a "Getting Started" section
|
||||
-- Added sample sounds and configuration files.
|
||||
-- Added LPC10 very low bandwidth (low quality) compression
|
||||
-- Enhanced translation selection mechanism.
|
||||
-- Enhanced IAX jitter buffer, improved reliability
|
||||
-- Support echo cancelation on PhoneJack
|
||||
-- Updated PhoneJack driver to std. Telephony interface
|
||||
-- Added app_echo for evaluating VoIP latency
|
||||
-- Added app_system to execute arbitrary programs
|
||||
-- Updated sample configuration files
|
||||
-- Added OSS channel driver (full duplex only)
|
||||
-- Added IAX implementation
|
||||
-- Fixed some deadlocks.
|
||||
-- A whole bunch of bug fixes
|
||||
* Asterisk 0.1.1
|
||||
-- Revised translator, fixed some general race conditions throughout *
|
||||
-- Made dialer somewhat more aware of incompatible voice channels
|
||||
-- Added Voice Modem driver and A/Open Modem Driver stub
|
||||
-- Added MP3 decoder channel
|
||||
-- Added Microsoft WAV49 support
|
||||
-- Revised License -- Pure GPL, nothing else
|
||||
-- Modified Copyright statement since code is still currently owned by author
|
||||
-- Added RAW GSM headerless data format
|
||||
-- Innumerable bug fixes
|
||||
* Asterisk 0.1.0
|
||||
-- Initial Release
|
||||
Changes since Asterisk 1.2.0-beta2:
|
||||
|
||||
* Cygwin build system portability
|
||||
* Optional generation of outbound silence during channel recording
|
||||
|
||||
Changes since Asterisk 1.2.0-beta1:
|
||||
|
||||
* Many, many bug fixes
|
||||
* Documentation and sample configuration updates
|
||||
* Vastly improved presence/subscription support in the SIP channel driver
|
||||
* A new (experimental) mISDN channel driver
|
||||
* A new monitoring application (MixMonitor)
|
||||
* More portability fixes for non-Linux platforms
|
||||
* New dialplan functions replacing old applications
|
||||
* Significant deadlock and performance upgrades for the Manager interface
|
||||
* An upgrade to the 'new' dialplan expression parser for all users
|
||||
* New Zaptel echo cancellers with improved performance
|
||||
* Support for the latest OSP toolkit from TransNexus
|
||||
* Support user-controlled volume adjustment in MeetMe application
|
||||
* More dialplan applications now return status variables instead of priority jumping
|
||||
* Much more powerful ENUM support in the dialplan
|
||||
* SIP domain support for authentication and virtual hosting
|
||||
* Many PRI protocol updates and fixes, including more complete Q.SIG support
|
||||
* New applications: Pickup() and Page()
|
||||
|
||||
Changes since Asterisk 1.0:
|
||||
|
||||
This list currently only containts changes made from the end of November until
|
||||
March 26, 2005.
|
||||
|
||||
* Add new applications:
|
||||
-- AgentMonitorOutgoing
|
||||
-- Curl
|
||||
-- ExecIf
|
||||
-- ExecIfTime
|
||||
-- IAX2Provision
|
||||
-- MacroExit
|
||||
-- MacroIf
|
||||
-- PauseQueueMember
|
||||
-- ReadFile
|
||||
-- SetRDNIS
|
||||
-- SIPAddHeader
|
||||
-- SIPGetHeader
|
||||
-- StartMusicOnHold
|
||||
-- StopMusicOnHold
|
||||
-- UnpauseQueueMember
|
||||
-- WaitForSilence
|
||||
-- While / EndWhile
|
||||
* app Answer
|
||||
-- added delay option
|
||||
* app ChanIsAvail
|
||||
-- added 's' option
|
||||
* app Dial
|
||||
-- add option to specify the class for musiconhold with m option
|
||||
* app EnumLookup
|
||||
-- added "reload enum" for configuration
|
||||
* app Goto
|
||||
-- added relative priorities
|
||||
* app GotoIf
|
||||
-- added relative priorities
|
||||
* app MeetMe
|
||||
-- added 'i' option
|
||||
-- added 'r' option
|
||||
-- added 'T' option
|
||||
-- added 'P' option
|
||||
-- added 'c' option
|
||||
-- added adminpin to meetme.conf
|
||||
-- added reload command
|
||||
* app PrivacyManager
|
||||
-- add config file privacy.conf
|
||||
* app queue
|
||||
-- queues.conf
|
||||
-- added persistentmembers option to queues.conf
|
||||
-- changed music option to musiconhold
|
||||
-- added weight option
|
||||
-- added note about why agent groups probably shouldn't be used
|
||||
-- added timeoutrestart option
|
||||
* app Read
|
||||
-- added attempts parameter
|
||||
-- added timeout parameter
|
||||
* app Record
|
||||
-- added 'q' option
|
||||
* app SendDTMF
|
||||
-- add timeout option
|
||||
* app SMS
|
||||
-- document alternative syntax for queueing messages
|
||||
* app Voicemail
|
||||
-- add info about VM_CATEGORY
|
||||
-- voicemail.conf
|
||||
-- added usedirectory option
|
||||
-- added VM_CIDNUM and VM_CIDNAME in message config
|
||||
* chan IAX2
|
||||
-- new jitterbuffer
|
||||
-- added setvar option
|
||||
-- added regex to iax2 show peers/users
|
||||
-- allow multiple bindaddr lines in iax.conf
|
||||
-- added reload command
|
||||
-- added forcejitterbuffer option
|
||||
-- added note about specifying bindport before bindaddr
|
||||
-- added trunktimestamps option
|
||||
* chan Agent
|
||||
-- added agent logoff CLI command
|
||||
* chan OSS
|
||||
-- added Flash CLI command
|
||||
* chan SIP
|
||||
-- added setvar option
|
||||
-- added compactheaders option
|
||||
-- added usereqphone option
|
||||
-- added registertimeout option
|
||||
-- added externhost option
|
||||
-- added sip notify CLI command
|
||||
-- added sip_notify.conf
|
||||
-- added allowguest option
|
||||
* chan Zap
|
||||
-- added hanguponplarityswitch option
|
||||
-- added sendcalleridafter option
|
||||
-- added priresetinterval option
|
||||
-- added TON/NPI config options (the ones right above the resetinterval option)
|
||||
-- added answeronpolarityswitch option
|
||||
-- added "never" for resetinterval
|
||||
* extensions
|
||||
-- allow '*' when including files (#include "sip-*.conf")
|
||||
-- added eswitch
|
||||
* General
|
||||
-- added #exec syntax for including output from a command
|
||||
-- added show features CLI command
|
||||
-- added configuration templates for category inheritance
|
||||
|
||||
341
COPYING
Normal file
341
COPYING
Normal file
@@ -0,0 +1,341 @@
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
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 Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
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.
|
||||
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
|
||||
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
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
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
|
||||
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
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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,
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
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
|
||||
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
|
||||
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
|
||||
programs whose distribution conditions are different, write to the author
|
||||
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
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
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
|
||||
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
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
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.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) 19yy <name of author>
|
||||
|
||||
This program 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.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
|
||||
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) 19yy 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 Library General
|
||||
Public License instead of this License.
|
||||
57
CREDITS
Executable file → Normal file
57
CREDITS
Executable file → Normal file
@@ -1,10 +1,12 @@
|
||||
|
||||
=== DEVELOPMENT SUPPORT ===
|
||||
I'd like to thank the following companies for helping fund development of
|
||||
We'd like to thank the following companies for helping fund development of
|
||||
Asterisk:
|
||||
|
||||
Pilosoft, Inc. - for supporting ADSI development in Asterisk
|
||||
|
||||
Asterlink, Inc. - for supporting broad Asterisk development
|
||||
|
||||
GFS - for supporting ALSA development
|
||||
|
||||
Telesthetic - for supporting SIP development
|
||||
@@ -12,6 +14,7 @@ Telesthetic - for supporting SIP development
|
||||
Christos Ricudis - for substantial code contributions
|
||||
|
||||
Paul Bagyenda, Digital Solutions - for initial Voicetronix driver development
|
||||
|
||||
=== WISHLIST CONTRIBUTERS ===
|
||||
Jeremy McNamara - SpeeX support
|
||||
Nick Seraphin - RDNIS support
|
||||
@@ -23,44 +26,70 @@ Wasim - Hangup detect
|
||||
PhoneJack and Linejack card to the project. (http://www.quicknet.net)
|
||||
|
||||
=== MISCELLANEOUS PATCHES ===
|
||||
Jim Dixon - Zapata Telephony and app_rpt
|
||||
http://www.zapatatelephony.org/app_rpt.html
|
||||
Russell Bryant - Asterisk 1.0 maintainer and misc. enhancements
|
||||
russelb@clemson.edu
|
||||
Anthony Minessale II - Countless big and small fixes, and relentless forward push
|
||||
anthmct@yahoo.com http://www.asterlink.com
|
||||
James Golovich - Innumerable contributions
|
||||
You can find him and asterisk-perl at http://asterisk.gnuinter.net
|
||||
You can find him and asterisk-perl at http://asterisk.gnuinter.net
|
||||
Andre Bierwirth - Extension hints and status
|
||||
Oliver Daudey - ISDN4Linux fixes
|
||||
Pauline Middelink - ISDN4Linux patches and some general patches.
|
||||
She can be found at http://www.polyware.nl/~middelink/En/
|
||||
She can be found at http://www.polyware.nl/~middelink/En/
|
||||
Jean-Denis Girard - Various contributions from the South Pacific Islands
|
||||
jd-girard@esoft.pf http://www.esoft.pf
|
||||
William Jordan / Vonage - MySQL enhancmenets to Voicemail
|
||||
jd-girard@esoft.pf http://www.esoft.pf
|
||||
William Jordan / Vonage - MySQL enhancements to Voicemail
|
||||
wjordan@vonage.com
|
||||
Jac Kersing - Various fixes
|
||||
Steven Critchfield - Seek and Trunc functions for playback and recording
|
||||
critch@basesys.com
|
||||
critch@basesys.com
|
||||
Jefferson Noxon - app_lookupcidname, app_db, and various other contributions
|
||||
Klaus-Peter Junghanns - in-band DTMF on SIP and MGCP
|
||||
Ross Finlayson - Dynamic RTP payload support
|
||||
Mahmut Fettahlioglu - Audio recording, music-on-hold changes, alaw file
|
||||
format, and various fixes. Can be contacted at mahmut@oa.com.au
|
||||
format, and various fixes. Can be contacted at mahmut@oa.com.au
|
||||
James Dennis - Cisco SIP compatibility patches to work with SIP service
|
||||
providers. Can be contacted at asterisk@jdennis.net
|
||||
Tilghman Lesher - - Route lookup code; ast_localtime(), ast_say_date_with_format();
|
||||
GotoIfTime, Random, SayUnixTime, HasNewVoicemail, and Cut applications,
|
||||
along with various other patches. http://asterisk.drunkcoder.com/
|
||||
providers. Can be contacted at asterisk@jdennis.net
|
||||
Tilghman Lesher - ast_localtime(); ast_say_date_with_format();
|
||||
GotoIfTime, Random, SayUnixTime, HasNewVoicemail applications;
|
||||
CUT, SORT, EVAL, CURL, FIELDQTY, STRFTIME, QUEUEAGENT* functions;
|
||||
and other innumerable bug fixes. http://asterisk.drunkcoder.com/
|
||||
Jayson Vantuyl - Manager protocol changes, various other bugs.
|
||||
jvantuyl@computingedge.net
|
||||
Thorsten Lockert - OpenBSD, FreeBSD ports, making MacOS X port run on 10.3,
|
||||
dialplan include verification, route lookup on OpenBSD, various other
|
||||
bugs. tholo@sigmasoft.com
|
||||
Brian West - ODBC support and Bug Marshaling
|
||||
Josh Roberson - chan_zap reload support, Advanced Voicemail Features, other misc. patches,
|
||||
and Bug Marshalling. - josh@asteriasgi.com, http://www.asteriasgi.com
|
||||
William Waites - syslog support, SIP NAT traversal for SIP-UA. ww@styx.org
|
||||
|
||||
Rich Murphey - Porting to FreeBSD, NetBSD, OpenBSD, and Darwin.
|
||||
rich@whiteoaklabs.com http://whiteoaklabs.com
|
||||
Simon Lockhart - Porting to Solaris (based on work of Logan ???)
|
||||
simon@slimey.org
|
||||
Olle E. Johansson - SIP RFC compliance, documentation and testing, testing, testing
|
||||
oej@edvina.net, http://edvina.net
|
||||
Steve Kann - new jitter buffer for IAX2
|
||||
stevek@stevek.com
|
||||
Constantine Filin - major contributions to the Asterisk Realtime Architecture
|
||||
Steve Murphy - privacy support
|
||||
Claude Patry - bug fixes, feature enhancements, and bug marshalling
|
||||
cpatry@gmail.com
|
||||
|
||||
=== OTHER CONTRIBUTIONS ===
|
||||
John Todd - Monkey sounds and associated teletorture prompt
|
||||
Michael Jerris - bug marshaling
|
||||
Leif Madsen, Jared Smith and Jim van Meggelen - the Asterisk book
|
||||
available under a Creative Commons License at http://www.asteriskdocs.org
|
||||
|
||||
=== HOLD MUSIC ===
|
||||
Music provided by www.opsound.org
|
||||
|
||||
=== OTHER SOURCE CODE IN ASTERISK ===
|
||||
|
||||
I did not implement the codecs in asterisk. Here is the copyright on the
|
||||
Digium did not implement the codecs in Asterisk. Here is the copyright on the
|
||||
GSM source:
|
||||
|
||||
Copyright 1992, 1993, 1994 by Jutta Degener and Carsten Bormann,
|
||||
@@ -85,7 +114,7 @@ And the copyright on the ADPCM source:
|
||||
Copyright 1992 by Stichting Mathematisch Centrum, Amsterdam, The
|
||||
Netherlands.
|
||||
|
||||
All Rights Reserved
|
||||
All Rights Reserved
|
||||
|
||||
Permission to use, copy, modify, and distribute this software and its
|
||||
documentation for any purpose and without fee is hereby granted,
|
||||
|
||||
6
HARDWARE
Executable file → Normal file
6
HARDWARE
Executable file → Normal file
@@ -16,11 +16,11 @@ Zaptel compatible hardware
|
||||
* Wildcard X100P - Single FXO interface connects to Loopstart phone
|
||||
line
|
||||
|
||||
* Wildcard T400P - Quad T1 interface connects to four T1/PRI
|
||||
* Wildcard T400P (obsolete) - Quad T1 interface connects to four T1/PRI
|
||||
interfaces. Supports RBS and PRI voice and PPP, FR, and HDLC data.
|
||||
|
||||
* Wildcard E400P - Quad E1 interface connects to four E1/PRI (or PRA)
|
||||
interfaces. Supports PRA/PRI, EuroISDN voice and PPP, FR, HDLC data.
|
||||
* Wildcard E400P (obsolete)- Quad E1 interface connects to four E1/PRI
|
||||
(or PRA) interfaces. Supports PRA/PRI, EuroISDN voice and data.
|
||||
|
||||
* Wildcard T100P - Single T1 interface connects to a single T1/PRI
|
||||
interface. Supports RBS and PRI voice and PPP, FR, and HDLC data.
|
||||
|
||||
381
LICENSE
Executable file → Normal file
381
LICENSE
Executable file → Normal file
@@ -1,341 +1,56 @@
|
||||
Asterisk is distributed under the GNU General Public License version 2
|
||||
and is also available under alternative licenses negotiated directly
|
||||
with Digium, Inc. If you obtained Asterisk under the GPL, then the GPL
|
||||
applies to all loadable Asterisk modules used on your system as well,
|
||||
except as defined below. The GPL (version 2) is included in this
|
||||
source tree in the file COPYING.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
Digium, Inc. (formerly Linux Support Services) holds copyright
|
||||
and/or sufficient licenses to all components of the Asterisk
|
||||
package, and therefore can grant, at its sole discretion, the ability
|
||||
for companies, individuals, or organizations to create proprietary or
|
||||
Open Source (even if not GPL) modules which may be dynamically linked at
|
||||
runtime with the portions of Asterisk which fall under our
|
||||
copyright/license umbrella, or are distributed under more flexible
|
||||
licenses than GPL.
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
If you wish to use our code in other GPL programs, don't worry --
|
||||
there is no requirement that you provide the same exception in your
|
||||
GPL'd products (although if you've written a module for Asterisk we
|
||||
would strongly encourage you to make the same exception that we do).
|
||||
|
||||
Preamble
|
||||
Specific permission is also granted to link Asterisk with OpenSSL and
|
||||
OpenH323.
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
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 Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
In addition, Asterisk implements two management/control protocols: the
|
||||
Asterisk Manager Interface (AMI) and the Asterisk Gateway Interface
|
||||
(AGI). It is our belief that applications using these protocols to
|
||||
manage or control an Asterisk instance do not have to be licensed
|
||||
under the GPL or a compatible license, as we believe these protocols
|
||||
do not create a 'derivative work' as referred to in the GPL. However,
|
||||
should any court or other judiciary body find that these protocols do
|
||||
fall under the terms of the GPL, then we hereby grant you a license to
|
||||
use these protocols in combination with Asterisk in external
|
||||
applications licensed under any license you wish.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
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.
|
||||
The 'Asterisk' name and logos are trademarks owned by Digium, Inc.,
|
||||
and use of them is subject to our trademark licensing policies. If you
|
||||
wish to use these trademarks for purposes other than simple
|
||||
redistribution of Asterisk source code obtained from Digium, you
|
||||
should contact our licensing department to determine the necessary
|
||||
steps you must take.
|
||||
|
||||
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.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
If you have any questions regarding our licensing policy, please
|
||||
contact us:
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
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.
|
||||
+1.877.546.8963 (via telephone in the USA)
|
||||
+1.256.428.6000 (via telephone outside the USA)
|
||||
+1.256.864.0464 (via FAX inside or outside the USA)
|
||||
IAX2/misery.digium.com/6000 (via IAX2)
|
||||
licensing@digium.com (via email)
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
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
|
||||
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
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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,
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
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
|
||||
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
|
||||
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
|
||||
programs whose distribution conditions are different, write to the author
|
||||
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
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
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
|
||||
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
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
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.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) 19yy <name of author>
|
||||
|
||||
This program 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.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
|
||||
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) 19yy 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 Library General
|
||||
Public License instead of this License.
|
||||
Digium, Inc.
|
||||
150 West Park Loop
|
||||
Suite 100
|
||||
Huntsville, AL 35806
|
||||
USA
|
||||
|
||||
221
README
Executable file → Normal file
221
README
Executable file → Normal file
@@ -1,12 +1,17 @@
|
||||
The Asterisk Open Source PBX
|
||||
by Mark Spencer <markster@digium.com>
|
||||
Copyright (C) 2001-2004 Digium
|
||||
and the Asterisk.org developer community
|
||||
|
||||
Copyright (C) 2001-2005 Digium, Inc.
|
||||
and other copyright holders.
|
||||
================================================================
|
||||
|
||||
* SECURITY
|
||||
It is imperative that you read and fully understand the contents of
|
||||
the SECURITY file before you attempt to configure an Asterisk server.
|
||||
the SECURITY file before you attempt to configure and run an Asterisk
|
||||
server.
|
||||
|
||||
* WHAT IS ASTERISK
|
||||
* WHAT IS ASTERISK ?
|
||||
Asterisk is an Open Source PBX and telephony toolkit. It is, in a
|
||||
sense, middleware between Internet and telephony channels on the bottom,
|
||||
and Internet and telephony applications at the top. For more information
|
||||
@@ -14,90 +19,118 @@ on the project itself, please visit the Asterisk home page at:
|
||||
|
||||
http://www.asterisk.org
|
||||
|
||||
* LICENSING
|
||||
Asterisk is distributed under GNU General Public License. The GPL also
|
||||
must apply to all loadable modules as well, except as defined below.
|
||||
In addition you'll find lots of information compiled by the Asterisk
|
||||
community on this Wiki:
|
||||
|
||||
Digium, Inc. (formerly Linux Support Services) retains copyright to all
|
||||
of the core Asterisk system, and therefore can grant, at its sole discression,
|
||||
the ability for companies, individuals, or organizations to create proprietary
|
||||
or Open Source (but non-GPL'd) modules which may be dynamically linked at
|
||||
runtime with the portions of Asterisk which fall under our copyright
|
||||
umbrella, or are distributed under more flexible licenses than GPL.
|
||||
http://www.voip-info.org/wiki-Asterisk
|
||||
|
||||
There is a book on Asterisk published by O'Reilly under the
|
||||
Creative Commons License. It is available in book stores as well
|
||||
as in a downloadable version on the http://www.asteriskdocs.org
|
||||
web site.
|
||||
|
||||
If you wish to use our code in other GPL programs, don't worry -- there
|
||||
is no requirement that you provide the same exemption in your GPL'd
|
||||
products (although if you've written a module for Asterisk we would
|
||||
strongly encourage you to make the same excemption that we do).
|
||||
|
||||
Specific permission is also granted to OpenSSL and OpenH323 to link to
|
||||
Asterisk.
|
||||
|
||||
If you have any questions, whatsoever, regarding our licensing policy,
|
||||
please contact us.
|
||||
|
||||
Modules that are GPL-licensed and not available under Digium's
|
||||
licensing scheme are added to the Asterisk-addons CVS module.
|
||||
|
||||
* REQUIRED COMPONENTS
|
||||
* SUPPORTED OPERATING SYSTEMS
|
||||
|
||||
== Linux ==
|
||||
Currently, the Asterisk Open Source PBX is only known to run on the
|
||||
Linux OS, although it may be portable to other UNIX-like operating systems
|
||||
as well.
|
||||
The Asterisk Open Source PBX is developed and tested primarily on the
|
||||
GNU/Linux operating system, and is supported on every major GNU/Linux
|
||||
distribution.
|
||||
|
||||
== Others ==
|
||||
Asterisk has also been 'ported' and reportedly runs properly on other
|
||||
operating systems as well, including Sun Solaris, Apple's Mac OS X, and
|
||||
the BSD variants.
|
||||
|
||||
* GETTING STARTED
|
||||
|
||||
First, be sure you've got supported hardware. To use Asterisk right now,
|
||||
you will need one of the following:
|
||||
First, be sure you've got supported hardware (but note that you don't need
|
||||
ANY special hardware, not even a soundcard) to install and run Asterisk.
|
||||
|
||||
Supported telephony hardware includes:
|
||||
|
||||
* All Wildcard (tm) products from Digium (www.digium.com)
|
||||
* QuickNet Internet PhoneJack and LineJack (http://www.quicknet.net)
|
||||
* Full Duplex Sound Card supported by Linux
|
||||
* Adtran Atlas 800 Plus
|
||||
* ISDN4Linux compatible ISDN card
|
||||
* Tormenta Dual T1 card (www.bsdtelephony.com.mx)
|
||||
* any full duplex sound card supported by ALSA or OSS
|
||||
* VoiceTronix OpenLine products
|
||||
|
||||
Assuming you have one of these (most likely the third) you're ready to
|
||||
proceed:
|
||||
The are several drivers for ISDN BRI cards available from third party sources.
|
||||
Check the voip-info.org wiki for more information on chan_capi, chan_misdn and
|
||||
zaphfc.
|
||||
|
||||
* UPGRADING FROM VERSION 1.0
|
||||
|
||||
If you are updating from a previous version of Asterisk, make sure you
|
||||
read the UPGRADE.txt file in the source directory. There are some files
|
||||
and configuration options that you will have to change, even though we
|
||||
made every effort possible to maintain backwards compatibility.
|
||||
|
||||
In order to discover new features to use, please check the configuration
|
||||
examples in the /configs directory of the source code distribution.
|
||||
To discover the major new features of Asterisk 1.2, please visit
|
||||
http://www.astricon.net/asterisk1-2/
|
||||
|
||||
* NEW INSTALLATIONS
|
||||
|
||||
Ensure that your system contains a compatible compiler and development
|
||||
libraries. Asterisk requires either the GNU Compiler Collection (GCC) version
|
||||
3.0 or higher, or a compiler that supports the C99 specification and some of
|
||||
the gcc language extensions. In addition, your system needs to have the C
|
||||
library headers available, and the headers and libraries for OpenSSL,
|
||||
ncurses and zlib.
|
||||
On many distributions, these files are installed by packages with names like
|
||||
'glibc-devel', 'ncurses-devel', 'openssl-devel' and 'zlib-devel' or similar.
|
||||
|
||||
So let's proceed:
|
||||
|
||||
1) Run "make"
|
||||
|
||||
Assuming the build completes successfully:
|
||||
|
||||
2) Run "make install"
|
||||
|
||||
If this is your first time working with Asterisk, you may wish to install
|
||||
Each time you update or checkout from CVS, you are strongly encouraged
|
||||
to ensure all previous object files are removed to avoid internal
|
||||
inconsistency in Asterisk. Normally, this is automatically done with
|
||||
the presence of the file .cleancount, which increments each time a 'make clean'
|
||||
is required, and the file .lastclean, which contains the last .cleancount used.
|
||||
|
||||
If this is your first time working with Asterisk, you may wish to install
|
||||
the sample PBX, with demonstration extensions, etc. If so, run:
|
||||
|
||||
"make samples"
|
||||
3) "make samples"
|
||||
|
||||
Doing so will overwrite any existing config files you have.
|
||||
Doing so will overwrite any existing config files you have.
|
||||
|
||||
Finally, you can launch Asterisk with:
|
||||
Finally, you can launch Asterisk in the foreground mode (not a daemon)
|
||||
with:
|
||||
|
||||
./asterisk -vvvc
|
||||
# asterisk -vvvc
|
||||
|
||||
You'll see a bunch of verbose messages fly by your screen as Asterisk
|
||||
You'll see a bunch of verbose messages fly by your screen as Asterisk
|
||||
initializes (that's the "very very verbose" mode). When it's ready, if
|
||||
you specified the "c" then you'll get a command line console, that looks
|
||||
like this:
|
||||
|
||||
*CLI>
|
||||
|
||||
You can type "help" at any time to get help with the system. For help
|
||||
You can type "help" at any time to get help with the system. For help
|
||||
with a specific command, type "help <command>". To start the PBX using
|
||||
your sound card, you can type "dial" to dial the PBX. Then you can use
|
||||
"answer", "hangup", and "dial" to simulate the actions of a telephone.
|
||||
Remember that if you don't have a full duplex sound card (And asterisk
|
||||
will tell you somewhere in its verbose messages if you do/don't) than it
|
||||
Remember that if you don't have a full duplex sound card (and Asterisk
|
||||
will tell you somewhere in its verbose messages if you do/don't) then it
|
||||
won't work right (not yet).
|
||||
|
||||
Feel free to look over the configuration files in /etc/asterisk, where
|
||||
"man asterisk" at the Unix/Linux command prompt will give you detailed
|
||||
information on how to start and stop Asterisk, as well as all the command
|
||||
line options for starting Asterisk.
|
||||
|
||||
Feel free to look over the configuration files in /etc/asterisk, where
|
||||
you'll find a lot of information about what you can do with Asterisk.
|
||||
|
||||
* ABOUT CONFIGURATION FILES
|
||||
|
||||
All Asterisk configuration files share a common format. Comments are
|
||||
All Asterisk configuration files share a common format. Comments are
|
||||
delimited by ';' (since '#' of course, being a DTMF digit, may occur in
|
||||
many places). A configuration file is divided into sections whose names
|
||||
appear in []'s. Each section typically contains two types of statements,
|
||||
@@ -106,12 +139,12 @@ parameters'. Internally the use of '=' and '=>' is exactly the same, so
|
||||
they're used only to help make the configuration file easier to
|
||||
understand, and do not affect how it is actually parsed.
|
||||
|
||||
Entries of the form 'variable=value' set the value of some parameter in
|
||||
asterisk. For example, in tormenta.conf, one might specify:
|
||||
Entries of the form 'variable=value' set the value of some parameter in
|
||||
asterisk. For example, in zapata.conf, one might specify:
|
||||
|
||||
switchtype=national
|
||||
|
||||
In order to indicate to Asterisk that the switch they are connecting to is
|
||||
in order to indicate to Asterisk that the switch they are connecting to is
|
||||
of the type "national". In general, the parameter will apply to
|
||||
instantiations which occur below its specification. For example, if the
|
||||
configuration file read:
|
||||
@@ -122,24 +155,94 @@ configuration file read:
|
||||
switchtype = dms100
|
||||
channel => 25-47
|
||||
|
||||
Then, the "national" switchtype would be applied to channels one through
|
||||
the "national" switchtype would be applied to channels one through
|
||||
four and channels 10 through 12, whereas the "dms100" switchtype would
|
||||
apply to channels 25 through 47.
|
||||
|
||||
The "object => parameters" instantiates an object with the given
|
||||
The "object => parameters" instantiates an object with the given
|
||||
parameters. For example, the line "channel => 25-47" creates objects for
|
||||
the channels 25 through 47 of the tormenta card, obtaining the settings
|
||||
the channels 25 through 47 of the card, obtaining the settings
|
||||
from the variables specified above.
|
||||
|
||||
* NETWORK SECURITY DEVICES
|
||||
|
||||
This release of Asterisk contains support for network security devices
|
||||
manufactured by Ranch Networks, Inc., using their MIDCOM interface
|
||||
library. You will need the companion libmidcom-0.1.0.tar.gz file to
|
||||
build the library. Contact Ranch Networks' support department for assistance
|
||||
in building and configuring MIDCOM support.
|
||||
|
||||
* SPECIAL NOTE ON TIME
|
||||
|
||||
Those using SIP phones should be aware that Asterisk is sensitive to
|
||||
large jumps in time. Manually changing the system time using date(1)
|
||||
(or other similar commands) may cause SIP registrations and other
|
||||
internal processes to fail. If your system cannot keep accurate time
|
||||
by itself use NTP (http://www.ntp.org/) to keep the system clock
|
||||
synchronized to "real time". NTP is designed to keep the system clock
|
||||
synchronized by speeding up or slowing down the system clock until it
|
||||
is synchronized to "real time" rather than by jumping the time and
|
||||
causing discontinuities. Most Linux distributions include precompiled
|
||||
versions of NTP. Beware of some time synchronization methods that get
|
||||
the correct real time periodically and then manually set the system
|
||||
clock.
|
||||
|
||||
Apparent time changes due to daylight savings time are just that,
|
||||
apparent. The use of daylight savings time in a Linux system is
|
||||
purely a user interface issue and does not affect the operation of the
|
||||
Linux kernel or Asterisk. The system clock on Linux kernels operates
|
||||
on UTC. UTC does not use daylight savings time.
|
||||
|
||||
Also note that this issue is separate from the clocking of TDM
|
||||
channels, and is known to at least affect SIP registrations.
|
||||
|
||||
* FILE DESCRIPTORS
|
||||
|
||||
Depending on the size of your system and your configuration,
|
||||
Asterisk can consume a large number of file descriptors. In UNIX,
|
||||
file descriptors are used for more than just files on disk. File
|
||||
descriptors are also used for handling network communication
|
||||
(e.g. SIP, IAX2, or H.323 calls) and hardware access (e.g. analog and
|
||||
digital trunk hardware). Asterisk accesses many on-disk files for
|
||||
everything from configuration information to voicemail storage.
|
||||
|
||||
Most systems limit the number of file descriptors that Asterisk can
|
||||
have open at one time. This can limit the number of simultaneous
|
||||
calls that your system can handle. For example, if the limit is set
|
||||
at 1024 (a common default value) Asterisk can handle approxiately 150
|
||||
SIP calls simultaneously. To change the number of file descriptors
|
||||
follow the instructions for your system below:
|
||||
|
||||
== PAM-based Linux System ==
|
||||
|
||||
If your system uses PAM (Pluggable Authentication Modules) edit
|
||||
/etc/security/limits.conf. Add these lines to the bottom of the file:
|
||||
|
||||
root soft nofile 4096
|
||||
root hard nofile 8196
|
||||
asterisk soft nofile 4096
|
||||
asterisk hard nofile 8196
|
||||
|
||||
(adjust the numbers to taste). You may need to reboot the system for
|
||||
these changes to take effect.
|
||||
|
||||
== Generic UNIX System ==
|
||||
|
||||
If there are no instructions specifically adapted to your system
|
||||
above you can try adding the command "ulimit -n 8192" to the script
|
||||
that starts Asterisk.
|
||||
|
||||
* MORE INFORMATION
|
||||
|
||||
See the doc directory for more documentation.
|
||||
See the doc directory for more documentation on various features. Again,
|
||||
please read all the configuration samples that include documentation on
|
||||
the configuration options.
|
||||
|
||||
Finally, you may wish to visit the web site and join the mailing list if
|
||||
Finally, you may wish to visit the web site and join the mailing list if
|
||||
you're interested in getting more information.
|
||||
|
||||
http://www.asterisk.org/index.php?menu=support
|
||||
http://www.asterisk.org/support
|
||||
|
||||
Welcome to the growing worldwide community of Asterisk users!
|
||||
Welcome to the growing worldwide community of Asterisk users!
|
||||
|
||||
Mark Spencer
|
||||
|
||||
22
README.opsound
Normal file
22
README.opsound
Normal file
@@ -0,0 +1,22 @@
|
||||
About Hold Music
|
||||
================
|
||||
These files were obtained from http://opsound.org, where the authors placed them
|
||||
under the Creative Commons Attribution-Share Alike 2.5 license, a copy of which
|
||||
may be found at http://creativecommons.org.
|
||||
|
||||
Credits
|
||||
================
|
||||
macroform-cold_day - Paul Shuler (Macroform)
|
||||
paulshuler@gmail.com - http://macroform.bandcamp.com/
|
||||
|
||||
macroform-robot_dity - Paul Shuler (Macroform)
|
||||
paulshuler@gmail.com - http://macroform.bandcamp.com/
|
||||
|
||||
macroform-the_simplicity - Paul Shuler (Macroform)
|
||||
paulshuler@gmail.com - http://macroform.bandcamp.com/
|
||||
|
||||
manolo_camp-morning_coffee - Manolo Camp
|
||||
beatbastard@gmx.net - http://ccmixter.org/people/ManoloCamp
|
||||
|
||||
reno_project-system - Reno Project
|
||||
renoproject@hotmail.com - http://www.jamendo.com/en/album/23661
|
||||
34
SECURITY
Executable file → Normal file
34
SECURITY
Executable file → Normal file
@@ -4,6 +4,32 @@ PLEASE READ THE FOLLOWING IMPORTANT SECURITY RELATED INFORMATION.
|
||||
IMPROPER CONFIGURATION OF ASTERISK COULD ALLOW UNAUTHORIZED USE OF YOUR
|
||||
FACILITIES, POTENTIALLY INCURRING SUBSTANTIAL CHARGES.
|
||||
|
||||
Asterisk security involves both network security (encryption, authentication)
|
||||
as well as dialplan security (authorization - who can access services in
|
||||
your pbx). If you are setting up Asterisk in production use, please make
|
||||
sure you understand the issues involved.
|
||||
|
||||
* NETWORK SECURITY
|
||||
|
||||
If you install Asterisk and use the "make samples" command to install
|
||||
a demonstration configuration, Asterisk will open a few ports for accepting
|
||||
VoIP calls. Check the channel configuration files for the ports and IP addresses.
|
||||
|
||||
If you enable the manager interface in manager.conf, please make sure that
|
||||
you access manager in a safe environment or protect it with SSH or other
|
||||
VPN solutions.
|
||||
|
||||
For all TCP/IP connections in Asterisk, you can set ACL lists that
|
||||
will permit or deny network access to Asterisk services. Please check
|
||||
the "permit" and "deny" configuration options in manager.conf and
|
||||
the VoIP channel configurations - i.e. sip.conf and iax.conf.
|
||||
|
||||
The IAX2 protocol supports strong RSA key authentication as well as
|
||||
AES encryption of voice and signalling. The SIP channel does not
|
||||
support encryption in this version of Asterisk.
|
||||
|
||||
* DIALPLAN SECURITY
|
||||
|
||||
First and foremost remember this:
|
||||
|
||||
USE THE EXTENSION CONTEXTS TO ISOLATE OUTGOING OR TOLL SERVICES FROM ANY
|
||||
@@ -25,17 +51,17 @@ the "default" context within other private contexts by using:
|
||||
in the appropriate section. A well designed PBX might look like this:
|
||||
|
||||
[longdistance]
|
||||
exten => _91NXXNXXXXXX,1,Dial,Tor/g2/BYEXTENSION
|
||||
exten => _91NXXNXXXXXX,1,Dial(Zap/g2/${EXTEN:1})
|
||||
include => local
|
||||
|
||||
[local]
|
||||
exten => _9NXXNXXX,1,Dial,Tor/g2/BYEXTENSION
|
||||
exten => _9NXXNXXX,1,Dial(Zap/g2/${EXTEN:1})
|
||||
include => default
|
||||
|
||||
[default]
|
||||
exten => 6123,Dial,Tor/1
|
||||
exten => 6123,Dial(Zap/1)
|
||||
|
||||
|
||||
DON'T FORGET TO TAKE THE DEMO CONTEXT OUT OF YOUR DEFAULT CONTEXT. There
|
||||
isn't really a security reason, it just will keep people from wanting to
|
||||
play with your asterisk setup remotely.
|
||||
play with your Asterisk setup remotely.
|
||||
|
||||
205
UPGRADE.txt
Normal file
205
UPGRADE.txt
Normal file
@@ -0,0 +1,205 @@
|
||||
Information for Upgrading From Previous Asterisk Releases
|
||||
=========================================================
|
||||
|
||||
Compiling:
|
||||
|
||||
* The Asterisk 1.2 source code now uses C language features
|
||||
supported only by 'modern' C compilers. Generally, this means GCC
|
||||
version 3.0 or higher, although some GCC 2.96 releases will also
|
||||
work. Some non-GCC compilers that support C99 and the common GCC
|
||||
extensions (including anonymous structures and unions) will also
|
||||
work. All releases of GCC 2.95 do _not_ have the requisite feature
|
||||
support; systems using that compiler will need to be upgraded to
|
||||
a more recent compiler release.
|
||||
|
||||
Dialplan Expressions:
|
||||
|
||||
* The dialplan expression parser (which handles $[ ... ] constructs)
|
||||
has gone through a major upgrade, but has one incompatible change:
|
||||
spaces are no longer required around expression operators, including
|
||||
string comparisons. However, you can now use quoting to keep strings
|
||||
together for comparison. For more details, please read the
|
||||
doc/README.variables file, and check over your dialplan for possible
|
||||
problems.
|
||||
|
||||
Agents:
|
||||
|
||||
* The default for ackcall has been changed to "no" instead of "yes"
|
||||
because of a bug which caused the "yes" behavior to generally act like
|
||||
"no". You may need to adjust the value if your agents behave
|
||||
differently than you expect with respect to acknowledgement.
|
||||
|
||||
* The AgentCallBackLogin application now requires a second '|' before
|
||||
specifying an extension@context. This is to distinguish the options
|
||||
string from the extension, so that they do not conflict. See
|
||||
'show application AgentCallbackLogin' for more details.
|
||||
|
||||
Parking:
|
||||
|
||||
* Parking behavior has changed slightly; when a parked call times out,
|
||||
Asterisk will attempt to deliver the call back to the extension that
|
||||
parked it, rather than the 's' extension. If that extension is busy
|
||||
or unavailable, the parked call will be lost.
|
||||
|
||||
Dialing:
|
||||
|
||||
* The Caller*ID of the outbound leg is now the extension that was
|
||||
called, rather than the Caller*ID of the inbound leg of the call. The
|
||||
"o" flag for Dial can be used to restore the original behavior if
|
||||
desired. Note that if you are looking for the originating callerid
|
||||
from the manager event, there is a new manager event "Dial" which
|
||||
provides the source and destination channels and callerid.
|
||||
|
||||
IAX:
|
||||
|
||||
* The naming convention for IAX channels has changed in two ways:
|
||||
1. The call number follows a "-" rather than a "/" character.
|
||||
2. The name of the channel has been simplified to IAX2/peer-callno,
|
||||
rather than IAX2/peer@peer-callno or even IAX2/peer@peer/callno.
|
||||
|
||||
SIP:
|
||||
|
||||
* The global option "port" in 1.0.X that is used to set which port to
|
||||
bind to has been changed to "bindport" to be more consistent with
|
||||
the other channel drivers and to avoid confusion with the "port"
|
||||
option for users/peers.
|
||||
|
||||
* The "Registry" event now uses "Username" rather than "User" for
|
||||
consistency with IAX.
|
||||
|
||||
Applications:
|
||||
|
||||
* With the addition of dialplan functions (which operate similarly
|
||||
to variables), the SetVar application has been renamed to Set.
|
||||
|
||||
* The CallerPres application has been removed. Use SetCallerPres
|
||||
instead. It accepts both numeric and symbolic names.
|
||||
|
||||
* The applications GetGroupCount, GetGroupMatchCount, SetGroup, and
|
||||
CheckGroup have been deprecated in favor of functions. Here is a
|
||||
table of their replacements:
|
||||
|
||||
GetGroupCount([groupname][@category] GROUP_COUNT([groupname][@category]) Set(GROUPCOUNT=${GROUP_COUNT()})
|
||||
GroupMatchCount(groupmatch[@category]) GROUP_MATCH_COUNT(groupmatch[@category]) Set(GROUPCOUNT=${GROUP_MATCH_COUNT(SIP/.*)})
|
||||
SetGroup(groupname[@category]) GROUP([category])=groupname Set(GROUP()=test)
|
||||
CheckGroup(max[@category]) N/A GotoIf($[ ${GROUP_COUNT()} > 5 ]?103)
|
||||
|
||||
Note that CheckGroup does not have a direct replacement. There is
|
||||
also a new function called GROUP_LIST() which will return a space
|
||||
separated list of all of the groups set on a channel. The GROUP()
|
||||
function can also return the name of the group set on a channel when
|
||||
used in a read environment.
|
||||
|
||||
* The applications DBGet and DBPut have been deprecated in favor of
|
||||
functions. Here is a table of their replacements:
|
||||
|
||||
DBGet(foo=family/key) Set(foo=${DB(family/key)})
|
||||
DBPut(family/key=${foo}) Set(DB(family/key)=${foo})
|
||||
|
||||
* The application SetLanguage has been deprecated in favor of the
|
||||
function LANGUAGE().
|
||||
|
||||
SetLanguage(fr) Set(LANGUAGE()=fr)
|
||||
|
||||
The LANGUAGE function can also return the currently set language:
|
||||
|
||||
Set(MYLANG=${LANGUAGE()})
|
||||
|
||||
* The applications AbsoluteTimeout, DigitTimeout, and ResponseTimeout
|
||||
have been deprecated in favor of the function TIMEOUT(timeouttype):
|
||||
|
||||
AbsoluteTimeout(300) Set(TIMEOUT(absolute)=300)
|
||||
DigitTimeout(15) Set(TIMEOUT(digit)=15)
|
||||
ResponseTimeout(15) Set(TIMEOUT(response)=15)
|
||||
|
||||
The TIMEOUT() function can also return the currently set timeouts:
|
||||
|
||||
Set(DTIMEOUT=${TIMEOUT(digit)})
|
||||
|
||||
* The applications SetCIDName, SetCIDNum, and SetRDNIS have been
|
||||
deprecated in favor of the CALLERID(datatype) function:
|
||||
|
||||
SetCIDName(Joe Cool) Set(CALLERID(name)=Joe Cool)
|
||||
SetCIDNum(2025551212) Set(CALLERID(number)=2025551212)
|
||||
SetRDNIS(2024561414) Set(CALLERID(RDNIS)=2024561414)
|
||||
|
||||
* The application Record now uses the period to separate the filename
|
||||
from the format, rather than the colon.
|
||||
|
||||
* The application VoiceMail now supports a 'temporary' greeting for each
|
||||
mailbox. This greeting can be recorded by using option 4 in the
|
||||
'mailbox options' menu, and 'change your password' option has been
|
||||
moved to option 5.
|
||||
|
||||
* The application VoiceMailMain now only matches the 'default' context if
|
||||
none is specified in the arguments. (This was the previously
|
||||
documented behavior, however, we didn't follow that behavior.) The old
|
||||
behavior can be restored by setting searchcontexts=yes in voicemail.conf.
|
||||
|
||||
Queues:
|
||||
|
||||
* A queue is now considered empty not only if there are no members but if
|
||||
none of the members are available (e.g. agents not logged on). To
|
||||
restore the original behavior, use "leavewhenempty=strict" or
|
||||
"joinwhenempty=strict" instead of "=yes" for those options.
|
||||
|
||||
* It is now possible to use multi-digit extensions in the exit context
|
||||
for a queue (although you should not have overlapping extensions,
|
||||
as there is no digit timeout). This means that the EXITWITHKEY event
|
||||
in queue_log can now contain a key field with more than a single
|
||||
character in it.
|
||||
|
||||
Extensions:
|
||||
|
||||
* By default, there is a new option called "autofallthrough" in
|
||||
extensions.conf that is set to yes. Asterisk 1.0 (and earlier)
|
||||
behavior was to wait for an extension to be dialed after there were no
|
||||
more extensions to execute. "autofallthrough" changes this behavior
|
||||
so that the call will immediately be terminated with BUSY,
|
||||
CONGESTION, or HANGUP based on Asterisk's best guess. If you are
|
||||
writing an extension for IVR, you must use the WaitExten application
|
||||
if "autofallthrough" is set to yes.
|
||||
|
||||
AGI:
|
||||
|
||||
* AGI scripts did not always get SIGHUP at the end, previously. That
|
||||
behavior has been fixed. If you do not want your script to terminate
|
||||
at the end of AGI being called (e.g. on a hangup) then set SIGHUP to
|
||||
be ignored within your application.
|
||||
|
||||
* CallerID is reported with agi_callerid and agi_calleridname instead
|
||||
of a single parameter holding both.
|
||||
|
||||
Music On Hold:
|
||||
|
||||
* The preferred format for musiconhold.conf has changed; please see the
|
||||
sample configuration file for the new format. The existing format
|
||||
is still supported but will generate warnings when the module is loaded.
|
||||
|
||||
chan_modem:
|
||||
|
||||
* All the chan_modem channel drivers (aopen, bestdata and i4l) are deprecated
|
||||
in this release, and will be removed in the next major Asterisk release.
|
||||
Please migrate to chan_misdn for ISDN interfaces; there is no upgrade
|
||||
path for aopen and bestdata modem users.
|
||||
|
||||
MeetMe:
|
||||
|
||||
* The conference application now allows users to increase/decrease their
|
||||
speaking volume and listening volume (independently of each other and
|
||||
other users); the 'admin' and 'user' menus have changed, and new sound
|
||||
files are included with this release. However, if a user calling in
|
||||
over a Zaptel channel that does NOT have hardware DTMF detection
|
||||
increases their speaking volume, it is likely they will no longer be
|
||||
able to enter/exit the menu or make any further adjustments, as the
|
||||
software DTMF detector will not be able to recognize the DTMF coming
|
||||
from their device.
|
||||
|
||||
GetVar Manager Action:
|
||||
|
||||
* Previously, the behavior of the GetVar manager action reported the value
|
||||
of a variable in the following manner:
|
||||
> name: value
|
||||
This has been changed to a manner similar to the SetVar action and is now
|
||||
> Variable: name
|
||||
> Value: value
|
||||
380
acl.c
Executable file → Normal file
380
acl.c
Executable file → Normal file
@@ -1,43 +1,78 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Various sorts of access control
|
||||
*
|
||||
* Copyright (C) 1999, Mark Spencer
|
||||
* Copyright (C) 1999 - 2005, Digium, Inc.
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
* Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief Various sorts of access control
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <asterisk/acl.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <sys/ioctl.h>
|
||||
#ifdef __OpenBSD__
|
||||
|
||||
#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__)
|
||||
#include <fcntl.h>
|
||||
#include <net/route.h>
|
||||
|
||||
static ast_mutex_t routeseq_lock = AST_MUTEX_INITIALIZER;
|
||||
#endif
|
||||
|
||||
#define AST_SENSE_DENY 0
|
||||
#define AST_SENSE_ALLOW 1
|
||||
#if defined(SOLARIS)
|
||||
#include <sys/sockio.h>
|
||||
#endif
|
||||
|
||||
/* netinet/ip.h may not define the following (See RFCs 791 and 1349) */
|
||||
#if !defined(IPTOS_LOWCOST)
|
||||
#define IPTOS_LOWCOST 0x02
|
||||
#endif
|
||||
|
||||
#if !defined(IPTOS_MINCOST)
|
||||
#define IPTOS_MINCOST IPTOS_LOWCOST
|
||||
#endif
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/acl.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/options.h"
|
||||
#include "asterisk/utils.h"
|
||||
#include "asterisk/lock.h"
|
||||
#include "asterisk/srv.h"
|
||||
#include "asterisk/compat.h"
|
||||
|
||||
#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__)
|
||||
AST_MUTEX_DEFINE_STATIC(routeseq_lock);
|
||||
#endif
|
||||
|
||||
struct ast_ha {
|
||||
/* Host access rule */
|
||||
@@ -55,6 +90,7 @@ struct my_ifreq {
|
||||
struct sockaddr_in ifru_addr;
|
||||
};
|
||||
|
||||
/* Free HA structure */
|
||||
void ast_free_ha(struct ast_ha *ha)
|
||||
{
|
||||
struct ast_ha *hal;
|
||||
@@ -65,31 +101,71 @@ void ast_free_ha(struct ast_ha *ha)
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy HA structure */
|
||||
static void ast_copy_ha(struct ast_ha *from, struct ast_ha *to)
|
||||
{
|
||||
memcpy(&to->netaddr, &from->netaddr, sizeof(from->netaddr));
|
||||
memcpy(&to->netmask, &from->netmask, sizeof(from->netmask));
|
||||
to->sense = from->sense;
|
||||
}
|
||||
|
||||
/* Create duplicate of ha structure */
|
||||
static struct ast_ha *ast_duplicate_ha(struct ast_ha *original)
|
||||
{
|
||||
struct ast_ha *new_ha = malloc(sizeof(struct ast_ha));
|
||||
/* Copy from original to new object */
|
||||
ast_copy_ha(original, new_ha);
|
||||
|
||||
return new_ha;
|
||||
}
|
||||
|
||||
/* Create duplicate HA link list */
|
||||
/* Used in chan_sip2 templates */
|
||||
struct ast_ha *ast_duplicate_ha_list(struct ast_ha *original)
|
||||
{
|
||||
struct ast_ha *start=original;
|
||||
struct ast_ha *ret = NULL;
|
||||
struct ast_ha *link,*prev=NULL;
|
||||
|
||||
while (start) {
|
||||
link = ast_duplicate_ha(start); /* Create copy of this object */
|
||||
if (prev)
|
||||
prev->next = link; /* Link previous to this object */
|
||||
|
||||
if (!ret)
|
||||
ret = link; /* Save starting point */
|
||||
|
||||
start = start->next; /* Go to next object */
|
||||
prev = link; /* Save pointer to this object */
|
||||
}
|
||||
return ret; /* Return start of list */
|
||||
}
|
||||
|
||||
struct ast_ha *ast_append_ha(char *sense, char *stuff, struct ast_ha *path)
|
||||
{
|
||||
struct ast_ha *ha = malloc(sizeof(struct ast_ha));
|
||||
char *nm;
|
||||
char tmp[256] = "";
|
||||
char *nm = "255.255.255.255";
|
||||
char tmp[256];
|
||||
struct ast_ha *prev = NULL;
|
||||
struct ast_ha *ret;
|
||||
int x,z;
|
||||
int x, z;
|
||||
unsigned int y;
|
||||
ret = path;
|
||||
while(path) {
|
||||
while (path) {
|
||||
prev = path;
|
||||
path = path->next;
|
||||
}
|
||||
if (ha) {
|
||||
strncpy(tmp, stuff, sizeof(tmp) - 1);
|
||||
ast_copy_string(tmp, stuff, sizeof(tmp));
|
||||
nm = strchr(tmp, '/');
|
||||
if (!nm)
|
||||
if (!nm) {
|
||||
nm = "255.255.255.255";
|
||||
else {
|
||||
} else {
|
||||
*nm = '\0';
|
||||
nm++;
|
||||
}
|
||||
if (!strchr(nm, '.')) {
|
||||
if ((sscanf(nm, "%i", &x) == 1) && (x >= 0) && (x <= 32)) {
|
||||
if ((sscanf(nm, "%d", &x) == 1) && (x >= 0) && (x <= 32)) {
|
||||
y = 0;
|
||||
for (z=0;z<x;z++) {
|
||||
y >>= 1;
|
||||
@@ -98,12 +174,12 @@ struct ast_ha *ast_append_ha(char *sense, char *stuff, struct ast_ha *path)
|
||||
ha->netmask.s_addr = htonl(y);
|
||||
}
|
||||
} else if (!inet_aton(nm, &ha->netmask)) {
|
||||
ast_log(LOG_WARNING, "%s not a valid netmask\n", nm);
|
||||
ast_log(LOG_WARNING, "%s is not a valid netmask\n", nm);
|
||||
free(ha);
|
||||
return path;
|
||||
}
|
||||
if (!inet_aton(tmp, &ha->netaddr)) {
|
||||
ast_log(LOG_WARNING, "%s not a valid IP\n", tmp);
|
||||
ast_log(LOG_WARNING, "%s is not a valid IP\n", tmp);
|
||||
free(ha);
|
||||
return path;
|
||||
}
|
||||
@@ -114,11 +190,13 @@ struct ast_ha *ast_append_ha(char *sense, char *stuff, struct ast_ha *path)
|
||||
ha->sense = AST_SENSE_DENY;
|
||||
}
|
||||
ha->next = NULL;
|
||||
if (prev)
|
||||
if (prev) {
|
||||
prev->next = ha;
|
||||
else
|
||||
} else {
|
||||
ret = ha;
|
||||
}
|
||||
}
|
||||
ast_log(LOG_DEBUG, "%s/%s appended to acl for peer\n", stuff, nm);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -126,20 +204,40 @@ int ast_apply_ha(struct ast_ha *ha, struct sockaddr_in *sin)
|
||||
{
|
||||
/* Start optimistic */
|
||||
int res = AST_SENSE_ALLOW;
|
||||
while(ha) {
|
||||
while (ha) {
|
||||
char iabuf[INET_ADDRSTRLEN];
|
||||
char iabuf2[INET_ADDRSTRLEN];
|
||||
/* DEBUG */
|
||||
ast_log(LOG_DEBUG,
|
||||
"##### Testing %s with %s\n",
|
||||
ast_inet_ntoa(iabuf, sizeof(iabuf), sin->sin_addr),
|
||||
ast_inet_ntoa(iabuf2, sizeof(iabuf2), ha->netaddr));
|
||||
/* For each rule, if this address and the netmask = the net address
|
||||
apply the current rule */
|
||||
if ((sin->sin_addr.s_addr & ha->netmask.s_addr) == (ha->netaddr.s_addr))
|
||||
if ((sin->sin_addr.s_addr & ha->netmask.s_addr) == ha->netaddr.s_addr)
|
||||
res = ha->sense;
|
||||
ha = ha->next;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
int ast_get_ip(struct sockaddr_in *sin, char *value)
|
||||
int ast_get_ip_or_srv(struct sockaddr_in *sin, const char *value, const char *service)
|
||||
{
|
||||
struct hostent *hp;
|
||||
hp = gethostbyname(value);
|
||||
struct ast_hostent ahp;
|
||||
char srv[256];
|
||||
char host[256];
|
||||
int tportno = ntohs(sin->sin_port);
|
||||
if (inet_aton(value, &sin->sin_addr))
|
||||
return 0;
|
||||
if (service) {
|
||||
snprintf(srv, sizeof(srv), "%s.%s", service, value);
|
||||
if (ast_get_srv(NULL, host, sizeof(host), &tportno, srv) > 0) {
|
||||
sin->sin_port = htons(tportno);
|
||||
value = host;
|
||||
}
|
||||
}
|
||||
hp = ast_gethostbyname(value, &ahp);
|
||||
if (hp) {
|
||||
memcpy(&sin->sin_addr, hp->h_addr, sizeof(sin->sin_addr));
|
||||
} else {
|
||||
@@ -149,183 +247,109 @@ int ast_get_ip(struct sockaddr_in *sin, char *value)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int inaddrcmp(struct sockaddr_in *sin1, struct sockaddr_in *sin2)
|
||||
int ast_str2tos(const char *value, int *tos)
|
||||
{
|
||||
return ((sin1->sin_addr.s_addr != sin2->sin_addr.s_addr )
|
||||
|| (sin1->sin_port != sin2->sin_port));
|
||||
int fval;
|
||||
if (sscanf(value, "%i", &fval) == 1)
|
||||
*tos = fval & 0xff;
|
||||
else if (!strcasecmp(value, "lowdelay"))
|
||||
*tos = IPTOS_LOWDELAY;
|
||||
else if (!strcasecmp(value, "throughput"))
|
||||
*tos = IPTOS_THROUGHPUT;
|
||||
else if (!strcasecmp(value, "reliability"))
|
||||
*tos = IPTOS_RELIABILITY;
|
||||
else if (!strcasecmp(value, "mincost"))
|
||||
*tos = IPTOS_MINCOST;
|
||||
else if (!strcasecmp(value, "none"))
|
||||
*tos = 0;
|
||||
else
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ast_get_ip(struct sockaddr_in *sin, const char *value)
|
||||
{
|
||||
return ast_get_ip_or_srv(sin, value, NULL);
|
||||
}
|
||||
|
||||
/* iface is the interface (e.g. eth0); address is the return value */
|
||||
int ast_lookup_iface(char *iface, struct in_addr *address) {
|
||||
int ast_lookup_iface(char *iface, struct in_addr *address)
|
||||
{
|
||||
int mysock, res = 0;
|
||||
struct my_ifreq ifreq;
|
||||
|
||||
memset(&ifreq, 0, sizeof(ifreq));
|
||||
strncpy(ifreq.ifrn_name,iface,sizeof(ifreq.ifrn_name) - 1);
|
||||
ast_copy_string(ifreq.ifrn_name, iface, sizeof(ifreq.ifrn_name));
|
||||
|
||||
mysock = socket(PF_INET,SOCK_DGRAM,IPPROTO_IP);
|
||||
res = ioctl(mysock,SIOCGIFADDR,&ifreq);
|
||||
mysock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
|
||||
res = ioctl(mysock, SIOCGIFADDR, &ifreq);
|
||||
|
||||
close(mysock);
|
||||
if (res < 0) {
|
||||
ast_log(LOG_WARNING, "Unable to get IP of %s: %s\n", iface, strerror(errno));
|
||||
memcpy((char *)address,(char *)&__ourip,sizeof(__ourip));
|
||||
memcpy((char *)address, (char *)&__ourip, sizeof(__ourip));
|
||||
return -1;
|
||||
} else {
|
||||
memcpy((char *)address,(char *)&ifreq.ifru_addr.sin_addr,sizeof(ifreq.ifru_addr.sin_addr));
|
||||
memcpy((char *)address, (char *)&ifreq.ifru_addr.sin_addr, sizeof(ifreq.ifru_addr.sin_addr));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int ast_ouraddrfor(struct in_addr *them, struct in_addr *us)
|
||||
{
|
||||
#ifdef __OpenBSD__
|
||||
struct sockaddr_in *sin;
|
||||
struct sockaddr *sa;
|
||||
struct {
|
||||
struct rt_msghdr m_rtm;
|
||||
char m_space[512];
|
||||
} m_rtmsg;
|
||||
char *cp, *p = ast_strdupa(inet_ntoa(*them));
|
||||
int i, l, s, seq, flags;
|
||||
pid_t pid = getpid();
|
||||
static int routeseq; /* Protected by "routeseq_lock" mutex */
|
||||
int s;
|
||||
struct sockaddr_in sin;
|
||||
socklen_t slen;
|
||||
|
||||
memset(us, 0, sizeof(struct in_addr));
|
||||
|
||||
memset(&m_rtmsg, 0, sizeof(m_rtmsg));
|
||||
m_rtmsg.m_rtm.rtm_type = RTM_GET;
|
||||
m_rtmsg.m_rtm.rtm_flags = RTF_UP | RTF_HOST;
|
||||
m_rtmsg.m_rtm.rtm_version = RTM_VERSION;
|
||||
ast_mutex_lock(&routeseq_lock);
|
||||
seq = ++routeseq;
|
||||
ast_mutex_unlock(&routeseq_lock);
|
||||
m_rtmsg.m_rtm.rtm_seq = seq;
|
||||
m_rtmsg.m_rtm.rtm_addrs = RTA_IFA | RTA_DST;
|
||||
m_rtmsg.m_rtm.rtm_msglen = sizeof(struct rt_msghdr) + sizeof(struct sockaddr_in);
|
||||
sin = (struct sockaddr_in *)m_rtmsg.m_space;
|
||||
sin->sin_family = AF_INET;
|
||||
sin->sin_len = sizeof(struct sockaddr_in);
|
||||
sin->sin_addr = *them;
|
||||
|
||||
if ((s = socket(PF_ROUTE, SOCK_RAW, 0)) < 0) {
|
||||
ast_log(LOG_ERROR, "Error opening routing socket\n");
|
||||
s = socket(PF_INET, SOCK_DGRAM, 0);
|
||||
if (s < 0) {
|
||||
ast_log(LOG_WARNING, "Cannot create socket\n");
|
||||
return -1;
|
||||
}
|
||||
flags = fcntl(s, F_GETFL);
|
||||
fcntl(s, F_SETFL, flags | O_NONBLOCK);
|
||||
if (write(s, (char *)&m_rtmsg, m_rtmsg.m_rtm.rtm_msglen) < 0) {
|
||||
ast_log(LOG_ERROR, "Error writing to routing socket: %s\n", strerror(errno));
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_port = 5060;
|
||||
sin.sin_addr = *them;
|
||||
if (connect(s, (struct sockaddr *)&sin, sizeof(sin))) {
|
||||
ast_log(LOG_WARNING, "Cannot connect\n");
|
||||
close(s);
|
||||
return -1;
|
||||
}
|
||||
do {
|
||||
l = read(s, (char *)&m_rtmsg, sizeof(m_rtmsg));
|
||||
} while (l > 0 && (m_rtmsg.m_rtm.rtm_seq != 1 || m_rtmsg.m_rtm.rtm_pid != pid));
|
||||
if (l < 0) {
|
||||
if (errno != EAGAIN)
|
||||
ast_log(LOG_ERROR, "Error reading from routing socket\n");
|
||||
slen = sizeof(sin);
|
||||
if (getsockname(s, (struct sockaddr *)&sin, &slen)) {
|
||||
ast_log(LOG_WARNING, "Cannot get socket name\n");
|
||||
close(s);
|
||||
return -1;
|
||||
}
|
||||
close(s);
|
||||
|
||||
if (m_rtmsg.m_rtm.rtm_version != RTM_VERSION) {
|
||||
ast_log(LOG_ERROR, "Unsupported route socket protocol version\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (m_rtmsg.m_rtm.rtm_msglen != l)
|
||||
ast_log(LOG_WARNING, "Message length mismatch, in packet %d, returned %d\n",
|
||||
m_rtmsg.m_rtm.rtm_msglen, l);
|
||||
|
||||
if (m_rtmsg.m_rtm.rtm_errno) {
|
||||
ast_log(LOG_ERROR, "RTM_GET got %s (%d)\n",
|
||||
strerror(m_rtmsg.m_rtm.rtm_errno), m_rtmsg.m_rtm.rtm_errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
cp = (char *)m_rtmsg.m_space;
|
||||
if (m_rtmsg.m_rtm.rtm_addrs)
|
||||
for (i = 1; i; i <<= 1)
|
||||
if (m_rtmsg.m_rtm.rtm_addrs & i) {
|
||||
sa = (struct sockaddr *)cp;
|
||||
if (i == RTA_IFA && sa->sa_family == AF_INET) {
|
||||
sin = (struct sockaddr_in *)sa;
|
||||
*us = sin->sin_addr;
|
||||
ast_log(LOG_DEBUG, "Found route to %s, output from our address %s.\n", p, inet_ntoa(*us));
|
||||
return 0;
|
||||
}
|
||||
cp += sa->sa_len > 0 ?
|
||||
(1 + ((sa->sa_len - 1) | (sizeof(long) - 1))) :
|
||||
sizeof(long);
|
||||
}
|
||||
|
||||
ast_log(LOG_DEBUG, "No route found for address %s!\n", p);
|
||||
return -1;
|
||||
#else
|
||||
FILE *PROC;
|
||||
unsigned int remote_ip;
|
||||
int res = 1;
|
||||
char line[256];
|
||||
remote_ip = them->s_addr;
|
||||
|
||||
PROC = fopen("/proc/net/route","r");
|
||||
if (!PROC) {
|
||||
bzero(us,sizeof(struct in_addr));
|
||||
return -1;
|
||||
}
|
||||
/* First line contains headers */
|
||||
fgets(line,sizeof(line),PROC);
|
||||
|
||||
while (!feof(PROC)) {
|
||||
char iface[8];
|
||||
unsigned int dest, gateway, mask;
|
||||
int i,fieldnum;
|
||||
char *fields[40];
|
||||
|
||||
fgets(line,sizeof(line),PROC);
|
||||
|
||||
fieldnum = 0;
|
||||
for (i=0;i<sizeof(line);i++) {
|
||||
char *offset;
|
||||
|
||||
fields[fieldnum++] = line + i;
|
||||
offset = strchr(line + i,'\t');
|
||||
if (offset == NULL) {
|
||||
/* Exit loop */
|
||||
break;
|
||||
} else if (fieldnum >= 9) {
|
||||
/* Short-circuit: can't break at 8, since the end of field 7 is figured when fieldnum=8 */
|
||||
break;
|
||||
} else {
|
||||
*offset = '\0';
|
||||
i = offset - line;
|
||||
}
|
||||
}
|
||||
|
||||
sscanf(fields[0],"%s",iface);
|
||||
sscanf(fields[1],"%x",&dest);
|
||||
sscanf(fields[2],"%x",&gateway);
|
||||
sscanf(fields[7],"%x",&mask);
|
||||
#if 0
|
||||
printf("Addr: %s %08x Dest: %08x Mask: %08x\n", inet_ntoa(*them), remote_ip, dest, mask);
|
||||
#endif
|
||||
/* Looks simple, but here is the magic */
|
||||
if (((remote_ip & mask) ^ dest) == 0) {
|
||||
res = ast_lookup_iface(iface,us);
|
||||
break;
|
||||
}
|
||||
}
|
||||
fclose(PROC);
|
||||
if (res == 1) {
|
||||
ast_log(LOG_WARNING, "Yikes! No default route?!!\n");
|
||||
bzero(us,sizeof(struct in_addr));
|
||||
return -2;
|
||||
} else if (res) {
|
||||
/* We've already warned in subroutine */
|
||||
return -1;
|
||||
}
|
||||
*us = sin.sin_addr;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
int ast_find_ourip(struct in_addr *ourip, struct sockaddr_in bindaddr)
|
||||
{
|
||||
char ourhost[MAXHOSTNAMELEN] = "";
|
||||
struct ast_hostent ahp;
|
||||
struct hostent *hp;
|
||||
struct in_addr saddr;
|
||||
|
||||
/* just use the bind address if it is nonzero */
|
||||
if (ntohl(bindaddr.sin_addr.s_addr)) {
|
||||
memcpy(ourip, &bindaddr.sin_addr, sizeof(*ourip));
|
||||
return 0;
|
||||
}
|
||||
/* try to use our hostname */
|
||||
if (gethostname(ourhost, sizeof(ourhost) - 1)) {
|
||||
ast_log(LOG_WARNING, "Unable to get hostname\n");
|
||||
} else {
|
||||
hp = ast_gethostbyname(ourhost, &ahp);
|
||||
if (hp) {
|
||||
memcpy(ourip, hp->h_addr, sizeof(*ourip));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/* A.ROOT-SERVERS.NET. */
|
||||
if (inet_aton("198.41.0.4", &saddr) && !ast_ouraddrfor(&saddr, ourip))
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
4
aescrypt.c
Executable file → Normal file
4
aescrypt.c
Executable file → Normal file
@@ -30,7 +30,9 @@
|
||||
---------------------------------------------------------------------------
|
||||
Issue Date: 26/08/2003
|
||||
|
||||
This file contains the code for implementing encryption and decryption
|
||||
*/
|
||||
/*! \file
|
||||
\brief This file contains the code for implementing encryption and decryption
|
||||
for AES (Rijndael) for block and key sizes of 16, 24 and 32 bytes. It
|
||||
can optionally be replaced by code written in assembler using NASM. For
|
||||
further details see the file aesopt.h
|
||||
|
||||
4
aeskey.c
Executable file → Normal file
4
aeskey.c
Executable file → Normal file
@@ -30,7 +30,9 @@
|
||||
---------------------------------------------------------------------------
|
||||
Issue Date: 26/08/2003
|
||||
|
||||
This file contains the code for implementing the key schedule for AES
|
||||
*/
|
||||
/*! \file
|
||||
\brief This file contains the code for implementing the key schedule for AES
|
||||
(Rijndael) for block and key sizes of 16, 24, and 32 bytes. See aesopt.h
|
||||
for further details including optimisation.
|
||||
*/
|
||||
|
||||
16
aesopt.h
Executable file → Normal file
16
aesopt.h
Executable file → Normal file
@@ -135,7 +135,8 @@
|
||||
#ifndef _AESOPT_H
|
||||
#define _AESOPT_H
|
||||
|
||||
#include <asterisk/aes.h>
|
||||
#include "asterisk/aes.h"
|
||||
#include "asterisk/endian.h"
|
||||
|
||||
/* CONFIGURATION - USE OF DEFINES
|
||||
|
||||
@@ -146,19 +147,6 @@
|
||||
#if clauses.
|
||||
*/
|
||||
|
||||
/* PLATFORM SPECIFIC INCLUDES */
|
||||
|
||||
#if defined( __FreeBSD__ ) || defined( __OpenBSD__ )
|
||||
# include <sys/endian.h>
|
||||
#elif defined( BSD ) && ( BSD >= 199103 )
|
||||
# include <machine/endian.h>
|
||||
#elif defined( __GNUC__ ) || defined( __GNU_LIBRARY__ )
|
||||
# include <endian.h>
|
||||
# include <byteswap.h>
|
||||
#elif defined( linux )
|
||||
# include <endian.h>
|
||||
#endif
|
||||
|
||||
/* BYTE ORDER IN 32-BIT WORDS
|
||||
|
||||
To obtain the highest speed on processors with 32-bit words, this code
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
eagi-test
|
||||
eagi-sphinx-test
|
||||
.depend
|
||||
0
agi/DialAnMp3.agi
Executable file → Normal file
0
agi/DialAnMp3.agi
Executable file → Normal file
25
agi/Makefile
Executable file → Normal file
25
agi/Makefile
Executable file → Normal file
@@ -1,11 +1,11 @@
|
||||
#
|
||||
# Asterisk -- A telephony toolkit for Linux.
|
||||
#
|
||||
# Makefile for PBX frontends (dynamically loaded)
|
||||
# Makefile for AGI-related stuff
|
||||
#
|
||||
# Copyright (C) 1999, Mark Spencer
|
||||
# Copyright (C) 1999-2005, Digium
|
||||
#
|
||||
# Mark Spencer <markster@linux-support.net>
|
||||
# Mark Spencer <markster@digium.com>
|
||||
#
|
||||
# This program is free software, distributed under the terms of
|
||||
# the GNU General Public License
|
||||
@@ -15,6 +15,15 @@ AGIS=agi-test.agi eagi-test eagi-sphinx-test
|
||||
|
||||
CFLAGS+=
|
||||
|
||||
LIBS=
|
||||
ifeq ($(OSARCH),SunOS)
|
||||
LIBS=-lsocket -lnsl ../strcompat.o
|
||||
endif
|
||||
|
||||
ifeq ($(findstring BSD,${OSARCH}),BSD)
|
||||
CFLAGS+=-I$(CROSS_COMPILE_TARGET)/usr/local/include -L$(CROSS_COMPILE_TARGET)/usr/local/lib
|
||||
endif
|
||||
|
||||
all: depend $(AGIS)
|
||||
|
||||
install: all
|
||||
@@ -22,13 +31,13 @@ install: all
|
||||
for x in $(AGIS); do $(INSTALL) -m 755 $$x $(DESTDIR)$(AGI_DIR) ; done
|
||||
|
||||
eagi-test: eagi-test.o
|
||||
$(CC) -o eagi-test eagi-test.o
|
||||
|
||||
$(CC) $(CFLAGS) -o eagi-test eagi-test.o $(LIBS)
|
||||
|
||||
eagi-sphinx-test: eagi-sphinx-test.o
|
||||
$(CC) -o eagi-sphinx-test eagi-sphinx-test.o
|
||||
$(CC) $(CFLAGS) -o eagi-sphinx-test eagi-sphinx-test.o $(LIBS)
|
||||
|
||||
clean:
|
||||
rm -f *.so *.o look .depend
|
||||
rm -f *.so *.o look .depend eagi-test eagi-sphinx-test
|
||||
|
||||
%.so : %.o
|
||||
$(CC) -shared -Xlinker -x -o $@ $<
|
||||
@@ -40,4 +49,4 @@ endif
|
||||
depend: .depend
|
||||
|
||||
.depend:
|
||||
../mkdep $(CFLAGS) `ls *.c`
|
||||
../build_tools/mkdep $(CFLAGS) `ls *.c`
|
||||
|
||||
0
agi/agi-test.agi
Executable file → Normal file
0
agi/agi-test.agi
Executable file → Normal file
1
agi/eagi-sphinx-test.c
Executable file → Normal file
1
agi/eagi-sphinx-test.c
Executable file → Normal file
@@ -17,6 +17,7 @@
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <asterisk/compat.h>
|
||||
|
||||
#define AUDIO_FILENO (STDERR_FILENO + 1)
|
||||
|
||||
|
||||
1
agi/eagi-test.c
Executable file → Normal file
1
agi/eagi-test.c
Executable file → Normal file
@@ -11,6 +11,7 @@
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <sys/select.h>
|
||||
#include <asterisk/compat.h>
|
||||
|
||||
#define AUDIO_FILENO (STDERR_FILENO + 1)
|
||||
|
||||
|
||||
94
agi/fastagi-test
Normal file
94
agi/fastagi-test
Normal file
@@ -0,0 +1,94 @@
|
||||
#!/usr/bin/perl
|
||||
use strict;
|
||||
use Socket;
|
||||
use Carp;
|
||||
use IO::Handle;
|
||||
|
||||
my $port = 4573;
|
||||
|
||||
$|=1;
|
||||
|
||||
# Setup some variables
|
||||
my %AGI; my $tests = 0; my $fail = 0; my $pass = 0;
|
||||
|
||||
sub checkresult {
|
||||
my ($res) = @_;
|
||||
my $retval;
|
||||
$tests++;
|
||||
chomp $res;
|
||||
if ($res =~ /^200/) {
|
||||
$res =~ /result=(-?\d+)/;
|
||||
if (!length($1)) {
|
||||
print STDERR "FAIL ($res)\n";
|
||||
$fail++;
|
||||
} else {
|
||||
print STDERR "PASS ($1)\n";
|
||||
$pass++;
|
||||
}
|
||||
} else {
|
||||
print STDERR "FAIL (unexpected result '$res')\n";
|
||||
$fail++;
|
||||
}
|
||||
}
|
||||
|
||||
socket(SERVER, PF_INET, SOCK_STREAM, 0);
|
||||
setsockopt(SERVER, SOL_SOCKET, SO_REUSEADDR, pack("l", 1));
|
||||
bind(SERVER, sockaddr_in($port, INADDR_ANY)) || die("can't bind\n");
|
||||
listen(SERVER, SOMAXCONN);
|
||||
|
||||
for(;;) {
|
||||
my $raddr = accept(CLIENT, SERVER);
|
||||
my ($s, $p) = sockaddr_in($raddr);
|
||||
CLIENT->autoflush(1);
|
||||
while(<CLIENT>) {
|
||||
chomp;
|
||||
last unless length($_);
|
||||
if (/^agi_(\w+)\:\s+(.*)$/) {
|
||||
$AGI{$1} = $2;
|
||||
}
|
||||
}
|
||||
print STDERR "AGI Environment Dump from $s:$p --\n";
|
||||
foreach my $i (sort keys %AGI) {
|
||||
print STDERR " -- $i = $AGI{$i}\n";
|
||||
}
|
||||
|
||||
print STDERR "1. Testing 'sendfile'...";
|
||||
print CLIENT "STREAM FILE beep \"\"\n";
|
||||
my $result = <CLIENT>;
|
||||
&checkresult($result);
|
||||
|
||||
print STDERR "2. Testing 'sendtext'...";
|
||||
print CLIENT "SEND TEXT \"hello world\"\n";
|
||||
my $result = <CLIENT>;
|
||||
&checkresult($result);
|
||||
|
||||
print STDERR "3. Testing 'sendimage'...";
|
||||
print CLIENT "SEND IMAGE asterisk-image\n";
|
||||
my $result = <CLIENT>;
|
||||
&checkresult($result);
|
||||
|
||||
print STDERR "4. Testing 'saynumber'...";
|
||||
print CLIENT "SAY NUMBER 192837465 \"\"\n";
|
||||
my $result = <CLIENT>;
|
||||
&checkresult($result);
|
||||
|
||||
print STDERR "5. Testing 'waitdtmf'...";
|
||||
print CLIENT "WAIT FOR DIGIT 1000\n";
|
||||
my $result = <CLIENT>;
|
||||
&checkresult($result);
|
||||
|
||||
print STDERR "6. Testing 'record'...";
|
||||
print CLIENT "RECORD FILE testagi gsm 1234 3000\n";
|
||||
my $result = <CLIENT>;
|
||||
&checkresult($result);
|
||||
|
||||
print STDERR "6a. Testing 'record' playback...";
|
||||
print CLIENT "STREAM FILE testagi \"\"\n";
|
||||
my $result = <CLIENT>;
|
||||
&checkresult($result);
|
||||
close(CLIENT);
|
||||
print STDERR "================== Complete ======================\n";
|
||||
print STDERR "$tests tests completed, $pass passed, $fail failed\n";
|
||||
print STDERR "==================================================\n";
|
||||
}
|
||||
|
||||
0
agi/numeralize
Executable file → Normal file
0
agi/numeralize
Executable file → Normal file
29
alaw.c
Executable file → Normal file
29
alaw.c
Executable file → Normal file
@@ -1,17 +1,32 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* u-Law to Signed linear conversion
|
||||
*
|
||||
* Copyright (C) 1999, Mark Spencer
|
||||
* Copyright (C) 1999 - 2005, Digium, Inc.
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
* Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
#include <asterisk/alaw.h>
|
||||
/*! \file
|
||||
*
|
||||
* \brief u-Law to Signed linear conversion
|
||||
*
|
||||
*/
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/alaw.h"
|
||||
|
||||
#define AMI_MASK 0x55
|
||||
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
.depend
|
||||
127
apps/Makefile
Executable file → Normal file
127
apps/Makefile
Executable file → Normal file
@@ -1,51 +1,87 @@
|
||||
#
|
||||
# Asterisk -- A telephony toolkit for Linux.
|
||||
#
|
||||
# Makefile for PBX frontends (dynamically loaded)
|
||||
# Makefile for PBX applications
|
||||
#
|
||||
# Copyright (C) 1999, Mark Spencer
|
||||
# Copyright (C) 1999-2005, Digium
|
||||
#
|
||||
# Mark Spencer <markster@linux-support.net>
|
||||
# Mark Spencer <markster@digium.com>
|
||||
#
|
||||
# This program is free software, distributed under the terms of
|
||||
# the GNU General Public License
|
||||
#
|
||||
|
||||
USE_MYSQL_VM_INTERFACE=0
|
||||
USE_POSTGRES_VM_INTERFACE=0
|
||||
|
||||
#APPS=app_dial.so app_playback.so app_directory.so app_intercom.so app_mp3.so
|
||||
APPS=app_dial.so app_playback.so app_voicemail.so app_directory.so app_mp3.so\
|
||||
app_system.so app_echo.so app_record.so app_image.so app_url.so app_disa.so \
|
||||
app_agi.so app_qcall.so app_adsiprog.so app_getcpeid.so app_milliwatt.so \
|
||||
app_zapateller.so app_datetime.so app_setcallerid.so app_festival.so \
|
||||
app_queue.so app_senddtmf.so app_parkandannounce.so app_striplsd.so \
|
||||
app_setcidname.so app_lookupcidname.so app_substring.so app_macro.so \
|
||||
app_adsiprog.so app_getcpeid.so app_milliwatt.so \
|
||||
app_zapateller.so app_setcallerid.so app_festival.so \
|
||||
app_queue.so app_senddtmf.so app_parkandannounce.so \
|
||||
app_setcidname.so app_lookupcidname.so app_macro.so \
|
||||
app_authenticate.so app_softhangup.so app_lookupblacklist.so \
|
||||
app_waitforring.so app_privacy.so app_db.so app_chanisavail.so \
|
||||
app_enumlookup.so app_transfer.so app_setcidnum.so app_cdr.so \
|
||||
app_hasnewvoicemail.so app_sayunixtime.so app_cut.so app_read.so \
|
||||
app_setcdruserfield.so app_random.so
|
||||
|
||||
ifneq (${OSARCH},Darwin)
|
||||
APPS+=app_intercom.so
|
||||
endif
|
||||
app_setcdruserfield.so app_random.so app_ices.so app_eval.so \
|
||||
app_nbscat.so app_sendtext.so app_exec.so \
|
||||
app_groupcount.so app_txtcidname.so app_controlplayback.so \
|
||||
app_talkdetect.so app_alarmreceiver.so app_userevent.so app_verbose.so \
|
||||
app_test.so app_forkcdr.so app_math.so app_realtime.so \
|
||||
app_dumpchan.so app_waitforsilence.so app_while.so app_setrdnis.so \
|
||||
app_md5.so app_readfile.so app_chanspy.so app_settransfercapability.so \
|
||||
app_dictate.so app_externalivr.so app_directed_pickup.so \
|
||||
app_mixmonitor.so app_stack.so
|
||||
|
||||
#
|
||||
# Obsolete things...
|
||||
#
|
||||
#APPS+=app_sql_postgres.so
|
||||
#APPS+=app_sql_odbc.so
|
||||
|
||||
APPS+=$(shell if [ -f /usr/include/linux/zaptel.h ]; then echo "app_zapras.so app_meetme.so app_flash.so app_zapbarge.so app_zapscan.so" ; fi)
|
||||
#APPS+=$(shell if [ -f /usr/include/zap.h ]; then echo "app_rpt.so" ; fi)
|
||||
#
|
||||
# Experimental things
|
||||
#
|
||||
#APPS+=app_ivrdemo.so
|
||||
#APPS+=app_skel.so
|
||||
#APPS+=app_rpt.so
|
||||
|
||||
ifndef WITHOUT_ZAPTEL
|
||||
ifneq ($(wildcard $(CROSS_COMPILE_TARGET)/usr/include/linux/zaptel.h)$(wildcard $(CROSS_COMPILE_TARGET)/usr/local/include/zaptel.h),)
|
||||
APPS+=app_zapras.so app_meetme.so app_flash.so app_zapbarge.so app_zapscan.so app_page.so
|
||||
endif
|
||||
endif # WITHOUT_ZAPTEL
|
||||
|
||||
ifneq ($(wildcard $(CROSS_COMPILE_TARGET)/usr/local/include/osp/osp.h $(CROSS_COMPILE_TARGET)/usr/include/osp/osp.h),)
|
||||
APPS+=app_osplookup.so
|
||||
endif
|
||||
|
||||
ifeq ($(findstring BSD,${OSARCH}),BSD)
|
||||
CFLAGS+=-I$(CROSS_COMPILE_TARGET)/usr/local/include -L$(CROSS_COMPILE_TARGET)/usr/local/lib
|
||||
endif
|
||||
|
||||
CURLLIBS=$(shell $(CROSS_COMPILE_BIN)curl-config --libs)
|
||||
ifneq ($(shell if [[ 0x`$(CROSS_COMPILE_BIN)curl-config --vernum` -ge 0x70907 ]]; then echo "OK" ; fi),)
|
||||
ifneq (${CURLLIBS},)
|
||||
APPS+=app_curl.so
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq (${OSARCH},CYGWIN)
|
||||
CYGSOLINK=-Wl,--out-implib=lib$@.a -Wl,--export-all-symbols
|
||||
CYGSOLIB=-L.. -L. -L../res -lasterisk.dll -lres_features.so -lres_adsi.so -lres_monitor.so
|
||||
else
|
||||
CFLAGS+=-fPIC
|
||||
|
||||
ifeq ($(USE_POSTGRES_VM_INTERFACE),1)
|
||||
CFLAGS+=-DUSEPOSTGRESVM
|
||||
APPS+=app_sms.so
|
||||
endif
|
||||
|
||||
ifeq ($(USE_MYSQL_VM_INTERFACE),1)
|
||||
CFLAGS+=-DUSEMYSQLVM
|
||||
endif
|
||||
#
|
||||
# If you have UnixODBC you can use ODBC voicemail
|
||||
# storage
|
||||
#
|
||||
# Uncomment to use ODBC storage
|
||||
#CFLAGS+=-DUSE_ODBC_STORAGE
|
||||
# Uncomment for extended ODBC voicemail storage
|
||||
#CFLAGS+=-DEXTENDED_ODBC_STORAGE
|
||||
# See doc/README.odbcstorage for more information
|
||||
|
||||
all: $(APPS)
|
||||
|
||||
@@ -53,48 +89,45 @@ clean:
|
||||
rm -f *.so *.o look .depend
|
||||
|
||||
%.so : %.o
|
||||
$(CC) $(SOLINK) -o $@ $<
|
||||
$(CC) $(SOLINK) -o $@ ${CYGSOLINK} $< ${CYGSOLIB}
|
||||
|
||||
app_rpt.so : app_rpt.o
|
||||
$(CC) $(SOLINK) -o $@ $< -ltonezone
|
||||
$(CC) $(SOLINK) -o $@ ${CYGSOLINK} $< ${CYGSOLIB} -ltonezone
|
||||
|
||||
install: all
|
||||
for x in $(APPS); do $(INSTALL) -m 755 $$x $(DESTDIR)$(MODULES_DIR) ; done
|
||||
rm -f $(DESTDIR)$(MODULES_DIR)/app_datetime.so
|
||||
rm -f $(DESTDIR)$(MODULES_DIR)/app_qcall.so
|
||||
|
||||
app_todd.o: app_todd.c
|
||||
gcc -pipe -O6 -g -Iinclude -I../include -D_REENTRANT -march=i586 -DDO_CRASH -c -o app_todd.o app_todd.c
|
||||
|
||||
app_todd.so: app_todd.o
|
||||
$(CC) $(SOLINK) -o $@ $< -L/usr/local/ssl/lib -lssl -lcrypto
|
||||
|
||||
app_voicemail.so : app_voicemail.o
|
||||
ifeq ($(USE_MYSQL_VM_INTERFACE),1)
|
||||
$(CC) $(SOLINK) -o $@ $(MLFLAGS) $< -L/usr/lib/mysql -lmysqlclient -lz
|
||||
else
|
||||
ifeq ($(USE_POSTGRES_VM_INTERFACE),1)
|
||||
$(CC) $(SOLINK) -o $@ $(MLFLAGS) $< -lpq
|
||||
else
|
||||
$(CC) $(SOLINK) -o $@ $(MLFLAGS) $<
|
||||
endif
|
||||
endif
|
||||
app_curl.so: app_curl.o
|
||||
$(CC) $(SOLINK) -o $@ ${CYGSOLINK} $< ${CYGSOLIB} $(CURLLIBS)
|
||||
|
||||
app_sql_postgres.o: app_sql_postgres.c
|
||||
$(CC) -pipe -I/usr/local/pgsql/include $(CFLAGS) -c -o app_sql_postgres.o app_sql_postgres.c
|
||||
|
||||
app_sql_postgres.so: app_sql_postgres.o
|
||||
$(CC) $(SOLINK) -o $@ $< -L/usr/local/pgsql/lib -lpq
|
||||
$(CC) $(SOLINK) -o $@ ${CYGSOLINK} $< ${CYGSOLIB} -L/usr/local/pgsql/lib -lpq
|
||||
|
||||
app_sql_odbc.so: app_sql_odbc.o
|
||||
$(CC) $(SOLINK) -o $@ $< -lodbc
|
||||
$(CC) $(SOLINK) -o $@ ${CYGSOLINK} $< ${CYGSOLIB} -lodbc
|
||||
|
||||
look: look.c
|
||||
gcc -pipe -O6 -g look.c -o look -lncurses
|
||||
$(CC) -pipe -O6 -g look.c -o look -lncurses
|
||||
|
||||
ifeq (SunOS,$(shell uname))
|
||||
app_chanspy.so: app_chanspy.o
|
||||
$(CC) $(SOLINK) -o $@ $< -lrt
|
||||
endif
|
||||
|
||||
|
||||
ifneq ($(wildcard .depend),)
|
||||
include .depend
|
||||
include .depend
|
||||
endif
|
||||
|
||||
depend: .depend
|
||||
|
||||
.depend:
|
||||
../mkdep $(CFLAGS) `ls *.c`
|
||||
../build_tools/mkdep $(CFLAGS) `ls *.c`
|
||||
|
||||
env:
|
||||
env
|
||||
|
||||
113
apps/app_adsiprog.c
Executable file → Normal file
113
apps/app_adsiprog.c
Executable file → Normal file
@@ -1,24 +1,28 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Program Asterisk ADSI Scripts into phone
|
||||
*
|
||||
* Copyright (C) 1999, Mark Spencer
|
||||
* Copyright (C) 1999 - 2005, Digium, Inc.
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
* Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
* \brief Program Asterisk ADSI Scripts into phone
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/adsi.h>
|
||||
#include <asterisk/options.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
@@ -28,10 +32,19 @@
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <pthread.h>
|
||||
#include "asterisk.h"
|
||||
|
||||
#include "../asterisk.h"
|
||||
#include "../astconf.h"
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/adsi.h"
|
||||
#include "asterisk/options.h"
|
||||
#include "asterisk/utils.h"
|
||||
#include "asterisk/lock.h"
|
||||
|
||||
static char *tdesc = "Asterisk ADSI Programming Application";
|
||||
|
||||
@@ -42,9 +55,8 @@ static char *synopsis = "Load Asterisk ADSI Scripts into phone";
|
||||
/* #define DUMP_MESSAGES */
|
||||
|
||||
static char *descrip =
|
||||
" ADSIProg(script): Programs an ADSI Phone with the given script.\n"
|
||||
"If none is specified, the default is used. Returns 0 unless CPE\n"
|
||||
"is hungup.\n";
|
||||
" ADSIProg(script): This application programs an ADSI Phone with the given\n"
|
||||
"script. If nothing is specified, the default script (asterisk.adsi) is used.\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
@@ -159,9 +171,9 @@ struct adsi_script {
|
||||
struct adsi_flag flags[7];
|
||||
|
||||
/* Stuff from adsi script */
|
||||
char sec[5];
|
||||
unsigned char sec[5];
|
||||
char desc[19];
|
||||
char fdn[5];
|
||||
unsigned char fdn[5];
|
||||
int ver;
|
||||
};
|
||||
|
||||
@@ -178,7 +190,7 @@ static int process_token(void *out, char *src, int maxlen, int argtype)
|
||||
maxlen = strlen(src) - 1;
|
||||
memcpy(out, src, maxlen);
|
||||
((char *)out)[maxlen] = '\0';
|
||||
} else if (strlen(src) && (src[0] == '\\')) {
|
||||
} else if (!ast_strlen_zero(src) && (src[0] == '\\')) {
|
||||
if (!(argtype & ARG_NUMBER))
|
||||
return -1;
|
||||
/* Octal value */
|
||||
@@ -198,7 +210,7 @@ static int process_token(void *out, char *src, int maxlen, int argtype)
|
||||
/* Convert */
|
||||
*((unsigned int *)out) = htonl(*((unsigned int *)out));
|
||||
}
|
||||
} else if ((strlen(src) && isdigit(src[0]))) {
|
||||
} else if ((!ast_strlen_zero(src) && isdigit(src[0]))) {
|
||||
if (!(argtype & ARG_NUMBER))
|
||||
return -1;
|
||||
/* Hex value */
|
||||
@@ -400,7 +412,7 @@ static struct adsi_flag *getflagbyname(struct adsi_script *state, char *name, ch
|
||||
ast_log(LOG_WARNING, "No more flag space at line %d of %s\n", lineno, script);
|
||||
return NULL;
|
||||
}
|
||||
strncpy(state->flags[state->numflags].vname, name, sizeof(state->flags[state->numflags].vname) - 1);
|
||||
ast_copy_string(state->flags[state->numflags].vname, name, sizeof(state->flags[state->numflags].vname));
|
||||
state->flags[state->numflags].id = state->numflags + 1;
|
||||
state->numflags++;
|
||||
return &state->flags[state->numflags-1];
|
||||
@@ -503,7 +515,7 @@ static struct adsi_soft_key *getkeybyname(struct adsi_script *state, char *name,
|
||||
ast_log(LOG_WARNING, "No more key space at line %d of %s\n", lineno, script);
|
||||
return NULL;
|
||||
}
|
||||
strncpy(state->keys[state->numkeys].vname, name, sizeof(state->keys[state->numkeys].vname) - 1);
|
||||
ast_copy_string(state->keys[state->numkeys].vname, name, sizeof(state->keys[state->numkeys].vname));
|
||||
state->keys[state->numkeys].id = state->numkeys + 2;
|
||||
state->numkeys++;
|
||||
return &state->keys[state->numkeys-1];
|
||||
@@ -519,7 +531,7 @@ static struct adsi_subscript *getsubbyname(struct adsi_script *state, char *name
|
||||
ast_log(LOG_WARNING, "No more subscript space at line %d of %s\n", lineno, script);
|
||||
return NULL;
|
||||
}
|
||||
strncpy(state->subs[state->numsubs].vname, name, sizeof(state->subs[state->numsubs].vname) - 1);
|
||||
ast_copy_string(state->subs[state->numsubs].vname, name, sizeof(state->subs[state->numsubs].vname));
|
||||
state->subs[state->numsubs].id = state->numsubs;
|
||||
state->numsubs++;
|
||||
return &state->subs[state->numsubs-1];
|
||||
@@ -538,7 +550,7 @@ static struct adsi_state *getstatebyname(struct adsi_script *state, char *name,
|
||||
ast_log(LOG_WARNING, "No more state space at line %d of %s\n", lineno, script);
|
||||
return NULL;
|
||||
}
|
||||
strncpy(state->states[state->numstates].vname, name, sizeof(state->states[state->numstates].vname) - 1);
|
||||
ast_copy_string(state->states[state->numstates].vname, name, sizeof(state->states[state->numstates].vname));
|
||||
state->states[state->numstates].id = state->numstates + 1;
|
||||
state->numstates++;
|
||||
return &state->states[state->numstates-1];
|
||||
@@ -557,7 +569,7 @@ static struct adsi_display *getdisplaybyname(struct adsi_script *state, char *na
|
||||
ast_log(LOG_WARNING, "No more display space at line %d of %s\n", lineno, script);
|
||||
return NULL;
|
||||
}
|
||||
strncpy(state->displays[state->numdisplays].vname, name, sizeof(state->displays[state->numdisplays].vname) - 1);
|
||||
ast_copy_string(state->displays[state->numdisplays].vname, name, sizeof(state->displays[state->numdisplays].vname));
|
||||
state->displays[state->numdisplays].id = state->numdisplays + 1;
|
||||
state->numdisplays++;
|
||||
return &state->displays[state->numdisplays-1];
|
||||
@@ -666,7 +678,7 @@ static int showdisplay(char *buf, char *name, int id, char *args, struct adsi_sc
|
||||
}
|
||||
|
||||
buf[0] = id;
|
||||
buf[1] = (cmd << 6) | (disp->id & 0x2f);
|
||||
buf[1] = (cmd << 6) | (disp->id & 0x3f);
|
||||
buf[2] = ((line & 0x1f) << 3) | (flag & 0x7);
|
||||
return 3;
|
||||
}
|
||||
@@ -695,6 +707,18 @@ static int digitdirect(char *buf, char *name, int id, char *args, struct adsi_sc
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int clearcbone(char *buf, char *name, int id, char *args, struct adsi_script *istate, char *script, int lineno)
|
||||
{
|
||||
char *tok;
|
||||
tok = get_token(&args, script, lineno);
|
||||
if (tok)
|
||||
ast_log(LOG_WARNING, "CLEARCB1 requires no arguments ('%s') at line %d of %s\n", tok, lineno, script);
|
||||
|
||||
buf[0] = id;
|
||||
buf[1] = 0;
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int digitcollect(char *buf, char *name, int id, char *args, struct adsi_script *istate, char *script, int lineno)
|
||||
{
|
||||
char *tok;
|
||||
@@ -831,6 +855,7 @@ static struct adsi_key_cmd kcmds[] = {
|
||||
{ "VOICEMODE", 0x93 },
|
||||
/* Display call buffer 'n' */
|
||||
/* Clear call buffer 'n' */
|
||||
{ "CLEARCB1", 0x95, clearcbone },
|
||||
{ "DIGITCOLLECT", 0x96, digitcollect },
|
||||
{ "DIGITDIRECT", 0x96, digitdirect },
|
||||
{ "CLEAR", 0x97 },
|
||||
@@ -1030,7 +1055,7 @@ static int adsi_process(struct adsi_script *state, char *buf, char *script, int
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
strncpy(tmp2, tmp, sizeof(tmp2) - 1);
|
||||
ast_copy_string(tmp2, tmp, sizeof(tmp2));
|
||||
}
|
||||
if (strlen(tmp2) > 18) {
|
||||
ast_log(LOG_WARNING, "Truncating full name to 18 characters at line %d of %s\n", lineno, script);
|
||||
@@ -1323,7 +1348,7 @@ static struct adsi_script *compile_script(char *script)
|
||||
int x, err;
|
||||
struct adsi_script *scr;
|
||||
if (script[0] == '/')
|
||||
strncpy(fn, script, sizeof(fn) - 1);
|
||||
ast_copy_string(fn, script, sizeof(fn));
|
||||
else
|
||||
snprintf(fn, sizeof(fn), "%s/%s", (char *)ast_config_AST_CONFIG_DIR, script);
|
||||
f = fopen(fn, "r");
|
||||
@@ -1350,7 +1375,7 @@ static struct adsi_script *compile_script(char *script)
|
||||
/* Strip comments */
|
||||
if (c)
|
||||
*c = '\0';
|
||||
if (strlen(buf))
|
||||
if (!ast_strlen_zero(buf))
|
||||
adsi_process(scr, buf, script, lineno);
|
||||
}
|
||||
}
|
||||
@@ -1412,7 +1437,7 @@ static int adsi_prog(struct ast_channel *chan, char *script)
|
||||
{
|
||||
struct adsi_script *scr;
|
||||
int x;
|
||||
char buf[1024];
|
||||
unsigned char buf[1024];
|
||||
int bytes;
|
||||
scr = compile_script(script);
|
||||
if (!scr)
|
||||
@@ -1435,7 +1460,7 @@ static int adsi_prog(struct ast_channel *chan, char *script)
|
||||
bytes = 0;
|
||||
/* Start with key definitions */
|
||||
for (x=0;x<scr->numkeys;x++) {
|
||||
if (bytes + scr->keys[x].retstrlen > 254) {
|
||||
if (bytes + scr->keys[x].retstrlen > 253) {
|
||||
/* Send what we've collected so far */
|
||||
if (adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD)) {
|
||||
ast_log(LOG_WARNING, "Unable to send chunk ending at %d\n", x);
|
||||
@@ -1459,7 +1484,7 @@ static int adsi_prog(struct ast_channel *chan, char *script)
|
||||
bytes = 0;
|
||||
/* Continue with the display messages */
|
||||
for (x=0;x<scr->numdisplays;x++) {
|
||||
if (bytes + scr->displays[x].datalen > 254) {
|
||||
if (bytes + scr->displays[x].datalen > 253) {
|
||||
/* Send what we've collected so far */
|
||||
if (adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD)) {
|
||||
ast_log(LOG_WARNING, "Unable to send chunk ending at %d\n", x);
|
||||
@@ -1483,7 +1508,7 @@ static int adsi_prog(struct ast_channel *chan, char *script)
|
||||
bytes = 0;
|
||||
/* Send subroutines */
|
||||
for (x=0;x<scr->numsubs;x++) {
|
||||
if (bytes + scr->subs[x].datalen > 254) {
|
||||
if (bytes + scr->subs[x].datalen > 253) {
|
||||
/* Send what we've collected so far */
|
||||
if (adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD)) {
|
||||
ast_log(LOG_WARNING, "Unable to send chunk ending at %d\n", x);
|
||||
@@ -1527,9 +1552,12 @@ static int adsi_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0;
|
||||
struct localuser *u;
|
||||
if (!data || !strlen(data))
|
||||
data = "asterisk.adsi";
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
if (ast_strlen_zero(data))
|
||||
data = "asterisk.adsi";
|
||||
|
||||
if (!adsi_available(chan)) {
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "ADSI Unavailable on CPE. Not bothering to try.\n");
|
||||
@@ -1538,14 +1566,21 @@ static int adsi_exec(struct ast_channel *chan, void *data)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "ADSI Available on CPE. Attempting Upload.\n");
|
||||
res = adsi_prog(chan, data);
|
||||
}
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app);
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
|
||||
867
apps/app_alarmreceiver.c
Normal file
867
apps/app_alarmreceiver.c
Normal file
@@ -0,0 +1,867 @@
|
||||
/*
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Copyright (C) 2004 - 2005 Steve Rodgers
|
||||
*
|
||||
* Steve Rodgers <hwstar@rodgers.sdcoxmail.com>
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
* \brief Central Station Alarm receiver for Ademco Contact ID
|
||||
* \author Steve Rodgers <hwstar@rodgers.sdcoxmail.com>
|
||||
*
|
||||
* *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING ***
|
||||
*
|
||||
* Use at your own risk. Please consult the GNU GPL license document included with Asterisk details. *
|
||||
*
|
||||
* *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING ***
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/lock.h"
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/translate.h"
|
||||
#include "asterisk/ulaw.h"
|
||||
#include "asterisk/options.h"
|
||||
#include "asterisk/app.h"
|
||||
#include "asterisk/dsp.h"
|
||||
#include "asterisk/config.h"
|
||||
#include "asterisk/localtime.h"
|
||||
#include "asterisk/callerid.h"
|
||||
#include "asterisk/astdb.h"
|
||||
|
||||
#define ALMRCV_CONFIG "alarmreceiver.conf"
|
||||
#define ADEMCO_CONTACT_ID "ADEMCO_CONTACT_ID"
|
||||
|
||||
struct event_node{
|
||||
char data[17];
|
||||
struct event_node *next;
|
||||
};
|
||||
|
||||
typedef struct event_node event_node_t;
|
||||
|
||||
static char *tdesc = "Alarm Receiver for Asterisk";
|
||||
|
||||
static char *app = "AlarmReceiver";
|
||||
|
||||
static char *synopsis = "Provide support for receving alarm reports from a burglar or fire alarm panel";
|
||||
static char *descrip =
|
||||
" AlarmReceiver(): Only 1 signalling format is supported at this time: Ademco\n"
|
||||
"Contact ID. This application should be called whenever there is an alarm\n"
|
||||
"panel calling in to dump its events. The application will handshake with the\n"
|
||||
"alarm panel, and receive events, validate them, handshake them, and store them\n"
|
||||
"until the panel hangs up. Once the panel hangs up, the application will run the\n"
|
||||
"system command specified by the eventcmd setting in alarmreceiver.conf and pipe\n"
|
||||
"the events to the standard input of the application. The configuration file also\n"
|
||||
"contains settings for DTMF timing, and for the loudness of the acknowledgement\n"
|
||||
"tones.\n";
|
||||
|
||||
/* Config Variables */
|
||||
|
||||
static int fdtimeout = 2000;
|
||||
static int sdtimeout = 200;
|
||||
static int toneloudness = 4096;
|
||||
static int log_individual_events = 0;
|
||||
static char event_spool_dir[128] = {'\0'};
|
||||
static char event_app[128] = {'\0'};
|
||||
static char db_family[128] = {'\0'};
|
||||
static char time_stamp_format[128] = {"%a %b %d, %Y @ %H:%M:%S %Z"};
|
||||
|
||||
|
||||
/* Misc variables */
|
||||
|
||||
|
||||
static char event_file[14] = "/event-XXXXXX";
|
||||
|
||||
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
/*
|
||||
* Attempt to access a database variable and increment it,
|
||||
* provided that the user defined db-family in alarmreceiver.conf
|
||||
* The alarmreceiver app will write statistics to a few variables
|
||||
* in this family if it is defined. If the new key doesn't exist in the
|
||||
* family, then create it and set its value to 1.
|
||||
*/
|
||||
|
||||
static void database_increment( char *key )
|
||||
{
|
||||
int res = 0;
|
||||
unsigned v;
|
||||
char value[16];
|
||||
|
||||
|
||||
if (ast_strlen_zero(db_family))
|
||||
return; /* If not defined, don't do anything */
|
||||
|
||||
res = ast_db_get(db_family, key, value, sizeof(value) - 1);
|
||||
|
||||
if(res){
|
||||
if(option_verbose >= 4)
|
||||
ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: Creating database entry %s and setting to 1\n", key);
|
||||
/* Guess we have to create it */
|
||||
res = ast_db_put(db_family, key, "1");
|
||||
return;
|
||||
}
|
||||
|
||||
sscanf(value, "%u", &v);
|
||||
v++;
|
||||
|
||||
if(option_verbose >= 4)
|
||||
ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: New value for %s: %u\n", key, v);
|
||||
|
||||
snprintf(value, sizeof(value), "%u", v);
|
||||
|
||||
res = ast_db_put(db_family, key, value);
|
||||
|
||||
if((res)&&(option_verbose >= 4))
|
||||
ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: database_increment write error");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Build a MuLaw data block for a single frequency tone
|
||||
*/
|
||||
|
||||
static void make_tone_burst(unsigned char *data, float freq, float loudness, int len, int *x)
|
||||
{
|
||||
int i;
|
||||
float val;
|
||||
|
||||
for(i = 0; i < len; i++){
|
||||
val = loudness * sin((freq * 2.0 * M_PI * (*x)++)/8000.0);
|
||||
data[i] = AST_LIN2MU((int)val);
|
||||
}
|
||||
|
||||
/* wrap back around from 8000 */
|
||||
|
||||
if (*x >= 8000) *x = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send a single tone burst for a specifed duration and frequency.
|
||||
* Returns 0 if successful
|
||||
*/
|
||||
|
||||
static int send_tone_burst(struct ast_channel *chan, float freq, int duration, int tldn)
|
||||
{
|
||||
int res = 0;
|
||||
int i = 0;
|
||||
int x = 0;
|
||||
struct ast_frame *f, wf;
|
||||
|
||||
struct {
|
||||
unsigned char offset[AST_FRIENDLY_OFFSET];
|
||||
unsigned char buf[640];
|
||||
} tone_block;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
|
||||
if (ast_waitfor(chan, -1) < 0){
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
f = ast_read(chan);
|
||||
if (!f){
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (f->frametype == AST_FRAME_VOICE) {
|
||||
wf.frametype = AST_FRAME_VOICE;
|
||||
wf.subclass = AST_FORMAT_ULAW;
|
||||
wf.offset = AST_FRIENDLY_OFFSET;
|
||||
wf.mallocd = 0;
|
||||
wf.data = tone_block.buf;
|
||||
wf.datalen = f->datalen;
|
||||
wf.samples = wf.datalen;
|
||||
|
||||
make_tone_burst(tone_block.buf, freq, (float) tldn, wf.datalen, &x);
|
||||
|
||||
i += wf.datalen / 8;
|
||||
if (i > duration) {
|
||||
break;
|
||||
}
|
||||
if (ast_write(chan, &wf)){
|
||||
if(option_verbose >= 4)
|
||||
ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: Failed to write frame on %s\n", chan->name);
|
||||
ast_log(LOG_WARNING, "AlarmReceiver Failed to write frame on %s\n",chan->name);
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ast_frfree(f);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Receive a string of DTMF digits where the length of the digit string is known in advance. Do not give preferential
|
||||
* treatment to any digit value, and allow separate time out values to be specified for the first digit and all subsequent
|
||||
* digits.
|
||||
*
|
||||
* Returns 0 if all digits successfully received.
|
||||
* Returns 1 if a digit time out occurred
|
||||
* Returns -1 if the caller hung up or there was a channel error.
|
||||
*
|
||||
*/
|
||||
|
||||
static int receive_dtmf_digits(struct ast_channel *chan, char *digit_string, int length, int fdto, int sdto)
|
||||
{
|
||||
int res = 0;
|
||||
int i = 0;
|
||||
int r;
|
||||
struct ast_frame *f;
|
||||
struct timeval lastdigittime;
|
||||
|
||||
lastdigittime = ast_tvnow();
|
||||
for(;;){
|
||||
/* if outa time, leave */
|
||||
if (ast_tvdiff_ms(ast_tvnow(), lastdigittime) >
|
||||
((i > 0) ? sdto : fdto)){
|
||||
if(option_verbose >= 4)
|
||||
ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: DTMF Digit Timeout on %s\n", chan->name);
|
||||
|
||||
ast_log(LOG_DEBUG,"AlarmReceiver: DTMF timeout on chan %s\n",chan->name);
|
||||
|
||||
res = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((r = ast_waitfor(chan, -1) < 0)) {
|
||||
ast_log(LOG_DEBUG, "Waitfor returned %d\n", r);
|
||||
continue;
|
||||
}
|
||||
|
||||
f = ast_read(chan);
|
||||
|
||||
if (f == NULL){
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* If they hung up, leave */
|
||||
if ((f->frametype == AST_FRAME_CONTROL) &&
|
||||
(f->subclass == AST_CONTROL_HANGUP)){
|
||||
ast_frfree(f);
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* if not DTMF, just do it again */
|
||||
if (f->frametype != AST_FRAME_DTMF){
|
||||
ast_frfree(f);
|
||||
continue;
|
||||
}
|
||||
|
||||
digit_string[i++] = f->subclass; /* save digit */
|
||||
|
||||
ast_frfree(f);
|
||||
|
||||
/* If we have all the digits we expect, leave */
|
||||
if(i >= length)
|
||||
break;
|
||||
|
||||
lastdigittime = ast_tvnow();
|
||||
}
|
||||
|
||||
digit_string[i] = '\0'; /* Nul terminate the end of the digit string */
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the metadata to the log file
|
||||
*/
|
||||
|
||||
static int write_metadata( FILE *logfile, char *signalling_type, struct ast_channel *chan)
|
||||
{
|
||||
int res = 0;
|
||||
time_t t;
|
||||
struct tm now;
|
||||
char *cl,*cn;
|
||||
char workstring[80];
|
||||
char timestamp[80];
|
||||
|
||||
/* Extract the caller ID location */
|
||||
if (chan->cid.cid_num)
|
||||
ast_copy_string(workstring, chan->cid.cid_num, sizeof(workstring));
|
||||
workstring[sizeof(workstring) - 1] = '\0';
|
||||
|
||||
ast_callerid_parse(workstring, &cn, &cl);
|
||||
if (cl)
|
||||
ast_shrink_phone_number(cl);
|
||||
|
||||
|
||||
/* Get the current time */
|
||||
|
||||
time(&t);
|
||||
ast_localtime(&t, &now, NULL);
|
||||
|
||||
/* Format the time */
|
||||
|
||||
strftime(timestamp, sizeof(timestamp), time_stamp_format, &now);
|
||||
|
||||
|
||||
res = fprintf(logfile, "\n\n[metadata]\n\n");
|
||||
|
||||
if(res >= 0)
|
||||
res = fprintf(logfile, "PROTOCOL=%s\n", signalling_type);
|
||||
|
||||
if(res >= 0)
|
||||
res = fprintf(logfile, "CALLINGFROM=%s\n", (!cl) ? "<unknown>" : cl);
|
||||
|
||||
if(res >- 0)
|
||||
res = fprintf(logfile, "CALLERNAME=%s\n", (!cn) ? "<unknown>" : cn);
|
||||
|
||||
if(res >= 0)
|
||||
res = fprintf(logfile, "TIMESTAMP=%s\n\n", timestamp);
|
||||
|
||||
if(res >= 0)
|
||||
res = fprintf(logfile, "[events]\n\n");
|
||||
|
||||
if(res < 0){
|
||||
ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: can't write metadata\n");
|
||||
|
||||
ast_log(LOG_DEBUG,"AlarmReceiver: can't write metadata\n");
|
||||
}
|
||||
else
|
||||
res = 0;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write a single event to the log file
|
||||
*/
|
||||
|
||||
static int write_event( FILE *logfile, event_node_t *event)
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
if( fprintf(logfile, "%s\n", event->data) < 0)
|
||||
res = -1;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* If we are configured to log events, do so here.
|
||||
*
|
||||
*/
|
||||
|
||||
static int log_events(struct ast_channel *chan, char *signalling_type, event_node_t *event)
|
||||
{
|
||||
|
||||
int res = 0;
|
||||
char workstring[sizeof(event_spool_dir)+sizeof(event_file)] = "";
|
||||
int fd;
|
||||
FILE *logfile;
|
||||
event_node_t *elp = event;
|
||||
|
||||
if (!ast_strlen_zero(event_spool_dir)) {
|
||||
|
||||
/* Make a template */
|
||||
|
||||
ast_copy_string(workstring, event_spool_dir, sizeof(workstring));
|
||||
strncat(workstring, event_file, sizeof(workstring) - strlen(workstring) - 1);
|
||||
|
||||
/* Make the temporary file */
|
||||
|
||||
fd = mkstemp(workstring);
|
||||
|
||||
if(fd == -1){
|
||||
ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: can't make temporary file\n");
|
||||
ast_log(LOG_DEBUG,"AlarmReceiver: can't make temporary file\n");
|
||||
res = -1;
|
||||
}
|
||||
|
||||
if(!res){
|
||||
logfile = fdopen(fd, "w");
|
||||
if(logfile){
|
||||
/* Write the file */
|
||||
res = write_metadata(logfile, signalling_type, chan);
|
||||
if(!res)
|
||||
while((!res) && (elp != NULL)){
|
||||
res = write_event(logfile, elp);
|
||||
elp = elp->next;
|
||||
}
|
||||
if(!res){
|
||||
if(fflush(logfile) == EOF)
|
||||
res = -1;
|
||||
if(!res){
|
||||
if(fclose(logfile) == EOF)
|
||||
res = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
res = -1;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function implements the logic to receive the Ademco contact ID format.
|
||||
*
|
||||
* The function will return 0 when the caller hangs up, else a -1 if there was a problem.
|
||||
*/
|
||||
|
||||
static int receive_ademco_contact_id( struct ast_channel *chan, void *data, int fdto, int sdto, int tldn, event_node_t **ehead)
|
||||
{
|
||||
int i,j;
|
||||
int res = 0;
|
||||
int checksum;
|
||||
char event[17];
|
||||
event_node_t *enew, *elp;
|
||||
int got_some_digits = 0;
|
||||
int events_received = 0;
|
||||
int ack_retries = 0;
|
||||
|
||||
static char digit_map[15] = "0123456789*#ABC";
|
||||
static unsigned char digit_weights[15] = {10,1,2,3,4,5,6,7,8,9,11,12,13,14,15};
|
||||
|
||||
database_increment("calls-received");
|
||||
|
||||
/* Wait for first event */
|
||||
|
||||
if(option_verbose >= 4)
|
||||
ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: Waiting for first event from panel\n");
|
||||
|
||||
while(res >= 0){
|
||||
|
||||
if(got_some_digits == 0){
|
||||
|
||||
/* Send ACK tone sequence */
|
||||
|
||||
|
||||
if(option_verbose >= 4)
|
||||
ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: Sending 1400Hz 100ms burst (ACK)\n");
|
||||
|
||||
|
||||
res = send_tone_burst(chan, 1400.0, 100, tldn);
|
||||
|
||||
if(!res)
|
||||
res = ast_safe_sleep(chan, 100);
|
||||
|
||||
if(!res){
|
||||
if(option_verbose >= 4)
|
||||
ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: Sending 2300Hz 100ms burst (ACK)\n");
|
||||
|
||||
res = send_tone_burst(chan, 2300.0, 100, tldn);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if( res >= 0)
|
||||
res = receive_dtmf_digits(chan, event, sizeof(event) - 1, fdto, sdto);
|
||||
|
||||
if (res < 0){
|
||||
|
||||
if(events_received == 0)
|
||||
/* Hangup with no events received should be logged in the DB */
|
||||
database_increment("no-events-received");
|
||||
else{
|
||||
if(ack_retries){
|
||||
if(option_verbose >= 4)
|
||||
ast_verbose(VERBOSE_PREFIX_2 "AlarmReceiver: ACK retries during this call: %d\n", ack_retries);
|
||||
|
||||
database_increment("ack-retries");
|
||||
}
|
||||
}
|
||||
if(option_verbose >= 4)
|
||||
ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: App exiting...\n");
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
if(res != 0){
|
||||
/* Didn't get all of the digits */
|
||||
if(option_verbose >= 2)
|
||||
ast_verbose(VERBOSE_PREFIX_2 "AlarmReceiver: Incomplete string: %s, trying again...\n", event);
|
||||
|
||||
if(!got_some_digits){
|
||||
got_some_digits = (!ast_strlen_zero(event)) ? 1 : 0;
|
||||
ack_retries++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
got_some_digits = 1;
|
||||
|
||||
if(option_verbose >= 2)
|
||||
ast_verbose(VERBOSE_PREFIX_2 "AlarmReceiver: Received Event %s\n", event);
|
||||
ast_log(LOG_DEBUG, "AlarmReceiver: Received event: %s\n", event);
|
||||
|
||||
/* Calculate checksum */
|
||||
|
||||
for(j = 0, checksum = 0; j < 16; j++){
|
||||
for(i = 0 ; i < sizeof(digit_map) ; i++){
|
||||
if(digit_map[i] == event[j])
|
||||
break;
|
||||
}
|
||||
|
||||
if(i == 16)
|
||||
break;
|
||||
|
||||
checksum += digit_weights[i];
|
||||
}
|
||||
|
||||
if(i == 16){
|
||||
if(option_verbose >= 2)
|
||||
ast_verbose(VERBOSE_PREFIX_2 "AlarmReceiver: Bad DTMF character %c, trying again\n", event[j]);
|
||||
continue; /* Bad character */
|
||||
}
|
||||
|
||||
/* Checksum is mod(15) of the total */
|
||||
|
||||
checksum = checksum % 15;
|
||||
|
||||
if(checksum){
|
||||
database_increment("checksum-errors");
|
||||
if(option_verbose >= 2){
|
||||
ast_verbose(VERBOSE_PREFIX_2 "AlarmReceiver: Nonzero checksum\n");
|
||||
ast_log(LOG_DEBUG, "AlarmReceiver: Nonzero checksum\n");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check the message type for correctness */
|
||||
|
||||
if(strncmp(event + 4, "18", 2)){
|
||||
if(strncmp(event + 4, "98", 2)){
|
||||
database_increment("format-errors");
|
||||
if(option_verbose >= 2)
|
||||
ast_verbose(VERBOSE_PREFIX_2 "AlarmReceiver: Wrong message type\n");
|
||||
ast_log(LOG_DEBUG, "AlarmReceiver: Wrong message type\n");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
events_received++;
|
||||
|
||||
/* Queue the Event */
|
||||
|
||||
if((enew = malloc(sizeof(event_node_t))) == NULL){
|
||||
if(option_verbose >= 1)
|
||||
ast_verbose(VERBOSE_PREFIX_1 "AlarmReceiver: Failed to allocate memory\n");
|
||||
ast_log(LOG_WARNING, "AlarmReceiver Failed to allocate memory\n");
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
memset(enew, 0, sizeof(event_node_t));
|
||||
|
||||
enew->next = NULL;
|
||||
ast_copy_string(enew->data, event, sizeof(enew->data));
|
||||
|
||||
/*
|
||||
* Insert event onto end of list
|
||||
*/
|
||||
|
||||
if(*ehead == NULL){
|
||||
*ehead = enew;
|
||||
}
|
||||
else{
|
||||
for(elp = *ehead; elp->next != NULL; elp = elp->next)
|
||||
;
|
||||
|
||||
elp->next = enew;
|
||||
}
|
||||
|
||||
if(res > 0)
|
||||
res = 0;
|
||||
|
||||
/* Let the user have the option of logging the single event before sending the kissoff tone */
|
||||
|
||||
if((res == 0) && (log_individual_events))
|
||||
res = log_events(chan, ADEMCO_CONTACT_ID, enew);
|
||||
|
||||
/* Wait 200 msec before sending kissoff */
|
||||
|
||||
if(res == 0)
|
||||
res = ast_safe_sleep(chan, 200);
|
||||
|
||||
/* Send the kissoff tone */
|
||||
|
||||
if(res == 0)
|
||||
res = send_tone_burst(chan, 1400.0, 900, tldn);
|
||||
}
|
||||
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This is the main function called by Asterisk Core whenever the App is invoked in the extension logic.
|
||||
* This function will always return 0.
|
||||
*/
|
||||
|
||||
static int alarmreceiver_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res = 0;
|
||||
struct localuser *u;
|
||||
event_node_t *elp, *efree;
|
||||
char signalling_type[64] = "";
|
||||
|
||||
event_node_t *event_head = NULL;
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
/* Set write and read formats to ULAW */
|
||||
|
||||
if(option_verbose >= 4)
|
||||
ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: Setting read and write formats to ULAW\n");
|
||||
|
||||
if (ast_set_write_format(chan,AST_FORMAT_ULAW)){
|
||||
ast_log(LOG_WARNING, "AlarmReceiver: Unable to set write format to Mu-law on %s\n",chan->name);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ast_set_read_format(chan,AST_FORMAT_ULAW)){
|
||||
ast_log(LOG_WARNING, "AlarmReceiver: Unable to set read format to Mu-law on %s\n",chan->name);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Set default values for this invokation of the application */
|
||||
|
||||
ast_copy_string(signalling_type, ADEMCO_CONTACT_ID, sizeof(signalling_type));
|
||||
|
||||
|
||||
/* Answer the channel if it is not already */
|
||||
|
||||
if(option_verbose >= 4)
|
||||
ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: Answering channel\n");
|
||||
|
||||
if (chan->_state != AST_STATE_UP) {
|
||||
|
||||
res = ast_answer(chan);
|
||||
|
||||
if (res) {
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Wait for the connection to settle post-answer */
|
||||
|
||||
if(option_verbose >= 4)
|
||||
ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: Waiting for connection to stabilize\n");
|
||||
|
||||
res = ast_safe_sleep(chan, 1250);
|
||||
|
||||
/* Attempt to receive the events */
|
||||
|
||||
if(!res){
|
||||
|
||||
/* Determine the protocol to receive in advance */
|
||||
/* Note: Ademco contact is the only one supported at this time */
|
||||
/* Others may be added later */
|
||||
|
||||
if(!strcmp(signalling_type, ADEMCO_CONTACT_ID))
|
||||
receive_ademco_contact_id(chan, data, fdtimeout, sdtimeout, toneloudness, &event_head);
|
||||
else
|
||||
res = -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Events queued by receiver, write them all out here if so configured */
|
||||
|
||||
if((!res) && (log_individual_events == 0)){
|
||||
res = log_events(chan, signalling_type, event_head);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Do we exec a command line at the end?
|
||||
*/
|
||||
|
||||
if((!res) && (!ast_strlen_zero(event_app)) && (event_head)){
|
||||
ast_log(LOG_DEBUG,"Alarmreceiver: executing: %s\n", event_app);
|
||||
ast_safe_system(event_app);
|
||||
}
|
||||
|
||||
/*
|
||||
* Free up the data allocated in our linked list
|
||||
*/
|
||||
|
||||
for(elp = event_head; (elp != NULL);){
|
||||
efree = elp;
|
||||
elp = elp->next;
|
||||
free(efree);
|
||||
}
|
||||
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Load the configuration from the configuration file
|
||||
*/
|
||||
|
||||
static int load_config(void)
|
||||
{
|
||||
struct ast_config *cfg;
|
||||
char *p;
|
||||
|
||||
/* Read in the config file */
|
||||
|
||||
cfg = ast_config_load(ALMRCV_CONFIG);
|
||||
|
||||
if(!cfg){
|
||||
|
||||
if(option_verbose >= 4)
|
||||
ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: No config file\n");
|
||||
}
|
||||
else{
|
||||
|
||||
|
||||
p = ast_variable_retrieve(cfg, "general", "eventcmd");
|
||||
|
||||
if(p){
|
||||
ast_copy_string(event_app, p, sizeof(event_app));
|
||||
event_app[sizeof(event_app) - 1] = '\0';
|
||||
}
|
||||
|
||||
p = ast_variable_retrieve(cfg, "general", "loudness");
|
||||
if(p){
|
||||
toneloudness = atoi(p);
|
||||
if(toneloudness < 100)
|
||||
toneloudness = 100;
|
||||
if(toneloudness > 8192)
|
||||
toneloudness = 8192;
|
||||
}
|
||||
p = ast_variable_retrieve(cfg, "general", "fdtimeout");
|
||||
if(p){
|
||||
fdtimeout = atoi(p);
|
||||
if(fdtimeout < 1000)
|
||||
fdtimeout = 1000;
|
||||
if(fdtimeout > 10000)
|
||||
fdtimeout = 10000;
|
||||
}
|
||||
|
||||
p = ast_variable_retrieve(cfg, "general", "sdtimeout");
|
||||
if(p){
|
||||
sdtimeout = atoi(p);
|
||||
if(sdtimeout < 110)
|
||||
sdtimeout = 110;
|
||||
if(sdtimeout > 4000)
|
||||
sdtimeout = 4000;
|
||||
|
||||
}
|
||||
|
||||
p = ast_variable_retrieve(cfg, "general", "logindividualevents");
|
||||
if(p){
|
||||
log_individual_events = ast_true(p);
|
||||
|
||||
}
|
||||
|
||||
p = ast_variable_retrieve(cfg, "general", "eventspooldir");
|
||||
|
||||
if(p){
|
||||
ast_copy_string(event_spool_dir, p, sizeof(event_spool_dir));
|
||||
event_spool_dir[sizeof(event_spool_dir) - 1] = '\0';
|
||||
}
|
||||
|
||||
p = ast_variable_retrieve(cfg, "general", "timestampformat");
|
||||
|
||||
if(p){
|
||||
ast_copy_string(time_stamp_format, p, sizeof(time_stamp_format));
|
||||
time_stamp_format[sizeof(time_stamp_format) - 1] = '\0';
|
||||
}
|
||||
|
||||
p = ast_variable_retrieve(cfg, "general", "db-family");
|
||||
|
||||
if(p){
|
||||
ast_copy_string(db_family, p, sizeof(db_family));
|
||||
db_family[sizeof(db_family) - 1] = '\0';
|
||||
}
|
||||
ast_config_destroy(cfg);
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* These functions are required to implement an Asterisk App.
|
||||
*/
|
||||
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app);
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
load_config();
|
||||
return ast_register_application(app, alarmreceiver_exec, synopsis, descrip);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
174
apps/app_authenticate.c
Executable file → Normal file
174
apps/app_authenticate.c
Executable file → Normal file
@@ -1,31 +1,46 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Execute arbitrary authenticate commands
|
||||
*
|
||||
* Copyright (C) 1999, Mark Spencer
|
||||
* Copyright (C) 1999 - 2005, Digium, Inc.
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
* Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
* \brief Execute arbitrary authenticate commands
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/app.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/lock.h"
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/app.h"
|
||||
#include "asterisk/astdb.h"
|
||||
#include "asterisk/utils.h"
|
||||
|
||||
static char *tdesc = "Authentication Application";
|
||||
|
||||
@@ -34,16 +49,24 @@ static char *app = "Authenticate";
|
||||
static char *synopsis = "Authenticate a user";
|
||||
|
||||
static char *descrip =
|
||||
" Authenticate(password[|options]): Requires a user to enter a"
|
||||
"given password in order to continue execution. If the\n"
|
||||
"password begins with the '/' character, it is interpreted as\n"
|
||||
"a file which contains a list of valid passwords (1 per line).\n"
|
||||
"an optional set of opions may be provided by concatenating any\n"
|
||||
"of the following letters:\n"
|
||||
" a - Set account code to the password that is entered\n"
|
||||
"\n"
|
||||
"Returns 0 if the user enters a valid password within three\n"
|
||||
"tries, or -1 otherwise (or on hangup).\n";
|
||||
" Authenticate(password[|options]): This application asks the caller to enter a\n"
|
||||
"given password in order to continue dialplan execution. If the password begins\n"
|
||||
"with the '/' character, it is interpreted as a file which contains a list of\n"
|
||||
"valid passwords, listed 1 password per line in the file.\n"
|
||||
" When using a database key, the value associated with the key can be anything.\n"
|
||||
"Users have three attempts to authenticate before the channel is hung up. If the\n"
|
||||
"passsword is invalid, the 'j' option is specified, and priority n+101 exists,\n"
|
||||
"dialplan execution will continnue at this location.\n"
|
||||
" Options:\n"
|
||||
" a - Set the channels' account code to the password that is entered\n"
|
||||
" d - Interpret the given path as database key, not a literal file\n"
|
||||
" j - Support jumping to n+101 if authentication fails\n"
|
||||
" m - Interpret the given path as a file which contains a list of account\n"
|
||||
" codes and password hashes delimited with ':', listed one per line in\n"
|
||||
" the file. When one of the passwords is matched, the channel will have\n"
|
||||
" its account code set to the corresponding account code in the file.\n"
|
||||
" r - Remove the database key upon successful entry (valid with 'd' only)\n"
|
||||
;
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
@@ -52,17 +75,21 @@ LOCAL_USER_DECL;
|
||||
static int auth_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0;
|
||||
int jump = 0;
|
||||
int retries;
|
||||
struct localuser *u;
|
||||
char password[256]="";
|
||||
char passwd[256];
|
||||
char *opts;
|
||||
char *prompt;
|
||||
if (!data || !strlen(data)) {
|
||||
|
||||
if (ast_strlen_zero(data)) {
|
||||
ast_log(LOG_WARNING, "Authenticate requires an argument(password)\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
if (chan->_state != AST_STATE_UP) {
|
||||
res = ast_answer(chan);
|
||||
if (res) {
|
||||
@@ -70,6 +97,7 @@ static int auth_exec(struct ast_channel *chan, void *data)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
strncpy(password, data, sizeof(password) - 1);
|
||||
opts=strchr(password, '|');
|
||||
if (opts) {
|
||||
@@ -77,6 +105,8 @@ static int auth_exec(struct ast_channel *chan, void *data)
|
||||
opts++;
|
||||
} else
|
||||
opts = "";
|
||||
if (strchr(opts, 'j'))
|
||||
jump = 1;
|
||||
/* Start asking for password */
|
||||
prompt = "agent-pass";
|
||||
for (retries = 0; retries < 3; retries++) {
|
||||
@@ -85,24 +115,63 @@ static int auth_exec(struct ast_channel *chan, void *data)
|
||||
break;
|
||||
res = 0;
|
||||
if (password[0] == '/') {
|
||||
/* Compare against a file */
|
||||
FILE *f;
|
||||
f = fopen(password, "r");
|
||||
if (f) {
|
||||
char buf[256] = "";
|
||||
while(!feof(f)) {
|
||||
fgets(buf, sizeof(buf), f);
|
||||
if (!feof(f) && strlen(buf)) {
|
||||
buf[strlen(buf) - 1] = '\0';
|
||||
if (strlen(buf) && !strcmp(passwd, buf))
|
||||
break;
|
||||
if (strchr(opts, 'd')) {
|
||||
char tmp[256];
|
||||
/* Compare against a database key */
|
||||
if (!ast_db_get(password + 1, passwd, tmp, sizeof(tmp))) {
|
||||
/* It's a good password */
|
||||
if (strchr(opts, 'r')) {
|
||||
ast_db_del(password + 1, passwd);
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
if (strlen(buf) && !strcmp(passwd, buf))
|
||||
break;
|
||||
} else
|
||||
ast_log(LOG_WARNING, "Unable to open file '%s' for authentication: %s\n", password, strerror(errno));
|
||||
}
|
||||
} else {
|
||||
/* Compare against a file */
|
||||
FILE *f;
|
||||
f = fopen(password, "r");
|
||||
if (f) {
|
||||
char buf[256] = "";
|
||||
char md5passwd[33] = "";
|
||||
char *md5secret = NULL;
|
||||
|
||||
while (!feof(f)) {
|
||||
fgets(buf, sizeof(buf), f);
|
||||
if (!feof(f) && !ast_strlen_zero(buf)) {
|
||||
buf[strlen(buf) - 1] = '\0';
|
||||
if (strchr(opts, 'm')) {
|
||||
md5secret = strchr(buf, ':');
|
||||
if (md5secret == NULL)
|
||||
continue;
|
||||
*md5secret = '\0';
|
||||
md5secret++;
|
||||
ast_md5_hash(md5passwd, passwd);
|
||||
if (!strcmp(md5passwd, md5secret)) {
|
||||
if (strchr(opts, 'a'))
|
||||
ast_cdr_setaccount(chan, buf);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (!strcmp(passwd, buf)) {
|
||||
if (strchr(opts, 'a'))
|
||||
ast_cdr_setaccount(chan, buf);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
if (!ast_strlen_zero(buf)) {
|
||||
if (strchr(opts, 'm')) {
|
||||
if (md5secret && !strcmp(md5passwd, md5secret))
|
||||
break;
|
||||
} else {
|
||||
if (!strcmp(passwd, buf))
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else
|
||||
ast_log(LOG_WARNING, "Unable to open file '%s' for authentication: %s\n", password, strerror(errno));
|
||||
}
|
||||
} else {
|
||||
/* Compare against a fixed password */
|
||||
if (!strcmp(passwd, password))
|
||||
@@ -111,17 +180,19 @@ static int auth_exec(struct ast_channel *chan, void *data)
|
||||
prompt="auth-incorrect";
|
||||
}
|
||||
if ((retries < 3) && !res) {
|
||||
if (strchr(opts, 'a'))
|
||||
if (strchr(opts, 'a') && !strchr(opts, 'm'))
|
||||
ast_cdr_setaccount(chan, passwd);
|
||||
res = ast_streamfile(chan, "auth-thankyou", chan->language);
|
||||
if (!res)
|
||||
res = ast_waitstream(chan, "");
|
||||
} else {
|
||||
if (!res)
|
||||
res = ast_streamfile(chan, "vm-goodbye", chan->language);
|
||||
if (!res)
|
||||
res = ast_waitstream(chan, "");
|
||||
res = -1;
|
||||
if (jump && ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101)) {
|
||||
res = 0;
|
||||
} else {
|
||||
if (!ast_streamfile(chan, "vm-goodbye", chan->language))
|
||||
res = ast_waitstream(chan, "");
|
||||
res = -1;
|
||||
}
|
||||
}
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
@@ -129,8 +200,13 @@ static int auth_exec(struct ast_channel *chan, void *data)
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app);
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
|
||||
55
apps/app_cdr.c
Executable file → Normal file
55
apps/app_cdr.c
Executable file → Normal file
@@ -1,28 +1,47 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Applictions connected with CDR engine
|
||||
*
|
||||
* Copyright (C) 2003, Digium
|
||||
* Copyright (C) 1999 - 2005, Digium, Inc.
|
||||
*
|
||||
* Martin Pycko <martinp@digium.com>
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
* \brief Applications connected with CDR engine
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
static char *tdesc = "Make sure asterisk doesn't save CDR for a certain call";
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/pbx.h"
|
||||
|
||||
|
||||
static char *tdesc = "Tell Asterisk to not maintain a CDR for the current call";
|
||||
|
||||
static char *nocdr_descrip =
|
||||
" NoCDR(): This application will tell Asterisk not to maintain a CDR for the\n"
|
||||
"current call.\n";
|
||||
|
||||
static char *nocdr_descrip = "NoCDR(): makes sure there won't be any CDR written for a certain call";
|
||||
static char *nocdr_app = "NoCDR";
|
||||
static char *nocdr_synopsis = "Make sure asterisk doesn't save CDR for a certain call";
|
||||
static char *nocdr_synopsis = "Tell Asterisk to not maintain a CDR for the current call";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
@@ -30,17 +49,29 @@ LOCAL_USER_DECL;
|
||||
|
||||
static int nocdr_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
struct localuser *u;
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
if (chan->cdr) {
|
||||
ast_cdr_free(chan->cdr);
|
||||
chan->cdr = NULL;
|
||||
}
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(nocdr_app);
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(nocdr_app);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
|
||||
142
apps/app_chanisavail.c
Executable file → Normal file
142
apps/app_chanisavail.c
Executable file → Normal file
@@ -1,49 +1,65 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* Check if Channel is Available
|
||||
*
|
||||
* Copyright (C) 2003, Digium
|
||||
*
|
||||
* Mark Spencer <markster@digium.com>
|
||||
* James Golovich <james@gnuinter.net>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
*
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Copyright (C) 1999 - 2005, Digium, Inc.
|
||||
*
|
||||
* Mark Spencer <markster@digium.com>
|
||||
* James Golovich <james@gnuinter.net>
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
* \brief Check if Channel is Available
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/app.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <pthread.h>
|
||||
#include "asterisk.h"
|
||||
|
||||
static char *tdesc = "Check if channel is available";
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/lock.h"
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/app.h"
|
||||
#include "asterisk/devicestate.h"
|
||||
#include "asterisk/options.h"
|
||||
|
||||
static char *tdesc = "Check channel availability";
|
||||
|
||||
static char *app = "ChanIsAvail";
|
||||
|
||||
static char *synopsis = "Check if channel is available";
|
||||
static char *synopsis = "Check channel availability";
|
||||
|
||||
static char *descrip =
|
||||
" ChanIsAvail(Technology/resource[&Technology2/resource2...]): \n"
|
||||
"Checks is any of the requested channels are available. If none\n"
|
||||
"of the requested channels are available the new priority will\n"
|
||||
"be n+101 (unless such a priority does not exist, in which case\n"
|
||||
"ChanIsAvail will return -1. If any of the requested channels\n"
|
||||
"are available, the next priority will be n+1, the channel variable\n"
|
||||
"${AVAILCHAN} will be set to the name of the available channel and\n"
|
||||
"the ChanIsAvail app will return 0.\n";
|
||||
" ChanIsAvail(Technology/resource[&Technology2/resource2...][|options]): \n"
|
||||
"This application will check to see if any of the specified channels are\n"
|
||||
"available. The following variables will be set by this application:\n"
|
||||
" ${AVAILCHAN} - the name of the available channel, if one exists\n"
|
||||
" ${AVAILORIGCHAN} - the canonical channel name that was used to create the channel\n"
|
||||
" ${AVAILSTATUS} - the status code for the available channel\n"
|
||||
" Options:\n"
|
||||
" s - Consider the channel unavailable if the channel is in use at all\n"
|
||||
" j - Support jumping to priority n+101 if no channel is available\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
@@ -51,18 +67,29 @@ LOCAL_USER_DECL;
|
||||
|
||||
static int chanavail_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=-1;
|
||||
int res=-1, inuse=-1, option_state=0, priority_jump=0;
|
||||
int status;
|
||||
struct localuser *u;
|
||||
char info[256], *peers, *tech, *number, *rest, *cur;
|
||||
char *info, tmp[512], trychan[512], *peers, *tech, *number, *rest, *cur, *options, *stringp;
|
||||
struct ast_channel *tempchan;
|
||||
|
||||
if (!data) {
|
||||
if (ast_strlen_zero(data)) {
|
||||
ast_log(LOG_WARNING, "ChanIsAvail requires an argument (Zap/1&Zap/2)\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
strncpy(info, (char *)data, strlen((char *)data) + AST_MAX_EXTENSION-1);
|
||||
info = ast_strdupa(data);
|
||||
stringp = info;
|
||||
strsep(&stringp, "|");
|
||||
options = strsep(&stringp, "|");
|
||||
if (options) {
|
||||
if (strchr(options, 's'))
|
||||
option_state = 1;
|
||||
if (strchr(options, 'j'))
|
||||
priority_jump = 1;
|
||||
}
|
||||
peers = info;
|
||||
if (peers) {
|
||||
cur = peers;
|
||||
@@ -76,28 +103,48 @@ static int chanavail_exec(struct ast_channel *chan, void *data)
|
||||
tech = cur;
|
||||
number = strchr(tech, '/');
|
||||
if (!number) {
|
||||
ast_log(LOG_WARNING, "ChanIsAvail argument takes format (Zap/[device])\n");
|
||||
continue;
|
||||
ast_log(LOG_WARNING, "ChanIsAvail argument takes format ([technology]/[device])\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
*number = '\0';
|
||||
number++;
|
||||
if ((tempchan = ast_request(tech, chan->nativeformats, number))) {
|
||||
|
||||
if (option_state) {
|
||||
/* If the pbx says in use then don't bother trying further.
|
||||
This is to permit testing if someone's on a call, even if the
|
||||
channel can permit more calls (ie callwaiting, sip calls, etc). */
|
||||
|
||||
snprintf(trychan, sizeof(trychan), "%s/%s",cur,number);
|
||||
status = inuse = ast_device_state(trychan);
|
||||
}
|
||||
if ((inuse <= 1) && (tempchan = ast_request(tech, chan->nativeformats, number, &status))) {
|
||||
pbx_builtin_setvar_helper(chan, "AVAILCHAN", tempchan->name);
|
||||
/* Store the originally used channel too */
|
||||
snprintf(tmp, sizeof(tmp), "%s/%s", tech, number);
|
||||
pbx_builtin_setvar_helper(chan, "AVAILORIGCHAN", tmp);
|
||||
snprintf(tmp, sizeof(tmp), "%d", status);
|
||||
pbx_builtin_setvar_helper(chan, "AVAILSTATUS", tmp);
|
||||
ast_hangup(tempchan);
|
||||
tempchan = NULL;
|
||||
res = 1;
|
||||
break;
|
||||
} else {
|
||||
snprintf(tmp, sizeof(tmp), "%d", status);
|
||||
pbx_builtin_setvar_helper(chan, "AVAILSTATUS", tmp);
|
||||
}
|
||||
cur = rest;
|
||||
} while (cur);
|
||||
}
|
||||
|
||||
if (res < 1) {
|
||||
pbx_builtin_setvar_helper(chan, "AVAILCHAN", "");
|
||||
if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->callerid))
|
||||
chan->priority+=100;
|
||||
else
|
||||
return -1;
|
||||
pbx_builtin_setvar_helper(chan, "AVAILORIGCHAN", "");
|
||||
if (priority_jump || option_priority_jumping) {
|
||||
if (ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101)) {
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
@@ -106,8 +153,13 @@ static int chanavail_exec(struct ast_channel *chan, void *data)
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
res = ast_unregister_application(app);
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
|
||||
587
apps/app_chanspy.c
Normal file
587
apps/app_chanspy.c
Normal file
@@ -0,0 +1,587 @@
|
||||
/*
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Copyright (C) 2005 Anthony Minessale II (anthmct@yahoo.com)
|
||||
*
|
||||
* Disclaimed to Digium
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
* \brief ChanSpy: Listen in on any channel.
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/chanspy.h"
|
||||
#include "asterisk/features.h"
|
||||
#include "asterisk/options.h"
|
||||
#include "asterisk/app.h"
|
||||
#include "asterisk/utils.h"
|
||||
#include "asterisk/say.h"
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/translate.h"
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/lock.h"
|
||||
|
||||
AST_MUTEX_DEFINE_STATIC(modlock);
|
||||
|
||||
#define AST_NAME_STRLEN 256
|
||||
#define ALL_DONE(u, ret) LOCAL_USER_REMOVE(u); return ret;
|
||||
#define get_volfactor(x) x ? ((x > 0) ? (1 << x) : ((1 << abs(x)) * -1)) : 0
|
||||
|
||||
static const char *synopsis = "Listen to the audio of an active channel\n";
|
||||
static const char *app = "ChanSpy";
|
||||
static const char *desc =
|
||||
" ChanSpy([chanprefix][|options]): This application is used to listen to the\n"
|
||||
"audio from an active Asterisk channel. This includes the audio coming in and\n"
|
||||
"out of the channel being spied on. If the 'chanprefix' parameter is specified,\n"
|
||||
"only channels beginning with this string will be spied upon.\n"
|
||||
" While Spying, the following actions may be performed:\n"
|
||||
" - Dialing # cycles the volume level.\n"
|
||||
" - Dialing * will stop spying and look for another channel to spy on.\n"
|
||||
" - Dialing a series of digits followed by # builds a channel name to append\n"
|
||||
" to 'chanprefix'. For example, executing ChanSpy(Agent) and then dialing\n"
|
||||
" the digits '1234#' while spying will begin spying on the channel,\n"
|
||||
" 'Agent/1234'.\n"
|
||||
" Options:\n"
|
||||
" b - Only spy on channels involved in a bridged call.\n"
|
||||
" g(grp) - Match only channels where their ${SPYGROUP} variable is set to\n"
|
||||
" 'grp'.\n"
|
||||
" q - Don't play a beep when beginning to spy on a channel.\n"
|
||||
" r[(basename)] - Record the session to the monitor spool directory. An\n"
|
||||
" optional base for the filename may be specified. The\n"
|
||||
" default is 'chanspy'.\n"
|
||||
" v([value]) - Adjust the initial volume in the range from -4 to 4. A\n"
|
||||
" negative value refers to a quieter setting.\n"
|
||||
;
|
||||
|
||||
static const char *chanspy_spy_type = "ChanSpy";
|
||||
|
||||
enum {
|
||||
OPTION_QUIET = (1 << 0), /* Quiet, no announcement */
|
||||
OPTION_BRIDGED = (1 << 1), /* Only look at bridged calls */
|
||||
OPTION_VOLUME = (1 << 2), /* Specify initial volume */
|
||||
OPTION_GROUP = (1 << 3), /* Only look at channels in group */
|
||||
OPTION_RECORD = (1 << 4), /* Record */
|
||||
} chanspy_opt_flags;
|
||||
|
||||
enum {
|
||||
OPT_ARG_VOLUME = 0,
|
||||
OPT_ARG_GROUP,
|
||||
OPT_ARG_RECORD,
|
||||
OPT_ARG_ARRAY_SIZE,
|
||||
} chanspy_opt_args;
|
||||
|
||||
AST_APP_OPTIONS(chanspy_opts, {
|
||||
AST_APP_OPTION('q', OPTION_QUIET),
|
||||
AST_APP_OPTION('b', OPTION_BRIDGED),
|
||||
AST_APP_OPTION_ARG('v', OPTION_VOLUME, OPT_ARG_VOLUME),
|
||||
AST_APP_OPTION_ARG('g', OPTION_GROUP, OPT_ARG_GROUP),
|
||||
AST_APP_OPTION_ARG('r', OPTION_RECORD, OPT_ARG_RECORD),
|
||||
});
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
struct chanspy_translation_helper {
|
||||
/* spy data */
|
||||
struct ast_channel_spy spy;
|
||||
int fd;
|
||||
int volfactor;
|
||||
};
|
||||
|
||||
static struct ast_channel *local_channel_walk(struct ast_channel *chan)
|
||||
{
|
||||
struct ast_channel *ret;
|
||||
ast_mutex_lock(&modlock);
|
||||
if ((ret = ast_channel_walk_locked(chan))) {
|
||||
ast_mutex_unlock(&ret->lock);
|
||||
}
|
||||
ast_mutex_unlock(&modlock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct ast_channel *local_get_channel_begin_name(char *name)
|
||||
{
|
||||
struct ast_channel *chan, *ret = NULL;
|
||||
ast_mutex_lock(&modlock);
|
||||
chan = local_channel_walk(NULL);
|
||||
while (chan) {
|
||||
if (!strncmp(chan->name, name, strlen(name))) {
|
||||
ret = chan;
|
||||
break;
|
||||
}
|
||||
chan = local_channel_walk(chan);
|
||||
}
|
||||
ast_mutex_unlock(&modlock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void *spy_alloc(struct ast_channel *chan, void *data)
|
||||
{
|
||||
/* just store the data pointer in the channel structure */
|
||||
return data;
|
||||
}
|
||||
|
||||
static void spy_release(struct ast_channel *chan, void *data)
|
||||
{
|
||||
/* nothing to do */
|
||||
}
|
||||
|
||||
static int spy_generate(struct ast_channel *chan, void *data, int len, int samples)
|
||||
{
|
||||
struct chanspy_translation_helper *csth = data;
|
||||
struct ast_frame *f;
|
||||
|
||||
if (csth->spy.status != CHANSPY_RUNNING)
|
||||
/* Channel is already gone more than likely */
|
||||
return -1;
|
||||
|
||||
ast_mutex_lock(&csth->spy.lock);
|
||||
f = ast_channel_spy_read_frame(&csth->spy, samples);
|
||||
ast_mutex_unlock(&csth->spy.lock);
|
||||
|
||||
if (!f)
|
||||
return 0;
|
||||
|
||||
if (ast_write(chan, f)) {
|
||||
ast_frfree(f);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (csth->fd)
|
||||
write(csth->fd, f->data, f->datalen);
|
||||
|
||||
ast_frfree(f);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static struct ast_generator spygen = {
|
||||
.alloc = spy_alloc,
|
||||
.release = spy_release,
|
||||
.generate = spy_generate,
|
||||
};
|
||||
|
||||
static int start_spying(struct ast_channel *chan, struct ast_channel *spychan, struct ast_channel_spy *spy)
|
||||
{
|
||||
int res;
|
||||
struct ast_channel *peer;
|
||||
|
||||
ast_log(LOG_NOTICE, "Attaching %s to %s\n", spychan->name, chan->name);
|
||||
|
||||
ast_mutex_lock(&chan->lock);
|
||||
res = ast_channel_spy_add(chan, spy);
|
||||
ast_mutex_unlock(&chan->lock);
|
||||
|
||||
if (!res && ast_test_flag(chan, AST_FLAG_NBRIDGE) && (peer = ast_bridged_channel(chan))) {
|
||||
ast_softhangup(peer, AST_SOFTHANGUP_UNBRIDGE);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static void stop_spying(struct ast_channel *chan, struct ast_channel_spy *spy)
|
||||
{
|
||||
/* If our status has changed to DONE, then the channel we're spying on is gone....
|
||||
DON'T TOUCH IT!!! RUN AWAY!!! */
|
||||
if (spy->status == CHANSPY_DONE)
|
||||
return;
|
||||
|
||||
if (!chan)
|
||||
return;
|
||||
|
||||
ast_mutex_lock(&chan->lock);
|
||||
ast_channel_spy_remove(chan, spy);
|
||||
ast_mutex_unlock(&chan->lock);
|
||||
};
|
||||
|
||||
/* Map 'volume' levels from -4 through +4 into
|
||||
decibel (dB) settings for channel drivers
|
||||
*/
|
||||
static signed char volfactor_map[] = {
|
||||
-24,
|
||||
-18,
|
||||
-12,
|
||||
-6,
|
||||
0,
|
||||
6,
|
||||
12,
|
||||
18,
|
||||
24,
|
||||
};
|
||||
|
||||
/* attempt to set the desired gain adjustment via the channel driver;
|
||||
if successful, clear it out of the csth structure so the
|
||||
generator will not attempt to do the adjustment itself
|
||||
*/
|
||||
static void set_volume(struct ast_channel *chan, struct chanspy_translation_helper *csth)
|
||||
{
|
||||
signed char volume_adjust = volfactor_map[csth->volfactor + 4];
|
||||
|
||||
if (!ast_channel_setoption(chan, AST_OPTION_TXGAIN, &volume_adjust, sizeof(volume_adjust), 0))
|
||||
csth->volfactor = 0;
|
||||
}
|
||||
|
||||
static int channel_spy(struct ast_channel *chan, struct ast_channel *spyee, int *volfactor, int fd)
|
||||
{
|
||||
struct chanspy_translation_helper csth;
|
||||
int running, res = 0, x = 0;
|
||||
char inp[24];
|
||||
char *name=NULL;
|
||||
struct ast_frame *f;
|
||||
|
||||
running = (chan && !ast_check_hangup(chan) && spyee && !ast_check_hangup(spyee));
|
||||
|
||||
if (running) {
|
||||
memset(inp, 0, sizeof(inp));
|
||||
name = ast_strdupa(spyee->name);
|
||||
if (option_verbose >= 2)
|
||||
ast_verbose(VERBOSE_PREFIX_2 "Spying on channel %s\n", name);
|
||||
|
||||
memset(&csth, 0, sizeof(csth));
|
||||
ast_set_flag(&csth.spy, CHANSPY_FORMAT_AUDIO);
|
||||
ast_set_flag(&csth.spy, CHANSPY_TRIGGER_NONE);
|
||||
ast_set_flag(&csth.spy, CHANSPY_MIXAUDIO);
|
||||
csth.spy.type = chanspy_spy_type;
|
||||
csth.spy.status = CHANSPY_RUNNING;
|
||||
csth.spy.read_queue.format = AST_FORMAT_SLINEAR;
|
||||
csth.spy.write_queue.format = AST_FORMAT_SLINEAR;
|
||||
ast_mutex_init(&csth.spy.lock);
|
||||
csth.volfactor = *volfactor;
|
||||
set_volume(chan, &csth);
|
||||
csth.spy.read_vol_adjustment = csth.volfactor;
|
||||
csth.spy.write_vol_adjustment = csth.volfactor;
|
||||
csth.fd = fd;
|
||||
|
||||
if (start_spying(spyee, chan, &csth.spy))
|
||||
running = 0;
|
||||
}
|
||||
|
||||
if (running) {
|
||||
running = 1;
|
||||
ast_activate_generator(chan, &spygen, &csth);
|
||||
|
||||
while (csth.spy.status == CHANSPY_RUNNING &&
|
||||
chan && !ast_check_hangup(chan) &&
|
||||
spyee &&
|
||||
!ast_check_hangup(spyee) &&
|
||||
running == 1 &&
|
||||
(res = ast_waitfor(chan, -1) > -1)) {
|
||||
if ((f = ast_read(chan))) {
|
||||
res = 0;
|
||||
if (f->frametype == AST_FRAME_DTMF) {
|
||||
res = f->subclass;
|
||||
}
|
||||
ast_frfree(f);
|
||||
if (!res) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
if (x == sizeof(inp)) {
|
||||
x = 0;
|
||||
}
|
||||
if (res < 0) {
|
||||
running = -1;
|
||||
}
|
||||
if (res == 0) {
|
||||
continue;
|
||||
} else if (res == '*') {
|
||||
running = 0;
|
||||
} else if (res == '#') {
|
||||
if (!ast_strlen_zero(inp)) {
|
||||
running = x ? atoi(inp) : -1;
|
||||
break;
|
||||
} else {
|
||||
(*volfactor)++;
|
||||
if (*volfactor > 4) {
|
||||
*volfactor = -4;
|
||||
}
|
||||
if (option_verbose > 2) {
|
||||
ast_verbose(VERBOSE_PREFIX_3 "Setting spy volume on %s to %d\n", chan->name, *volfactor);
|
||||
}
|
||||
csth.volfactor = *volfactor;
|
||||
set_volume(chan, &csth);
|
||||
csth.spy.read_vol_adjustment = csth.volfactor;
|
||||
csth.spy.write_vol_adjustment = csth.volfactor;
|
||||
}
|
||||
} else if (res >= 48 && res <= 57) {
|
||||
inp[x++] = res;
|
||||
}
|
||||
}
|
||||
ast_deactivate_generator(chan);
|
||||
stop_spying(spyee, &csth.spy);
|
||||
|
||||
if (option_verbose >= 2) {
|
||||
ast_verbose(VERBOSE_PREFIX_2 "Done Spying on channel %s\n", name);
|
||||
}
|
||||
} else {
|
||||
running = 0;
|
||||
}
|
||||
|
||||
ast_mutex_destroy(&csth.spy.lock);
|
||||
|
||||
return running;
|
||||
}
|
||||
|
||||
static int chanspy_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
struct localuser *u;
|
||||
struct ast_channel *peer=NULL, *prev=NULL;
|
||||
char name[AST_NAME_STRLEN],
|
||||
peer_name[AST_NAME_STRLEN + 5],
|
||||
*args,
|
||||
*ptr = NULL,
|
||||
*options = NULL,
|
||||
*spec = NULL,
|
||||
*argv[5],
|
||||
*mygroup = NULL,
|
||||
*recbase = NULL;
|
||||
int res = -1,
|
||||
volfactor = 0,
|
||||
silent = 0,
|
||||
argc = 0,
|
||||
bronly = 0,
|
||||
chosen = 0,
|
||||
count=0,
|
||||
waitms = 100,
|
||||
num = 0,
|
||||
oldrf = 0,
|
||||
oldwf = 0,
|
||||
fd = 0;
|
||||
struct ast_flags flags;
|
||||
signed char zero_volume = 0;
|
||||
|
||||
if (!(args = ast_strdupa((char *)data))) {
|
||||
ast_log(LOG_ERROR, "Out of memory!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
oldrf = chan->readformat;
|
||||
oldwf = chan->writeformat;
|
||||
if (ast_set_read_format(chan, AST_FORMAT_SLINEAR) < 0) {
|
||||
ast_log(LOG_ERROR, "Could Not Set Read Format.\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) {
|
||||
ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ast_answer(chan);
|
||||
|
||||
ast_set_flag(chan, AST_FLAG_SPYING); /* so nobody can spy on us while we are spying */
|
||||
|
||||
if ((argc = ast_app_separate_args(args, '|', argv, sizeof(argv) / sizeof(argv[0])))) {
|
||||
spec = argv[0];
|
||||
if ( argc > 1) {
|
||||
options = argv[1];
|
||||
}
|
||||
if (ast_strlen_zero(spec) || !strcmp(spec, "all")) {
|
||||
spec = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (options) {
|
||||
char *opts[OPT_ARG_ARRAY_SIZE];
|
||||
ast_app_parse_options(chanspy_opts, &flags, opts, options);
|
||||
if (ast_test_flag(&flags, OPTION_GROUP)) {
|
||||
mygroup = opts[1];
|
||||
}
|
||||
if (ast_test_flag(&flags, OPTION_RECORD)) {
|
||||
if (!(recbase = opts[2])) {
|
||||
recbase = "chanspy";
|
||||
}
|
||||
}
|
||||
silent = ast_test_flag(&flags, OPTION_QUIET);
|
||||
bronly = ast_test_flag(&flags, OPTION_BRIDGED);
|
||||
if (ast_test_flag(&flags, OPTION_VOLUME) && opts[1]) {
|
||||
int vol;
|
||||
|
||||
if ((sscanf(opts[0], "%d", &vol) != 1) || (vol > 4) || (vol < -4))
|
||||
ast_log(LOG_NOTICE, "Volume factor must be a number between -4 and 4\n");
|
||||
else
|
||||
volfactor = vol;
|
||||
}
|
||||
}
|
||||
|
||||
if (recbase) {
|
||||
char filename[512];
|
||||
snprintf(filename,sizeof(filename),"%s/%s.%d.raw",ast_config_AST_MONITOR_DIR, recbase, (int)time(NULL));
|
||||
if ((fd = open(filename, O_CREAT | O_WRONLY, O_TRUNC, 0644)) <= 0) {
|
||||
ast_log(LOG_WARNING, "Cannot open %s for recording\n", filename);
|
||||
fd = 0;
|
||||
}
|
||||
}
|
||||
|
||||
for(;;) {
|
||||
if (!silent) {
|
||||
res = ast_streamfile(chan, "beep", chan->language);
|
||||
if (!res)
|
||||
res = ast_waitstream(chan, "");
|
||||
if (res < 0) {
|
||||
ast_clear_flag(chan, AST_FLAG_SPYING);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
count = 0;
|
||||
res = ast_waitfordigit(chan, waitms);
|
||||
if (res < 0) {
|
||||
ast_clear_flag(chan, AST_FLAG_SPYING);
|
||||
break;
|
||||
}
|
||||
|
||||
peer = local_channel_walk(NULL);
|
||||
prev=NULL;
|
||||
while(peer) {
|
||||
if (peer != chan) {
|
||||
char *group = NULL;
|
||||
int igrp = 1;
|
||||
|
||||
if (peer == prev && !chosen) {
|
||||
break;
|
||||
}
|
||||
chosen = 0;
|
||||
group = pbx_builtin_getvar_helper(peer, "SPYGROUP");
|
||||
if (mygroup) {
|
||||
if (!group || strcmp(mygroup, group)) {
|
||||
igrp = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (igrp && (!spec || ((strlen(spec) <= strlen(peer->name) &&
|
||||
!strncasecmp(peer->name, spec, strlen(spec)))))) {
|
||||
if (peer && (!bronly || ast_bridged_channel(peer)) &&
|
||||
!ast_check_hangup(peer) && !ast_test_flag(peer, AST_FLAG_SPYING)) {
|
||||
int x = 0;
|
||||
strncpy(peer_name, "spy-", 5);
|
||||
strncpy(peer_name + strlen(peer_name), peer->name, AST_NAME_STRLEN);
|
||||
ptr = strchr(peer_name, '/');
|
||||
*ptr = '\0';
|
||||
ptr++;
|
||||
for (x = 0 ; x < strlen(peer_name) ; x++) {
|
||||
if (peer_name[x] == '/') {
|
||||
break;
|
||||
}
|
||||
peer_name[x] = tolower(peer_name[x]);
|
||||
}
|
||||
|
||||
if (!silent) {
|
||||
if (ast_fileexists(peer_name, NULL, NULL) != -1) {
|
||||
res = ast_streamfile(chan, peer_name, chan->language);
|
||||
if (!res)
|
||||
res = ast_waitstream(chan, "");
|
||||
if (res)
|
||||
break;
|
||||
} else
|
||||
res = ast_say_character_str(chan, peer_name, "", chan->language);
|
||||
if ((num=atoi(ptr)))
|
||||
ast_say_digits(chan, atoi(ptr), "", chan->language);
|
||||
}
|
||||
count++;
|
||||
prev = peer;
|
||||
res = channel_spy(chan, peer, &volfactor, fd);
|
||||
if (res == -1) {
|
||||
break;
|
||||
} else if (res > 1 && spec) {
|
||||
snprintf(name, AST_NAME_STRLEN, "%s/%d", spec, res);
|
||||
if ((peer = local_get_channel_begin_name(name))) {
|
||||
chosen = 1;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((peer = local_channel_walk(peer)) == NULL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
waitms = count ? 100 : 5000;
|
||||
}
|
||||
|
||||
|
||||
if (fd > 0) {
|
||||
close(fd);
|
||||
}
|
||||
|
||||
if (oldrf && ast_set_read_format(chan, oldrf) < 0) {
|
||||
ast_log(LOG_ERROR, "Could Not Set Read Format.\n");
|
||||
}
|
||||
|
||||
if (oldwf && ast_set_write_format(chan, oldwf) < 0) {
|
||||
ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
|
||||
}
|
||||
|
||||
ast_clear_flag(chan, AST_FLAG_SPYING);
|
||||
|
||||
ast_channel_setoption(chan, AST_OPTION_TXGAIN, &zero_volume, sizeof(zero_volume), 0);
|
||||
|
||||
ALL_DONE(u, res);
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app);
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(app, chanspy_exec, synopsis, desc);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return (char *) synopsis;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
190
apps/app_controlplayback.c
Normal file
190
apps/app_controlplayback.c
Normal file
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Copyright (C) 1999 - 2005, Digium, Inc.
|
||||
*
|
||||
* Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
* \brief Trivial application to control playback of a sound file
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/lock.h"
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/app.h"
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/translate.h"
|
||||
#include "asterisk/utils.h"
|
||||
#include "asterisk/options.h"
|
||||
|
||||
static const char *tdesc = "Control Playback Application";
|
||||
|
||||
static const char *app = "ControlPlayback";
|
||||
|
||||
static const char *synopsis = "Play a file with fast forward and rewind";
|
||||
|
||||
static const char *descrip =
|
||||
" ControlPlayback(file[|skipms[|ff[|rew[|stop[|pause[|restart|options]]]]]]]):\n"
|
||||
"This application will play back the given filename. By default, the '*' key\n"
|
||||
"can be used to rewind, and the '#' key can be used to fast-forward.\n"
|
||||
"Parameters:\n"
|
||||
" skipms - This is number of milliseconds to skip when rewinding or\n"
|
||||
" fast-forwarding.\n"
|
||||
" ff - Fast-forward when this DTMF digit is received.\n"
|
||||
" rew - Rewind when this DTMF digit is received.\n"
|
||||
" stop - Stop playback when this DTMF digit is received.\n"
|
||||
" pause - Pause playback when this DTMF digit is received.\n"
|
||||
" restart - Restart playback when this DTMF digit is received.\n"
|
||||
"Options:\n"
|
||||
" j - Jump to priority n+101 if the requested file is not found.\n"
|
||||
"This application sets the following channel variable upon completion:\n"
|
||||
" CPLAYBACKSTATUS - This variable contains the status of the attempt as a text\n"
|
||||
" string, one of: SUCCESS | USERSTOPPED | ERROR\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int is_on_phonepad(char key)
|
||||
{
|
||||
return key == 35 || key == 42 || (key >= 48 && key <= 57);
|
||||
}
|
||||
|
||||
static int controlplayback_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res = 0, priority_jump = 0;
|
||||
int skipms = 0;
|
||||
struct localuser *u;
|
||||
char *tmp;
|
||||
int argc;
|
||||
char *argv[8];
|
||||
enum arg_ids {
|
||||
arg_file = 0,
|
||||
arg_skip = 1,
|
||||
arg_fwd = 2,
|
||||
arg_rev = 3,
|
||||
arg_stop = 4,
|
||||
arg_pause = 5,
|
||||
arg_restart = 6,
|
||||
options = 7,
|
||||
};
|
||||
|
||||
if (ast_strlen_zero(data)) {
|
||||
ast_log(LOG_WARNING, "ControlPlayback requires an argument (filename)\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
tmp = ast_strdupa(data);
|
||||
memset(argv, 0, sizeof(argv));
|
||||
|
||||
argc = ast_app_separate_args(tmp, '|', argv, sizeof(argv) / sizeof(argv[0]));
|
||||
|
||||
if (argc < 1) {
|
||||
ast_log(LOG_WARNING, "ControlPlayback requires an argument (filename)\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
skipms = argv[arg_skip] ? atoi(argv[arg_skip]) : 3000;
|
||||
if (!skipms)
|
||||
skipms = 3000;
|
||||
|
||||
if (!argv[arg_fwd] || !is_on_phonepad(*argv[arg_fwd]))
|
||||
argv[arg_fwd] = "#";
|
||||
if (!argv[arg_rev] || !is_on_phonepad(*argv[arg_rev]))
|
||||
argv[arg_rev] = "*";
|
||||
if (argv[arg_stop] && !is_on_phonepad(*argv[arg_stop]))
|
||||
argv[arg_stop] = NULL;
|
||||
if (argv[arg_pause] && !is_on_phonepad(*argv[arg_pause]))
|
||||
argv[arg_pause] = NULL;
|
||||
if (argv[arg_restart] && !is_on_phonepad(*argv[arg_restart]))
|
||||
argv[arg_restart] = NULL;
|
||||
|
||||
if (argv[options]) {
|
||||
if (strchr(argv[options], 'j'))
|
||||
priority_jump = 1;
|
||||
}
|
||||
|
||||
res = ast_control_streamfile(chan, argv[arg_file], argv[arg_fwd], argv[arg_rev], argv[arg_stop], argv[arg_pause], argv[arg_restart], skipms);
|
||||
|
||||
/* If we stopped on one of our stop keys, return 0 */
|
||||
if (argv[arg_stop] && strchr(argv[arg_stop], res)) {
|
||||
res = 0;
|
||||
pbx_builtin_setvar_helper(chan, "CPLAYBACKSTATUS", "USERSTOPPED");
|
||||
} else {
|
||||
if (res < 0) {
|
||||
if (priority_jump || option_priority_jumping) {
|
||||
if (ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101)) {
|
||||
ast_log(LOG_WARNING, "ControlPlayback tried to jump to priority n+101 as requested, but priority didn't exist\n");
|
||||
}
|
||||
}
|
||||
res = 0;
|
||||
pbx_builtin_setvar_helper(chan, "CPLAYBACKSTATUS", "ERROR");
|
||||
} else
|
||||
pbx_builtin_setvar_helper(chan, "CPLAYBACKSTATUS", "SUCCESS");
|
||||
}
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app);
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(app, controlplayback_exec, synopsis, descrip);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return (char *) tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
256
apps/app_curl.c
Normal file
256
apps/app_curl.c
Normal file
@@ -0,0 +1,256 @@
|
||||
/*
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Copyright (C) 2004 - 2005, Tilghman Lesher
|
||||
*
|
||||
* Tilghman Lesher <curl-20050919@the-tilghman.com>
|
||||
* and Brian Wilkins <bwilkins@cfl.rr.com> (Added POST option)
|
||||
*
|
||||
* app_curl.c is distributed with no restrictions on usage or
|
||||
* redistribution.
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
* \brief Curl - App to load a URL
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <curl/curl.h>
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/lock.h"
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/cli.h"
|
||||
#include "asterisk/options.h"
|
||||
#include "asterisk/module.h"
|
||||
|
||||
static char *tdesc = "Load external URL";
|
||||
|
||||
static char *app = "Curl";
|
||||
|
||||
static char *synopsis = "Load an external URL";
|
||||
|
||||
static char *descrip =
|
||||
" Curl(URL[|postdata]): This application will request the specified URL.\n"
|
||||
"It is mainly used for signalling external applications of an event.\n"
|
||||
"Parameters:\n"
|
||||
" URL - This is the external URL to request.\n"
|
||||
" postdata - This information will be treated as POST data.\n"
|
||||
"This application will set the following variable:\n"
|
||||
" CURL - This variable will contain the resulting page.\n"
|
||||
"This application has been deprecated in favor of the CURL function.\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
struct MemoryStruct {
|
||||
char *memory;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
static void *myrealloc(void *ptr, size_t size)
|
||||
{
|
||||
/* There might be a realloc() out there that doesn't like reallocing
|
||||
NULL pointers, so we take care of it here */
|
||||
if (ptr)
|
||||
return realloc(ptr, size);
|
||||
else
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
static size_t WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data)
|
||||
{
|
||||
register int realsize = size * nmemb;
|
||||
struct MemoryStruct *mem = (struct MemoryStruct *)data;
|
||||
|
||||
mem->memory = (char *)myrealloc(mem->memory, mem->size + realsize + 1);
|
||||
if (mem->memory) {
|
||||
memcpy(&(mem->memory[mem->size]), ptr, realsize);
|
||||
mem->size += realsize;
|
||||
mem->memory[mem->size] = 0;
|
||||
}
|
||||
return realsize;
|
||||
}
|
||||
|
||||
static int curl_internal(struct MemoryStruct *chunk, char *url, char *post)
|
||||
{
|
||||
CURL *curl;
|
||||
|
||||
curl_global_init(CURL_GLOBAL_ALL);
|
||||
curl = curl_easy_init();
|
||||
|
||||
if (!curl) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_URL, url);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)chunk);
|
||||
curl_easy_setopt(curl, CURLOPT_USERAGENT, "asterisk-libcurl-agent/1.0");
|
||||
|
||||
if (post) {
|
||||
curl_easy_setopt(curl, CURLOPT_POST, 1);
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post);
|
||||
}
|
||||
|
||||
curl_easy_perform(curl);
|
||||
curl_easy_cleanup(curl);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int curl_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res = 0;
|
||||
struct localuser *u;
|
||||
char *info, *post_data=NULL, *url;
|
||||
struct MemoryStruct chunk = { NULL, 0 };
|
||||
static int dep_warning = 0;
|
||||
|
||||
if (!dep_warning) {
|
||||
ast_log(LOG_WARNING, "The application Curl is deprecated. Please use the CURL() function instead.\n");
|
||||
dep_warning = 1;
|
||||
}
|
||||
|
||||
if (ast_strlen_zero(data)) {
|
||||
ast_log(LOG_WARNING, "Curl requires an argument (URL)\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
if ((info = ast_strdupa(data))) {
|
||||
url = strsep(&info, "|");
|
||||
post_data = info;
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Out of memory\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (! curl_internal(&chunk, url, post_data)) {
|
||||
if (chunk.memory) {
|
||||
chunk.memory[chunk.size] = '\0';
|
||||
if (chunk.memory[chunk.size - 1] == 10)
|
||||
chunk.memory[chunk.size - 1] = '\0';
|
||||
|
||||
pbx_builtin_setvar_helper(chan, "CURL", chunk.memory);
|
||||
|
||||
free(chunk.memory);
|
||||
}
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Cannot allocate curl structure\n");
|
||||
res = -1;
|
||||
}
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
static char *acf_curl_exec(struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len)
|
||||
{
|
||||
struct localuser *u;
|
||||
char *info, *post_data=NULL, *url;
|
||||
struct MemoryStruct chunk = { NULL, 0 };
|
||||
|
||||
*buf = '\0';
|
||||
|
||||
if (ast_strlen_zero(data)) {
|
||||
ast_log(LOG_WARNING, "CURL requires an argument (URL)\n");
|
||||
return buf;
|
||||
}
|
||||
|
||||
LOCAL_USER_ACF_ADD(u);
|
||||
|
||||
info = ast_strdupa(data);
|
||||
if (!info) {
|
||||
ast_log(LOG_ERROR, "Out of memory\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return buf;
|
||||
}
|
||||
|
||||
url = strsep(&info, "|");
|
||||
post_data = info;
|
||||
|
||||
if (! curl_internal(&chunk, url, post_data)) {
|
||||
if (chunk.memory) {
|
||||
chunk.memory[chunk.size] = '\0';
|
||||
if (chunk.memory[chunk.size - 1] == 10)
|
||||
chunk.memory[chunk.size - 1] = '\0';
|
||||
|
||||
ast_copy_string(buf, chunk.memory, len);
|
||||
free(chunk.memory);
|
||||
}
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Cannot allocate curl structure\n");
|
||||
}
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return buf;
|
||||
}
|
||||
|
||||
struct ast_custom_function acf_curl = {
|
||||
.name = "CURL",
|
||||
.synopsis = "Retrieves the contents of a URL",
|
||||
.syntax = "CURL(url[|post-data])",
|
||||
.desc =
|
||||
" url - URL to retrieve\n"
|
||||
" post-data - Optional data to send as a POST (GET is default action)\n",
|
||||
.read = acf_curl_exec,
|
||||
};
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_custom_function_unregister(&acf_curl);
|
||||
res |= ast_unregister_application(app);
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_custom_function_register(&acf_curl);
|
||||
res |= ast_register_application(app, curl_exec, synopsis, descrip);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
389
apps/app_cut.c
Executable file → Normal file
389
apps/app_cut.c
Executable file → Normal file
@@ -1,98 +1,192 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* Cut application
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Copyright (c) 2003 Tilghman Lesher. All rights reserved.
|
||||
*
|
||||
* Tilghman Lesher <app_cut__v002@the-tilghman.com>
|
||||
*
|
||||
* $Id$
|
||||
* Tilghman Lesher <app_cut__v003@the-tilghman.com>
|
||||
*
|
||||
* This code is released by the author with no restrictions on usage.
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
* \brief Cut application
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/options.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/options.h"
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/app.h"
|
||||
|
||||
/* Maximum length of any variable */
|
||||
#define MAXRESULT 1024
|
||||
|
||||
static char *tdesc = "Cuts up variables";
|
||||
static char *tdesc = "Cut out information from a string";
|
||||
|
||||
static char *app_cut = "Cut";
|
||||
|
||||
static char *cut_synopsis = "Cut(newvar=varname|delimiter|fieldspec)";
|
||||
static char *cut_synopsis = "Splits a variable's contents using the specified delimiter";
|
||||
|
||||
static char *cut_descrip =
|
||||
"Cut(newvar=varname,delimiter,field)\n"
|
||||
" Cut(newvar=varname,delimiter,fieldspec): This applicaiton will split the\n"
|
||||
"contents of a variable based on the given delimeter and store the result in\n"
|
||||
"a new variable.\n"
|
||||
"Parameters:\n"
|
||||
" newvar - new variable created from result string\n"
|
||||
" varname - variable you want cut\n"
|
||||
" delimiter - defaults to '-'\n"
|
||||
" fieldspec - number of the field you want (1-based offset)\n"
|
||||
" may also be specified as a range (with -)\n"
|
||||
" or group of ranges and fields (with &)\n"
|
||||
" Returns 0 or -1 on hangup or error.\n";
|
||||
" may also be specified as a range (with -)\n"
|
||||
" or group of ranges and fields (with &)\n"
|
||||
"This application has been deprecated in favor of the CUT function.\n";
|
||||
|
||||
static char *app_sort = "Sort";
|
||||
static char *app_sort_synopsis = "Sorts a list of keywords and values";
|
||||
static char *app_sort_descrip =
|
||||
" Sort(newvar=key1:val1[,key2:val2[[...],keyN:valN]]): This application will\n"
|
||||
"sort the list provided in ascending order. The result will be stored in the\n"
|
||||
"specified variable name.\n"
|
||||
" This applicaiton has been deprecated in favor of the SORT function.\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int cut_exec(struct ast_channel *chan, void *data)
|
||||
struct sortable_keys {
|
||||
char *key;
|
||||
float value;
|
||||
};
|
||||
|
||||
static int sort_subroutine(const void *arg1, const void *arg2)
|
||||
{
|
||||
int res=0;
|
||||
struct localuser *u;
|
||||
char *s, *newvar=NULL, *varname=NULL, *delimiter=NULL, *field=NULL;
|
||||
const struct sortable_keys *one=arg1, *two=arg2;
|
||||
if (one->value < two->value) {
|
||||
return -1;
|
||||
} else if (one->value == two->value) {
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
#define ERROR_NOARG (-1)
|
||||
#define ERROR_NOMEM (-2)
|
||||
#define ERROR_USAGE (-3)
|
||||
|
||||
static int sort_internal(struct ast_channel *chan, char *data, char *buffer, size_t buflen)
|
||||
{
|
||||
char *strings, *ptrkey, *ptrvalue;
|
||||
int count=1, count2, element_count=0;
|
||||
struct sortable_keys *sortable_keys;
|
||||
|
||||
memset(buffer, 0, buflen);
|
||||
|
||||
if (!data) {
|
||||
return ERROR_NOARG;
|
||||
}
|
||||
|
||||
strings = ast_strdupa((char *)data);
|
||||
if (!strings) {
|
||||
return ERROR_NOMEM;
|
||||
}
|
||||
|
||||
for (ptrkey = strings; *ptrkey; ptrkey++) {
|
||||
if (*ptrkey == '|') {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
sortable_keys = alloca(count * sizeof(struct sortable_keys));
|
||||
if (!sortable_keys) {
|
||||
return ERROR_NOMEM;
|
||||
}
|
||||
|
||||
memset(sortable_keys, 0, count * sizeof(struct sortable_keys));
|
||||
|
||||
/* Parse each into a struct */
|
||||
count2 = 0;
|
||||
while ((ptrkey = strsep(&strings, "|"))) {
|
||||
ptrvalue = index(ptrkey, ':');
|
||||
if (!ptrvalue) {
|
||||
count--;
|
||||
continue;
|
||||
}
|
||||
*ptrvalue = '\0';
|
||||
ptrvalue++;
|
||||
sortable_keys[count2].key = ptrkey;
|
||||
sscanf(ptrvalue, "%f", &sortable_keys[count2].value);
|
||||
count2++;
|
||||
}
|
||||
|
||||
/* Sort the structs */
|
||||
qsort(sortable_keys, count, sizeof(struct sortable_keys), sort_subroutine);
|
||||
|
||||
for (count2 = 0; count2 < count; count2++) {
|
||||
int blen = strlen(buffer);
|
||||
if (element_count++) {
|
||||
strncat(buffer + blen, ",", buflen - blen - 1);
|
||||
blen++;
|
||||
}
|
||||
strncat(buffer + blen, sortable_keys[count2].key, buflen - blen - 1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cut_internal(struct ast_channel *chan, char *data, char *buffer, size_t buflen)
|
||||
{
|
||||
char *s, *args[3], *varname=NULL, *delimiter=NULL, *field=NULL;
|
||||
int args_okay = 0;
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
memset(buffer, 0, buflen);
|
||||
|
||||
/* Check and parse arguments */
|
||||
if (data) {
|
||||
s = ast_strdupa((char *)data);
|
||||
if (s) {
|
||||
newvar = strsep(&s, "=");
|
||||
if (newvar && (newvar[0] != '\0')) {
|
||||
varname = strsep(&s, "|");
|
||||
if (varname && (varname[0] != '\0')) {
|
||||
delimiter = strsep(&s, "|");
|
||||
if (delimiter) {
|
||||
field = strsep(&s, "|");
|
||||
if (field) {
|
||||
args_okay = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
ast_app_separate_args(s, '|', args, 3);
|
||||
varname = args[0];
|
||||
delimiter = args[1];
|
||||
field = args[2];
|
||||
|
||||
if (field) {
|
||||
args_okay = 1;
|
||||
}
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Out of memory\n");
|
||||
res = -1;
|
||||
return ERROR_NOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
if (args_okay) {
|
||||
char d, ds[2];
|
||||
char *tmp = alloca(strlen(varname) + 4);
|
||||
char *tmp2 = alloca(MAXRESULT);
|
||||
char retstring[MAXRESULT];
|
||||
char varvalue[MAXRESULT], *tmp2=varvalue;
|
||||
|
||||
memset(retstring, 0, MAXRESULT);
|
||||
|
||||
if (tmp && tmp2) {
|
||||
if (tmp) {
|
||||
snprintf(tmp, strlen(varname) + 4, "${%s}", varname);
|
||||
memset(tmp2, 0, sizeof(tmp2));
|
||||
memset(varvalue, 0, sizeof(varvalue));
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Out of memory");
|
||||
return -1;
|
||||
return ERROR_NOMEM;
|
||||
}
|
||||
|
||||
if (delimiter[0])
|
||||
@@ -101,7 +195,7 @@ static int cut_exec(struct ast_channel *chan, void *data)
|
||||
d = '-';
|
||||
|
||||
/* String form of the delimiter, for use with strsep(3) */
|
||||
sprintf(ds,"%c",d);
|
||||
snprintf(ds, sizeof(ds), "%c", d);
|
||||
|
||||
pbx_substitute_variables_helper(chan, tmp, tmp2, MAXRESULT - 1);
|
||||
|
||||
@@ -124,9 +218,7 @@ static int cut_exec(struct ast_channel *chan, void *data)
|
||||
/* single number */
|
||||
num2 = num1;
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Cut(): Illegal range '%s'\n", nextgroup);
|
||||
ast_log(LOG_ERROR, "Usage: %s\n", cut_synopsis);
|
||||
return -1;
|
||||
return ERROR_USAGE;
|
||||
}
|
||||
|
||||
/* Get to start, if any */
|
||||
@@ -139,7 +231,7 @@ static int cut_exec(struct ast_channel *chan, void *data)
|
||||
|
||||
/* Most frequent problem is the expectation of reordering fields */
|
||||
if ((num1 > 0) && (curfieldnum > num1)) {
|
||||
ast_log(LOG_WARNING, "Cut(): we're already past the field you wanted?\n");
|
||||
ast_log(LOG_WARNING, "We're already past the field you wanted?\n");
|
||||
}
|
||||
|
||||
/* Re-null tmp2 if we added 1 to NULL */
|
||||
@@ -149,35 +241,218 @@ static int cut_exec(struct ast_channel *chan, void *data)
|
||||
/* Output fields until we either run out of fields or num2 is reached */
|
||||
while ((tmp2 != NULL) && (curfieldnum <= num2)) {
|
||||
char *tmp3 = strsep(&tmp2, ds);
|
||||
int curlen = strlen(retstring);
|
||||
int curlen = strlen(buffer);
|
||||
|
||||
if (strlen(retstring)) {
|
||||
snprintf(retstring + curlen, MAXRESULT - curlen, "%c%s", d, tmp3);
|
||||
if (curlen) {
|
||||
snprintf(buffer + curlen, buflen - curlen, "%c%s", d, tmp3);
|
||||
} else {
|
||||
snprintf(retstring, MAXRESULT, "%s", tmp3);
|
||||
snprintf(buffer, buflen, "%s", tmp3);
|
||||
}
|
||||
|
||||
curfieldnum++;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return ERROR_NOARG;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
pbx_builtin_setvar_helper(chan, newvar, retstring);
|
||||
static int sort_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0;
|
||||
struct localuser *u;
|
||||
char *varname, *strings, result[512] = "";
|
||||
static int dep_warning=0;
|
||||
|
||||
if (!dep_warning) {
|
||||
ast_log(LOG_WARNING, "The application Sort is deprecated. Please use the SORT() function instead.\n");
|
||||
dep_warning=1;
|
||||
}
|
||||
|
||||
if (!data) {
|
||||
ast_log(LOG_ERROR, "Sort() requires an argument\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
strings = ast_strdupa((char *)data);
|
||||
if (!strings) {
|
||||
ast_log(LOG_ERROR, "Out of memory\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return 0;
|
||||
}
|
||||
|
||||
varname = strsep(&strings, "=");
|
||||
switch (sort_internal(chan, strings, result, sizeof(result))) {
|
||||
case ERROR_NOARG:
|
||||
ast_log(LOG_ERROR, "Sort() requires an argument\n");
|
||||
res = 0;
|
||||
break;
|
||||
case ERROR_NOMEM:
|
||||
ast_log(LOG_ERROR, "Out of memory\n");
|
||||
res = -1;
|
||||
break;
|
||||
case 0:
|
||||
pbx_builtin_setvar_helper(chan, varname, result);
|
||||
res = 0;
|
||||
break;
|
||||
default:
|
||||
ast_log(LOG_ERROR, "Unknown internal error\n");
|
||||
res = -1;
|
||||
}
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int cut_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0;
|
||||
struct localuser *u;
|
||||
char *s, *newvar=NULL, result[512];
|
||||
static int dep_warning = 0;
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
if (!dep_warning) {
|
||||
ast_log(LOG_WARNING, "The application Cut is deprecated. Please use the CUT() function instead.\n");
|
||||
dep_warning=1;
|
||||
}
|
||||
|
||||
/* Check and parse arguments */
|
||||
if (data) {
|
||||
s = ast_strdupa((char *)data);
|
||||
if (s) {
|
||||
newvar = strsep(&s, "=");
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Out of memory\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
switch (cut_internal(chan, s, result, sizeof(result))) {
|
||||
case ERROR_NOARG:
|
||||
ast_log(LOG_ERROR, "Cut() requires an argument\n");
|
||||
res = 0;
|
||||
break;
|
||||
case ERROR_NOMEM:
|
||||
ast_log(LOG_ERROR, "Out of memory\n");
|
||||
res = -1;
|
||||
break;
|
||||
case ERROR_USAGE:
|
||||
ast_log(LOG_ERROR, "Usage: %s\n", cut_synopsis);
|
||||
res = 0;
|
||||
break;
|
||||
case 0:
|
||||
pbx_builtin_setvar_helper(chan, newvar, result);
|
||||
res = 0;
|
||||
break;
|
||||
default:
|
||||
ast_log(LOG_ERROR, "Unknown internal error\n");
|
||||
res = -1;
|
||||
}
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
static char *acf_sort_exec(struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len)
|
||||
{
|
||||
struct localuser *u;
|
||||
|
||||
LOCAL_USER_ACF_ADD(u);
|
||||
|
||||
switch (sort_internal(chan, data, buf, len)) {
|
||||
case ERROR_NOARG:
|
||||
ast_log(LOG_ERROR, "SORT() requires an argument\n");
|
||||
break;
|
||||
case ERROR_NOMEM:
|
||||
ast_log(LOG_ERROR, "Out of memory\n");
|
||||
break;
|
||||
case 0:
|
||||
break;
|
||||
default:
|
||||
ast_log(LOG_ERROR, "Unknown internal error\n");
|
||||
}
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static char *acf_cut_exec(struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len)
|
||||
{
|
||||
struct localuser *u;
|
||||
|
||||
LOCAL_USER_ACF_ADD(u);
|
||||
|
||||
switch (cut_internal(chan, data, buf, len)) {
|
||||
case ERROR_NOARG:
|
||||
ast_log(LOG_ERROR, "CUT() requires an argument\n");
|
||||
break;
|
||||
case ERROR_NOMEM:
|
||||
ast_log(LOG_ERROR, "Out of memory\n");
|
||||
break;
|
||||
case ERROR_USAGE:
|
||||
ast_log(LOG_ERROR, "Usage: %s\n", cut_synopsis);
|
||||
break;
|
||||
case 0:
|
||||
break;
|
||||
default:
|
||||
ast_log(LOG_ERROR, "Unknown internal error\n");
|
||||
}
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return buf;
|
||||
}
|
||||
|
||||
struct ast_custom_function acf_sort = {
|
||||
.name = "SORT",
|
||||
.synopsis = "Sorts a list of key/vals into a list of keys, based upon the vals",
|
||||
.syntax = "SORT(key1:val1[...][,keyN:valN])",
|
||||
.desc =
|
||||
"Takes a comma-separated list of keys and values, each separated by a colon, and returns a\n"
|
||||
"comma-separated list of the keys, sorted by their values. Values will be evaluated as\n"
|
||||
"floating-point numbers.\n",
|
||||
.read = acf_sort_exec,
|
||||
};
|
||||
|
||||
struct ast_custom_function acf_cut = {
|
||||
.name = "CUT",
|
||||
.synopsis = "Slices and dices strings, based upon a named delimiter.",
|
||||
.syntax = "CUT(<varname>,<char-delim>,<range-spec>)",
|
||||
.desc =
|
||||
" varname - variable you want cut\n"
|
||||
" char-delim - defaults to '-'\n"
|
||||
" range-spec - number of the field you want (1-based offset)\n"
|
||||
" may also be specified as a range (with -)\n"
|
||||
" or group of ranges and fields (with &)\n",
|
||||
.read = acf_cut_exec,
|
||||
};
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_custom_function_unregister(&acf_cut);
|
||||
res |= ast_custom_function_unregister(&acf_sort);
|
||||
res |= ast_unregister_application(app_sort);
|
||||
res |= ast_unregister_application(app_cut);
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app_cut);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(app_cut, cut_exec, cut_synopsis, cut_descrip);
|
||||
int res;
|
||||
|
||||
res = ast_custom_function_register(&acf_cut);
|
||||
res |= ast_custom_function_register(&acf_sort);
|
||||
res |= ast_register_application(app_sort, sort_exec, app_sort_synopsis, app_sort_descrip);
|
||||
res |= ast_register_application(app_cut, cut_exec, cut_synopsis, cut_descrip);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
|
||||
53
apps/app_datetime.c
Executable file → Normal file
53
apps/app_datetime.c
Executable file → Normal file
@@ -1,30 +1,43 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Time of day - Report the time of day
|
||||
*
|
||||
* Copyright (C) 1999, Mark Spencer
|
||||
* Copyright (C) 1999 - 2005, Digium, Inc.
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
* Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/say.h>
|
||||
/*! \file
|
||||
* \brief Time of day - Report the time of day
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <pthread.h>
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/lock.h"
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/say.h"
|
||||
|
||||
static char *tdesc = "Date and Time";
|
||||
|
||||
@@ -33,8 +46,7 @@ static char *app = "DateTime";
|
||||
static char *synopsis = "Say the date and time";
|
||||
|
||||
static char *descrip =
|
||||
" DateTime(): Says the current date and time. Returns -1 on hangup or 0\n"
|
||||
"otherwise.\n";
|
||||
" DateTime(): This application will say the current date and time.\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
@@ -57,8 +69,13 @@ static int datetime_exec(struct ast_channel *chan, void *data)
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app);
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
|
||||
511
apps/app_db.c
Executable file → Normal file
511
apps/app_db.c
Executable file → Normal file
@@ -1,52 +1,74 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Database access functions
|
||||
*
|
||||
* Copyright (C) 1999, Mark Spencer
|
||||
* Copyright (C) 1999 - 2005, Digium, Inc.
|
||||
* Copyright (C) 2003, Jefferson Noxon
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
* Mark Spencer <markster@digium.com>
|
||||
* Jefferson Noxon <jeff@debian.org>
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief Database access functions
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <asterisk/options.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/astdb.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
static char *tdesc = "Database access functions for Asterisk extension logic";
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/options.h"
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/astdb.h"
|
||||
#include "asterisk/lock.h"
|
||||
#include "asterisk/options.h"
|
||||
|
||||
static char *tdesc = "Database Access Functions";
|
||||
|
||||
static char *g_descrip =
|
||||
" DBget(varname=family/key): Retrieves a value from the Asterisk\n"
|
||||
"database and stores it in the given variable. Always returns 0. If the\n"
|
||||
"requested key is not found, jumps to priority n+101 if available.\n";
|
||||
" DBget(varname=family/key[|options]): This application will retrieve a value\n"
|
||||
"from the Asterisk database and store it in the given variable.\n"
|
||||
" Options:\n"
|
||||
" j - Jump to priority n+101 if the requested family/key isn't found.\n"
|
||||
" This application sets the following channel variable upon completion:\n"
|
||||
" DBGETSTATUS - This variable will contain the status of the attempt\n"
|
||||
" FOUND | NOTFOUND \n"
|
||||
" This application has been deprecated in favor of the DB function.\n";
|
||||
|
||||
static char *p_descrip =
|
||||
" DBput(family/key=value): Stores the given value in the Asterisk\n"
|
||||
"database. Always returns 0.\n";
|
||||
" DBput(family/key=value): This application will store the given value in the\n"
|
||||
"specified location in the Asterisk database.\n"
|
||||
" This application has been deprecated in favor of the DB function.\n";
|
||||
|
||||
static char *d_descrip =
|
||||
" DBdel(family/key): Deletes a key from the Asterisk database. Always\n"
|
||||
"returns 0.\n";
|
||||
" DBdel(family/key): This applicaiton will delete a key from the Asterisk\n"
|
||||
"database.\n";
|
||||
|
||||
static char *dt_descrip =
|
||||
" DBdeltree(family[/keytree]): Deletes a family or keytree from the Asterisk\n"
|
||||
"database. Always returns 0.\n";
|
||||
" DBdeltree(family[/keytree]): This application will delete a family or keytree\n"
|
||||
"from the Asterisk database\n";
|
||||
|
||||
static char *g_app = "DBget";
|
||||
static char *p_app = "DBput";
|
||||
@@ -62,255 +84,240 @@ STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
|
||||
static int
|
||||
deltree_exec (struct ast_channel *chan, void *data)
|
||||
static int deltree_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int arglen;
|
||||
char *argv, *family, *keytree;
|
||||
char *argv, *family, *keytree;
|
||||
struct localuser *u;
|
||||
|
||||
arglen = strlen (data);
|
||||
argv = alloca (arglen + 1);
|
||||
if (!argv) /* Why would this fail? */
|
||||
{
|
||||
ast_log (LOG_DEBUG, "Memory allocation failed\n");
|
||||
return 0;
|
||||
}
|
||||
memcpy (argv, data, arglen + 1);
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
if (strchr (argv, '/')) {
|
||||
{
|
||||
family = strsep (&argv, "/");
|
||||
keytree = strsep (&argv, "\0");
|
||||
if (!family || !keytree)
|
||||
{
|
||||
ast_log (LOG_DEBUG, "Ignoring; Syntax error in argument\n");
|
||||
return 0;
|
||||
}
|
||||
if (!strlen (keytree))
|
||||
keytree = 0;
|
||||
}
|
||||
} else
|
||||
{
|
||||
family = argv;
|
||||
keytree = 0;
|
||||
}
|
||||
|
||||
if (option_verbose > 2)
|
||||
{
|
||||
if (keytree)
|
||||
ast_verbose (VERBOSE_PREFIX_3 "DBdeltree: family=%s, keytree=%s\n",
|
||||
family, keytree);
|
||||
else
|
||||
ast_verbose (VERBOSE_PREFIX_3 "DBdeltree: family=%s\n", family);
|
||||
}
|
||||
|
||||
if (ast_db_deltree (family, keytree))
|
||||
{
|
||||
if (option_verbose > 2)
|
||||
ast_verbose (VERBOSE_PREFIX_3
|
||||
"DBdeltree: Error deleting key from database.\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
del_exec (struct ast_channel *chan, void *data)
|
||||
{
|
||||
int arglen;
|
||||
char *argv, *family, *key;
|
||||
|
||||
arglen = strlen (data);
|
||||
argv = alloca (arglen + 1);
|
||||
if (!argv) /* Why would this fail? */
|
||||
{
|
||||
ast_log (LOG_DEBUG, "Memory allocation failed\n");
|
||||
return 0;
|
||||
}
|
||||
memcpy (argv, data, arglen + 1);
|
||||
|
||||
if (strchr (argv, '/'))
|
||||
{
|
||||
family = strsep (&argv, "/");
|
||||
key = strsep (&argv, "\0");
|
||||
if (!family || !key)
|
||||
{
|
||||
ast_log (LOG_DEBUG, "Ignoring; Syntax error in argument\n");
|
||||
return 0;
|
||||
}
|
||||
if (option_verbose > 2)
|
||||
ast_verbose (VERBOSE_PREFIX_3
|
||||
"DBdel: family=%s, key=%s\n", family, key);
|
||||
if (ast_db_del (family, key))
|
||||
{
|
||||
if (option_verbose > 2)
|
||||
ast_verbose (VERBOSE_PREFIX_3
|
||||
"DBdel: Error deleting key from database.\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ast_log (LOG_DEBUG, "Ignoring, no parameters\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
put_exec (struct ast_channel *chan, void *data)
|
||||
{
|
||||
int arglen;
|
||||
char *argv, *value, *family, *key;
|
||||
|
||||
arglen = strlen (data);
|
||||
argv = alloca (arglen + 1);
|
||||
if (!argv) /* Why would this fail? */
|
||||
{
|
||||
ast_log (LOG_DEBUG, "Memory allocation failed\n");
|
||||
return 0;
|
||||
}
|
||||
memcpy (argv, data, arglen + 1);
|
||||
|
||||
if (strchr (argv, '/') && strchr (argv, '='))
|
||||
{
|
||||
family = strsep (&argv, "/");
|
||||
key = strsep (&argv, "=");
|
||||
value = strsep (&argv, "\0");
|
||||
if (!value || !family || !key)
|
||||
{
|
||||
ast_log (LOG_DEBUG, "Ignoring; Syntax error in argument\n");
|
||||
return 0;
|
||||
}
|
||||
if (option_verbose > 2)
|
||||
ast_verbose (VERBOSE_PREFIX_3
|
||||
"DBput: family=%s, key=%s, value=%s\n", family, key,
|
||||
value);
|
||||
if (ast_db_put (family, key, value))
|
||||
{
|
||||
if (option_verbose > 2)
|
||||
ast_verbose (VERBOSE_PREFIX_3
|
||||
"DBput: Error writing value to database.\n");
|
||||
argv = ast_strdupa(data);
|
||||
if (!argv) {
|
||||
ast_log(LOG_ERROR, "Memory allocation failed\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
ast_log (LOG_DEBUG, "Ignoring, no parameters\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
get_exec (struct ast_channel *chan, void *data)
|
||||
{
|
||||
int arglen;
|
||||
char *argv, *varname, *family, *key;
|
||||
char dbresult[256];
|
||||
|
||||
arglen = strlen (data);
|
||||
argv = alloca (arglen + 1);
|
||||
if (!argv) /* Why would this fail? */
|
||||
{
|
||||
ast_log (LOG_DEBUG, "Memory allocation failed\n");
|
||||
return 0;
|
||||
}
|
||||
memcpy (argv, data, arglen + 1);
|
||||
|
||||
if (strchr (argv, '=') && strchr (argv, '/'))
|
||||
{
|
||||
varname = strsep (&argv, "=");
|
||||
family = strsep (&argv, "/");
|
||||
key = strsep (&argv, "\0");
|
||||
if (!varname || !family || !key)
|
||||
{
|
||||
ast_log (LOG_DEBUG, "Ignoring; Syntax error in argument\n");
|
||||
return 0;
|
||||
}
|
||||
if (option_verbose > 2)
|
||||
ast_verbose (VERBOSE_PREFIX_3
|
||||
"DBget: varname=%s, family=%s, key=%s\n", varname,
|
||||
family, key);
|
||||
if (!ast_db_get (family, key, dbresult, sizeof (dbresult) - 1))
|
||||
{
|
||||
pbx_builtin_setvar_helper (chan, varname, dbresult);
|
||||
if (option_verbose > 2)
|
||||
ast_verbose (VERBOSE_PREFIX_3
|
||||
"DBget: set variable %s to %s\n", varname, dbresult);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (option_verbose > 2)
|
||||
ast_verbose (VERBOSE_PREFIX_3
|
||||
"DBget: Value not found in database.\n");
|
||||
/* Send the call to n+101 priority, where n is the current priority */
|
||||
if (ast_exists_extension
|
||||
(chan, chan->context, chan->exten, chan->priority + 101,
|
||||
chan->callerid))
|
||||
chan->priority += 100;
|
||||
if (strchr(argv, '/')) {
|
||||
family = strsep(&argv, "/");
|
||||
keytree = strsep(&argv, "\0");
|
||||
if (!family || !keytree) {
|
||||
ast_log(LOG_DEBUG, "Ignoring; Syntax error in argument\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return 0;
|
||||
}
|
||||
if (ast_strlen_zero(keytree))
|
||||
keytree = 0;
|
||||
} else {
|
||||
family = argv;
|
||||
keytree = 0;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
ast_log (LOG_DEBUG, "Ignoring, no parameters\n");
|
||||
}
|
||||
if (option_verbose > 2) {
|
||||
if (keytree)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "DBdeltree: family=%s, keytree=%s\n", family, keytree);
|
||||
else
|
||||
ast_verbose(VERBOSE_PREFIX_3 "DBdeltree: family=%s\n", family);
|
||||
}
|
||||
|
||||
return 0;
|
||||
if (ast_db_deltree(family, keytree)) {
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "DBdeltree: Error deleting key from database.\n");
|
||||
}
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
unload_module (void)
|
||||
static int del_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int retval;
|
||||
char *argv, *family, *key;
|
||||
struct localuser *u;
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
retval = ast_unregister_application (dt_app);
|
||||
retval |= ast_unregister_application (d_app);
|
||||
retval |= ast_unregister_application (p_app);
|
||||
retval |= ast_unregister_application (g_app);
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
return retval;
|
||||
argv = ast_strdupa(data);
|
||||
if (!argv) {
|
||||
ast_log (LOG_ERROR, "Memory allocation failed\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strchr(argv, '/')) {
|
||||
family = strsep(&argv, "/");
|
||||
key = strsep(&argv, "\0");
|
||||
if (!family || !key) {
|
||||
ast_log(LOG_DEBUG, "Ignoring; Syntax error in argument\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return 0;
|
||||
}
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "DBdel: family=%s, key=%s\n", family, key);
|
||||
if (ast_db_del(family, key)) {
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "DBdel: Error deleting key from database.\n");
|
||||
}
|
||||
} else {
|
||||
ast_log(LOG_DEBUG, "Ignoring, no parameters\n");
|
||||
}
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
load_module (void)
|
||||
static int put_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int retval;
|
||||
char *argv, *value, *family, *key;
|
||||
static int dep_warning = 0;
|
||||
struct localuser *u;
|
||||
|
||||
retval = ast_register_application (g_app, get_exec, g_synopsis, g_descrip);
|
||||
if (!retval)
|
||||
retval =
|
||||
ast_register_application (p_app, put_exec, p_synopsis, p_descrip);
|
||||
if (!retval)
|
||||
retval =
|
||||
ast_register_application (d_app, del_exec, d_synopsis, d_descrip);
|
||||
if (!retval)
|
||||
retval =
|
||||
ast_register_application (dt_app, deltree_exec, dt_synopsis,
|
||||
dt_descrip);
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
return retval;
|
||||
if (!dep_warning) {
|
||||
ast_log(LOG_WARNING, "This application has been deprecated, please use the ${DB(family/key)} function instead.\n");
|
||||
dep_warning = 1;
|
||||
}
|
||||
|
||||
argv = ast_strdupa(data);
|
||||
if (!argv) {
|
||||
ast_log(LOG_ERROR, "Memory allocation failed\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strchr(argv, '/') && strchr(argv, '=')) {
|
||||
family = strsep(&argv, "/");
|
||||
key = strsep(&argv, "=");
|
||||
value = strsep(&argv, "\0");
|
||||
if (!value || !family || !key) {
|
||||
ast_log(LOG_DEBUG, "Ignoring; Syntax error in argument\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return 0;
|
||||
}
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "DBput: family=%s, key=%s, value=%s\n", family, key, value);
|
||||
if (ast_db_put(family, key, value)) {
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "DBput: Error writing value to database.\n");
|
||||
}
|
||||
|
||||
} else {
|
||||
ast_log (LOG_DEBUG, "Ignoring, no parameters\n");
|
||||
}
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *
|
||||
description (void)
|
||||
static int get_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
return tdesc;
|
||||
char *argv, *varname, *family, *key, *options = NULL;
|
||||
char dbresult[256];
|
||||
static int dep_warning = 0;
|
||||
int priority_jump = 0;
|
||||
struct localuser *u;
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
if (!dep_warning) {
|
||||
ast_log(LOG_WARNING, "This application has been deprecated, please use the ${DB(family/key)} function instead.\n");
|
||||
dep_warning = 1;
|
||||
}
|
||||
|
||||
argv = ast_strdupa(data);
|
||||
if (!argv) {
|
||||
ast_log(LOG_ERROR, "Memory allocation failed\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strchr(argv, '=') && strchr(argv, '/')) {
|
||||
varname = strsep(&argv, "=");
|
||||
family = strsep(&argv, "/");
|
||||
if (strchr((void *)&argv, '|')) {
|
||||
key = strsep(&argv, "|");
|
||||
options = strsep(&argv, "\0");
|
||||
} else
|
||||
key = strsep(&argv, "\0");
|
||||
|
||||
if (!varname || !family || !key) {
|
||||
ast_log(LOG_DEBUG, "Ignoring; Syntax error in argument\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (options) {
|
||||
if (strchr(options, 'j'))
|
||||
priority_jump = 1;
|
||||
}
|
||||
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "DBget: varname=%s, family=%s, key=%s\n", varname, family, key);
|
||||
if (!ast_db_get(family, key, dbresult, sizeof (dbresult) - 1)) {
|
||||
pbx_builtin_setvar_helper(chan, varname, dbresult);
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "DBget: set variable %s to %s\n", varname, dbresult);
|
||||
pbx_builtin_setvar_helper(chan, "DBGETSTATUS", "FOUND");
|
||||
} else {
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "DBget: Value not found in database.\n");
|
||||
if (priority_jump || option_priority_jumping) {
|
||||
/* Send the call to n+101 priority, where n is the current priority */
|
||||
ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
|
||||
}
|
||||
pbx_builtin_setvar_helper(chan, "DBGETSTATUS", "NOTFOUND");
|
||||
}
|
||||
} else {
|
||||
ast_log(LOG_DEBUG, "Ignoring, no parameters\n");
|
||||
}
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
usecount (void)
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT (res);
|
||||
return res;
|
||||
int retval;
|
||||
|
||||
retval = ast_unregister_application(dt_app);
|
||||
retval |= ast_unregister_application(d_app);
|
||||
retval |= ast_unregister_application(p_app);
|
||||
retval |= ast_unregister_application(g_app);
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
char *
|
||||
key ()
|
||||
int load_module(void)
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
int retval;
|
||||
|
||||
retval = ast_register_application(g_app, get_exec, g_synopsis, g_descrip);
|
||||
retval |= ast_register_application(p_app, put_exec, p_synopsis, p_descrip);
|
||||
retval |= ast_register_application(d_app, del_exec, d_synopsis, d_descrip);
|
||||
retval |= ast_register_application(dt_app, deltree_exec, dt_synopsis, dt_descrip);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
|
||||
1805
apps/app_dial.c
Executable file → Normal file
1805
apps/app_dial.c
Executable file → Normal file
File diff suppressed because it is too large
Load Diff
358
apps/app_dictate.c
Normal file
358
apps/app_dictate.c
Normal file
@@ -0,0 +1,358 @@
|
||||
/*
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Copyright (C) 2005, Anthony Minessale II
|
||||
*
|
||||
* Anthony Minessale II <anthmct@yahoo.com>
|
||||
*
|
||||
* Donated by Sangoma Technologies <http://www.samgoma.com>
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief Virtual Dictation Machine Application For Asterisk
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h> /* for mkdir */
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/say.h"
|
||||
#include "asterisk/lock.h"
|
||||
#include "asterisk/app.h"
|
||||
|
||||
static char *tdesc = "Virtual Dictation Machine";
|
||||
static char *app = "Dictate";
|
||||
static char *synopsis = "Virtual Dictation Machine";
|
||||
static char *desc = " Dictate([<base_dir>])\n"
|
||||
"Start dictation machine using optional base dir for files.\n";
|
||||
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
typedef enum {
|
||||
DFLAG_RECORD = (1 << 0),
|
||||
DFLAG_PLAY = (1 << 1),
|
||||
DFLAG_TRUNC = (1 << 2),
|
||||
DFLAG_PAUSE = (1 << 3),
|
||||
} dflags;
|
||||
|
||||
typedef enum {
|
||||
DMODE_INIT,
|
||||
DMODE_RECORD,
|
||||
DMODE_PLAY
|
||||
} dmodes;
|
||||
|
||||
#define ast_toggle_flag(it,flag) if(ast_test_flag(it, flag)) ast_clear_flag(it, flag); else ast_set_flag(it, flag)
|
||||
|
||||
static int play_and_wait(struct ast_channel *chan, char *file, char *digits)
|
||||
{
|
||||
int res = -1;
|
||||
if (!ast_streamfile(chan, file, chan->language)) {
|
||||
res = ast_waitstream(chan, digits);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static int dictate_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
char *mydata, *argv[2], *path = NULL, filein[256];
|
||||
char dftbase[256];
|
||||
char *base;
|
||||
struct ast_flags flags = {0};
|
||||
struct ast_filestream *fs;
|
||||
struct ast_frame *f = NULL;
|
||||
struct localuser *u;
|
||||
int ffactor = 320 * 80,
|
||||
res = 0,
|
||||
argc = 0,
|
||||
done = 0,
|
||||
oldr = 0,
|
||||
lastop = 0,
|
||||
samples = 0,
|
||||
speed = 1,
|
||||
digit = 0,
|
||||
len = 0,
|
||||
maxlen = 0,
|
||||
mode = 0;
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
snprintf(dftbase, sizeof(dftbase), "%s/dictate", ast_config_AST_SPOOL_DIR);
|
||||
if (!ast_strlen_zero(data) && (mydata = ast_strdupa(data))) {
|
||||
argc = ast_app_separate_args(mydata, '|', argv, sizeof(argv) / sizeof(argv[0]));
|
||||
}
|
||||
|
||||
if (argc) {
|
||||
base = argv[0];
|
||||
} else {
|
||||
base = dftbase;
|
||||
}
|
||||
|
||||
oldr = chan->readformat;
|
||||
if ((res = ast_set_read_format(chan, AST_FORMAT_SLINEAR)) < 0) {
|
||||
ast_log(LOG_WARNING, "Unable to set to linear mode.\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ast_answer(chan);
|
||||
ast_safe_sleep(chan, 200);
|
||||
for(res = 0; !res;) {
|
||||
if (ast_app_getdata(chan, "dictate/enter_filename", filein, sizeof(filein), 0) ||
|
||||
ast_strlen_zero(filein)) {
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
mkdir(base, 0755);
|
||||
len = strlen(base) + strlen(filein) + 2;
|
||||
if (!path || len > maxlen) {
|
||||
path = alloca(len);
|
||||
memset(path, 0, len);
|
||||
maxlen = len;
|
||||
} else {
|
||||
memset(path, 0, maxlen);
|
||||
}
|
||||
|
||||
snprintf(path, len, "%s/%s", base, filein);
|
||||
fs = ast_writefile(path, "raw", NULL, O_CREAT|O_APPEND, 0, 0700);
|
||||
mode = DMODE_PLAY;
|
||||
memset(&flags, 0, sizeof(flags));
|
||||
ast_set_flag(&flags, DFLAG_PAUSE);
|
||||
digit = play_and_wait(chan, "dictate/forhelp", AST_DIGIT_ANY);
|
||||
done = 0;
|
||||
speed = 1;
|
||||
res = 0;
|
||||
lastop = 0;
|
||||
samples = 0;
|
||||
while (!done && ((res = ast_waitfor(chan, -1)) > -1) && fs && (f = ast_read(chan))) {
|
||||
if (digit) {
|
||||
struct ast_frame fr = {AST_FRAME_DTMF, digit};
|
||||
ast_queue_frame(chan, &fr);
|
||||
digit = 0;
|
||||
}
|
||||
if ((f->frametype == AST_FRAME_DTMF)) {
|
||||
int got = 1;
|
||||
switch(mode) {
|
||||
case DMODE_PLAY:
|
||||
switch(f->subclass) {
|
||||
case '1':
|
||||
ast_set_flag(&flags, DFLAG_PAUSE);
|
||||
mode = DMODE_RECORD;
|
||||
break;
|
||||
case '2':
|
||||
speed++;
|
||||
if (speed > 4) {
|
||||
speed = 1;
|
||||
}
|
||||
res = ast_say_number(chan, speed, AST_DIGIT_ANY, chan->language, (char *) NULL);
|
||||
break;
|
||||
case '7':
|
||||
samples -= ffactor;
|
||||
if(samples < 0) {
|
||||
samples = 0;
|
||||
}
|
||||
ast_seekstream(fs, samples, SEEK_SET);
|
||||
break;
|
||||
case '8':
|
||||
samples += ffactor;
|
||||
ast_seekstream(fs, samples, SEEK_SET);
|
||||
break;
|
||||
|
||||
default:
|
||||
got = 0;
|
||||
}
|
||||
break;
|
||||
case DMODE_RECORD:
|
||||
switch(f->subclass) {
|
||||
case '1':
|
||||
ast_set_flag(&flags, DFLAG_PAUSE);
|
||||
mode = DMODE_PLAY;
|
||||
break;
|
||||
case '8':
|
||||
ast_toggle_flag(&flags, DFLAG_TRUNC);
|
||||
lastop = 0;
|
||||
break;
|
||||
default:
|
||||
got = 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
got = 0;
|
||||
}
|
||||
if (!got) {
|
||||
switch(f->subclass) {
|
||||
case '#':
|
||||
done = 1;
|
||||
continue;
|
||||
break;
|
||||
case '*':
|
||||
ast_toggle_flag(&flags, DFLAG_PAUSE);
|
||||
if (ast_test_flag(&flags, DFLAG_PAUSE)) {
|
||||
digit = play_and_wait(chan, "dictate/pause", AST_DIGIT_ANY);
|
||||
} else {
|
||||
digit = play_and_wait(chan, mode == DMODE_PLAY ? "dictate/playback" : "dictate/record", AST_DIGIT_ANY);
|
||||
}
|
||||
break;
|
||||
case '0':
|
||||
ast_set_flag(&flags, DFLAG_PAUSE);
|
||||
digit = play_and_wait(chan, "dictate/paused", AST_DIGIT_ANY);
|
||||
switch(mode) {
|
||||
case DMODE_PLAY:
|
||||
digit = play_and_wait(chan, "dictate/play_help", AST_DIGIT_ANY);
|
||||
break;
|
||||
case DMODE_RECORD:
|
||||
digit = play_and_wait(chan, "dictate/record_help", AST_DIGIT_ANY);
|
||||
break;
|
||||
}
|
||||
if (digit == 0) {
|
||||
digit = play_and_wait(chan, "dictate/both_help", AST_DIGIT_ANY);
|
||||
} else if (digit < 0) {
|
||||
done = 1;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} else if (f->frametype == AST_FRAME_VOICE) {
|
||||
switch(mode) {
|
||||
struct ast_frame *fr;
|
||||
int x;
|
||||
case DMODE_PLAY:
|
||||
if (lastop != DMODE_PLAY) {
|
||||
if (ast_test_flag(&flags, DFLAG_PAUSE)) {
|
||||
digit = play_and_wait(chan, "dictate/playback_mode", AST_DIGIT_ANY);
|
||||
if (digit == 0) {
|
||||
digit = play_and_wait(chan, "dictate/paused", AST_DIGIT_ANY);
|
||||
} else if (digit < 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (lastop != DFLAG_PLAY) {
|
||||
lastop = DFLAG_PLAY;
|
||||
ast_closestream(fs);
|
||||
fs = ast_openstream(chan, path, chan->language);
|
||||
ast_seekstream(fs, samples, SEEK_SET);
|
||||
chan->stream = NULL;
|
||||
}
|
||||
lastop = DMODE_PLAY;
|
||||
}
|
||||
|
||||
if (!ast_test_flag(&flags, DFLAG_PAUSE)) {
|
||||
for (x = 0; x < speed; x++) {
|
||||
if ((fr = ast_readframe(fs))) {
|
||||
ast_write(chan, fr);
|
||||
samples += fr->samples;
|
||||
ast_frfree(fr);
|
||||
fr = NULL;
|
||||
} else {
|
||||
samples = 0;
|
||||
ast_seekstream(fs, 0, SEEK_SET);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DMODE_RECORD:
|
||||
if (lastop != DMODE_RECORD) {
|
||||
int oflags = O_CREAT | O_WRONLY;
|
||||
if (ast_test_flag(&flags, DFLAG_PAUSE)) {
|
||||
digit = play_and_wait(chan, "dictate/record_mode", AST_DIGIT_ANY);
|
||||
if (digit == 0) {
|
||||
digit = play_and_wait(chan, "dictate/paused", AST_DIGIT_ANY);
|
||||
} else if (digit < 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
lastop = DMODE_RECORD;
|
||||
ast_closestream(fs);
|
||||
if ( ast_test_flag(&flags, DFLAG_TRUNC)) {
|
||||
oflags |= O_TRUNC;
|
||||
digit = play_and_wait(chan, "dictate/truncating_audio", AST_DIGIT_ANY);
|
||||
} else {
|
||||
oflags |= O_APPEND;
|
||||
}
|
||||
fs = ast_writefile(path, "raw", NULL, oflags, 0, 0700);
|
||||
if (ast_test_flag(&flags, DFLAG_TRUNC)) {
|
||||
ast_seekstream(fs, 0, SEEK_SET);
|
||||
ast_clear_flag(&flags, DFLAG_TRUNC);
|
||||
} else {
|
||||
ast_seekstream(fs, 0, SEEK_END);
|
||||
}
|
||||
}
|
||||
if (!ast_test_flag(&flags, DFLAG_PAUSE)) {
|
||||
res = ast_writestream(fs, f);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ast_frfree(f);
|
||||
}
|
||||
}
|
||||
if (oldr) {
|
||||
ast_set_read_format(chan, oldr);
|
||||
}
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app);
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(app, dictate_exec, synopsis, desc);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
|
||||
169
apps/app_directed_pickup.c
Normal file
169
apps/app_directed_pickup.c
Normal file
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Copyright (C) 2005, Joshua Colp
|
||||
*
|
||||
* Joshua Colp <jcolp@asterlink.com>
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief Directed Call Pickup Support
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/lock.h"
|
||||
#include "asterisk/app.h"
|
||||
|
||||
static const char *tdesc = "Directed Call Pickup Application";
|
||||
static const char *app = "Pickup";
|
||||
static const char *synopsis = "Directed Call Pickup";
|
||||
static const char *descrip =
|
||||
" Pickup(extension[@context]): This application can pickup any ringing channel\n"
|
||||
"that is calling the specified extension. If no context is specified, the current\n"
|
||||
"context will be used.\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int pickup_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res = 0;
|
||||
struct localuser *u = NULL;
|
||||
struct ast_channel *origin = NULL, *target = NULL;
|
||||
char *tmp = NULL, *exten = NULL, *context = NULL;
|
||||
char workspace[256] = "";
|
||||
|
||||
if (ast_strlen_zero(data)) {
|
||||
ast_log(LOG_WARNING, "Pickup requires an argument (extension) !\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
/* Get the extension and context if present */
|
||||
exten = data;
|
||||
context = strchr(data, '@');
|
||||
if (context) {
|
||||
*context = '\0';
|
||||
context++;
|
||||
}
|
||||
|
||||
/* Find a channel to pickup */
|
||||
origin = ast_get_channel_by_exten_locked(exten, context);
|
||||
if (origin && origin->cdr) {
|
||||
ast_cdr_getvar(origin->cdr, "dstchannel", &tmp, workspace,
|
||||
sizeof(workspace), 0);
|
||||
if (tmp) {
|
||||
/* We have a possible channel... now we need to find it! */
|
||||
target = ast_get_channel_by_name_locked(tmp);
|
||||
} else {
|
||||
ast_log(LOG_DEBUG, "No target channel found.\n");
|
||||
res = -1;
|
||||
}
|
||||
ast_mutex_unlock(&origin->lock);
|
||||
} else {
|
||||
if (origin)
|
||||
ast_mutex_unlock(&origin->lock);
|
||||
ast_log(LOG_DEBUG, "No originating channel found.\n");
|
||||
}
|
||||
|
||||
if (res)
|
||||
goto out;
|
||||
|
||||
if (target && (!target->pbx) && ((target->_state == AST_STATE_RINGING) || (target->_state == AST_STATE_RING))) {
|
||||
ast_log(LOG_DEBUG, "Call pickup on chan '%s' by '%s'\n", target->name,
|
||||
chan->name);
|
||||
res = ast_answer(chan);
|
||||
if (res) {
|
||||
ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name);
|
||||
res = -1;
|
||||
goto out;
|
||||
}
|
||||
res = ast_queue_control(chan, AST_CONTROL_ANSWER);
|
||||
if (res) {
|
||||
ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n",
|
||||
chan->name);
|
||||
res = -1;
|
||||
goto out;
|
||||
}
|
||||
res = ast_channel_masquerade(target, chan);
|
||||
if (res) {
|
||||
ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, target->name);
|
||||
res = -1;
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
ast_log(LOG_DEBUG, "No call pickup possible...\n");
|
||||
res = -1;
|
||||
}
|
||||
/* Done */
|
||||
out:
|
||||
if (target)
|
||||
ast_mutex_unlock(&target->lock);
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app);
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(app, pickup_exec, synopsis, descrip);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return (char *) tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
STANDARD_USECOUNT(res);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
420
apps/app_directory.c
Executable file → Normal file
420
apps/app_directory.c
Executable file → Normal file
@@ -1,48 +1,74 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Provide a directory of extensions
|
||||
*
|
||||
* Copyright (C) 1999, Mark Spencer
|
||||
* Copyright (C) 1999 - 2005, Digium, Inc.
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
* Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief Provide a directory of extensions
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/config.h>
|
||||
#include <asterisk/say.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include "../asterisk.h"
|
||||
#include "../astconf.h"
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/lock.h"
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/config.h"
|
||||
#include "asterisk/say.h"
|
||||
#include "asterisk/utils.h"
|
||||
|
||||
static char *tdesc = "Extension Directory";
|
||||
static char *app = "Directory";
|
||||
|
||||
static char *synopsis = "Provide directory of voicemail extensions";
|
||||
static char *descrip =
|
||||
" Directory(context): Presents the user with a directory of extensions from\n"
|
||||
"which they may select by name. The list of names and extensions is\n"
|
||||
"discovered from voicemail.conf. The context argument is required, and\n"
|
||||
"specifies the context in which to interpret the extensions. Returns 0\n"
|
||||
"unless the user hangs up. It also sets up the channel on exit to enter the\n"
|
||||
"extension the user selected.\n";
|
||||
" Directory(vm-context[|dial-context[|options]]): This application will present\n"
|
||||
"the calling channel with a directory of extensions from which they can search\n"
|
||||
"by name. The list of names and corresponding extensions is retrieved from the\n"
|
||||
"voicemail configuration file, voicemail.conf.\n"
|
||||
" This applicaiton will immediate exit if one of the following DTMF digits are\n"
|
||||
"received and the extension to jump to exists:\n"
|
||||
" 0 - Jump to the 'o' extension, if it exists.\n"
|
||||
" * - Jump to the 'a' extension, if it exists.\n\n"
|
||||
" Parameters:\n"
|
||||
" vm-context - This is the context within voicemail.conf to use for the\n"
|
||||
" Directory.\n"
|
||||
" dial-context - This is the dialplan context to use when looking for an\n"
|
||||
" extension that the user has selected, or when jumping to the\n"
|
||||
" 'o' or 'a' extension.\n\n"
|
||||
" Options:\n"
|
||||
" f - Allow the caller to enter the first name of a user in the directory\n"
|
||||
" instead of using the last name.\n";
|
||||
|
||||
/* For simplicity, I'm keeping the format compatible with the voicemail config,
|
||||
but i'm open to suggestions for isolating it */
|
||||
|
||||
#define DIRECTORY_CONFIG "voicemail.conf"
|
||||
#define VOICEMAIL_CONFIG "voicemail.conf"
|
||||
|
||||
/* How many digits to read in */
|
||||
#define NUMDIGITS 3
|
||||
@@ -120,20 +146,187 @@ static char *convert(char *lastname)
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static int do_directory(struct ast_channel *chan, struct ast_config *cfg, char *context, char digit)
|
||||
/* play name of mailbox owner.
|
||||
* returns: -1 for bad or missing extension
|
||||
* '1' for selected entry from directory
|
||||
* '*' for skipped entry from directory
|
||||
*/
|
||||
static int play_mailbox_owner(struct ast_channel *chan, char *context, char *dialcontext, char *ext, char *name) {
|
||||
int res = 0;
|
||||
int loop = 3;
|
||||
char fn[256];
|
||||
char fn2[256];
|
||||
|
||||
/* Check for the VoiceMail2 greeting first */
|
||||
snprintf(fn, sizeof(fn), "%s/voicemail/%s/%s/greet",
|
||||
(char *)ast_config_AST_SPOOL_DIR, context, ext);
|
||||
|
||||
/* Otherwise, check for an old-style Voicemail greeting */
|
||||
snprintf(fn2, sizeof(fn2), "%s/vm/%s/greet",
|
||||
(char *)ast_config_AST_SPOOL_DIR, ext);
|
||||
|
||||
if (ast_fileexists(fn, NULL, chan->language) > 0) {
|
||||
res = ast_streamfile(chan, fn, chan->language);
|
||||
if (!res) {
|
||||
res = ast_waitstream(chan, AST_DIGIT_ANY);
|
||||
}
|
||||
ast_stopstream(chan);
|
||||
} else if (ast_fileexists(fn2, NULL, chan->language) > 0) {
|
||||
res = ast_streamfile(chan, fn2, chan->language);
|
||||
if (!res) {
|
||||
res = ast_waitstream(chan, AST_DIGIT_ANY);
|
||||
}
|
||||
ast_stopstream(chan);
|
||||
} else {
|
||||
res = ast_say_character_str(chan, !ast_strlen_zero(name) ? name : ext,
|
||||
AST_DIGIT_ANY, chan->language);
|
||||
}
|
||||
|
||||
while (loop) {
|
||||
if (!res) {
|
||||
res = ast_streamfile(chan, "dir-instr", chan->language);
|
||||
}
|
||||
if (!res) {
|
||||
res = ast_waitstream(chan, AST_DIGIT_ANY);
|
||||
}
|
||||
if (!res) {
|
||||
res = ast_waitfordigit(chan, 3000);
|
||||
}
|
||||
ast_stopstream(chan);
|
||||
|
||||
if (res > -1) {
|
||||
switch (res) {
|
||||
case '1':
|
||||
/* Name selected */
|
||||
loop = 0;
|
||||
if (ast_goto_if_exists(chan, dialcontext, ext, 1)) {
|
||||
ast_log(LOG_WARNING,
|
||||
"Can't find extension '%s' in context '%s'. "
|
||||
"Did you pass the wrong context to Directory?\n",
|
||||
ext, dialcontext);
|
||||
res = -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case '*':
|
||||
/* Skip to next match in list */
|
||||
loop = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Not '1', or '*', so decrement number of tries */
|
||||
res = 0;
|
||||
loop--;
|
||||
break;
|
||||
} /* end switch */
|
||||
} /* end if */
|
||||
else {
|
||||
/* User hungup, so jump out now */
|
||||
loop = 0;
|
||||
}
|
||||
} /* end while */
|
||||
|
||||
return(res);
|
||||
}
|
||||
|
||||
static struct ast_config *realtime_directory(char *context)
|
||||
{
|
||||
struct ast_config *cfg;
|
||||
struct ast_config *rtdata;
|
||||
struct ast_category *cat;
|
||||
struct ast_variable *var;
|
||||
char *mailbox;
|
||||
char *fullname;
|
||||
char *hidefromdir;
|
||||
char tmp[100];
|
||||
|
||||
/* Load flat file config. */
|
||||
cfg = ast_config_load(VOICEMAIL_CONFIG);
|
||||
|
||||
if (!cfg) {
|
||||
/* Loading config failed. */
|
||||
ast_log(LOG_WARNING, "Loading config failed.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Get realtime entries, categorized by their mailbox number
|
||||
and present in the requested context */
|
||||
rtdata = ast_load_realtime_multientry("voicemail", "mailbox LIKE", "%", "context", context, NULL);
|
||||
|
||||
/* if there are no results, just return the entries from the config file */
|
||||
if (!rtdata)
|
||||
return cfg;
|
||||
|
||||
/* Does the context exist within the config file? If not, make one */
|
||||
cat = ast_category_get(cfg, context);
|
||||
if (!cat) {
|
||||
cat = ast_category_new(context);
|
||||
if (!cat) {
|
||||
ast_log(LOG_WARNING, "Out of memory\n");
|
||||
ast_config_destroy(cfg);
|
||||
return NULL;
|
||||
}
|
||||
ast_category_append(cfg, cat);
|
||||
}
|
||||
|
||||
mailbox = ast_category_browse(rtdata, NULL);
|
||||
while (mailbox) {
|
||||
fullname = ast_variable_retrieve(rtdata, mailbox, "fullname");
|
||||
hidefromdir = ast_variable_retrieve(rtdata, mailbox, "hidefromdir");
|
||||
snprintf(tmp, sizeof(tmp), "no-password,%s,hidefromdir=%s",
|
||||
fullname ? fullname : "",
|
||||
hidefromdir ? hidefromdir : "no");
|
||||
var = ast_variable_new(mailbox, tmp);
|
||||
if (var)
|
||||
ast_variable_append(cat, var);
|
||||
else
|
||||
ast_log(LOG_WARNING, "Out of memory adding mailbox '%s'\n", mailbox);
|
||||
mailbox = ast_category_browse(rtdata, mailbox);
|
||||
}
|
||||
ast_config_destroy(rtdata);
|
||||
|
||||
return cfg;
|
||||
}
|
||||
|
||||
static int do_directory(struct ast_channel *chan, struct ast_config *cfg, char *context, char *dialcontext, char digit, int last)
|
||||
{
|
||||
/* Read in the first three digits.. "digit" is the first digit, already read */
|
||||
char ext[NUMDIGITS + 1];
|
||||
char name[80] = "";
|
||||
struct ast_variable *v;
|
||||
int res;
|
||||
int found=0;
|
||||
int lastuserchoice = 0;
|
||||
char *start, *pos, *conv,*stringp=NULL;
|
||||
char fn[256];
|
||||
char fn2[256];
|
||||
if (!context || !strlen(context)) {
|
||||
ast_log(LOG_WARNING, "Directory must be called with an argument (context in which to interpret extensions)\n");
|
||||
|
||||
if (ast_strlen_zero(context)) {
|
||||
ast_log(LOG_WARNING,
|
||||
"Directory must be called with an argument "
|
||||
"(context in which to interpret extensions)\n");
|
||||
return -1;
|
||||
}
|
||||
if (digit == '0') {
|
||||
if (!ast_goto_if_exists(chan, chan->context, "o", 1) ||
|
||||
(!ast_strlen_zero(chan->macrocontext) &&
|
||||
!ast_goto_if_exists(chan, chan->macrocontext, "o", 1))) {
|
||||
return 0;
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "Can't find extension 'o' in current context. "
|
||||
"Not Exiting the Directory!\n");
|
||||
res = 0;
|
||||
}
|
||||
}
|
||||
if (digit == '*') {
|
||||
if (!ast_goto_if_exists(chan, chan->context, "a", 1) ||
|
||||
(!ast_strlen_zero(chan->macrocontext) &&
|
||||
!ast_goto_if_exists(chan, chan->macrocontext, "a", 1))) {
|
||||
return 0;
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "Can't find extension 'a' in current context. "
|
||||
"Not Exiting the Directory!\n");
|
||||
res = 0;
|
||||
}
|
||||
}
|
||||
memset(ext, 0, sizeof(ext));
|
||||
ext[0] = digit;
|
||||
res = 0;
|
||||
@@ -146,13 +339,14 @@ static int do_directory(struct ast_channel *chan, struct ast_config *cfg, char *
|
||||
while(v) {
|
||||
/* Find a candidate extension */
|
||||
start = strdup(v->value);
|
||||
if (start) {
|
||||
if (start && !strcasestr(start, "hidefromdir=yes")) {
|
||||
stringp=start;
|
||||
strsep(&stringp, ",");
|
||||
pos = strsep(&stringp, ",");
|
||||
if (pos) {
|
||||
ast_copy_string(name, pos, sizeof(name));
|
||||
/* Grab the last name */
|
||||
if (strrchr(pos, ' '))
|
||||
if (last && strrchr(pos,' '))
|
||||
pos = strrchr(pos, ' ') + 1;
|
||||
conv = convert(pos);
|
||||
if (conv) {
|
||||
@@ -170,59 +364,46 @@ static int do_directory(struct ast_channel *chan, struct ast_config *cfg, char *
|
||||
}
|
||||
v = v->next;
|
||||
}
|
||||
|
||||
if (v) {
|
||||
/* We have a match -- play a greeting if they have it */
|
||||
/* Check for the VoiceMail2 greeting first */
|
||||
snprintf(fn, sizeof(fn), "%s/voicemail/%s/%s/greet", (char *)ast_config_AST_SPOOL_DIR, context, v->name);
|
||||
/* Otherwise, check for an old-style Voicemail greeting */
|
||||
snprintf(fn2, sizeof(fn2), "%s/vm/%s/greet", (char *)ast_config_AST_SPOOL_DIR, v->name);
|
||||
if (ast_fileexists(fn, NULL, chan->language) > 0) {
|
||||
res = ast_streamfile(chan, fn, chan->language);
|
||||
if (!res)
|
||||
res = ast_waitstream(chan, AST_DIGIT_ANY);
|
||||
ast_stopstream(chan);
|
||||
} else if (ast_fileexists(fn2, NULL, chan->language) > 0) {
|
||||
res = ast_streamfile(chan, fn2, chan->language);
|
||||
if (!res)
|
||||
res = ast_waitstream(chan, AST_DIGIT_ANY);
|
||||
ast_stopstream(chan);
|
||||
} else {
|
||||
res = ast_say_digit_str(chan, v->name, AST_DIGIT_ANY, chan->language);
|
||||
}
|
||||
ahem:
|
||||
if (!res)
|
||||
res = ast_streamfile(chan, "dir-instr", chan->language);
|
||||
if (!res)
|
||||
res = ast_waitstream(chan, AST_DIGIT_ANY);
|
||||
if (!res)
|
||||
res = ast_waitfordigit(chan, 3000);
|
||||
ast_stopstream(chan);
|
||||
if (res > -1) {
|
||||
if (res == '1') {
|
||||
strncpy(chan->exten, v->name, sizeof(chan->exten)-1);
|
||||
chan->priority = 0;
|
||||
strncpy(chan->context, context, sizeof(chan->context)-1);
|
||||
res = play_mailbox_owner(chan, context, dialcontext, v->name, name);
|
||||
switch (res) {
|
||||
case -1:
|
||||
/* user pressed '1' but extension does not exist, or
|
||||
* user hungup
|
||||
*/
|
||||
lastuserchoice = 0;
|
||||
break;
|
||||
case '1':
|
||||
/* user pressed '1' and extensions exists;
|
||||
play_mailbox_owner will already have done
|
||||
a goto() on the channel
|
||||
*/
|
||||
lastuserchoice = res;
|
||||
break;
|
||||
case '*':
|
||||
/* user pressed '*' to skip something found */
|
||||
lastuserchoice = res;
|
||||
res = 0;
|
||||
break;
|
||||
} else if (res == '*') {
|
||||
res = 0;
|
||||
v = v->next;
|
||||
} else {
|
||||
res = 0;
|
||||
goto ahem;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (found)
|
||||
res = ast_streamfile(chan, "dir-nomore", chan->language);
|
||||
else
|
||||
res = ast_streamfile(chan, "dir-nomatch", chan->language);
|
||||
if (!res)
|
||||
res = 1;
|
||||
return res;
|
||||
v = v->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (lastuserchoice != '1') {
|
||||
if (found)
|
||||
res = ast_streamfile(chan, "dir-nomore", chan->language);
|
||||
else
|
||||
res = ast_streamfile(chan, "dir-nomatch", chan->language);
|
||||
if (!res)
|
||||
res = 1;
|
||||
return res;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@@ -232,45 +413,84 @@ static int directory_exec(struct ast_channel *chan, void *data)
|
||||
int res = 0;
|
||||
struct localuser *u;
|
||||
struct ast_config *cfg;
|
||||
if (!data) {
|
||||
ast_log(LOG_WARNING, "directory requires an argument (context)\n");
|
||||
return -1;
|
||||
}
|
||||
cfg = ast_load(DIRECTORY_CONFIG);
|
||||
if (!cfg) {
|
||||
ast_log(LOG_WARNING, "Unable to open directory configuration %s\n", DIRECTORY_CONFIG);
|
||||
int last = 1;
|
||||
char *context, *dialcontext, *dirintro, *options;
|
||||
|
||||
if (ast_strlen_zero(data)) {
|
||||
ast_log(LOG_WARNING, "Directory requires an argument (context[,dialcontext])\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
top:
|
||||
|
||||
context = ast_strdupa(data);
|
||||
dialcontext = strchr(context, '|');
|
||||
if (dialcontext) {
|
||||
*dialcontext = '\0';
|
||||
dialcontext++;
|
||||
options = strchr(dialcontext, '|');
|
||||
if (options) {
|
||||
*options = '\0';
|
||||
options++;
|
||||
if (strchr(options, 'f'))
|
||||
last = 0;
|
||||
}
|
||||
} else
|
||||
dialcontext = context;
|
||||
|
||||
cfg = realtime_directory(context);
|
||||
if (!cfg) {
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
dirintro = ast_variable_retrieve(cfg, context, "directoryintro");
|
||||
if (ast_strlen_zero(dirintro))
|
||||
dirintro = ast_variable_retrieve(cfg, "general", "directoryintro");
|
||||
if (ast_strlen_zero(dirintro)) {
|
||||
if (last)
|
||||
dirintro = "dir-intro";
|
||||
else
|
||||
dirintro = "dir-intro-fn";
|
||||
}
|
||||
|
||||
if (chan->_state != AST_STATE_UP)
|
||||
res = ast_answer(chan);
|
||||
if (!res)
|
||||
res = ast_streamfile(chan, "dir-intro", chan->language);
|
||||
if (!res)
|
||||
res = ast_waitstream(chan, AST_DIGIT_ANY);
|
||||
ast_stopstream(chan);
|
||||
if (!res)
|
||||
res = ast_waitfordigit(chan, 5000);
|
||||
if (res > 0) {
|
||||
res = do_directory(chan, cfg, (char *)data, res);
|
||||
if (res > 0) {
|
||||
|
||||
for (;;) {
|
||||
if (!res)
|
||||
res = ast_streamfile(chan, dirintro, chan->language);
|
||||
if (!res)
|
||||
res = ast_waitstream(chan, AST_DIGIT_ANY);
|
||||
ast_stopstream(chan);
|
||||
if (res >= 0) {
|
||||
goto top;
|
||||
ast_stopstream(chan);
|
||||
if (!res)
|
||||
res = ast_waitfordigit(chan, 5000);
|
||||
if (res > 0) {
|
||||
res = do_directory(chan, cfg, context, dialcontext, res, last);
|
||||
if (res > 0) {
|
||||
res = ast_waitstream(chan, AST_DIGIT_ANY);
|
||||
ast_stopstream(chan);
|
||||
if (res >= 0) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
ast_destroy(cfg);
|
||||
ast_config_destroy(cfg);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app);
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
|
||||
439
apps/app_disa.c
Executable file → Normal file
439
apps/app_disa.c
Executable file → Normal file
@@ -1,36 +1,52 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* DISA -- Direct Inward System Access Application 6/20/2001
|
||||
*
|
||||
* Copyright (C) 2001, Linux Support Services, Inc.
|
||||
* Copyright (C) 1999 - 2005, Digium, Inc.
|
||||
*
|
||||
* Jim Dixon <jim@lambdatel.com>
|
||||
*
|
||||
* Made only slightly more sane by Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief DISA -- Direct Inward System Access Application
|
||||
*
|
||||
* \author Jim Dixon <jim@lambdatel.com>
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/translate.h>
|
||||
#include <asterisk/ulaw.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
/*
|
||||
#define TONE_BLOCK_SIZE 320
|
||||
*/
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/lock.h"
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/app.h"
|
||||
#include "asterisk/indications.h"
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/translate.h"
|
||||
#include "asterisk/ulaw.h"
|
||||
#include "asterisk/callerid.h"
|
||||
|
||||
static char *tdesc = "DISA (Direct Inward System Access) Application";
|
||||
|
||||
@@ -39,30 +55,27 @@ static char *app = "DISA";
|
||||
static char *synopsis = "DISA (Direct Inward System Access)";
|
||||
|
||||
static char *descrip =
|
||||
"DISA (Direct Inward System Access) -- Allows someone from outside\n"
|
||||
"the telephone switch (PBX) to obtain an \"internal\" system dialtone\n"
|
||||
"and to place calls from it as if they were placing a call from within\n"
|
||||
"the switch. A user calls a number that connects to the DISA application\n"
|
||||
"and is given dialtone. The user enters their passcode, followed by the\n"
|
||||
"pound sign (#). If the passcode is correct, the user is then given\n"
|
||||
"DISA(<numeric passcode>[|<context>]) or disa(<filename>)\n"
|
||||
"The DISA, Direct Inward System Access, application allows someone from \n"
|
||||
"outside the telephone switch (PBX) to obtain an \"internal\" system \n"
|
||||
"dialtone and to place calls from it as if they were placing a call from \n"
|
||||
"within the switch.\n"
|
||||
"DISA plays a dialtone. The user enters their numeric passcode, followed by\n"
|
||||
"the pound sign (#). If the passcode is correct, the user is then given\n"
|
||||
"system dialtone on which a call may be placed. Obviously, this type\n"
|
||||
"of access has SERIOUS security implications, and GREAT care must be\n"
|
||||
"taken NOT to compromise your security.\n\n"
|
||||
"There is a possibility of accessing DISA without password. Simply\n"
|
||||
"exchange your password with no-password.\n\n"
|
||||
" Example: exten => s,1,DISA,no-password|local\n\n"
|
||||
"but be aware of using this for your security compromising.\n\n"
|
||||
"exchange your password with \"no-password\".\n\n"
|
||||
" Example: exten => s,1,DISA(no-password|local)\n\n"
|
||||
"Be aware that using this compromises the security of your PBX.\n\n"
|
||||
"The arguments to this application (in extensions.conf) allow either\n"
|
||||
"specification of a single global password (that everyone uses), or\n"
|
||||
"individual passwords contained in a file. It also allow specification\n"
|
||||
"specification of a single global passcode (that everyone uses), or\n"
|
||||
"individual passcodes contained in a file. It also allow specification\n"
|
||||
"of the context on which the user will be dialing. If no context is\n"
|
||||
"specified, the DISA application defaults the context to \"disa\"\n"
|
||||
"presumably that a normal system will have a special context set up\n"
|
||||
"for DISA use with some or a lot of restrictions. The arguments are\n"
|
||||
"one of the following:\n\n"
|
||||
" numeric-passcode\n"
|
||||
" numeric-passcode|context\n"
|
||||
" full-pathname-of-file-that-contains-passcodes\n\n"
|
||||
"specified, the DISA application defaults the context to \"disa\".\n"
|
||||
"Presumably a normal system will have a special context set up\n"
|
||||
"for DISA use with some or a lot of restrictions. \n\n"
|
||||
"The file that contains the passcodes (if used) allows specification\n"
|
||||
"of either just a passcode (defaulting to the \"disa\" context, or\n"
|
||||
"passcode|context on each line of the file. The file may contain blank\n"
|
||||
@@ -70,120 +83,125 @@ static char *descrip =
|
||||
"above arguments may have |new-callerid-string appended to them, to\n"
|
||||
"specify a new (different) callerid to be used for this call, for\n"
|
||||
"example: numeric-passcode|context|\"My Phone\" <(234) 123-4567> or \n"
|
||||
"full-pathname-of-passcode-file|\"My Phone\" <(234) 123-4567>. Note that\n"
|
||||
"full-pathname-of-passcode-file|\"My Phone\" <(234) 123-4567>. Last\n"
|
||||
"but not least, |mailbox[@context] may be appended, which will cause\n"
|
||||
"a stutter-dialtone (indication \"dialrecall\") to be used, if the\n"
|
||||
"specified mailbox contains any new messages, for example:\n"
|
||||
"numeric-passcode|context||1234 (w/a changing callerid). Note that\n"
|
||||
"in the case of specifying the numeric-passcode, the context must be\n"
|
||||
"specified if the callerid is specified also.\n\n"
|
||||
"If login is successful, the application parses the dialed number in\n"
|
||||
"the specified (or default) context, and returns 0 with the new extension\n"
|
||||
"context filled-in and the priority set to 1, so that the PBX may\n"
|
||||
"re-apply the routing tables to it and complete the call normally.";
|
||||
|
||||
"If login is successful, the application looks up the dialed number in\n"
|
||||
"the specified (or default) context, and executes it if found.\n"
|
||||
"If the user enters an invalid extension and extension \"i\" (invalid) \n"
|
||||
"exists in the context, it will be used.\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static float loudness=4096.0;
|
||||
|
||||
static int firstdigittimeout = 20000; /* 20 seconds first digit timeout */
|
||||
static int digittimeout = 10000; /* 10 seconds subsequent digit timeout */
|
||||
|
||||
static void make_tone_block(unsigned char *data, float f1, float f2, int len, int *x)
|
||||
static void play_dialtone(struct ast_channel *chan, char *mailbox)
|
||||
{
|
||||
int i;
|
||||
float val;
|
||||
|
||||
for(i = 0; i < len; i++)
|
||||
{
|
||||
val = loudness * sin((f1 * 2.0 * M_PI * (*x))/8000.0);
|
||||
val += loudness * sin((f2 * 2.0 * M_PI * (*x)++)/8000.0);
|
||||
data[i] = AST_LIN2MU((int)val);
|
||||
}
|
||||
/* wrap back around from 8000 */
|
||||
if (*x >= 8000) *x = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
static int ms_diff(struct timeval *tv1, struct timeval *tv2)
|
||||
{
|
||||
int ms;
|
||||
|
||||
ms = (tv1->tv_sec - tv2->tv_sec) * 1000;
|
||||
ms += (tv1->tv_usec - tv2->tv_usec) / 1000;
|
||||
return(ms);
|
||||
const struct tone_zone_sound *ts = NULL;
|
||||
if(ast_app_has_voicemail(mailbox, NULL))
|
||||
ts = ast_get_indication_tone(chan->zone, "dialrecall");
|
||||
else
|
||||
ts = ast_get_indication_tone(chan->zone, "dial");
|
||||
if (ts)
|
||||
ast_playtones_start(chan, 0, ts->data, 0);
|
||||
else
|
||||
ast_tonepair_start(chan, 350, 440, 0, 0);
|
||||
}
|
||||
|
||||
static int disa_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int i,j,k,x;
|
||||
int i,j,k,x,did_ignore;
|
||||
int firstdigittimeout = 20000;
|
||||
int digittimeout = 10000;
|
||||
struct localuser *u;
|
||||
char tmp[256],arg2[256],exten[AST_MAX_EXTENSION],acctcode[20];
|
||||
struct {
|
||||
unsigned char offset[AST_FRIENDLY_OFFSET];
|
||||
unsigned char buf[640];
|
||||
} tone_block;
|
||||
char *ourcontext,*ourcallerid;
|
||||
struct ast_frame *f,wf;
|
||||
struct timeval lastout, now, lastdigittime;
|
||||
char *tmp, exten[AST_MAX_EXTENSION],acctcode[20]="";
|
||||
char pwline[256];
|
||||
char ourcidname[256],ourcidnum[256];
|
||||
struct ast_frame *f;
|
||||
struct timeval lastdigittime;
|
||||
int res;
|
||||
time_t rstart;
|
||||
FILE *fp;
|
||||
char *stringp=NULL;
|
||||
AST_DECLARE_APP_ARGS(args,
|
||||
AST_APP_ARG(passcode);
|
||||
AST_APP_ARG(context);
|
||||
AST_APP_ARG(cid);
|
||||
AST_APP_ARG(mailbox);
|
||||
);
|
||||
|
||||
if (ast_set_write_format(chan,AST_FORMAT_ULAW))
|
||||
{
|
||||
ast_log(LOG_WARNING, "Unable to set write format to Mu-law on %s\n",chan->name);
|
||||
return -1;
|
||||
}
|
||||
if (ast_set_read_format(chan,AST_FORMAT_ULAW))
|
||||
{
|
||||
ast_log(LOG_WARNING, "Unable to set read format to Mu-law on %s\n",chan->name);
|
||||
return -1;
|
||||
}
|
||||
lastout.tv_sec = lastout.tv_usec = 0;
|
||||
if (!data || !strlen((char *)data)) {
|
||||
if (ast_strlen_zero(data)) {
|
||||
ast_log(LOG_WARNING, "disa requires an argument (passcode/passcode file)\n");
|
||||
return -1;
|
||||
}
|
||||
strncpy(tmp, (char *)data, sizeof(tmp)-1);
|
||||
stringp=tmp;
|
||||
strsep(&stringp, "|");
|
||||
ourcontext = strsep(&stringp, "|");
|
||||
/* if context specified, save 2nd arg and parse third */
|
||||
if (ourcontext) {
|
||||
strcpy(arg2,ourcontext);
|
||||
ourcallerid = strsep(&stringp,"|");
|
||||
}
|
||||
/* if context not specified, use "disa" */
|
||||
else {
|
||||
arg2[0] = 0;
|
||||
ourcallerid = NULL;
|
||||
ourcontext = "disa";
|
||||
}
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
if (chan->_state != AST_STATE_UP)
|
||||
{
|
||||
|
||||
if (chan->pbx) {
|
||||
firstdigittimeout = chan->pbx->rtimeout*1000;
|
||||
digittimeout = chan->pbx->dtimeout*1000;
|
||||
}
|
||||
|
||||
if (ast_set_write_format(chan,AST_FORMAT_ULAW)) {
|
||||
ast_log(LOG_WARNING, "Unable to set write format to Mu-law on %s\n",chan->name);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
if (ast_set_read_format(chan,AST_FORMAT_ULAW)) {
|
||||
ast_log(LOG_WARNING, "Unable to set read format to Mu-law on %s\n",chan->name);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ast_log(LOG_DEBUG, "Digittimeout: %d\n", digittimeout);
|
||||
ast_log(LOG_DEBUG, "Responsetimeout: %d\n", firstdigittimeout);
|
||||
|
||||
tmp = ast_strdupa(data);
|
||||
if (!tmp) {
|
||||
ast_log(LOG_ERROR, "Out of memory\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
AST_STANDARD_APP_ARGS(args, tmp);
|
||||
|
||||
if (ast_strlen_zero(args.context))
|
||||
args.context = "disa";
|
||||
if (ast_strlen_zero(args.mailbox))
|
||||
args.mailbox = "";
|
||||
|
||||
ast_log(LOG_DEBUG, "Mailbox: %s\n",args.mailbox);
|
||||
|
||||
if (chan->_state != AST_STATE_UP) {
|
||||
/* answer */
|
||||
ast_answer(chan);
|
||||
}
|
||||
i = k = x = 0; /* k is 0 for pswd entry, 1 for ext entry */
|
||||
did_ignore = 0;
|
||||
exten[0] = 0;
|
||||
acctcode[0] = 0;
|
||||
/* can we access DISA without password? */
|
||||
if (!strcasecmp(tmp, "no-password"))
|
||||
{;
|
||||
k = 1;
|
||||
|
||||
ast_log(LOG_DEBUG, "Context: %s\n",args.context);
|
||||
|
||||
if (!strcasecmp(args.passcode, "no-password")) {
|
||||
k |= 1; /* We have the password */
|
||||
ast_log(LOG_DEBUG, "DISA no-password login success\n");
|
||||
}
|
||||
gettimeofday(&lastdigittime,NULL);
|
||||
for(;;)
|
||||
{
|
||||
gettimeofday(&now,NULL);
|
||||
lastdigittime = ast_tvnow();
|
||||
|
||||
play_dialtone(chan, args.mailbox);
|
||||
|
||||
for (;;) {
|
||||
/* if outa time, give em reorder */
|
||||
if (ms_diff(&now,&lastdigittime) >
|
||||
((k) ? digittimeout : firstdigittimeout))
|
||||
if (ast_tvdiff_ms(ast_tvnow(), lastdigittime) >
|
||||
((k&2) ? digittimeout : firstdigittimeout))
|
||||
{
|
||||
ast_log(LOG_DEBUG,"DISA %s entry timeout on chan %s\n",
|
||||
((k) ? "extension" : "password"),chan->name);
|
||||
((k&1) ? "extension" : "password"),chan->name);
|
||||
break;
|
||||
}
|
||||
if ((res = ast_waitfor(chan, -1) < 0)) {
|
||||
@@ -205,24 +223,7 @@ static int disa_exec(struct ast_channel *chan, void *data)
|
||||
return -1;
|
||||
}
|
||||
if (f->frametype == AST_FRAME_VOICE) {
|
||||
if (!i || (ast_ignore_pattern(ourcontext, exten) && k)) {
|
||||
wf.frametype = AST_FRAME_VOICE;
|
||||
wf.subclass = AST_FORMAT_ULAW;
|
||||
wf.offset = AST_FRIENDLY_OFFSET;
|
||||
wf.mallocd = 0;
|
||||
wf.data = tone_block.buf;
|
||||
wf.datalen = f->datalen;
|
||||
make_tone_block(tone_block.buf, 350, 440, f->datalen, &x);
|
||||
wf.samples = wf.datalen;
|
||||
ast_frfree(f);
|
||||
if (ast_write(chan, &wf))
|
||||
{
|
||||
ast_log(LOG_WARNING, "DISA Failed to write frame on %s\n",chan->name);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
} else
|
||||
ast_frfree(f);
|
||||
ast_frfree(f);
|
||||
continue;
|
||||
}
|
||||
/* if not DTMF, just do it again */
|
||||
@@ -234,144 +235,158 @@ static int disa_exec(struct ast_channel *chan, void *data)
|
||||
|
||||
j = f->subclass; /* save digit */
|
||||
ast_frfree(f);
|
||||
|
||||
gettimeofday(&lastdigittime,NULL);
|
||||
if (i == 0)
|
||||
{
|
||||
k|=2; /* We have the first digit */
|
||||
ast_playtones_stop(chan);
|
||||
}
|
||||
lastdigittime = ast_tvnow();
|
||||
/* got a DTMF tone */
|
||||
if (i < AST_MAX_EXTENSION) /* if still valid number of digits */
|
||||
{
|
||||
if (!k) /* if in password state */
|
||||
if (!(k&1)) /* if in password state */
|
||||
{
|
||||
if (j == '#') /* end of password */
|
||||
{
|
||||
/* see if this is an integer */
|
||||
if (sscanf(tmp,"%d",&j) < 1)
|
||||
if (sscanf(args.passcode,"%d",&j) < 1)
|
||||
{ /* nope, it must be a filename */
|
||||
fp = fopen(tmp,"r");
|
||||
fp = fopen(args.passcode,"r");
|
||||
if (!fp)
|
||||
{
|
||||
ast_log(LOG_WARNING,"DISA password file %s not found on chan %s\n",tmp,chan->name);
|
||||
ast_log(LOG_WARNING,"DISA password file %s not found on chan %s\n",args.passcode,chan->name);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
tmp[0] = 0;
|
||||
while(fgets(tmp,sizeof(tmp) - 1,fp))
|
||||
pwline[0] = 0;
|
||||
while(fgets(pwline,sizeof(pwline) - 1,fp))
|
||||
{
|
||||
char *stringp=NULL,*stringp2;
|
||||
if (!tmp[0]) continue;
|
||||
if (tmp[strlen(tmp) - 1] == '\n')
|
||||
tmp[strlen(tmp) - 1] = 0;
|
||||
if (!tmp[0]) continue;
|
||||
if (!pwline[0]) continue;
|
||||
if (pwline[strlen(pwline) - 1] == '\n')
|
||||
pwline[strlen(pwline) - 1] = 0;
|
||||
if (!pwline[0]) continue;
|
||||
/* skip comments */
|
||||
if (tmp[0] == '#') continue;
|
||||
if (tmp[0] == ';') continue;
|
||||
stringp=tmp;
|
||||
strsep(&stringp, "|");
|
||||
stringp2=strsep(&stringp, "|");
|
||||
if (stringp2) {
|
||||
ourcontext=stringp2;
|
||||
stringp2=strsep(&stringp, "|");
|
||||
if (stringp2) ourcallerid=stringp2;
|
||||
}
|
||||
if (pwline[0] == '#') continue;
|
||||
if (pwline[0] == ';') continue;
|
||||
|
||||
AST_STANDARD_APP_ARGS(args, pwline);
|
||||
|
||||
ast_log(LOG_DEBUG, "Mailbox: %s\n",args.mailbox);
|
||||
|
||||
/* password must be in valid format (numeric) */
|
||||
if (sscanf(tmp,"%d",&j) < 1) continue;
|
||||
if (sscanf(args.passcode,"%d",&j) < 1) continue;
|
||||
/* if we got it */
|
||||
if (!strcmp(exten,tmp)) break;
|
||||
if (!strcmp(exten,args.passcode)) {
|
||||
if (ast_strlen_zero(args.context))
|
||||
args.context = "disa";
|
||||
if (ast_strlen_zero(args.mailbox))
|
||||
args.mailbox = "";
|
||||
break;
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
/* compare the two */
|
||||
if (strcmp(exten,tmp))
|
||||
if (strcmp(exten,args.passcode))
|
||||
{
|
||||
ast_log(LOG_WARNING,"DISA on chan %s got bad password %s\n",chan->name,exten);
|
||||
goto reorder;
|
||||
|
||||
}
|
||||
/* password good, set to dial state */
|
||||
ast_log(LOG_WARNING,"DISA on chan %s password is good\n",chan->name);
|
||||
k = 1;
|
||||
ast_log(LOG_DEBUG,"DISA on chan %s password is good\n",chan->name);
|
||||
play_dialtone(chan, args.mailbox);
|
||||
|
||||
k|=1; /* In number mode */
|
||||
i = 0; /* re-set buffer pointer */
|
||||
exten[sizeof(acctcode)] = 0;
|
||||
strcpy(acctcode,exten);
|
||||
ast_copy_string(acctcode, exten, sizeof(acctcode));
|
||||
exten[0] = 0;
|
||||
ast_log(LOG_DEBUG,"Successful DISA log-in on chan %s\n",chan->name);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
exten[i++] = j; /* save digit */
|
||||
exten[i] = 0;
|
||||
if (!k) continue; /* if getting password, continue doing it */
|
||||
if (!(k&1)) continue; /* if getting password, continue doing it */
|
||||
/* if this exists */
|
||||
|
||||
if (ast_ignore_pattern(args.context, exten)) {
|
||||
play_dialtone(chan, "");
|
||||
did_ignore = 1;
|
||||
} else
|
||||
if (did_ignore) {
|
||||
ast_playtones_stop(chan);
|
||||
did_ignore = 0;
|
||||
}
|
||||
|
||||
/* if can do some more, do it */
|
||||
if (!ast_matchmore_extension(chan,ourcontext,exten,1, chan->callerid))
|
||||
if (!ast_matchmore_extension(chan,args.context,exten,1, chan->cid.cid_num)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (k && ast_exists_extension(chan,ourcontext,exten,1, chan->callerid))
|
||||
{
|
||||
/* We're authenticated and have a valid extension */
|
||||
if (ourcallerid && *ourcallerid)
|
||||
{
|
||||
if (chan->callerid) free(chan->callerid);
|
||||
chan->callerid = strdup(ourcallerid);
|
||||
if (k == 3) {
|
||||
int recheck = 0;
|
||||
struct ast_flags flags = { AST_CDR_FLAG_POSTED };
|
||||
|
||||
if (!ast_exists_extension(chan, args.context, exten, 1, chan->cid.cid_num)) {
|
||||
pbx_builtin_setvar_helper(chan, "INVALID_EXTEN", exten);
|
||||
exten[0] = 'i';
|
||||
exten[1] = '\0';
|
||||
recheck = 1;
|
||||
}
|
||||
if (!recheck || ast_exists_extension(chan, args.context, exten, 1, chan->cid.cid_num)) {
|
||||
ast_playtones_stop(chan);
|
||||
/* We're authenticated and have a target extension */
|
||||
if (!ast_strlen_zero(args.cid))
|
||||
{
|
||||
ast_callerid_split(args.cid, ourcidname, sizeof(ourcidname), ourcidnum, sizeof(ourcidnum));
|
||||
ast_set_callerid(chan, ourcidnum, ourcidname, ourcidnum);
|
||||
}
|
||||
|
||||
if (!ast_strlen_zero(acctcode))
|
||||
ast_copy_string(chan->accountcode, acctcode, sizeof(chan->accountcode));
|
||||
|
||||
ast_cdr_reset(chan->cdr, &flags);
|
||||
ast_explicit_goto(chan, args.context, exten, 1);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return 0;
|
||||
}
|
||||
strcpy(chan->exten,exten);
|
||||
strcpy(chan->context,ourcontext);
|
||||
strcpy(chan->accountcode,acctcode);
|
||||
chan->priority = 0;
|
||||
ast_cdr_init(chan->cdr,chan);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Received invalid, but no "i" extension exists in the given context */
|
||||
|
||||
reorder:
|
||||
|
||||
/* something is invalid, give em reorder forever */
|
||||
x = 0;
|
||||
k = 0; /* k = 0 means busy tone, k = 1 means silence) */
|
||||
i = 0; /* Number of samples we've done */
|
||||
for(;;)
|
||||
|
||||
ast_indicate(chan,AST_CONTROL_CONGESTION);
|
||||
/* something is invalid, give em reorder for several seconds */
|
||||
time(&rstart);
|
||||
while(time(NULL) < rstart + 10)
|
||||
{
|
||||
if (ast_waitfor(chan, -1) < 0)
|
||||
break;
|
||||
f = ast_read(chan);
|
||||
if (!f)
|
||||
break;
|
||||
if (f->frametype == AST_FRAME_VOICE) {
|
||||
wf.frametype = AST_FRAME_VOICE;
|
||||
wf.subclass = AST_FORMAT_ULAW;
|
||||
wf.offset = AST_FRIENDLY_OFFSET;
|
||||
wf.mallocd = 0;
|
||||
wf.data = tone_block.buf;
|
||||
wf.datalen = f->datalen;
|
||||
wf.samples = wf.datalen;
|
||||
if (k)
|
||||
memset(tone_block.buf, 0x7f, wf.datalen);
|
||||
else
|
||||
make_tone_block(tone_block.buf,480.0, 620.0,wf.datalen, &x);
|
||||
i += wf.datalen / 8;
|
||||
if (i > 250) {
|
||||
i = 0;
|
||||
k = !k;
|
||||
}
|
||||
if (ast_write(chan, &wf))
|
||||
{
|
||||
ast_log(LOG_WARNING, "DISA Failed to write frame on %s\n",chan->name);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
ast_frfree(f);
|
||||
}
|
||||
ast_playtones_stop(chan);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app);
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
|
||||
192
apps/app_dumpchan.c
Normal file
192
apps/app_dumpchan.c
Normal file
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Copyright (C) 2004 - 2005, Anthony Minessale II.
|
||||
*
|
||||
* Anthony Minessale <anthmct@yahoo.com>
|
||||
*
|
||||
* disclaimed to Digium
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief Application to dump channel variables
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/options.h"
|
||||
#include "asterisk/utils.h"
|
||||
#include "asterisk/lock.h"
|
||||
#include "asterisk/utils.h"
|
||||
|
||||
static char *tdesc = "Dump Info About The Calling Channel";
|
||||
static char *app = "DumpChan";
|
||||
static char *synopsis = "Dump Info About The Calling Channel";
|
||||
static char *desc =
|
||||
" DumpChan([<min_verbose_level>])\n"
|
||||
"Displays information on channel and listing of all channel\n"
|
||||
"variables. If min_verbose_level is specified, output is only\n"
|
||||
"displayed when the verbose level is currently set to that number\n"
|
||||
"or greater. \n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int ast_serialize_showchan(struct ast_channel *c, char *buf, size_t size)
|
||||
{
|
||||
struct timeval now;
|
||||
long elapsed_seconds=0;
|
||||
int hour=0, min=0, sec=0;
|
||||
char cgrp[256];
|
||||
char pgrp[256];
|
||||
|
||||
now = ast_tvnow();
|
||||
memset(buf,0,size);
|
||||
if (!c)
|
||||
return 0;
|
||||
|
||||
if (c->cdr) {
|
||||
elapsed_seconds = now.tv_sec - c->cdr->start.tv_sec;
|
||||
hour = elapsed_seconds / 3600;
|
||||
min = (elapsed_seconds % 3600) / 60;
|
||||
sec = elapsed_seconds % 60;
|
||||
}
|
||||
|
||||
snprintf(buf,size,
|
||||
"Name= %s\n"
|
||||
"Type= %s\n"
|
||||
"UniqueID= %s\n"
|
||||
"CallerID= %s\n"
|
||||
"CallerIDName= %s\n"
|
||||
"DNIDDigits= %s\n"
|
||||
"State= %s (%d)\n"
|
||||
"Rings= %d\n"
|
||||
"NativeFormat= %d\n"
|
||||
"WriteFormat= %d\n"
|
||||
"ReadFormat= %d\n"
|
||||
"1stFileDescriptor= %d\n"
|
||||
"Framesin= %d %s\n"
|
||||
"Framesout= %d %s\n"
|
||||
"TimetoHangup= %ld\n"
|
||||
"ElapsedTime= %dh%dm%ds\n"
|
||||
"Context= %s\n"
|
||||
"Extension= %s\n"
|
||||
"Priority= %d\n"
|
||||
"CallGroup= %s\n"
|
||||
"PickupGroup= %s\n"
|
||||
"Application= %s\n"
|
||||
"Data= %s\n"
|
||||
"Blocking_in= %s\n",
|
||||
c->name,
|
||||
c->type,
|
||||
c->uniqueid,
|
||||
(c->cid.cid_num ? c->cid.cid_num : "(N/A)"),
|
||||
(c->cid.cid_name ? c->cid.cid_name : "(N/A)"),
|
||||
(c->cid.cid_dnid ? c->cid.cid_dnid : "(N/A)" ),
|
||||
ast_state2str(c->_state),
|
||||
c->_state,
|
||||
c->rings,
|
||||
c->nativeformats,
|
||||
c->writeformat,
|
||||
c->readformat,
|
||||
c->fds[0], c->fin & 0x7fffffff, (c->fin & 0x80000000) ? " (DEBUGGED)" : "",
|
||||
c->fout & 0x7fffffff, (c->fout & 0x80000000) ? " (DEBUGGED)" : "", (long)c->whentohangup,
|
||||
hour,
|
||||
min,
|
||||
sec,
|
||||
c->context,
|
||||
c->exten,
|
||||
c->priority,
|
||||
ast_print_group(cgrp, sizeof(cgrp), c->callgroup),
|
||||
ast_print_group(pgrp, sizeof(pgrp), c->pickupgroup),
|
||||
( c->appl ? c->appl : "(N/A)" ),
|
||||
( c-> data ? (!ast_strlen_zero(c->data) ? c->data : "(Empty)") : "(None)"),
|
||||
(ast_test_flag(c, AST_FLAG_BLOCKING) ? c->blockproc : "(Not Blocking)"));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dumpchan_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0;
|
||||
struct localuser *u;
|
||||
char vars[1024];
|
||||
char info[1024];
|
||||
int level = 0;
|
||||
static char *line = "================================================================================";
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
if (!ast_strlen_zero(data)) {
|
||||
level = atoi(data);
|
||||
}
|
||||
|
||||
pbx_builtin_serialize_variables(chan, vars, sizeof(vars));
|
||||
ast_serialize_showchan(chan, info, sizeof(info));
|
||||
if (option_verbose >= level)
|
||||
ast_verbose("\nDumping Info For Channel: %s:\n%s\nInfo:\n%s\nVariables:\n%s%s\n",chan->name, line, info, vars, line);
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app);
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(app, dumpchan_exec, synopsis, desc);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
|
||||
56
apps/app_echo.c
Executable file → Normal file
56
apps/app_echo.c
Executable file → Normal file
@@ -1,29 +1,43 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Echo application -- play back what you hear to evaluate latency
|
||||
*
|
||||
* Copyright (C) 1999, Mark Spencer
|
||||
* Copyright (C) 1999 - 2005, Digium, Inc.
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
* Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief Echo application -- play back what you hear to evaluate latency
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <pthread.h>
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/lock.h"
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/module.h"
|
||||
|
||||
static char *tdesc = "Simple Echo Application";
|
||||
|
||||
@@ -32,8 +46,9 @@ static char *app = "Echo";
|
||||
static char *synopsis = "Echo audio read back to the user";
|
||||
|
||||
static char *descrip =
|
||||
" Echo(): Echo audio read from channel back to the channel. Returns 0\n"
|
||||
"if the user exits with the '#' key, or -1 if the user hangs up.\n";
|
||||
" Echo(): Echo audio read from channel back to the channel. \n"
|
||||
"User can exit the application by either pressing the '#' key, \n"
|
||||
"or hanging up.\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
@@ -52,6 +67,8 @@ static int echo_exec(struct ast_channel *chan, void *data)
|
||||
f = ast_read(chan);
|
||||
if (!f)
|
||||
break;
|
||||
f->delivery.tv_sec = 0;
|
||||
f->delivery.tv_usec = 0;
|
||||
if (f->frametype == AST_FRAME_VOICE) {
|
||||
if (ast_write(chan, f))
|
||||
break;
|
||||
@@ -74,8 +91,13 @@ static int echo_exec(struct ast_channel *chan, void *data)
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app);
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
|
||||
187
apps/app_enumlookup.c
Executable file → Normal file
187
apps/app_enumlookup.c
Executable file → Normal file
@@ -1,33 +1,50 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Time of day - Report the time of day
|
||||
*
|
||||
* Copyright (C) 1999, Mark Spencer
|
||||
* Copyright (C) 1999 - 2005, Digium, Inc.
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
* Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief Enumlookup - lookup entry in ENUM
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/options.h>
|
||||
#include <asterisk/config.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/enum.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <pthread.h>
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/lock.h"
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/options.h"
|
||||
#include "asterisk/config.h"
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/enum.h"
|
||||
#include "asterisk/utils.h"
|
||||
#include "asterisk/app.h"
|
||||
#include "asterisk/options.h"
|
||||
|
||||
static char *tdesc = "ENUM Lookup";
|
||||
|
||||
@@ -35,45 +52,85 @@ static char *app = "EnumLookup";
|
||||
|
||||
static char *synopsis = "Lookup number in ENUM";
|
||||
|
||||
static char *descrip =
|
||||
" EnumLookup(exten): Looks up an extension via ENUM and sets\n"
|
||||
static char *descrip =
|
||||
" EnumLookup(exten[|option]): Looks up an extension via ENUM and sets\n"
|
||||
"the variable 'ENUM'. For VoIP URIs this variable will \n"
|
||||
"look like 'TECHNOLOGY/URI' with the appropriate technology.\n"
|
||||
"Returns -1 on hangup, or 0 on completion regardless of whether the \n"
|
||||
"lookup was successful. \n"
|
||||
"Currently, the enumservices SIP, H323, IAX, IAX2 and TEL are recognized. \n"
|
||||
"A good SIP, H323, IAX or IAX2 entry will result in normal priority handling, \n"
|
||||
"whereas a good TEL entry will increase the priority by 51 (if existing).\n"
|
||||
"If the lookup was *not* successful and there exists a priority n + 101,\n"
|
||||
"then that priority will be taken next.\n" ;
|
||||
"\nReturns status in the ENUMSTATUS channel variable:\n"
|
||||
" ERROR Failed to do a lookup\n"
|
||||
" <tech> Technology of the successful lookup: SIP, H323, IAX, IAX2 or TEL\n"
|
||||
" BADURI Got URI Asterisk does not understand.\n"
|
||||
" The option string may contain zero or the following character:\n"
|
||||
" 'j' -- jump to +101 priority if the lookup isn't successful.\n"
|
||||
" and jump to +51 priority on a TEL entry.\n";
|
||||
|
||||
#define ENUM_CONFIG "enum.conf"
|
||||
|
||||
static char h323driver[80];
|
||||
static char h323driver[80] = "";
|
||||
#define H323DRIVERDEFAULT "H323"
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
/*--- enumlookup_exec: Look up number in ENUM and return result */
|
||||
static int enumlookup_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0;
|
||||
int res=0,priority_jump=0;
|
||||
char tech[80];
|
||||
char dest[80];
|
||||
char tmp[256];
|
||||
char *c,*t;
|
||||
char *c,*t = NULL;
|
||||
static int dep_warning=0;
|
||||
struct localuser *u;
|
||||
if (!data || !strlen(data)) {
|
||||
char *parse;
|
||||
AST_DECLARE_APP_ARGS(args,
|
||||
AST_APP_ARG(d);
|
||||
AST_APP_ARG(o);
|
||||
);
|
||||
|
||||
if (ast_strlen_zero(data)) {
|
||||
ast_log(LOG_WARNING, "EnumLookup requires an argument (extension)\n");
|
||||
res = 1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!dep_warning) {
|
||||
ast_log(LOG_WARNING, "The application EnumLookup is deprecated. Please use the ENUMLOOKUP() function instead.\n");
|
||||
dep_warning = 1;
|
||||
}
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
if (!res) {
|
||||
res = ast_get_enum(chan, data, dest, sizeof(dest), tech, sizeof(tech));
|
||||
printf("ENUM got '%d'\n", res);
|
||||
|
||||
parse = ast_strdupa(data);
|
||||
if (!parse) {
|
||||
ast_log(LOG_ERROR, "Out of memory!\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
AST_STANDARD_APP_ARGS(args, parse);
|
||||
|
||||
tech[0] = '\0';
|
||||
dest[0] = '\0';
|
||||
|
||||
if (args.o) {
|
||||
if (strchr(args.o, 'j'))
|
||||
priority_jump = 1;
|
||||
}
|
||||
|
||||
res = ast_get_enum(chan, args.d, dest, sizeof(dest), tech, sizeof(tech), NULL, NULL);
|
||||
|
||||
if (!res) { /* Failed to do a lookup */
|
||||
if (priority_jump || option_priority_jumping) {
|
||||
/* Look for a "busy" place */
|
||||
ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
|
||||
}
|
||||
pbx_builtin_setvar_helper(chan, "ENUMSTATUS", "ERROR");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return 0;
|
||||
}
|
||||
pbx_builtin_setvar_helper(chan, "ENUMSTATUS", tech);
|
||||
/* Parse it out */
|
||||
if (res > 0) {
|
||||
if (!strcasecmp(tech, "SIP")) {
|
||||
@@ -89,7 +146,7 @@ static int enumlookup_exec(struct ast_channel *chan, void *data)
|
||||
snprintf(tmp, sizeof(tmp), "%s/%s", h323driver, c);
|
||||
/* do a s!;.*!! on the H323 URI */
|
||||
t = strchr(c,';');
|
||||
if (t)
|
||||
if (t)
|
||||
*t = 0;
|
||||
pbx_builtin_setvar_helper(chan, "ENUM", tmp);
|
||||
} else if (!strcasecmp(tech, "iax")) {
|
||||
@@ -114,7 +171,7 @@ static int enumlookup_exec(struct ast_channel *chan, void *data)
|
||||
res = 0;
|
||||
} else {
|
||||
/* now copy over the number, skipping all non-digits and stop at ; or NULL */
|
||||
t = tmp;
|
||||
t = tmp;
|
||||
while( *c && (*c != ';') && (t - tmp < (sizeof(tmp) - 1))) {
|
||||
if (isdigit(*c))
|
||||
*t++ = *c;
|
||||
@@ -123,38 +180,37 @@ static int enumlookup_exec(struct ast_channel *chan, void *data)
|
||||
*t = 0;
|
||||
pbx_builtin_setvar_helper(chan, "ENUM", tmp);
|
||||
ast_log(LOG_NOTICE, "tel: ENUM set to \"%s\"\n", tmp);
|
||||
if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 51, chan->callerid))
|
||||
chan->priority += 50;
|
||||
else
|
||||
res = 0;
|
||||
if (priority_jump || option_priority_jumping) {
|
||||
if (ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 51))
|
||||
res = 0;
|
||||
}
|
||||
}
|
||||
} else if (strlen(tech)) {
|
||||
} else if (!ast_strlen_zero(tech)) {
|
||||
ast_log(LOG_NOTICE, "Don't know how to handle technology '%s'\n", tech);
|
||||
pbx_builtin_setvar_helper(chan, "ENUMSTATUS", "BADURI");
|
||||
res = 0;
|
||||
}
|
||||
}
|
||||
if (!res) {
|
||||
/* Look for a "busy" place */
|
||||
if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->callerid))
|
||||
chan->priority += 100;
|
||||
} else if (res > 0)
|
||||
res = 0;
|
||||
return res;
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*--- load_config: Load enum.conf and find out how to handle H.323 */
|
||||
static int load_config(void)
|
||||
{
|
||||
struct ast_config *cfg;
|
||||
char *s;
|
||||
|
||||
cfg = ast_load(ENUM_CONFIG);
|
||||
cfg = ast_config_load(ENUM_CONFIG);
|
||||
if (cfg) {
|
||||
if (!(s=ast_variable_retrieve(cfg, "general", "h323driver"))) {
|
||||
strcpy(h323driver, H323DRIVERDEFAULT);
|
||||
strncpy(h323driver, H323DRIVERDEFAULT, sizeof(h323driver) - 1);
|
||||
} else {
|
||||
strcpy(h323driver, s);
|
||||
strncpy(h323driver, s, sizeof(h323driver) - 1);
|
||||
}
|
||||
ast_destroy(cfg);
|
||||
ast_config_destroy(cfg);
|
||||
return 0;
|
||||
}
|
||||
ast_log(LOG_NOTICE, "No ENUM Config file, using defaults\n");
|
||||
@@ -162,30 +218,39 @@ static int load_config(void)
|
||||
}
|
||||
|
||||
|
||||
/*--- unload_module: Unload this application from PBX */
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app);
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*--- load_module: Load this application into PBX */
|
||||
int load_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_register_application(app, enumlookup_exec, synopsis, descrip);
|
||||
if (res)
|
||||
return(res);
|
||||
if ((res=load_config())) {
|
||||
return(res);
|
||||
}
|
||||
return(0);
|
||||
|
||||
if (!res)
|
||||
res = load_config();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*--- reload: Reload configuration file */
|
||||
int reload(void)
|
||||
{
|
||||
return(load_config());
|
||||
return load_config();
|
||||
}
|
||||
|
||||
|
||||
/*--- description: Describe module */
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
|
||||
127
apps/app_eval.c
Normal file
127
apps/app_eval.c
Normal file
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Copyright (c) 2004 - 2005, Tilghman Lesher. All rights reserved.
|
||||
*
|
||||
* Tilghman Lesher <app_eval__v001@the-tilghman.com>
|
||||
*
|
||||
* This code is released by the author with no restrictions on usage.
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
* \brief Eval application
|
||||
*
|
||||
* \author Tilghman Lesher <app_eval__v001@the-tilghman.com>
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/options.h"
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/module.h"
|
||||
|
||||
/* Maximum length of any variable */
|
||||
#define MAXRESULT 1024
|
||||
|
||||
static char *tdesc = "Reevaluates strings";
|
||||
|
||||
static char *app_eval = "Eval";
|
||||
|
||||
static char *eval_synopsis = "Evaluates a string";
|
||||
|
||||
static char *eval_descrip =
|
||||
"Usage: Eval(newvar=somestring)\n"
|
||||
" Normally Asterisk evaluates variables inline. But what if you want to\n"
|
||||
"store variable offsets in a database, to be evaluated later? Eval is\n"
|
||||
"the answer, by allowing a string to be evaluated twice in the dialplan,\n"
|
||||
"the first time as part of the normal dialplan, and the second using Eval.\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int eval_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0;
|
||||
struct localuser *u;
|
||||
char *s, *newvar=NULL, tmp[MAXRESULT];
|
||||
static int dep_warning = 0;
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
if (!dep_warning) {
|
||||
ast_log(LOG_WARNING, "This application has been deprecated in favor of the dialplan function, EVAL\n");
|
||||
dep_warning = 1;
|
||||
}
|
||||
|
||||
/* Check and parse arguments */
|
||||
if (data) {
|
||||
s = ast_strdupa((char *)data);
|
||||
if (s) {
|
||||
newvar = strsep(&s, "=");
|
||||
if (newvar && (newvar[0] != '\0')) {
|
||||
memset(tmp, 0, MAXRESULT);
|
||||
pbx_substitute_variables_helper(chan, s, tmp, MAXRESULT - 1);
|
||||
pbx_builtin_setvar_helper(chan, newvar, tmp);
|
||||
}
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Out of memory\n");
|
||||
res = -1;
|
||||
}
|
||||
}
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app_eval);
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(app_eval, eval_exec, eval_synopsis, eval_descrip);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
135
apps/app_exec.c
Normal file
135
apps/app_exec.c
Normal file
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Copyright (c) 2004 - 2005, Tilghman Lesher. All rights reserved.
|
||||
*
|
||||
* Tilghman Lesher <app_exec__v001@the-tilghman.com>
|
||||
*
|
||||
* This code is released by the author with no restrictions on usage.
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief Exec application
|
||||
*
|
||||
* \author Tilghman Lesher <app_exec__v001@the-tilghman.com>
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/options.h"
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/module.h"
|
||||
|
||||
/* Maximum length of any variable */
|
||||
#define MAXRESULT 1024
|
||||
|
||||
static char *tdesc = "Executes applications";
|
||||
|
||||
static char *app_exec = "Exec";
|
||||
|
||||
static char *exec_synopsis = "Executes internal application";
|
||||
|
||||
static char *exec_descrip =
|
||||
"Usage: Exec(appname(arguments))\n"
|
||||
" Allows an arbitrary application to be invoked even when not\n"
|
||||
"hardcoded into the dialplan. To invoke external applications\n"
|
||||
"see the application System. Returns whatever value the\n"
|
||||
"app returns or a non-zero value if the app cannot be found.\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int exec_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0;
|
||||
struct localuser *u;
|
||||
char *s, *appname, *endargs, args[MAXRESULT];
|
||||
struct ast_app *app;
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
memset(args, 0, MAXRESULT);
|
||||
|
||||
/* Check and parse arguments */
|
||||
if (data) {
|
||||
s = ast_strdupa((char *)data);
|
||||
if (s) {
|
||||
appname = strsep(&s, "(");
|
||||
if (s) {
|
||||
endargs = strrchr(s, ')');
|
||||
if (endargs)
|
||||
*endargs = '\0';
|
||||
pbx_substitute_variables_helper(chan, s, args, MAXRESULT - 1);
|
||||
}
|
||||
if (appname) {
|
||||
app = pbx_findapp(appname);
|
||||
if (app) {
|
||||
res = pbx_exec(chan, app, args, 1);
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "Could not find application (%s)\n", appname);
|
||||
res = -1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Out of memory\n");
|
||||
res = -1;
|
||||
}
|
||||
}
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app_exec);
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(app_exec, exec_exec, exec_synopsis, exec_descrip);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
583
apps/app_externalivr.c
Normal file
583
apps/app_externalivr.c
Normal file
@@ -0,0 +1,583 @@
|
||||
/*
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Copyright (C) 1999 - 2005, Digium, Inc.
|
||||
*
|
||||
* Kevin P. Fleming <kpfleming@digium.com>
|
||||
*
|
||||
* Portions taken from the file-based music-on-hold work
|
||||
* created by Anthony Minessale II in res_musiconhold.c
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief External IVR application interface
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/lock.h"
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/linkedlists.h"
|
||||
#include "asterisk/app.h"
|
||||
|
||||
static const char *tdesc = "External IVR Interface Application";
|
||||
|
||||
static const char *app = "ExternalIVR";
|
||||
|
||||
static const char *synopsis = "Interfaces with an external IVR application";
|
||||
|
||||
static const char *descrip =
|
||||
" ExternalIVR(command[|arg[|arg...]]): Forks an process to run the supplied command,\n"
|
||||
"and starts a generator on the channel. The generator's play list is\n"
|
||||
"controlled by the external application, which can add and clear entries\n"
|
||||
"via simple commands issued over its stdout. The external application\n"
|
||||
"will receive all DTMF events received on the channel, and notification\n"
|
||||
"if the channel is hung up. The application will not be forcibly terminated\n"
|
||||
"when the channel is hung up.\n"
|
||||
"See doc/README.externalivr for a protocol specification.\n";
|
||||
|
||||
/* XXX the parser in gcc 2.95 gets confused if you don't put a space between 'name' and the comma */
|
||||
#define ast_chan_log(level, channel, format, ...) ast_log(level, "%s: " format, channel->name , ## __VA_ARGS__)
|
||||
|
||||
struct playlist_entry {
|
||||
AST_LIST_ENTRY(playlist_entry) list;
|
||||
char filename[1];
|
||||
};
|
||||
|
||||
struct localuser {
|
||||
struct ast_channel *chan;
|
||||
struct localuser *next;
|
||||
AST_LIST_HEAD(playlist, playlist_entry) playlist;
|
||||
AST_LIST_HEAD(finishlist, playlist_entry) finishlist;
|
||||
int abort_current_sound;
|
||||
int playing_silence;
|
||||
int option_autoclear;
|
||||
};
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
struct gen_state {
|
||||
struct localuser *u;
|
||||
struct ast_filestream *stream;
|
||||
struct playlist_entry *current;
|
||||
int sample_queue;
|
||||
};
|
||||
|
||||
static void send_child_event(FILE *handle, const char event, const char *data,
|
||||
const struct ast_channel *chan)
|
||||
{
|
||||
char tmp[256];
|
||||
|
||||
if (!data) {
|
||||
snprintf(tmp, sizeof(tmp), "%c,%10d", event, (int)time(NULL));
|
||||
} else {
|
||||
snprintf(tmp, sizeof(tmp), "%c,%10d,%s", event, (int)time(NULL), data);
|
||||
}
|
||||
|
||||
fprintf(handle, "%s\n", tmp);
|
||||
ast_chan_log(LOG_DEBUG, chan, "sent '%s'\n", tmp);
|
||||
}
|
||||
|
||||
static void *gen_alloc(struct ast_channel *chan, void *params)
|
||||
{
|
||||
struct localuser *u = params;
|
||||
struct gen_state *state;
|
||||
|
||||
state = calloc(1, sizeof(*state));
|
||||
|
||||
if (!state)
|
||||
return NULL;
|
||||
|
||||
state->u = u;
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
static void gen_closestream(struct gen_state *state)
|
||||
{
|
||||
if (!state->stream)
|
||||
return;
|
||||
|
||||
ast_closestream(state->stream);
|
||||
state->u->chan->stream = NULL;
|
||||
state->stream = NULL;
|
||||
}
|
||||
|
||||
static void gen_release(struct ast_channel *chan, void *data)
|
||||
{
|
||||
struct gen_state *state = data;
|
||||
|
||||
gen_closestream(state);
|
||||
free(data);
|
||||
}
|
||||
|
||||
/* caller has the playlist locked */
|
||||
static int gen_nextfile(struct gen_state *state)
|
||||
{
|
||||
struct localuser *u = state->u;
|
||||
char *file_to_stream;
|
||||
|
||||
u->abort_current_sound = 0;
|
||||
u->playing_silence = 0;
|
||||
gen_closestream(state);
|
||||
|
||||
while (!state->stream) {
|
||||
state->current = AST_LIST_REMOVE_HEAD(&u->playlist, list);
|
||||
if (state->current) {
|
||||
file_to_stream = state->current->filename;
|
||||
} else {
|
||||
file_to_stream = "silence-10";
|
||||
u->playing_silence = 1;
|
||||
}
|
||||
|
||||
if (!(state->stream = ast_openstream_full(u->chan, file_to_stream, u->chan->language, 1))) {
|
||||
ast_chan_log(LOG_WARNING, u->chan, "File '%s' could not be opened: %s\n", file_to_stream, strerror(errno));
|
||||
if (!u->playing_silence) {
|
||||
continue;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (!state->stream);
|
||||
}
|
||||
|
||||
static struct ast_frame *gen_readframe(struct gen_state *state)
|
||||
{
|
||||
struct ast_frame *f = NULL;
|
||||
struct localuser *u = state->u;
|
||||
|
||||
if (u->abort_current_sound ||
|
||||
(u->playing_silence && AST_LIST_FIRST(&u->playlist))) {
|
||||
gen_closestream(state);
|
||||
AST_LIST_LOCK(&u->playlist);
|
||||
gen_nextfile(state);
|
||||
AST_LIST_UNLOCK(&u->playlist);
|
||||
}
|
||||
|
||||
if (!(state->stream && (f = ast_readframe(state->stream)))) {
|
||||
if (state->current) {
|
||||
AST_LIST_LOCK(&u->finishlist);
|
||||
AST_LIST_INSERT_TAIL(&u->finishlist, state->current, list);
|
||||
AST_LIST_UNLOCK(&u->finishlist);
|
||||
state->current = NULL;
|
||||
}
|
||||
if (!gen_nextfile(state))
|
||||
f = ast_readframe(state->stream);
|
||||
}
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
static int gen_generate(struct ast_channel *chan, void *data, int len, int samples)
|
||||
{
|
||||
struct gen_state *state = data;
|
||||
struct ast_frame *f = NULL;
|
||||
int res = 0;
|
||||
|
||||
state->sample_queue += samples;
|
||||
|
||||
while (state->sample_queue > 0) {
|
||||
if (!(f = gen_readframe(state)))
|
||||
return -1;
|
||||
|
||||
res = ast_write(chan, f);
|
||||
ast_frfree(f);
|
||||
if (res < 0) {
|
||||
ast_chan_log(LOG_WARNING, chan, "Failed to write frame: %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
state->sample_queue -= f->samples;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static struct ast_generator gen =
|
||||
{
|
||||
alloc: gen_alloc,
|
||||
release: gen_release,
|
||||
generate: gen_generate,
|
||||
};
|
||||
|
||||
static struct playlist_entry *make_entry(const char *filename)
|
||||
{
|
||||
struct playlist_entry *entry;
|
||||
|
||||
entry = calloc(1, sizeof(*entry) + strlen(filename) + 10);
|
||||
|
||||
if (!entry)
|
||||
return NULL;
|
||||
|
||||
strcpy(entry->filename, filename);
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
static int app_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
struct localuser *u = NULL;
|
||||
struct playlist_entry *entry;
|
||||
const char *args = data;
|
||||
int child_stdin[2] = { 0,0 };
|
||||
int child_stdout[2] = { 0,0 };
|
||||
int child_stderr[2] = { 0,0 };
|
||||
int res = -1;
|
||||
int gen_active = 0;
|
||||
int pid;
|
||||
char *argv[32];
|
||||
int argc = 1;
|
||||
char *buf, *command;
|
||||
FILE *child_commands = NULL;
|
||||
FILE *child_errors = NULL;
|
||||
FILE *child_events = NULL;
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
AST_LIST_HEAD_INIT(&u->playlist);
|
||||
AST_LIST_HEAD_INIT(&u->finishlist);
|
||||
u->abort_current_sound = 0;
|
||||
|
||||
if (ast_strlen_zero(args)) {
|
||||
ast_log(LOG_WARNING, "ExternalIVR requires a command to execute\n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
buf = ast_strdupa(data);
|
||||
if (!buf) {
|
||||
ast_log(LOG_ERROR, "Out of memory!\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
argc = ast_app_separate_args(buf, '|', argv, sizeof(argv) / sizeof(argv[0]));
|
||||
|
||||
if (pipe(child_stdin)) {
|
||||
ast_chan_log(LOG_WARNING, chan, "Could not create pipe for child input: %s\n", strerror(errno));
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (pipe(child_stdout)) {
|
||||
ast_chan_log(LOG_WARNING, chan, "Could not create pipe for child output: %s\n", strerror(errno));
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (pipe(child_stderr)) {
|
||||
ast_chan_log(LOG_WARNING, chan, "Could not create pipe for child errors: %s\n", strerror(errno));
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (chan->_state != AST_STATE_UP) {
|
||||
ast_answer(chan);
|
||||
}
|
||||
|
||||
if (ast_activate_generator(chan, &gen, u) < 0) {
|
||||
ast_chan_log(LOG_WARNING, chan, "Failed to activate generator\n");
|
||||
goto exit;
|
||||
} else
|
||||
gen_active = 1;
|
||||
|
||||
pid = fork();
|
||||
if (pid < 0) {
|
||||
ast_log(LOG_WARNING, "Failed to fork(): %s\n", strerror(errno));
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (!pid) {
|
||||
/* child process */
|
||||
int i;
|
||||
|
||||
dup2(child_stdin[0], STDIN_FILENO);
|
||||
dup2(child_stdout[1], STDOUT_FILENO);
|
||||
dup2(child_stderr[1], STDERR_FILENO);
|
||||
for (i = STDERR_FILENO + 1; i < 1024; i++)
|
||||
close(i);
|
||||
execv(argv[0], argv);
|
||||
fprintf(stderr, "Failed to execute '%s': %s\n", argv[0], strerror(errno));
|
||||
exit(1);
|
||||
} else {
|
||||
/* parent process */
|
||||
int child_events_fd = child_stdin[1];
|
||||
int child_commands_fd = child_stdout[0];
|
||||
int child_errors_fd = child_stderr[0];
|
||||
struct ast_frame *f;
|
||||
int ms;
|
||||
int exception;
|
||||
int ready_fd;
|
||||
int waitfds[2] = { child_errors_fd, child_commands_fd };
|
||||
struct ast_channel *rchan;
|
||||
|
||||
close(child_stdin[0]);
|
||||
child_stdin[0] = 0;
|
||||
close(child_stdout[1]);
|
||||
child_stdout[1] = 0;
|
||||
close(child_stderr[1]);
|
||||
child_stderr[1] = 0;
|
||||
|
||||
if (!(child_events = fdopen(child_events_fd, "w"))) {
|
||||
ast_chan_log(LOG_WARNING, chan, "Could not open stream for child events\n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (!(child_commands = fdopen(child_commands_fd, "r"))) {
|
||||
ast_chan_log(LOG_WARNING, chan, "Could not open stream for child commands\n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (!(child_errors = fdopen(child_errors_fd, "r"))) {
|
||||
ast_chan_log(LOG_WARNING, chan, "Could not open stream for child errors\n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
setvbuf(child_events, NULL, _IONBF, 0);
|
||||
setvbuf(child_commands, NULL, _IONBF, 0);
|
||||
setvbuf(child_errors, NULL, _IONBF, 0);
|
||||
|
||||
res = 0;
|
||||
|
||||
while (1) {
|
||||
if (ast_test_flag(chan, AST_FLAG_ZOMBIE)) {
|
||||
ast_chan_log(LOG_NOTICE, chan, "Is a zombie\n");
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ast_check_hangup(chan)) {
|
||||
ast_chan_log(LOG_NOTICE, chan, "Got check_hangup\n");
|
||||
send_child_event(child_events, 'H', NULL, chan);
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
ready_fd = 0;
|
||||
ms = 100;
|
||||
errno = 0;
|
||||
exception = 0;
|
||||
|
||||
rchan = ast_waitfor_nandfds(&chan, 1, waitfds, 2, &exception, &ready_fd, &ms);
|
||||
|
||||
if (!AST_LIST_EMPTY(&u->finishlist)) {
|
||||
AST_LIST_LOCK(&u->finishlist);
|
||||
while ((entry = AST_LIST_REMOVE_HEAD(&u->finishlist, list))) {
|
||||
send_child_event(child_events, 'F', entry->filename, chan);
|
||||
free(entry);
|
||||
}
|
||||
AST_LIST_UNLOCK(&u->finishlist);
|
||||
}
|
||||
|
||||
if (rchan) {
|
||||
/* the channel has something */
|
||||
f = ast_read(chan);
|
||||
if (!f) {
|
||||
ast_chan_log(LOG_NOTICE, chan, "Returned no frame\n");
|
||||
send_child_event(child_events, 'H', NULL, chan);
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (f->frametype == AST_FRAME_DTMF) {
|
||||
send_child_event(child_events, f->subclass, NULL, chan);
|
||||
if (u->option_autoclear) {
|
||||
if (!u->abort_current_sound && !u->playing_silence)
|
||||
send_child_event(child_events, 'T', NULL, chan);
|
||||
AST_LIST_LOCK(&u->playlist);
|
||||
while ((entry = AST_LIST_REMOVE_HEAD(&u->playlist, list))) {
|
||||
send_child_event(child_events, 'D', entry->filename, chan);
|
||||
free(entry);
|
||||
}
|
||||
if (!u->playing_silence)
|
||||
u->abort_current_sound = 1;
|
||||
AST_LIST_UNLOCK(&u->playlist);
|
||||
}
|
||||
} else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP)) {
|
||||
ast_chan_log(LOG_NOTICE, chan, "Got AST_CONTROL_HANGUP\n");
|
||||
send_child_event(child_events, 'H', NULL, chan);
|
||||
ast_frfree(f);
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
ast_frfree(f);
|
||||
} else if (ready_fd == child_commands_fd) {
|
||||
char input[1024];
|
||||
|
||||
if (exception || feof(child_commands)) {
|
||||
ast_chan_log(LOG_WARNING, chan, "Child process went away\n");
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!fgets(input, sizeof(input), child_commands))
|
||||
continue;
|
||||
|
||||
command = ast_strip(input);
|
||||
|
||||
ast_chan_log(LOG_DEBUG, chan, "got command '%s'\n", input);
|
||||
|
||||
if (strlen(input) < 4)
|
||||
continue;
|
||||
|
||||
if (input[0] == 'S') {
|
||||
if (ast_fileexists(&input[2], NULL, NULL) == -1) {
|
||||
ast_chan_log(LOG_WARNING, chan, "Unknown file requested '%s'\n", &input[2]);
|
||||
send_child_event(child_events, 'Z', NULL, chan);
|
||||
strcpy(&input[2], "exception");
|
||||
}
|
||||
if (!u->abort_current_sound && !u->playing_silence)
|
||||
send_child_event(child_events, 'T', NULL, chan);
|
||||
AST_LIST_LOCK(&u->playlist);
|
||||
while ((entry = AST_LIST_REMOVE_HEAD(&u->playlist, list))) {
|
||||
send_child_event(child_events, 'D', entry->filename, chan);
|
||||
free(entry);
|
||||
}
|
||||
if (!u->playing_silence)
|
||||
u->abort_current_sound = 1;
|
||||
entry = make_entry(&input[2]);
|
||||
if (entry)
|
||||
AST_LIST_INSERT_TAIL(&u->playlist, entry, list);
|
||||
AST_LIST_UNLOCK(&u->playlist);
|
||||
} else if (input[0] == 'A') {
|
||||
if (ast_fileexists(&input[2], NULL, NULL) == -1) {
|
||||
ast_chan_log(LOG_WARNING, chan, "Unknown file requested '%s'\n", &input[2]);
|
||||
send_child_event(child_events, 'Z', NULL, chan);
|
||||
strcpy(&input[2], "exception");
|
||||
}
|
||||
entry = make_entry(&input[2]);
|
||||
if (entry) {
|
||||
AST_LIST_LOCK(&u->playlist);
|
||||
AST_LIST_INSERT_TAIL(&u->playlist, entry, list);
|
||||
AST_LIST_UNLOCK(&u->playlist);
|
||||
}
|
||||
} else if (input[0] == 'H') {
|
||||
ast_chan_log(LOG_NOTICE, chan, "Hanging up: %s\n", &input[2]);
|
||||
send_child_event(child_events, 'H', NULL, chan);
|
||||
break;
|
||||
} else if (input[0] == 'O') {
|
||||
if (!strcasecmp(&input[2], "autoclear"))
|
||||
u->option_autoclear = 1;
|
||||
else if (!strcasecmp(&input[2], "noautoclear"))
|
||||
u->option_autoclear = 0;
|
||||
else
|
||||
ast_chan_log(LOG_WARNING, chan, "Unknown option requested '%s'\n", &input[2]);
|
||||
}
|
||||
} else if (ready_fd == child_errors_fd) {
|
||||
char input[1024];
|
||||
|
||||
if (exception || feof(child_errors)) {
|
||||
ast_chan_log(LOG_WARNING, chan, "Child process went away\n");
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (fgets(input, sizeof(input), child_errors)) {
|
||||
command = ast_strip(input);
|
||||
ast_chan_log(LOG_NOTICE, chan, "stderr: %s\n", command);
|
||||
}
|
||||
} else if ((ready_fd < 0) && ms) {
|
||||
if (errno == 0 || errno == EINTR)
|
||||
continue;
|
||||
|
||||
ast_chan_log(LOG_WARNING, chan, "Wait failed (%s)\n", strerror(errno));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
if (gen_active)
|
||||
ast_deactivate_generator(chan);
|
||||
|
||||
if (child_events)
|
||||
fclose(child_events);
|
||||
|
||||
if (child_commands)
|
||||
fclose(child_commands);
|
||||
|
||||
if (child_errors)
|
||||
fclose(child_errors);
|
||||
|
||||
if (child_stdin[0])
|
||||
close(child_stdin[0]);
|
||||
|
||||
if (child_stdin[1])
|
||||
close(child_stdin[1]);
|
||||
|
||||
if (child_stdout[0])
|
||||
close(child_stdout[0]);
|
||||
|
||||
if (child_stdout[1])
|
||||
close(child_stdout[1]);
|
||||
|
||||
if (child_stderr[0])
|
||||
close(child_stderr[0]);
|
||||
|
||||
if (child_stderr[1])
|
||||
close(child_stderr[1]);
|
||||
|
||||
while ((entry = AST_LIST_REMOVE_HEAD(&u->playlist, list)))
|
||||
free(entry);
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app);
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(app, app_exec, synopsis, descrip);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return (char *) tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
STANDARD_USECOUNT(res);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
145
apps/app_festival.c
Executable file → Normal file
145
apps/app_festival.c
Executable file → Normal file
@@ -1,24 +1,29 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Connect to festival
|
||||
*
|
||||
* Copyright (C) 2002, Christos Ricudis
|
||||
*
|
||||
* Christos Ricudis <ricudis@paiko.gr>
|
||||
* Christos Ricudis <ricudis@itc.auth.gr>
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief Connect to festival
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/md5.h>
|
||||
#include <asterisk/config.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
@@ -34,8 +39,20 @@
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <ctype.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/md5.h"
|
||||
#include "asterisk/config.h"
|
||||
#include "asterisk/utils.h"
|
||||
#include "asterisk/lock.h"
|
||||
|
||||
#define FESTIVAL_CONFIG "festival.conf"
|
||||
|
||||
@@ -119,7 +136,7 @@ static int send_waveform_to_fd(char *waveform, int length, int fd) {
|
||||
if (x != fd)
|
||||
close(x);
|
||||
}
|
||||
//IAS
|
||||
/*IAS */
|
||||
#ifdef __PPC__
|
||||
for( x=0; x<length; x+=2)
|
||||
{
|
||||
@@ -130,7 +147,6 @@ static int send_waveform_to_fd(char *waveform, int length, int fd) {
|
||||
#endif
|
||||
|
||||
write(fd,waveform,length);
|
||||
write(fd,"a",1);
|
||||
close(fd);
|
||||
exit(0);
|
||||
}
|
||||
@@ -155,8 +171,12 @@ static int send_waveform_to_channel(struct ast_channel *chan, char *waveform, in
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Answer if it's not already going */
|
||||
if (chan->_state != AST_STATE_UP)
|
||||
ast_answer(chan);
|
||||
ast_stopstream(chan);
|
||||
|
||||
ast_indicate(chan, -1);
|
||||
|
||||
owriteformat = chan->writeformat;
|
||||
res = ast_set_write_format(chan, AST_FORMAT_SLINEAR);
|
||||
if (res < 0) {
|
||||
@@ -195,7 +215,7 @@ static int send_waveform_to_channel(struct ast_channel *chan, char *waveform, in
|
||||
needed = f->samples * 2;
|
||||
if (needed > sizeof(myf.frdata)) {
|
||||
ast_log(LOG_WARNING, "Only able to deliver %d of %d requested samples\n",
|
||||
sizeof(myf.frdata) / 2, needed/2);
|
||||
(int)sizeof(myf.frdata) / 2, needed/2);
|
||||
needed = sizeof(myf.frdata);
|
||||
}
|
||||
res = read(fds[0], myf.frdata, needed);
|
||||
@@ -212,7 +232,7 @@ static int send_waveform_to_channel(struct ast_channel *chan, char *waveform, in
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
if (res < needed) { // last frame
|
||||
if (res < needed) { /* last frame */
|
||||
ast_log(LOG_DEBUG, "Last frame\n");
|
||||
res=0;
|
||||
break;
|
||||
@@ -227,8 +247,9 @@ static int send_waveform_to_channel(struct ast_channel *chan, char *waveform, in
|
||||
}
|
||||
close(fds[0]);
|
||||
close(fds[1]);
|
||||
// if (pid > -1)
|
||||
// kill(pid, SIGKILL);
|
||||
|
||||
/* if (pid > -1) */
|
||||
/* kill(pid, SIGKILL); */
|
||||
if (!res && owriteformat)
|
||||
ast_set_write_format(chan, owriteformat);
|
||||
return res;
|
||||
@@ -247,6 +268,7 @@ static int festival_exec(struct ast_channel *chan, void *vdata)
|
||||
struct localuser *u;
|
||||
struct sockaddr_in serv_addr;
|
||||
struct hostent *serverhost;
|
||||
struct ast_hostent ahp;
|
||||
int fd;
|
||||
FILE *fs;
|
||||
char *host;
|
||||
@@ -263,22 +285,30 @@ static int festival_exec(struct ast_channel *chan, void *vdata)
|
||||
int i;
|
||||
struct MD5Context md5ctx;
|
||||
unsigned char MD5Res[16];
|
||||
char MD5Hex[32];
|
||||
char koko[4];
|
||||
char cachefile[MAXFESTLEN];
|
||||
char MD5Hex[33] = "";
|
||||
char koko[4] = "";
|
||||
char cachefile[MAXFESTLEN]="";
|
||||
int readcache=0;
|
||||
int writecache=0;
|
||||
int strln;
|
||||
int fdesc = -1;
|
||||
char buffer[16384];
|
||||
int seekpos = 0;
|
||||
char data[256] = "";
|
||||
char *data;
|
||||
char *intstr;
|
||||
|
||||
struct ast_config *cfg;
|
||||
cfg = ast_load(FESTIVAL_CONFIG);
|
||||
|
||||
if (ast_strlen_zero(vdata)) {
|
||||
ast_log(LOG_WARNING, "festival requires an argument (text)\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
cfg = ast_config_load(FESTIVAL_CONFIG);
|
||||
if (!cfg) {
|
||||
ast_log(LOG_WARNING, "No such configuration file %s\n", FESTIVAL_CONFIG);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
if (!(host = ast_variable_retrieve(cfg, "general", "host"))) {
|
||||
@@ -301,20 +331,22 @@ static int festival_exec(struct ast_channel *chan, void *vdata)
|
||||
festivalcommand = "(tts_textasterisk \"%s\" 'file)(quit)\n";
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (!vdata || !strlen(vdata)) {
|
||||
ast_log(LOG_WARNING, "festival requires an argument (text)\n");
|
||||
data = ast_strdupa(vdata);
|
||||
if (!data) {
|
||||
ast_log(LOG_ERROR, "Out of memery\n");
|
||||
ast_config_destroy(cfg);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
strncpy(data, vdata, sizeof(data) - 1);
|
||||
if ((intstr = strchr(data, '|'))) {
|
||||
|
||||
intstr = strchr(data, '|');
|
||||
if (intstr) {
|
||||
*intstr = '\0';
|
||||
intstr++;
|
||||
if (!strcasecmp(intstr, "any"))
|
||||
intstr = AST_DIGIT_ANY;
|
||||
}
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
ast_log(LOG_DEBUG, "Text passed to festival server : %s\n",(char *)data);
|
||||
/* Connect to local festival server */
|
||||
|
||||
@@ -322,14 +354,18 @@ static int festival_exec(struct ast_channel *chan, void *vdata)
|
||||
|
||||
if (fd < 0) {
|
||||
ast_log(LOG_WARNING,"festival_client: can't get socket\n");
|
||||
ast_config_destroy(cfg);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
memset(&serv_addr, 0, sizeof(serv_addr));
|
||||
if ((serv_addr.sin_addr.s_addr = inet_addr(host)) == -1) {
|
||||
/* its a name rather than an ipnum */
|
||||
serverhost = gethostbyname(host);
|
||||
serverhost = ast_gethostbyname(host, &ahp);
|
||||
if (serverhost == (struct hostent *)0) {
|
||||
ast_log(LOG_WARNING,"festival_client: gethostbyname failed\n");
|
||||
ast_config_destroy(cfg);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
memmove(&serv_addr.sin_addr,serverhost->h_addr, serverhost->h_length);
|
||||
@@ -339,6 +375,8 @@ static int festival_exec(struct ast_channel *chan, void *vdata)
|
||||
|
||||
if (connect(fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) != 0) {
|
||||
ast_log(LOG_WARNING,"festival_client: connect to server failed\n");
|
||||
ast_config_destroy(cfg);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -346,21 +384,21 @@ static int festival_exec(struct ast_channel *chan, void *vdata)
|
||||
MD5Init(&md5ctx);
|
||||
MD5Update(&md5ctx,(unsigned char const *)data,strlen(data));
|
||||
MD5Final(MD5Res,&md5ctx);
|
||||
strcpy(MD5Hex,"");
|
||||
MD5Hex[0] = '\0';
|
||||
|
||||
/* Convert to HEX and look if there is any matching file in the cache
|
||||
directory */
|
||||
for (i=0;i<16;i++) {
|
||||
sprintf(koko,"%X",MD5Res[i]);
|
||||
strcat(MD5Hex,koko);
|
||||
snprintf(koko, sizeof(koko), "%X",MD5Res[i]);
|
||||
strncat(MD5Hex, koko, sizeof(MD5Hex) - strlen(MD5Hex) - 1);
|
||||
}
|
||||
readcache=0;
|
||||
writecache=0;
|
||||
if (strlen(cachedir)+strlen(MD5Hex)+1<=MAXFESTLEN && (usecache==-1)) {
|
||||
sprintf(cachefile,"%s/%s",cachedir,MD5Hex);
|
||||
snprintf(cachefile, sizeof(cachefile), "%s/%s", cachedir, MD5Hex);
|
||||
fdesc=open(cachefile,O_RDWR);
|
||||
if (fdesc==-1) {
|
||||
fdesc=open(cachefile,O_CREAT|O_RDWR,0);
|
||||
fdesc=open(cachefile,O_CREAT|O_RDWR,0777);
|
||||
if (fdesc!=-1) {
|
||||
writecache=1;
|
||||
strln=strlen((char *)data);
|
||||
@@ -372,11 +410,12 @@ static int festival_exec(struct ast_channel *chan, void *vdata)
|
||||
}
|
||||
} else {
|
||||
read(fdesc,&strln,sizeof(int));
|
||||
ast_log(LOG_DEBUG,"Cache file exists, strln=%d, strlen=%d\n",strln,strlen((char *)data));
|
||||
ast_log(LOG_DEBUG,"Cache file exists, strln=%d, strlen=%d\n",strln,(int)strlen((char *)data));
|
||||
if (strlen((char *)data)==strln) {
|
||||
ast_log(LOG_DEBUG,"Size OK\n");
|
||||
read(fdesc,&bigstring,strln);
|
||||
if (strcmp(bigstring,data)==0) {
|
||||
bigstring[strln] = 0;
|
||||
if (strcmp(bigstring,data)==0) {
|
||||
readcache=1;
|
||||
} else {
|
||||
ast_log(LOG_WARNING,"Strings do not match\n");
|
||||
@@ -417,8 +456,20 @@ static int festival_exec(struct ast_channel *chan, void *vdata)
|
||||
/* This assumes only one waveform will come back, also LP is unlikely */
|
||||
wave = 0;
|
||||
do {
|
||||
int read_data;
|
||||
for (n=0; n < 3; )
|
||||
n += read(fd,ack+n,3-n);
|
||||
{
|
||||
read_data = read(fd,ack+n,3-n);
|
||||
/* this avoids falling in infinite loop
|
||||
* in case that festival server goes down
|
||||
* */
|
||||
if ( read_data == -1 )
|
||||
{
|
||||
ast_log(LOG_WARNING,"Unable to read from cache/festival fd");
|
||||
return -1;
|
||||
}
|
||||
n += read_data;
|
||||
}
|
||||
ack[3] = '\0';
|
||||
if (strcmp(ack,"WV\n") == 0) { /* receive a waveform */
|
||||
ast_log(LOG_DEBUG,"Festival WV command\n");
|
||||
@@ -440,15 +491,21 @@ static int festival_exec(struct ast_channel *chan, void *vdata)
|
||||
}
|
||||
} while (strcmp(ack,"OK\n") != 0);
|
||||
close(fd);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
ast_config_destroy(cfg);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app);
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
|
||||
69
apps/app_flash.c
Executable file → Normal file
69
apps/app_flash.c
Executable file → Normal file
@@ -1,31 +1,52 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* App to flash a zap trunk
|
||||
*
|
||||
* Copyright (C) 1999, Mark Spencer
|
||||
* Copyright (C) 1999 - 2005, Digium, Inc.
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
* Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief App to flash a zap trunk
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/translate.h>
|
||||
#include <asterisk/image.h>
|
||||
#include <asterisk/options.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/zaptel.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/ioctl.h>
|
||||
#ifdef __linux__
|
||||
#include <linux/zaptel.h>
|
||||
#else
|
||||
#include <zaptel.h>
|
||||
#endif /* __linux__ */
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/lock.h"
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/translate.h"
|
||||
#include "asterisk/image.h"
|
||||
#include "asterisk/options.h"
|
||||
|
||||
static char *tdesc = "Flash zap trunk application";
|
||||
|
||||
@@ -36,8 +57,7 @@ static char *synopsis = "Flashes a Zap Trunk";
|
||||
static char *descrip =
|
||||
" Flash(): Sends a flash on a zap trunk. This is only a hack for\n"
|
||||
"people who want to perform transfers and such via AGI and is generally\n"
|
||||
"quite useless otherwise. Returns 0 on success or -1 if this is not\n"
|
||||
"a zap trunk\n";
|
||||
"quite useless oths application will only work on Zap trunks.\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
@@ -89,8 +109,13 @@ static int flash_exec(struct ast_channel *chan, void *data)
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app);
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
|
||||
131
apps/app_forkcdr.c
Normal file
131
apps/app_forkcdr.c
Normal file
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Copyright (C) 1999 - 2005, Anthony Minessale anthmct@yahoo.com
|
||||
* Development of this app Sponsered/Funded by TAAN Softworks Corp
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief Fork CDR application
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/cdr.h"
|
||||
#include "asterisk/module.h"
|
||||
|
||||
static char *tdesc = "Fork The CDR into 2 separate entities.";
|
||||
static char *app = "ForkCDR";
|
||||
static char *synopsis =
|
||||
"Forks the Call Data Record";
|
||||
static char *descrip =
|
||||
" ForkCDR([options]): Causes the Call Data Record to fork an additional\n"
|
||||
"cdr record starting from the time of the fork call\n"
|
||||
"If the option 'v' is passed all cdr variables will be passed along also.\n"
|
||||
"";
|
||||
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static void ast_cdr_fork(struct ast_channel *chan)
|
||||
{
|
||||
struct ast_cdr *cdr;
|
||||
struct ast_cdr *newcdr;
|
||||
struct ast_flags flags = { AST_CDR_FLAG_KEEP_VARS };
|
||||
|
||||
cdr = chan->cdr;
|
||||
|
||||
while (cdr->next)
|
||||
cdr = cdr->next;
|
||||
|
||||
if (!(newcdr = ast_cdr_dup(cdr)))
|
||||
return;
|
||||
|
||||
ast_cdr_append(cdr, newcdr);
|
||||
ast_cdr_reset(newcdr, &flags);
|
||||
|
||||
if (!ast_test_flag(cdr, AST_CDR_FLAG_KEEP_VARS))
|
||||
ast_cdr_free_vars(cdr, 0);
|
||||
|
||||
ast_set_flag(cdr, AST_CDR_FLAG_CHILD | AST_CDR_FLAG_LOCKED);
|
||||
}
|
||||
|
||||
static int forkcdr_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res = 0;
|
||||
struct localuser *u;
|
||||
|
||||
if (!chan->cdr) {
|
||||
ast_log(LOG_WARNING, "Channel does not have a CDR\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
if (!ast_strlen_zero(data))
|
||||
ast_set2_flag(chan->cdr, strchr(data, 'v'), AST_CDR_FLAG_KEEP_VARS);
|
||||
|
||||
ast_cdr_fork(chan);
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app);
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(app, forkcdr_exec, synopsis, descrip);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
78
apps/app_getcpeid.c
Executable file → Normal file
78
apps/app_getcpeid.c
Executable file → Normal file
@@ -1,31 +1,45 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Execute arbitrary system commands
|
||||
*
|
||||
* Copyright (C) 1999, Mark Spencer
|
||||
* Copyright (C) 1999 - 2005, Digium, Inc.
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
* Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief Get ADSI CPE ID
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/adsi.h>
|
||||
#include <asterisk/options.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <pthread.h>
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/lock.h"
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/adsi.h"
|
||||
#include "asterisk/options.h"
|
||||
|
||||
static char *tdesc = "Get ADSI CPE ID";
|
||||
|
||||
@@ -34,9 +48,8 @@ static char *app = "GetCPEID";
|
||||
static char *synopsis = "Get ADSI CPE ID";
|
||||
|
||||
static char *descrip =
|
||||
" GetCPEID: Obtains and displays CPE ID and other information in order to\n"
|
||||
"properly setup zapata.conf for on-hook operations. Returns -1 on hanup\n"
|
||||
"only.";
|
||||
" GetCPEID: Obtains and displays ADSI CPE ID and other information in order\n"
|
||||
"to properly setup zapata.conf for on-hook operations.\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
@@ -70,9 +83,9 @@ static int cpeid_exec(struct ast_channel *chan, void *idata)
|
||||
stuff[2] = data[2];
|
||||
stuff[3] = data[3];
|
||||
memset(data, 0, sizeof(data));
|
||||
strcpy(stuff[0], "** CPE Info **");
|
||||
strcpy(stuff[1], "Identifying CPE...");
|
||||
strcpy(stuff[2], "Please wait...");
|
||||
strncpy(stuff[0], "** CPE Info **", sizeof(data[0]) - 1);
|
||||
strncpy(stuff[1], "Identifying CPE...", sizeof(data[1]) - 1);
|
||||
strncpy(stuff[2], "Please wait...", sizeof(data[2]) - 1);
|
||||
res = adsi_load_session(chan, NULL, 0, 1);
|
||||
if (res > 0) {
|
||||
cpeid_setstatus(chan, stuff, 0);
|
||||
@@ -83,8 +96,8 @@ static int cpeid_exec(struct ast_channel *chan, void *idata)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "Got CPEID of '%02x:%02x:%02x:%02x' on '%s'\n", cpeid[0], cpeid[1], cpeid[2], cpeid[3], chan->name);
|
||||
}
|
||||
if (res > -1) {
|
||||
strcpy(stuff[1], "Measuring CPE...");
|
||||
strcpy(stuff[2], "Please wait...");
|
||||
strncpy(stuff[1], "Measuring CPE...", sizeof(data[1]) - 1);
|
||||
strncpy(stuff[2], "Please wait...", sizeof(data[2]) - 1);
|
||||
cpeid_setstatus(chan, stuff, 0);
|
||||
res = adsi_get_cpeinfo(chan, &width, &height, &buttons, 0);
|
||||
if (res > -1) {
|
||||
@@ -95,14 +108,14 @@ static int cpeid_exec(struct ast_channel *chan, void *idata)
|
||||
}
|
||||
if (res > -1) {
|
||||
if (gotcpeid)
|
||||
sprintf(stuff[1], "CPEID: %02x:%02x:%02x:%02x", cpeid[0], cpeid[1], cpeid[2], cpeid[3]);
|
||||
snprintf(stuff[1], sizeof(data[1]), "CPEID: %02x:%02x:%02x:%02x", cpeid[0], cpeid[1], cpeid[2], cpeid[3]);
|
||||
else
|
||||
strcpy(stuff[1], "CPEID Unknown");
|
||||
strncpy(stuff[1], "CPEID Unknown", sizeof(data[1]) - 1);
|
||||
if (gotgeometry)
|
||||
sprintf(stuff[2], "Geom: %dx%d, %d buttons", width, height, buttons);
|
||||
snprintf(stuff[2], sizeof(data[2]), "Geom: %dx%d, %d buttons", width, height, buttons);
|
||||
else
|
||||
strcpy(stuff[2], "Geometry unknown");
|
||||
strcpy(stuff[3], "Press # to exit");
|
||||
strncpy(stuff[2], "Geometry unknown", sizeof(data[2]) - 1);
|
||||
strncpy(stuff[3], "Press # to exit", sizeof(data[3]) - 1);
|
||||
cpeid_setstatus(chan, stuff, 1);
|
||||
for(;;) {
|
||||
res = ast_waitfordigit(chan, 1000);
|
||||
@@ -122,8 +135,13 @@ static int cpeid_exec(struct ast_channel *chan, void *idata)
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app);
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
|
||||
340
apps/app_groupcount.c
Normal file
340
apps/app_groupcount.c
Normal file
@@ -0,0 +1,340 @@
|
||||
/*
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Copyright (C) 1999 - 2005, Digium, Inc.
|
||||
*
|
||||
* Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief Group Manipulation Applications
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <regex.h>
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/options.h"
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/utils.h"
|
||||
#include "asterisk/cli.h"
|
||||
#include "asterisk/app.h"
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int group_count_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res = 0;
|
||||
int count;
|
||||
struct localuser *u;
|
||||
char group[80] = "";
|
||||
char category[80] = "";
|
||||
char ret[80] = "";
|
||||
char *grp;
|
||||
static int deprecation_warning = 0;
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
if (!deprecation_warning) {
|
||||
ast_log(LOG_WARNING, "The GetGroupCount application has been deprecated, please use the GROUP_COUNT function.\n");
|
||||
deprecation_warning = 1;
|
||||
}
|
||||
|
||||
ast_app_group_split_group(data, group, sizeof(group), category, sizeof(category));
|
||||
|
||||
if (ast_strlen_zero(group)) {
|
||||
grp = pbx_builtin_getvar_helper(chan, category);
|
||||
strncpy(group, grp, sizeof(group) - 1);
|
||||
}
|
||||
|
||||
count = ast_app_group_get_count(group, category);
|
||||
snprintf(ret, sizeof(ret), "%d", count);
|
||||
pbx_builtin_setvar_helper(chan, "GROUPCOUNT", ret);
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int group_match_count_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res = 0;
|
||||
int count;
|
||||
struct localuser *u;
|
||||
char group[80] = "";
|
||||
char category[80] = "";
|
||||
char ret[80] = "";
|
||||
static int deprecation_warning = 0;
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
if (!deprecation_warning) {
|
||||
ast_log(LOG_WARNING, "The GetGroupMatchCount application has been deprecated, please use the GROUP_MATCH_COUNT function.\n");
|
||||
deprecation_warning = 1;
|
||||
}
|
||||
|
||||
ast_app_group_split_group(data, group, sizeof(group), category, sizeof(category));
|
||||
|
||||
if (!ast_strlen_zero(group)) {
|
||||
count = ast_app_group_match_get_count(group, category);
|
||||
snprintf(ret, sizeof(ret), "%d", count);
|
||||
pbx_builtin_setvar_helper(chan, "GROUPCOUNT", ret);
|
||||
}
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int group_set_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res = 0;
|
||||
struct localuser *u;
|
||||
static int deprecation_warning = 0;
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
if (!deprecation_warning) {
|
||||
ast_log(LOG_WARNING, "The SetGroup application has been deprecated, please use the GROUP() function.\n");
|
||||
deprecation_warning = 1;
|
||||
}
|
||||
|
||||
if (ast_app_group_set_channel(chan, data))
|
||||
ast_log(LOG_WARNING, "SetGroup requires an argument (group name)\n");
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int group_check_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res = 0;
|
||||
int max, count;
|
||||
struct localuser *u;
|
||||
char limit[80]="";
|
||||
char category[80]="";
|
||||
static int deprecation_warning = 0;
|
||||
char *parse;
|
||||
int priority_jump = 0;
|
||||
AST_DECLARE_APP_ARGS(args,
|
||||
AST_APP_ARG(max);
|
||||
AST_APP_ARG(options);
|
||||
);
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
if (!deprecation_warning) {
|
||||
ast_log(LOG_WARNING, "The CheckGroup application has been deprecated, please use a combination of the GotoIf application and the GROUP_COUNT() function.\n");
|
||||
deprecation_warning = 1;
|
||||
}
|
||||
|
||||
if (!(parse = ast_strdupa(data))) {
|
||||
ast_log(LOG_WARNING, "Memory Error!\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
AST_STANDARD_APP_ARGS(args, parse);
|
||||
|
||||
if (args.options) {
|
||||
if (strchr(args.options, 'j'))
|
||||
priority_jump = 1;
|
||||
}
|
||||
|
||||
if (ast_strlen_zero(args.max)) {
|
||||
ast_log(LOG_WARNING, "CheckGroup requires an argument(max[@category][|options])\n");
|
||||
return res;
|
||||
}
|
||||
|
||||
ast_app_group_split_group(args.max, limit, sizeof(limit), category, sizeof(category));
|
||||
|
||||
if ((sscanf(limit, "%d", &max) == 1) && (max > -1)) {
|
||||
count = ast_app_group_get_count(pbx_builtin_getvar_helper(chan, category), category);
|
||||
if (count > max) {
|
||||
pbx_builtin_setvar_helper(chan, "CHECKGROUPSTATUS", "OVERMAX");
|
||||
if (priority_jump || option_priority_jumping) {
|
||||
if (!ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101))
|
||||
res = -1;
|
||||
}
|
||||
} else
|
||||
pbx_builtin_setvar_helper(chan, "CHECKGROUPSTATUS", "OK");
|
||||
} else
|
||||
ast_log(LOG_WARNING, "CheckGroup requires a positive integer argument (max)\n");
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int group_show_channels(int fd, int argc, char *argv[])
|
||||
{
|
||||
#define FORMAT_STRING "%-25s %-20s %-20s\n"
|
||||
|
||||
struct ast_channel *c = NULL;
|
||||
int numchans = 0;
|
||||
struct ast_var_t *current;
|
||||
struct varshead *headp;
|
||||
regex_t regexbuf;
|
||||
int havepattern = 0;
|
||||
|
||||
if (argc < 3 || argc > 4)
|
||||
return RESULT_SHOWUSAGE;
|
||||
|
||||
if (argc == 4) {
|
||||
if (regcomp(®exbuf, argv[3], REG_EXTENDED | REG_NOSUB))
|
||||
return RESULT_SHOWUSAGE;
|
||||
havepattern = 1;
|
||||
}
|
||||
|
||||
ast_cli(fd, FORMAT_STRING, "Channel", "Group", "Category");
|
||||
while ( (c = ast_channel_walk_locked(c)) != NULL) {
|
||||
headp=&c->varshead;
|
||||
AST_LIST_TRAVERSE(headp,current,entries) {
|
||||
if (!strncmp(ast_var_name(current), GROUP_CATEGORY_PREFIX "_", strlen(GROUP_CATEGORY_PREFIX) + 1)) {
|
||||
if (!havepattern || !regexec(®exbuf, ast_var_value(current), 0, NULL, 0)) {
|
||||
ast_cli(fd, FORMAT_STRING, c->name, ast_var_value(current),
|
||||
(ast_var_name(current) + strlen(GROUP_CATEGORY_PREFIX) + 1));
|
||||
numchans++;
|
||||
}
|
||||
} else if (!strcmp(ast_var_name(current), GROUP_CATEGORY_PREFIX)) {
|
||||
if (!havepattern || !regexec(®exbuf, ast_var_value(current), 0, NULL, 0)) {
|
||||
ast_cli(fd, FORMAT_STRING, c->name, ast_var_value(current), "(default)");
|
||||
numchans++;
|
||||
}
|
||||
}
|
||||
}
|
||||
numchans++;
|
||||
ast_mutex_unlock(&c->lock);
|
||||
}
|
||||
|
||||
if (havepattern)
|
||||
regfree(®exbuf);
|
||||
|
||||
ast_cli(fd, "%d active channel%s\n", numchans, (numchans != 1) ? "s" : "");
|
||||
return RESULT_SUCCESS;
|
||||
#undef FORMAT_STRING
|
||||
}
|
||||
|
||||
static char *tdesc = "Group Management Routines";
|
||||
|
||||
static char *app_group_count = "GetGroupCount";
|
||||
static char *app_group_set = "SetGroup";
|
||||
static char *app_group_check = "CheckGroup";
|
||||
static char *app_group_match_count = "GetGroupMatchCount";
|
||||
|
||||
static char *group_count_synopsis = "Get the channel count of a group";
|
||||
static char *group_set_synopsis = "Set the channel's group";
|
||||
static char *group_check_synopsis = "Check the channel count of a group against a limit";
|
||||
static char *group_match_count_synopsis = "Get the channel count of all groups that match a pattern";
|
||||
|
||||
static char *group_count_descrip =
|
||||
"Usage: GetGroupCount([groupname][@category])\n"
|
||||
" Calculates the group count for the specified group, or uses\n"
|
||||
"the current channel's group if not specifed (and non-empty).\n"
|
||||
"Stores result in GROUPCOUNT. \n"
|
||||
"This application has been deprecated, please use the function\n"
|
||||
"GroupCount.\n";
|
||||
|
||||
static char *group_set_descrip =
|
||||
"Usage: SetGroup(groupname[@category])\n"
|
||||
" Sets the channel group to the specified value. Equivalent to\n"
|
||||
"Set(GROUP=group). Always returns 0.\n";
|
||||
|
||||
static char *group_check_descrip =
|
||||
"Usage: CheckGroup(max[@category][|options])\n"
|
||||
" Checks that the current number of total channels in the\n"
|
||||
"current channel's group does not exceed 'max'. If the number\n"
|
||||
"does not exceed 'max', we continue to the next step. \n"
|
||||
" The option string may contain zero of the following character:\n"
|
||||
" 'j' -- jump to n+101 priority if the number does in fact exceed max,\n"
|
||||
" and priority n+101 exists. Execuation then continues at that\n"
|
||||
" step, otherwise -1 is returned.\n"
|
||||
" This application sets the following channel variable upon successful completion:\n"
|
||||
" CHECKGROUPSTATUS The status of the check that the current channel's\n"
|
||||
" group does not exceed 'max'. It's value is one of\n"
|
||||
" OK | OVERMAX \n";
|
||||
|
||||
static char *group_match_count_descrip =
|
||||
"Usage: GetGroupMatchCount(groupmatch[@category])\n"
|
||||
" Calculates the group count for all groups that match the specified\n"
|
||||
"pattern. Uses standard regular expression matching (see regex(7)).\n"
|
||||
"Stores result in GROUPCOUNT. Always returns 0.\n"
|
||||
"This application has been deprecated, please use the function\n"
|
||||
"GroupMatchCount.\n";
|
||||
|
||||
static char show_channels_usage[] =
|
||||
"Usage: group show channels [pattern]\n"
|
||||
" Lists all currently active channels with channel group(s) specified.\n Optional regular expression pattern is matched to group names for each channel.\n";
|
||||
|
||||
static struct ast_cli_entry cli_show_channels =
|
||||
{ { "group", "show", "channels", NULL }, group_show_channels, "Show active channels with group(s)", show_channels_usage};
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_cli_unregister(&cli_show_channels);
|
||||
res |= ast_unregister_application(app_group_count);
|
||||
res |= ast_unregister_application(app_group_set);
|
||||
res |= ast_unregister_application(app_group_check);
|
||||
res |= ast_unregister_application(app_group_match_count);
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_register_application(app_group_count, group_count_exec, group_count_synopsis, group_count_descrip);
|
||||
res |= ast_register_application(app_group_set, group_set_exec, group_set_synopsis, group_set_descrip);
|
||||
res |= ast_register_application(app_group_check, group_check_exec, group_check_synopsis, group_check_descrip);
|
||||
res |= ast_register_application(app_group_match_count, group_match_count_exec, group_match_count_synopsis, group_match_count_descrip);
|
||||
res |= ast_cli_register(&cli_show_channels);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
283
apps/app_hasnewvoicemail.c
Executable file → Normal file
283
apps/app_hasnewvoicemail.c
Executable file → Normal file
@@ -1,130 +1,249 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* HasNewVoicemail application
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Changes Copyright (c) 2004 - 2005 Todd Freeman <freeman@andrews.edu>
|
||||
*
|
||||
* 95% based on HasNewVoicemail by:
|
||||
*
|
||||
* Copyright (c) 2003 Tilghman Lesher. All rights reserved.
|
||||
*
|
||||
* Tilghman Lesher <asterisk-hasnewvoicemail-app@the-tilghman.com>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief HasVoicemail application
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <pthread.h>
|
||||
#include "asterisk.h"
|
||||
|
||||
#include "../astconf.h"
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/lock.h"
|
||||
#include "asterisk/utils.h"
|
||||
#include "asterisk/app.h"
|
||||
#include "asterisk/options.h"
|
||||
|
||||
static char *tdesc = "Indicator for whether a voice mailbox has messages in a given folder.";
|
||||
static char *app_hasvoicemail = "HasVoicemail";
|
||||
static char *hasvoicemail_synopsis = "Conditionally branches to priority + 101 with the right options set";
|
||||
static char *hasvoicemail_descrip =
|
||||
"HasVoicemail(vmbox[/folder][@context][|varname[|options]])\n"
|
||||
" Optionally sets <varname> to the number of messages in that folder."
|
||||
" Assumes folder of INBOX if not specified.\n"
|
||||
" The option string may contain zero or the following character:\n"
|
||||
" 'j' -- jump to priority n+101, if there is voicemail in the folder indicated.\n"
|
||||
" This application sets the following channel variable upon completion:\n"
|
||||
" HASVMSTATUS The result of the voicemail check returned as a text string as follows\n"
|
||||
" <# of messages in the folder, 0 for NONE>\n";
|
||||
|
||||
static char *tdesc = "Indicator for whether a voice mailbox has new messages.";
|
||||
static char *app_hasnewvoicemail = "HasNewVoicemail";
|
||||
static char *hasnewvoicemail_synopsis = "Conditionally branches to priority + 101";
|
||||
static char *hasnewvoicemail_synopsis = "Conditionally branches to priority + 101 with the right options set";
|
||||
static char *hasnewvoicemail_descrip =
|
||||
"HasNewVoicemail(vmbox[@context][|varname])\n"
|
||||
" Branches to priority + 101, if there is new voicemail"
|
||||
" Optionally sets <varname> to the number of new messages.\n";
|
||||
"HasNewVoicemail(vmbox[/folder][@context][|varname[|options]])\n"
|
||||
"Assumes folder 'INBOX' if folder is not specified. Optionally sets <varname> to the number of messages\n"
|
||||
"in that folder.\n"
|
||||
" The option string may contain zero of the following character:\n"
|
||||
" 'j' -- jump to priority n+101, if there is new voicemail in folder 'folder' or INBOX\n"
|
||||
" This application sets the following channel variable upon completion:\n"
|
||||
" HASVMSTATUS The result of the new voicemail check returned as a text string as follows\n"
|
||||
" <# of messages in the folder, 0 for NONE>\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int hasnewvoicemail_exec(struct ast_channel *chan, void *data)
|
||||
static int hasvoicemail_internal(char *context, char *box, char *folder)
|
||||
{
|
||||
int res=0;
|
||||
struct localuser *u;
|
||||
char vmpath[256], *input, *varname = NULL, *vmbox, *context = "default";
|
||||
char vmpath[256];
|
||||
DIR *vmdir;
|
||||
struct dirent *vment;
|
||||
int vmcount = 0;
|
||||
int count=0;
|
||||
|
||||
snprintf(vmpath,sizeof(vmpath), "%s/voicemail/%s/%s/%s", (char *)ast_config_AST_SPOOL_DIR, context, box, folder);
|
||||
if ((vmdir = opendir(vmpath))) {
|
||||
/* No matter what the format of VM, there will always be a .txt file for each message. */
|
||||
while ((vment = readdir(vmdir))) {
|
||||
if (!strncmp(vment->d_name + 7, ".txt", 4)) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
closedir(vmdir);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
static int hasvoicemail_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
struct localuser *u;
|
||||
char *input, *varname = NULL, *vmbox, *context = "default";
|
||||
char *vmfolder;
|
||||
int vmcount = 0;
|
||||
static int dep_warning = 0;
|
||||
int priority_jump = 0;
|
||||
char tmp[12];
|
||||
AST_DECLARE_APP_ARGS(args,
|
||||
AST_APP_ARG(vmbox);
|
||||
AST_APP_ARG(varname);
|
||||
AST_APP_ARG(options);
|
||||
);
|
||||
|
||||
if (!dep_warning) {
|
||||
ast_log(LOG_WARNING, "The applications HasVoicemail and HasNewVoicemail have been deprecated. Please use the VMCOUNT() function instead.\n");
|
||||
dep_warning = 1;
|
||||
}
|
||||
|
||||
if (!data) {
|
||||
ast_log(LOG_WARNING, "HasNewVoicemail requires an argument (vm-box[@context]|varname)\n");
|
||||
ast_log(LOG_WARNING, "HasVoicemail requires an argument (vm-box[/folder][@context][|varname[|options]])\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
input = ast_strdupa((char *)data);
|
||||
if (input) {
|
||||
if ((vmbox = strsep(&input,"|")))
|
||||
varname = input;
|
||||
else
|
||||
vmbox = input;
|
||||
|
||||
if (index(vmbox,'@')) {
|
||||
context = vmbox;
|
||||
vmbox = strsep(&context,"@");
|
||||
}
|
||||
|
||||
snprintf(vmpath,sizeof(vmpath), "%s/voicemail/%s/%s/INBOX", (char *)ast_config_AST_SPOOL_DIR, context, vmbox);
|
||||
if (!(vmdir = opendir(vmpath))) {
|
||||
ast_log(LOG_NOTICE, "Voice mailbox %s at %s does not exist\n", vmbox, vmpath);
|
||||
} else {
|
||||
|
||||
/* No matter what the format of VM, there will always be a .txt file for each message. */
|
||||
while ((vment = readdir(vmdir)))
|
||||
if (!strncmp(vment->d_name + 7,".txt",4))
|
||||
vmcount++;
|
||||
closedir(vmdir);
|
||||
}
|
||||
/* Set the count in the channel variable */
|
||||
if (varname) {
|
||||
char tmp[12];
|
||||
snprintf(tmp, sizeof(tmp) - 1, "%d", vmcount);
|
||||
pbx_builtin_setvar_helper(chan, varname, tmp);
|
||||
}
|
||||
|
||||
if (vmcount > 0) {
|
||||
/* Branch to the next extension */
|
||||
if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->callerid)) {
|
||||
chan->priority += 100;
|
||||
} else
|
||||
ast_log(LOG_WARNING, "VM box %s@%s has new voicemail, but extension %s, priority %d doesn't exist\n", vmbox, context, chan->exten, chan->priority + 101);
|
||||
}
|
||||
} else {
|
||||
if (! input) {
|
||||
ast_log(LOG_ERROR, "Out of memory error\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
AST_STANDARD_APP_ARGS(args, input);
|
||||
|
||||
if ((vmbox = strsep(&args.vmbox, "@")))
|
||||
if (!ast_strlen_zero(args.vmbox))
|
||||
context = args.vmbox;
|
||||
if (!vmbox)
|
||||
vmbox = args.vmbox;
|
||||
|
||||
vmfolder = strchr(vmbox, '/');
|
||||
if (vmfolder) {
|
||||
*vmfolder = '\0';
|
||||
vmfolder++;
|
||||
} else {
|
||||
vmfolder = "INBOX";
|
||||
}
|
||||
|
||||
if (args.options) {
|
||||
if (strchr(args.options, 'j'))
|
||||
priority_jump = 1;
|
||||
}
|
||||
|
||||
vmcount = hasvoicemail_internal(context, vmbox, vmfolder);
|
||||
/* Set the count in the channel variable */
|
||||
if (varname) {
|
||||
snprintf(tmp, sizeof(tmp), "%d", vmcount);
|
||||
pbx_builtin_setvar_helper(chan, varname, tmp);
|
||||
}
|
||||
|
||||
if (vmcount > 0) {
|
||||
/* Branch to the next extension */
|
||||
if (priority_jump || option_priority_jumping) {
|
||||
if (ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101))
|
||||
ast_log(LOG_WARNING, "VM box %s@%s has new voicemail, but extension %s, priority %d doesn't exist\n", vmbox, context, chan->exten, chan->priority + 101);
|
||||
}
|
||||
}
|
||||
|
||||
snprintf(tmp, sizeof(tmp), "%d", vmcount);
|
||||
pbx_builtin_setvar_helper(chan, "HASVMSTATUS", tmp);
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *acf_vmcount_exec(struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len)
|
||||
{
|
||||
struct localuser *u;
|
||||
char *args, *context, *box, *folder;
|
||||
|
||||
LOCAL_USER_ACF_ADD(u);
|
||||
|
||||
buf[0] = '\0';
|
||||
|
||||
args = ast_strdupa(data);
|
||||
if (!args) {
|
||||
ast_log(LOG_ERROR, "Out of memory");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return buf;
|
||||
}
|
||||
|
||||
box = strsep(&args, "|");
|
||||
if (strchr(box, '@')) {
|
||||
context = box;
|
||||
box = strsep(&context, "@");
|
||||
} else {
|
||||
context = "default";
|
||||
}
|
||||
|
||||
if (args) {
|
||||
folder = args;
|
||||
} else {
|
||||
folder = "INBOX";
|
||||
}
|
||||
|
||||
snprintf(buf, len, "%d", hasvoicemail_internal(context, box, folder));
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
struct ast_custom_function acf_vmcount = {
|
||||
.name = "VMCOUNT",
|
||||
.synopsis = "Counts the voicemail in a specified mailbox",
|
||||
.syntax = "VMCOUNT(vmbox[@context][|folder])",
|
||||
.desc =
|
||||
" context - defaults to \"default\"\n"
|
||||
" folder - defaults to \"INBOX\"\n",
|
||||
.read = acf_vmcount_exec,
|
||||
};
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_custom_function_unregister(&acf_vmcount);
|
||||
res |= ast_unregister_application(app_hasvoicemail);
|
||||
res |= ast_unregister_application(app_hasnewvoicemail);
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app_hasnewvoicemail);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(app_hasnewvoicemail, hasnewvoicemail_exec, hasnewvoicemail_synopsis, hasnewvoicemail_descrip);
|
||||
int res;
|
||||
|
||||
res = ast_custom_function_register(&acf_vmcount);
|
||||
res |= ast_register_application(app_hasvoicemail, hasvoicemail_exec, hasvoicemail_synopsis, hasvoicemail_descrip);
|
||||
res |= ast_register_application(app_hasnewvoicemail, hasvoicemail_exec, hasnewvoicemail_synopsis, hasnewvoicemail_descrip);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
|
||||
225
apps/app_ices.c
Normal file
225
apps/app_ices.c
Normal file
@@ -0,0 +1,225 @@
|
||||
/*
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Copyright (C) 1999 - 2005, Digium, Inc.
|
||||
*
|
||||
* Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief Stream to an icecast server via ICES (see contrib/asterisk-ices.xml)
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/time.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/lock.h"
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/frame.h"
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/translate.h"
|
||||
|
||||
#define ICES "/usr/bin/ices"
|
||||
#define LOCAL_ICES "/usr/local/bin/ices"
|
||||
|
||||
static char *tdesc = "Encode and Stream via icecast and ices";
|
||||
|
||||
static char *app = "ICES";
|
||||
|
||||
static char *synopsis = "Encode and stream using 'ices'";
|
||||
|
||||
static char *descrip =
|
||||
" ICES(config.xml) Streams to an icecast server using ices\n"
|
||||
"(available separately). A configuration file must be supplied\n"
|
||||
"for ices (see examples/asterisk-ices.conf). \n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int icesencode(char *filename, int fd)
|
||||
{
|
||||
int res;
|
||||
int x;
|
||||
res = fork();
|
||||
if (res < 0)
|
||||
ast_log(LOG_WARNING, "Fork failed\n");
|
||||
if (res)
|
||||
return res;
|
||||
dup2(fd, STDIN_FILENO);
|
||||
for (x=STDERR_FILENO + 1;x<256;x++) {
|
||||
if ((x != STDIN_FILENO) && (x != STDOUT_FILENO))
|
||||
close(x);
|
||||
}
|
||||
/* Most commonly installed in /usr/local/bin */
|
||||
execl(ICES, "ices", filename, (char *)NULL);
|
||||
/* But many places has it in /usr/bin */
|
||||
execl(LOCAL_ICES, "ices", filename, (char *)NULL);
|
||||
/* As a last-ditch effort, try to use PATH */
|
||||
execlp("ices", "ices", filename, (char *)NULL);
|
||||
ast_log(LOG_WARNING, "Execute of ices failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int ices_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0;
|
||||
struct localuser *u;
|
||||
int fds[2];
|
||||
int ms = -1;
|
||||
int pid = -1;
|
||||
int flags;
|
||||
int oreadformat;
|
||||
struct timeval last;
|
||||
struct ast_frame *f;
|
||||
char filename[256]="";
|
||||
char *c;
|
||||
|
||||
if (ast_strlen_zero(data)) {
|
||||
ast_log(LOG_WARNING, "ICES requires an argument (configfile.xml)\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
last = ast_tv(0, 0);
|
||||
|
||||
if (pipe(fds)) {
|
||||
ast_log(LOG_WARNING, "Unable to create pipe\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
flags = fcntl(fds[1], F_GETFL);
|
||||
fcntl(fds[1], F_SETFL, flags | O_NONBLOCK);
|
||||
|
||||
ast_stopstream(chan);
|
||||
|
||||
if (chan->_state != AST_STATE_UP)
|
||||
res = ast_answer(chan);
|
||||
|
||||
if (res) {
|
||||
close(fds[0]);
|
||||
close(fds[1]);
|
||||
ast_log(LOG_WARNING, "Answer failed!\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
oreadformat = chan->readformat;
|
||||
res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
|
||||
if (res < 0) {
|
||||
close(fds[0]);
|
||||
close(fds[1]);
|
||||
ast_log(LOG_WARNING, "Unable to set write format to signed linear\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
if (((char *)data)[0] == '/')
|
||||
strncpy(filename, (char *)data, sizeof(filename) - 1);
|
||||
else
|
||||
snprintf(filename, sizeof(filename), "%s/%s", (char *)ast_config_AST_CONFIG_DIR, (char *)data);
|
||||
/* Placeholder for options */
|
||||
c = strchr(filename, '|');
|
||||
if (c)
|
||||
*c = '\0';
|
||||
res = icesencode(filename, fds[0]);
|
||||
close(fds[0]);
|
||||
if (res >= 0) {
|
||||
pid = res;
|
||||
for (;;) {
|
||||
/* Wait for audio, and stream */
|
||||
ms = ast_waitfor(chan, -1);
|
||||
if (ms < 0) {
|
||||
ast_log(LOG_DEBUG, "Hangup detected\n");
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
f = ast_read(chan);
|
||||
if (!f) {
|
||||
ast_log(LOG_DEBUG, "Null frame == hangup() detected\n");
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
if (f->frametype == AST_FRAME_VOICE) {
|
||||
res = write(fds[1], f->data, f->datalen);
|
||||
if (res < 0) {
|
||||
if (errno != EAGAIN) {
|
||||
ast_log(LOG_WARNING, "Write failed to pipe: %s\n", strerror(errno));
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
ast_frfree(f);
|
||||
}
|
||||
}
|
||||
close(fds[1]);
|
||||
|
||||
if (pid > -1)
|
||||
kill(pid, SIGKILL);
|
||||
if (!res && oreadformat)
|
||||
ast_set_read_format(chan, oreadformat);
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app);
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(app, ices_exec, synopsis, descrip);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
115
apps/app_image.c
Executable file → Normal file
115
apps/app_image.c
Executable file → Normal file
@@ -1,27 +1,46 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* App to transmit an image
|
||||
*
|
||||
* Copyright (C) 1999, Mark Spencer
|
||||
* Copyright (C) 1999 - 2005, Digium, Inc.
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
* Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief App to transmit an image
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/translate.h>
|
||||
#include <asterisk/image.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/lock.h"
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/translate.h"
|
||||
#include "asterisk/image.h"
|
||||
#include "asterisk/app.h"
|
||||
#include "asterisk/options.h"
|
||||
|
||||
static char *tdesc = "Image Transmission Application";
|
||||
|
||||
@@ -30,12 +49,15 @@ static char *app = "SendImage";
|
||||
static char *synopsis = "Send an image file";
|
||||
|
||||
static char *descrip =
|
||||
" SendImage(filename): Sends an image on a channel. If the channel\n"
|
||||
"does not support image transport, and there exists a step with\n"
|
||||
"priority n + 101, then execution will continue at that step.\n"
|
||||
"Otherwise, execution will continue at the next priority level.\n"
|
||||
"SendImage only returns 0 if the image was sent correctly or if\n"
|
||||
"the channel does not support image transport, and -1 otherwise.\n";
|
||||
" SendImage(filename): Sends an image on a channel. \n"
|
||||
"If the channel supports image transport but the image send\n"
|
||||
"fails, the channel will be hung up. Otherwise, the dialplan\n"
|
||||
"continues execution.\n"
|
||||
"The option string may contain the following character:\n"
|
||||
" 'j' -- jump to priority n+101 if the channel doesn't support image transport\n"
|
||||
"This application sets the following channel variable upon completion:\n"
|
||||
" SENDIMAGESTATUS The status is the result of the attempt as a text string, one of\n"
|
||||
" OK | NOSUPPORT \n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
@@ -45,26 +67,61 @@ static int sendimage_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res = 0;
|
||||
struct localuser *u;
|
||||
if (!data || !strlen((char *)data)) {
|
||||
ast_log(LOG_WARNING, "SendImage requires an argument (filename)\n");
|
||||
char *parse;
|
||||
int priority_jump = 0;
|
||||
AST_DECLARE_APP_ARGS(args,
|
||||
AST_APP_ARG(filename);
|
||||
AST_APP_ARG(options);
|
||||
);
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
if (!(parse = ast_strdupa(data))) {
|
||||
ast_log(LOG_WARNING, "Memory Error!\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
AST_STANDARD_APP_ARGS(args, parse);
|
||||
|
||||
if (ast_strlen_zero(args.filename)) {
|
||||
ast_log(LOG_WARNING, "SendImage requires an argument (filename[|options])\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (args.options) {
|
||||
if (strchr(args.options, 'j'))
|
||||
priority_jump = 1;
|
||||
}
|
||||
|
||||
if (!ast_supports_images(chan)) {
|
||||
/* Does not support transport */
|
||||
if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->callerid))
|
||||
chan->priority += 100;
|
||||
if (priority_jump || option_priority_jumping)
|
||||
ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
|
||||
pbx_builtin_setvar_helper(chan, "SENDIMAGESTATUS", "NOSUPPORT");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return 0;
|
||||
}
|
||||
res = ast_send_image(chan, data);
|
||||
|
||||
res = ast_send_image(chan, args.filename);
|
||||
|
||||
if (!res)
|
||||
pbx_builtin_setvar_helper(chan, "SENDIMAGESTATUS", "OK");
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app);
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
|
||||
75
apps/app_intercom.c
Executable file → Normal file
75
apps/app_intercom.c
Executable file → Normal file
@@ -1,39 +1,57 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Use /dev/dsp as an intercom.
|
||||
*
|
||||
* Copyright (C) 1999, Mark Spencer
|
||||
* Copyright (C) 1999 - 2005, Digium, Inc.
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
* Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief Use /dev/dsp as an intercom.
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/frame.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/translate.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/time.h>
|
||||
#ifdef __linux__
|
||||
#include <netinet/in.h>
|
||||
|
||||
#if defined(__linux__)
|
||||
#include <linux/soundcard.h>
|
||||
#elif defined(__FreeBSD__)
|
||||
#include <machine/soundcard.h>
|
||||
#include <sys/soundcard.h>
|
||||
#else
|
||||
#include <soundcard.h>
|
||||
#endif
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/lock.h"
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/frame.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/translate.h"
|
||||
|
||||
#ifdef __OpenBSD__
|
||||
#define DEV_DSP "/dev/audio"
|
||||
@@ -51,14 +69,13 @@ static char *app = "Intercom";
|
||||
static char *synopsis = "(Obsolete) Send to Intercom";
|
||||
static char *descrip =
|
||||
" Intercom(): Sends the user to the intercom (i.e. /dev/dsp). This program\n"
|
||||
"is generally considered obselete by the chan_oss module. Returns 0 if the\n"
|
||||
"user exits with a DTMF tone, or -1 if they hangup.\n";
|
||||
"is generally considered obselete by the chan_oss module. User can terminate\n"with a DTMF tone, or by hangup.\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static ast_mutex_t sound_lock = AST_MUTEX_INITIALIZER;
|
||||
AST_MUTEX_DEFINE_STATIC(sound_lock);
|
||||
static int sound = -1;
|
||||
|
||||
static int write_audio(short *data, int len)
|
||||
@@ -141,6 +158,7 @@ static int intercom_exec(struct ast_channel *chan, void *data)
|
||||
res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
|
||||
if (res < 0) {
|
||||
ast_log(LOG_WARNING, "Unable to set format to signed linear on channel %s\n", chan->name);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
/* Read packets from the channel */
|
||||
@@ -168,18 +186,27 @@ static int intercom_exec(struct ast_channel *chan, void *data)
|
||||
res = -1;
|
||||
}
|
||||
}
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
if (!res)
|
||||
ast_set_read_format(chan, oreadformat);
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
int res;
|
||||
|
||||
if (sound > -1)
|
||||
close(sound);
|
||||
return ast_unregister_application(app);
|
||||
|
||||
res = ast_unregister_application(app);
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
|
||||
144
apps/app_ivrdemo.c
Normal file
144
apps/app_ivrdemo.c
Normal file
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Copyright (C) 1999 - 2005, Digium, Inc.
|
||||
*
|
||||
* Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief IVR Demo application
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/lock.h"
|
||||
#include "asterisk/app.h"
|
||||
|
||||
static char *tdesc = "IVR Demo Application";
|
||||
static char *app = "IVRDemo";
|
||||
static char *synopsis =
|
||||
" This is a skeleton application that shows you the basic structure to create your\n"
|
||||
"own asterisk applications and demonstrates the IVR demo.\n";
|
||||
|
||||
static int ivr_demo_func(struct ast_channel *chan, void *data)
|
||||
{
|
||||
ast_verbose("IVR Demo, data is %s!\n", (char *)data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
AST_IVR_DECLARE_MENU(ivr_submenu, "IVR Demo Sub Menu", 0,
|
||||
{
|
||||
{ "s", AST_ACTION_BACKGROUND, "demo-abouttotry" },
|
||||
{ "s", AST_ACTION_WAITOPTION },
|
||||
{ "1", AST_ACTION_PLAYBACK, "digits/1" },
|
||||
{ "1", AST_ACTION_PLAYBACK, "digits/1" },
|
||||
{ "1", AST_ACTION_RESTART },
|
||||
{ "2", AST_ACTION_PLAYLIST, "digits/2;digits/3" },
|
||||
{ "3", AST_ACTION_CALLBACK, ivr_demo_func },
|
||||
{ "4", AST_ACTION_TRANSFER, "demo|s|1" },
|
||||
{ "*", AST_ACTION_REPEAT },
|
||||
{ "#", AST_ACTION_UPONE },
|
||||
{ NULL }
|
||||
});
|
||||
|
||||
AST_IVR_DECLARE_MENU(ivr_demo, "IVR Demo Main Menu", 0,
|
||||
{
|
||||
{ "s", AST_ACTION_BACKGROUND, "demo-congrats" },
|
||||
{ "g", AST_ACTION_BACKGROUND, "demo-instruct" },
|
||||
{ "g", AST_ACTION_WAITOPTION },
|
||||
{ "1", AST_ACTION_PLAYBACK, "digits/1" },
|
||||
{ "1", AST_ACTION_RESTART },
|
||||
{ "2", AST_ACTION_MENU, &ivr_submenu },
|
||||
{ "2", AST_ACTION_RESTART },
|
||||
{ "i", AST_ACTION_PLAYBACK, "invalid" },
|
||||
{ "i", AST_ACTION_REPEAT, (void *)(unsigned long)2 },
|
||||
{ "#", AST_ACTION_EXIT },
|
||||
{ NULL },
|
||||
});
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int skel_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0;
|
||||
struct localuser *u;
|
||||
|
||||
if (ast_strlen_zero(data)) {
|
||||
ast_log(LOG_WARNING, "skel requires an argument (filename)\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
/* Do our thing here */
|
||||
|
||||
if (chan->_state != AST_STATE_UP)
|
||||
res = ast_answer(chan);
|
||||
if (!res)
|
||||
res = ast_ivr_menu_run(chan, &ivr_demo, data);
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app);
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(app, skel_exec, tdesc, synopsis);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
134
apps/app_lookupblacklist.c
Executable file → Normal file
134
apps/app_lookupblacklist.c
Executable file → Normal file
@@ -1,30 +1,49 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* App to lookup the callerid number, and see if it is blacklisted
|
||||
*
|
||||
* Copyright (C) 1999, Mark Spencer
|
||||
* Copyright (C) 1999 - 2005, Digium, Inc.
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
* Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief App to lookup the callerid number, and see if it is blacklisted
|
||||
*
|
||||
* \ingroup applications
|
||||
*
|
||||
*/
|
||||
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/options.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/translate.h>
|
||||
#include <asterisk/image.h>
|
||||
#include <asterisk/callerid.h>
|
||||
#include <asterisk/astdb.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/lock.h"
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/options.h"
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/translate.h"
|
||||
#include "asterisk/image.h"
|
||||
#include "asterisk/callerid.h"
|
||||
#include "asterisk/astdb.h"
|
||||
#include "asterisk/options.h"
|
||||
|
||||
static char *tdesc = "Look up Caller*ID name/number from blacklist database";
|
||||
|
||||
@@ -33,14 +52,14 @@ static char *app = "LookupBlacklist";
|
||||
static char *synopsis = "Look up Caller*ID name/number from blacklist database";
|
||||
|
||||
static char *descrip =
|
||||
" LookupBlacklist: Looks up the Caller*ID number on the active\n"
|
||||
"channel in the Asterisk database (family 'blacklist'). If the\n"
|
||||
"number is found, and if there exists a priority n + 101,\n"
|
||||
"where 'n' is the priority of the current instance, then the\n"
|
||||
"channel will be setup to continue at that priority level.\n"
|
||||
"Otherwise, it returns 0. Does nothing if no Caller*ID was received on the\n"
|
||||
"channel.\n"
|
||||
"Example: database put blacklist <name/number> 1\n";
|
||||
" LookupBlacklist(options): Looks up the Caller*ID number on the active\n"
|
||||
"channel in the Asterisk database (family 'blacklist'). \n"
|
||||
"The option string may contain the following character:\n"
|
||||
" 'j' -- jump to n+101 priority if the number/name is found in the blacklist\n"
|
||||
"This application sets the following channel variable upon completion:\n"
|
||||
" LOOKUPBLSTATUS The status of the Blacklist lookup as a text string, one of\n"
|
||||
" FOUND | NOTFOUND\n"
|
||||
"Example: exten => 1234,1,LookupBlacklist()\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
@@ -49,47 +68,54 @@ LOCAL_USER_DECL;
|
||||
static int
|
||||
lookupblacklist_exec (struct ast_channel *chan, void *data)
|
||||
{
|
||||
char old_cid[144] = "", *num, *name;
|
||||
char blacklist[1];
|
||||
char shrunknum[64] = "";
|
||||
struct localuser *u;
|
||||
int bl = 0;
|
||||
int priority_jump = 0;
|
||||
|
||||
LOCAL_USER_ADD (u);
|
||||
if (chan->callerid)
|
||||
{
|
||||
strncpy (old_cid, chan->callerid, sizeof (old_cid) - 1);
|
||||
ast_callerid_parse (old_cid, &name, &num);
|
||||
if (num)
|
||||
strncpy (shrunknum, num, sizeof (shrunknum) - 1);
|
||||
else
|
||||
num = shrunknum;
|
||||
|
||||
ast_shrink_phone_number (shrunknum);
|
||||
if (!ast_db_get ("blacklist", shrunknum, blacklist, sizeof (blacklist)))
|
||||
{
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
if (!ast_strlen_zero(data)) {
|
||||
if (strchr(data, 'j'))
|
||||
priority_jump = 1;
|
||||
}
|
||||
|
||||
if (chan->cid.cid_num) {
|
||||
if (!ast_db_get("blacklist", chan->cid.cid_num, blacklist, sizeof (blacklist))) {
|
||||
if (option_verbose > 2)
|
||||
ast_log(LOG_NOTICE, "Blacklisted number %s found\n",shrunknum);
|
||||
bl = 1;
|
||||
}
|
||||
else if (!ast_db_get ("blacklist", name, blacklist, sizeof (blacklist)))
|
||||
{
|
||||
if (option_verbose > 2)
|
||||
ast_log (LOG_NOTICE,"Blacklisted name \"%s\" found\n",name);
|
||||
ast_log(LOG_NOTICE, "Blacklisted number %s found\n",chan->cid.cid_num);
|
||||
bl = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (bl && ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->callerid))
|
||||
chan->priority+=100;
|
||||
LOCAL_USER_REMOVE (u);
|
||||
if (chan->cid.cid_name) {
|
||||
if (!ast_db_get("blacklist", chan->cid.cid_name, blacklist, sizeof (blacklist))) {
|
||||
if (option_verbose > 2)
|
||||
ast_log (LOG_NOTICE,"Blacklisted name \"%s\" found\n",chan->cid.cid_name);
|
||||
bl = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (bl) {
|
||||
if (priority_jump || option_priority_jumping)
|
||||
ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
|
||||
pbx_builtin_setvar_helper(chan, "LOOKUPBLSTATUS", "FOUND");
|
||||
} else
|
||||
pbx_builtin_setvar_helper(chan, "LOOKUPBLSTATUS", "NOTFOUND");
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int unload_module (void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app);
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application (app);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module (void)
|
||||
|
||||
94
apps/app_lookupcidname.c
Executable file → Normal file
94
apps/app_lookupcidname.c
Executable file → Normal file
@@ -1,30 +1,47 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* App to set callerid name from database, based on directory number
|
||||
*
|
||||
* Copyright (C) 1999, Mark Spencer
|
||||
* Copyright (C) 1999 - 2005, Digium, Inc.
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
* Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief App to set callerid name from database, based on directory number
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/options.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/translate.h>
|
||||
#include <asterisk/image.h>
|
||||
#include <asterisk/callerid.h>
|
||||
#include <asterisk/astdb.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/lock.h"
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/options.h"
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/translate.h"
|
||||
#include "asterisk/image.h"
|
||||
#include "asterisk/callerid.h"
|
||||
#include "asterisk/astdb.h"
|
||||
|
||||
static char *tdesc = "Look up CallerID Name from local database";
|
||||
|
||||
@@ -38,7 +55,7 @@ static char *descrip =
|
||||
"Caller*ID name. Does nothing if no Caller*ID was received on the\n"
|
||||
"channel. This is useful if you do not subscribe to Caller*ID\n"
|
||||
"name delivery, or if you want to change the names on some incoming\n"
|
||||
"calls. Always returns 0.\n";
|
||||
"calls.\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
@@ -47,32 +64,18 @@ LOCAL_USER_DECL;
|
||||
static int
|
||||
lookupcidname_exec (struct ast_channel *chan, void *data)
|
||||
{
|
||||
char old_cid[144] = "", *num, *name;
|
||||
char new_cid[144];
|
||||
char dbname[64];
|
||||
char shrunknum[64] = "";
|
||||
struct localuser *u;
|
||||
|
||||
LOCAL_USER_ADD (u);
|
||||
if (chan->callerid)
|
||||
{
|
||||
strncpy (old_cid, chan->callerid, sizeof (old_cid) - 1);
|
||||
ast_callerid_parse (old_cid, &name, &num); /* this destroys the original string */
|
||||
if (num) /* It's possible to get an empty number */
|
||||
strncpy (shrunknum, num, sizeof (shrunknum) - 1);
|
||||
else
|
||||
num = shrunknum;
|
||||
ast_shrink_phone_number (shrunknum);
|
||||
if (!ast_db_get ("cidname", shrunknum, dbname, sizeof (dbname)))
|
||||
{
|
||||
snprintf (new_cid, sizeof (new_cid), "\"%s\" <%s>", dbname, num);
|
||||
ast_set_callerid (chan, new_cid, 0);
|
||||
if (option_verbose > 2)
|
||||
ast_verbose (VERBOSE_PREFIX_3 "Changed Caller*ID to %s\n",
|
||||
new_cid);
|
||||
if (chan->cid.cid_num) {
|
||||
if (!ast_db_get ("cidname", chan->cid.cid_num, dbname, sizeof (dbname))) {
|
||||
ast_set_callerid (chan, NULL, dbname, NULL);
|
||||
if (option_verbose > 2)
|
||||
ast_verbose (VERBOSE_PREFIX_3 "Changed Caller*ID name to %s\n",
|
||||
dbname);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
LOCAL_USER_REMOVE (u);
|
||||
return 0;
|
||||
}
|
||||
@@ -80,8 +83,13 @@ lookupcidname_exec (struct ast_channel *chan, void *data)
|
||||
int
|
||||
unload_module (void)
|
||||
{
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application (app);
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application (app);
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int
|
||||
|
||||
504
apps/app_macro.c
Executable file → Normal file
504
apps/app_macro.c
Executable file → Normal file
@@ -1,50 +1,87 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Macro Implementation
|
||||
*
|
||||
* Copyright (C) 2003, Digium
|
||||
* Copyright (C) 1999 - 2005, Digium, Inc.
|
||||
*
|
||||
* Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/options.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
/*! \file
|
||||
*
|
||||
* \brief Dial plan macro Implementation
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/options.h"
|
||||
#include "asterisk/config.h"
|
||||
#include "asterisk/utils.h"
|
||||
#include "asterisk/lock.h"
|
||||
|
||||
#define MAX_ARGS 80
|
||||
|
||||
/* special result value used to force macro exit */
|
||||
#define MACRO_EXIT_RESULT 1024
|
||||
|
||||
static char *tdesc = "Extension Macros";
|
||||
|
||||
static char *descrip =
|
||||
" Macro(macroname|arg1|arg2...): Executes a macro using the context\n"
|
||||
"'macro-<macroname>', jumping to the 's' extension of that context and\n"
|
||||
"executing each step, then returning when the steps end. The calling\n"
|
||||
"extension, context, and priority are stored in ${MACRO_EXTEN}, \n"
|
||||
"executing each step, then returning when the steps end. \n"
|
||||
"The calling extension, context, and priority are stored in ${MACRO_EXTEN}, \n"
|
||||
"${MACRO_CONTEXT} and ${MACRO_PRIORITY} respectively. Arguments become\n"
|
||||
"${ARG1}, ${ARG2}, etc in the macro context. Macro returns -1 if\n"
|
||||
"any step in the macro returns -1, and 0 otherwise. If you Goto out\n"
|
||||
"of the Macro context, the Macro will terminate and control will be return\n"
|
||||
"at the location of the Goto. Otherwise if ${MACRO_OFFSET} is set at\n"
|
||||
"termination, Macro will attempt to continue at priority\n"
|
||||
"MACRO_OFFSET + N + 1 if such a step exists, and N + 1 otherwise.\n";
|
||||
"${ARG1}, ${ARG2}, etc in the macro context.\n"
|
||||
"If you Goto out of the Macro context, the Macro will terminate and control\n"
|
||||
"will be returned at the location of the Goto.\n"
|
||||
"If ${MACRO_OFFSET} is set at termination, Macro will attempt to continue\n"
|
||||
"at priority MACRO_OFFSET + N + 1 if such a step exists, and N + 1 otherwise.\n";
|
||||
|
||||
static char *if_descrip =
|
||||
" MacroIf(<expr>?macroname_a[|arg1][:macroname_b[|arg1]])\n"
|
||||
"Executes macro defined in <macroname_a> if <expr> is true\n"
|
||||
"(otherwise <macroname_b> if provided)\n"
|
||||
"Arguments and return values as in application macro()\n";
|
||||
|
||||
static char *exit_descrip =
|
||||
" MacroExit():\n"
|
||||
"Causes the currently running macro to exit as if it had\n"
|
||||
"ended normally by running out of priorities to execute.\n"
|
||||
"If used outside a macro, will likely cause unexpected\n"
|
||||
"behavior.\n";
|
||||
|
||||
static char *app = "Macro";
|
||||
static char *if_app = "MacroIf";
|
||||
static char *exit_app = "MacroExit";
|
||||
|
||||
static char *synopsis = "Macro Implementation";
|
||||
static char *if_synopsis = "Conditional Macro Implementation";
|
||||
static char *exit_synopsis = "Exit From Macro";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
@@ -52,185 +89,284 @@ LOCAL_USER_DECL;
|
||||
|
||||
static int macro_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
char tmp[256] = "";
|
||||
char *cur, *rest;
|
||||
char *macro;
|
||||
char fullmacro[80];
|
||||
char varname[80];
|
||||
char *oldargs[MAX_ARGS + 1] = { NULL, };
|
||||
int argc, x;
|
||||
int res=0;
|
||||
char oldexten[256]="";
|
||||
int oldpriority;
|
||||
char pc[80];
|
||||
char oldcontext[256] = "";
|
||||
char *offsets;
|
||||
int offset;
|
||||
int setmacrocontext=0;
|
||||
char *tmp;
|
||||
char *cur, *rest;
|
||||
char *macro;
|
||||
char fullmacro[80];
|
||||
char varname[80];
|
||||
char *oldargs[MAX_ARGS + 1] = { NULL, };
|
||||
int argc, x;
|
||||
int res=0;
|
||||
char oldexten[256]="";
|
||||
int oldpriority;
|
||||
char pc[80], depthc[12];
|
||||
char oldcontext[AST_MAX_CONTEXT] = "";
|
||||
char *offsets;
|
||||
int offset, depth;
|
||||
int setmacrocontext=0;
|
||||
int autoloopflag;
|
||||
|
||||
char *save_macro_exten;
|
||||
char *save_macro_context;
|
||||
char *save_macro_priority;
|
||||
char *save_macro_offset;
|
||||
|
||||
if (!data || !strlen(data)) {
|
||||
ast_log(LOG_WARNING, "Invalid Macro incantation\n");
|
||||
return 0;
|
||||
}
|
||||
strncpy(tmp, data, sizeof(tmp) - 1);
|
||||
rest = tmp;
|
||||
macro = strsep(&rest, "|");
|
||||
if (!macro || !strlen(macro)) {
|
||||
ast_log(LOG_WARNING, "Invalid macro name specified\n");
|
||||
return 0;
|
||||
}
|
||||
snprintf(fullmacro, sizeof(fullmacro), "macro-%s", macro);
|
||||
if (!ast_exists_extension(chan, fullmacro, "s", 1, chan->callerid)) {
|
||||
if (!ast_context_find(fullmacro))
|
||||
ast_log(LOG_WARNING, "No such context '%s' for macro '%s'\n", fullmacro, macro);
|
||||
else
|
||||
ast_log(LOG_WARNING, "Context '%s' for macro '%s' lacks 's' extension, priority 1\n", fullmacro, macro);
|
||||
return 0;
|
||||
}
|
||||
/* Save old info */
|
||||
oldpriority = chan->priority;
|
||||
strncpy(oldexten, chan->exten, sizeof(oldexten) - 1);
|
||||
strncpy(oldcontext, chan->context, sizeof(oldcontext) - 1);
|
||||
if (!strlen(chan->macrocontext)) {
|
||||
strncpy(chan->macrocontext, chan->context, sizeof(chan->macrocontext) - 1);
|
||||
strncpy(chan->macroexten, chan->exten, sizeof(chan->macroexten) - 1);
|
||||
chan->macropriority = chan->priority;
|
||||
setmacrocontext=1;
|
||||
}
|
||||
argc = 1;
|
||||
/* Save old macro variables */
|
||||
save_macro_exten = pbx_builtin_getvar_helper(chan, "MACRO_EXTEN");
|
||||
if (save_macro_exten) save_macro_exten = strdup(save_macro_exten);
|
||||
pbx_builtin_setvar_helper(chan, "MACRO_EXTEN", oldexten);
|
||||
|
||||
save_macro_context = pbx_builtin_getvar_helper(chan, "MACRO_CONTEXT");
|
||||
if (save_macro_context) save_macro_context = strdup(save_macro_context);
|
||||
pbx_builtin_setvar_helper(chan, "MACRO_CONTEXT", oldcontext);
|
||||
|
||||
save_macro_priority = pbx_builtin_getvar_helper(chan, "MACRO_PRIORITY");
|
||||
if (save_macro_priority) save_macro_priority = strdup(save_macro_priority);
|
||||
snprintf(pc, sizeof(pc), "%d", oldpriority);
|
||||
pbx_builtin_setvar_helper(chan, "MACRO_PRIORITY", pc);
|
||||
|
||||
save_macro_offset = pbx_builtin_getvar_helper(chan, "MACRO_OFFSET");
|
||||
if (save_macro_offset) save_macro_offset = strdup(save_macro_offset);
|
||||
pbx_builtin_setvar_helper(chan, "MACRO_OFFSET", NULL);
|
||||
|
||||
/* Setup environment for new run */
|
||||
strcpy(chan->exten, "s");
|
||||
strncpy(chan->context, fullmacro, sizeof(chan->context));
|
||||
chan->priority = 1;
|
||||
|
||||
while((cur = strsep(&rest, "|")) && (argc < MAX_ARGS)) {
|
||||
/* Save copy of old arguments if we're overwriting some, otherwise
|
||||
let them pass through to the other macro */
|
||||
snprintf(varname, sizeof(varname), "ARG%d", argc);
|
||||
oldargs[argc] = pbx_builtin_getvar_helper(chan, varname);
|
||||
if (oldargs[argc])
|
||||
oldargs[argc] = strdup(oldargs[argc]);
|
||||
pbx_builtin_setvar_helper(chan, varname, cur);
|
||||
argc++;
|
||||
}
|
||||
while(ast_exists_extension(chan, chan->context, chan->exten, chan->priority, chan->callerid)) {
|
||||
if ((res = ast_spawn_extension(chan, chan->context, chan->exten, chan->priority, chan->callerid))) {
|
||||
/* Something bad happened, or a hangup has been requested. */
|
||||
if (((res >= '0') && (res <= '9')) || ((res >= 'A') && (res <= 'F'))) {
|
||||
/* Just return result as to the previous application as if it had been dialed */
|
||||
ast_log(LOG_DEBUG, "Oooh, got something to jump out with ('%c')!\n", res);
|
||||
break;
|
||||
}
|
||||
switch(res) {
|
||||
case AST_PBX_KEEPALIVE:
|
||||
if (option_debug)
|
||||
ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited KEEPALIVE in macro %s on '%s'\n", chan->context, chan->exten, chan->priority, macro, chan->name);
|
||||
else if (option_verbose > 1)
|
||||
ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited KEEPALIVE in macro '%s' on '%s'\n", chan->context, chan->exten, chan->priority, macro, chan->name);
|
||||
goto out;
|
||||
break;
|
||||
default:
|
||||
if (option_debug)
|
||||
ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s' in macro '%s'\n", chan->context, chan->exten, chan->priority, chan->name, macro);
|
||||
else if (option_verbose > 1)
|
||||
ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s' in macro '%s'\n", chan->context, chan->exten, chan->priority, chan->name, macro);
|
||||
goto out;
|
||||
}
|
||||
char *save_macro_exten;
|
||||
char *save_macro_context;
|
||||
char *save_macro_priority;
|
||||
char *save_macro_offset;
|
||||
struct localuser *u;
|
||||
|
||||
if (ast_strlen_zero(data)) {
|
||||
ast_log(LOG_WARNING, "Macro() requires arguments. See \"show application macro\" for help.\n");
|
||||
return -1;
|
||||
}
|
||||
if (strcasecmp(chan->context, fullmacro)) {
|
||||
if (option_verbose > 1)
|
||||
ast_verbose(VERBOSE_PREFIX_2 "Channel '%s' jumping out of macro '%s'\n", chan->name, macro);
|
||||
break;
|
||||
}
|
||||
/* don't stop executing extensions when we're in "h" */
|
||||
if (chan->_softhangup && strcasecmp(oldexten,"h")) {
|
||||
ast_log(LOG_DEBUG, "Extension %s, priority %d returned normally even though call was hung up\n",
|
||||
chan->exten, chan->priority);
|
||||
goto out;
|
||||
}
|
||||
chan->priority++;
|
||||
}
|
||||
out:
|
||||
for (x=1;x<argc;x++) {
|
||||
/* Restore old arguments and delete ours */
|
||||
snprintf(varname, sizeof(varname), "ARG%d", x);
|
||||
if (oldargs[x]) {
|
||||
pbx_builtin_setvar_helper(chan, varname, oldargs[x]);
|
||||
free(oldargs[x]);
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
/* Count how many levels deep the rabbit hole goes */
|
||||
tmp = pbx_builtin_getvar_helper(chan, "MACRO_DEPTH");
|
||||
if (tmp) {
|
||||
sscanf(tmp, "%d", &depth);
|
||||
} else {
|
||||
pbx_builtin_setvar_helper(chan, varname, NULL);
|
||||
depth = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Restore macro variables */
|
||||
pbx_builtin_setvar_helper(chan, "MACRO_EXTEN", save_macro_exten);
|
||||
if (save_macro_exten) free(save_macro_exten);
|
||||
pbx_builtin_setvar_helper(chan, "MACRO_CONTEXT", save_macro_context);
|
||||
if (save_macro_context) free(save_macro_context);
|
||||
pbx_builtin_setvar_helper(chan, "MACRO_PRIORITY", save_macro_priority);
|
||||
if (save_macro_priority) free(save_macro_priority);
|
||||
if (setmacrocontext) {
|
||||
strcpy(chan->macrocontext, "");
|
||||
strcpy(chan->macroexten, "");
|
||||
chan->macropriority = 0;
|
||||
}
|
||||
if (depth >= 7) {
|
||||
ast_log(LOG_ERROR, "Macro(): possible infinite loop detected. Returning early.\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return 0;
|
||||
}
|
||||
snprintf(depthc, sizeof(depthc), "%d", depth + 1);
|
||||
pbx_builtin_setvar_helper(chan, "MACRO_DEPTH", depthc);
|
||||
|
||||
if (!strcasecmp(chan->context, fullmacro)) {
|
||||
/* If we're leaving the macro normally, restore original information */
|
||||
chan->priority = oldpriority;
|
||||
strncpy(chan->context, oldcontext, sizeof(chan->context) - 1);
|
||||
if (!chan->_softhangup) {
|
||||
/* Copy the extension, so long as we're not in softhangup, where we could be given an asyncgoto */
|
||||
strncpy(chan->exten, oldexten, sizeof(chan->exten) - 1);
|
||||
if ((offsets = pbx_builtin_getvar_helper(chan, "MACRO_OFFSET"))) {
|
||||
/* Handle macro offset if it's set by checking the availability of step n + offset + 1, otherwise continue
|
||||
normally if there is any problem */
|
||||
if (sscanf(offsets, "%d", &offset) == 1) {
|
||||
if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + offset + 1, chan->callerid)) {
|
||||
chan->priority += offset;
|
||||
tmp = ast_strdupa(data);
|
||||
rest = tmp;
|
||||
macro = strsep(&rest, "|");
|
||||
if (ast_strlen_zero(macro)) {
|
||||
ast_log(LOG_WARNING, "Invalid macro name specified\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return 0;
|
||||
}
|
||||
snprintf(fullmacro, sizeof(fullmacro), "macro-%s", macro);
|
||||
if (!ast_exists_extension(chan, fullmacro, "s", 1, chan->cid.cid_num)) {
|
||||
if (!ast_context_find(fullmacro))
|
||||
ast_log(LOG_WARNING, "No such context '%s' for macro '%s'\n", fullmacro, macro);
|
||||
else
|
||||
ast_log(LOG_WARNING, "Context '%s' for macro '%s' lacks 's' extension, priority 1\n", fullmacro, macro);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Save old info */
|
||||
oldpriority = chan->priority;
|
||||
ast_copy_string(oldexten, chan->exten, sizeof(oldexten));
|
||||
ast_copy_string(oldcontext, chan->context, sizeof(oldcontext));
|
||||
if (ast_strlen_zero(chan->macrocontext)) {
|
||||
ast_copy_string(chan->macrocontext, chan->context, sizeof(chan->macrocontext));
|
||||
ast_copy_string(chan->macroexten, chan->exten, sizeof(chan->macroexten));
|
||||
chan->macropriority = chan->priority;
|
||||
setmacrocontext=1;
|
||||
}
|
||||
argc = 1;
|
||||
/* Save old macro variables */
|
||||
save_macro_exten = pbx_builtin_getvar_helper(chan, "MACRO_EXTEN");
|
||||
if (save_macro_exten)
|
||||
save_macro_exten = strdup(save_macro_exten);
|
||||
pbx_builtin_setvar_helper(chan, "MACRO_EXTEN", oldexten);
|
||||
|
||||
save_macro_context = pbx_builtin_getvar_helper(chan, "MACRO_CONTEXT");
|
||||
if (save_macro_context)
|
||||
save_macro_context = strdup(save_macro_context);
|
||||
pbx_builtin_setvar_helper(chan, "MACRO_CONTEXT", oldcontext);
|
||||
|
||||
save_macro_priority = pbx_builtin_getvar_helper(chan, "MACRO_PRIORITY");
|
||||
if (save_macro_priority)
|
||||
save_macro_priority = strdup(save_macro_priority);
|
||||
snprintf(pc, sizeof(pc), "%d", oldpriority);
|
||||
pbx_builtin_setvar_helper(chan, "MACRO_PRIORITY", pc);
|
||||
|
||||
save_macro_offset = pbx_builtin_getvar_helper(chan, "MACRO_OFFSET");
|
||||
if (save_macro_offset)
|
||||
save_macro_offset = strdup(save_macro_offset);
|
||||
pbx_builtin_setvar_helper(chan, "MACRO_OFFSET", NULL);
|
||||
|
||||
/* Setup environment for new run */
|
||||
chan->exten[0] = 's';
|
||||
chan->exten[1] = '\0';
|
||||
ast_copy_string(chan->context, fullmacro, sizeof(chan->context));
|
||||
chan->priority = 1;
|
||||
|
||||
while((cur = strsep(&rest, "|")) && (argc < MAX_ARGS)) {
|
||||
/* Save copy of old arguments if we're overwriting some, otherwise
|
||||
let them pass through to the other macro */
|
||||
snprintf(varname, sizeof(varname), "ARG%d", argc);
|
||||
oldargs[argc] = pbx_builtin_getvar_helper(chan, varname);
|
||||
if (oldargs[argc])
|
||||
oldargs[argc] = strdup(oldargs[argc]);
|
||||
pbx_builtin_setvar_helper(chan, varname, cur);
|
||||
argc++;
|
||||
}
|
||||
autoloopflag = ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP);
|
||||
ast_set_flag(chan, AST_FLAG_IN_AUTOLOOP);
|
||||
while(ast_exists_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num)) {
|
||||
/* Reset the macro depth, if it was changed in the last iteration */
|
||||
pbx_builtin_setvar_helper(chan, "MACRO_DEPTH", depthc);
|
||||
if ((res = ast_spawn_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num))) {
|
||||
/* Something bad happened, or a hangup has been requested. */
|
||||
if (((res >= '0') && (res <= '9')) || ((res >= 'A') && (res <= 'F')) ||
|
||||
(res == '*') || (res == '#')) {
|
||||
/* Just return result as to the previous application as if it had been dialed */
|
||||
ast_log(LOG_DEBUG, "Oooh, got something to jump out with ('%c')!\n", res);
|
||||
break;
|
||||
}
|
||||
switch(res) {
|
||||
case MACRO_EXIT_RESULT:
|
||||
res = 0;
|
||||
goto out;
|
||||
case AST_PBX_KEEPALIVE:
|
||||
if (option_debug)
|
||||
ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited KEEPALIVE in macro %s on '%s'\n", chan->context, chan->exten, chan->priority, macro, chan->name);
|
||||
else if (option_verbose > 1)
|
||||
ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited KEEPALIVE in macro '%s' on '%s'\n", chan->context, chan->exten, chan->priority, macro, chan->name);
|
||||
goto out;
|
||||
break;
|
||||
default:
|
||||
if (option_debug)
|
||||
ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s' in macro '%s'\n", chan->context, chan->exten, chan->priority, chan->name, macro);
|
||||
else if (option_verbose > 1)
|
||||
ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s' in macro '%s'\n", chan->context, chan->exten, chan->priority, chan->name, macro);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
if (strcasecmp(chan->context, fullmacro)) {
|
||||
if (option_verbose > 1)
|
||||
ast_verbose(VERBOSE_PREFIX_2 "Channel '%s' jumping out of macro '%s'\n", chan->name, macro);
|
||||
break;
|
||||
}
|
||||
/* don't stop executing extensions when we're in "h" */
|
||||
if (chan->_softhangup && strcasecmp(oldexten,"h")) {
|
||||
ast_log(LOG_DEBUG, "Extension %s, priority %d returned normally even though call was hung up\n",
|
||||
chan->exten, chan->priority);
|
||||
goto out;
|
||||
}
|
||||
chan->priority++;
|
||||
}
|
||||
out:
|
||||
/* Reset the depth back to what it was when the routine was entered (like if we called Macro recursively) */
|
||||
snprintf(depthc, sizeof(depthc), "%d", depth);
|
||||
pbx_builtin_setvar_helper(chan, "MACRO_DEPTH", depthc);
|
||||
|
||||
ast_set2_flag(chan, autoloopflag, AST_FLAG_IN_AUTOLOOP);
|
||||
for (x=1; x<argc; x++) {
|
||||
/* Restore old arguments and delete ours */
|
||||
snprintf(varname, sizeof(varname), "ARG%d", x);
|
||||
if (oldargs[x]) {
|
||||
pbx_builtin_setvar_helper(chan, varname, oldargs[x]);
|
||||
free(oldargs[x]);
|
||||
} else {
|
||||
pbx_builtin_setvar_helper(chan, varname, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* Restore macro variables */
|
||||
pbx_builtin_setvar_helper(chan, "MACRO_EXTEN", save_macro_exten);
|
||||
if (save_macro_exten)
|
||||
free(save_macro_exten);
|
||||
pbx_builtin_setvar_helper(chan, "MACRO_CONTEXT", save_macro_context);
|
||||
if (save_macro_context)
|
||||
free(save_macro_context);
|
||||
pbx_builtin_setvar_helper(chan, "MACRO_PRIORITY", save_macro_priority);
|
||||
if (save_macro_priority)
|
||||
free(save_macro_priority);
|
||||
if (setmacrocontext) {
|
||||
chan->macrocontext[0] = '\0';
|
||||
chan->macroexten[0] = '\0';
|
||||
chan->macropriority = 0;
|
||||
}
|
||||
|
||||
if (!strcasecmp(chan->context, fullmacro)) {
|
||||
/* If we're leaving the macro normally, restore original information */
|
||||
chan->priority = oldpriority;
|
||||
ast_copy_string(chan->context, oldcontext, sizeof(chan->context));
|
||||
if (!(chan->_softhangup & AST_SOFTHANGUP_ASYNCGOTO)) {
|
||||
/* Copy the extension, so long as we're not in softhangup, where we could be given an asyncgoto */
|
||||
ast_copy_string(chan->exten, oldexten, sizeof(chan->exten));
|
||||
if ((offsets = pbx_builtin_getvar_helper(chan, "MACRO_OFFSET"))) {
|
||||
/* Handle macro offset if it's set by checking the availability of step n + offset + 1, otherwise continue
|
||||
normally if there is any problem */
|
||||
if (sscanf(offsets, "%d", &offset) == 1) {
|
||||
if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + offset + 1, chan->cid.cid_num)) {
|
||||
chan->priority += offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pbx_builtin_setvar_helper(chan, "MACRO_OFFSET", save_macro_offset);
|
||||
if (save_macro_offset) free(save_macro_offset);
|
||||
return res;
|
||||
pbx_builtin_setvar_helper(chan, "MACRO_OFFSET", save_macro_offset);
|
||||
if (save_macro_offset)
|
||||
free(save_macro_offset);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int macroif_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
char *expr = NULL, *label_a = NULL, *label_b = NULL;
|
||||
int res = 0;
|
||||
struct localuser *u;
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
expr = ast_strdupa(data);
|
||||
if (!expr) {
|
||||
ast_log(LOG_ERROR, "Out of Memory!\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((label_a = strchr(expr, '?'))) {
|
||||
*label_a = '\0';
|
||||
label_a++;
|
||||
if ((label_b = strchr(label_a, ':'))) {
|
||||
*label_b = '\0';
|
||||
label_b++;
|
||||
}
|
||||
if (ast_true(expr))
|
||||
macro_exec(chan, label_a);
|
||||
else if (label_b)
|
||||
macro_exec(chan, label_b);
|
||||
} else
|
||||
ast_log(LOG_WARNING, "Invalid Syntax.\n");
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int macro_exit_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
return MACRO_EXIT_RESULT;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(if_app);
|
||||
res |= ast_unregister_application(exit_app);
|
||||
res |= ast_unregister_application(app);
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(app, macro_exec, synopsis, descrip);
|
||||
int res;
|
||||
|
||||
res = ast_register_application(exit_app, macro_exit_exec, exit_synopsis, exit_descrip);
|
||||
res |= ast_register_application(if_app, macroif_exec, if_synopsis, if_descrip);
|
||||
res |= ast_register_application(app, macro_exec, synopsis, descrip);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
|
||||
297
apps/app_math.c
Normal file
297
apps/app_math.c
Normal file
@@ -0,0 +1,297 @@
|
||||
/*
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Copyright (C) 2004 - 2005, Andy Powell
|
||||
*
|
||||
* Updated by Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief A simple math application
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
#include <dirent.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/file.h>
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/lock.h"
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/options.h"
|
||||
#include "asterisk/config.h"
|
||||
#include "asterisk/say.h"
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/app.h"
|
||||
#include "asterisk/manager.h"
|
||||
#include "asterisk/localtime.h"
|
||||
#include "asterisk/cli.h"
|
||||
#include "asterisk/utils.h"
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/translate.h"
|
||||
|
||||
static char *tdesc = "Basic Math Functions";
|
||||
|
||||
static char *app_math = "Math";
|
||||
|
||||
static char *math_synopsis = "Performs Mathematical Functions";
|
||||
|
||||
static char *math_descrip =
|
||||
"Math(returnvar,<number1><op><number 2>\n\n"
|
||||
"Perform floating point calculation on number 1 to number 2 and \n"
|
||||
"store the result in returnvar. Valid ops are: \n"
|
||||
" +,-,/,*,%,<,>,>=,<=,==\n"
|
||||
"and behave as their C equivalents.\n";
|
||||
|
||||
#define ADDFUNCTION 0
|
||||
#define DIVIDEFUNCTION 1
|
||||
#define MULTIPLYFUNCTION 2
|
||||
#define SUBTRACTFUNCTION 3
|
||||
#define MODULUSFUNCTION 4
|
||||
|
||||
#define GTFUNCTION 5
|
||||
#define LTFUNCTION 6
|
||||
#define GTEFUNCTION 7
|
||||
#define LTEFUNCTION 8
|
||||
#define EQFUNCTION 9
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int math_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
float fnum1;
|
||||
float fnum2;
|
||||
float ftmp = 0;
|
||||
char *op;
|
||||
int iaction=-1;
|
||||
static int deprecation_warning = 0;
|
||||
|
||||
/* dunno, big calulations :D */
|
||||
char user_result[30];
|
||||
|
||||
char *s;
|
||||
char *mvar, *mvalue1, *mvalue2=NULL;
|
||||
|
||||
struct localuser *u;
|
||||
|
||||
if (!deprecation_warning) {
|
||||
ast_log(LOG_WARNING, "Math() is deprecated, please use Set(var=${MATH(...)} instead.\n");
|
||||
deprecation_warning = 1;
|
||||
}
|
||||
|
||||
if (ast_strlen_zero(data)) {
|
||||
ast_log(LOG_WARNING, "No parameters passed. !\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
s = ast_strdupa(data);
|
||||
if (!s) {
|
||||
ast_log(LOG_ERROR, "Out of memory\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
mvar = strsep(&s, "|");
|
||||
mvalue1 = strsep(&s, "|");
|
||||
|
||||
if ((op = strchr(mvalue1, '+'))) {
|
||||
iaction = ADDFUNCTION;
|
||||
*op = '\0';
|
||||
} else if ((op = strchr(mvalue1, '-'))) {
|
||||
iaction = SUBTRACTFUNCTION;
|
||||
*op = '\0';
|
||||
} else if ((op = strchr(mvalue1, '*'))) {
|
||||
iaction = MULTIPLYFUNCTION;
|
||||
*op = '\0';
|
||||
} else if ((op = strchr(mvalue1, '/'))) {
|
||||
iaction = DIVIDEFUNCTION;
|
||||
*op = '\0';
|
||||
} else if ((op = strchr(mvalue1, '>'))) {
|
||||
iaction = GTFUNCTION;
|
||||
*op = '\0';
|
||||
if (*(op+1) == '=') {
|
||||
op++;
|
||||
*op = '\0';
|
||||
iaction = GTEFUNCTION;
|
||||
}
|
||||
} else if ((op = strchr(mvalue1, '<'))) {
|
||||
iaction = LTFUNCTION;
|
||||
*op = '\0';
|
||||
if (*(op+1) == '=') {
|
||||
op++;
|
||||
*op = '\0';
|
||||
iaction = LTEFUNCTION;
|
||||
}
|
||||
} else if ((op = strchr(mvalue1, '='))) {
|
||||
iaction = GTFUNCTION;
|
||||
*op = '\0';
|
||||
if (*(op+1) == '=') {
|
||||
op++;
|
||||
*op = '\0';
|
||||
iaction = EQFUNCTION;
|
||||
} else
|
||||
op = NULL;
|
||||
}
|
||||
|
||||
if (op)
|
||||
mvalue2 = op + 1;
|
||||
|
||||
if (!mvar || !mvalue1 || !mvalue2) {
|
||||
ast_log(LOG_WARNING, "Supply all the parameters - just this once, please\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!strcmp(mvar,"")) {
|
||||
ast_log(LOG_WARNING, "No return variable set.\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sscanf(mvalue1, "%f", &fnum1) != 1) {
|
||||
ast_log(LOG_WARNING, "'%s' is not a valid number\n", mvalue1);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sscanf(mvalue2, "%f", &fnum2) != 1) {
|
||||
ast_log(LOG_WARNING, "'%s' is not a valid number\n", mvalue2);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (iaction) {
|
||||
case ADDFUNCTION :
|
||||
ftmp = fnum1 + fnum2;
|
||||
break;
|
||||
case DIVIDEFUNCTION :
|
||||
if (fnum2 <=0)
|
||||
ftmp = 0; /* can't do a divide by 0 */
|
||||
else
|
||||
ftmp = (fnum1 / fnum2);
|
||||
break;
|
||||
case MULTIPLYFUNCTION :
|
||||
ftmp = (fnum1 * fnum2);
|
||||
break;
|
||||
case SUBTRACTFUNCTION :
|
||||
ftmp = (fnum1 - fnum2);
|
||||
break;
|
||||
case MODULUSFUNCTION : {
|
||||
int inum1 = fnum1;
|
||||
int inum2 = fnum2;
|
||||
|
||||
ftmp = (inum1 % inum2);
|
||||
|
||||
break;
|
||||
}
|
||||
case GTFUNCTION :
|
||||
if (fnum1 > fnum2)
|
||||
strcpy(user_result, "TRUE");
|
||||
else
|
||||
strcpy(user_result, "FALSE");
|
||||
break;
|
||||
case LTFUNCTION :
|
||||
if (fnum1 < fnum2)
|
||||
strcpy(user_result, "TRUE");
|
||||
else
|
||||
strcpy(user_result, "FALSE");
|
||||
break;
|
||||
case GTEFUNCTION :
|
||||
if (fnum1 >= fnum2)
|
||||
strcpy(user_result, "TRUE");
|
||||
else
|
||||
strcpy(user_result, "FALSE");
|
||||
break;
|
||||
case LTEFUNCTION :
|
||||
if (fnum1 <= fnum2)
|
||||
strcpy(user_result, "TRUE");
|
||||
else
|
||||
strcpy(user_result, "FALSE");
|
||||
break;
|
||||
case EQFUNCTION :
|
||||
if (fnum1 == fnum2)
|
||||
strcpy(user_result, "TRUE");
|
||||
else
|
||||
strcpy(user_result, "FALSE");
|
||||
break;
|
||||
default :
|
||||
ast_log(LOG_WARNING, "Something happened that neither of us should be proud of %d\n", iaction);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (iaction < GTFUNCTION || iaction > EQFUNCTION)
|
||||
snprintf(user_result,sizeof(user_result),"%f",ftmp);
|
||||
|
||||
pbx_builtin_setvar_helper(chan, mvar, user_result);
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app_math);
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(app_math, math_exec, math_synopsis, math_descrip);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
|
||||
/* Fading everything to black and blue... */
|
||||
205
apps/app_md5.c
Normal file
205
apps/app_md5.c
Normal file
@@ -0,0 +1,205 @@
|
||||
/*
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Copyright (C) 2005, Olle E. Johansson, Edvina.net
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief MD5 checksum application
|
||||
*
|
||||
* \todo Remove this deprecated application in 1.3dev
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/utils.h"
|
||||
#include "asterisk/options.h"
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/lock.h"
|
||||
#include "asterisk/app.h"
|
||||
|
||||
static char *tdesc_md5 = "MD5 checksum applications";
|
||||
static char *app_md5 = "MD5";
|
||||
static char *desc_md5 = "Calculate MD5 checksum";
|
||||
static char *synopsis_md5 =
|
||||
" MD5(<var>=<string>): Calculates a MD5 checksum on <string>.\n"
|
||||
"Returns hash value in a channel variable. \n";
|
||||
|
||||
static char *app_md5check = "MD5Check";
|
||||
static char *desc_md5check = "Check MD5 checksum";
|
||||
static char *synopsis_md5check =
|
||||
" MD5Check(<md5hash>|<string>[|options]): Calculates a MD5 checksum on <string>\n"
|
||||
"and compares it with the hash. Returns 0 if <md5hash> is correct for <string>.\n"
|
||||
"The option string may contain zero or more of the following characters:\n"
|
||||
" 'j' -- jump to priority n+101 if the hash and string do not match \n"
|
||||
"This application sets the following channel variable upon completion:\n"
|
||||
" CHECKMD5STATUS The status of the MD5 check, one of the following\n"
|
||||
" MATCH | NOMATCH\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
/*--- md5_exec: Calculate MD5 checksum (hash) on given string and
|
||||
return it in channel variable ---*/
|
||||
static int md5_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0;
|
||||
struct localuser *u;
|
||||
char *varname= NULL; /* Variable to set */
|
||||
char *string = NULL; /* String to calculate on */
|
||||
char retvar[50]; /* Return value */
|
||||
static int dep_warning = 0;
|
||||
|
||||
if (!dep_warning) {
|
||||
ast_log(LOG_WARNING, "This application has been deprecated, please use the MD5 function instead.\n");
|
||||
dep_warning = 1;
|
||||
}
|
||||
|
||||
if (ast_strlen_zero(data)) {
|
||||
ast_log(LOG_WARNING, "Syntax: md5(<varname>=<string>) - missing argument!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
memset(retvar,0, sizeof(retvar));
|
||||
string = ast_strdupa(data);
|
||||
varname = strsep(&string,"=");
|
||||
if (ast_strlen_zero(varname)) {
|
||||
ast_log(LOG_WARNING, "Syntax: md5(<varname>=<string>) - missing argument!\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
ast_md5_hash(retvar, string);
|
||||
pbx_builtin_setvar_helper(chan, varname, retvar);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
/*--- md5check_exec: Calculate MD5 checksum and compare it with
|
||||
existing checksum. ---*/
|
||||
static int md5check_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0;
|
||||
struct localuser *u;
|
||||
char *string = NULL; /* String to calculate on */
|
||||
char newhash[50]; /* Return value */
|
||||
static int dep_warning = 0;
|
||||
int priority_jump = 0;
|
||||
AST_DECLARE_APP_ARGS(args,
|
||||
AST_APP_ARG(md5hash);
|
||||
AST_APP_ARG(string);
|
||||
AST_APP_ARG(options);
|
||||
);
|
||||
|
||||
if (!dep_warning) {
|
||||
ast_log(LOG_WARNING, "This application has been deprecated, please use the CHECK_MD5 function instead.\n");
|
||||
dep_warning = 1;
|
||||
}
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
if (!(string = ast_strdupa(data))) {
|
||||
ast_log(LOG_WARNING, "Memory Error!\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
AST_STANDARD_APP_ARGS(args, string);
|
||||
|
||||
if (args.options) {
|
||||
if (strchr(args.options, 'j'))
|
||||
priority_jump = 1;
|
||||
}
|
||||
|
||||
if (ast_strlen_zero(args.md5hash) || ast_strlen_zero(args.string)) {
|
||||
ast_log(LOG_WARNING, "Syntax: MD5Check(<md5hash>|<string>[|options]) - missing argument!\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(newhash,0, sizeof(newhash));
|
||||
|
||||
ast_md5_hash(newhash, args.string);
|
||||
if (!strcmp(newhash, args.md5hash)) { /* Verification ok */
|
||||
if (option_debug > 2)
|
||||
ast_log(LOG_DEBUG, "MD5 verified ok: %s -- %s\n", args.md5hash, args.string);
|
||||
pbx_builtin_setvar_helper(chan, "CHECKMD5STATUS", "MATCH");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return 0;
|
||||
}
|
||||
if (option_debug > 2)
|
||||
ast_log(LOG_DEBUG, "ERROR: MD5 not verified: %s -- %s\n", args.md5hash, args.string);
|
||||
pbx_builtin_setvar_helper(chan, "CHECKMD5STATUS", "NOMATCH");
|
||||
if (priority_jump || option_priority_jumping) {
|
||||
if (ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101))
|
||||
if (option_debug > 2)
|
||||
ast_log(LOG_DEBUG, "Can't jump to exten+101 (e%s,p%d), sorry\n", chan->exten,chan->priority+101);
|
||||
}
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app_md5);
|
||||
res |= ast_unregister_application(app_md5check);
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_register_application(app_md5check, md5check_exec, desc_md5check, synopsis_md5check);
|
||||
res |= ast_register_application(app_md5, md5_exec, desc_md5, synopsis_md5);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc_md5;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
2140
apps/app_meetme.c
Executable file → Normal file
2140
apps/app_meetme.c
Executable file → Normal file
File diff suppressed because it is too large
Load Diff
57
apps/app_milliwatt.c
Executable file → Normal file
57
apps/app_milliwatt.c
Executable file → Normal file
@@ -1,29 +1,44 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Digital Milliwatt Test
|
||||
*
|
||||
* Copyright (C) 2002, Mark Spencer
|
||||
* Copyright (C) 1999 - 2005, Digium, Inc.
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
* Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief Digital Milliwatt Test
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <pthread.h>
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/lock.h"
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/module.h"
|
||||
|
||||
static char *tdesc = "Digital Milliwatt (mu-law) Test Application";
|
||||
|
||||
@@ -64,7 +79,7 @@ static int milliwatt_generate(struct ast_channel *chan, void *data, int len, int
|
||||
|
||||
if (len > sizeof(buf))
|
||||
{
|
||||
ast_log(LOG_WARNING,"Only doing %d bytes (%d bytes requested)\n",sizeof(buf),len);
|
||||
ast_log(LOG_WARNING,"Only doing %d bytes (%d bytes requested)\n",(int)sizeof(buf),len);
|
||||
len = sizeof(buf);
|
||||
}
|
||||
waste[0] = 0; /* make compiler happy */
|
||||
@@ -76,6 +91,8 @@ static int milliwatt_generate(struct ast_channel *chan, void *data, int len, int
|
||||
wf.datalen = len;
|
||||
wf.samples = wf.datalen;
|
||||
wf.src = "app_milliwatt";
|
||||
wf.delivery.tv_sec = 0;
|
||||
wf.delivery.tv_usec = 0;
|
||||
/* create a buffer containing the digital milliwatt pattern */
|
||||
for(i = 0; i < len; i++)
|
||||
{
|
||||
@@ -111,6 +128,7 @@ static int milliwatt_exec(struct ast_channel *chan, void *data)
|
||||
if (ast_activate_generator(chan,&milliwattgen,"milliwatt") < 0)
|
||||
{
|
||||
ast_log(LOG_WARNING,"Failed to activate generator on '%s'\n",chan->name);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
while(!ast_safe_sleep(chan, 10000));
|
||||
@@ -121,8 +139,13 @@ static int milliwatt_exec(struct ast_channel *chan, void *data)
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app);
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
|
||||
466
apps/app_mixmonitor.c
Normal file
466
apps/app_mixmonitor.c
Normal file
@@ -0,0 +1,466 @@
|
||||
/*
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Copyright (C) 2005, Anthony Minessale II
|
||||
* Copyright (C) 2005, Digium, Inc.
|
||||
*
|
||||
* Mark Spencer <markster@digium.com>
|
||||
* Kevin P. Fleming <kpfleming@digium.com>
|
||||
*
|
||||
* Based on app_muxmon.c provided by
|
||||
* Anthony Minessale II <anthmct@yahoo.com>
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
* \brief MixMonitor() - Record a call and mix the audio during the recording
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/chanspy.h"
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/lock.h"
|
||||
#include "asterisk/cli.h"
|
||||
#include "asterisk/options.h"
|
||||
#include "asterisk/app.h"
|
||||
#include "asterisk/linkedlists.h"
|
||||
|
||||
#define get_volfactor(x) x ? ((x > 0) ? (1 << x) : ((1 << abs(x)) * -1)) : 0
|
||||
|
||||
static const char *tdesc = "Mixed Audio Monitoring Application";
|
||||
static const char *app = "MixMonitor";
|
||||
static const char *synopsis = "Record a call and mix the audio during the recording";
|
||||
static const char *desc = ""
|
||||
" MixMonitor(<file>.<ext>[|<options>[|<command>]])\n\n"
|
||||
"Records the audio on the current channel to the specified file.\n"
|
||||
"If the filename is an absolute path, uses that path, otherwise\n"
|
||||
"creates the file in the configured monitoring directory from\n"
|
||||
"asterisk.conf.\n\n"
|
||||
"Valid options:\n"
|
||||
" a - Append to the file instead of overwriting it.\n"
|
||||
" b - Only save audio to the file while the channel is bridged.\n"
|
||||
" Note: does not include conferences.\n"
|
||||
" v(<x>) - Adjust the heard volume by a factor of <x> (range -4 to 4)\n"
|
||||
" V(<x>) - Adjust the spoken volume by a factor of <x> (range -4 to 4)\n"
|
||||
" W(<x>) - Adjust the both heard and spoken volumes by a factor of <x>\n"
|
||||
" (range -4 to 4)\n\n"
|
||||
"<command> will be executed when the recording is over\n"
|
||||
"Any strings matching ^{X} will be unescaped to ${X} and \n"
|
||||
"all variables will be evaluated at that time.\n"
|
||||
"The variable MIXMONITOR_FILENAME will contain the filename used to record.\n"
|
||||
"";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static const char *mixmonitor_spy_type = "MixMonitor";
|
||||
|
||||
struct mixmonitor {
|
||||
struct ast_channel *chan;
|
||||
char *filename;
|
||||
char *post_process;
|
||||
unsigned int flags;
|
||||
int readvol;
|
||||
int writevol;
|
||||
};
|
||||
|
||||
enum {
|
||||
MUXFLAG_APPEND = (1 << 1),
|
||||
MUXFLAG_BRIDGED = (1 << 2),
|
||||
MUXFLAG_VOLUME = (1 << 3),
|
||||
MUXFLAG_READVOLUME = (1 << 4),
|
||||
MUXFLAG_WRITEVOLUME = (1 << 5),
|
||||
} mixmonitor_flags;
|
||||
|
||||
enum {
|
||||
OPT_ARG_READVOLUME = 0,
|
||||
OPT_ARG_WRITEVOLUME,
|
||||
OPT_ARG_VOLUME,
|
||||
OPT_ARG_ARRAY_SIZE,
|
||||
} mixmonitor_args;
|
||||
|
||||
AST_APP_OPTIONS(mixmonitor_opts, {
|
||||
AST_APP_OPTION('a', MUXFLAG_APPEND),
|
||||
AST_APP_OPTION('b', MUXFLAG_BRIDGED),
|
||||
AST_APP_OPTION_ARG('v', MUXFLAG_READVOLUME, OPT_ARG_READVOLUME),
|
||||
AST_APP_OPTION_ARG('V', MUXFLAG_WRITEVOLUME, OPT_ARG_WRITEVOLUME),
|
||||
AST_APP_OPTION_ARG('W', MUXFLAG_VOLUME, OPT_ARG_VOLUME),
|
||||
});
|
||||
|
||||
static void stopmon(struct ast_channel *chan, struct ast_channel_spy *spy)
|
||||
{
|
||||
/* If our status has changed to DONE, then the channel we're spying on is gone....
|
||||
DON'T TOUCH IT!!! RUN AWAY!!! */
|
||||
if (spy->status == CHANSPY_DONE)
|
||||
return;
|
||||
|
||||
if (!chan)
|
||||
return;
|
||||
|
||||
ast_mutex_lock(&chan->lock);
|
||||
ast_channel_spy_remove(chan, spy);
|
||||
ast_mutex_unlock(&chan->lock);
|
||||
}
|
||||
|
||||
static int startmon(struct ast_channel *chan, struct ast_channel_spy *spy)
|
||||
{
|
||||
struct ast_channel *peer;
|
||||
int res;
|
||||
|
||||
if (!chan)
|
||||
return -1;
|
||||
|
||||
ast_mutex_lock(&chan->lock);
|
||||
res = ast_channel_spy_add(chan, spy);
|
||||
ast_mutex_unlock(&chan->lock);
|
||||
|
||||
if (!res && ast_test_flag(chan, AST_FLAG_NBRIDGE) && (peer = ast_bridged_channel(chan)))
|
||||
ast_softhangup(peer, AST_SOFTHANGUP_UNBRIDGE);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
#define SAMPLES_PER_FRAME 160
|
||||
|
||||
static void *mixmonitor_thread(void *obj)
|
||||
{
|
||||
struct mixmonitor *mixmonitor = obj;
|
||||
struct ast_channel_spy spy;
|
||||
struct ast_filestream *fs = NULL;
|
||||
char *ext, *name;
|
||||
unsigned int oflags;
|
||||
struct ast_frame *f;
|
||||
char post_process[1024] = "";
|
||||
|
||||
STANDARD_INCREMENT_USECOUNT;
|
||||
|
||||
name = ast_strdupa(mixmonitor->chan->name);
|
||||
|
||||
oflags = O_CREAT|O_WRONLY;
|
||||
oflags |= ast_test_flag(mixmonitor, MUXFLAG_APPEND) ? O_APPEND : O_TRUNC;
|
||||
|
||||
if ((ext = strrchr(mixmonitor->filename, '.'))) {
|
||||
*(ext++) = '\0';
|
||||
} else {
|
||||
ext = "raw";
|
||||
}
|
||||
|
||||
fs = ast_writefile(mixmonitor->filename, ext, NULL, oflags, 0, 0644);
|
||||
if (!fs) {
|
||||
ast_log(LOG_ERROR, "Cannot open %s.%s\n", mixmonitor->filename, ext);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (ast_test_flag(mixmonitor, MUXFLAG_APPEND))
|
||||
ast_seekstream(fs, 0, SEEK_END);
|
||||
|
||||
memset(&spy, 0, sizeof(spy));
|
||||
ast_set_flag(&spy, CHANSPY_FORMAT_AUDIO);
|
||||
ast_set_flag(&spy, CHANSPY_MIXAUDIO);
|
||||
spy.type = mixmonitor_spy_type;
|
||||
spy.status = CHANSPY_RUNNING;
|
||||
spy.read_queue.format = AST_FORMAT_SLINEAR;
|
||||
spy.write_queue.format = AST_FORMAT_SLINEAR;
|
||||
if (mixmonitor->readvol) {
|
||||
ast_set_flag(&spy, CHANSPY_READ_VOLADJUST);
|
||||
spy.read_vol_adjustment = mixmonitor->readvol;
|
||||
}
|
||||
if (mixmonitor->writevol) {
|
||||
ast_set_flag(&spy, CHANSPY_WRITE_VOLADJUST);
|
||||
spy.write_vol_adjustment = mixmonitor->writevol;
|
||||
}
|
||||
ast_mutex_init(&spy.lock);
|
||||
|
||||
if (startmon(mixmonitor->chan, &spy)) {
|
||||
ast_log(LOG_WARNING, "Unable to add '%s' spy to channel '%s'\n",
|
||||
spy.type, mixmonitor->chan->name);
|
||||
goto out2;
|
||||
}
|
||||
|
||||
if (option_verbose > 1)
|
||||
ast_verbose(VERBOSE_PREFIX_2 "Begin MixMonitor Recording %s\n", name);
|
||||
|
||||
while (1) {
|
||||
struct ast_frame *next;
|
||||
int write;
|
||||
|
||||
ast_mutex_lock(&spy.lock);
|
||||
|
||||
ast_channel_spy_trigger_wait(&spy);
|
||||
|
||||
if (ast_check_hangup(mixmonitor->chan) || spy.status != CHANSPY_RUNNING) {
|
||||
ast_mutex_unlock(&spy.lock);
|
||||
break;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
if (!(f = ast_channel_spy_read_frame(&spy, SAMPLES_PER_FRAME)))
|
||||
break;
|
||||
|
||||
write = (!ast_test_flag(mixmonitor, MUXFLAG_BRIDGED) ||
|
||||
ast_bridged_channel(mixmonitor->chan));
|
||||
|
||||
/* it is possible for ast_channel_spy_read_frame() to return a chain
|
||||
of frames if a queue flush was necessary, so process them
|
||||
*/
|
||||
for (; f; f = next) {
|
||||
next = f->next;
|
||||
if (write)
|
||||
ast_writestream(fs, f);
|
||||
ast_frfree(f);
|
||||
}
|
||||
}
|
||||
|
||||
ast_mutex_unlock(&spy.lock);
|
||||
}
|
||||
|
||||
if (mixmonitor->post_process) {
|
||||
char *p;
|
||||
|
||||
for (p = mixmonitor->post_process; *p ; p++) {
|
||||
if (*p == '^' && *(p+1) == '{') {
|
||||
*p = '$';
|
||||
}
|
||||
}
|
||||
pbx_substitute_variables_helper(mixmonitor->chan, mixmonitor->post_process, post_process, sizeof(post_process) - 1);
|
||||
}
|
||||
|
||||
stopmon(mixmonitor->chan, &spy);
|
||||
|
||||
if (option_verbose > 1)
|
||||
ast_verbose(VERBOSE_PREFIX_2 "End MixMonitor Recording %s\n", name);
|
||||
|
||||
if (!ast_strlen_zero(post_process)) {
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_2 "Executing [%s]\n", post_process);
|
||||
ast_safe_system(post_process);
|
||||
}
|
||||
|
||||
out2:
|
||||
ast_mutex_destroy(&spy.lock);
|
||||
|
||||
if (fs)
|
||||
ast_closestream(fs);
|
||||
|
||||
out:
|
||||
free(mixmonitor);
|
||||
|
||||
STANDARD_DECREMENT_USECOUNT;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void launch_monitor_thread(struct ast_channel *chan, const char *filename, unsigned int flags,
|
||||
int readvol, int writevol, const char *post_process)
|
||||
{
|
||||
pthread_attr_t attr;
|
||||
pthread_t thread;
|
||||
struct mixmonitor *mixmonitor;
|
||||
int len;
|
||||
|
||||
len = sizeof(*mixmonitor) + strlen(filename) + 1;
|
||||
if (!ast_strlen_zero(post_process))
|
||||
len += strlen(post_process) + 1;
|
||||
|
||||
if (!(mixmonitor = calloc(1, len))) {
|
||||
ast_log(LOG_ERROR, "Memory Error!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
mixmonitor->chan = chan;
|
||||
mixmonitor->filename = (char *) mixmonitor + sizeof(*mixmonitor);
|
||||
strcpy(mixmonitor->filename, filename);
|
||||
if (!ast_strlen_zero(post_process)) {
|
||||
mixmonitor->post_process = mixmonitor->filename + strlen(filename) + 1;
|
||||
strcpy(mixmonitor->post_process, post_process);
|
||||
}
|
||||
mixmonitor->readvol = readvol;
|
||||
mixmonitor->writevol = writevol;
|
||||
mixmonitor->flags = flags;
|
||||
|
||||
pthread_attr_init(&attr);
|
||||
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||||
ast_pthread_create(&thread, &attr, mixmonitor_thread, mixmonitor);
|
||||
pthread_attr_destroy(&attr);
|
||||
}
|
||||
|
||||
static int mixmonitor_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int x, readvol = 0, writevol = 0;
|
||||
struct localuser *u;
|
||||
struct ast_flags flags = {0};
|
||||
char *parse;
|
||||
AST_DECLARE_APP_ARGS(args,
|
||||
AST_APP_ARG(filename);
|
||||
AST_APP_ARG(options);
|
||||
AST_APP_ARG(post_process);
|
||||
);
|
||||
|
||||
if (ast_strlen_zero(data)) {
|
||||
ast_log(LOG_WARNING, "MixMonitor requires an argument (filename)\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
if (!(parse = ast_strdupa(data))) {
|
||||
ast_log(LOG_WARNING, "Memory Error!\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
AST_STANDARD_APP_ARGS(args, parse);
|
||||
|
||||
if (ast_strlen_zero(args.filename)) {
|
||||
ast_log(LOG_WARNING, "MixMonitor requires an argument (filename)\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (args.options) {
|
||||
char *opts[OPT_ARG_ARRAY_SIZE] = { NULL, };
|
||||
|
||||
ast_app_parse_options(mixmonitor_opts, &flags, opts, args.options);
|
||||
|
||||
if (ast_test_flag(&flags, MUXFLAG_READVOLUME)) {
|
||||
if (ast_strlen_zero(opts[OPT_ARG_READVOLUME])) {
|
||||
ast_log(LOG_WARNING, "No volume level was provided for the heard volume ('v') option.\n");
|
||||
} else if ((sscanf(opts[OPT_ARG_READVOLUME], "%d", &x) != 1) || (x < -4) || (x > 4)) {
|
||||
ast_log(LOG_NOTICE, "Heard volume must be a number between -4 and 4, not '%s'\n", opts[OPT_ARG_READVOLUME]);
|
||||
} else {
|
||||
readvol = get_volfactor(x);
|
||||
}
|
||||
}
|
||||
|
||||
if (ast_test_flag(&flags, MUXFLAG_WRITEVOLUME)) {
|
||||
if (ast_strlen_zero(opts[OPT_ARG_WRITEVOLUME])) {
|
||||
ast_log(LOG_WARNING, "No volume level was provided for the spoken volume ('V') option.\n");
|
||||
} else if ((sscanf(opts[OPT_ARG_WRITEVOLUME], "%d", &x) != 1) || (x < -4) || (x > 4)) {
|
||||
ast_log(LOG_NOTICE, "Spoken volume must be a number between -4 and 4, not '%s'\n", opts[OPT_ARG_WRITEVOLUME]);
|
||||
} else {
|
||||
writevol = get_volfactor(x);
|
||||
}
|
||||
}
|
||||
|
||||
if (ast_test_flag(&flags, MUXFLAG_VOLUME)) {
|
||||
if (ast_strlen_zero(opts[OPT_ARG_VOLUME])) {
|
||||
ast_log(LOG_WARNING, "No volume level was provided for the combined volume ('W') option.\n");
|
||||
} else if ((sscanf(opts[OPT_ARG_VOLUME], "%d", &x) != 1) || (x < -4) || (x > 4)) {
|
||||
ast_log(LOG_NOTICE, "Combined volume must be a number between -4 and 4, not '%s'\n", opts[OPT_ARG_VOLUME]);
|
||||
} else {
|
||||
readvol = writevol = get_volfactor(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* if not provided an absolute path, use the system-configured monitoring directory */
|
||||
if (args.filename[0] != '/') {
|
||||
char *build;
|
||||
|
||||
build = alloca(strlen(ast_config_AST_MONITOR_DIR) + strlen(args.filename) + 3);
|
||||
sprintf(build, "%s/%s", ast_config_AST_MONITOR_DIR, args.filename);
|
||||
args.filename = build;
|
||||
}
|
||||
|
||||
pbx_builtin_setvar_helper(chan, "MIXMONITOR_FILENAME", args.filename);
|
||||
launch_monitor_thread(chan, args.filename, flags.flags, readvol, writevol, args.post_process);
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mixmonitor_cli(int fd, int argc, char **argv)
|
||||
{
|
||||
struct ast_channel *chan;
|
||||
|
||||
if (argc < 3)
|
||||
return RESULT_SHOWUSAGE;
|
||||
|
||||
if (!(chan = ast_get_channel_by_name_prefix_locked(argv[2], strlen(argv[2])))) {
|
||||
ast_cli(fd, "No channel matching '%s' found.\n", argv[2]);
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
if (!strcasecmp(argv[1], "start"))
|
||||
mixmonitor_exec(chan, argv[3]);
|
||||
else if (!strcasecmp(argv[1], "stop"))
|
||||
ast_channel_spy_stop_by_type(chan, mixmonitor_spy_type);
|
||||
|
||||
ast_mutex_unlock(&chan->lock);
|
||||
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static struct ast_cli_entry cli_mixmonitor = {
|
||||
{ "mixmonitor", NULL, NULL },
|
||||
mixmonitor_cli,
|
||||
"Execute a MixMonitor command",
|
||||
"mixmonitor <start|stop> <chan_name> [<args>]\n"
|
||||
};
|
||||
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_cli_unregister(&cli_mixmonitor);
|
||||
res |= ast_unregister_application(app);
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_cli_register(&cli_mixmonitor);
|
||||
res |= ast_register_application(app, mixmonitor_exec, synopsis, desc);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return (char *) tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
STANDARD_USECOUNT(res);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
163
apps/app_mp3.c
Executable file → Normal file
163
apps/app_mp3.c
Executable file → Normal file
@@ -1,33 +1,49 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Silly application to play an MP3 file -- uses mpg123
|
||||
*
|
||||
* Copyright (C) 1999, Mark Spencer
|
||||
* Copyright (C) 1999 - 2005, Digium, Inc.
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
* Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief Silly application to play an MP3 file -- uses mpg123
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/frame.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/translate.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/lock.h"
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/frame.h"
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/translate.h"
|
||||
|
||||
#define LOCAL_MPG_123 "/usr/local/bin/mpg123"
|
||||
#define MPG_123 "/usr/bin/mpg123"
|
||||
|
||||
@@ -38,9 +54,9 @@ static char *app = "MP3Player";
|
||||
static char *synopsis = "Play an MP3 file or stream";
|
||||
|
||||
static char *descrip =
|
||||
" MP3Player(location) Executes mpg123 to play the given location\n"
|
||||
"which typically would be a filename or a URL. Returns -1 on\n"
|
||||
"hangup or 0 otherwise. User can exit by pressing any key\n.";
|
||||
" MP3Player(location) Executes mpg123 to play the given location,\n"
|
||||
"which typically would be a filename or a URL. User can exit by pressing\n"
|
||||
"any key on the dialpad, or by hanging up.";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
@@ -61,36 +77,35 @@ static int mp3play(char *filename, int fd)
|
||||
close(x);
|
||||
}
|
||||
/* Execute mpg123, but buffer if it's a net connection */
|
||||
if (strncmp(filename, "http://", 7)) {
|
||||
if (!strncasecmp(filename, "http://", 7)) {
|
||||
/* Most commonly installed in /usr/local/bin */
|
||||
execl(LOCAL_MPG_123, "mpg123", "-q", "-s", "-b", "1024", "--mono", "-r", "8000", filename, (char *)NULL);
|
||||
execl(LOCAL_MPG_123, "mpg123", "-q", "-s", "-b", "1024", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL);
|
||||
/* But many places has it in /usr/bin */
|
||||
execl(MPG_123, "mpg123", "-q", "-s", "-b", "1024", "--mono", "-r", "8000", filename, (char *)NULL);
|
||||
execl(MPG_123, "mpg123", "-q", "-s", "-b", "1024","-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL);
|
||||
/* As a last-ditch effort, try to use PATH */
|
||||
execlp("mpg123", "mpg123", "-q", "-s", "-b", "1024", "--mono", "-r", "8000", filename, (char *)NULL);
|
||||
execlp("mpg123", "mpg123", "-q", "-s", "-b", "1024", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL);
|
||||
}
|
||||
else {
|
||||
/* Most commonly installed in /usr/local/bin */
|
||||
execl(MPG_123, "mpg123", "-q", "-s", "--mono", "-r", "8000", filename, (char *)NULL);
|
||||
execl(MPG_123, "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL);
|
||||
/* But many places has it in /usr/bin */
|
||||
execl(LOCAL_MPG_123, "mpg123", "-q", "-s", "--mono", "-r", "8000", filename, (char *)NULL);
|
||||
execl(LOCAL_MPG_123, "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL);
|
||||
/* As a last-ditch effort, try to use PATH */
|
||||
execlp("mpg123", "mpg123", "-q", "-s", "--mono", "-r", "8000", filename, (char *)NULL);
|
||||
execlp("mpg123", "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL);
|
||||
}
|
||||
ast_log(LOG_WARNING, "Execute of mpg123 failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int timed_read(int fd, void *data, int datalen)
|
||||
static int timed_read(int fd, void *data, int datalen, int timeout)
|
||||
{
|
||||
int res;
|
||||
fd_set fds;
|
||||
struct timeval tv = { 2, 0 }; /* Wait no more than 2 seconds */
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(fd, &fds);
|
||||
res = ast_select(fd + 1, &fds, NULL, NULL, &tv);
|
||||
struct pollfd fds[1];
|
||||
fds[0].fd = fd;
|
||||
fds[0].events = POLLIN;
|
||||
res = poll(fds, 1, timeout);
|
||||
if (res < 1) {
|
||||
ast_log(LOG_NOTICE, "Selected timed out/errored out with %d\n", res);
|
||||
ast_log(LOG_NOTICE, "Poll timed out/errored out with %d\n", res);
|
||||
return -1;
|
||||
}
|
||||
return read(fd, data, datalen);
|
||||
@@ -105,63 +120,53 @@ static int mp3_exec(struct ast_channel *chan, void *data)
|
||||
int ms = -1;
|
||||
int pid = -1;
|
||||
int owriteformat;
|
||||
struct timeval last;
|
||||
int timeout = 2000;
|
||||
struct timeval next;
|
||||
struct ast_frame *f;
|
||||
struct myframe {
|
||||
struct ast_frame f;
|
||||
char offset[AST_FRIENDLY_OFFSET];
|
||||
short frdata[160];
|
||||
} myf;
|
||||
last.tv_usec = 0;
|
||||
last.tv_sec = 0;
|
||||
if (!data) {
|
||||
|
||||
if (ast_strlen_zero(data)) {
|
||||
ast_log(LOG_WARNING, "MP3 Playback requires an argument (filename)\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
if (pipe(fds)) {
|
||||
ast_log(LOG_WARNING, "Unable to create pipe\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
ast_stopstream(chan);
|
||||
|
||||
owriteformat = chan->writeformat;
|
||||
res = ast_set_write_format(chan, AST_FORMAT_SLINEAR);
|
||||
if (res < 0) {
|
||||
ast_log(LOG_WARNING, "Unable to set write format to signed linear\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = mp3play((char *)data, fds[1]);
|
||||
if (!strncasecmp((char *)data, "http://", 7)) {
|
||||
timeout = 10000;
|
||||
}
|
||||
/* Wait 1000 ms first */
|
||||
ms = 1000;
|
||||
next = ast_tvnow();
|
||||
next.tv_sec += 1;
|
||||
if (res >= 0) {
|
||||
pid = res;
|
||||
/* Order is important -- there's almost always going to be mp3... we want to prioritize the
|
||||
user */
|
||||
for (;;) {
|
||||
ms = ast_waitfor(chan, ms);
|
||||
if (ms < 0) {
|
||||
ast_log(LOG_DEBUG, "Hangup detected\n");
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
if (ms) {
|
||||
f = ast_read(chan);
|
||||
if (!f) {
|
||||
ast_log(LOG_DEBUG, "Null frame == hangup() detected\n");
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
if (f->frametype == AST_FRAME_DTMF) {
|
||||
ast_log(LOG_DEBUG, "User pressed a key\n");
|
||||
ast_frfree(f);
|
||||
res = 0;
|
||||
break;
|
||||
}
|
||||
ast_frfree(f);
|
||||
} else {
|
||||
res = timed_read(fds[0], myf.frdata, sizeof(myf.frdata));
|
||||
ms = ast_tvdiff_ms(next, ast_tvnow());
|
||||
if (ms <= 0) {
|
||||
res = timed_read(fds[0], myf.frdata, sizeof(myf.frdata), timeout);
|
||||
if (res > 0) {
|
||||
myf.f.frametype = AST_FRAME_VOICE;
|
||||
myf.f.subclass = AST_FORMAT_SLINEAR;
|
||||
@@ -170,6 +175,8 @@ static int mp3_exec(struct ast_channel *chan, void *data)
|
||||
myf.f.mallocd = 0;
|
||||
myf.f.offset = AST_FRIENDLY_OFFSET;
|
||||
myf.f.src = __PRETTY_FUNCTION__;
|
||||
myf.f.delivery.tv_sec = 0;
|
||||
myf.f.delivery.tv_usec = 0;
|
||||
myf.f.data = myf.frdata;
|
||||
if (ast_write(chan, &myf.f) < 0) {
|
||||
res = -1;
|
||||
@@ -180,24 +187,54 @@ static int mp3_exec(struct ast_channel *chan, void *data)
|
||||
res = 0;
|
||||
break;
|
||||
}
|
||||
ms = res / 16;
|
||||
next = ast_tvadd(next, ast_samp2tv(myf.f.samples, 8000));
|
||||
} else {
|
||||
ms = ast_waitfor(chan, ms);
|
||||
if (ms < 0) {
|
||||
ast_log(LOG_DEBUG, "Hangup detected\n");
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
if (ms) {
|
||||
f = ast_read(chan);
|
||||
if (!f) {
|
||||
ast_log(LOG_DEBUG, "Null frame == hangup() detected\n");
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
if (f->frametype == AST_FRAME_DTMF) {
|
||||
ast_log(LOG_DEBUG, "User pressed a key\n");
|
||||
ast_frfree(f);
|
||||
res = 0;
|
||||
break;
|
||||
}
|
||||
ast_frfree(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
close(fds[0]);
|
||||
close(fds[1]);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
if (pid > -1)
|
||||
kill(pid, SIGKILL);
|
||||
if (!res && owriteformat)
|
||||
ast_set_write_format(chan, owriteformat);
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app);
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
|
||||
241
apps/app_nbscat.c
Normal file
241
apps/app_nbscat.c
Normal file
@@ -0,0 +1,241 @@
|
||||
/*
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Copyright (C) 1999 - 2005, Digium, Inc.
|
||||
*
|
||||
* Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief Silly application to play an NBScat file -- uses nbscat8k
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/lock.h"
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/frame.h"
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/translate.h"
|
||||
|
||||
#define LOCAL_NBSCAT "/usr/local/bin/nbscat8k"
|
||||
#define NBSCAT "/usr/bin/nbscat8k"
|
||||
|
||||
#ifndef AF_LOCAL
|
||||
#define AF_LOCAL AF_UNIX
|
||||
#endif
|
||||
|
||||
static char *tdesc = "Silly NBS Stream Application";
|
||||
|
||||
static char *app = "NBScat";
|
||||
|
||||
static char *synopsis = "Play an NBS local stream";
|
||||
|
||||
static char *descrip =
|
||||
" NBScat: Executes nbscat to listen to the local NBS stream.\n"
|
||||
"User can exit by pressing any key\n.";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int NBScatplay(int fd)
|
||||
{
|
||||
int res;
|
||||
int x;
|
||||
res = fork();
|
||||
if (res < 0)
|
||||
ast_log(LOG_WARNING, "Fork failed\n");
|
||||
if (res)
|
||||
return res;
|
||||
dup2(fd, STDOUT_FILENO);
|
||||
for (x=0;x<256;x++) {
|
||||
if (x != STDOUT_FILENO)
|
||||
close(x);
|
||||
}
|
||||
/* Most commonly installed in /usr/local/bin */
|
||||
execl(NBSCAT, "nbscat8k", "-d", (char *)NULL);
|
||||
execl(LOCAL_NBSCAT, "nbscat8k", "-d", (char *)NULL);
|
||||
ast_log(LOG_WARNING, "Execute of nbscat8k failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int timed_read(int fd, void *data, int datalen)
|
||||
{
|
||||
int res;
|
||||
struct pollfd fds[1];
|
||||
fds[0].fd = fd;
|
||||
fds[0].events = POLLIN;
|
||||
res = poll(fds, 1, 2000);
|
||||
if (res < 1) {
|
||||
ast_log(LOG_NOTICE, "Selected timed out/errored out with %d\n", res);
|
||||
return -1;
|
||||
}
|
||||
return read(fd, data, datalen);
|
||||
|
||||
}
|
||||
|
||||
static int NBScat_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0;
|
||||
struct localuser *u;
|
||||
int fds[2];
|
||||
int ms = -1;
|
||||
int pid = -1;
|
||||
int owriteformat;
|
||||
struct timeval next;
|
||||
struct ast_frame *f;
|
||||
struct myframe {
|
||||
struct ast_frame f;
|
||||
char offset[AST_FRIENDLY_OFFSET];
|
||||
short frdata[160];
|
||||
} myf;
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
if (socketpair(AF_LOCAL, SOCK_STREAM, 0, fds)) {
|
||||
ast_log(LOG_WARNING, "Unable to create socketpair\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ast_stopstream(chan);
|
||||
|
||||
owriteformat = chan->writeformat;
|
||||
res = ast_set_write_format(chan, AST_FORMAT_SLINEAR);
|
||||
if (res < 0) {
|
||||
ast_log(LOG_WARNING, "Unable to set write format to signed linear\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = NBScatplay(fds[1]);
|
||||
/* Wait 1000 ms first */
|
||||
next = ast_tvnow();
|
||||
next.tv_sec += 1;
|
||||
if (res >= 0) {
|
||||
pid = res;
|
||||
/* Order is important -- there's almost always going to be mp3... we want to prioritize the
|
||||
user */
|
||||
for (;;) {
|
||||
ms = ast_tvdiff_ms(next, ast_tvnow());
|
||||
if (ms <= 0) {
|
||||
res = timed_read(fds[0], myf.frdata, sizeof(myf.frdata));
|
||||
if (res > 0) {
|
||||
myf.f.frametype = AST_FRAME_VOICE;
|
||||
myf.f.subclass = AST_FORMAT_SLINEAR;
|
||||
myf.f.datalen = res;
|
||||
myf.f.samples = res / 2;
|
||||
myf.f.mallocd = 0;
|
||||
myf.f.offset = AST_FRIENDLY_OFFSET;
|
||||
myf.f.src = __PRETTY_FUNCTION__;
|
||||
myf.f.delivery.tv_sec = 0;
|
||||
myf.f.delivery.tv_usec = 0;
|
||||
myf.f.data = myf.frdata;
|
||||
if (ast_write(chan, &myf.f) < 0) {
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
ast_log(LOG_DEBUG, "No more mp3\n");
|
||||
res = 0;
|
||||
break;
|
||||
}
|
||||
next = ast_tvadd(next, ast_samp2tv(myf.f.samples, 8000));
|
||||
} else {
|
||||
ms = ast_waitfor(chan, ms);
|
||||
if (ms < 0) {
|
||||
ast_log(LOG_DEBUG, "Hangup detected\n");
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
if (ms) {
|
||||
f = ast_read(chan);
|
||||
if (!f) {
|
||||
ast_log(LOG_DEBUG, "Null frame == hangup() detected\n");
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
if (f->frametype == AST_FRAME_DTMF) {
|
||||
ast_log(LOG_DEBUG, "User pressed a key\n");
|
||||
ast_frfree(f);
|
||||
res = 0;
|
||||
break;
|
||||
}
|
||||
ast_frfree(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
close(fds[0]);
|
||||
close(fds[1]);
|
||||
|
||||
if (pid > -1)
|
||||
kill(pid, SIGKILL);
|
||||
if (!res && owriteformat)
|
||||
ast_set_write_format(chan, owriteformat);
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app);
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(app, NBScat_exec, synopsis, descrip);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
375
apps/app_osplookup.c
Normal file
375
apps/app_osplookup.c
Normal file
@@ -0,0 +1,375 @@
|
||||
/*
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Copyright (C) 1999 - 2005, Digium, Inc.
|
||||
*
|
||||
* Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief Open Settlement Protocol Lookup
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/lock.h"
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/options.h"
|
||||
#include "asterisk/config.h"
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/utils.h"
|
||||
#include "asterisk/causes.h"
|
||||
#include "asterisk/astosp.h"
|
||||
#include "asterisk/app.h"
|
||||
#include "asterisk/options.h"
|
||||
|
||||
static char *tdesc = "OSP Lookup";
|
||||
|
||||
static char *app = "OSPLookup";
|
||||
static char *app2 = "OSPNext";
|
||||
static char *app3 = "OSPFinish";
|
||||
|
||||
static char *synopsis = "Lookup number in OSP";
|
||||
static char *synopsis2 = "Lookup next OSP entry";
|
||||
static char *synopsis3 = "Record OSP entry";
|
||||
|
||||
static char *descrip =
|
||||
" OSPLookup(exten[|provider[|options]]): Looks up an extension via OSP and sets\n"
|
||||
"the variables, where 'n' is the number of the result beginning with 1:\n"
|
||||
" ${OSPTECH}: The technology to use for the call\n"
|
||||
" ${OSPDEST}: The destination to use for the call\n"
|
||||
" ${OSPTOKEN}: The actual OSP token as a string\n"
|
||||
" ${OSPHANDLE}: The OSP Handle for anything remaining\n"
|
||||
" ${OSPRESULTS}: The number of OSP results total remaining\n"
|
||||
"\n"
|
||||
"The option string may contain the following character:\n"
|
||||
" 'j' -- jump to n+101 priority if the lookup was NOT successful\n"
|
||||
"This application sets the following channel variable upon completion:\n"
|
||||
" OSPLOOKUPSTATUS The status of the OSP Lookup attempt as a text string, one of\n"
|
||||
" SUCCESS | FAILED \n";
|
||||
|
||||
|
||||
static char *descrip2 =
|
||||
" OSPNext(cause[|options]): Looks up the next OSP Destination for ${OSPHANDLE}\n"
|
||||
"See OSPLookup for more information\n"
|
||||
"\n"
|
||||
"The option string may contain the following character:\n"
|
||||
" 'j' -- jump to n+101 priority if the lookup was NOT successful\n"
|
||||
"This application sets the following channel variable upon completion:\n"
|
||||
" OSPNEXTSTATUS The status of the OSP Next attempt as a text string, one of\n"
|
||||
" SUCCESS | FAILED \n";
|
||||
|
||||
static char *descrip3 =
|
||||
" OSPFinish(status[|options]): Records call state for ${OSPHANDLE}, according to\n"
|
||||
"status, which should be one of BUSY, CONGESTION, ANSWER, NOANSWER, or CHANUNAVAIL\n"
|
||||
"or coincidentally, just what the Dial application stores in its ${DIALSTATUS}.\n"
|
||||
"\n"
|
||||
"The option string may contain the following character:\n"
|
||||
" 'j' -- jump to n+101 priority if the finish attempt was NOT successful\n"
|
||||
"This application sets the following channel variable upon completion:\n"
|
||||
" OSPFINISHSTATUS The status of the OSP Finish attempt as a text string, one of\n"
|
||||
" SUCCESS | FAILED \n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int str2cause(char *cause)
|
||||
{
|
||||
if (!strcasecmp(cause, "BUSY"))
|
||||
return AST_CAUSE_BUSY;
|
||||
if (!strcasecmp(cause, "CONGESTION"))
|
||||
return AST_CAUSE_CONGESTION;
|
||||
if (!strcasecmp(cause, "ANSWER"))
|
||||
return AST_CAUSE_NORMAL;
|
||||
if (!strcasecmp(cause, "CANCEL"))
|
||||
return AST_CAUSE_NORMAL;
|
||||
if (!strcasecmp(cause, "NOANSWER"))
|
||||
return AST_CAUSE_NOANSWER;
|
||||
if (!strcasecmp(cause, "NOCHANAVAIL"))
|
||||
return AST_CAUSE_CONGESTION;
|
||||
ast_log(LOG_WARNING, "Unknown cause '%s', using NORMAL\n", cause);
|
||||
return AST_CAUSE_NORMAL;
|
||||
}
|
||||
|
||||
static int osplookup_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0;
|
||||
struct localuser *u;
|
||||
char *temp;
|
||||
struct ast_osp_result result;
|
||||
int priority_jump = 0;
|
||||
AST_DECLARE_APP_ARGS(args,
|
||||
AST_APP_ARG(extension);
|
||||
AST_APP_ARG(provider);
|
||||
AST_APP_ARG(options);
|
||||
);
|
||||
|
||||
if (ast_strlen_zero(data)) {
|
||||
ast_log(LOG_WARNING, "OSPLookup requires an argument OSPLookup(exten[|provider[|options]])\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
temp = ast_strdupa(data);
|
||||
if (!temp) {
|
||||
ast_log(LOG_ERROR, "Out of memory!\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
AST_STANDARD_APP_ARGS(args, temp);
|
||||
|
||||
if (args.options) {
|
||||
if (strchr(args.options, 'j'))
|
||||
priority_jump = 1;
|
||||
}
|
||||
|
||||
ast_log(LOG_DEBUG, "Whoo hoo, looking up OSP on '%s' via '%s'\n", args.extension, args.provider ? args.provider : "<default>");
|
||||
if ((res = ast_osp_lookup(chan, args.provider, args.extension, chan->cid.cid_num, &result)) > 0) {
|
||||
char tmp[80];
|
||||
snprintf(tmp, sizeof(tmp), "%d", result.handle);
|
||||
pbx_builtin_setvar_helper(chan, "_OSPHANDLE", tmp);
|
||||
pbx_builtin_setvar_helper(chan, "_OSPTECH", result.tech);
|
||||
pbx_builtin_setvar_helper(chan, "_OSPDEST", result.dest);
|
||||
pbx_builtin_setvar_helper(chan, "_OSPTOKEN", result.token);
|
||||
snprintf(tmp, sizeof(tmp), "%d", result.numresults);
|
||||
pbx_builtin_setvar_helper(chan, "_OSPRESULTS", tmp);
|
||||
pbx_builtin_setvar_helper(chan, "OSPLOOKUPSTATUS", "SUCCESS");
|
||||
|
||||
} else {
|
||||
if (!res) {
|
||||
ast_log(LOG_NOTICE, "OSP Lookup failed for '%s' (provider '%s')\n", args.extension, args.provider ? args.provider : "<default>");
|
||||
pbx_builtin_setvar_helper(chan, "OSPLOOKUPSTATUS", "FAILED");
|
||||
} else
|
||||
ast_log(LOG_DEBUG, "Got hangup on '%s' while doing OSP Lookup for '%s' (provider '%s')!\n", chan->name, args.extension, args.provider ? args.provider : "<default>" );
|
||||
}
|
||||
if (!res) {
|
||||
/* Look for a "busy" place */
|
||||
if (priority_jump || option_priority_jumping)
|
||||
ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
|
||||
} else if (res > 0)
|
||||
res = 0;
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int ospnext_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0;
|
||||
struct localuser *u;
|
||||
char *temp;
|
||||
int cause;
|
||||
struct ast_osp_result result;
|
||||
int priority_jump = 0;
|
||||
AST_DECLARE_APP_ARGS(args,
|
||||
AST_APP_ARG(cause);
|
||||
AST_APP_ARG(options);
|
||||
);
|
||||
|
||||
if (ast_strlen_zero(data)) {
|
||||
ast_log(LOG_WARNING, "OSPNext should have an argument (cause[|options])\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
temp = ast_strdupa(data);
|
||||
if (!temp) {
|
||||
ast_log(LOG_ERROR, "Out of memory!\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
AST_STANDARD_APP_ARGS(args, temp);
|
||||
|
||||
if (args.options) {
|
||||
if (strchr(args.options, 'j'))
|
||||
priority_jump = 1;
|
||||
}
|
||||
|
||||
cause = str2cause(args.cause);
|
||||
temp = pbx_builtin_getvar_helper(chan, "OSPHANDLE");
|
||||
result.handle = -1;
|
||||
if (!ast_strlen_zero(temp) && (sscanf(temp, "%d", &result.handle) == 1) && (result.handle > -1)) {
|
||||
temp = pbx_builtin_getvar_helper(chan, "OSPRESULTS");
|
||||
if (ast_strlen_zero(temp) || (sscanf(temp, "%d", &result.numresults) != 1)) {
|
||||
result.numresults = 0;
|
||||
}
|
||||
if ((res = ast_osp_next(&result, cause)) > 0) {
|
||||
char tmp[80];
|
||||
snprintf(tmp, sizeof(tmp), "%d", result.handle);
|
||||
pbx_builtin_setvar_helper(chan, "_OSPHANDLE", tmp);
|
||||
pbx_builtin_setvar_helper(chan, "_OSPTECH", result.tech);
|
||||
pbx_builtin_setvar_helper(chan, "_OSPDEST", result.dest);
|
||||
pbx_builtin_setvar_helper(chan, "_OSPTOKEN", result.token);
|
||||
snprintf(tmp, sizeof(tmp), "%d", result.numresults);
|
||||
pbx_builtin_setvar_helper(chan, "_OSPRESULTS", tmp);
|
||||
pbx_builtin_setvar_helper(chan, "OSPNEXTSTATUS", "SUCCESS");
|
||||
}
|
||||
} else {
|
||||
if (!res) {
|
||||
if (result.handle < 0)
|
||||
ast_log(LOG_NOTICE, "OSP Lookup Next failed for handle '%d'\n", result.handle);
|
||||
else
|
||||
ast_log(LOG_DEBUG, "No OSP handle specified\n");
|
||||
pbx_builtin_setvar_helper(chan, "OSPNEXTSTATUS", "FAILED");
|
||||
} else
|
||||
ast_log(LOG_DEBUG, "Got hangup on '%s' while doing OSP Next!\n", chan->name);
|
||||
}
|
||||
if (!res) {
|
||||
/* Look for a "busy" place */
|
||||
if (priority_jump || option_priority_jumping)
|
||||
ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
|
||||
} else if (res > 0)
|
||||
res = 0;
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int ospfinished_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0;
|
||||
struct localuser *u;
|
||||
char *temp;
|
||||
int cause;
|
||||
time_t start=0, duration=0;
|
||||
struct ast_osp_result result;
|
||||
int priority_jump = 0;
|
||||
AST_DECLARE_APP_ARGS(args,
|
||||
AST_APP_ARG(status);
|
||||
AST_APP_ARG(options);
|
||||
);
|
||||
|
||||
if (ast_strlen_zero(data)) {
|
||||
ast_log(LOG_WARNING, "OSPFinish should have an argument (status[|options])\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
temp = ast_strdupa(data);
|
||||
if (!temp) {
|
||||
ast_log(LOG_ERROR, "Out of memory!\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
AST_STANDARD_APP_ARGS(args, temp);
|
||||
|
||||
if (args.options) {
|
||||
if (strchr(args.options, 'j'))
|
||||
priority_jump = 1;
|
||||
}
|
||||
|
||||
if (chan->cdr) {
|
||||
start = chan->cdr->answer.tv_sec;
|
||||
if (start)
|
||||
duration = time(NULL) - start;
|
||||
else
|
||||
duration = 0;
|
||||
} else
|
||||
ast_log(LOG_WARNING, "OSPFinish called on channel '%s' with no CDR!\n", chan->name);
|
||||
|
||||
cause = str2cause(args.status);
|
||||
temp = pbx_builtin_getvar_helper(chan, "OSPHANDLE");
|
||||
result.handle = -1;
|
||||
if (!ast_strlen_zero(temp) && (sscanf(temp, "%d", &result.handle) == 1) && (result.handle > -1)) {
|
||||
if (!ast_osp_terminate(result.handle, cause, start, duration)) {
|
||||
pbx_builtin_setvar_helper(chan, "_OSPHANDLE", "");
|
||||
pbx_builtin_setvar_helper(chan, "OSPFINISHSTATUS", "SUCCESS");
|
||||
res = 1;
|
||||
}
|
||||
} else {
|
||||
if (!res) {
|
||||
if (result.handle > -1)
|
||||
ast_log(LOG_NOTICE, "OSP Finish failed for handle '%d'\n", result.handle);
|
||||
else
|
||||
ast_log(LOG_DEBUG, "No OSP handle specified\n");
|
||||
pbx_builtin_setvar_helper(chan, "OSPFINISHSTATUS", "FAILED");
|
||||
} else
|
||||
ast_log(LOG_DEBUG, "Got hangup on '%s' while doing OSP Terminate!\n", chan->name);
|
||||
}
|
||||
if (!res) {
|
||||
/* Look for a "busy" place */
|
||||
if (priority_jump || option_priority_jumping)
|
||||
ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
|
||||
} else if (res > 0)
|
||||
res = 0;
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app3);
|
||||
res |= ast_unregister_application(app2);
|
||||
res |= ast_unregister_application(app);
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_register_application(app, osplookup_exec, synopsis, descrip);
|
||||
res |= ast_register_application(app2, ospnext_exec, synopsis2, descrip2);
|
||||
res |= ast_register_application(app3, ospfinished_exec, synopsis3, descrip3);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int reload(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
|
||||
234
apps/app_page.c
Normal file
234
apps/app_page.c
Normal file
@@ -0,0 +1,234 @@
|
||||
/*
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Copyright (c) 2004 - 2005 Digium, Inc. All rights reserved.
|
||||
*
|
||||
* Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* This code is released under the GNU General Public License
|
||||
* version 2.0. See LICENSE for more information.
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief page() - Paging application
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/options.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/app.h"
|
||||
#include "asterisk/chanvars.h"
|
||||
|
||||
|
||||
static const char *tdesc = "Page Multiple Phones";
|
||||
|
||||
static const char *app_page= "Page";
|
||||
|
||||
static const char *page_synopsis = "Pages phones";
|
||||
|
||||
static const char *page_descrip =
|
||||
"Page(Technology/Resource&Technology2/Resource2[|options])\n"
|
||||
" Places outbound calls to the given technology / resource and dumps\n"
|
||||
"them into a conference bridge as muted participants. The original\n"
|
||||
"caller is dumped into the conference as a speaker and the room is\n"
|
||||
"destroyed when the original caller leaves. Valid options are:\n"
|
||||
" d - full duplex audio\n"
|
||||
" q - quiet, do not play beep to caller\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
enum {
|
||||
PAGE_DUPLEX = (1 << 0),
|
||||
PAGE_QUIET = (1 << 1),
|
||||
} page_opt_flags;
|
||||
|
||||
AST_APP_OPTIONS(page_opts, {
|
||||
AST_APP_OPTION('d', PAGE_DUPLEX),
|
||||
AST_APP_OPTION('q', PAGE_QUIET),
|
||||
});
|
||||
|
||||
struct calloutdata {
|
||||
char cidnum[64];
|
||||
char cidname[64];
|
||||
char tech[64];
|
||||
char resource[256];
|
||||
char meetmeopts[64];
|
||||
struct ast_variable *variables;
|
||||
};
|
||||
|
||||
static void *page_thread(void *data)
|
||||
{
|
||||
struct calloutdata *cd = data;
|
||||
ast_pbx_outgoing_app(cd->tech, AST_FORMAT_SLINEAR, cd->resource, 30000,
|
||||
"MeetMe", cd->meetmeopts, NULL, 0, cd->cidnum, cd->cidname, cd->variables, NULL);
|
||||
free(cd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void launch_page(struct ast_channel *chan, const char *meetmeopts, const char *tech, const char *resource)
|
||||
{
|
||||
struct calloutdata *cd;
|
||||
const char *varname;
|
||||
struct ast_variable *lastvar = NULL;
|
||||
struct ast_var_t *varptr;
|
||||
pthread_t t;
|
||||
pthread_attr_t attr;
|
||||
cd = malloc(sizeof(struct calloutdata));
|
||||
if (cd) {
|
||||
memset(cd, 0, sizeof(struct calloutdata));
|
||||
ast_copy_string(cd->cidnum, chan->cid.cid_num ? chan->cid.cid_num : "", sizeof(cd->cidnum));
|
||||
ast_copy_string(cd->cidname, chan->cid.cid_name ? chan->cid.cid_name : "", sizeof(cd->cidname));
|
||||
ast_copy_string(cd->tech, tech, sizeof(cd->tech));
|
||||
ast_copy_string(cd->resource, resource, sizeof(cd->resource));
|
||||
ast_copy_string(cd->meetmeopts, meetmeopts, sizeof(cd->meetmeopts));
|
||||
|
||||
AST_LIST_TRAVERSE(&chan->varshead, varptr, entries) {
|
||||
if (!(varname = ast_var_full_name(varptr)))
|
||||
continue;
|
||||
if (varname[0] == '_') {
|
||||
struct ast_variable *newvar = NULL;
|
||||
|
||||
if (varname[1] == '_') {
|
||||
newvar = ast_variable_new(varname, ast_var_value(varptr));
|
||||
} else {
|
||||
newvar = ast_variable_new(&varname[1], ast_var_value(varptr));
|
||||
}
|
||||
|
||||
if (newvar) {
|
||||
if (lastvar)
|
||||
lastvar->next = newvar;
|
||||
else
|
||||
cd->variables = newvar;
|
||||
lastvar = newvar;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pthread_attr_init(&attr);
|
||||
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||||
if (ast_pthread_create(&t, &attr, page_thread, cd)) {
|
||||
ast_log(LOG_WARNING, "Unable to create paging thread: %s\n", strerror(errno));
|
||||
free(cd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int page_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
struct localuser *u;
|
||||
char *options;
|
||||
char *tech, *resource;
|
||||
char meetmeopts[80];
|
||||
struct ast_flags flags = { 0 };
|
||||
unsigned int confid = rand();
|
||||
struct ast_app *app;
|
||||
char *tmp;
|
||||
int res=0;
|
||||
|
||||
if (ast_strlen_zero(data)) {
|
||||
ast_log(LOG_WARNING, "This application requires at least one argument (destination(s) to page)\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
if (!(app = pbx_findapp("MeetMe"))) {
|
||||
ast_log(LOG_WARNING, "There is no MeetMe application available!\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
};
|
||||
|
||||
options = ast_strdupa(data);
|
||||
if (!options) {
|
||||
ast_log(LOG_ERROR, "Out of memory\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
tmp = strsep(&options, "|");
|
||||
if (options)
|
||||
ast_app_parse_options(page_opts, &flags, NULL, options);
|
||||
|
||||
snprintf(meetmeopts, sizeof(meetmeopts), "%ud|%sqxdw", confid, ast_test_flag(&flags, PAGE_DUPLEX) ? "" : "m");
|
||||
while ((tech = strsep(&tmp, "&"))) {
|
||||
if ((resource = strchr(tech, '/'))) {
|
||||
*resource++ = '\0';
|
||||
launch_page(chan, meetmeopts, tech, resource);
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "Incomplete destination '%s' supplied.\n", tech);
|
||||
}
|
||||
}
|
||||
if (!ast_test_flag(&flags, PAGE_QUIET)) {
|
||||
res = ast_streamfile(chan, "beep", chan->language);
|
||||
if (!res)
|
||||
res = ast_waitstream(chan, "");
|
||||
}
|
||||
if (!res) {
|
||||
snprintf(meetmeopts, sizeof(meetmeopts), "%ud|A%sqxd", confid, ast_test_flag(&flags, PAGE_DUPLEX) ? "" : "t");
|
||||
pbx_exec(chan, app, meetmeopts, 1);
|
||||
}
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app_page);
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(app_page, page_exec, page_synopsis, page_descrip);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return (char *) tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
STANDARD_USECOUNT(res);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
360
apps/app_parkandannounce.c
Executable file → Normal file
360
apps/app_parkandannounce.c
Executable file → Normal file
@@ -1,37 +1,51 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Copyright (C) 1999 - 2005, Digium, Inc.
|
||||
*
|
||||
* Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* ParkAndAnnounce application for Asterisk
|
||||
* Author: Ben Miller <bgmiller@dccinc.com>
|
||||
* With TONS of help from Mark!
|
||||
*
|
||||
* Asterisk is Copyrighted as follows
|
||||
* Copyright (C) 1999, Mark Spencer
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/channel_pvt.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/parking.h>
|
||||
#include <asterisk/options.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/say.h>
|
||||
/*! \file
|
||||
*
|
||||
* \brief ParkAndAnnounce application for Asterisk
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <pthread.h>
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/features.h"
|
||||
#include "asterisk/options.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/say.h"
|
||||
#include "asterisk/lock.h"
|
||||
|
||||
static char *tdesc = "Call Parking and Announce Application";
|
||||
|
||||
@@ -42,7 +56,7 @@ static char *synopsis = "Park and Announce";
|
||||
static char *descrip =
|
||||
" ParkAndAnnounce(announce:template|timeout|dial|[return_context]):\n"
|
||||
"Park a call into the parkinglot and announce the call over the console.\n"
|
||||
"announce template: colon seperated list of files to announce, the word PARKED\n"
|
||||
"announce template: colon separated list of files to announce, the word PARKED\n"
|
||||
" will be replaced by a say_digits of the ext the call is parked in\n"
|
||||
"timeout: time in seconds before the call returns into the return context.\n"
|
||||
"dial: The app_dial style resource to call to make the announcement. Console/dsp calls the console.\n"
|
||||
@@ -55,184 +69,198 @@ LOCAL_USER_DECL;
|
||||
|
||||
static int parkandannounce_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0;
|
||||
char *return_context;
|
||||
int l, lot, timeout, dres;
|
||||
char *working, *context, *exten, *priority, *dial, *dialtech, *dialstr;
|
||||
char *template, *tpl_working, *tpl_current;
|
||||
char *tmp[100];
|
||||
int looptemp=0,i=0;
|
||||
char *s,*orig_s;
|
||||
int res=0;
|
||||
char *return_context;
|
||||
int l, lot, timeout = 0, dres;
|
||||
char *working, *context, *exten, *priority, *dial, *dialtech, *dialstr;
|
||||
char *template, *tpl_working, *tpl_current;
|
||||
char *tmp[100];
|
||||
int looptemp=0,i=0;
|
||||
char *s,*orig_s;
|
||||
|
||||
struct ast_channel *dchan;
|
||||
int outstate;
|
||||
struct ast_channel *dchan;
|
||||
struct outgoing_helper oh;
|
||||
int outstate;
|
||||
|
||||
struct localuser *u;
|
||||
if (!data) {
|
||||
ast_log(LOG_WARNING, "Park requires an argument (parkinglot)\n");
|
||||
return -1;
|
||||
}
|
||||
struct localuser *u;
|
||||
|
||||
if (ast_strlen_zero(data)) {
|
||||
ast_log(LOG_WARNING, "ParkAndAnnounce requires arguments: (announce:template|timeout|dial|[return_context])\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
l=strlen(data)+2;
|
||||
orig_s=malloc(l);
|
||||
s=orig_s;
|
||||
strncpy(s,data,l);
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
template=strsep(&s,"|");
|
||||
if (! template) {
|
||||
ast_log(LOG_WARNING, "PARK: An announce template must be defined\n");
|
||||
free(orig_s);
|
||||
return -1;
|
||||
}
|
||||
l=strlen(data)+2;
|
||||
orig_s=malloc(l);
|
||||
if(!orig_s) {
|
||||
ast_log(LOG_WARNING, "Out of memory\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
s=orig_s;
|
||||
strncpy(s,data,l);
|
||||
|
||||
template=strsep(&s,"|");
|
||||
if(! template) {
|
||||
ast_log(LOG_WARNING, "PARK: An announce template must be defined\n");
|
||||
free(orig_s);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
timeout = atoi(strsep(&s, "|"));
|
||||
timeout *= 1000;
|
||||
if(s) {
|
||||
timeout = atoi(strsep(&s, "|"));
|
||||
timeout *= 1000;
|
||||
}
|
||||
dial=strsep(&s, "|");
|
||||
if(!dial) {
|
||||
ast_log(LOG_WARNING, "PARK: A dial resource must be specified i.e: Console/dsp or Zap/g1/5551212\n");
|
||||
free(orig_s);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
} else {
|
||||
dialtech=strsep(&dial, "/");
|
||||
dialstr=dial;
|
||||
ast_verbose( VERBOSE_PREFIX_3 "Dial Tech,String: (%s,%s)\n", dialtech,dialstr);
|
||||
}
|
||||
|
||||
dial=strsep(&s, "|");
|
||||
if (! dial) {
|
||||
ast_log(LOG_WARNING, "PARK: A dial resouce must be specified i.e: Console/dsp or Zap/g1/5551212\n");
|
||||
free(orig_s);
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
dialtech=strsep(&dial, "/");
|
||||
dialstr=dial;
|
||||
ast_verbose( VERBOSE_PREFIX_3 "Dial Tech,String: (%s,%s)\n", dialtech,dialstr);
|
||||
}
|
||||
|
||||
return_context = s;
|
||||
return_context = s;
|
||||
|
||||
if (return_context != NULL) {
|
||||
/* set the return context. Code borrowed from the Goto builtin */
|
||||
if(return_context != NULL) {
|
||||
/* set the return context. Code borrowed from the Goto builtin */
|
||||
|
||||
working = return_context;
|
||||
context = strsep(&working, "|");
|
||||
exten = strsep(&working, "|");
|
||||
if (!exten) {
|
||||
/* Only a priority in this one */
|
||||
priority = context;
|
||||
exten = NULL;
|
||||
context = NULL;
|
||||
} else {
|
||||
priority = strsep(&working, "|");
|
||||
if (!priority) {
|
||||
/* Only an extension and priority in this one */
|
||||
priority = exten;
|
||||
exten = context;
|
||||
context = NULL;
|
||||
}
|
||||
}
|
||||
if (atoi(priority) < 0) {
|
||||
ast_log(LOG_WARNING, "Priority '%s' must be a number > 0\n", priority);
|
||||
free(orig_s);
|
||||
return -1;
|
||||
}
|
||||
/* At this point we have a priority and maybe an extension and a context */
|
||||
chan->priority = atoi(priority);
|
||||
if (exten && strcasecmp(exten, "BYEXTENSION"))
|
||||
strncpy(chan->exten, exten, sizeof(chan->exten)-1);
|
||||
if (context)
|
||||
strncpy(chan->context, context, sizeof(chan->context)-1);
|
||||
}
|
||||
else { /* increment the priority by default*/
|
||||
chan->priority++;
|
||||
}
|
||||
working = return_context;
|
||||
context = strsep(&working, "|");
|
||||
exten = strsep(&working, "|");
|
||||
if(!exten) {
|
||||
/* Only a priority in this one */
|
||||
priority = context;
|
||||
exten = NULL;
|
||||
context = NULL;
|
||||
} else {
|
||||
priority = strsep(&working, "|");
|
||||
if(!priority) {
|
||||
/* Only an extension and priority in this one */
|
||||
priority = exten;
|
||||
exten = context;
|
||||
context = NULL;
|
||||
}
|
||||
}
|
||||
if(atoi(priority) < 0) {
|
||||
ast_log(LOG_WARNING, "Priority '%s' must be a number > 0\n", priority);
|
||||
free(orig_s);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
/* At this point we have a priority and maybe an extension and a context */
|
||||
chan->priority = atoi(priority);
|
||||
if(exten && strcasecmp(exten, "BYEXTENSION"))
|
||||
strncpy(chan->exten, exten, sizeof(chan->exten)-1);
|
||||
if(context)
|
||||
strncpy(chan->context, context, sizeof(chan->context)-1);
|
||||
} else { /* increment the priority by default*/
|
||||
chan->priority++;
|
||||
}
|
||||
|
||||
|
||||
if (option_verbose > 2) {
|
||||
ast_verbose( VERBOSE_PREFIX_3 "Return Context: (%s,%s,%d) ID: %s\n", chan->context,chan->exten, chan->priority, chan->callerid);
|
||||
if (!ast_exists_extension(chan, chan->context, chan->exten, chan->priority, chan->callerid)) {
|
||||
ast_verbose( VERBOSE_PREFIX_3 "Warning: Return Context Invalid, call will return to default|s\n");
|
||||
}
|
||||
}
|
||||
if(option_verbose > 2) {
|
||||
ast_verbose( VERBOSE_PREFIX_3 "Return Context: (%s,%s,%d) ID: %s\n", chan->context,chan->exten, chan->priority, chan->cid.cid_num);
|
||||
if(!ast_exists_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num)) {
|
||||
ast_verbose( VERBOSE_PREFIX_3 "Warning: Return Context Invalid, call will return to default|s\n");
|
||||
}
|
||||
}
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
/* we are using masq_park here to protect * from touching the channel once we park it. If the channel comes out of timeout
|
||||
before we are done announcing and the channel is messed with, Kablooeee. So we use Masq to prevent this. */
|
||||
|
||||
/* we are using masq_park here to protect * from touching the channel once we park it. If the channel comes out of timeout
|
||||
before we are done announcing and the channel is messed with, Kablooeee. So we use Masq to prevent this. */
|
||||
ast_masq_park_call(chan, NULL, timeout, &lot);
|
||||
|
||||
ast_masq_park_call(chan, NULL, timeout, &lot);
|
||||
res=-1;
|
||||
|
||||
res=-1;
|
||||
ast_verbose( VERBOSE_PREFIX_3 "Call Parking Called, lot: %d, timeout: %d, context: %s\n", lot, timeout, return_context);
|
||||
|
||||
ast_verbose( VERBOSE_PREFIX_3 "Call Parking Called, lot: %d, timeout: %d, context: %s\n", lot, timeout, return_context);
|
||||
/* Now place the call to the extention */
|
||||
|
||||
/* Now place the call to the extention */
|
||||
memset(&oh, 0, sizeof(oh));
|
||||
oh.parent_channel = chan;
|
||||
dchan = __ast_request_and_dial(dialtech, AST_FORMAT_SLINEAR, dialstr,30000, &outstate, chan->cid.cid_num, chan->cid.cid_name, &oh);
|
||||
|
||||
dchan = ast_request_and_dial(dialtech, AST_FORMAT_SLINEAR, dialstr,30000, &outstate, chan->callerid);
|
||||
if(dchan) {
|
||||
if(dchan->_state == AST_STATE_UP) {
|
||||
if(option_verbose > 3)
|
||||
ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", dchan->name);
|
||||
} else {
|
||||
if(option_verbose > 3)
|
||||
ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", dchan->name);
|
||||
ast_log(LOG_WARNING, "PARK: Channel %s was never answered for the announce.\n", dchan->name);
|
||||
ast_hangup(dchan);
|
||||
free(orig_s);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "PARK: Unable to allocate announce channel.\n");
|
||||
free(orig_s);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (dchan) {
|
||||
if (dchan->_state == AST_STATE_UP) {
|
||||
if (option_verbose > 3)
|
||||
ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", dchan->name);
|
||||
} else {
|
||||
if (option_verbose > 3)
|
||||
ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", dchan->name);
|
||||
ast_log(LOG_WARNING, "PARK: Channel %s was never answered for the announce.\n", dchan->name);
|
||||
ast_hangup(dchan);
|
||||
free(orig_s);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ast_log(LOG_WARNING, "PARK: Unable to allocate announce channel.\n");
|
||||
free(orig_s);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
ast_stopstream(dchan);
|
||||
|
||||
ast_stopstream(dchan);
|
||||
/* now we have the call placed and are ready to play stuff to it */
|
||||
|
||||
/* now we have the call placed and are ready to play stuff to it */
|
||||
ast_verbose(VERBOSE_PREFIX_4 "Announce Template:%s\n", template);
|
||||
|
||||
ast_verbose(VERBOSE_PREFIX_4 "Announce Template:%s\n", template);
|
||||
tpl_working = template;
|
||||
tpl_current=strsep(&tpl_working, ":");
|
||||
|
||||
tpl_working = template;
|
||||
tpl_current=strsep(&tpl_working, ":");
|
||||
while(tpl_current && looptemp < sizeof(tmp)) {
|
||||
tmp[looptemp]=tpl_current;
|
||||
looptemp++;
|
||||
tpl_current=strsep(&tpl_working,":");
|
||||
}
|
||||
|
||||
while ( tpl_current && looptemp < sizeof(tmp)) {
|
||||
tmp[looptemp]=tpl_current;
|
||||
looptemp++;
|
||||
tpl_current=strsep(&tpl_working,":");
|
||||
}
|
||||
for(i=0; i<looptemp; i++) {
|
||||
ast_verbose(VERBOSE_PREFIX_4 "Announce:%s\n", tmp[i]);
|
||||
if(!strcmp(tmp[i], "PARKED")) {
|
||||
ast_say_digits(dchan, lot, "", dchan->language);
|
||||
} else {
|
||||
dres = ast_streamfile(dchan, tmp[i], dchan->language);
|
||||
if(!dres) {
|
||||
dres = ast_waitstream(dchan, "");
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", tmp[i], dchan->name);
|
||||
dres = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(i=0; i<looptemp; i++) {
|
||||
ast_verbose(VERBOSE_PREFIX_4 "Announce:%s\n", tmp[i]);
|
||||
if (!strcmp(tmp[i], "PARKED")) {
|
||||
ast_say_digits(dchan, lot, "", dchan->language);
|
||||
}
|
||||
else {
|
||||
dres = ast_streamfile(dchan, tmp[i], dchan->language);
|
||||
if (!dres)
|
||||
dres = ast_waitstream(dchan, "");
|
||||
else {
|
||||
ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", tmp[i], dchan->name);
|
||||
dres = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ast_stopstream(dchan);
|
||||
ast_hangup(dchan);
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
free(orig_s);
|
||||
return res;
|
||||
ast_stopstream(dchan);
|
||||
ast_hangup(dchan);
|
||||
free(orig_s);
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app);
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
/* return ast_register_application(app, park_exec); */
|
||||
return ast_register_application(app, parkandannounce_exec, synopsis, descrip);
|
||||
/* return ast_register_application(app, park_exec); */
|
||||
return ast_register_application(app, parkandannounce_exec, synopsis, descrip);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
|
||||
152
apps/app_playback.c
Executable file → Normal file
152
apps/app_playback.c
Executable file → Normal file
@@ -1,43 +1,68 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Trivial application to playback a sound file
|
||||
*
|
||||
* Copyright (C) 1999, Mark Spencer
|
||||
* Copyright (C) 1999 - 2005, Digium, Inc.
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
* Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief Trivial application to playback a sound file
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/translate.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static char *tdesc = "Trivial Playback Application";
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/lock.h"
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/translate.h"
|
||||
#include "asterisk/utils.h"
|
||||
#include "asterisk/options.h"
|
||||
#include "asterisk/app.h"
|
||||
|
||||
static char *tdesc = "Sound File Playback Application";
|
||||
|
||||
static char *app = "Playback";
|
||||
|
||||
static char *synopsis = "Play a file";
|
||||
|
||||
static char *descrip =
|
||||
" Playback(filename[|option]): Plays back a given filename (do not put\n"
|
||||
"extension). Options may also be included following a pipe symbol. The only\n"
|
||||
"defined option at this time is 'skip', which causes the playback of the\n"
|
||||
"message to be skipped if the channel is not in the 'up' state (i.e. it\n"
|
||||
"hasn't been answered yet. If 'skip' is specified, the application will\n"
|
||||
"return immediately should the channel not be off hook. Otherwise, unless\n"
|
||||
"'noanswer' is specified, the channel channel will be answered before the sound\n"
|
||||
"is played. Not all channels support playing messages while on hook. Returns -1\n"
|
||||
"if the channel was hung up, or if the file does not exist. Returns 0 otherwise.\n";
|
||||
" Playback(filename[&filename2...][|option]): Plays back given filenames (do not put\n"
|
||||
"extension). Options may also be included following a pipe symbol. The 'skip'\n"
|
||||
"option causes the playback of the message to be skipped if the channel\n"
|
||||
"is not in the 'up' state (i.e. it hasn't been answered yet). If 'skip' is \n"
|
||||
"specified, the application will return immediately should the channel not be\n"
|
||||
"off hook. Otherwise, unless 'noanswer' is specified, the channel will\n"
|
||||
"be answered before the sound is played. Not all channels support playing\n"
|
||||
"messages while still on hook. If 'j' is specified, the application\n"
|
||||
"will jump to priority n+101 if present when a file specified to be played\n"
|
||||
"does not exist.\n"
|
||||
"This application sets the following channel variable upon completion:\n"
|
||||
" PLAYBACKSTATUS The status of the playback attempt as a text string, one of\n"
|
||||
" SUCCESS | FAILED\n"
|
||||
;
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
@@ -45,26 +70,43 @@ LOCAL_USER_DECL;
|
||||
|
||||
static int playback_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res = 0;
|
||||
int res = 0, mres = 0;
|
||||
struct localuser *u;
|
||||
char tmp[256];
|
||||
char *options;
|
||||
char *tmp = NULL;
|
||||
int option_skip=0;
|
||||
int option_noanswer = 0;
|
||||
char *stringp;
|
||||
if (!data || !strlen((char *)data)) {
|
||||
char *front = NULL, *back = NULL;
|
||||
int priority_jump = 0;
|
||||
AST_DECLARE_APP_ARGS(args,
|
||||
AST_APP_ARG(filenames);
|
||||
AST_APP_ARG(options);
|
||||
);
|
||||
|
||||
if (ast_strlen_zero(data)) {
|
||||
ast_log(LOG_WARNING, "Playback requires an argument (filename)\n");
|
||||
return -1;
|
||||
}
|
||||
strncpy(tmp, (char *)data, sizeof(tmp)-1);
|
||||
stringp=tmp;
|
||||
strsep(&stringp, "|");
|
||||
options = strsep(&stringp, "|");
|
||||
if (options && !strcasecmp(options, "skip"))
|
||||
option_skip = 1;
|
||||
if (options && !strcasecmp(options, "noanswer"))
|
||||
option_noanswer = 1;
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
tmp = ast_strdupa(data);
|
||||
if (!tmp) {
|
||||
ast_log(LOG_ERROR, "Out of memory!\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
AST_STANDARD_APP_ARGS(args, tmp);
|
||||
|
||||
if (args.options) {
|
||||
if (strcasestr(args.options, "skip"))
|
||||
option_skip = 1;
|
||||
if (strcasestr(args.options, "noanswer"))
|
||||
option_noanswer = 1;
|
||||
if (strchr(args.options, 'j'))
|
||||
priority_jump = 1;
|
||||
}
|
||||
|
||||
if (chan->_state != AST_STATE_UP) {
|
||||
if (option_skip) {
|
||||
/* At the user's option, skip if the line is not up */
|
||||
@@ -76,14 +118,29 @@ static int playback_exec(struct ast_channel *chan, void *data)
|
||||
}
|
||||
if (!res) {
|
||||
ast_stopstream(chan);
|
||||
res = ast_streamfile(chan, tmp, chan->language);
|
||||
if (!res)
|
||||
res = ast_waitstream(chan, "");
|
||||
else {
|
||||
ast_log(LOG_WARNING, "ast_streamfile failed on %s for %s\n", chan->name, (char *)data);
|
||||
res = 0;
|
||||
front = tmp;
|
||||
while (!res && front) {
|
||||
if ((back = strchr(front, '&'))) {
|
||||
*back = '\0';
|
||||
back++;
|
||||
}
|
||||
res = ast_streamfile(chan, front, chan->language);
|
||||
if (!res) {
|
||||
res = ast_waitstream(chan, "");
|
||||
ast_stopstream(chan);
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "ast_streamfile failed on %s for %s\n", chan->name, (char *)data);
|
||||
if (priority_jump || option_priority_jumping)
|
||||
ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
|
||||
res = 0;
|
||||
mres = 1;
|
||||
}
|
||||
front = back;
|
||||
}
|
||||
ast_stopstream(chan);
|
||||
if (mres)
|
||||
pbx_builtin_setvar_helper(chan, "PLAYBACKSTATUS", "FAILED");
|
||||
else
|
||||
pbx_builtin_setvar_helper(chan, "PLAYBACKSTATUS", "SUCCESS");
|
||||
}
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
@@ -91,8 +148,13 @@ static int playback_exec(struct ast_channel *chan, void *data)
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app);
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
|
||||
207
apps/app_privacy.c
Executable file → Normal file
207
apps/app_privacy.c
Executable file → Normal file
@@ -1,31 +1,49 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Block all calls without Caller*ID, require phone # to be entered
|
||||
*
|
||||
* Copyright (C) 1999, Mark Spencer
|
||||
* Copyright (C) 1999 - 2005, Digium, Inc.
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
* Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief Block all calls without Caller*ID, require phone # to be entered
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/options.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/translate.h>
|
||||
#include <asterisk/image.h>
|
||||
#include <asterisk/callerid.h>
|
||||
#include <asterisk/app.h>
|
||||
#include <asterisk/config.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/lock.h"
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/utils.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/options.h"
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/translate.h"
|
||||
#include "asterisk/image.h"
|
||||
#include "asterisk/callerid.h"
|
||||
#include "asterisk/app.h"
|
||||
#include "asterisk/config.h"
|
||||
|
||||
#define PRIV_CONFIG "privacy.conf"
|
||||
|
||||
@@ -36,40 +54,56 @@ static char *app = "PrivacyManager";
|
||||
static char *synopsis = "Require phone number to be entered, if no CallerID sent";
|
||||
|
||||
static char *descrip =
|
||||
" PrivacyManager: If no Caller*ID is sent, PrivacyManager answers the\n"
|
||||
"channel and asks the caller to enter their 10 digit phone number.\n"
|
||||
"The caller is given 3 attempts. If after 3 attempts, they do not enter\n"
|
||||
"their 10 digit phone number, and if there exists a priority n + 101,\n"
|
||||
"where 'n' is the priority of the current instance, then the\n"
|
||||
"channel will be setup to continue at that priority level.\n"
|
||||
"Otherwise, it returns 0. Does nothing if Caller*ID was received on the\n"
|
||||
"channel.\n";
|
||||
" PrivacyManager([maxretries[|minlength[|options]]]): If no Caller*ID \n"
|
||||
"is sent, PrivacyManager answers the channel and asks the caller to\n"
|
||||
"enter their phone number. The caller is given 3 attempts to do so.\n"
|
||||
"The application does nothing if Caller*ID was received on the channel.\n"
|
||||
" Configuration file privacy.conf contains two variables:\n"
|
||||
" maxretries default 3 -maximum number of attempts the caller is allowed \n"
|
||||
" to input a callerid.\n"
|
||||
" minlength default 10 -minimum allowable digits in the input callerid number.\n"
|
||||
"If you don't want to use the config file and have an i/o operation with\n"
|
||||
"every call, you can also specify maxretries and minlength as application\n"
|
||||
"parameters. Doing so supercedes any values set in privacy.conf.\n"
|
||||
"The option string may contain the following character: \n"
|
||||
" 'j' -- jump to n+101 priority after <maxretries> failed attempts to collect\n"
|
||||
" the minlength number of digits.\n"
|
||||
"The application sets the following channel variable upon completion: \n"
|
||||
"PRIVACYMGRSTATUS The status of the privacy manager's attempt to collect \n"
|
||||
" a phone number from the user. A text string that is either:\n"
|
||||
" SUCCESS | FAILED \n"
|
||||
;
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int
|
||||
privacy_exec (struct ast_channel *chan, void *data)
|
||||
|
||||
|
||||
static int privacy_exec (struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0;
|
||||
int retries;
|
||||
int maxretries = 3;
|
||||
int x;
|
||||
int minlength = 10;
|
||||
int x = 0;
|
||||
char *s;
|
||||
char phone[10];
|
||||
char new_cid[144];
|
||||
char phone[30];
|
||||
struct localuser *u;
|
||||
struct ast_config *cfg;
|
||||
struct ast_config *cfg = NULL;
|
||||
char *parse = NULL;
|
||||
int priority_jump = 0;
|
||||
AST_DECLARE_APP_ARGS(args,
|
||||
AST_APP_ARG(maxretries);
|
||||
AST_APP_ARG(minlength);
|
||||
AST_APP_ARG(options);
|
||||
);
|
||||
|
||||
LOCAL_USER_ADD (u);
|
||||
if (chan->callerid)
|
||||
{
|
||||
if (!ast_strlen_zero(chan->cid.cid_num)) {
|
||||
if (option_verbose > 2)
|
||||
ast_verbose (VERBOSE_PREFIX_3 "CallerID Present: Skipping\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
/*Answer the channel if it is not already*/
|
||||
if (chan->_state != AST_STATE_UP) {
|
||||
res = ast_answer(chan);
|
||||
@@ -78,9 +112,55 @@ privacy_exec (struct ast_channel *chan, void *data)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
/*Read in the config file*/
|
||||
cfg = ast_load(PRIV_CONFIG);
|
||||
|
||||
if (!ast_strlen_zero((char *)data))
|
||||
{
|
||||
parse = ast_strdupa(data);
|
||||
if (!parse) {
|
||||
ast_log(LOG_ERROR, "Out of memory!\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
AST_STANDARD_APP_ARGS(args, parse);
|
||||
|
||||
if (args.maxretries) {
|
||||
if (sscanf(args.maxretries, "%d", &x) == 1)
|
||||
maxretries = x;
|
||||
else
|
||||
ast_log(LOG_WARNING, "Invalid max retries argument\n");
|
||||
}
|
||||
if (args.minlength) {
|
||||
if (sscanf(args.minlength, "%d", &x) == 1)
|
||||
minlength = x;
|
||||
else
|
||||
ast_log(LOG_WARNING, "Invalid min length argument\n");
|
||||
}
|
||||
if (args.options)
|
||||
if (strchr(args.options, 'j'))
|
||||
priority_jump = 1;
|
||||
|
||||
}
|
||||
|
||||
if (!x)
|
||||
{
|
||||
/*Read in the config file*/
|
||||
cfg = ast_config_load(PRIV_CONFIG);
|
||||
|
||||
if (cfg && (s = ast_variable_retrieve(cfg, "general", "maxretries"))) {
|
||||
if (sscanf(s, "%d", &x) == 1)
|
||||
maxretries = x;
|
||||
else
|
||||
ast_log(LOG_WARNING, "Invalid max retries argument\n");
|
||||
}
|
||||
|
||||
if (cfg && (s = ast_variable_retrieve(cfg, "general", "minlength"))) {
|
||||
if (sscanf(s, "%d", &x) == 1)
|
||||
minlength = x;
|
||||
else
|
||||
ast_log(LOG_WARNING, "Invalid min length argument\n");
|
||||
}
|
||||
}
|
||||
|
||||
/*Play unidentified call*/
|
||||
res = ast_safe_sleep(chan, 1000);
|
||||
@@ -89,23 +169,21 @@ privacy_exec (struct ast_channel *chan, void *data)
|
||||
if (!res)
|
||||
res = ast_waitstream(chan, "");
|
||||
|
||||
if (cfg && (s = ast_variable_retrieve(cfg, "general", "maxretries"))) {
|
||||
if (sscanf(s, "%d", &x) == 1) {
|
||||
maxretries = x;
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "Invalid max retries argument\n");
|
||||
}
|
||||
}
|
||||
|
||||
/*Ask for 10 digit number, give 3 attempts*/
|
||||
for (retries = 0; retries < maxretries; retries++) {
|
||||
if (!res)
|
||||
res = ast_app_getdata(chan, "privacy-prompt", phone, sizeof(phone), 0);
|
||||
res = ast_streamfile(chan, "privacy-prompt", chan->language);
|
||||
if (!res)
|
||||
res = ast_waitstream(chan, "");
|
||||
|
||||
if (!res )
|
||||
res = ast_readstring(chan, phone, sizeof(phone) - 1, /* digit timeout ms */ 3200, /* first digit timeout */ 5000, "#");
|
||||
|
||||
if (res < 0)
|
||||
break;
|
||||
|
||||
/*Make sure we get 10 digits*/
|
||||
if (strlen(phone) == 10)
|
||||
/*Make sure we get at least digits*/
|
||||
if (strlen(phone) >= minlength )
|
||||
break;
|
||||
else {
|
||||
res = ast_streamfile(chan, "privacy-incorrect", chan->language);
|
||||
@@ -115,21 +193,21 @@ privacy_exec (struct ast_channel *chan, void *data)
|
||||
}
|
||||
|
||||
/*Got a number, play sounds and send them on their way*/
|
||||
if ((retries < maxretries) && !res) {
|
||||
if ((retries < maxretries) && !res ) {
|
||||
res = ast_streamfile(chan, "privacy-thankyou", chan->language);
|
||||
if (!res)
|
||||
res = ast_waitstream(chan, "");
|
||||
snprintf (new_cid, sizeof (new_cid), "\"%s\" <%s>", "Privacy Manager", phone);
|
||||
ast_set_callerid (chan, new_cid, 0);
|
||||
ast_set_callerid (chan, phone, "Privacy Manager", NULL);
|
||||
if (option_verbose > 2)
|
||||
ast_verbose (VERBOSE_PREFIX_3 "Changed Caller*ID to %s\n",new_cid);
|
||||
ast_verbose (VERBOSE_PREFIX_3 "Changed Caller*ID to %s\n",phone);
|
||||
pbx_builtin_setvar_helper(chan, "PRIVACYMGRSTATUS", "SUCCESS");
|
||||
} else {
|
||||
/*Send the call to n+101 priority, where n is the current priority*/
|
||||
if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->callerid))
|
||||
chan->priority+=100;
|
||||
if (priority_jump || option_priority_jumping)
|
||||
ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
|
||||
pbx_builtin_setvar_helper(chan, "PRIVACYMGRSTATUS", "FAILED");
|
||||
}
|
||||
if (cfg)
|
||||
ast_destroy(cfg);
|
||||
ast_config_destroy(cfg);
|
||||
}
|
||||
|
||||
LOCAL_USER_REMOVE (u);
|
||||
@@ -139,8 +217,13 @@ privacy_exec (struct ast_channel *chan, void *data)
|
||||
int
|
||||
unload_module (void)
|
||||
{
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application (app);
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application (app);
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int
|
||||
|
||||
386
apps/app_qcall.c
386
apps/app_qcall.c
@@ -1,386 +0,0 @@
|
||||
/** @file app_qcall.c
|
||||
*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* Call back a party and connect them to a running pbx thread
|
||||
*
|
||||
* Copyright (C) 1999, Mark Spencer
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
*
|
||||
* Call a user from a file contained within a queue (/var/spool/asterisk/qcall)
|
||||
*
|
||||
* The queue is a directory containing files with the call request information
|
||||
* as a single line of text as follows:
|
||||
*
|
||||
* Dialstring Caller-ID Extension Maxsecs [Identifier] [Required-response]
|
||||
*
|
||||
* Dialstring -- A Dial String (The number to be called) in the
|
||||
* format Technology/Number, such IAX/mysys/1234 or Zap/g1/1234
|
||||
*
|
||||
* Caller-ID -- A Standard nomalized representation of the Caller-ID of
|
||||
* the number being dialed (generally 10 digits in the US). Leave as
|
||||
* "asreceived" to use the default Caller*ID
|
||||
*
|
||||
* Extension -- The Extension (optionally Extension@context) that the
|
||||
* user should be "transferred" to after acceptance of the call.
|
||||
*
|
||||
* Maxsecs -- The Maximum time of the call in seconds. Specify 0 for infinite.
|
||||
*
|
||||
* Identifier -- The "Identifier" of the request. This is used to determine
|
||||
* the names of the audio prompt files played. The first prompt, the one that
|
||||
* asks for the input, is just the exact string specified as the identifier.
|
||||
* The second prompt, the one that is played after the correct input is given,
|
||||
* (generally a "thank you" recording), is the specified string with "-ok"
|
||||
* added to the end. So, if you specify "foo" as the identifier, your first
|
||||
* prompt file that will be played will be "foo" and the second one will be
|
||||
* "foo-ok". If omitted no prompt is given
|
||||
*
|
||||
* Required-Response (Optional) -- Specify a digit string to be used as the
|
||||
* acceptance "code" if you desire it to be something other then "1". This
|
||||
* can be used to implement some sort of PIN or security system. It may be
|
||||
* more then a single character.
|
||||
*
|
||||
* NOTE: It is important to remember that the process that creates these
|
||||
* files needs keep and maintain a write lock (using flock with the LOCK_EX
|
||||
* option) when writing these files.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/translate.h>
|
||||
#include <asterisk/options.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#include <dirent.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/file.h>
|
||||
#include "../astconf.h"
|
||||
|
||||
static char qdir[255];
|
||||
static char *tdesc = "Call from Queue";
|
||||
static pthread_t qcall_thread;
|
||||
static int debug = 0;
|
||||
STANDARD_LOCAL_USER;
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
#define OLDESTOK 14400 /* not any more then this number of secs old */
|
||||
#define INITIALONE 1 /* initial wait before the first one in secs */
|
||||
#define NEXTONE 600 /* wait before trying it again in secs */
|
||||
#define MAXWAITFORANSWER 45000 /* max call time before answer */
|
||||
/* define either one or both of these two if your application requires it */
|
||||
#if 0
|
||||
#define ACCTCODE "SOMETHING" /* Account code */
|
||||
#define AMAFLAGS AST_CDR_BILLING /* AMA flags */
|
||||
#endif
|
||||
/* define this if you want to have a particular CLID display on the user's
|
||||
phone when they receive the call */
|
||||
#if 0
|
||||
#define OURCLID "2564286275" /* The callerid to be displayed when calling */
|
||||
#endif
|
||||
|
||||
static void *qcall_do(void *arg);
|
||||
|
||||
static void *qcall(void *ignore)
|
||||
{
|
||||
pthread_t dialer_thread;
|
||||
DIR *dirp;
|
||||
FILE *fp;
|
||||
struct dirent *dp;
|
||||
char fname[80];
|
||||
struct stat mystat;
|
||||
time_t t;
|
||||
void *arg;
|
||||
pthread_attr_t attr;
|
||||
|
||||
time(&t);
|
||||
if (debug) printf("@@@@ qcall starting at %s",ctime(&t));
|
||||
for(;;)
|
||||
{
|
||||
time(&t);
|
||||
dirp = opendir(qdir);
|
||||
if (!dirp)
|
||||
{
|
||||
perror("app_qcall:Cannot open queue directory");
|
||||
break;
|
||||
}
|
||||
while((dp = readdir(dirp)) != NULL)
|
||||
{
|
||||
if (dp->d_name[0] == '.') continue;
|
||||
sprintf(fname,"%s/%s",qdir,dp->d_name);
|
||||
if (stat(fname,&mystat) == -1)
|
||||
{
|
||||
perror("app_qcall:stat");
|
||||
fprintf(stderr,"%s\n",fname);
|
||||
continue;
|
||||
}
|
||||
/* if not a regular file, skip it */
|
||||
if ((mystat.st_mode & S_IFMT) != S_IFREG) continue;
|
||||
/* if not yet .... */
|
||||
if (mystat.st_atime == mystat.st_mtime)
|
||||
{ /* first time */
|
||||
if ((mystat.st_atime + INITIALONE) > t)
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{ /* already looked at once */
|
||||
if ((mystat.st_atime + NEXTONE) > t) continue;
|
||||
}
|
||||
/* if too old */
|
||||
if (mystat.st_mtime < (t - OLDESTOK))
|
||||
{
|
||||
/* kill it, its too old */
|
||||
unlink(fname);
|
||||
continue;
|
||||
}
|
||||
/* "touch" file's access time */
|
||||
fp = fopen(fname,"r");
|
||||
if (fp) fclose(fp);
|
||||
/* make a copy of the filename string, so that we
|
||||
may go on and use the buffer */
|
||||
arg = (void *) strdup(fname);
|
||||
pthread_attr_init(&attr);
|
||||
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||||
if (pthread_create(&dialer_thread,&attr,qcall_do,arg) == -1)
|
||||
{
|
||||
perror("qcall: Cannot create thread");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
closedir(dirp);
|
||||
sleep(1);
|
||||
}
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
|
||||
/* single thread with one file (request) to dial */
|
||||
static void *qcall_do(void *arg)
|
||||
{
|
||||
char fname[300],dialstr[300],extstr[300],ident[300],reqinp[300],buf[300];
|
||||
char clid[300],*tele,*context;
|
||||
FILE *fp;
|
||||
int ms = MAXWAITFORANSWER,maxsecs;
|
||||
struct ast_channel *channel;
|
||||
time_t t;
|
||||
|
||||
/* get the filename from the arg */
|
||||
strcpy(fname,(char *)arg);
|
||||
free(arg);
|
||||
time(&t);
|
||||
fp = fopen(fname,"r");
|
||||
if (!fp) /* if cannot open request file */
|
||||
{
|
||||
perror("qcall_do:fopen");
|
||||
fprintf(stderr,"%s\n",fname);
|
||||
unlink(fname);
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
/* lock the file */
|
||||
if (flock(fileno(fp),LOCK_EX) == -1)
|
||||
{
|
||||
perror("qcall_do:flock");
|
||||
fprintf(stderr,"%s\n",fname);
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
strcpy(reqinp,"1"); /* default required input for acknowledgement */
|
||||
strcpy(ident, ""); /* default no ident */
|
||||
if (fscanf(fp,"%s %s %s %d %s %s",dialstr,clid,
|
||||
extstr,&maxsecs,ident,reqinp) < 4)
|
||||
{
|
||||
fprintf(stderr,"qcall_do:file line invalid in file %s:\n",fname);
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
flock(fileno(fp),LOCK_UN);
|
||||
fclose(fp);
|
||||
tele = strchr(dialstr,'/');
|
||||
if (!tele)
|
||||
{
|
||||
fprintf(stderr,"qcall_do:Dial number must be in format tech/number\n");
|
||||
unlink(fname);
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
*tele++ = 0;
|
||||
channel = ast_request(dialstr,AST_FORMAT_SLINEAR,tele);
|
||||
if (channel)
|
||||
{
|
||||
ast_set_read_format(channel,AST_FORMAT_SLINEAR);
|
||||
ast_set_write_format(channel,AST_FORMAT_SLINEAR);
|
||||
#ifdef OURCLID
|
||||
if (channel->callerid)
|
||||
free(channel->callerid);
|
||||
channel->callerid = strdup(OURCLID);
|
||||
if (channel->ani)
|
||||
free(channel->ani);
|
||||
channel->ani = strdup(OURCLID);
|
||||
#endif
|
||||
channel->whentohangup = 0;
|
||||
channel->appl = "AppQcall";
|
||||
channel->data = "(Outgoing Line)";
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "Qcall initiating call to %s/%s on %s (%s)\n",
|
||||
dialstr,tele,channel->name,fname);
|
||||
ast_call(channel,tele,MAXWAITFORANSWER);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,"qcall_do:Sorry unable to obtain channel\n");
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
if (strcasecmp(clid, "asreceived")) {
|
||||
if (channel->callerid) free(channel->callerid);
|
||||
channel->callerid = NULL;
|
||||
if (channel->ani) free(channel->ani);
|
||||
channel->ani = NULL;
|
||||
}
|
||||
if (channel->_state == AST_STATE_UP)
|
||||
if (debug) printf("@@@@ Autodial:Line is Up\n");
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "Qcall waiting for answer on %s\n",
|
||||
channel->name);
|
||||
while(ms > 0){
|
||||
struct ast_frame *f;
|
||||
ms = ast_waitfor(channel,ms);
|
||||
f = ast_read(channel);
|
||||
if (!f)
|
||||
{
|
||||
if (debug) printf("@@@@ qcall_do:Hung Up\n");
|
||||
unlink(fname);
|
||||
break;
|
||||
}
|
||||
if (f->frametype == AST_FRAME_CONTROL)
|
||||
{
|
||||
if (f->subclass == AST_CONTROL_HANGUP)
|
||||
{
|
||||
if (debug) printf("@@@@ qcall_do:Hung Up\n");
|
||||
unlink(fname);
|
||||
ast_frfree(f);
|
||||
break;
|
||||
}
|
||||
if (f->subclass == AST_CONTROL_ANSWER)
|
||||
{
|
||||
if (debug) printf("@@@@ qcall_do:Phone Answered\n");
|
||||
if (channel->_state == AST_STATE_UP)
|
||||
{
|
||||
unlink(fname);
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "Qcall got answer on %s\n",
|
||||
channel->name);
|
||||
usleep(1500000);
|
||||
if (strlen(ident)) {
|
||||
ast_streamfile(channel,ident,0);
|
||||
if (ast_readstring(channel,buf,strlen(reqinp),10000,5000,"#"))
|
||||
{
|
||||
ast_stopstream(channel);
|
||||
if (debug) printf("@@@@ qcall_do: timeout or hangup in dtmf read\n");
|
||||
ast_frfree(f);
|
||||
break;
|
||||
}
|
||||
ast_stopstream(channel);
|
||||
if (strcmp(buf,reqinp)) /* if not match */
|
||||
{
|
||||
if (debug) printf("@@@@ qcall_do: response (%s) does not match required (%s)\n",buf,reqinp);
|
||||
ast_frfree(f);
|
||||
break;
|
||||
}
|
||||
ast_frfree(f);
|
||||
}
|
||||
/* okay, now we go for it */
|
||||
context = strchr(extstr,'@');
|
||||
if (!context) context = "default";
|
||||
else *context++ = 0;
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "Qcall got accept, now putting through to %s@%s on %s\n",
|
||||
extstr,context,channel->name);
|
||||
if (strlen(ident)) {
|
||||
strcat(ident,"-ok");
|
||||
/* if file existant, play it */
|
||||
if (!ast_streamfile(channel,ident,0))
|
||||
{
|
||||
ast_waitstream(channel,"");
|
||||
ast_stopstream(channel);
|
||||
}
|
||||
}
|
||||
if (strcasecmp(clid, "asreceived")) {
|
||||
channel->callerid = strdup(clid);
|
||||
channel->ani = strdup(clid);
|
||||
}
|
||||
channel->language[0] = 0;
|
||||
channel->dnid = strdup(extstr);
|
||||
#ifdef AMAFLAGS
|
||||
channel->amaflags = AMAFLAGS;
|
||||
#endif
|
||||
#ifdef ACCTCODE
|
||||
strcpy(channel->accountcode,ACCTCODE);
|
||||
#else
|
||||
channel->accountcode[0] = 0;
|
||||
#endif
|
||||
if (maxsecs) /* if finite length call */
|
||||
{
|
||||
time(&channel->whentohangup);
|
||||
channel->whentohangup += maxsecs;
|
||||
}
|
||||
strcpy(channel->exten,extstr);
|
||||
strcpy(channel->context,context);
|
||||
channel->priority = 1;
|
||||
printf("Caller ID is %s\n", channel->callerid);
|
||||
ast_pbx_run(channel);
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
}
|
||||
else if(f->subclass==AST_CONTROL_RINGING)
|
||||
if (debug) printf("@@@@ qcall_do:Phone Ringing end\n");
|
||||
}
|
||||
ast_frfree(f);
|
||||
}
|
||||
ast_hangup(channel);
|
||||
if (debug) printf("@@@@ qcall_do:Hung up channel\n");
|
||||
pthread_exit(NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
snprintf((char *)qdir,sizeof(qdir)-1,"%s/%s",(char *)ast_config_AST_SPOOL_DIR,"qcall");
|
||||
mkdir(qdir,0760);
|
||||
pthread_create(&qcall_thread,NULL,qcall,NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
3608
apps/app_queue.c
Executable file → Normal file
3608
apps/app_queue.c
Executable file → Normal file
File diff suppressed because it is too large
Load Diff
103
apps/app_random.c
Executable file → Normal file
103
apps/app_random.c
Executable file → Normal file
@@ -1,27 +1,43 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Random application
|
||||
*
|
||||
* Copyright (c) 2003-2004 Tilghman Lesher. All rights reserved.
|
||||
* Copyright (c) 2003 - 2005 Tilghman Lesher. All rights reserved.
|
||||
*
|
||||
* Tilghman Lesher <asterisk__app_random__20040111@the-tilghman.com>
|
||||
* Tilghman Lesher <asterisk__app_random__200508@the-tilghman.com>
|
||||
*
|
||||
* This code is released by the author with no restrictions on usage or distribution.
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief Random application
|
||||
*
|
||||
* \author Tilghman Lesher <asterisk__app_random__200508@the-tilghman.com>
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/options.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/options.h"
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/module.h"
|
||||
|
||||
static char *tdesc = "Random goto";
|
||||
|
||||
@@ -37,76 +53,59 @@ STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static char random_state[256];
|
||||
|
||||
static int random_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0;
|
||||
struct localuser *u;
|
||||
|
||||
char *s, *ts;
|
||||
char *exten, *pri, *context;
|
||||
char *s;
|
||||
char *prob;
|
||||
int probint, priorityint;
|
||||
|
||||
if (!data) {
|
||||
int probint;
|
||||
|
||||
if (ast_strlen_zero(data)) {
|
||||
ast_log(LOG_WARNING, "Random requires an argument ([probability]:[[context|]extension|]priority)\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
s = ast_strdupa((void *) data);
|
||||
|
||||
prob = strsep(&ts,":");
|
||||
s = ast_strdupa(data);
|
||||
if (!s) {
|
||||
ast_log(LOG_ERROR, "Out of memory!\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
prob = strsep(&s,":");
|
||||
if ((!prob) || (sscanf(prob, "%d", &probint) != 1))
|
||||
probint = 0;
|
||||
|
||||
if ((random() % 100) + probint > 100) {
|
||||
context = strsep(&s, "|");
|
||||
exten = strsep(&s, "|");
|
||||
if (!exten) {
|
||||
/* Only a priority */
|
||||
pri = context;
|
||||
exten = NULL;
|
||||
context = NULL;
|
||||
} else {
|
||||
pri = strsep(&s, "|");
|
||||
if (!pri) {
|
||||
pri = exten;
|
||||
exten = context;
|
||||
context = NULL;
|
||||
}
|
||||
}
|
||||
if (!pri) {
|
||||
ast_log(LOG_WARNING, "No label specified\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
} else if (sscanf(pri, "%d", &priorityint) != 1) {
|
||||
ast_log(LOG_WARNING, "Priority '%s' must be a number > 0\n", pri);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
/* At this point we have a priority and */
|
||||
/* maybe an extension and a context */
|
||||
chan->priority = priorityint - 1;
|
||||
if (exten && strcasecmp(exten, "BYEXTENSION"))
|
||||
strncpy(chan->exten, exten, sizeof(chan->exten)-1);
|
||||
if (context)
|
||||
strncpy(chan->context, context, sizeof(chan->context)-1);
|
||||
res = ast_parseable_goto(chan, s);
|
||||
if (option_verbose > 2)
|
||||
ast_verbose( VERBOSE_PREFIX_3 "Random branches to (%s,%s,%d)\n",
|
||||
chan->context,chan->exten, chan->priority+1);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
}
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app_random);
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app_random);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
srandom((unsigned int)getpid() + (unsigned int)time(NULL));
|
||||
initstate((getppid() * 65535 + getpid()) % RAND_MAX, random_state, 256);
|
||||
return ast_register_application(app_random, random_exec, random_synopsis, random_descrip);
|
||||
}
|
||||
|
||||
|
||||
207
apps/app_read.c
Executable file → Normal file
207
apps/app_read.c
Executable file → Normal file
@@ -1,28 +1,46 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Trivial application to read a variable
|
||||
*
|
||||
* Copyright (C) 2003, Digium
|
||||
* Copyright (C) 1999 - 2005, Digium, Inc.
|
||||
*
|
||||
* Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief Trivial application to read a variable
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/app.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/translate.h>
|
||||
#include <asterisk/options.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/lock.h"
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/app.h"
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/translate.h"
|
||||
#include "asterisk/options.h"
|
||||
#include "asterisk/utils.h"
|
||||
|
||||
static char *tdesc = "Read Variable Application";
|
||||
|
||||
@@ -31,45 +49,153 @@ static char *app = "Read";
|
||||
static char *synopsis = "Read a variable";
|
||||
|
||||
static char *descrip =
|
||||
" Read(variable[|filename]): Reads a '#' terminated string of digits from\n"
|
||||
"the user, optionally playing a given filename first. Returns -1 on hangup or\n"
|
||||
"error and 0 otherwise.\n";
|
||||
" Read(variable[|filename][|maxdigits][|option][|attempts][|timeout])\n\n"
|
||||
"Reads a #-terminated string of digits a certain number of times from the\n"
|
||||
"user in to the given variable.\n"
|
||||
" filename -- file to play before reading digits.\n"
|
||||
" maxdigits -- maximum acceptable number of digits. Stops reading after\n"
|
||||
" maxdigits have been entered (without requiring the user to\n"
|
||||
" press the '#' key).\n"
|
||||
" Defaults to 0 - no limit - wait for the user press the '#' key.\n"
|
||||
" Any value below 0 means the same. Max accepted value is 255.\n"
|
||||
" option -- may be 'skip' to return immediately if the line is not up,\n"
|
||||
" or 'noanswer' to read digits even if the line is not up.\n"
|
||||
" attempts -- if greater than 1, that many attempts will be made in the \n"
|
||||
" event no data is entered.\n"
|
||||
" timeout -- if greater than 0, that value will override the default timeout.\n\n"
|
||||
"Read should disconnect if the function fails or errors out.\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
#define ast_next_data(instr,ptr,delim) if((ptr=strchr(instr,delim))) { *(ptr) = '\0' ; ptr++;}
|
||||
|
||||
static int read_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res = 0;
|
||||
struct localuser *u;
|
||||
char tmp[256];
|
||||
char tmp2[128]="";
|
||||
char *filename;
|
||||
char *stringp;
|
||||
if (!data || !strlen((char *)data)) {
|
||||
char *timeout = NULL;
|
||||
char *varname = NULL;
|
||||
char *filename = NULL;
|
||||
char *loops;
|
||||
char *maxdigitstr=NULL;
|
||||
char *options=NULL;
|
||||
int option_skip = 0;
|
||||
int option_noanswer = 0;
|
||||
int maxdigits=255;
|
||||
int tries = 1;
|
||||
int to = 0;
|
||||
int x = 0;
|
||||
char *argcopy = NULL;
|
||||
char *args[8];
|
||||
|
||||
if (ast_strlen_zero(data)) {
|
||||
ast_log(LOG_WARNING, "Read requires an argument (variable)\n");
|
||||
return -1;
|
||||
}
|
||||
strncpy(tmp, (char *)data, sizeof(tmp)-1);
|
||||
stringp=tmp;
|
||||
strsep(&stringp, "|");
|
||||
filename = strsep(&stringp, "|");
|
||||
if (!strlen(tmp)) {
|
||||
ast_log(LOG_WARNING, "Read requires an variable name\n");
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
argcopy = ast_strdupa(data);
|
||||
if (!argcopy) {
|
||||
ast_log(LOG_ERROR, "Out of memory\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
if (ast_app_separate_args(argcopy, '|', args, sizeof(args) / sizeof(args[0])) < 1) {
|
||||
ast_log(LOG_WARNING, "Cannot Parse Arguments.\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
varname = args[x++];
|
||||
filename = args[x++];
|
||||
maxdigitstr = args[x++];
|
||||
options = args[x++];
|
||||
loops = args[x++];
|
||||
timeout = args[x++];
|
||||
|
||||
if (options) {
|
||||
if (!strcasecmp(options, "skip"))
|
||||
option_skip = 1;
|
||||
else if (!strcasecmp(options, "noanswer"))
|
||||
option_noanswer = 1;
|
||||
else {
|
||||
if (strchr(options, 's'))
|
||||
option_skip = 1;
|
||||
if (strchr(options, 'n'))
|
||||
option_noanswer = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(loops) {
|
||||
tries = atoi(loops);
|
||||
if(tries <= 0)
|
||||
tries = 1;
|
||||
}
|
||||
|
||||
if(timeout) {
|
||||
to = atoi(timeout);
|
||||
if (to <= 0)
|
||||
to = 0;
|
||||
else
|
||||
to *= 1000;
|
||||
}
|
||||
|
||||
if (ast_strlen_zero(filename))
|
||||
filename = NULL;
|
||||
if (maxdigitstr) {
|
||||
maxdigits = atoi(maxdigitstr);
|
||||
if ((maxdigits<1) || (maxdigits>255)) {
|
||||
maxdigits = 255;
|
||||
} else if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "Accepting a maximum of %d digits.\n", maxdigits);
|
||||
}
|
||||
if (ast_strlen_zero(varname)) {
|
||||
ast_log(LOG_WARNING, "Invalid! Usage: Read(variable[|filename][|maxdigits][|option][|attempts][|timeout])\n\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (chan->_state != AST_STATE_UP) {
|
||||
/* Answer if the line isn't up. */
|
||||
res = ast_answer(chan);
|
||||
if (option_skip) {
|
||||
/* At the user's option, skip if the line is not up */
|
||||
pbx_builtin_setvar_helper(chan, varname, "\0");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return 0;
|
||||
} else if (!option_noanswer) {
|
||||
/* Otherwise answer unless we're supposed to read while on-hook */
|
||||
res = ast_answer(chan);
|
||||
}
|
||||
}
|
||||
if (!res) {
|
||||
ast_stopstream(chan);
|
||||
res = ast_app_getdata(chan, filename, tmp2, sizeof(tmp2) - 1, 0);
|
||||
if (!res)
|
||||
pbx_builtin_setvar_helper(chan, tmp, tmp2);
|
||||
ast_verbose(VERBOSE_PREFIX_3 "User entered '%s'\n", tmp2);
|
||||
while(tries && !res) {
|
||||
ast_stopstream(chan);
|
||||
res = ast_app_getdata(chan, filename, tmp, maxdigits, to);
|
||||
if (res > -1) {
|
||||
pbx_builtin_setvar_helper(chan, varname, tmp);
|
||||
if (!ast_strlen_zero(tmp)) {
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "User entered '%s'\n", tmp);
|
||||
tries = 0;
|
||||
} else {
|
||||
tries--;
|
||||
if (option_verbose > 2) {
|
||||
if (tries)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "User entered nothing, %d chance%s left\n", tries, (tries != 1) ? "s" : "");
|
||||
else
|
||||
ast_verbose(VERBOSE_PREFIX_3 "User entered nothing.\n");
|
||||
}
|
||||
}
|
||||
res = 0;
|
||||
} else {
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "User disconnected\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
@@ -77,8 +203,13 @@ static int read_exec(struct ast_channel *chan, void *data)
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app);
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
|
||||
143
apps/app_readfile.c
Normal file
143
apps/app_readfile.c
Normal file
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Copyright (C) 1999 - 2005, Digium, Inc.
|
||||
*
|
||||
* Matt O'Gorman <mogorman@digium.com>
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief ReadFile application -- Reads in a File for you.
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/options.h"
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/app.h"
|
||||
#include "asterisk/module.h"
|
||||
|
||||
static char *tdesc = "Stores output of file into a variable";
|
||||
|
||||
static char *app_readfile = "ReadFile";
|
||||
|
||||
static char *readfile_synopsis = "ReadFile(varname=file,length)";
|
||||
|
||||
static char *readfile_descrip =
|
||||
"ReadFile(varname=file,length)\n"
|
||||
" Varname - Result stored here.\n"
|
||||
" File - The name of the file to read.\n"
|
||||
" Length - Maximum number of characters to capture.\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
|
||||
static int readfile_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0;
|
||||
struct localuser *u;
|
||||
char *s, *varname=NULL, *file=NULL, *length=NULL, *returnvar=NULL;
|
||||
int len=0;
|
||||
|
||||
if (ast_strlen_zero(data)) {
|
||||
ast_log(LOG_WARNING, "ReadFile require an argument!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
s = ast_strdupa(data);
|
||||
if (!s) {
|
||||
ast_log(LOG_ERROR, "Out of memory\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
varname = strsep(&s, "=");
|
||||
file = strsep(&s, "|");
|
||||
length = s;
|
||||
|
||||
if (!varname || !file) {
|
||||
ast_log(LOG_ERROR, "No file or variable specified!\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (length) {
|
||||
if ((sscanf(length, "%d", &len) != 1) || (len < 0)) {
|
||||
ast_log(LOG_WARNING, "%s is not a positive number, defaulting length to max\n", length);
|
||||
len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
returnvar = ast_read_textfile(file);
|
||||
if(len > 0){
|
||||
if(len < strlen(returnvar))
|
||||
returnvar[len]='\0';
|
||||
else
|
||||
ast_log(LOG_WARNING,"%s is longer than %d, and %d \n", file, len, (int)strlen(returnvar));
|
||||
}
|
||||
pbx_builtin_setvar_helper(chan, varname, returnvar);
|
||||
free(returnvar);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app_readfile);
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(app_readfile, readfile_exec, readfile_synopsis, readfile_descrip);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
262
apps/app_realtime.c
Normal file
262
apps/app_realtime.c
Normal file
@@ -0,0 +1,262 @@
|
||||
/*
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Copyright (C) 1999 - 2005, Digium, Inc.
|
||||
*
|
||||
* Anthony Minessale <anthmct@yahoo.com>
|
||||
* Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief RealTime App
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/options.h"
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/config.h"
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/lock.h"
|
||||
#include "asterisk/cli.h"
|
||||
|
||||
#define next_one(var) var = var->next
|
||||
#define crop_data(str) { *(str) = '\0' ; (str)++; }
|
||||
|
||||
static char *tdesc = "Realtime Data Lookup/Rewrite";
|
||||
static char *app = "RealTime";
|
||||
static char *uapp = "RealTimeUpdate";
|
||||
static char *synopsis = "Realtime Data Lookup";
|
||||
static char *usynopsis = "Realtime Data Rewrite";
|
||||
static char *USAGE = "RealTime(<family>|<colmatch>|<value>[|<prefix>])";
|
||||
static char *UUSAGE = "RealTimeUpdate(<family>|<colmatch>|<value>|<newcol>|<newval>)";
|
||||
static char *desc = "Use the RealTime config handler system to read data into channel variables.\n"
|
||||
"RealTime(<family>|<colmatch>|<value>[|<prefix>])\n\n"
|
||||
"All unique column names will be set as channel variables with optional prefix to the name.\n"
|
||||
"e.g. prefix of 'var_' would make the column 'name' become the variable ${var_name}\n\n";
|
||||
static char *udesc = "Use the RealTime config handler system to update a value\n"
|
||||
"RealTimeUpdate(<family>|<colmatch>|<value>|<newcol>|<newval>)\n\n"
|
||||
"The column <newcol> in 'family' matching column <colmatch>=<value> will be updated to <newval>\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int cli_load_realtime(int fd, int argc, char **argv)
|
||||
{
|
||||
char *header_format = "%30s %-30s\n";
|
||||
struct ast_variable *var=NULL;
|
||||
|
||||
if(argc<5) {
|
||||
ast_cli(fd, "You must supply a family name, a column to match on, and a value to match to.\n");
|
||||
return RESULT_FAILURE;
|
||||
}
|
||||
|
||||
var = ast_load_realtime(argv[2], argv[3], argv[4], NULL);
|
||||
|
||||
if(var) {
|
||||
ast_cli(fd, header_format, "Column Name", "Column Value");
|
||||
ast_cli(fd, header_format, "--------------------", "--------------------");
|
||||
while(var) {
|
||||
ast_cli(fd, header_format, var->name, var->value);
|
||||
var = var->next;
|
||||
}
|
||||
} else {
|
||||
ast_cli(fd, "No rows found matching search criteria.\n");
|
||||
}
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static int cli_update_realtime(int fd, int argc, char **argv) {
|
||||
int res = 0;
|
||||
|
||||
if(argc<7) {
|
||||
ast_cli(fd, "You must supply a family name, a column to update on, a new value, column to match, and value to to match.\n");
|
||||
ast_cli(fd, "Ex: realtime update sipfriends name bobsphone port 4343\n will execute SQL as UPDATE sipfriends SET port = 4343 WHERE name = bobsphone\n");
|
||||
return RESULT_FAILURE;
|
||||
}
|
||||
|
||||
res = ast_update_realtime(argv[2], argv[3], argv[4], argv[5], argv[6], NULL);
|
||||
|
||||
if(res < 0) {
|
||||
ast_cli(fd, "Failed to update. Check the debug log for possible SQL related entries.\n");
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
ast_cli(fd, "Updated %d RealTime record%s.\n", res, (res != 1) ? "s" : "");
|
||||
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static char cli_load_realtime_usage[] =
|
||||
"Usage: realtime load <family> <colmatch> <value>\n"
|
||||
" Prints out a list of variables using the RealTime driver.\n";
|
||||
|
||||
static struct ast_cli_entry cli_load_realtime_cmd = {
|
||||
{ "realtime", "load", NULL, NULL }, cli_load_realtime,
|
||||
"Used to print out RealTime variables.", cli_load_realtime_usage, NULL };
|
||||
|
||||
static char cli_update_realtime_usage[] =
|
||||
"Usage: realtime update <family> <colmatch> <value>\n"
|
||||
" Update a single variable using the RealTime driver.\n";
|
||||
|
||||
static struct ast_cli_entry cli_update_realtime_cmd = {
|
||||
{ "realtime", "update", NULL, NULL }, cli_update_realtime,
|
||||
"Used to update RealTime variables.", cli_update_realtime_usage, NULL };
|
||||
|
||||
static int realtime_update_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
char *family=NULL, *colmatch=NULL, *value=NULL, *newcol=NULL, *newval=NULL;
|
||||
struct localuser *u;
|
||||
int res = 0;
|
||||
|
||||
if (ast_strlen_zero(data)) {
|
||||
ast_log(LOG_ERROR,"Invalid input: usage %s\n",UUSAGE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
if ((family = ast_strdupa(data))) {
|
||||
if ((colmatch = strchr(family,'|'))) {
|
||||
crop_data(colmatch);
|
||||
if ((value = strchr(colmatch,'|'))) {
|
||||
crop_data(value);
|
||||
if ((newcol = strchr(value,'|'))) {
|
||||
crop_data(newcol);
|
||||
if ((newval = strchr(newcol,'|')))
|
||||
crop_data(newval);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (! (family && value && colmatch && newcol && newval) ) {
|
||||
ast_log(LOG_ERROR,"Invalid input: usage %s\n",UUSAGE);
|
||||
res = -1;
|
||||
} else {
|
||||
ast_update_realtime(family,colmatch,value,newcol,newval,NULL);
|
||||
}
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static int realtime_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0;
|
||||
struct localuser *u;
|
||||
struct ast_variable *var, *itt;
|
||||
char *family=NULL, *colmatch=NULL, *value=NULL, *prefix=NULL, *vname=NULL;
|
||||
size_t len;
|
||||
|
||||
if (ast_strlen_zero(data)) {
|
||||
ast_log(LOG_ERROR,"Invalid input: usage %s\n",USAGE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
if ((family = ast_strdupa(data))) {
|
||||
if ((colmatch = strchr(family,'|'))) {
|
||||
crop_data(colmatch);
|
||||
if ((value = strchr(colmatch,'|'))) {
|
||||
crop_data(value);
|
||||
if ((prefix = strchr(value,'|')))
|
||||
crop_data(prefix);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (! (family && value && colmatch) ) {
|
||||
ast_log(LOG_ERROR,"Invalid input: usage %s\n",USAGE);
|
||||
res = -1;
|
||||
} else {
|
||||
if (option_verbose > 3)
|
||||
ast_verbose(VERBOSE_PREFIX_4"Realtime Lookup: family:'%s' colmatch:'%s' value:'%s'\n",family,colmatch,value);
|
||||
if ((var = ast_load_realtime(family, colmatch, value, NULL))) {
|
||||
for (itt = var; itt; itt = itt->next) {
|
||||
if(prefix) {
|
||||
len = strlen(prefix) + strlen(itt->name) + 2;
|
||||
vname = alloca(len);
|
||||
snprintf(vname,len,"%s%s",prefix,itt->name);
|
||||
|
||||
} else
|
||||
vname = itt->name;
|
||||
|
||||
pbx_builtin_setvar_helper(chan, vname, itt->value);
|
||||
}
|
||||
ast_variables_destroy(var);
|
||||
} else if (option_verbose > 3)
|
||||
ast_verbose(VERBOSE_PREFIX_4"No Realtime Matches Found.\n");
|
||||
}
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_cli_unregister(&cli_load_realtime_cmd);
|
||||
res |= ast_cli_unregister(&cli_update_realtime_cmd);
|
||||
res |= ast_unregister_application(uapp);
|
||||
res |= ast_unregister_application(app);
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_cli_register(&cli_load_realtime_cmd);
|
||||
res |= ast_cli_register(&cli_update_realtime_cmd);
|
||||
res |= ast_register_application(uapp, realtime_update_exec, usynopsis, udesc);
|
||||
res |= ast_register_application(app, realtime_exec, synopsis, desc);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
|
||||
432
apps/app_record.c
Executable file → Normal file
432
apps/app_record.c
Executable file → Normal file
@@ -1,27 +1,46 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Trivial application to record a sound file
|
||||
*
|
||||
* Copyright (C) 2001, Linux Support Services, Inc.
|
||||
* Copyright (C) 1999 - 2005, Digium, Inc.
|
||||
*
|
||||
* Matthew Fredrickson <creslin@linux-support.net>
|
||||
* Matthew Fredrickson <creslin@digium.com>
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief Trivial application to record a sound file
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/translate.h>
|
||||
#include <asterisk/dsp.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/lock.h"
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/translate.h"
|
||||
#include "asterisk/dsp.h"
|
||||
#include "asterisk/utils.h"
|
||||
#include "asterisk/options.h"
|
||||
|
||||
static char *tdesc = "Trivial Record Application";
|
||||
|
||||
@@ -30,11 +49,26 @@ static char *app = "Record";
|
||||
static char *synopsis = "Record to a file";
|
||||
|
||||
static char *descrip =
|
||||
" Record(filename:extension|silence): Records from the channel into a given\n"
|
||||
"filename. If the file exists it will be overwritten. The 'extension'\n"
|
||||
"is the extension of the file type to be recorded (wav, gsm, etc).\n"
|
||||
"'silence' is the number of seconds of silence to allow before returning.\n"
|
||||
"Returns -1 when the user hangs up.\n";
|
||||
" Record(filename.format|silence[|maxduration][|options])\n\n"
|
||||
"Records from the channel into a given filename. If the file exists it will\n"
|
||||
"be overwritten.\n"
|
||||
"- 'format' is the format of the file type to be recorded (wav, gsm, etc).\n"
|
||||
"- 'silence' is the number of seconds of silence to allow before returning.\n"
|
||||
"- 'maxduration' is the maximum recording duration in seconds. If missing\n"
|
||||
"or 0 there is no maximum.\n"
|
||||
"- 'options' may contain any of the following letters:\n"
|
||||
" 'a' : append to existing recording rather than replacing\n"
|
||||
" 'n' : do not answer, but record anyway if line not yet answered\n"
|
||||
" 'q' : quiet (do not play a beep tone)\n"
|
||||
" 's' : skip recording if the line is not yet answered\n"
|
||||
" 't' : use alternate '*' terminator key instead of default '#'\n"
|
||||
"\n"
|
||||
"If filename contains '%d', these characters will be replaced with a number\n"
|
||||
"incremented by one each time the file is recorded. \n\n"
|
||||
"Use 'show file formats' to see the available formats on your system\n\n"
|
||||
"User can press '#' to terminate the recording and continue to the next priority.\n\n"
|
||||
"If the user should hangup during a recording, all data will be lost and the\n"
|
||||
"application will teminate. \n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
@@ -45,12 +79,10 @@ static int record_exec(struct ast_channel *chan, void *data)
|
||||
int res = 0;
|
||||
int count = 0;
|
||||
int percentflag = 0;
|
||||
char fil[256];
|
||||
char tmp[256];
|
||||
char ext[10];
|
||||
char * vdata; /* Used so I don't have to typecast every use of *data */
|
||||
char *filename, *ext = NULL, *silstr, *maxstr, *options;
|
||||
char *vdata, *p;
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
char tmp[256];
|
||||
|
||||
struct ast_filestream *s = '\0';
|
||||
struct localuser *u;
|
||||
@@ -61,68 +93,124 @@ static int record_exec(struct ast_channel *chan, void *data)
|
||||
int dspsilence = 0;
|
||||
int silence = 0; /* amount of silence to allow */
|
||||
int gotsilence = 0; /* did we timeout for silence? */
|
||||
char silencestr[5];
|
||||
int k = 0;
|
||||
int maxduration = 0; /* max duration of recording in milliseconds */
|
||||
int gottimeout = 0; /* did we timeout for maxduration exceeded? */
|
||||
int option_skip = 0;
|
||||
int option_noanswer = 0;
|
||||
int option_append = 0;
|
||||
int terminator = '#';
|
||||
int option_quiet = 0;
|
||||
int rfmt = 0;
|
||||
|
||||
vdata = data; /* explained above */
|
||||
|
||||
int flags;
|
||||
int waitres;
|
||||
struct ast_silence_generator *silgen = NULL;
|
||||
|
||||
/* The next few lines of code parse out the filename and header from the input string */
|
||||
if (!vdata) { /* no data implies no filename or anything is present */
|
||||
if (ast_strlen_zero(data)) { /* no data implies no filename or anything is present */
|
||||
ast_log(LOG_WARNING, "Record requires an argument (filename)\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
/* Yay for strsep being easy */
|
||||
vdata = ast_strdupa(data);
|
||||
if (!vdata) {
|
||||
ast_log(LOG_ERROR, "Out of memory\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
p = vdata;
|
||||
filename = strsep(&p, "|");
|
||||
silstr = strsep(&p, "|");
|
||||
maxstr = strsep(&p, "|");
|
||||
options = strsep(&p, "|");
|
||||
|
||||
for (; vdata[i] && (vdata[i] != ':') && (vdata[i] != '|'); i++ ) {
|
||||
if ((vdata[i] == '%') && (vdata[i+1] == 'd')) {
|
||||
percentflag = 1; /* the wildcard is used */
|
||||
if (filename) {
|
||||
if (strstr(filename, "%d"))
|
||||
percentflag = 1;
|
||||
ext = strrchr(filename, '.'); /* to support filename with a . in the filename, not format */
|
||||
if (!ext)
|
||||
ext = strchr(filename, ':');
|
||||
if (ext) {
|
||||
*ext = '\0';
|
||||
ext++;
|
||||
}
|
||||
|
||||
if (i == strlen(vdata) ) {
|
||||
ast_log(LOG_WARNING, "No extension found\n");
|
||||
return -1;
|
||||
}
|
||||
if (!ext) {
|
||||
ast_log(LOG_WARNING, "No extension specified to filename!\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
if (silstr) {
|
||||
if ((sscanf(silstr, "%d", &i) == 1) && (i > -1)) {
|
||||
silence = i * 1000;
|
||||
} else if (!ast_strlen_zero(silstr)) {
|
||||
ast_log(LOG_WARNING, "'%s' is not a valid silence duration\n", silstr);
|
||||
}
|
||||
fil[i] = vdata[i];
|
||||
}
|
||||
fil[i++] = '\0';
|
||||
|
||||
for (; j < 10 && i < strlen(data) && (vdata[i] != '|'); i++, j++)
|
||||
ext[j] = vdata[i];
|
||||
ext[j] = '\0';
|
||||
|
||||
if (vdata[i] && (vdata[i] == '|')) i++;
|
||||
for (; vdata[i] && (vdata[i] != '|') && (k < 3) && i < strlen(data); i++, k++)
|
||||
silencestr[k] = vdata[i];
|
||||
silencestr[k] = '\0';
|
||||
|
||||
if (silencestr) {
|
||||
silence = atoi(silencestr);
|
||||
if (silence > 0)
|
||||
silence *= 1000;
|
||||
|
||||
if (maxstr) {
|
||||
if ((sscanf(maxstr, "%d", &i) == 1) && (i > -1))
|
||||
/* Convert duration to milliseconds */
|
||||
maxduration = i * 1000;
|
||||
else if (!ast_strlen_zero(maxstr))
|
||||
ast_log(LOG_WARNING, "'%s' is not a valid maximum duration\n", maxstr);
|
||||
}
|
||||
|
||||
if (options) {
|
||||
/* Retain backwards compatibility with old style options */
|
||||
if (!strcasecmp(options, "skip"))
|
||||
option_skip = 1;
|
||||
else if (!strcasecmp(options, "noanswer"))
|
||||
option_noanswer = 1;
|
||||
else {
|
||||
if (strchr(options, 's'))
|
||||
option_skip = 1;
|
||||
if (strchr(options, 'n'))
|
||||
option_noanswer = 1;
|
||||
if (strchr(options, 'a'))
|
||||
option_append = 1;
|
||||
if (strchr(options, 't'))
|
||||
terminator = '*';
|
||||
if (strchr(options, 'q'))
|
||||
option_quiet = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* done parsing */
|
||||
|
||||
|
||||
/* these are to allow the use of the %d in the config file for a wild card of sort to
|
||||
create a new file with the inputed name scheme */
|
||||
if (percentflag) {
|
||||
do {
|
||||
snprintf(tmp, 256, fil, count);
|
||||
snprintf(tmp, sizeof(tmp), filename, count);
|
||||
count++;
|
||||
} while ( ast_fileexists(tmp, ext, chan->language) != -1 );
|
||||
pbx_builtin_setvar_helper(chan, "RECORDED_FILE", tmp);
|
||||
} else
|
||||
strncpy(tmp, fil, 256-1);
|
||||
strncpy(tmp, filename, sizeof(tmp)-1);
|
||||
/* end of routine mentioned */
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
|
||||
|
||||
|
||||
if (chan->_state != AST_STATE_UP) {
|
||||
res = ast_answer(chan); /* Shouldn't need this, but checking to see if channel is already answered
|
||||
* Theoretically asterisk should already have answered before running the app */
|
||||
if (option_skip) {
|
||||
/* At the user's option, skip if the line is not up */
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return 0;
|
||||
} else if (!option_noanswer) {
|
||||
/* Otherwise answer unless we're supposed to record while on-hook */
|
||||
res = ast_answer(chan);
|
||||
}
|
||||
}
|
||||
|
||||
if (!res) {
|
||||
if (res) {
|
||||
ast_log(LOG_WARNING, "Could not answer channel '%s'\n", chan->name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!option_quiet) {
|
||||
/* Some code to play a nice little beep to signify the start of the record operation */
|
||||
res = ast_streamfile(chan, "beep", chan->language);
|
||||
if (!res) {
|
||||
@@ -131,107 +219,139 @@ static int record_exec(struct ast_channel *chan, void *data)
|
||||
ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", chan->name);
|
||||
}
|
||||
ast_stopstream(chan);
|
||||
|
||||
/* The end of beep code. Now the recording starts */
|
||||
|
||||
|
||||
if (silence > 0) {
|
||||
rfmt = chan->readformat;
|
||||
res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
|
||||
if (res < 0) {
|
||||
ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
|
||||
return -1;
|
||||
}
|
||||
sildet = ast_dsp_new();
|
||||
if (!sildet) {
|
||||
ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
|
||||
return -1;
|
||||
}
|
||||
ast_dsp_set_threshold(sildet, 256);
|
||||
}
|
||||
|
||||
s = ast_writefile( tmp, ext, NULL, O_CREAT|O_TRUNC|O_WRONLY , 0, 0644);
|
||||
|
||||
if (s) {
|
||||
while (ast_waitfor(chan, -1) > -1) {
|
||||
f = ast_read(chan);
|
||||
if (!f) {
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
if (f->frametype == AST_FRAME_VOICE) {
|
||||
res = ast_writestream(s, f);
|
||||
|
||||
if (res) {
|
||||
ast_log(LOG_WARNING, "Problem writing frame\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if (silence > 0) {
|
||||
dspsilence = 0;
|
||||
ast_dsp_silence(sildet, f, &dspsilence);
|
||||
if (dspsilence) {
|
||||
totalsilence = dspsilence;
|
||||
} else {
|
||||
totalsilence = 0;
|
||||
}
|
||||
if (totalsilence > silence) {
|
||||
/* Ended happily with silence */
|
||||
ast_frfree(f);
|
||||
gotsilence = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (f->frametype == AST_FRAME_VIDEO) {
|
||||
res = ast_writestream(s, f);
|
||||
|
||||
if (res) {
|
||||
ast_log(LOG_WARNING, "Problem writing frame\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ((f->frametype == AST_FRAME_DTMF) &&
|
||||
(f->subclass == '#')) {
|
||||
ast_frfree(f);
|
||||
break;
|
||||
}
|
||||
ast_frfree(f);
|
||||
}
|
||||
if (!f) {
|
||||
ast_log(LOG_DEBUG, "Got hangup\n");
|
||||
res = -1;
|
||||
}
|
||||
|
||||
if (gotsilence) {
|
||||
ast_stream_rewind(s, silence-1000);
|
||||
ast_truncstream(s);
|
||||
} else {
|
||||
/* Strip off the last 1/4 second of it */
|
||||
ast_stream_rewind(s, 250);
|
||||
ast_truncstream(s);
|
||||
}
|
||||
ast_closestream(s);
|
||||
} else
|
||||
ast_log(LOG_WARNING, "Could not create file %s\n", fil);
|
||||
} else
|
||||
ast_log(LOG_WARNING, "Could not answer channel '%s'\n", chan->name);
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
}
|
||||
|
||||
/* The end of beep code. Now the recording starts */
|
||||
|
||||
if (silence > 0) {
|
||||
res = ast_set_read_format(chan, rfmt);
|
||||
if (res)
|
||||
ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name);
|
||||
rfmt = chan->readformat;
|
||||
res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
|
||||
if (res < 0) {
|
||||
ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
sildet = ast_dsp_new();
|
||||
if (!sildet) {
|
||||
ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
ast_dsp_set_threshold(sildet, 256);
|
||||
}
|
||||
|
||||
|
||||
flags = option_append ? O_CREAT|O_APPEND|O_WRONLY : O_CREAT|O_TRUNC|O_WRONLY;
|
||||
s = ast_writefile( tmp, ext, NULL, flags , 0, 0644);
|
||||
|
||||
if (!s) {
|
||||
ast_log(LOG_WARNING, "Could not create file %s\n", filename);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (option_transmit_silence_during_record)
|
||||
silgen = ast_channel_start_silence_generator(chan);
|
||||
|
||||
/* Request a video update */
|
||||
ast_indicate(chan, AST_CONTROL_VIDUPDATE);
|
||||
|
||||
if (maxduration <= 0)
|
||||
maxduration = -1;
|
||||
|
||||
while ((waitres = ast_waitfor(chan, maxduration)) > -1) {
|
||||
if (maxduration > 0) {
|
||||
if (waitres == 0) {
|
||||
gottimeout = 1;
|
||||
break;
|
||||
}
|
||||
maxduration = waitres;
|
||||
}
|
||||
|
||||
f = ast_read(chan);
|
||||
if (!f) {
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
if (f->frametype == AST_FRAME_VOICE) {
|
||||
res = ast_writestream(s, f);
|
||||
|
||||
if (res) {
|
||||
ast_log(LOG_WARNING, "Problem writing frame\n");
|
||||
ast_frfree(f);
|
||||
break;
|
||||
}
|
||||
|
||||
if (silence > 0) {
|
||||
dspsilence = 0;
|
||||
ast_dsp_silence(sildet, f, &dspsilence);
|
||||
if (dspsilence) {
|
||||
totalsilence = dspsilence;
|
||||
} else {
|
||||
totalsilence = 0;
|
||||
}
|
||||
if (totalsilence > silence) {
|
||||
/* Ended happily with silence */
|
||||
ast_frfree(f);
|
||||
gotsilence = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (f->frametype == AST_FRAME_VIDEO) {
|
||||
res = ast_writestream(s, f);
|
||||
|
||||
if (res) {
|
||||
ast_log(LOG_WARNING, "Problem writing frame\n");
|
||||
ast_frfree(f);
|
||||
break;
|
||||
}
|
||||
} else if ((f->frametype == AST_FRAME_DTMF) &&
|
||||
(f->subclass == terminator)) {
|
||||
ast_frfree(f);
|
||||
break;
|
||||
}
|
||||
ast_frfree(f);
|
||||
}
|
||||
if (!f) {
|
||||
ast_log(LOG_DEBUG, "Got hangup\n");
|
||||
res = -1;
|
||||
}
|
||||
|
||||
if (gotsilence) {
|
||||
ast_stream_rewind(s, silence-1000);
|
||||
ast_truncstream(s);
|
||||
} else if (!gottimeout) {
|
||||
/* Strip off the last 1/4 second of it */
|
||||
ast_stream_rewind(s, 250);
|
||||
ast_truncstream(s);
|
||||
}
|
||||
ast_closestream(s);
|
||||
|
||||
if (silgen)
|
||||
ast_channel_stop_silence_generator(chan, silgen);
|
||||
|
||||
out:
|
||||
if ((silence > 0) && rfmt) {
|
||||
res = ast_set_read_format(chan, rfmt);
|
||||
if (res)
|
||||
ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name);
|
||||
if (sildet)
|
||||
ast_dsp_free(sildet);
|
||||
}
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app);
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
|
||||
6384
apps/app_rpt.c
Executable file → Normal file
6384
apps/app_rpt.c
Executable file → Normal file
File diff suppressed because it is too large
Load Diff
78
apps/app_sayunixtime.c
Executable file → Normal file
78
apps/app_sayunixtime.c
Executable file → Normal file
@@ -1,32 +1,49 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* SayUnixTime application
|
||||
*
|
||||
* Copyright (c) 2003 Tilghman Lesher. All rights reserved.
|
||||
*
|
||||
* Tilghman Lesher <app_sayunixtime__200309@the-tilghman.com>
|
||||
*
|
||||
* This code is released by the author with no restrictions on usage.
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief SayUnixTime application
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/options.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/say.h>
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/options.h"
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/say.h"
|
||||
|
||||
|
||||
static char *tdesc = "Say time";
|
||||
|
||||
static char *app_sayunixtime = "SayUnixTime";
|
||||
static char *app_datetime = "DateTime";
|
||||
|
||||
static char *sayunixtime_synopsis = "Says a specified time in a custom format";
|
||||
|
||||
@@ -37,8 +54,15 @@ static char *sayunixtime_descrip =
|
||||
" timezone: timezone, see /usr/share/zoneinfo for a list.\n"
|
||||
" defaults to machine default.\n"
|
||||
" format: a format the time is to be said in. See voicemail.conf.\n"
|
||||
" defaults to \"ABdY 'digits/at' IMp\"\n"
|
||||
" Returns 0 or -1 on hangup.\n";
|
||||
" defaults to \"ABdY 'digits/at' IMp\"\n";
|
||||
static char *datetime_descrip =
|
||||
"DateTime([unixtime][|[timezone][|format]])\n"
|
||||
" unixtime: time, in seconds since Jan 1, 1970. May be negative.\n"
|
||||
" defaults to now.\n"
|
||||
" timezone: timezone, see /usr/share/zoneinfo for a list.\n"
|
||||
" defaults to machine default.\n"
|
||||
" format: a format the time is to be said in. See voicemail.conf.\n"
|
||||
" defaults to \"ABdY 'digits/at' IMp\"\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
@@ -48,16 +72,23 @@ static int sayunixtime_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0;
|
||||
struct localuser *u;
|
||||
char *s,*zone=NULL,*timec;
|
||||
char *s,*zone=NULL,*timec,*format;
|
||||
time_t unixtime;
|
||||
char *format = "ABdY 'digits/at' IMp";
|
||||
struct timeval tv;
|
||||
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
gettimeofday(&tv,NULL);
|
||||
tv = ast_tvnow();
|
||||
unixtime = (time_t)tv.tv_sec;
|
||||
|
||||
if( !strcasecmp(chan->language, "da" ) ) {
|
||||
format = "A dBY HMS";
|
||||
} else if ( !strcasecmp(chan->language, "de" ) ) {
|
||||
format = "A dBY HMS";
|
||||
} else {
|
||||
format = "ABdY 'digits/at' IMp";
|
||||
}
|
||||
|
||||
if (data) {
|
||||
s = data;
|
||||
s = ast_strdupa(s);
|
||||
@@ -94,13 +125,24 @@ static int sayunixtime_exec(struct ast_channel *chan, void *data)
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app_sayunixtime);
|
||||
res |= ast_unregister_application(app_datetime);
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app_sayunixtime);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(app_sayunixtime, sayunixtime_exec, sayunixtime_synopsis, sayunixtime_descrip);
|
||||
int res;
|
||||
|
||||
res = ast_register_application(app_sayunixtime, sayunixtime_exec, sayunixtime_synopsis, sayunixtime_descrip);
|
||||
res |= ast_register_application(app_datetime, sayunixtime_exec, sayunixtime_synopsis, datetime_descrip);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
|
||||
112
apps/app_senddtmf.c
Executable file → Normal file
112
apps/app_senddtmf.c
Executable file → Normal file
@@ -1,27 +1,46 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* App to send DTMF digits
|
||||
*
|
||||
* Copyright (C) 1999, Mark Spencer
|
||||
* Copyright (C) 1999 - 2005, Digium, Inc.
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
* Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief App to send DTMF digits
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/translate.h>
|
||||
#include <asterisk/options.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/lock.h"
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/translate.h"
|
||||
#include "asterisk/options.h"
|
||||
#include "asterisk/utils.h"
|
||||
#include "asterisk/app.h"
|
||||
|
||||
static char *tdesc = "Send DTMF digits Application";
|
||||
|
||||
@@ -30,8 +49,10 @@ static char *app = "SendDTMF";
|
||||
static char *synopsis = "Sends arbitrary DTMF digits";
|
||||
|
||||
static char *descrip =
|
||||
" SendDTMF(digits): Sends DTMF digits on a channel. Returns 0 on success"
|
||||
"or -1 on a hangup.\n";
|
||||
" SendDTMF(digits[|timeout_ms]): Sends DTMF digits on a channel. \n"
|
||||
" Accepted digits: 0-9, *#abcd\n"
|
||||
" The application will either pass the assigned digits or terminate if it\n"
|
||||
" encounters an error.\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
@@ -41,39 +62,48 @@ static int senddtmf_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res = 0;
|
||||
struct localuser *u;
|
||||
char *digits = data;
|
||||
struct ast_frame f;
|
||||
int x;
|
||||
if (!digits || !strlen(digits)) {
|
||||
ast_log(LOG_WARNING, "SendDTMF requires an argument (digits)\n");
|
||||
char *digits = NULL, *to = NULL;
|
||||
int timeout = 250;
|
||||
|
||||
if (ast_strlen_zero(data)) {
|
||||
ast_log(LOG_WARNING, "SendDTMF requires an argument (digits or *#aAbBcCdD)\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
digits = ast_strdupa(data);
|
||||
if (!digits) {
|
||||
ast_log(LOG_ERROR, "Out of Memory!\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
LOCAL_USER_ADD(u);
|
||||
for (x=0;x<strlen(digits);x++) {
|
||||
memset(&f, 0, sizeof(f));
|
||||
f.frametype = AST_FRAME_DTMF;
|
||||
f.subclass = digits[x];
|
||||
f.src = "app_senddtmf";
|
||||
res = ast_write(chan, &f);
|
||||
if (res)
|
||||
break;
|
||||
/* Wait 250ms */
|
||||
res = ast_safe_sleep(chan, 250);
|
||||
if (res)
|
||||
break;
|
||||
|
||||
if ((to = strchr(digits,'|'))) {
|
||||
*to = '\0';
|
||||
to++;
|
||||
timeout = atoi(to);
|
||||
}
|
||||
if (!res)
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "Sent digit string '%s' on %s\n", digits, chan->name);
|
||||
|
||||
|
||||
if(timeout <= 0)
|
||||
timeout = 250;
|
||||
|
||||
res = ast_dtmf_stream(chan,NULL,digits,timeout);
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app);
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
|
||||
156
apps/app_sendtext.c
Normal file
156
apps/app_sendtext.c
Normal file
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Copyright (C) 1999 - 2005, Digium, Inc.
|
||||
*
|
||||
* Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief App to transmit a text message
|
||||
*
|
||||
* Requires support of sending text messages from channel driver
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/lock.h"
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/translate.h"
|
||||
#include "asterisk/image.h"
|
||||
#include "asterisk/options.h"
|
||||
#include "asterisk/app.h"
|
||||
|
||||
static const char *tdesc = "Send Text Applications";
|
||||
|
||||
static const char *app = "SendText";
|
||||
|
||||
static const char *synopsis = "Send a Text Message";
|
||||
|
||||
static const char *descrip =
|
||||
" SendText(text[|options]): Sends text to current channel (callee).\n"
|
||||
"Result of transmission will be stored in the SENDTEXTSTATUS\n"
|
||||
"channel variable:\n"
|
||||
" SUCCESS Transmission succeeded\n"
|
||||
" FAILURE Transmission failed\n"
|
||||
" UNSUPPORTED Text transmission not supported by channel\n"
|
||||
"\n"
|
||||
"At this moment, text is supposed to be 7 bit ASCII in most channels.\n"
|
||||
"The option string many contain the following character:\n"
|
||||
"'j' -- jump to n+101 priority if the channel doesn't support\n"
|
||||
" text transport\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int sendtext_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res = 0;
|
||||
struct localuser *u;
|
||||
char *status = "UNSUPPORTED";
|
||||
char *parse = NULL;
|
||||
int priority_jump = 0;
|
||||
AST_DECLARE_APP_ARGS(args,
|
||||
AST_APP_ARG(text);
|
||||
AST_APP_ARG(options);
|
||||
);
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
if (ast_strlen_zero(data)) {
|
||||
ast_log(LOG_WARNING, "SendText requires an argument (text[|options])\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
} else {
|
||||
parse = ast_strdupa(data);
|
||||
if (!parse) {
|
||||
ast_log(LOG_ERROR, "Out of memory!\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
AST_STANDARD_APP_ARGS(args, parse);
|
||||
|
||||
if (args.options) {
|
||||
if (strchr(args.options, 'j'))
|
||||
priority_jump = 1;
|
||||
}
|
||||
|
||||
ast_mutex_lock(&chan->lock);
|
||||
if (!chan->tech->send_text) {
|
||||
ast_mutex_unlock(&chan->lock);
|
||||
/* Does not support transport */
|
||||
if (priority_jump || option_priority_jumping)
|
||||
ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return 0;
|
||||
}
|
||||
status = "FAILURE";
|
||||
ast_mutex_unlock(&chan->lock);
|
||||
res = ast_sendtext(chan, args.text);
|
||||
if (!res)
|
||||
status = "SUCCESS";
|
||||
pbx_builtin_setvar_helper(chan, "SENDTEXTSTATUS", status);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app);
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(app, sendtext_exec, synopsis, descrip);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return (char *) tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
STANDARD_USECOUNT(res);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
146
apps/app_setcallerid.c
Executable file → Normal file
146
apps/app_setcallerid.c
Executable file → Normal file
@@ -1,27 +1,92 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* App to set callerid
|
||||
*
|
||||
* Copyright (C) 1999, Mark Spencer
|
||||
* Copyright (C) 1999 - 2005, Digium, Inc.
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
* Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief App to set callerid
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/translate.h>
|
||||
#include <asterisk/image.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/lock.h"
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/translate.h"
|
||||
#include "asterisk/image.h"
|
||||
#include "asterisk/callerid.h"
|
||||
|
||||
static char *app2 = "SetCallerPres";
|
||||
|
||||
static char *synopsis2 = "Set CallerID Presentation";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static char *descrip2 =
|
||||
" SetCallerPres(presentation): Set Caller*ID presentation on a call.\n"
|
||||
" Valid presentations are:\n"
|
||||
"\n"
|
||||
" allowed_not_screened : Presentation Allowed, Not Screened\n"
|
||||
" allowed_passed_screen : Presentation Allowed, Passed Screen\n"
|
||||
" allowed_failed_screen : Presentation Allowed, Failed Screen\n"
|
||||
" allowed : Presentation Allowed, Network Number\n"
|
||||
" prohib_not_screened : Presentation Prohibited, Not Screened\n"
|
||||
" prohib_passed_screen : Presentation Prohibited, Passed Screen\n"
|
||||
" prohib_failed_screen : Presentation Prohibited, Failed Screen\n"
|
||||
" prohib : Presentation Prohibited, Network Number\n"
|
||||
" unavailable : Number Unavailable\n"
|
||||
"\n"
|
||||
;
|
||||
|
||||
static int setcallerid_pres_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
struct localuser *u;
|
||||
int pres = -1;
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
pres = ast_parse_caller_presentation(data);
|
||||
|
||||
if (pres < 0) {
|
||||
ast_log(LOG_WARNING, "'%s' is not a valid presentation (see 'show application SetCallerPres')\n",
|
||||
(char *) data);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return 0;
|
||||
}
|
||||
|
||||
chan->cid.cid_pres = pres;
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static char *tdesc = "Set CallerID Application";
|
||||
|
||||
@@ -31,21 +96,32 @@ static char *synopsis = "Set CallerID";
|
||||
|
||||
static char *descrip =
|
||||
" SetCallerID(clid[|a]): Set Caller*ID on a call to a new\n"
|
||||
"value. Sets ANI as well if a flag is used. Always returns 0\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
"value. Sets ANI as well if a flag is used. \n";
|
||||
|
||||
static int setcallerid_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res = 0;
|
||||
char tmp[256] = "";
|
||||
char *tmp = NULL;
|
||||
char name[256];
|
||||
char num[256];
|
||||
struct localuser *u;
|
||||
char *opt;
|
||||
int anitoo = 0;
|
||||
if (data)
|
||||
strncpy(tmp, (char *)data, sizeof(tmp) - 1);
|
||||
|
||||
if (ast_strlen_zero(data)) {
|
||||
ast_log(LOG_WARNING, "SetCallerID requires an argument!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
tmp = ast_strdupa(data);
|
||||
if (!tmp) {
|
||||
ast_log(LOG_ERROR, "Out of memory\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
opt = strchr(tmp, '|');
|
||||
if (opt) {
|
||||
*opt = '\0';
|
||||
@@ -53,21 +129,35 @@ static int setcallerid_exec(struct ast_channel *chan, void *data)
|
||||
if (*opt == 'a')
|
||||
anitoo = 1;
|
||||
}
|
||||
LOCAL_USER_ADD(u);
|
||||
ast_set_callerid(chan, strlen(tmp) ? tmp : NULL, anitoo);
|
||||
|
||||
ast_callerid_split(tmp, name, sizeof(name), num, sizeof(num));
|
||||
ast_set_callerid(chan, num, name, anitoo ? num : NULL);
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app2);
|
||||
res |= ast_unregister_application(app);
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(app, setcallerid_exec, synopsis, descrip);
|
||||
int res;
|
||||
|
||||
res = ast_register_application(app2, setcallerid_pres_exec, synopsis2, descrip2);
|
||||
res |= ast_register_application(app, setcallerid_exec, synopsis, descrip);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
|
||||
98
apps/app_setcdruserfield.c
Executable file → Normal file
98
apps/app_setcdruserfield.c
Executable file → Normal file
@@ -1,26 +1,45 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Applictions connected with CDR engine
|
||||
*
|
||||
* Copyright (C) 2003, Digium
|
||||
* Copyright (C) 1999 - 2005, Digium, Inc.
|
||||
*
|
||||
* Justin Huff <jjhuff@mspin.net>
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief Applictions connected with CDR engine
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/cdr.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/logger.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/cdr.h"
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/config.h"
|
||||
#include "asterisk/manager.h"
|
||||
#include "asterisk/utils.h"
|
||||
|
||||
|
||||
static char *tdesc = "CDR user field apps";
|
||||
|
||||
@@ -33,8 +52,7 @@ static char *setcdruserfield_descrip =
|
||||
" can use for data not stored anywhere else in the record.\n"
|
||||
" CDR records can be used for billing or storing other arbitrary data\n"
|
||||
" (I.E. telephone survey responses)\n"
|
||||
" Also see AppendCDRUserField().\n"
|
||||
" Always returns 0\n";
|
||||
" Also see AppendCDRUserField().\n";
|
||||
|
||||
|
||||
static char *setcdruserfield_app = "SetCDRUserField";
|
||||
@@ -49,8 +67,7 @@ static char *appendcdruserfield_descrip =
|
||||
" can use for data not stored anywhere else in the record.\n"
|
||||
" CDR records can be used for billing or storing other arbitrary data\n"
|
||||
" (I.E. telephone survey responses)\n"
|
||||
" Also see SetCDRUserField().\n"
|
||||
" Always returns 0\n";
|
||||
" Also see SetCDRUserField().\n";
|
||||
|
||||
static char *appendcdruserfield_app = "AppendCDRUserField";
|
||||
static char *appendcdruserfield_synopsis = "Append to the CDR user field";
|
||||
@@ -59,14 +76,43 @@ STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int action_setcdruserfield(struct mansession *s, struct message *m)
|
||||
{
|
||||
struct ast_channel *c = NULL;
|
||||
char *userfield = astman_get_header(m, "UserField");
|
||||
char *channel = astman_get_header(m, "Channel");
|
||||
char *append = astman_get_header(m, "Append");
|
||||
|
||||
if (ast_strlen_zero(channel)) {
|
||||
astman_send_error(s, m, "No Channel specified");
|
||||
return 0;
|
||||
}
|
||||
if (ast_strlen_zero(userfield)) {
|
||||
astman_send_error(s, m, "No UserField specified");
|
||||
return 0;
|
||||
}
|
||||
c = ast_get_channel_by_name_locked(channel);
|
||||
if (!c) {
|
||||
astman_send_error(s, m, "No such channel");
|
||||
return 0;
|
||||
}
|
||||
if (ast_true(append))
|
||||
ast_cdr_appenduserfield(c, userfield);
|
||||
else
|
||||
ast_cdr_setuserfield(c, userfield);
|
||||
ast_mutex_unlock(&c->lock);
|
||||
astman_send_ack(s, m, "CDR Userfield Set");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int setcdruserfield_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
struct localuser *u;
|
||||
int res = 0;
|
||||
|
||||
LOCAL_USER_ADD(u)
|
||||
if (chan->cdr && data)
|
||||
{
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
if (chan->cdr && data) {
|
||||
ast_cdr_setuserfield(chan, (char*)data);
|
||||
}
|
||||
|
||||
@@ -80,9 +126,9 @@ static int appendcdruserfield_exec(struct ast_channel *chan, void *data)
|
||||
struct localuser *u;
|
||||
int res = 0;
|
||||
|
||||
LOCAL_USER_ADD(u)
|
||||
if (chan->cdr && data)
|
||||
{
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
if (chan->cdr && data) {
|
||||
ast_cdr_appenduserfield(chan, (char*)data);
|
||||
}
|
||||
|
||||
@@ -94,18 +140,24 @@ static int appendcdruserfield_exec(struct ast_channel *chan, void *data)
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
|
||||
res = ast_unregister_application(setcdruserfield_app);
|
||||
res |= ast_unregister_application(appendcdruserfield_app);
|
||||
res |= ast_manager_unregister("SetCDRUserField");
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_register_application(setcdruserfield_app, setcdruserfield_exec, setcdruserfield_synopsis, setcdruserfield_descrip);
|
||||
res |= ast_register_application(appendcdruserfield_app, appendcdruserfield_exec, appendcdruserfield_synopsis, appendcdruserfield_descrip);
|
||||
|
||||
res |= ast_manager_register("SetCDRUserField", EVENT_FLAG_CALL, action_setcdruserfield, "Set the CDR UserField");
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
117
apps/app_setcidname.c
Executable file → Normal file
117
apps/app_setcidname.c
Executable file → Normal file
@@ -1,28 +1,46 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* App to set callerid
|
||||
*
|
||||
* Copyright (C) 1999, Mark Spencer
|
||||
* Copyright (C) 1999 - 2005, Digium, Inc.
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
* Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief App to set callerid
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/translate.h>
|
||||
#include <asterisk/image.h>
|
||||
#include <asterisk/callerid.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/lock.h"
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/translate.h"
|
||||
#include "asterisk/image.h"
|
||||
#include "asterisk/callerid.h"
|
||||
#include "asterisk/utils.h"
|
||||
|
||||
static char *tdesc = "Set CallerID Name";
|
||||
|
||||
@@ -34,7 +52,9 @@ static char *descrip =
|
||||
" SetCIDName(cname[|a]): Set Caller*ID Name on a call to a new\n"
|
||||
"value, while preserving the original Caller*ID number. This is\n"
|
||||
"useful for providing additional information to the called\n"
|
||||
"party. Sets ANI as well if a flag is used. Always returns 0\n";
|
||||
"party. \n"
|
||||
"SetCIDName has been deprecated in favor of the function\n"
|
||||
"CALLERID(name)\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
@@ -42,46 +62,51 @@ LOCAL_USER_DECL;
|
||||
|
||||
static int setcallerid_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res = 0;
|
||||
char tmp[256] = "";
|
||||
char oldcid[256] = "", *l, *n;
|
||||
char newcid[256] = "";
|
||||
char *tmp = NULL;
|
||||
struct localuser *u;
|
||||
char *opt;
|
||||
int anitoo = 0;
|
||||
if (data)
|
||||
strncpy(tmp, (char *)data, sizeof(tmp) - 1);
|
||||
static int deprecation_warning = 0;
|
||||
|
||||
if (!deprecation_warning) {
|
||||
ast_log(LOG_WARNING, "SetCIDName is deprecated, please use Set(CALLERID(name)=value) instead.\n");
|
||||
deprecation_warning = 1;
|
||||
}
|
||||
|
||||
if (ast_strlen_zero(data)) {
|
||||
ast_log(LOG_ERROR, "SetCIDName requires an argument!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
tmp = ast_strdupa(data);
|
||||
if (!tmp) {
|
||||
ast_log(LOG_ERROR, "Out of memory\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
opt = strchr(tmp, '|');
|
||||
if (opt) {
|
||||
*opt = '\0';
|
||||
opt++;
|
||||
if (*opt == 'a')
|
||||
anitoo = 1;
|
||||
}
|
||||
LOCAL_USER_ADD(u);
|
||||
if (chan->callerid) {
|
||||
strncpy(oldcid, chan->callerid, sizeof(oldcid) - 1);
|
||||
ast_callerid_parse(oldcid, &n, &l);
|
||||
n = tmp;
|
||||
if (strlen(n)) {
|
||||
if (l && strlen(l))
|
||||
snprintf(newcid, sizeof(newcid), "\"%s\" <%s>", n, l);
|
||||
else
|
||||
strncpy(newcid, tmp, sizeof(newcid) - 1);
|
||||
} else if (l && strlen(l)) {
|
||||
strncpy(newcid, l, sizeof(newcid) - 1);
|
||||
}
|
||||
} else
|
||||
strncpy(newcid, tmp, sizeof(newcid));
|
||||
ast_set_callerid(chan, strlen(newcid) ? newcid : NULL, anitoo);
|
||||
|
||||
ast_set_callerid(chan, NULL, tmp, NULL);
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app);
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
|
||||
101
apps/app_setcidnum.c
Executable file → Normal file
101
apps/app_setcidnum.c
Executable file → Normal file
@@ -1,29 +1,47 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* App to set callerid
|
||||
*
|
||||
* Copyright (C) 1999, Mark Spencer
|
||||
* Copyright (C) 1999 - 2005, Digium, Inc.
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
* Mark Spencer <markster@digium.com>
|
||||
* Oliver Daudey <traveler@xs4all.nl>
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief App to set callerid number
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/translate.h>
|
||||
#include <asterisk/image.h>
|
||||
#include <asterisk/callerid.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/lock.h"
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/translate.h"
|
||||
#include "asterisk/image.h"
|
||||
#include "asterisk/callerid.h"
|
||||
#include "asterisk/utils.h"
|
||||
|
||||
static char *tdesc = "Set CallerID Number";
|
||||
|
||||
@@ -35,7 +53,9 @@ static char *descrip =
|
||||
" SetCIDNum(cnum[|a]): Set Caller*ID Number on a call to a new\n"
|
||||
"value, while preserving the original Caller*ID name. This is\n"
|
||||
"useful for providing additional information to the called\n"
|
||||
"party. Sets ANI as well if a flag is used. Always returns 0\n";
|
||||
"party. Sets ANI as well if a flag is used.\n"
|
||||
"SetCIDNum has been deprecated in favor of the function\n"
|
||||
"CALLERID(number)\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
@@ -44,14 +64,24 @@ LOCAL_USER_DECL;
|
||||
static int setcallerid_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res = 0;
|
||||
char tmp[256] = "";
|
||||
char oldcid[256] = "", *l, *n;
|
||||
char newcid[256] = "";
|
||||
struct localuser *u;
|
||||
char *opt;
|
||||
int anitoo = 0;
|
||||
char *tmp = NULL;
|
||||
static int deprecation_warning = 0;
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
if (!deprecation_warning) {
|
||||
ast_log(LOG_WARNING, "SetCIDNum is deprecated, please use Set(CALLERID(number)=value) instead.\n");
|
||||
deprecation_warning = 1;
|
||||
}
|
||||
|
||||
if (data)
|
||||
strncpy(tmp, (char *)data, sizeof(tmp) - 1);
|
||||
tmp = ast_strdupa(data);
|
||||
else
|
||||
tmp = "";
|
||||
|
||||
opt = strchr(tmp, '|');
|
||||
if (opt) {
|
||||
*opt = '\0';
|
||||
@@ -59,30 +89,23 @@ static int setcallerid_exec(struct ast_channel *chan, void *data)
|
||||
if (*opt == 'a')
|
||||
anitoo = 1;
|
||||
}
|
||||
LOCAL_USER_ADD(u);
|
||||
if (chan->callerid) {
|
||||
strncpy(oldcid, chan->callerid, sizeof(oldcid) - 1);
|
||||
ast_callerid_parse(oldcid, &n, &l);
|
||||
l = tmp;
|
||||
if (strlen(l)) {
|
||||
if (n && strlen(n))
|
||||
snprintf(newcid, sizeof(newcid), "\"%s\" <%s>", n, l);
|
||||
else
|
||||
strncpy(newcid, tmp, sizeof(newcid) - 1);
|
||||
} else if (n && strlen(n)) {
|
||||
strncpy(newcid, n, sizeof(newcid) - 1);
|
||||
}
|
||||
} else
|
||||
strncpy(newcid, tmp, sizeof(newcid));
|
||||
ast_set_callerid(chan, strlen(newcid) ? newcid : NULL, anitoo);
|
||||
|
||||
ast_set_callerid(chan, tmp, NULL, anitoo ? tmp : NULL);
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app);
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
|
||||
132
apps/app_setrdnis.c
Normal file
132
apps/app_setrdnis.c
Normal file
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Copyright (C) 1999 - 2005, Digium, Inc.
|
||||
*
|
||||
* Mark Spencer <markster@digium.com>
|
||||
* Oliver Daudey <traveler@xs4all.nl>
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief App to set rdnis
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/lock.h"
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/translate.h"
|
||||
#include "asterisk/image.h"
|
||||
#include "asterisk/callerid.h"
|
||||
#include "asterisk/utils.h"
|
||||
|
||||
static char *tdesc = "Set RDNIS Number";
|
||||
|
||||
static char *app = "SetRDNIS";
|
||||
|
||||
static char *synopsis = "Set RDNIS Number";
|
||||
|
||||
static char *descrip =
|
||||
" SetRDNIS(cnum): Set RDNIS Number on a call to a new\n"
|
||||
"value.\n"
|
||||
"SetRDNIS has been deprecated in favor of the function\n"
|
||||
"CALLERID(rdnis)\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int setrdnis_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
struct localuser *u;
|
||||
char *opt, *n, *l;
|
||||
char *tmp = NULL;
|
||||
static int deprecation_warning = 0;
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
if (!deprecation_warning) {
|
||||
ast_log(LOG_WARNING, "SetRDNIS is deprecated, please use Set(CALLERID(rdnis)=value) instead.\n");
|
||||
deprecation_warning = 1;
|
||||
}
|
||||
|
||||
if (data)
|
||||
tmp = ast_strdupa(data);
|
||||
else
|
||||
tmp = "";
|
||||
|
||||
opt = strchr(tmp, '|');
|
||||
if (opt)
|
||||
*opt = '\0';
|
||||
|
||||
n = l = NULL;
|
||||
ast_callerid_parse(tmp, &n, &l);
|
||||
if (l) {
|
||||
ast_shrink_phone_number(l);
|
||||
ast_mutex_lock(&chan->lock);
|
||||
if (chan->cid.cid_rdnis)
|
||||
free(chan->cid.cid_rdnis);
|
||||
chan->cid.cid_rdnis = (l[0]) ? strdup(l) : NULL;
|
||||
ast_mutex_unlock(&chan->lock);
|
||||
}
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app);
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(app, setrdnis_exec, synopsis, descrip);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
145
apps/app_settransfercapability.c
Normal file
145
apps/app_settransfercapability.c
Normal file
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Copyright (C) 2005, Frank Sautter, levigo holding gmbh, www.levigo.de
|
||||
*
|
||||
* Frank Sautter - asterisk+at+sautter+dot+com
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief App to set the ISDN Transfer Capability
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/options.h"
|
||||
#include "asterisk/transcap.h"
|
||||
|
||||
|
||||
static char *app = "SetTransferCapability";
|
||||
|
||||
static char *synopsis = "Set ISDN Transfer Capability";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static struct { int val; char *name; } transcaps[] = {
|
||||
{ AST_TRANS_CAP_SPEECH, "SPEECH" },
|
||||
{ AST_TRANS_CAP_DIGITAL, "DIGITAL" },
|
||||
{ AST_TRANS_CAP_RESTRICTED_DIGITAL, "RESTRICTED_DIGITAL" },
|
||||
{ AST_TRANS_CAP_3_1K_AUDIO, "3K1AUDIO" },
|
||||
{ AST_TRANS_CAP_DIGITAL_W_TONES, "DIGITAL_W_TONES" },
|
||||
{ AST_TRANS_CAP_VIDEO, "VIDEO" },
|
||||
};
|
||||
|
||||
static char *descrip =
|
||||
" SetTransferCapability(transfercapability): Set the ISDN Transfer \n"
|
||||
"Capability of a call to a new value.\n"
|
||||
"Valid Transfer Capabilities are:\n"
|
||||
"\n"
|
||||
" SPEECH : 0x00 - Speech (default, voice calls)\n"
|
||||
" DIGITAL : 0x08 - Unrestricted digital information (data calls)\n"
|
||||
" RESTRICTED_DIGITAL : 0x09 - Restricted digital information\n"
|
||||
" 3K1AUDIO : 0x10 - 3.1kHz Audio (fax calls)\n"
|
||||
" DIGITAL_W_TONES : 0x11 - Unrestricted digital information with tones/announcements\n"
|
||||
" VIDEO : 0x18 - Video:\n"
|
||||
"\n"
|
||||
;
|
||||
|
||||
static int settransfercapability_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
char *tmp = NULL;
|
||||
struct localuser *u;
|
||||
int x;
|
||||
char *opts;
|
||||
int transfercapability = -1;
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
if (data)
|
||||
tmp = ast_strdupa(data);
|
||||
else
|
||||
tmp = "";
|
||||
|
||||
opts = strchr(tmp, '|');
|
||||
if (opts)
|
||||
*opts = '\0';
|
||||
|
||||
for (x = 0; x < (sizeof(transcaps) / sizeof(transcaps[0])); x++) {
|
||||
if (!strcasecmp(transcaps[x].name, tmp)) {
|
||||
transfercapability = transcaps[x].val;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (transfercapability < 0) {
|
||||
ast_log(LOG_WARNING, "'%s' is not a valid transfer capability (see 'show application SetTransferCapability')\n", tmp);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return 0;
|
||||
}
|
||||
|
||||
chan->transfercapability = (unsigned short)transfercapability;
|
||||
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "Setting transfer capability to: 0x%.2x - %s.\n", transfercapability, tmp);
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app);
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(app, settransfercapability_exec, synopsis, descrip);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return synopsis;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
117
apps/app_skel.c
Executable file → Normal file
117
apps/app_skel.c
Executable file → Normal file
@@ -1,59 +1,134 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Skeleton application
|
||||
*
|
||||
* Copyright (C) 1999, Mark Spencer
|
||||
* Copyright (C) <Year>, <Your Name Here>
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
* <Your Name Here> <<Your Email Here>>
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
/*! \file
|
||||
*
|
||||
* \brief Skeleton application
|
||||
*
|
||||
* This is a skeleton for development of an Asterisk application
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/lock.h"
|
||||
#include "asterisk/app.h"
|
||||
|
||||
static char *tdesc = "Trivial skeleton Application";
|
||||
static char *app = "skel";
|
||||
static char *app = "Skel";
|
||||
static char *synopsis =
|
||||
" This is a skeleton application that shows you the basic structure to create your\n"
|
||||
"own asterisk applications.\n";
|
||||
"Skeleton application.";
|
||||
static char *descrip = "This application is a template to build other applications from.\n"
|
||||
" It shows you the basic structure to create your own Asterisk applications.\n";
|
||||
|
||||
#define OPTION_A (1 << 0) /* Option A */
|
||||
#define OPTION_B (1 << 1) /* Option B(n) */
|
||||
#define OPTION_C (1 << 2) /* Option C(str) */
|
||||
#define OPTION_NULL (1 << 3) /* Dummy Termination */
|
||||
|
||||
AST_DECLARE_OPTIONS(app_opts,{
|
||||
['a'] = { OPTION_A },
|
||||
['b'] = { OPTION_B, 1 },
|
||||
['c'] = { OPTION_C, 2 }
|
||||
});
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int skel_exec(struct ast_channel *chan, void *data)
|
||||
static int app_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0;
|
||||
int res = 0;
|
||||
struct ast_flags flags;
|
||||
struct localuser *u;
|
||||
if (!data) {
|
||||
ast_log(LOG_WARNING, "skel requires an argument (filename)\n");
|
||||
char *options=NULL;
|
||||
char *dummy = NULL;
|
||||
char *args;
|
||||
int argc = 0;
|
||||
char *opts[2];
|
||||
char *argv[2];
|
||||
|
||||
if (ast_strlen_zero(data)) {
|
||||
ast_log(LOG_WARNING, "%s requires an argument (dummy|[options])\n",app);
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
/* Do our thing here */
|
||||
|
||||
/* We need to make a copy of the input string if we are going to modify it! */
|
||||
args = ast_strdupa(data);
|
||||
if (!args) {
|
||||
ast_log(LOG_ERROR, "Out of memory!\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((argc = ast_app_separate_args(args, '|', argv, sizeof(argv) / sizeof(argv[0])))) {
|
||||
dummy = argv[0];
|
||||
options = argv[1];
|
||||
ast_parseoptions(app_opts, &flags, opts, options);
|
||||
}
|
||||
|
||||
if (!ast_strlen_zero(dummy))
|
||||
ast_log(LOG_NOTICE, "Dummy value is : %s\n", dummy);
|
||||
|
||||
if (ast_test_flag(&flags, OPTION_A))
|
||||
ast_log(LOG_NOTICE, "Option A is set\n");
|
||||
|
||||
if (ast_test_flag(&flags, OPTION_B))
|
||||
ast_log(LOG_NOTICE,"Option B is set with : %s\n", opts[0] ? opts[0] : "<unspecified>");
|
||||
|
||||
if (ast_test_flag(&flags, OPTION_C))
|
||||
ast_log(LOG_NOTICE,"Option C is set with : %s\n", opts[1] ? opts[1] : "<unspecified>");
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app);
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(app, skel_exec, synopsis, tdesc);
|
||||
return ast_register_application(app, app_exec, synopsis, descrip);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
|
||||
1555
apps/app_sms.c
Normal file
1555
apps/app_sms.c
Normal file
File diff suppressed because it is too large
Load Diff
98
apps/app_softhangup.c
Executable file → Normal file
98
apps/app_softhangup.c
Executable file → Normal file
@@ -1,36 +1,54 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* SoftHangup application
|
||||
*
|
||||
* Copyright (C) 1999, Mark Spencer
|
||||
* Copyright (C) 1999 - 2005, Digium, Inc.
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
* Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief SoftHangup application
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <pthread.h>
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/lock.h"
|
||||
|
||||
static char *synopsis = "Soft Hangup Application";
|
||||
|
||||
static char *tdesc = "Hangs up the requested channel";
|
||||
|
||||
static char *desc = " SoftHangup(Technology/resource)\n"
|
||||
"Hangs up the requested channel. Always returns 0\n";
|
||||
static char *desc = " SoftHangup(Technology/resource|options)\n"
|
||||
"Hangs up the requested channel. If there are no channels to hangup,\n"
|
||||
"the application will report it.\n"
|
||||
"- 'options' may contain the following letter:\n"
|
||||
" 'a' : hang up all channels on a specified device instead of a single resource\n";
|
||||
|
||||
static char *app = "SoftHangup";
|
||||
|
||||
@@ -42,19 +60,46 @@ static int softhangup_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
struct localuser *u;
|
||||
struct ast_channel *c=NULL;
|
||||
if (!data) {
|
||||
char *options, *cut, *cdata, *match;
|
||||
char name[AST_CHANNEL_NAME] = "";
|
||||
int all = 0;
|
||||
|
||||
if (ast_strlen_zero(data)) {
|
||||
ast_log(LOG_WARNING, "SoftHangup requires an argument (Technology/resource)\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
c = ast_channel_walk(NULL);
|
||||
|
||||
cdata = ast_strdupa(data);
|
||||
match = strsep(&cdata, "|");
|
||||
options = strsep(&cdata, "|");
|
||||
all = options && strchr(options,'a');
|
||||
c = ast_channel_walk_locked(NULL);
|
||||
while (c) {
|
||||
if (!strcasecmp(c->name, data)) {
|
||||
ast_softhangup(c, AST_SOFTHANGUP_EXPLICIT);
|
||||
break;
|
||||
strncpy(name, c->name, sizeof(name)-1);
|
||||
ast_mutex_unlock(&c->lock);
|
||||
/* XXX watch out, i think it is wrong to access c-> after unlocking! */
|
||||
if (all) {
|
||||
/* CAPI is set up like CAPI[foo/bar]/clcnt */
|
||||
if (!strcmp(c->type,"CAPI"))
|
||||
cut = strrchr(name,'/');
|
||||
/* Basically everything else is Foo/Bar-Z */
|
||||
else
|
||||
cut = strchr(name,'-');
|
||||
/* Get rid of what we've cut */
|
||||
if (cut)
|
||||
*cut = 0;
|
||||
}
|
||||
c = ast_channel_walk(c);
|
||||
if (!strcasecmp(name, match)) {
|
||||
ast_log(LOG_WARNING, "Soft hanging %s up.\n",c->name);
|
||||
ast_softhangup(c, AST_SOFTHANGUP_EXPLICIT);
|
||||
if(!all)
|
||||
break;
|
||||
}
|
||||
c = ast_channel_walk_locked(c);
|
||||
}
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
return 0;
|
||||
@@ -62,8 +107,13 @@ static int softhangup_exec(struct ast_channel *chan, void *data)
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app);
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user