Browse Source

Initial commit

master
Pali 5 years ago
commit
4a0f2d370b
  1. 59
      admin_scripts/auto_answer.pl
  2. 25
      admin_scripts/erase_config.pl
  3. 24
      admin_scripts/force_reboot.pl
  4. 23
      admin_scripts/list_errors.pl
  5. 29
      admin_scripts/normalize_volume.pl
  6. 54
      admin_scripts/send_reboot.pl
  7. 33
      admin_scripts/volume_up.pl
  8. 6
      all_reboot.sh
  9. 14
      ann_end.sh
  10. 11
      ann_end_all.sh
  11. 21
      ann_listen.sh
  12. 5
      ann_listen_all.sh
  13. 30
      ann_play.sh
  14. 36
      ann_play_unicast.sh
  15. 18
      ann_stop.sh
  16. 18
      ann_volup.sh
  17. 15
      autoanswer_all.sh
  18. 12
      autoanswer_line.sh
  19. 24
      cislovaci_plan
  20. 2
      clean.sh
  21. 4
      config.txt
  22. 8
      conv_ring.sh
  23. 22
      etc_asterisk/confbridge.conf
  24. 141
      etc_asterisk/extensions.lua
  25. 3
      etc_asterisk/logger.conf
  26. 11
      etc_asterisk/manager.conf
  27. 73
      etc_asterisk/modules.conf
  28. 10
      etc_asterisk/pjsip.conf
  29. 36
      etc_asterisk/pjsip_wizard.conf
  30. 6
      etc_asterisk/voicemail.conf
  31. 6
      etc_dnsmasq.d/dhcp.conf
  32. 4
      etc_dnsmasq.d/phones_tftp.conf
  33. 174
      gen.pl
  34. 11
      gen_hr.sh
  35. 16
      gen_sounds.sh
  36. 12
      hangup_all.sh
  37. 179
      hr.txt
  38. 5
      hr_join.sh
  39. 6
      list_errors.sh
  40. 1
      list_errors_crontab
  41. 54
      logo/anytoppm.sh
  42. BIN
      logo/hipporion.bmp
  43. BIN
      logo/hipporion.png
  44. BIN
      logo/hipporion2.bmp
  45. BIN
      logo/hipporion2.png
  46. BIN
      logo/ksp.bmp
  47. BIN
      logo/logo
  48. 55
      logo/logo.sh
  49. 21
      logo/ppmfix.sh
  50. 58
      message_receiver.pl
  51. 4
      message_receiver.service
  52. 12
      normalize_volume_all.sh
  53. 40
      phones.txt
  54. 20
      pocasi.py
  55. 7
      rand_line.sh
  56. BIN
      sounds/heslo.wav
  57. BIN
      sounds/klapka.wav
  58. BIN
      sounds/spatne_heslo.wav
  59. 17
      tftp/Dialplan.xml
  60. 9
      tftp/RingTones/Piano.pcm
  61. 230
      tftp/SIPDefault.cnf
  62. 3
      tftp/syncinfo.xml
  63. 26
      tftp_reflash/XMLDefault.cnf.xml
  64. 25
      toilet_paper.sh
  65. 3
      tts.sh
  66. 5
      wc_thanks.sh
  67. 157
      webapp/directory.psgi
  68. 4
      webapp/directory.service
  69. 6
      webapp/directory.uwsgi
  70. 33
      webapp/hraj.pl
  71. 4
      webapp/hraj.service
  72. 7
      webapp/hraj.uwsgi
  73. 676
      webapp/services.psgi
  74. 4
      webapp/services.service
  75. 6
      webapp/services.uwsgi
  76. 13
      www/directory_external.txt
  77. BIN
      www/logo.bmp
  78. 2
      www/orgovia.txt
  79. 2
      www/osoby.txt
  80. 34
      www/tovar.txt
  81. 0
      znelky/.keep

59
admin_scripts/auto_answer.pl

@ -0,0 +1,59 @@
#!/usr/bin/perl
# (c) Pali 2019, Perl license
use strict;
use warnings;
use Net::Telnet;
use Time::HiRes qw(usleep);
die "Usage: $0 host pass line 0|1\n" unless @ARGV == 4;
my $host = $ARGV[0];
my $pass = $ARGV[1];
my $line = $ARGV[2];
my $enable = $ARGV[3];
die "Line $line is not valid line number [1-6]\n" unless $line =~ /^[1-6]$/;
my $t = Net::Telnet->new(Timeout => 3, Prompt => '/[^\n]*> $/');
$t->open($host);
$t->waitfor('/Password :$/');
$t->print($pass);
$t->waitfor($t->prompt);
my $failed;
my $skip;
my $auto_answer;
for (1..10) {
if ($_ == 10) {
$failed = 1;
last;
}
($auto_answer) = map { /^auto_answer : ([0-9]+)$/ ? $1 : () } $t->cmd('show config');
if ($enable and ($auto_answer & (1 << ($line - 1)))) {
do { print "auto_answer on $host is already enabled\n"; $skip = 1 } if $_ == 1;
last;
} elsif (not $enable and not ($auto_answer & (1 << ($line - 1)))) {
do { print "auto_answer on $host is already disabled\n"; $skip = 1 } if $_ == 1;
last;
}
foreach ('open', 'key dir', 'key set', 'key set', 'key soft4', 'key set', 'key 6', 'key 8', "key $line", 'key soft1', 'key soft2', 'key set', 'close') {
$t->cmd("test $_");
usleep 200_000;
}
}
$t->print("exit");
$t->close();
if ($failed) {
warn (($enable ? "enabling" : "disabling") . " auto_answer on $host failed\n");
exit 1;
} else {
print ("auto_answer on $host is now " . ($enable ? "enabled" : "disabled") . "\n") unless $skip;
exit 0;
}

25
admin_scripts/erase_config.pl

@ -0,0 +1,25 @@
#!/usr/bin/perl
# (c) Pali 2019, Perl license
use strict;
use warnings;
use Net::Telnet;
die "Usage: $0 host pass\n" unless @ARGV == 2;
my $host = $ARGV[0];
my $pass = $ARGV[1];
my $t = Net::Telnet->new(Timeout => 3, Prompt => '/[^\n]*> $/');
$t->open($host);
$t->waitfor('/Password :$/');
$t->print($pass);
$t->waitfor($t->prompt);
$t->cmd('erase protflash');
# TODO: check if erase was allowed
$t->print('exit');
$t->close();

24
admin_scripts/force_reboot.pl

@ -0,0 +1,24 @@
#!/usr/bin/perl
# (c) Pali 2019, Perl license
use strict;
use warnings;
use Net::Telnet;
die "Usage: $0 host pass\n" unless @ARGV == 2;
my $host = $ARGV[0];
my $pass = $ARGV[1];
my $t = Net::Telnet->new(Timeout => 3, Prompt => '/[^\n]*> $/');
$t->open($host);
$t->waitfor('/Password :$/');
$t->print($pass);
$t->waitfor($t->prompt);
$t->print('reset');
# TODO: check if reset was allowed
$t->close();

23
admin_scripts/list_errors.pl

@ -0,0 +1,23 @@
#!/usr/bin/perl
# (c) Pali 2019, Perl license
use strict;
use warnings;
use Net::Telnet;
die "Usage: $0 host pass\n" unless @ARGV == 2;
my $host = $ARGV[0];
my $pass = $ARGV[1];
my $t = Net::Telnet->new(Timeout => 3, Prompt => '/[^\n]*> $/');
$t->open($host);
$t->waitfor('/Password :$/');
$t->print($pass);
$t->waitfor($t->prompt);
print "$_\n" foreach grep !/^(?:Current Phone Status|--------------------|I100 No errors|)$/, map { /^[\x00-\x31\s]*(.*?)\s*$/s; $1 } $t->cmd('show status');
$t->print("exit");
$t->close();

29
admin_scripts/normalize_volume.pl

@ -0,0 +1,29 @@
#!/usr/bin/perl
# (c) Pali 2019, Perl license
use strict;
use warnings;
use Net::Telnet;
use Time::HiRes qw(usleep);
die "Usage: $0 host pass volume\n" unless @ARGV == 3;
my $host = $ARGV[0];
my $pass = $ARGV[1];
my $vol = $ARGV[2];
my $t = Net::Telnet->new(Timeout => 3, Prompt => '/[^\n]*> $/');
$t->open($host);
$t->waitfor('/Password :$/');
$t->print($pass);
$t->waitfor($t->prompt);
foreach ('open', ('key voldn') x 16, ('key volup') x $vol, 'close') {
$t->cmd("test $_");
usleep 200_000;
}
$t->print("exit");
$t->close();

54
admin_scripts/send_reboot.pl

@ -0,0 +1,54 @@
#!/usr/bin/perl
# (c) Pali 2019, Perl license
use strict;
use warnings;
use Net::SIP;
use Net::SIP::Util qw(laddr4dst INETSOCK ip_sockaddr2parts);
use Socket;
die "Usage: $0 host line\n" unless @ARGV == 2;
my $host = $ARGV[0];
my $line = $ARGV[1];
my $ip = inet_aton($host);
die "ERROR: Cannot resolve host\n" unless defined $ip;
my $addr = inet_ntoa($ip);
my $laddr = laddr4dst($addr);
die "ERROR: No route to host\n" unless $laddr;
my $sock = INETSOCK(Proto => 'udp', LocalAddr => $laddr, LocalPort => 0);
die "ERROR: Cannot create socket: $!\n" unless $sock;
my $lport = (ip_sockaddr2parts(getsockname($sock)))[1];
my $leg = Net::SIP::Leg->new(sock => $sock);
die "ERROR: Cannot create leg: $!\n" unless $leg;
my $ua = Net::SIP::Simple->new(from => "<sip:root\@$laddr:$lport>", leg => $leg);
die "ERROR: Cannot create SIP user agent: $!\n" unless $ua;
my ($stop, $code, $text);
$ua->{endpoint}->new_request(
'NOTIFY',
{ from => $ua->{from}, to => "<sip:$line\@$host>" },
sub {
(undef, undef, undef, $code, my $packet) = @_;
(undef, $text) = $packet ? $packet->as_parts : ();
$stop = 1;
},
'',
uri => "sip:$line\@$addr",
Event => 'check-sync',
Contact => $ua->{from},
);
$ua->loop(3, \$stop);
$ua->cleanup();
die "ERROR: Timeout\n" unless $stop;
die "ERROR: Invalid response\n" unless $code and $text;
die "ERROR: SIP response: $code $text\n" unless $code eq '200';

33
admin_scripts/volume_up.pl

@ -0,0 +1,33 @@
#!/usr/bin/perl
# (c) Pali 2019, Perl license
use strict;
use warnings;
use Net::Telnet;
use Time::HiRes qw(usleep);
die "Usage: $0 host pass ast_user\n" unless @ARGV == 3;
my $host = $ARGV[0];
my $pass = $ARGV[1];
my $user = $ARGV[2];
my $t = Net::Telnet->new(Timeout => 3, Prompt => '/[^\n]*> $/');
$t->open($host);
$t->waitfor('/Password :$/');
$t->print($pass);
$t->waitfor($t->prompt);
foreach ('open', ('key volup') x 16, 'close') {
if (system('sh', '-c', qq[asterisk -rx "core show channels" |grep -q "$user"]) != 0) {
print STDERR "Call ended, exiting";
last;
}
$t->cmd("test $_");
usleep 200_000;
}
$t->print("exit");
$t->close();

6
all_reboot.sh

@ -0,0 +1,6 @@
#!/bin/sh
pass=`sed -n 's/telnet_pass=//p' config.txt`
ip=`sed -n 's/server_ip=//p' config.txt | sed 's/\.[0-9]*$//'`
for i in `cat phones.txt | grep -v \- | sed -n 's/^\([0-9][0-9]\).*/\1/p'`; do
{ admin_scripts/send_reboot.pl "$ip.$i" "$i" 2>&1 || admin_scripts/force_reboot.pl "$ip.$i" "$pass" 2>&1 ; } | sed "s/^/$i: /"
done

14
ann_end.sh

@ -0,0 +1,14 @@
#!/bin/bash
line="$1"
[[ -n "$line" ]] || { echo >&2 "usage: $0 <line>"; exit 1; }
echo "Action: login
username: admin
secret: admin
events: off
Action: hangup
Channel: /PJSIP/emerg$line-.*/
" | socat - TCP:localhost:5038

11
ann_end_all.sh

@ -0,0 +1,11 @@
#!/bin/bash
cd "$(dirname "$0")"
echo "Action: login
username: admin
secret: admin
events: off
Action: hangup
Channel: /.*emerg.*/
" | socat - TCP:localhost:5038

21
ann_listen.sh

@ -0,0 +1,21 @@
#!/bin/bash
cd "$(dirname "$0")"
line="$1"
. config.txt
./ann_end.sh "$line" # and any existing calls to prevent our call ending up in "call waiting" state (and thus not autoanswered)
sleep 0.5
./autoanswer_line.sh "$line" 1 || { echo >&2 "failed to enable autoanswer, exiting."; exit 1; }
fn=/var/spool/asterisk/tmp/ann_$line.call
echo "
Channel: PJSIP/emerg$line
Context: emerg_listen
Extension: 120
Priority: 1
" >$fn
mv "$fn" /var/spool/asterisk/outgoing/
./ann_volup.sh "$line" &

5
ann_listen_all.sh

@ -0,0 +1,5 @@
#!/bin/bash
cd "$(dirname "$0")"
cat phones.txt | awk '{print $1}' | grep '^[3-5]' | xargs -n1 -P0 ./ann_listen.sh

30
ann_play.sh

@ -0,0 +1,30 @@
#!/bin/bash
# By default, we operate in bracketed mode: initiate listening calls, play announcement and terminate them
# With -n, we do not do bracketing, you have to initiate and terminate listening calls yourself
# with ann_listen[_all].sh and ann_end[_all].sh. Useful if you want to combine playback and speech in
# one announcement (call 121 to speak without bracketing).
if [[ "$1" == -n ]]; then num=121; shift; else num=122; fi
playstring="silence/1"
i=0
for arg in "$@"; do
if [[ "$arg" =~ ^silence ]]; then
playitem="$arg"
else
ffmpeg -i "$arg" -ar 8000 -ac 1 -y /tmp/ann$i.wav
playitem=/tmp/ann$i
fi
playstring="$playstring&$playitem"
i=$((i+1))
done
fn=/var/spool/asterisk/tmp/ann_play.call
echo "
Channel: Local/$num@orgs
Application: Playback
Data: $playstring
" >$fn
mv $fn /var/spool/asterisk/outgoing/

36
ann_play_unicast.sh

@ -0,0 +1,36 @@
#!/bin/bash
cd "$(dirname "$0")"
line="$1"
snd="$2"
. config.txt
./ann_end.sh "$line" # and any existing calls to prevent our call ending up in "call waiting" state (and thus not autoanswered)
sleep 0.5
./autoanswer_line.sh "$line" 1 || { echo >&2 "failed to enable autoanswer, exiting."; exit 1; }
playstring="silence/1"
i=0
for arg in "$@"; do
if [[ "$arg" =~ ^silence ]]; then
playitem="$arg"
else
ffmpeg -i "$arg" -ar 8000 -ac 1 -y /tmp/ann${line}_$i.wav
playitem=/tmp/ann${line}_$i
fi
playstring="$playstring&$playitem"
i=$((i+1))
done
fn=/var/spool/asterisk/tmp/ann_$line.call
echo "
Channel: PJSIP/emerg$line
Application: Playback
Data: $playstring
Priority: 1
" >$fn
mv "$fn" /var/spool/asterisk/outgoing/
./ann_volup.sh "$line" &

18
ann_stop.sh

@ -0,0 +1,18 @@
#!/bin/bash
cd "$(dirname "$0")"
./ann_end_all.sh
echo "Action: login
username: admin
secret: admin
events: off
Action: hangup
Channel: /.*emerg.*/
Action: ConfbridgeKick
Conference: 120
Channel: all
" | socat - TCP:localhost:5038

18
ann_volup.sh

@ -0,0 +1,18 @@
#!/bin/bash
cd "$(dirname "$0")"
line="$1"
[[ "$line" =~ ^[0-9]+$ ]] || { echo >&2 "usage: $0 <line>"; exit 1; }
. config.txt
ip_prefix=${server_ip%.*}
ip="$ip_prefix.$line"
for i in $(seq 1 10); do
if asterisk -rx "core show channels" |grep -q "emerg$line"; then
./admin_scripts/volume_up.pl "$ip" "$telnet_pass" "emerg$line"
break
else
sleep 1
fi
done

15
autoanswer_all.sh

@ -0,0 +1,15 @@
#!/bin/bash
state="$1"
case $state in
1)
gr=enabled
;;
0)
gr=disabled
;;
esac
cd /opt/ksp
cat phones.txt | awk '{print $1}' | grep '^[3-5]' | xargs -i -n1 -P0 ./autoanswer_line.sh '{}' "$state" | grep $gr | cut -d. -f4| cut -d' ' -f1

12
autoanswer_line.sh

@ -0,0 +1,12 @@
#!/bin/bash
cd "$(dirname "$0")"
line="$1"
state="$2"
{ [[ "$line" =~ ^[0-9]+$ ]] && [[ "$state" =~ ^[01]$ ]]; } || { echo >&2 "usage: $0 <line> <0|1>"; exit 1; }
. config.txt
ip_prefix=${server_ip%.*}
ip="$ip_prefix.$line"
./admin_scripts/auto_answer.pl "$ip" "$telnet_pass" 2 "$state"

24
cislovaci_plan

@ -0,0 +1,24 @@
veřejné číslo pro volání zvenku: 910 128 976
0 - 9 - nič
20 - 29 - ORG cisco telefóny
30 - 59 - zvyšné cisco telefóny
60 - 99 - zvyšné ne-cisco telefóny (ak budeme zapájať iných SIP klientov)
78 - (mnemonic: "su") Volání org-only čísel z libovolného telefonu, případně zvenku
100 - 199 - čísla pre automaty, odkazové schránky a iné veci
- 11x... veřejné konference
- 12x announce mechanismus
- 120 announce listen
- 121 [org only] announce speak (jen umožňuje mluvit k posluchačům)
- 122 [org only] announce (připoj všechny účastníky do konference a pak mluv)
- 123xx [org only] unicast announce na telefon xx (funguje obousměrně; nezneužívat k odposlechu, ale můžete se bavit s účastníky)
- 130 - vytočí náhodnú non-ORG linku
- 131 - vyzvednutí hlasových zpráv
- 14xx - přímé zanechání hlasové zprávy pro linku xx
- 16x - IVR
- 161 - FBI
Podle samolepek na telefonu:
8888 - helpdesk -> FBI
4445 - HR -> přečtení pokynů

2
clean.sh

@ -0,0 +1,2 @@
#!/bin/sh
rm -f etc_asterisk/pjsip_wizard_phones.conf etc_asterisk/voicemail_gen.conf tftp_reflash/SIP00*.cnf tftp_reflash/SIPDefault.cnf tftp/Phones/SIP00*.cnf tftp/RINGLIST.DAT etc_dnsmasq.d/phones.conf www/directory.txt etc_asterisk/voicemail_gen.conf

4
config.txt

@ -0,0 +1,4 @@
server_ip=172.16.0.1
telnet_pass=FIXME
hmac_key=FIXME
fake_year=2114

8
conv_ring.sh

@ -0,0 +1,8 @@
#!/bin/sh -e
if test "$#" != "1"; then echo "Usage: $0 sound_file.ext"; exit 1; fi
file="${1%.*}.pcm"
ffmpeg -loglevel fatal -y -i "$1" -f u8 -c pcm_mulaw -ar 8000 -ac 1 "$file"
size=`du -b "$file" | cut -f1`
size=$(($size/240*240))
if test "$size" -gt "16080"; then size=16080; fi
truncate -s "$size" "$file"

22
etc_asterisk/confbridge.conf

@ -0,0 +1,22 @@
[default_bridge]
type=bridge
video_mode=none
[ann_listen]
type=user
startmuted=yes
quiet=yes
announce_only_user=no
[ann_speak]
type=user
quiet=yes
announce_only_user=no
startmuted=no
[ann]
type=bridge
video_mode=none
[empty_menu]
type=menu

141
etc_asterisk/extensions.lua

@ -0,0 +1,141 @@
extensions = {}
extensions.participants = {}
extensions.orgs = {}
extensions.emerg = {}
extensions.emerg_listen = {}
extensions.ann_bracket = {}
extensions.odorik = {}
extensions.external = {}
function sip_exten(ch, ext)
app.dial("PJSIP/" .. ext, 40)
local status = channel.DIALSTATUS:get()
app.verbose("status: " .. status)
if status == "BUSY" then
flags="b"
else
flags="u"
end
app.voicemail(ext, flags)
end
function ann_unicast(ch, ext)
app.dial("PJSIP/emerg" .. string.sub(ext, 4))
end
function sip_nightmode(ch, ext)
local hour = tonumber(os.date("%H"))
local minute = tonumber(os.date("%M"))
if hour < 12 or (hour == 12 and minute < 10) or hour > 23 or (hour == 23 and minute > 20) then
app.playback("/opt/ksp/sounds/nocni_klid")
app.voicemail(ext)
else
sip_exten(ch, ext)
end
end
function voicemail_direct(ch, ext)
app.voicemail(string.sub(ext, 3))
end
function voicemail_listen(ch, ext)
local caller = channel.CALLERID("num"):get()
app.voicemailmain(caller, "s") -- no password prompt
end
function conf(ch, ext)
app.confbridge(ext)
end
function add(ctxs, ext, func)
for i = 1, #ctxs do
extensions[ctxs[i]][ext] = func
end
end
function ann_listen(ch, ext)
app.confbridge("120", "ann", "ann_listen", "empty_menu")
end
function ann_speak(ch, ext)
app.confbridge("120", "ann", "ann_speak")
end
function ann_bracket(ch, ext)
app.system("/opt/ksp/ann_listen_all.sh")
app.confbridge("120", "ann", "ann_speak")
end
function ann_bracket_hangup(ch, ext)
app.system("/opt/ksp/ann_end_all.sh")
end
function ann_bracket_goto(ch, ext)
app.goto("ann_bracket", "122", 1)
end
function fbi(ch, ext)
app.dial("PJSIP/910119352@odorik")
end
function odorik_incoming(ch, ext)
app.answer()
app.read("klapka", "/opt/ksp/sounds/klapka")
local klapka = channel.klapka:get()
app.goto("external", klapka, 1)
end
function su(ch, ext)
app.read("heslo", "/opt/ksp/sounds/heslo")
local heslo = channel.heslo:get()
if heslo == "2886287" then
app.read("klapka", "/opt/ksp/sounds/klapka")
local klapka = channel.klapka:get()
app.goto("orgs", klapka, 1)
else
app.playback("/opt/ksp/sounds/spatne_heslo")
app.hangup()
end
end
--http://lua-users.org/wiki/StringTrim
function trim1(s)
return (s:gsub("^%s*(.-)%s*$", "%1"))
end
function call_rand(ch, ext)
local caller = channel.CALLERID("num"):get():gsub("'", "")
local handle = io.popen("/opt/ksp/rand_line.sh '" .. caller .. "'")
local line = trim1(handle:read("*all"))
handle:close()
app.verbose("RAND: " .. line)
app.dial("PJSIP/"..line)
end
function snd(name)
return function(ch, ext)
app.answer()
app.playback("/opt/ksp/sounds/" .. name)
app.hangup()
end
end
add({"orgs"}, "_2X", sip_exten) -- org phones
add({"orgs"}, "_[345]X", sip_exten) -- participant phones
-- night mode restriction applies only when calling from participant phones
add({"participants", "external"}, "_2X", sip_nightmode) -- org phones
add({"participants", "external"}, "_[345]X", sip_nightmode) -- participant phones
add({"orgs", "participants", "external"}, "_11.", conf)
add({"orgs", "participants", "emerg_listen", "external"}, "120", ann_listen)
add({"orgs"}, "121", ann_speak)
-- Because hangup actions are per-context and not per-extension, we need to jump to
-- a separate context to allow a hangup handler to terminate listeners after a call
-- to 122 is done.
add({"orgs"}, "122", ann_bracket_goto)
add({"ann_bracket"}, "122", ann_bracket)
add({"ann_bracket"}, "h", ann_bracket_hangup)
add({"orgs"}, "_123XX", ann_unicast)
add({"orgs", "participants"}, "131", voicemail_listen) -- does not work, done in extensions.conf!!
add({"orgs", "participants", "external"}, "_14XX", voicemail_direct)
add({"participants", "external"}, "78", su)
add({"odorik"}, "s", odorik_incoming)
add({"orgs", "participants", "external"}, "160", fbi)
add({"orgs", "participants", "external"}, "910119352", fbi)
-- Na některých telefonech je od původních majitelů nálepka "call helpdesk at 8888"
add({"orgs", "participants", "external"}, "8888", fbi)
add({"orgs", "participants", "external"}, "4445", snd("hr"))
add({"orgs", "participants", "external"}, "130", call_rand)
--add({"orgs", "participants"}, "_131", snd("sadtromb"))

3
etc_asterisk/logger.conf

@ -0,0 +1,3 @@
[logfiles]
console => notice,warning,error,debug,verbose

11
etc_asterisk/manager.conf

@ -0,0 +1,11 @@
[general]
enabled = yes
webenabled = no
port = 5038
bindaddr = 127.0.0.1
[admin]
secret = admin
read = all
write = all

73
etc_asterisk/modules.conf

@ -0,0 +1,73 @@
;
; Asterisk configuration file
;
; Module Loader configuration file
;
[modules]
autoload=yes
;
; Any modules that need to be loaded before the Asterisk core has been
; initialized (just after the logger has been initialized) can be loaded
; using 'preload'. This will frequently be needed if you wish to map all
; module configuration files into Realtime storage, since the Realtime
; driver will need to be loaded before the modules using those configuration
; files are initialized.
;
; An example of loading ODBC support would be:
;preload => res_odbc.so
;preload => res_config_odbc.so
;
; If you want, load the GTK console right away.
; Don't load the KDE console since
; it's not as sophisticated right now.
;
noload => pbx_gtkconsole.so
;load => pbx_gtkconsole.so
noload => pbx_kdeconsole.so
;
; Intercom application is obsoleted by
; chan_oss. Don't load it.
;
noload => app_intercom.so
;
; The 'modem' channel driver and its subdrivers are
; obsolete, don't load them.
;
noload => chan_modem.so
noload => chan_modem_aopen.so
noload => chan_modem_bestdata.so
noload => chan_modem_i4l.so
;
; Comment this out (after installing CAPI middleware and hardware
; drivers) if you have CAPI-able hardware and wish to use it in
; Asterisk.
;
noload => chan_capi.so
;
load => res_musiconhold.so
;
; Do not load load local channel drivers (using the system speaker) by default,
; they are not used in most installations and might block the sound hardware
;
noload => chan_alsa.so
noload => chan_console.so
noload => chan_oss.so
;
; Disable CDR logging to SQLite by default since it writes unconditionally to
; cdr.db without a way to rotate it.
;
noload => cdr_sqlite.so
;
; These conflict with app_directory.so and each other.
noload => app_directory_odbc.so
;
; Enable these if you want to configure Asterisk in a database
;
noload => res_config_odbc.so
noload => res_config_pgsql.so
;
; Module names listed in "global" section will have symbols globally
; exported to modules loaded after them.
;
[global]

10
etc_asterisk/pjsip.conf

@ -0,0 +1,10 @@
[system-udp]
type=transport
protocol=udp
bind=0.0.0.0
[system-tcp]
type=transport
protocol=tcp
bind=0.0.0.0

36
etc_asterisk/pjsip_wizard.conf

@ -0,0 +1,36 @@
[base_phone](!)
type = wizard
transport = system-udp
accepts_registrations = yes
sends_registrations = no
accepts_auth = yes
sends_auth = no
aor/max_contacts = 1
aor/remove_existing = yes
endpoint/allow = !all,alaw
endpoint/direct_media = yes
[participant_phone](!,base_phone)
endpoint/context = participants
[participant_emerg](!,base_phone)
endpoint/context = emerg
[org_phone](!,base_phone)
endpoint/context = orgs
[odorik]
type = wizard
transport = system-udp
sends_auth = yes
sends_registrations = yes
remote_hosts = 81.31.45.51 ; sip.odorik.cz
; public number: 910 128 976
outbound_auth/username = 747515
#include odorik_pass.conf
endpoint/context = odorik
aor/qualify_frequency = 15
endpoint/allow = !all,alaw
#include pjsip_wizard_phones.conf

6
etc_asterisk/voicemail.conf

@ -0,0 +1,6 @@
[general]
format=wav
[default]
#include voicemail_gen.conf

6
etc_dnsmasq.d/dhcp.conf

@ -0,0 +1,6 @@
interface=eth0
bind-dynamic
dhcp-authoritative
listen-address=172.16.0.1
dhcp-range=172.16.0.100,172.16.0.200
dhcp-leasefile=/tmp/dhcp.leases

4
etc_dnsmasq.d/phones_tftp.conf

@ -0,0 +1,4 @@
dhcp-vendorclass=set:CiscoIPPhone,"Cisco Systems, Inc. IP Phone"
dhcp-option=tag:CiscoIPPhone,150,0.0.0.0
enable-tftp
tftp-root=/opt/ksp/tftp

174
gen.pl

@ -0,0 +1,174 @@
#!/usr/bin/perl
use strict;
use warnings;
use Digest::SHA qw(hmac_sha1_hex);
use Encode;
use Text::Unidecode;
mkdir "tftp/Phones";
my $fh;
my %config;
open $fh, '<', 'config.txt' or die "Cannot read file config: $!\n";
while (<$fh>) {
chomp;
my ($key, $value) = split /=/, $_, 2;
$config{$key} = $value;
}
close $fh;
my $server_ip = $config{server_ip};
my $ip_template = $server_ip;
$ip_template =~ s/\.[^.]*$//;
my $fake_second_half = $config{fake_year};
my $sipdefault_reflash = <<"EOD";
image_version: P0S3-8-12-00
phone_password: $config{telnet_pass}
encrypt_key: 00000000000000000000000000000000
telnet_level: 2
tftp_cfg_dir: ""
EOD
chomp $sipdefault_reflash;
open my $phones_fh, '<', 'phones.txt' or die "Cannot read file phones.txt: $!\n";
open my $ast_fh, '>', 'etc_asterisk/pjsip_wizard_phones.conf' or die "Cannot create file etc_asterisk/pjsip_wizard_phones.conf: $!\n";
open my $dnsmasq_fh, '>', 'etc_dnsmasq.d/phones.conf' or die "Cannot create file etc_dnsmasq.d/phones.conf: $!\n";
open my $directory_fh, '>', 'www/directory.txt' or die "Cannot create file www/directory.txt: $!\n";
open my $voicemail_fh, '>', 'etc_asterisk/voicemail_gen.conf' or die "Cannot create file etc_asterisk/voicemail_gen.conf: $!\n";
print $ast_fh "; This is autogenerated file, do not edit it!\n";
print $dnsmasq_fh "# This is autogenerated file, do not edit it!\n";
print $directory_fh "# This is autogenerated file, do not edit it!\n";
print $voicemail_fh "; This is autogenerated file, do not edit it!\n";
while (<$phones_fh>) {
chomp $_;
next if $_ =~ /^(?:#|$)/;
$_ =~ s/#.*//;
$_ =~ s/\s*$//;
my ($line, $mac, $alias, $name) = split /\s+/, $_, 4;
die "Invalid line $.: $_\n" unless defined $name;
$mac = uc $mac;
my $name_latin1 = $name;
Encode::from_to($name_latin1, 'UTF-8', 'ISO-8859-1', sub { unidecode(chr($_[0])) });
$line =~ /^[2-9][0-9]$/ or die "Invalid LINE $line on line $.: $_\n";
$alias =~ /^[A-Za-z0-9_]{1,20}$/ or die "Invalid ALIAS $alias on line $.: $_\n";
length $name_latin1 <= 30 or die "Too long NAME $name on line $.: $_\n";
my $parent = ($line =~ /^2[0-9]$/) ? 'org_phone' : 'participant_phone';
my $pass = substr(hmac_sha1_hex($line, $config{hmac_key}), 0, 12);
my $cisco_fh;
my $ciscofile;
if ($mac ne '-') {
$mac =~ /^(?:[0-9A-F]{2}:){5}[0-9A-F]{2}$/ or die "Invalid MAC $mac on line $.: $_\n";
$ciscofile = $mac;
$ciscofile =~ s/://g;
open $cisco_fh, '>', "tftp/Phones/SIP$ciscofile.cnf" or die "Cannot create file tftp/Phones/SIP$ciscofile.cnf: $!\n";
print $cisco_fh <<"EOD";
# This is autogenerated file, do not edit it!
phone_label: "$fake_second_half Klapka $line "
phone_prompt: "Telnet phone $line"
proxy_register: 1
proxy1_address: $server_ip
proxy1_port: 5060
line1_name: $line
line1_authname: $line
line1_password: $pass
line1_displayname: "$alias"
line1_shortname: "$name_latin1"
sntp_server: $server_ip
sntp_mode: unicast
services_url: http://$server_ip/services.xml
directory_url: http://$server_ip/directory.xml
logo_url: http://$server_ip/logo.bmp
messages_uri: 131
telnet_level: 2
EOD
close $fh;
}
print $ast_fh <<"EOD";
[$line]($parent)
inbound_auth/username = $line
inbound_auth/password = $pass
endpoint/mailboxes = $line
EOD
if ($parent eq 'participant_phone') {
print $ast_fh <<"EOD";
[emerg$line](participant_emerg)
inbound_auth/username = emerg$line
inbound_auth/password = $pass
EOD
if ($mac ne '-') {
print $cisco_fh <<"EOD"
proxy2_address: $server_ip
proxy2_port: 5060
line2_name: emerg$line
line2_authname: emerg$line
line2_password: $pass
line2_displayname: "Emergency $line"
line2_shortname: " "
EOD
}
} else {
if ($mac ne '-') {
print $cisco_fh <<"EOD"
dnd_control: 0
EOD
}
}
if ($mac ne '-') {
close $cisco_fh;
open $fh, '>', "tftp_reflash/SIP$ciscofile.cnf" or die "Cannot create file tftp_reflash/SIP$ciscofile.cnf: $!\n";
print $fh <<"EOD";
# This is autogenerated file, do not edit it!
$sipdefault_reflash
proxy_register: 0
line1_name: $line
EOD
}
if ($mac ne '-') {
print $dnsmasq_fh <<"EOD";
dhcp-host=$mac,$ip_template.$line,$alias
EOD
}
print $directory_fh <<"EOD";
$name=$line
EOD
print $voicemail_fh <<"EOD"
$line => 0000,$name
EOD
}
close $phones_fh;
close $ast_fh;
close $dnsmasq_fh;
close $directory_fh;
close $voicemail_fh;
open $fh, '>', 'tftp_reflash/SIPDefault.cnf' or die "Cannot create file tftp_reflash/SIPDefault.cnf: $!\n";
print $fh <<"EOD";
# This is autogenerated file, do not edit it!
$sipdefault_reflash;
EOD
close $fh;
open $fh, '>', 'tftp/RINGLIST.DAT' or die "Cannot create file tftp/RINGLIST.DAT: $!\n";
foreach (<tftp/RingTones/*.pcm>) {
$_ =~ m{^tftp/(RingTones/(.*)\.pcm)$};
my ($file, $name) = ($1, $2);
$name =~ s/_/ /g;
print $fh "$name\t$file\n";
}
close $fh;

11
gen_hr.sh

@ -0,0 +1,11 @@
#!/bin/bash
i=0
grep . hr.txt | while read line; do
i=$((i+1))
echo ">> [$i] $line"
fn=hr/$(printf %03d $i).wav
if [[ -e "$fn" ]]; then continue; fi
./tts.sh "$line" "$fn"
sleep 10
done

16
gen_sounds.sh

@ -0,0 +1,16 @@
#!/bin/bash
gen_sound() {
fn="sounds/$1.wav"
[[ -e "$fn" ]] || ./tts.sh "$2" "$fn"
}
gen_sound nocni_klid "Z důvodu nočního klidu budete přesměrováni do hlasové schránky. Pokud chcete telefonovat v reálném čase, můžete oba zavolat do společné konference."
gen_sound heslo "Zadejte heslo"
gen_sound spatne_heslo "Špatné heslo"
gen_sound klapka "Zadejte číslo klapky"
gen_sound wc_thanks "Děkujeme za použití toalety. Nezapomeňte si umýt ruce."
gen_sound wc_thanks_m "Děkujeme, že jste použil naše toalety. Nezapomeňte si umýt ruce."
gen_sound wc_thanks_f "Děkujeme, že jste použila naše toalety. Nezapomeňte si umýt ruce."
gen_sound tp_prizemi "V kontaminační komoře na nulté palubě došel toaletní papír. Prosíme cestující, aby se solidárně podělili o své noviny."
gen_sound tp_prvni "V kontaminační komoře na první palubě došel toaletní papír. Prosíme cestující, aby se solidárně podělili o své noviny."
gen_sound tp_druhe "V kontaminační komoře na druhé palubě došel toaletní papír. Prosíme cestující, aby se solidárně podělili o své noviny."

12
hangup_all.sh

@ -0,0 +1,12 @@
#!/bin/bash
echo "Action: login
username: admin
secret: admin
events: off
Action: hangup
Channel: /.*/
" | socat - TCP:localhost:5038

179
hr.txt

@ -0,0 +1,179 @@
VŠEOBECNÉ SMĚRNICE PROVOZU LODI
Pokud je vaše pracovní uniforma kontaminována dihydrogen monoxidem, použijte vysokokapacitní savou substanci pro odstranění kontaminace.
Loď je vybavena telekomunikačním systémem, jehož terminály jsou rozmístěny ve většině obytných i jiných prostor.
Tyto terminály smíte využívat pro vzájemnou komunikaci s posádkou i s vedením lodi.
Váš hovor může být monitorován pro zlepšení služeb, které jsou k dispozici vedení lodi.
Zároveň budou terminály využívány pro svolávání posádky či vyvolání poplachu.
Tyto terminály je ZAKÁZÁNO ničit, vypojovat, poškozovat či jinak s nimi nemístně manipulovat.
V případě katastrofálního nedostatku toaletního papíru, který je detekován až po zahájení využívání toalety, použijte pro přivolání asistence přiloženého telekomunikačního zařízení.
Strava na lodi je vydávána nejméně třikrát denně (snídaně, oběd, večeře).
Pro blaho posádky je povinnná účast na snídani.
Snídani předchází dobrovolná tělesná rozcvička a preventivní test psychoakustické zdatnosti.
Podmínkou účasti na snídani je účast na rozcvičce.
Vzdělávání posádky je vedením podporováno.
Z tohoto důvodu se ve společenských prostorách budou každý den pořádat přibližně tři bloky odborného trénování a lekcí z teorie civilizace a vesmírné kolonizace.
Na těchto lekcích je přísně zakázáno rušit či spát.
Spící osoby budou kosmeticky či geneticky modifikovány.
Při rekreační rotační pohybové hře kruhozávodu po směru hodinových ručiček budou libovolné vzpoury tvrdě potlačeny.
Viníci budou vyhozeni přetlakovou komorou do mezihvězdného prostoru, následně budou opět zachyceni a zpracováni na karbonovou pastu.
Vedení by chtělo důrazně varovat posádku lodi o faktu, že kdo umře v Polsku, umře i ve skutečnosti.
Je zakázáno chovat na lodi domácí mazlíčky či jinou zvěř mimo prostor skladiště biologického materiálu.
Vyjímku tvoří lišky, hroši, prasata a medvědi.
Každý lodní den bude vyhrazeno nejméně třicet tři procent dne na spánek či odpočinek.
Definice lodního dne, spánku, odpočinku a procent bude upřesněna.
Při zjištění incidentu zcizení vlastního předmětu jiným členem posádky je nutno zajistit znalost jména všech zúčastněných osob.
V případě závady na skafandru je možno vyžádat si od vedení lodi náhradní.
Mějte ovšem na paměti, že nadbytečných skafandrů je omezené množství.
K respirátorům jsou k dispozici speciální kyslíkové náplně s vůní mrkve.
Je přísně zakázáno krmit zvěř ve skladišti biologického materiálu.
Po večerce se uložte ke spánku v gravitačních kójích.
Pro kvalitní spánek je nutné nejdříve ke svému jazyku připojit kabely s koncovkou typu krokodýl, která stimuluje sny, detekuje náměsíčnost a slouží jako efektivní budíček.
Budíček smí využívat pouze bezpečných úrovní napětí.
Pokud nastane katastrofální selhání štěpného reaktoru, použijte k pacifikaci zběhlých neutronů vystužených kontrolních tyčí z boronu.
Vedení lodi by chtělo zvlášť poděkovat umělci Markovi "Maark" Černému za design lodního exteriéru.
Pro zlepšenou orientaci posádky je interiér lodi vybaven orietačními symboly a směrovkami.
Mějte na paměti, že směrovky jsou orientované! Navíc je zaručeno, že graf směrovek je 2-souvislý.
Je přísně zakázáno kontaminovat mezihvězdný prostor odpadky, jako jsou například konzervy.
Veškerá rekreační zařízení jsou testována na dětech.
Do stázové komory je vstup povolen pouze v pyžamu splňujícím normu 3GPP-4923587-3B.
Nedodržení může vyústit ve smrt stářím.
Berte na vědomí, že červená reflexní etiketa značí extrémně pálivé pokrmy.
Politické mapy nově kolonizovaných území musí splňovat, že sousední území nejsou obarvena shodně a jsou použity nejvýše čtyři barvy.
Pro případ politické diskuze jsou nouzové plamenomety uloženy na třetí palubě.
Nekrmte lodní kočku bez jejího svolení.
Veškerá data o posádce (včetně záznamů pohybu, biotelemetrie, vyhledávaných frází a publikovaných příspěvků na lodní sociální síti)
budou využita pro algoritmické vylepšení a personalizaci lodních předpisů.
Každý člen posádky musí znát nejméně 50 souhvězdí.
POKYNY PŘI EVAKUACI
Veškerá posádka lodi je povinna řídit se evakuačními pokyny.
Pokud dojde k evakuaci z důvodu úniku radioaktivního materiálu ze štěpného reaktoru,
z důvodu vniku radioaktivního materiálu do fůzního reaktoru,
kvůli selhání vzduchotechniky, softwarové vyjímky, kolize s cizím objektem,
kolize se spřízněným objektem, nebo z důvodu napadení cizí formou života,
ignorujte v tomto případě všeobecné nařízení §451-3.
Pokud dojde k evakuaci z důvodu ztráty elektrické energie,
z důvodu vniku radioaktivního materiálu do fůzního reaktoru,
kvůli prudkému poklesu tlaku, kontaminaci melounovou Kofolou či katastrofálnímu nadbytku čočky,
ignorujte lemma 6.66.
Pokyny:
Každý člen posádky je především povinen řídit se pokyny z lodní telefonní sítě.
S telefony je přísně zakázáno neoprávněně manipulovat či narušovat jejich činnost.
Každý člen posádky je povinen řídit se pokyny velících důstojníků, a to i mimo své domovské oddělení.
Evakuace je zahájena všeobecným poplachem.
Po zahájení evakuace se urychleně připravte opustit loď.
Očekávaná doba na přípravu je PĚT AŽ SEDM MINUT.
Pomalejší členové posádky budou zanecháni na lodi!
S sebou si vemte:
nezbytnou osobní výbavu na 2 až 5 hodin v mezihvězdném prostoru,
vhodný exosuit do slunečního větru, meteorického deště a zimy blízké absolutní nule,
osobní jetpack,
otvírák na konzervy a lžičku,
diplomatickou příručku,
šifrovací pomůcky
kyanidovou tabletku.
Po shromáždění osobní výbavy se urychleně přesuňte k přetlakové komoře.
Zde vám bude vydán skafandr, který si nasaďte před opuštěním lodi.
Po opuštění lodi se přesuňte k nástupnímu prostoru únikového modulu a urychleně do něj nastupte.
Únikový modul má kapacitu DESET osob.
Do únikového modulu vkročte PRAVOU nohou.
Unikový modul odlétá do PATNÁCTI minut od zahájení evakuace a v zájmu záchrany co největší části posádky na nikoho nečeká.
Jakmile budete v bezpečí, řiďte se pokyny pro zjistění stavu lodi a příčiny evakuace.
POKYNY V PŘÍPADĚ KONTAKTU S CIZÍ FORMOU ŽIVOTA
Při komunikaci ujistěte cizí formu života, že sdělené názory jsou vaše vlastní a nereprezentují oficiální stanovisko Hegemonie člověka.
V případě nenalezení společného jazyka využijte Braillovo písmo.
Při konfliktu s formou života na bázi stroje pamatujte, že před kyBorkem neutečete.
POKYNY PRO POUŽÍVÁNÍ TELEKOMUNIKAČNÍCH ZAŘÍZENÍ
Je přísně zakázáno libovolné telekomunikační zařízení vypínat, odpojovat z rozvodné sítě či jinak narušovat jeho činnost!
Dále je zakázáno měnit nastavení libovolného terminálu.
Při problémech se obraťte na vedení posádky či lodního síťaře.
Nenechávejte vyvěšené sluchátko!
V případě vypojení libovolného kabelu z terminálu DBEJTE ZVÝŠENÉ OPATRNOSTI! Terminály jsou netradičně napájeny z datových kabelů napětím 48V.
Je zakázáno olizovat libovolné dráty.
Některé jsou pod napětím.
Navíc jsou ostré.
Terminál může být použit k účelům všeobecné distribuce informace.
POKYNY V PŘÍPADĚ NÁVŠTĚVY EXOPLANETY
Tyto pokyny se vztahují pouze pro návštěvy exoplanet s prokazatelnou přítomností vyšších organismů.
Na exoplanetách s pouze bakteriálním životem či zcela bez biosféry se řiďte předpisy pro návštěvu asteroidů vyjma sekce 3 pokynů pro chování v mikrogravitaci.
Při pohybu na exoplanetách dbejte zvýšené opatrnosti.
Všichni členové posádky jsou povinni pohybovat se ve skupinách nejméně dvou osob.
V případě výskytu inteligentního domorodého života omezte kontakt na minimum, není-li vedením lodi specifikováno jinak.
Je doporučeno zahrnout do výbavy expedice šifrovací pomůcky.
Každá skupina je povinna mít s sebou nejméně jeden měřič ionizujícího záření.

5
hr_join.sh

@ -0,0 +1,5 @@
#!/bin/bash
printf "file '%s'\n" hr/*.wav > hr_concat.txt
ffmpeg -f concat -safe 0 -i hr_concat.txt -c copy sounds/hr.wav

6
list_errors.sh

@ -0,0 +1,6 @@
#!/bin/sh
pass=`sed -n 's/telnet_pass=//p' config.txt`
ip=`sed -n 's/server_ip=//p' config.txt | sed 's/\.[0-9]*$//'`
for i in `cat phones.txt | grep -v backup | grep -v \- | sed -n 's/^\([0-9][0-9]\).*/\1/p'`; do
admin_scripts/list_errors.pl "$ip.$i" "$pass" 2>&1 | sed '/^$/d' | sed "s/^/$i: /"
done

1
list_errors_crontab

@ -0,0 +1 @@
*/10 * * * * cd /opt/ksp; ./list_errors.sh | sed -E 's/172\.16\.0\.//;s/,? ?port 23//;s/ ?at .* line [0-9]*//' > /tmp/error.log.new; mv /tmp/error.log.new /tmp/error.log

54
logo/anytoppm.sh

@ -0,0 +1,54 @@
#!/bin/bash -eu
usage() {
echo >&2 "usage: $0 <input> <output>"
exit 1
}
[[ $# == 2 ]] || usage
FW_INFILE="$1"
FW_OUTFILE="$2"
MIME=`file -b --mime-type "$FW_INFILE"`
case $MIME in
image/gif)
giftopnm "$FW_INFILE" > "$FW_OUTFILE" 2>/dev/null
;;
image/jpeg |\
image/jpg)
jpegtopnm "$FW_INFILE" > "$FW_OUTFILE" 2>/dev/null
;;
image/png)
pngtopnm "$FW_INFILE" > "$FW_OUTFILE" 2>/dev/null
;;
image/x-ms-bmp |\
image/bmp |\
image/x-bmp |\
image/x-bitmap |\
image/x-xbitmap |\
image/x-win-bitmap |\
image/x-windows-bmp |\
image/ms-bmp)
bmptoppm "$FW_INFILE" > "$FW_OUTFILE" 2>/dev/null
;;
*)
echo "Unknown file contents. [$MIME]" >&2
exit 1
;;
esac
MIME2=`file -b --mime-type "$FW_OUTFILE"`
case $MIME2 in
image/x-portable-pixmap |\
image/x-portable-bitmap |\
image/x-portable-greymap)
#temporary file created
;;
*)
echo "Failed to convert file. [$MIME => $MIME2]" >&2
exit 1
;;
esac
exit 0

BIN
logo/hipporion.bmp

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

BIN
logo/hipporion.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 797 B

BIN
logo/hipporion2.bmp

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

BIN
logo/hipporion2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 777 B

BIN
logo/ksp.bmp

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

BIN
logo/logo

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

55
logo/logo.sh

@ -0,0 +1,55 @@
#!/bin/bash
set -eu
CONVERTED_FILE=processed.pnm
FW_INFILE="$1"
TARGET="$2"
./anytoppm.sh "$FW_INFILE" $CONVERTED_FILE || exit 1
#generate logo for the phone
PREVIEW=_preview.png
FW_IDENT=logo_sip
case $FW_IDENT in
logo_sip)
# BMP 90x56 (8-bit), phone can display 4 colors
{ cat $CONVERTED_FILE | pnmscale -width 90 -height 56 | ppmquant 4 | ./ppmfix.sh | ppmtobmp -bpp=8 > $TARGET; } 2>/dev/null
#generate logo preview for Operator's Administration
{ cat $TARGET | bmptopnm | ./ppmfix.sh | pnmtopng > $PREVIEW; } 2>/dev/null
;;
logo_sep_bw)
# PNG 320x196 (8-bit), phone can display a 4 color PNG file
{ cat $CONVERTED_FILE | pnmscale -width 320 -height 196 | ppmquant 4 | ./ppmfix.sh | pnmtopng > $TARGET; } 2>/dev/null
# BMP 80x49 (8-bit), phone can display a 4 color PNG file
{ cat $CONVERTED_FILE | pnmscale -width 80 -height 49 | ppmquant 4 | ./ppmfix.sh | pnmtopng > $TARGET_TN; } 2>/dev/null
#generate logo preview for Operator's Administration
cp $TARGET $PREVIEW
;;
logo_sep_color)
# PNG 320x212 (12-bit)
{ cat $CONVERTED_FILE | pnmscale -width 320 -height 212 | ppmquant 4096 | ./ppmfix.sh | pnmtopng > $TARGET; } 2>/dev/null
# PNG 80x53 (12-bit)
{ cat $CONVERTED_FILE | pnmscale -width 80 -height 53 | ppmquant 4096 | ./ppmfix.sh | pnmtopng > $TARGET_TN; } 2>/dev/null
#generate logo preview for Operator's Administration
cp $TARGET $PREVIEW
;;
logo_sep_color_16)
# PNG 320x212 (16-bit)
{ cat $CONVERTED_FILE | pnmscale -width 320 -height 212 | ppmquant 65536 | ./ppmfix.sh | pnmtopng > $TARGET; } 2>/dev/null
# PNG 80x53 (16-bit)
{ cat $CONVERTED_FILE | pnmscale -width 80 -height 53 | ppmquant 65536 | ./ppmfix.sh | pnmtopng > $TARGET_TN; } 2>/dev/null
#generate logo preview for Operator's Administration
cp $TARGET $PREVIEW
;;
*)
echo "Unknown logo ident. [$FW_IDENT]" >&2
exit 1
;;
esac

21
logo/ppmfix.sh

@ -0,0 +1,21 @@
#!/usr/bin/gawk -f
BEGIN {
fix = 0
}
NR == 3 && /^0$/ {
fix = 1
print "1"
next
}
fix == 0 {
print
next
}
fix == 1 {
gsub(/\x00/, "\x01", $0)
print $0
}

58
message_receiver.pl

@ -0,0 +1,58 @@
#!/usr/bin/perl
use strict;
use warnings;
use DBI;
use Encode;
use Net::SIP;
use Net::SIP::Util qw(sip_hdrval2parts sip_uri2parts);
my $addr = $ARGV[0];
my $port = $ARGV[1];
my $dbfile = $ARGV[2];
die "Usage: $0 listen_address listen_port database_file\n" unless $addr and $port and $dbfile;
my $dbh = DBI->connect("DBI:SQLite:$dbfile", undef, undef, { PrintError => 0, RaiseError => 1, sqlite_unicode => 1 });
my $leg = Net::SIP::Leg->new(proto => 'udp', addr => $addr, port => $port) or die "Error: Cannot create leg: $!\n";
my $ua = Net::SIP::Simple->new(from => '', leg => $leg) or die "Error: Cannot create user agent: $!\n";
$dbh->do('CREATE TABLE IF NOT EXISTS messages(id INTEGER PRIMARY KEY AUTOINCREMENT, r INT NOT NULL DEFAULT 0, f TEXT NOT NULL, t TEXT NOT NULL, m TEXT NOT NULL)');
$dbh->do('CREATE INDEX IF NOT EXISTS idx ON messages(r, t)');
$ua->{endpoint}->set_application(sub {
my ($endpoint, $ctx, $packet, $leg, $from_addr) = @_;
return unless $packet->is_request;
my $resp;
if ($packet->method eq 'MESSAGE') {
my (undef, $for, undef, $message) = $packet->as_parts;
$message = decode('UTF-8', $message);
my $for_user = (sip_uri2parts($for))[1];
my ($from) = $packet->get_header('from');
($from) = sip_hdrval2parts(from => $from);
print "Recevied message for user $for_user from uri: $from\n";
my $success = eval { $dbh->do('INSERT INTO messages(f, t, m) VALUES(?, ?, ?)', undef, $from, $for_user, $message) };
if ($success) {
$resp = $packet->create_response('200', 'OK');
} else {
$resp = $packet->create_response('500', $dbh->errstr);
}
} elsif ($packet->method eq 'OPTIONS') {
$resp = $packet->create_response('200', 'OK');
} else {
$resp = $packet->create_response('606', 'Not Acceptable');
}
$resp->set_header('Allow' => 'OPTIONS, MESSAGE');
$endpoint->new_response($ctx, $resp, $leg, $from_addr);
$endpoint->close_context($ctx);
});
$ua->loop();

4
message_receiver.service

@ -0,0 +1,4 @@
[Service]
ExecStart=/usr/bin/perl /opt/ksp/message_receiver.pl 172.16.0.1 5062 /tmp/messages.db
[Install]
WantedBy=multi-user.target

12
normalize_volume_all.sh

@ -0,0 +1,12 @@
#!/bin/bash
vol=9
cd /opt/ksp
. config.txt
ip_prefix=${server_ip%.*}
./hangup_all.sh
sleep 1
cat phones.txt | awk '{print $1}' | grep '^[2-5]' | xargs -i -n1 -P0 ./admin_scripts/normalize_volume.pl "$ip_prefix.{}" "$telnet_pass" "$vol"

40
phones.txt

@ -0,0 +1,40 @@
# LINE MAC ALIAS NAME
# org
21 00:0c:85:b9:8d:72 org1 Org 1
22 00:0a:41:9e:70:4c org2 Org 2
23 00:1d:a2:66:e1:1b org3 Org 3
24 00:1e:be:90:7a:1a org4 Org 4
25 - lodni_kocka Lodní kočka # Medvěd
# non-org
31 00:0a:8a:2c:8c:d2 prechod_komora Přechodová komora # botnik
32 00:0c:85:b9:8d:47 kontam_komora_0 Kontaminační komora 0 # wc přízemí
33 00:1b:d4:60:6e:3f lodni_kaple_1 Lodní kaple 1 # jedalen1
34 00:1d:a2:66:e1:0b lodni_kaple_2 Lodní kaple 2 # jedalen2
35 00:0c:85:b9:8d:57 unikovy_vychod Únikový východ # chodba
36 00:0a:41:f9:77:32 xenobio_lab_1 Xenobiologická laboratoř 1 # jedalen1 mala
37 00:1e:f7:c2:28:66 xenobio_lab_2 Xenobiologická laboratoř 2 # jedalen2 mala
38 00:0c:85:b9:8d:50 odd_inkub_techn Oddělení inkubačních techn. # izba 6.c
39 00:0c:85:b9:8a:63 odd_appl_noem Oddělení aplikované noematiky # izba 5
40 00:17:0e:c8:52:bf chodba_0 Chodba 0 # chodba
41 00:1d:a2:66:e0:cc odd_rela_efekt Oddělení relat. efektů # izba 4
42 00:1b:d4:5f:f3:33 odd_auto_agrik Oddělení autonomní agrikultury # izba 3
43 00:0c:85:3b:ba:84 dekontam_sprcha Dekontaminační sprcha # sprchy
44 00:0c:85:b9:8d:5e kontam_komora_1 Kontaminační komora 1 # wc 1. patro
45 00:0a:8a:2c:8d:73 odd_civil_vycvik Oddělení civilizačního výcviku # izba 7
46 00:1e:be:90:79:ea odd_psycho Oddělení psychoakustiky # izba 8
47 00:0a:8a:21:57:38 serverovna Serverovna # switch
48 00:0c:85:48:c9:c3 sklad_nebez_odpad Sklad nebezpečného odpadu # schody
49 00:0c:85:8d:18:2d chodba_1 Chodba 1 # chodba
50 00:17:0e:c8:50:d2 odd_abstr_umeni Oddělení abstraktního umění # izba 1
51 00:0c:85:8d:16:13 odd_dezinfo Oddělení dezinformace # izba 2
56 00:0a:8a:21:51:bc backup1 backup1
57 00:0a:8a:66:49:8e backup2 backup2
58 00:0a:8a:2c:8d:0b backup3 backup3
59 00:0a:41:f9:79:2a backup4 backup4
# dead
#00:0a:8a:2c:8f:f1
#00:0a:8a:2c:8d:74

20
pocasi.py

@ -0,0 +1,20 @@
#!/usr/bin/python3
import xml.etree.ElementTree as ET
from datetime import datetime as dt
from urllib import request
xml = request.urlopen('https://www.yr.no/place/Czech_Republic/Olomouc/Ruda_nad_Moravou/forecast.xml').read()
root = ET.fromstring(xml)
days = ['Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa', 'Su']
for time in root.iter('time'):
attrib = time.attrib
time_from = dt.strptime(attrib['from'], '%Y-%m-%dT%H:%M:%S')
time_to = dt.strptime(attrib['to'], '%Y-%m-%dT%H:%M:%S')
style = time.find('symbol').attrib
temperature = time.find('temperature').attrib
preci = time.find('precipitation')
output = days[time_from.weekday()] + time_from.strftime(' %H') + '-' + time_to.strftime("%Hh") + ': ' + temperature['value'] + '°C' + ', ' + style['name']
print(output.replace('Partly', 'Pt.'))

7
rand_line.sh

@ -0,0 +1,7 @@
#!/bin/bash
cd "$(dirname "$0")"
myself="$1"
[[ -n "$myself" ]] || myself=xxx
cat phones.txt | grep -E '^[3-5]' | cut -d' ' -f1 | grep -vFx "$myself" | sort -R | head -n 1

BIN
sounds/heslo.wav

Binary file not shown.

BIN
sounds/klapka.wav

Binary file not shown.

BIN
sounds/spatne_heslo.wav

Binary file not shown.

17
tftp/Dialplan.xml

@ -0,0 +1,17 @@
<DIALTEMPLATE>
<TEMPLATE MATCH="2." TIMEOUT="0"/>
<TEMPLATE MATCH="3." TIMEOUT="0"/>
<TEMPLATE MATCH="40" TIMEOUT="0"/>
<TEMPLATE MATCH="41" TIMEOUT="0"/>
<TEMPLATE MATCH="42" TIMEOUT="0"/>
<TEMPLATE MATCH="43" TIMEOUT="0"/>
<TEMPLATE MATCH="4445" TIMEOUT="0"/>
<TEMPLATE MATCH="45" TIMEOUT="0"/>
<TEMPLATE MATCH="46" TIMEOUT="0"/>
<TEMPLATE MATCH="47" TIMEOUT="0"/>
<TEMPLATE MATCH="48" TIMEOUT="0"/>
<TEMPLATE MATCH="49" TIMEOUT="0"/>
<TEMPLATE MATCH="5." TIMEOUT="0"/>
<TEMPLATE MATCH="8888" TIMEOUT="0"/>
<TEMPLATE MATCH="*" TIMEOUT="9999"/>
</DIALTEMPLATE>

9
tftp/RingTones/Piano.pcm

@ -0,0 +1,9 @@
џџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџ________џ________________џџџџџ___________JR__пR!'8ЛЪ­���ЁЂЏЇЪ5 J�������В­-!-",>ЪОЄ8ЄЪ��DЊ8Џ�,*џЪ_ JJ8����;Ъ$���2"�Л5Љ�������  2�����Њ/->J*ЁФ'ЌЕ����Њ2ЌЉ> *Ќ�)���ЁЌR )��Ї,*_в-Џ�­Љ-ЕЄ����п$ ВЇФJ"пЊ�ОЏЪ"�ЅЌџ И��­����в2Ф  �����ЊЏ,$" )->8Џ�Ъ8вJ��--ЕЉВО2/RИDФ5J����Ъ"%'2­Ќ��ФФв%'Є*5���ЁЌвФ!
/ЪЁЅ����RФЕ/*Ъ8*!Ё��­в���пЪ/в������Ф8 _Є��Ъ8_2Л�ЏJЅJ>���5Ъ$)ЂЂ�ЇЕ-ЪЄ�,DЁЄЕ;/ *_Е������ЌЛ  Л�����ЄЇЛЛ8%,$ !JџОЄ��вЅ�ЊпJ!5 RО'Ъ����џ5*$>���ЇЪп>'R_>ЄЅ���Ђ!%" 8ФФ_Фв����ЛВИЊ�R''�������ЉЌп  D�����ЄИD2')-ВВD;ФЅ�ВJ�ЏИ_)'Фп,$*����ЪJ5в����ФвJ)_$/Є�����*% )_џпЕВ��Ђ�ОИЛЕЅJ''�������ЉЌп  D�����ЂЛ>-%-%DЂЊ>2џЊ�Њ/ВЏ­џ%);Е_>$Њ���ЛвR5­�Ё��ИФџџ,$Є�����п$%
)2В����ЌЊвRЪ$;8-" '����Ђ���вD> /������Ђ_2Љ��ЄЕJ!8ИЏ*$џЪЛ";Њ�ЇJJ5->8ЇЉЛ_*8Е�ЂВВ��ЌЪ 8J������ЁФ% 
 Џ�����Њ_Jџ$%%_Rв���Ѕ��ЄЛџ/$ 5_2џџЄ����ИDJЂ��ЄИФ>"*J5"/_п����В),2%5Фџвв��Ї��ФDЛОЛR
R��������ЕDџ������Є-5"!DD­ЉџRR�ЁЛВЏЏЌD$%$!,Ев8,ЏЁ�ЊЇ­J*-ОЇЂ��ЏВR,ФЅ�����О5* *ИЄ����ЇЕВџ2"_5 $��������ФЛ2 8О������;*"*Џ���В;*џВ5RRJЛ5,RЌЇЏЏОR/*"JЪRЛD-%>ЏЄ�ЊЕЄ�­2)пЄ������Џ$ ОЄ����ЇЊЕJ,!5%%-'ВЂЊЅ��Ё�ЪФп*,2вв>Љ��Ё�ВJ-,Ф��ЂЕЏ2'");,,JФЌ���­RвR'$>5-5ЛЏЏЉ�ЁЏЕОЛВJ*2'пЁ�����ЄЌ>/Є�����ЏЪ5,,!//R­­ЛвФВВИџпФп;'2,)вЕ­Ъ8;ОЕппОЏD)2ЪИЉ�ЅЊ­Ф'$'%;ОЂ����О_J*%$;в���ЄЅЌЕЪ-8;5/!,ИЄЂЁ���ЌФЪ;%!,ЛЊЂЅЂ�Єп>;5'/џВ�ЅЕ_8џ>85JпJ;5RФЕЌЏЕЕв;-,2;>8J52DЪЄЉЏВ­ЏИ_/''DЕ����ЄЅО;%),5вЉ���ЇЏЕв-)5--)*//DЪЛОИЏЌЌОввџ;)"'8пџJRвЕОЕВИОD-*)';ОЉЁЉЏИJ2*$/228D_Ъ­ЄЁЏФООџ,!%-)$8пО­ЌЉЉЛЛФвџDD>*)_ВЂЁЅЇЊ­ЛJ5-*%!2ЪВЌЄЁЂЊФR>5-$'/5_ИООвџвЛФЪФОЪ>;;-8RЛЕЪD;џ_5DЪОв>;>JвФОЕВЛЕп/-,*,,;JФЌЉЉЇЊЛЪп>;,"!$)*JЕЅЂЇЉВИв55>;;5,*,5JвЛВВЊЊЪвпJ5,/5;>JпФФвЛВОпJ;2,*'5џИЌЏВФвп;;DDD;5-2;_ЪОЕЕЏЏпџџJ8258;;DџЪЪпЛЏИЪџR;/,'/DвВЕИппџDDJRRD>2;RпФОИИЛв>8;88>___пФЕЕЛпЪФџR>82*,-;RвВЊЊЛИИвJ8RR;,)-28пВЅЊЏ­ЛЪ>25588D>JJџЪпЪФпЪџR_RJ;5;џФвЪ_ЪЪ_ппФв_RDD55JЪВЕИЛпJ52888;џџпЪОВЪџпв_8-2822DџОЕВЊ­ЕвJJ;>;>D882;RЪИЏЌВЛЪ_R>5;;;,,5JпвИЏЌЏЪпџ>/-28>DпИОЪџџЪDDR_JDJ_џRпИВИ_Rџ;//8JR_Jџ>%-8ЛВВЂ��ВЕпФЪ2-;ФJЏЁ��Џ8*58пЌОпЊ���Ќ/)_RJ)ЏЇ�����­$  '%��Ђ����џ''*)RR2п/$џ���­­��Ќ%!%џЕ��Ё�ЇЊЊ!%-*"ЕЏИЉDJ5_�ЇЏ_5ЉЊ*">Џ­Њ"!-%58ВЇвЕЊв'џФЅЊ%ИИR);п-п_ВЉ��Џ>5>;!*2Ђ����ЕОJЪJ,*џ,!5џпВ_ЪЏппОЌ_-52,/ЏЊ;8О�ЂЏЁЪ2*'J2"J��Ѕ_DЛ;%)џJ)DОЕЏ��­Ъ$">*'D_пЪЛФ��Ѕ�J/ИИФ*!_�������ЪD-Ё�����Єџ)8'')!Џ�ЉИ*RЂЉRJОџИD*)*џЪФЛ5/ФЉЇЌЌЪЪ;)џФ­ЂЏОФВD2'>)/Є���ЏЏЛ8'",5J����Ъ­Џ_,>п"!п��ЏЁ���Ќџ''*­�Ђ����ЅD)/$!џпЇЅџп;,RЊЪD_ИЌ_'DвЁИ%2;,'Rџ;џJЪџ"8Л��ОВ�Ќвп,8Ф�����ЉЉВ"/И����ЇЌЏЅR"5,%'>DОЌЂ�Љ��ЊЛ--*џЪвпВ�Ђ��ЏJ)%,*Љ��ЇвЛџ-%$*--)DпЪЉЁ�Љ8)58-*_;5RRЌЄ��ЏЛИЅВв)'Ф������ЁЌО*,Ђ�����ЄЛв8!%")ИЄФRџФ�ЉВЌЕ­J$"%)пџџR8ЊЂЇЌЪИD"%>ЇЂ��ООЕ>%%)И�����Е>2)!"/пЂ����ВИЛФR;2Л�������ИRD ;Љ������И;/!!JЕЉЇЇЪ>RЕЕ>џпИФ*'_ВОвJJ>/пп_вџRџ)!,џЕЌЊ­ЂЉЇФ5,,­������ЊR-Њ�����ЊЉВ>/5/%)*>ЕЌЇЅ���ЊпR,)DФЛЉ���ЄО;'JЏ��ЄЊ­И;$"%!!);ЏЅ���ЏЪЛп2)*2,"!8>п­ЉЊЉ���ВJ;% )RВЉ�����ВJ,,џЅ�ЅЌВЛ>,,/2*5>RИЉ��Їџ>џ>*$"8;5/5ЪЕЏЇЄЏВЉЉ­п-) DЊ������ЁФ' %И������­О82)"")џОФџџ­ЄЉЉЊЌЛD)"'JпЪJџВЉ­ВЕОв"'RВЉ�ЄЌЊЕJ!'8вЂ����Ќв_5%,DЏ���ЄЉЊЉЛџп2*;ЕЅ�����­ЕR%)џЇ�����Ќв;-$"8џЕЊЌЪ>џЪRџџОФD-/џвЪФЪвџпRDRRJD>2)5DЛЅЊЌЉЄЌФR/!/вЂ�����Їџ-"'>Л����ЁЉ­Ъ88/$!$$JИЕЊ����ЏЛп5%;џџИЅЉЇЂЏОJ*$!"*JИЉЏЕЌп;>-/;5;RRџЛЉЂ­пФпJ>')2/%*>џЛВЉЅЉЊЌЏЕ_55*/вЊ����ЄЉО2'"*пВЅ���ЁЌОџ;/%!)_ЪЪФЛЏЉЌЌ­Лп>,-$-DФЛввЕЕОвпЪD*%)/RО­ЇЌВ­И>*"%'");вВЅЁ��­ЛвD8)!!!%2ЪЉЄЄЄЇЇЌЛпJ5,%!5ЪЕЇ���Ђ­Иџ/!/џИ­ЌЇ�Ё­ЪR>-$!'/>ЪЕЕЪџпЪџJпЪвD28J_вввОФФЪџJD;;>2/5JОВВ­Ќ­ЏО_;)*RЏЄЄЄЁЁЇИJ;8)",JЏЅЄЅЉЉ­Ъ_J8/)),,-8RпОВЇЄЌЕЛвJ-$$*8JџпФИИВЏИОR8/,,/>пЛЕВЕФ_>58;>>JJJвЛЕИФФЛОџ>882*,8DпЪИЏВЏВЕОп_J5%"*;Ъ­ЇЄЄЄЉЕвD8,%"'/DвЕЉЂЂЉВФ_D-*,*5DJ__пЪОЛОЛФЪ_JD528Dџпџ_вв_џпЪпJD>>J_вФООВЛпJ58-,2;RџЪЛВВЛОФпџD5-*,*2DЪЕЏЊЌЌВФпR>2/,))->џОВЏЊ­ЛФп_;///2/2>пЪФЕЏВЛвв_>5-88>пОИЪЪЪпRDDJJD>RR_џвЛЛИФџ_D>88>>DDRпФФФЛОФЪ_J8---22>пЛВЕ­ВИвRJD;-*-/5DЪЏ­Ќ­ЏЕџD;522558;RвЪЛООИФвп_RD;28>DRRЪЪвЪЪФвџJJD55;,'2JЕЕВЊ�ЉИЛЪЕЪ>-'5JЉ����­ЕЛФR/DJRџ,"DФВD-Ќ�R��Е�ЕЪ;$-пЁЁЪ%>%!2�����* >Љ����ВЛ52��")п���ЊD;Ђ�� $;�Є���Ќ_D2),�Љ­ИЪD%JИ/5�Ё58R;вЇD)"п�ЂJЌЁЉ,,"-Љ����) 2���Є��ЇИ$;/ ОЊ!8Љ��ЇЛ;Њ��в28����ИЕ->ЏЌ­�Ќ)>)ЊЂ"2��вJ/,5/2Џп)2��ФвЏ>%'Ъ_���/*% $џ���Ѕ��ЊИ%-,!ЏЌ''в­­�ЌDЅ��Ѕ;"
����Є�Џ­ЪЄ_ОЕЕО)ЛЌв/Л�Ђџ*$)DФ'$Ї���­J,Є��ЂИЌ_>DЁЇЊ���Ђ)*8Ъ/2D_вО�ОЪ���Џ) Џ�������џ) 2R,25­�ЪФЊФ8Ќ�ЅФ%"5В*"J���Є>,)Ф���Џ>8п''-%ЪЉВВВ��Ъ->*/џ8*%5%џ������Ѕ/
2����ЂЊ�_5/2_J$­ЄЕОЛОЪЏ��ЅJJ>/И����;5,Ъ���ЊD2%!*$ФЇ�ЂВ��Ф!%!!/;ЕЕ285'!ЛЅЊЅ���Ї**  Ф������­О' ,2,/Ъ��ЉЏОRЪЌЁ�И$*_D����ЌЛDЏ���_Л>-D>*"J­ФџЊ��џ;D2/ЪОФ-"*RЕ�����Ё;2 5�����ЁЄЪ2$ *2,Љ�ЁЂ­ЏвЕ��Њ* $>в����ЂЅО"���ЊЪпR;Jџ!)>ЪЅЕ;ФЏ8D-'%-О��­_-,ЛЕ����Ќп> 2������Џ;"!%88*Ъ��ЇЉЏRпЅ��Ъ! 2Џ�����ЇЪ- 'Ѕ��ЌЅЕОЕЛ;''8ВЕ>;п_џRџ*>Џ�Ёџ>,%џЛЉЂ��ЇвR'_������п-2!)>!/ЛЊЄЇЅ­ОЇ��Љ5
$И�����ЅИ5$в��ЉЇЇО_ЛФ,,5И�џ)-8/5џ>,5И��ЄЪ/""5пЕ���ЂОRв�����В2,'%пJ/DИИОЇ­ФЕЊ��Џ8$ ,в�����Є­5ИЁЌЂ�ЄОФЪ8,%JЂ­D*88-Rџ--DЇ��ЌџD"%-5Ф���­џ;'"$)Е����Ђ_8;'$_в;5_п_ФЌЇ­ЛЇ�Ёп'*">В����ЄЊџ)5ЕЌЊЅ�ЌЪИR5,/ЏЅФ**)%8DJ_>Е���в;)$)>Ќ��ЁИФ5"$!%"/Ї����В855*5И­RJв88пИЌФФЄ�Њџ5"*JЄ�����Ќ;'8ФЕЇ��ЇЌв_8,_ЛИ;%*)%/DRD_­��ВџD/'!'$;Ї��ЊОФ;)'))8ЊЂЂ�ЄЛ_;5,;ОЛJDD8;ЪВВФЛЇ�ЏJ/!*JЄ����ЂВ8$;ФИЇ�ЁЉЏп_5-_ЛЛ8%,)'-D_DџЌ��ИџJ2*")$;Є��ЌОФD,*-,!DЊЅЇЁЅОФJ8-%DОвJD58JЛЌИЛВЉЂИ>-!-_Є����ЇФ5!%RЛИЇ�Ђ­Фџ_52_Вв82,)',Jџ_Е��ЂО_D/$",ЪЄ�Є­И_;2*-%$5Ф­ЉЇЉВО_>2%%*пЕФвD58RФЕЪвЏЄЉЪ>-)!,5џЌ��ЂЂЌЪ8')%-J_ЛЉЄЇИЪФR>>џЪ_;2-)-;JRЪЌ�ЂВФџJ5'$$"/ЪЊЅЌЏИОп>8,)*>ОФЪИВВвJD5*)JЕВО_>;5Jв_RФЌЂ­вD2)!$**2џЉ��ЁЊИп22)"")8DџЕЌЌЛФОпRDRФФпJ8-''2;RИЇЁЅВФв_/*,*,5Ф­ВИОИИ_>5-,2џвпЪОВОпџD5-;ЪИОџD;/5JR_Ъ­ЅЉЕвD5,,5/,2вЌЉЅ­ВЛJ;2*%'5JџЪОВЛЪпвп>DпЪЪ_D;/)-DџФВЉЉ­Ив_8,-,*,JОЛВИЕЕпJ5-*-JџџвФЕИОвпJ2;вФФвџ_J8;JJ_ЪЏЏИЪJ>5/585->ФИЌВЕИвR82,*2>џЪОЕИЛФЪвDD_пввџR>-*5DџОЌЌ­ЕФџ>/-/-*2RвЛЛЕЏЛв8,ФОЇ����Ѕ­ЊJ/D*JЊ��ЄВ';'*'Л�ЅЉ����ЁJЏ*  )-Џ�����2;>RRИЌ��­ФD�ЄЉ��Е  R�������D2% R��Ќ),2ЊRв'D���ЇЄD>>пЂВ8%)��J-О�џJО8Ѕ�Ќ2 2���Ъ����J,J  $����ЇЕ�ИR5!-%;џЏ�О,ОЕ�Ѕ"JО,%$ЪИ�;8)_���Ќ8),2Њ�Є����в>/)����Е�Ї* ,Љ�����Ќ>_ЁRJD­О$/���DJ���Ѕ-)'8В�����Љ>)���Є%"DDпЌОвЉЕп�Ё­,Ї22��ЂО)!-ЊЁЄ*J��ЂR5 )Л�������Ф,  Њ���ЅВЊЛвJD)R5$'вЌЊ>��ЂФЉ�Л*, %ЛЕ$Љ����_5"-���ЊЊЅФR2,;5$����ЉЌ)*/* >Џџ/пО��џп__ИЄ�Ъ5"%��пЉ�����Ъ- 
Л������Џ_$R_Љ�О)$DЛЄВ)В�ЉФ,>_вR;'*%����в2*вЁЇЄ��ЄЛ_*"����ЏЅп%*;ЪЪ���В5впЛЕ_ВЌ/џ��Ќ­Ё��ЁЪ)8 $>_Ђ����ЂО-Џ���Фџ,,8ФЛ$)RОџ2D��Ќ5D58Ъ_ЄЊ>2"!JЂЇИвФ��ЅЪ ,JЂ���Ё��О- -�����Љпп52/D8'$/ЇвDЌИЪRЏ�ЂЊФR-пФ)>Ъ����­Ф$ Е����ИО;$)!)ОЄ����_$%>)*ЪЇпRФЉЏвЕО_5Љ�ЉЌ/! в�Ї������п2 /Ѕ�����ЇФ)*')RЏИЌЌ-8DЌЊ>О­ЊИ2$8,пЏв,)DЂЁЅЕИџ$>JЪЁЄ��­ИR*О�����Ђ_>)%$>Є����ЏООD2)-Ов%8�ЄЏИ����ФВ2 RЉ�����Є/%'п����в/%5J!%;JЛппВ�ЂОЪ5,$!',­ЊОФ5)8В­ЉЛЕ��ЅJ2 п������ЂJ -�����ЕџФв,*!5Ф2$")-*ЛЊОВЅЂЁ�ЕвD>DЪJ_Ё��ЊЊп*"%_Ё��ЊИЪ-*%%,!)пЊЇ���Ъ>пJп8/JЏЊЌ��ЊввпФ­J2- 5Ф������ЂЊ8 џ������пD-"%_вИ�ЏJ8ФФ_R>ИЅ­п5>,'ФВJ*$/­�­­ЉИ,!)џЕЂ��ЄЏџ%п������џ**-RЛЇ��ЄвОФ_J)RВЪ;$-ЕЇЌЅ���ЄЛФ2!$2Ї���Ё�И-/8*!вЅ��ВR-,JD5;JЪвФJ_ВЕИЪвџ8!"8пЪJ>п5-вЌ�ЏџВЇЊЪ8)*JЅ����ЁЇD"!%)*ЛЂ���ЉВВџ>!-/222;>пЛИЛОФЪЕЏВЕџ/%JО8->ИЅ­ВЊЕџ8*)$/­Ё�Ї­Л5)'%*)'2ЪВЉ��ЅЪ>>8),J_;ОЏЏЊЏЕЕ_DџвОФџD'%ЪВЉ����ЇИ>)""‽Є��ЏФ;DJ,'%8џпЕЏп;>>_џ>JОЕИ_RD-DЪЕО>/5ФФRвЛв;2/;_пФЛЊЊИЛR'*%'*,/DЏ��ЄЅЏ_J;2/%$/25ОЄЁЇВЕЛО_28џR85'$-8џЛЛЕЛЊЊОЛИџ2*),2,,DвФОЉЅ­ОЪЪ_5)!8ЪЛЕЛпJD;;5;DRОЛпЕЏЛФппJ5%!,;JџОЕФОИЕЛпDDФИЪп>>5))'-DЪЌЁЄЌЊЏп8-8/$!5џЪ­ЅЅЕФвJ>//;__Rџџџџ_пџвЪвФФпв_D2,8пФЪџJппJRJпRD_RџJRФВЏЪв_;-,;__RRОЛФИВЕџJпџ>%%-855_ЪЕЕ­Љ­О_DJ>DD>;/28RпФВЏЊВЛФJD55;52,/JвФОИВВЛR__>//;>_пОВФпRџ_25RџџџџџпRпЕОџ88D58DџЪвџ_џџJR_ппввџRџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџ

230
tftp/SIPDefault.cnf

@ -0,0 +1,230 @@
# SIP Default Generic Configuration File
# Image Version
image_version: P0S3-8-12-00
# Proxy Server (Can be dotted IP or FQDN)
proxy1_address: ""
proxy2_address: ""
proxy3_address: ""
proxy4_address: ""
proxy5_address: ""
proxy6_address: ""
# Proxy Server Port (default - 5060)
proxy1_port: ""
proxy2_port: ""
proxy3_port: ""
proxy4_port: ""
proxy5_port: ""
proxy6_port: ""
# Proxy Registration (0-disable (default), 1-enable)
proxy_register: 0
# Phone Registration Expiration [1-3932100 sec] (Default - 3600)
timer_register_expires: 3600
# Codec for media stream (g711ulaw (default), g711alaw, g729a)
preferred_codec: g711alaw
# Inband DTMF Settings (0-disable, 1-enable (default))
dtmf_inband: 0
# Out of band DTMF Settings (none-disable, avt-avt enable (default), avt_always-always avt)
dtmf_outofband: avt
# DTMF dB Level Settings (1-6dB down, 2-3db down, 3-nominal (default), 4-3db up, 5-6dB up)
dtmf_db_level: 3
# SIP Timers
timer_t1: 500; Default 500 msec
timer_t2: 4000; Default 4 sec
sip_retx: 10; Default 10
sip_invite_retx: 6; Default 6
timer_invite_expires: 180; Default 180 sec
####### New Parameters added in Release 2.0 #######
# Dialplan template (.xml format file relative to the TFTP root directory)
dial_template: Dialplan
# TFTP Phone Specific Configuration File Directory
tftp_cfg_dir: Phones/; Example: ./sip_phone/
# Time Server (There are multiple values and configurations refer to Admin Guide for Specifics)
sntp_server: ""; SNTP Server IP Address
sntp_mode: unicast; anycast (default), unicast, multicast, or directedbroadcast
time_zone: CET; Time Zone Phone is in
dst_offset: 1; Offset from Phone's time when DST is in effect
dst_start_month: April; Month in which DST starts
dst_start_day: ""; Day of month in which DST starts
dst_start_day_of_week: Sun; Day of week in which DST starts
dst_start_week_of_month: 1; Week of month in which DST starts
dst_start_time: 02; Time of day in which DST starts
dst_stop_month: Oct; Month in which DST stops
dst_stop_day: ""; Day of month in which DST stops
dst_stop_day_of_week: Sunday; Day of week in which DST stops
dst_stop_week_of_month: 8; Week of month in which DST stops 8=last week of month
dst_stop_time: 2; Time of day in which DST stops
dst_auto_adjust: 1; Enable(1-Default)/Disable(0) DST automatic adjustment
time_format_24hr: 1; Enable(1 - 24Hr Default)/Disable(0 - 12Hr)
# Do Not Disturb Control (0-off (default), 1-on, 2-off with no user control, 3-on with no user control)
dnd_control: 2
# Caller ID Blocking (0-disabled, 1-enabled, 2-disabled no user control, 3-enabled no user control)
callerid_blocking: 0; (Default is 0 - disabled and sending all calls as anonymous)
# Anonymous Call Blocking (0-disabled, 1-enabled, 2-disabled no user control, 3-enabled no user control)
anonymous_call_block: 0; (Default is 0 - disabled and blocking of anonymous calls)
# DTMF AVT Payload (Dynamic payload range for AVT tones - 96-127)
dtmf_avt_payload: 101; Default 101
# Sync value of the phone used for remote reset
# Value against which to compare the value in the syncinfo.xml file before a remote reboot is performed
sync: 1; Default 1
####### New Parameters added in Release 2.1 #######
# Backup Proxy Support
proxy_backup: 0.0.0.0; Dotted IP of Backup Proxy
proxy_backup_port: ""; Backup Proxy port (default is 5060)
# Emergency Proxy Support
proxy_emergency: 0.0.0.0; Dotted IP of Emergency Proxy
proxy_emergency_port: ""; Emergency Proxy port (default is 5060)
# Configurable VAD option (voice activation detection)
enable_vad: 0; VAD setting 0-disable (Default), 1-enable
####### New Parameters added in Release 2.2 ######
# NAT/Firewall Traversal
nat_enable: 1; 0-Disabled (default), 1-Enabled
nat_address: ""; WAN IP address of NAT box (dotted IP or DNS A record only)
voip_control_port: 5060; UDP port used for SIP messages (default - 5060)
start_media_port: 16384; Start RTP range for media (default - 16384)
end_media_port: 32766; End RTP range for media (default - 32766)
nat_received_processing: 1; 0-Disabled (default), 1-Enabled
# Outbound Proxy Support
outbound_proxy: ""; restricted to dotted IP or DNS A record only
outbound_proxy_port: ""; default is 5060
####### New Parameter added in Release 3.0 #######
# Allow for the bridge on a 3way call to join remaining parties upon hangup
cnf_join_enable: 1; 0-Disabled, 1-Enabled (default)
####### New Parameters added in Release 3.1 #######
# Allow Transfer to be completed while target phone is still ringing
semi_attended_transfer: 1; 0-Disabled, 1-Enabled (default)
# Telnet Level (enable or disable the ability to Telnet into the phone)
telnet_level: 2; 0-Disabled (default), 1-Enabled, 2-Privileged
####### New Parameters added in Release 4.0 #######
# XML URLs
services_url: ""; URL for external Phone Services
directory_url: ""; URL for external Directory location
logo_url: ""; URL for branding logo to be used on phone display
# HTTP Proxy Support
http_proxy_addr: ""; Address of HTTP Proxy server
http_proxy_port: ""; Port of HTTP Proxy Server (80-default)
# Dynamic DNS/TFTP Support
dyn_dns_addr_1: ""; restricted to dotted IP
dyn_dns_addr_2: ""; restricted to dotted IP
dyn_tftp_addr: ""; restricted to dotted IP
# Remote Party ID
remote_party_id: 0; 0-Disabled (default), 1-Enabled
####### New Parameters added in Release 4.4 #######
# Call Hold Ringback (0-off, 1-on, 2-off with no user control, 3-on with no user control)
call_hold_ringback: 0; Default 0 (Call Hold Ringback feature is off)
####### New Parameters added in Release 6.0 #######
# Dialtone Stutter for MWI
stutter_msg_waiting: 1; 0-Disabled (default), 1-Enabled
# RTP Call Statistics (SIP BYE/200 OK message exchange)
call_stats: 1; 0-Disabled (default), 1-Enabled
####### Other parameters #######
date_format: D/M/Y; Default is M/D/Y
dscpForAudio: 184; Differentiated Services Code Point (DSCP) specifies the class of service for each audio packet
garp_enable: 0; Gratuitous ARP
language: english; English is the only value that is currently supported
local_cfwd_enable: 1; Whether the phone can do local call forwarding
messages_uri: ""; Configures the voice-mail number that is dialed when the messages button is pressed
network_media_type: Auto; Auto (default), Full100, Half100, Full10, Half10
network_port2_type: Hub/Switch; Hub/Switch (default), PC (Specifying the PC option and then connecting port 2 to a switch results in spanning-tree loops and network confusion)
rfc_2543_hold: 0; 0 (default)
sip_max_forwards: 70; The phone uses the value specified in this parameter in the Max-Forwards header of the SIP requests that it generates
timer_register_delta: 5; Configures the time interval at which reregistration will occur
####### Phone specific ######
autocomplete: 1; Configures automatic completion of numbers
call_waiting: 1;
phone_label: ""; Text desired to be displayed in upper right corner
#phone_password: cisco; Password to be used for console or telnet login (default: cisco)
phone_prompt: "SIP Phone"; The prompt that will be displayed on console and telnet (default: "SIP Phone")
user_info: none; User classification used when Registering [none (default), phone, ip]
line1_authname: ""
line2_authname: ""
line3_authname: ""
line4_authname: ""
line5_authname: ""
line6_authname: ""
line1_contact: ""
line2_contact: ""
line3_contact: ""
line4_contact: ""
line5_contact: ""
line6_contact: ""
line1_displayname: ""
line2_displayname: ""
line3_displayname: ""
line4_displayname: ""
line5_displayname: ""
line6_displayname: ""
line1_name: ""
line2_name: ""
line3_name: ""
line4_name: ""
line5_name: ""
line6_name: ""
line1_password: ""
line2_password: ""
line3_password: ""
line4_password: ""
line5_password: ""
line6_password: ""
line1_shortname: ""
line2_shortname: ""
line3_shortname: ""
line4_shortname: ""
line5_shortname: ""
line6_shortname: ""
call_manager1_addr: ""
call_manager2_addr: ""
call_manager3_addr: ""
call_manager4_addr: ""
call_manager5_addr: ""
call_manager1_sip_port: ""
call_manager2_sip_port: ""
call_manager3_sip_port: ""
call_manager4_sip_port: ""
call_manager5_sip_port: ""

3
tftp/syncinfo.xml

@ -0,0 +1,3 @@
<SYNCINFO>
<IMAGE VERSION="*" SYNC="2"/>
</SYNCINFO>

26
tftp_reflash/XMLDefault.cnf.xml

@ -0,0 +1,26 @@
<Default>
<callManagerGroup>
<members>
<member priority="0">
<callManager>
<ports>
<ethernetPhonePort>2000</ethernetPhonePort>
<mgcpPorts>
<listen>2427</listen>
<keepAlive>2428</keepAlive>
</mgcpPorts>
</ports>
<processNodeName></processNodeName>
</callManager>
</member>
</members>
</callManagerGroup>
<loadInformation8 model="IP Phone 7940">P0S3-8-12-00</loadInformation8>
<loadInformation7 model="IP Phone 7960">P0S3-8-12-00</loadInformation7>
<authenticationURL></authenticationURL>
<directoryURL></directoryURL>
<idleURL></idleURL>
<informationURL></informationURL>
<messagesURL></messagesURL>
<servicesURL></servicesURL>
</Default>

25
toilet_paper.sh

@ -0,0 +1,25 @@
#!/bin/sh
cd "$(dirname "$0")"
line="$1"
stamp=/tmp/last_tp
case "$line" in
32)
snd="tp_prizemi"
;;
44)
snd="tp_prvni"
;;
49)
snd="tp_druhe"
;;
*)
exit
;;
esac
if find "$stamp" -mmin -120 | grep -q .; then echo "Too soon"; exit 2; fi
/opt/ksp/ann_play.sh /opt/ksp/sounds/$snd.wav
touch "$stamp"

3
tts.sh

@ -0,0 +1,3 @@
#!/bin/bash
curl "https://translate.google.com/translate_tts?ie=UTF-8&q="$(perl -MURI::Escape -e 'print uri_escape($ARGV[0])' "$1")"&tl=cs&client=tw-ob" -H 'Referer: http://translate.google.com/' -H 'User-Agent: stagefright/1.2 (Linux;Android 5.0)' |ffmpeg -i - -ar 8000 -ac 1 -y "$2"

5
wc_thanks.sh

@ -0,0 +1,5 @@
#!/bin/bash
cd "$(dirname "$0")"
./ann_play_unicast.sh 32 /opt/ksp/sounds/wc_thanks

157
webapp/directory.psgi

@ -0,0 +1,157 @@
#!/usr/bin/perl
use strict;
use warnings;
use utf8;
use feature 'unicode_strings';
use Encode;
use Text::Unidecode;
use URI::Escape;
my %directory;
open my $fh1, '<', '/opt/ksp/www/directory.txt' or die "Cannot open file directory.txt: $!\n";
open my $fh2, '<', '/opt/ksp/www/directory_external.txt' or die "Cannot open file directory_external.txt: $!\n";
for my $fh ($fh1, $fh2) {
while (<$fh>) {
chomp;
next if /^#/;
next unless /^\s*(.*?)\s*=\s*([^=]*?)\s*$/;
my ($key, $value) = ($1, $2);
next unless length $key and length $value;
$directory{decode('UTF-8', $key)} = decode('UTF-8', $value);
}
}
close $fh1;
close $fh2;
sub search {
my ($keyword, $page) = @_;
my @keys = sort keys %directory;
@keys = grep /\Q$keyword\E/i, @keys if length $keyword;
splice @keys, 0, $page * 32;
my $next = splice @keys, 32;
return $next, map { $_ => $directory{$_} } @keys;
}
sub escape {
my ($text) = @_;
$text =~ s/&/&amp;/g;
$text =~ s/</&lt;/g;
$text =~ s/>/&gt;/g;
$text =~ s/\x00//g;
$text =~ s/['"]/_/g; # XML parser does not accept input which contains "&quot;" or "&apos;"
$text =~ s/\x86/_/g; # IP Phone firmware crashes when input contains byte 0x86
return $text;
}
sub string {
return escape(encode('ISO-8859-1', $_[0], sub { unidecode(chr($_[0])) }));
}
my $app = sub {
my ($env) = @_;
return [ '405' ] if $env->{REQUEST_METHOD} !~ /^(?:HEAD|GET)$/;
my %raw_args = map { (split /=/, $_, 2)[0,1] } split /&/, $env->{QUERY_STRING} // '';
my %args = map { decode('ISO-8859-1', uri_unescape($_ // '')) } %raw_args;
my $keyword = $args{keyword} // '';
my $page = $args{page} // '';
$page = 0 unless $page =~ /^[0-9]+$/;
my $current_url = $env->{'psgi.url_scheme'} . '://' . $env->{HTTP_HOST} . $env->{PATH_INFO};
if (not $args{search}) {
return [
'200',
[ 'Content-Type' => 'text/xml; charset="ISO-8859-1"' ],
[ <<"EOD"
<?xml version="1.0" encoding="ISO-8859-1"?>
<CiscoIPPhoneInput>
<Title>Search for an entry</Title>
<Prompt>Enter a search keyword</Prompt>
<URL>$current_url?search=1</URL>
<InputItem>
<DisplayName>Keyword</DisplayName>
<QueryStringParam>keyword</QueryStringParam>
<InputFlags></InputFlags>
<DefaultValue></DefaultValue>
</InputItem>
</CiscoIPPhoneInput>
EOD
],
];
}
my $title = length $keyword ? 'Search Result' : 'External Directory';
if ($args{end}) {
return [
'200',
[ 'Content-Type' => 'text/xml; charset="ISO-8859-1"' ],
[ <<"EOD"
<?xml version="1.0" encoding="ISO-8859-1"?>
<CiscoIPPhoneText>
<Title>$title</Title>
<Text>No more entries</Text>
</CiscoIPPhoneText>
EOD
],
];
}
my ($next, %search_result) = search($keyword, $page);
if (not keys %search_result) {
my $text = length $keyword ? 'No matching entry' : 'Directory is empty';
return [
'200',
[ 'Content-Type' => 'text/xml; charset="ISO-8859-1"' ],
[ <<"EOD"
<?xml version="1.0" encoding="ISO-8859-1"?>
<CiscoIPPhoneText>
<Title>$title</Title>
<Text>$text</Text>
</CiscoIPPhoneText>
EOD
]
];
}
my @next_args;
push @next_args, 'search=1';
push @next_args, "keyword=$raw_args{keyword}" if length $keyword;
push @next_args, 'page=' . ($page+1) if $next;
push @next_args, 'end=1' unless $next;
my $next_url = $current_url . '?' . (join '&', @next_args);
my $directories = '';
foreach (sort keys %search_result) {
my $key = $_;
my $name = string($key);
my $telephone = string($search_result{$key});
$directories .= <<"EOD";
<DirectoryEntry>
<Name>$name</Name>
<Telephone>$telephone</Telephone>
</DirectoryEntry>
EOD
}
return [
'200',
[
'Content-Type' => 'text/xml; charset="ISO-8859-1"',
'Refresh' => "0; url=$next_url",
],
[ <<"EOD"
<?xml version="1.0" encoding="ISO-8859-1"?>
<CiscoIPPhoneDirectory>
<Title>$title</Title>
<Prompt>Select an entry</Prompt>
$directories</CiscoIPPhoneDirectory>
EOD
]
];
};

4
webapp/directory.service

@ -0,0 +1,4 @@
[Service]
ExecStart=/usr/bin/uwsgi --ini=/opt/ksp/webapp/directory.uwsgi
[Install]
WantedBy=multi-user.service

6
webapp/directory.uwsgi

@ -0,0 +1,6 @@
[uwsgi]
socket=/tmp/directory.sock
plugin=psgi
psgi=/opt/ksp/webapp/directory.psgi
chmod-socket=666

33
webapp/hraj.pl

@ -0,0 +1,33 @@
my $app = sub {
my ($env) = @_;
my $path = $env->{PATH_INFO};
my $meth = $env->{REQUEST_METHOD};
if ($path =~ m|^/hraj/?$| && $meth eq "GET") {
my $r = '<html><body>';
$r .= qq[<div><form action="/hraj/stop" method="POST"><button style="font-size: 28px;" type="submit">Zastavit vše</button></form></div>];
opendir my $dir, "/opt/ksp/znelky" or die "Cannot open directory: $!";
for (readdir $dir) {
next if /^\./;
$r .= qq[<div><form action="/hraj/play/$_" method="POST" onsubmit="return confirm('Přehrát $_?')"><button style="font-size: 28px;" type="submit">$_</button></form></div>];
}
closedir $dir;
$r .= '</body></html>';
return [200, ['Content-Type' => 'text/html; charset=UTF-8'], [$r]];
} elsif ($path =~ m|^/hraj/play/(.*)$| && $meth eq "POST") {
system "/opt/ksp/ann_play.sh", "/opt/ksp/znelky/$1";
my $r = '<html><body style="font-size: large; ">';
$r .= qq[Přehrávám $1<br/><a href="/hraj">Zpět</a>];
$r .= '</body></html>';
return [200, ['Content-Type' => 'text/html; charset=UTF-8'], [$r]];
} elsif ($path =~ m|^/hraj/stop$| && $meth eq "POST") {
system "/opt/ksp/ann_stop.sh";
my $r = '<html><body style="font-size: large; ">';
$r .= qq[Zastaveno<br/><a href="/hraj">Zpět</a>];
$r .= '</body></html>';
return [200, ['Content-Type' => 'text/html; charset=UTF-8'], [$r]];
} else {
return [404, [], []];
}
}

4
webapp/hraj.service

@ -0,0 +1,4 @@
[Service]
ExecStart=/usr/bin/uwsgi --ini=/opt/ksp/webapp/hraj.uwsgi
[Install]
WantedBy=multi-user.service

7
webapp/hraj.uwsgi

@ -0,0 +1,7 @@
[uwsgi]
socket=/tmp/hraj.sock
chmod-socket=666
plugin=psgi
psgi=/opt/ksp/webapp/hraj.pl

676
webapp/services.psgi

@ -0,0 +1,676 @@
#!/usr/bin/perl
use strict;
use warnings;
use utf8;
use feature 'unicode_strings';
use DBI;
use Encode;
use Net::SIP;
use Net::SIP::Util qw(laddr4dst INETSOCK ip_sockaddr2parts sip_uri2parts);
use Socket;
use Text::Unidecode;
use URI::Escape;
my $dbfile = '/tmp/messages.db'; # TODO
my $dbh = DBI->connect("DBI:SQLite:$dbfile", undef, undef, { PrintError => 0, RaiseError => 1, sqlite_unicode => 1 });
$dbh->do('CREATE TABLE IF NOT EXISTS messages(id INTEGER PRIMARY KEY AUTOINCREMENT, r INT NOT NULL DEFAULT 0, f TEXT NOT NULL, t TEXT NOT NULL, m TEXT NOT NULL)');
$dbh->do('CREATE INDEX IF NOT EXISTS idx ON messages(r, t)');
my $mlsnikfile = '/opt/ksp/mlsnik.db';
my $mlsnik_dbh = DBI->connect("DBI:SQLite:$mlsnikfile", undef, undef, { PrintError => 0, RaiseError => 1, sqlite_unicode => 1 });
$mlsnik_dbh->do('CREATE TABLE IF NOT EXISTS nakup(id INTEGER PRIMARY KEY AUTOINCREMENT, meno TEXT NOT NULL, tovar TEXT NOT NULL, cena INT NOT NULL)');
$mlsnik_dbh->do('CREATE INDEX IF NOT EXISTS idx ON nakup(meno)');
sub escape {
my ($text) = @_;
$text =~ s/&/&amp;/g;
$text =~ s/</&lt;/g;
$text =~ s/>/&gt;/g;
$text =~ s/\x00//g;
$text =~ s/['"]/_/g; # XML parser does not accept input which contains "&quot;" or "&apos;"
$text =~ s/\x86/_/g; # IP Phone firmware crashes when input contains byte 0x86
return $text;
}
sub string {
return escape(encode('ISO-8859-1', $_[0], sub { unidecode(chr($_[0])) }));
}
my @month_names = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
my @day_names = qw(Sun Mon Tue Wed Thu Fri Sat Sun);
sub sip_date {
my @time = gmtime(time());
return sprintf('%s, %02u %s %04u %02u:%02u:%02u GMT', $day_names[$time[6]], $time[3], $month_names[$time[4]], $time[5] + 1900, $time[2], $time[1], $time[0]);
}
sub send_sip_message {
my ($from_ip, $to, $message) = @_;
# HACK: fill sender
$from_ip =~ /\.([0-9]+)$/;
my $user = $1 // 'message';
my $domain = '172.16.0.1:5062';
$to .= "\@$domain";
my ($host, $recipient) = sip_uri2parts($to);
($host, $recipient) = sip_uri2parts("$to\@$domain") unless defined $host;
return '400 Bad Request' unless defined $host;
my $port = ($host =~ s/:([0-9]+)$//) ? $1 : undef;
my $ip = inet_aton($host);
return "478 Unresolvable destination" unless defined $ip;
my $addr = inet_ntoa($ip);
my $laddr = laddr4dst($addr);
return '478 Unresolvable destination' unless $laddr;
my $sock = INETSOCK(Proto => 'udp', LocalAddr => $laddr, LocalPort => 0);
return "500 Cannot create socket: $!" unless $sock;
my $lport = (ip_sockaddr2parts(getsockname($sock)))[1];
my $leg = Net::SIP::Leg->new(sock => $sock);
return "500 Cannot create leg: $!" unless $leg;
my $ua = Net::SIP::Simple->new(from => "<sip:$user\@$domain>", leg => $leg);
return "500 Cannot create SIP user agent: $!" unless $ua;
my ($stop, $code, $text);
$ua->{endpoint}->new_request(
'MESSAGE',
{ from => $ua->{from}, to => ('<sip:' . (defined $recipient ? "$recipient\@" : '') . $host . (defined $port ? ":$port" : '') . '>') },
sub {
(undef, undef, undef, $code, my $packet) = @_;
(undef, $text) = $packet ? $packet->as_parts : ();
$stop = 1;
},
encode('UTF-8', $message),
uri => ('sip:' . (defined $recipient ? "$recipient\@" : '') . $addr . (defined $port ? ":$port" : '')),
Contact => "<sip:$user\@$laddr:$lport>",
Date => sip_date(),
'Content-Type' => 'text/plain',
'User-Agent' => 'CMXML HTTP Message Sender',
);
$ua->loop(10, \$stop);
$ua->cleanup();
return '408 Request Timeout' unless $stop;
return '400 Bad Request' unless $code and $text;
return "$code $text" unless $code eq '200';
return ''; # no error
}
sub send_message {
my ($env, $service, $args, $current_url, $raw_args) = @_;
my $recipient = $args->{recipient} // '';
my $message = $args->{message} // '';
my $send = $args->{send};
if (not $send) {
$recipient = string($recipient);
$message = string($message);
return [
'200',
[
'Content-Type' => 'text/xml; charset="ISO-8859-1"',
Expires => '-1',
],
[ <<"EOD"
<?xml version="1.0" encoding="ISO-8859-1"?>
<CiscoIPPhoneInput>
<Title>Send a new text message</Title>
<Prompt>Send a new text message</Prompt>
<URL>$current_url?service=$service&amp;send=1</URL>
<InputItem>
<DisplayName>Recipient</DisplayName>
<QueryStringParam>recipient</QueryStringParam>
<InputFlags>T</InputFlags>
<DefaultValue>$recipient</DefaultValue>
</InputItem>
<InputItem>
<DisplayName>Message</DisplayName>
<QueryStringParam>message</QueryStringParam>
<InputFlags></InputFlags>
<DefaultValue>$message</DefaultValue>
</InputItem>
</CiscoIPPhoneInput>
EOD
]
];
}
my $error = '';
my $timeout = 0;
if (not length $recipient) {
$error = "Recipient was not specified";
$timeout = 3;
} elsif (not length $message) {
$error = "Text of a message was not specified";
$timeout = 3;
} else {
$error = send_sip_message($env->{REMOTE_ADDR}, $recipient, $message);
}
my $redirect_url = "$current_url?service=$service";
if (length $error) {
$redirect_url .= '&recipient=' . $raw_args->{recipient} if length $recipient;
$redirect_url .= '&message=' . $raw_args->{message} if length $message;
}
my $text = length $error ? string("ERROR: $error") : 'Message was successfully sent';
return [
'200',
[
'Content-Type' => 'text/xml; charset="ISO-8859-1"',
Expires => '-1',
Refresh => "$timeout; url=$redirect_url",
],
[ <<"EOD"
<?xml version="1.0" encoding="ISO-8859-1"?>
<CiscoIPPhoneText>
<Title>Send a new text message</Title>
<Text>$text</Text>
</CiscoIPPhoneText>
EOD
]
];
}
sub read_message {
my ($env, $service, $args, $current_url) = @_;
my $next = $args->{next};
$next = 0 unless $next;
$next = 1 if $next !~ /^[0-9]+$/;
# HACK: get phone number
my $recipient = $env->{REMOTE_ADDR};
$recipient =~ s/.*\.//;
$dbh->do('UPDATE messages SET r=1 WHERE id < ? AND r = 0 AND t = ?', undef, $next, $recipient);
my ($id, $from, $message) = $dbh->selectrow_array('SELECT id, f, m FROM messages WHERE r = 0 AND t = ? ORDER BY id LIMIT 1', undef, $recipient);
# HACK: strip SIP domain
(undef, $from) = sip_uri2parts($from);
$next = $id+1 if defined $id;
my $timeout = defined $id ? 0 : 10;
my $title = defined $id ? string("From: " . $from) : "Waiting for a message...";
my $prompt = defined $id ? "Show next message" : "No more unread text messages";
my $text = defined $id ? string($message) : '';
return [
'200',
[
'Content-Type' => 'text/xml; charset="ISO-8859-1"',
Expires => '-1',
Refresh => "$timeout; url=$current_url?service=$service&next=$next",
],
[ <<"EOD"
<?xml version="1.0" encoding="ISO-8859-1"?>
<CiscoIPPhoneText>
<Title>$title</Title>
<Prompt>$prompt</Prompt>
<Text>$text</Text>
</CiscoIPPhoneText>
EOD
]
];
}
my %names;
my %orgs;
my %items;
{
open my $fh, '<:utf8', '/opt/ksp/www/osoby.txt' or die "Cannot open file osoby.txt: $!\n";
%names = map { chomp($_); my $tmp = unidecode(lc $_); $tmp =~ s/[^a-z0-9]+/_/g; ($tmp => $_) } <$fh>;
close $fh;
}
{
open my $fh, '<:utf8', '/opt/ksp/www/orgovia.txt' or die "Cannot open file orgovia.txt: $!\n";
%orgs = map { chomp($_); my $tmp = unidecode(lc $_); $tmp =~ s/[^a-z0-9]+/_/g; ($tmp => $_) } <$fh>;
close $fh;
}
{
# FORMAT: ascii_query_param TAB Unicode name TAB price Kc TAB available count
open my $fh, '<:utf8', '/opt/ksp/www/tovar.txt' or die "Cannot open file tovar.txt: $!\n";
%items = map { chomp($_); my ($param, $name, $price, $count) = split /\t+/; ($param => [$name, $price, $count]) } <$fh>;
close $fh;
}
sub mlsnik {
my ($env, $service, $args, $current_url) = @_;
my $title = string('Mlsník');
my $sub = $args->{sub} // '';
my $name = $args->{name} // '';
my $item = $args->{item} // '';
my $confirm = $args->{confirm};
my $org = $args->{org} // '0';
my $string;
my $refresh;
if ($sub eq 'utrata') {
$title .= string(' - Útrata');
if (not length $name) {
my $prompt = 'Vyberte osobu';
$string = <<"EOD";
<?xml version="1.0" encoding="ISO-8859-1"?>
<CiscoIPPhoneMenu>
<Title>$title</Title>
<Prompt>$prompt</Prompt>
EOD
if (not $org) {
for my $name (sort { $names{$a} cmp $names{$b} } keys %names) {
my $info = string($names{$name});
$string .= <<"EOD";
<MenuItem>
<Name>$info</Name>
<URL>$current_url?service=$service&amp;sub=utrata&amp;org=0&amp;name=$name</URL>
</MenuItem>
EOD
}
$string .= <<"EOD";
<MenuItem>
<Name>Orgovia</Name>
<URL>$current_url?service=$service&amp;sub=utrata&amp;org=1</URL>
</MenuItem>
EOD
$string .= '</CiscoIPPhoneMenu>';
} else {
for my $name (sort { $orgs{$a} cmp $orgs{$b} } keys %orgs) {
my $info = string($orgs{$name});
$string .= <<"EOD";
<MenuItem>
<Name>$info</Name>
<URL>$current_url?service=$service&amp;sub=utrata&amp;org=1&amp;name=$name</URL>
</MenuItem>
EOD
}
}
$string .= '</CiscoIPPhoneMenu>';
} else {
$title = string('Útrata pre ' . ($org ? $orgs{$name} : $names{$name}));
$string = <<"EOD";
<?xml version="1.0" encoding="ISO-8859-1"?>
<CiscoIPPhoneMenu>
<Title>$title</Title>
EOD
my @items = $mlsnik_dbh->selectall_array('SELECT tovar,COUNT(tovar),SUM(cena) FROM nakup WHERE meno = ? GROUP BY tovar', undef, $name);
foreach (@items) {
my ($tovar, $count, $cena) = @{$_};
my $item = $items{$tovar}->[0];
my $info = string("${count}x $item ... $cena Kč");
$string .= <<"EOD";
<MenuItem>
<Name>$info</Name>
<URL>$current_url?service=$service&amp;sub=utrata&amp;org=$org&amp;name=$name</URL>
</MenuItem>
EOD
}
my $cena = $mlsnik_dbh->selectrow_array('SELECT SUM(cena) FROM nakup WHERE meno = ?', undef, $name);
$cena ||= 0;
my $info = string("Celkom ... $cena Kč");
$string .= <<"EOD";
<MenuItem>
<Name>$info</Name>
<URL>$current_url?service=$service&amp;sub=utrata&amp;org=$org&amp;name=$name</URL>
</MenuItem>
EOD
$string .= '</CiscoIPPhoneMenu>';
}
} elsif ($sub eq 'kupa') {
$title .= string(' - Kúpa');
my $prompt = 'Vyberte osobu';
$string = <<"EOD";
<?xml version="1.0" encoding="ISO-8859-1"?>
<CiscoIPPhoneMenu>
<Title>$title</Title>
<Prompt>$prompt</Prompt>
EOD
if (not length $name) {
if (not $org) {
for my $name (sort { $names{$a} cmp $names{$b} } keys %names) {
my $info = string($names{$name});
$string .= <<"EOD";
<MenuItem>
<Name>$info</Name>
<URL>$current_url?service=$service&amp;sub=kupa&amp;org=0&amp;name=$name</URL>
</MenuItem>
EOD
}
$string .= <<"EOD";
<MenuItem>
<Name>Orgovia</Name>
<URL>$current_url?service=$service&amp;sub=kupa&amp;org=1</URL>
</MenuItem>
EOD
} else {
for my $name (sort { $orgs{$a} cmp $orgs{$b} } keys %orgs) {
my $info = string($orgs{$name});
$string .= <<"EOD";
<MenuItem>
<Name>$info</Name>
<URL>$current_url?service=$service&amp;sub=kupa&amp;org=1&amp;name=$name</URL>
</MenuItem>
EOD
}
}
$string .= '</CiscoIPPhoneMenu>';
} elsif (not length $item) {
$title = string("Kúpiť pre " . ($org ? $orgs{$name} : $names{$name}));
$string = <<"EOD";
<?xml version="1.0" encoding="ISO-8859-1"?>
<CiscoIPPhoneMenu>
<Title>$title</Title>
<Prompt>Vyberte tovar</Prompt>
EOD
for my $item (sort { $items{$a}->[0] cmp $items{$b}->[0] } keys %items) {
next unless $items{$item}->[2];
my $info = string($items{$item}->[0] . " - " . $items{$item}->[1] . " Kč");
$string .= <<"EOD";
<MenuItem>
<Name>$info</Name>
<URL>$current_url?service=$service&amp;sub=kupa&amp;org=$org&amp;name=$name&amp;item=$item</URL>
</MenuItem>
EOD
}
$string .= '</CiscoIPPhoneMenu>';
} elsif (not $confirm) {
my $prompt = string("Potvrdiť");
my $info = string(($org ? $orgs{$name} : $names{$name}) . " si zakupuje tovar " . $items{$item}->[0] . " za " . $items{$item}->[1] . " Kč");
$string = <<"EOD";
<?xml version="1.0" encoding="ISO-8859-1"?>
<CiscoIPPhoneMenu>
<Title>$title</Title>
<Prompt>$prompt</Prompt>
<MenuItem>
<Name>$info</Name>
<URL>$current_url?service=$service&amp;sub=kupa&amp;org=$org&amp;name=$name&amp;item=$item&amp;confirm=1</URL>
</MenuItem>
</CiscoIPPhoneMenu>
EOD
} else {
$mlsnik_dbh->do('INSERT INTO nakup(meno, tovar, cena) VALUES(?, ?, ?)', undef, $name, $item, $items{$item}->[1]);
$refresh = "2; url=$current_url";
my $info = string("Potvrdené");
$string = <<"EOD";
<?xml version="1.0" encoding="ISO-8859-1"?>
<CiscoIPPhoneText>
<Title>$title</Title>
<Text>$info</Text>
</CiscoIPPhoneText>
EOD
}
} else {
my $prompt = string('Vyberte možnosť');
my $item1 = string('Kúpiť tovar');
my $item2 = string('Zobraziť útratu');
$string = <<"EOD";
<?xml version="1.0" encoding="ISO-8859-1"?>
<CiscoIPPhoneMenu>
<Title>$title</Title>
<Prompt>$prompt</Prompt>
<MenuItem>
<Name>$item1</Name>
<URL>$current_url?service=$service&amp;sub=kupa</URL>
</MenuItem>
<MenuItem>
<Name>$item2</Name>
<URL>$current_url?service=$service&amp;sub=utrata</URL>
</MenuItem>
</CiscoIPPhoneMenu>
EOD
}
utf8::downgrade($string); # Workaround bug in PSGI
return [
'200',
[
'Content-Type' => 'text/xml; charset="ISO-8859-1"',
Expires => '-1',
($refresh ? (Refresh => $refresh) : ()),
],
[
$string
]
];
}
sub weather {
my ($env, $service, $args, $current_url) = @_;
my $title = string('Weather Forecast');
my @items;
if (open my $fh, '<:utf8', '/tmp/weather.txt') {
chomp(@items = <$fh>);
close $fh;
} else {
push @items, 'ERROR: Cannot open /tmp/weather.txt';
}
push @items, 'ERROR: /tmp/weather.txt is empty' unless @items;
my $items;
foreach (@items) {
my $text = string($_);
$items .= <<"EOD";
<MenuItem>
<Name>$text</Name>
<URL>$current_url?service=$service</URL>
</MenuItem>
EOD
}
my $string = <<"EOD";
<?xml version="1.0" encoding="ISO-8859-1"?>
<CiscoIPPhoneMenu>
<Title>$title</Title>
<Prompt>Update</Prompt>
$items</CiscoIPPhoneMenu>
EOD
utf8::downgrade($string); # Workaround bug in PSGI
return [
'200',
[
'Content-Type' => 'text/xml; charset="ISO-8859-1"',
Expires => '-1',
Refresh => "30; url=$current_url?service=$service",
],
[
$string
],
];
}
sub status {
my ($env, $service, $args, $current_url) = @_;
my $title = string('Error status log');
my @items;
if (open my $fh, '<:utf8', '/tmp/error.log') {
chomp(@items = <$fh>);
close $fh;
} else {
push @items, 'ERROR: Cannot open error log';
}
push @items, 'No errors' unless @items;
my $items;
foreach (@items) {
my $text = string($_);
$items .= <<"EOD";
<MenuItem>
<Name>$text</Name>
<URL>$current_url?service=$service</URL>
</MenuItem>
EOD
}
my $string = <<"EOD";
<?xml version="1.0" encoding="ISO-8859-1"?>
<CiscoIPPhoneMenu>
<Title>$title</Title>
<Prompt>Update</Prompt>
$items</CiscoIPPhoneMenu>
EOD
utf8::downgrade($string); # Workaround bug in PSGI
return [
'200',
[
'Content-Type' => 'text/xml; charset="ISO-8859-1"',
Expires => '-1',
Refresh => "30; url=$current_url?service=$service",
],
[
$string
],
];
}
my %services = (
send_message => [ 'Send a new text message' => \&send_message, 1 ],
read_message => [ 'Show unread text messages' => \&read_message, 2 ],
mlsnik => [ 'Mlsnik' => \&mlsnik, 3 ],
weather => [ 'Weather Forecast - yr.no' => \&weather, 4 ],
status => [ 'Error status log' => \&status, 5 ],
);
sub wc_paper {
my ($env, $service, $args, $current_url, $raw_args, $line) = @_;
my ($sec, $min, $hour) = localtime();
if ($hour >= 23 || $hour < 7) { # Night time
return [
'200',
[
'Content-Type' => 'text/xml; charset="ISO-8859-1"',
Expires => '-1',
],
[
<<"EOD"
<?xml version="1.0" encoding="ISO-8859-1"?>
<CiscoIPPhoneText>
<Title>WC: I need a toilet paper</Title>
<Text>This feature is disabled during night time.</Text>
</CiscoIPPhoneText>
EOD
],
];
}
if ($args->{confirm}) {
say STDERR "running: '/opt/ksp/toilet_paper.sh $line &'";
system("sh", "-c", "/opt/ksp/toilet_paper.sh $line &");
}
return [
'200',
[
'Content-Type' => 'text/xml; charset="ISO-8859-1"',
Expires => '-1',
],
[
$args->{confirm} ? <<"EOD"
<?xml version="1.0" encoding="ISO-8859-1"?>
<CiscoIPPhoneText>
<Title>WC: I need a toilet paper</Title>
<Text>Request for a new toilet paper was sent.</Text>
</CiscoIPPhoneText>
EOD
: <<"EOD"
<?xml version="1.0" encoding="ISO-8859-1"?>
<CiscoIPPhoneMenu>
<Title>WC: I need a toilet paper</Title>
<Prompt>Confirm</Prompt>
<MenuItem>
<Name>Is a toilet paper really missing? Requeust for a new one.</Name>
<URL>$current_url?service=$service&amp;confirm=1</URL>
</MenuItem>
</CiscoIPPhoneMenu>
EOD
],
];
}
sub wc_call_help {
my ($env) = @_;
return [
'200',
[ 'Content-Type' => 'text/xml; charset="ISO-8859-1"' ],
[ <<"EOD"
<?xml version="1.0" encoding="ISO-8859-1"?>
<CiscoIPPhoneDirectory>
<Title>WC: Call for HELP</Title>
<DirectoryEntry>
<Name>Call for HELP</Name>
<Telephone>130</Telephone>
</DirectoryEntry>
</CiscoIPPhoneDirectory>
EOD
]
];
}
my %wc_services = (
wc_paper => [ 'WC: I need a toilet paper' => \&wc_paper ],
wc_call_help => [ 'WC: Call for HELP' => \&wc_call_help ],
);
my $app = sub {
my ($env) = @_;
return [ '405' ] if $env->{REQUEST_METHOD} !~ /^(?:HEAD|GET)$/;
my %raw_args = map { (split /=/, $_, 2)[0,1] } split /&/, $env->{QUERY_STRING} // '';
my %args = map { decode('ISO-8859-1', uri_unescape($_ // '')) } %raw_args;
my $service = $args{service} // '';
my $current_url = $env->{'psgi.url_scheme'} . '://' . $env->{HTTP_HOST} . $env->{PATH_INFO};
# HACK: get line
my $line = $env->{REMOTE_ADDR};
$line =~ s/.*\.//;
return $wc_services{$service}->[1]->($env, $service, \%args, $current_url, \%raw_args, $line) if exists $wc_services{$service};
return $services{$service}->[1]->($env, $service, \%args, $current_url, \%raw_args, $line) if exists $services{$service};
return [ '404' ] if length $service;
my $services = '';
my @services_keys = sort { $services{$a}->[2] cmp $services{$b}->[2] } keys %services;
@services_keys = grep !/mlsnik/, @services_keys unless $line =~ /^(?:36|37|2.|33)$/;
unshift @services_keys, sort { $wc_services{$a}->[0] cmp $wc_services{$b}->[0] } keys %wc_services if $line =~ /^(?:32|44|49)$/;
foreach (@services_keys) {
my $name = string(exists $services{$_} ? $services{$_}->[0] : $wc_services{$_}->[0]);
my $url = "$current_url?service=$_";
$services .= <<"EOD";
<MenuItem>
<Name>$name</Name>
<URL>$url</URL>
</MenuItem>
EOD
}
return [
'200',
[ 'Content-Type' => 'text/xml; charset="ISO-8859-1"' ],
[ <<"EOD"
<?xml version="1.0" encoding="ISO-8859-1"?>
<CiscoIPPhoneMenu>
<Title>Services for line $line</Title>
<Prompt>Select option</Prompt>
$services</CiscoIPPhoneMenu>
EOD
]
];
};

4
webapp/services.service

@ -0,0 +1,4 @@
[Service]
ExecStart=/usr/bin/uwsgi --ini=/opt/ksp/webapp/services.uwsgi
[Install]
WantedBy=multi-user.service

6
webapp/services.uwsgi

@ -0,0 +1,6 @@
[uwsgi]
socket=/tmp/services.sock
plugin=psgi
psgi=/opt/ksp/webapp/services.psgi
chmod-socket=666

13
www/directory_external.txt

@ -0,0 +1,13 @@
Technická podpora FBI = 910119352
HR linka = 4445
Hlasová schránka = 131
Konference 0 = 110
Konference 1 = 111
Konference 2 = 112
Konference 3 = 113
Konference 4 = 114
Konference 5 = 115
Konference 6 = 116
Konference 7 = 117
Konference 8 = 118
Konference 9 = 119

BIN
www/logo.bmp

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

2
www/orgovia.txt

@ -0,0 +1,2 @@
Org 1
Org 2

2
www/osoby.txt

@ -0,0 +1,2 @@
Meno 1
Meno 2

34
www/tovar.txt

@ -0,0 +1,34 @@
coca_cola Coca Cola 1.75 22 0
pepsi_cola Pepsi Cola 2.5 20 0
minonky Miňonky 10 1
kastany Kaštany 11 0
tofik Tofík 5 0
musli Müsli tyčinka 5 1
fin_carre_200 Fin Carré 200g (velk) 33 0
fin_carre_100 Fin Carré 100g (malá) 16 1
fin_carre_nois Fin Carré Noisette 20 1
fin_carre_74 Fin Carré 74% 20 0
piskoy_coko Piškoty v čokoládě 13 0
zele_jelly Želé Rainbow Jelly 10 0
syrove_tycinky Sýrové tyčinky 15 1
arasidy_pikan Arašídy pikantní 17 0
chipsy_snack Chipsy Snack 150g 16 0
syrove_koule Sýrové koule / Snack 8 0
mrkev Mrkev 1 0
chipsy_bohemia Chipsy Bohemia 130g 30 0
kofola_15 Kofola 1.5 26 0
oreo Oreo 44g 11 0
pepsi_cola15 Pepsi Cola 1.5 18 0
import_paper Historické nákupy 0 0
kofola_2 Kofola 2l 15 1
bramb_tycinky Bramborové tyčinky 15 1
chipsy_ahb Chipsy 22 1
arasidy_sl_kar Arašídy slaný karam. 30 1
arasidy_sol Arašídy solené 11 1
arasid_krup Arašídové křupky 9 1
banán Banán 3 1
zlate_polom Zlaté polomáčané 17 1
napoli_or Manner snack 4 1
happy_day Happy day džus 30 1
stud_pecet Studenská pečeť 30 1
mrkev_2 Mrkev 2 1

0
znelky/.keep

Loading…
Cancel
Save