diff --git a/.gitignore b/.gitignore index 16acc6448..bfce84f17 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,7 @@ opt/gemeinschaft/etc/asterisk/extensions.ael *.pyc .gemeinschaft-version *.komodoproject + +# exclude yealink firmware images +opt/gemeinschaft/htdocs/prov/yealink/fw/*.rom + diff --git a/etc/asterisk/asterisk.conf b/etc/asterisk/asterisk.conf index 33fe71975..391c7f148 100644 --- a/etc/asterisk/asterisk.conf +++ b/etc/asterisk/asterisk.conf @@ -32,7 +32,7 @@ astetcdir => /opt/gemeinschaft/etc/asterisk astmoddir => /usr/lib/asterisk/modules astvarlibdir => /var/lib/asterisk -astdatadir => /var/lib/asterisk +astdatadir => /usr/share/asterisk astagidir => /var/lib/asterisk/agi-bin astspooldir => /var/spool/asterisk astrundir => /var/run/asterisk diff --git a/etc/gemeinschaft/gemeinschaft.php b/etc/gemeinschaft/gemeinschaft.php index 75fc80761..d35c4d7a7 100644 --- a/etc/gemeinschaft/gemeinschaft.php +++ b/etc/gemeinschaft/gemeinschaft.php @@ -275,6 +275,7 @@ //$PROV_MODELS_ENABLED_AASTRA = '*'; # or '51i,53i,55i,57i' //$PROV_MODELS_ENABLED_GRANDSTREAM = '*'; # or 'bt110,gxp2000,gxp2020', ... //$PROV_MODELS_ENABLED_TIPTEL = '*'; # or 'ip280,ip284,ip286' +//$PROV_MODELS_ENABLED_YEALINK = '*'; # or 'yealink-sip-t46g,yealink-sip-t48g' //$PROV_MODELS_ENABLED_POLYCOM = '*'; # or 'spip-550,spip-670', ... @@ -490,6 +491,56 @@ # 'f20' Private Hold # 'f27' XML Browser +//-----------------------[ Yealink ]-----------------------// + +$YEALINK_PROV_ENABLED = true; # do provisioning for Yealink? + +$YEALINK_PROV_HTTP_PASS = 'admin'; # e.g. "gEheiM23y89sdo23", default: 'admin' + # to password protect the phone's web gui. + # changing these values will likely cause automatic rebooting to fail + +//$YEALINK_PROV_NTP = @$PROV_HOST; +//$YEALINK_PROV_NTP = '192.168.1.130'; + # NTP Server. the stupid Tiptel needs it + + # Set $LOG_LEVEL to "NOTICE" or even "DEBUG" and + # tail -f /var/log/gemeinschaft/gs.log + # Test the update mechanism with 1 or 2 phones. This is especially + # important with PoE (Power over Ethernet) switches. +$YEALINK_PROV_FW_UPDATE = false; # allow firmware updates? + +//$YEALINK_PROV_KEY_BLACKLIST = ''; + # do not show these softkey functions in GUI, + # comma separated list (e.g. 'f5,f12,f17'), default: '' + # 'f13' SpeedDial + # 'f16' BLF + # 'f1' Conference + # 'f2' Forward + # 'f3' Transfer + # 'f4' Hold + # 'f5' DND + # 'f6' Redial + # 'f7' Call Return + # 'f8' SMS + # 'f9' Call Pickup + # 'f10' Call Park + # 'f11' Custom + # 'f12' Voicemail + # 'f14' Intercom + # 'f15' Line + # 'f17' URL + # 'f18' Group Listening + # 'f19' Public Hold + # 'f20' Private Hold + # 'f27' XML Browser + +$YEALINK_PROV_FW_DEFAULT_SIP_T42G = ''; +$YEALINK_PROV_FW_DEFAULT_SIP_T46G = ''; +$YEALINK_PROV_FW_DEFAULT_SIP_T48G = ''; + +$YEALINK_PROV_FW_DEFAULT_SIP_T42S = ''; +$YEALINK_PROV_FW_DEFAULT_SIP_T46S = ''; +$YEALINK_PROV_FW_DEFAULT_SIP_T46U = ''; //-----------------------[ Polycom ]----------------------// @@ -676,6 +727,9 @@ //$FAX_INIT_DOCDIR = '/tmp/'; # directory containing fax documents to be used by "send-fax.php" +//$FAX_MAP_IAXMODEM_USER = ""; + # use group membership of user for dialout by IAXmodem + /*********************************************************** * BRANCH OFFICE INTEGRATION (BOI) ***********************************************************/ diff --git a/install.sh b/install.sh index a84b9ad2f..9e4b96faa 100644 --- a/install.sh +++ b/install.sh @@ -219,7 +219,7 @@ ${APTITUDE_INSTALL} \ vim less git linux-headers-$(uname -r) \ gcc make gcc make ncurses-dev zlib1g-dev \ g++ libxml2-dev doxygen libmysql++-dev libcrypto++-dev libssl-dev \ - libportaudio2 portaudio19-dev libasound-dev + libportaudio2 portaudio19-dev libasound-dev lame # now that we have vim, enable syntax highlighting by default: if ( which vim 1>>/dev/null 2>>/dev/null ); then @@ -302,6 +302,24 @@ sleep 3 # sed -i -r -e 's/^(RAMRUN=)no/\1yes/' /etc/default/rcS || true +# install libjansson-dev, sqlite3, libsqlite-dev +# +echo "" +echo "***" +echo "*** Installing libjansson-dev, sqlite3, libsqlite3-dev ..." +echo "***" +if ( ! which libjansson-dev 1>>/dev/null 2>>/dev/null ); then + ${APTITUDE_INSTALL} libjansson-dev +fi +if ( ! which sqlite3 1>>/dev/null 2>>/dev/null ); then + ${APTITUDE_INSTALL} sqlite3 +fi +if ( ! which libsqlite3-dev 1>>/dev/null 2>>/dev/null ); then + ${APTITUDE_INSTALL} libsqlite3-dev +fi +if ( ! which uuid-dev 1>>/dev/null 2>>/dev/null ); then + ${APTITUDE_INSTALL} uuid-dev +fi # install dahdi # @@ -319,14 +337,37 @@ make config # generate /etc/dahdi/system.conf: dahdi_genconf || true +# install asterisk +# +echo "" +echo "***" +echo "*** Installing Asterisk ..." +echo "***" cd /usr/local/src/ -$DOWNLOAD "http://downloads.asterisk.org/pub/telephony/asterisk/asterisk-13-current.tar.gz" -tar -xvzf asterisk-13-current.tar.gz -cd $(tar -tzf asterisk-13-current.tar.gz | head -n 1 | cut -d '/' -f1) +$DOWNLOAD "http://downloads.asterisk.org/pub/telephony/asterisk/old-releases/asterisk-13.15.1.tar.gz" +$DOWNLOAD "https://issues.asterisk.org/jira/secure/attachment/55471/asterisk-13.13.1-one-way-audio.patch" +tar -xvzf asterisk-13.15.1.tar.gz +cd $(tar -tzf asterisk-13.15.1.tar.gz | head -n 1 | cut -d '/' -f1) + +# patch asterisk +# +echo "" +echo "***" +echo "*** Patching Asterisk ..." +echo "***" +# Patch against 1-way-audio when transcoding +patch -p0 < ../asterisk-13.13.1-one-way-audio.patch + +# read -p "Patching completed, Press enter to continue" + ./configure make menuselect.makeopts menuselect/menuselect --enable res_config_mysql menuselect.makeopts menuselect/menuselect --enable cdr_mysql menuselect.makeopts +menuselect/menuselect --enable app_meetme menuselect.makeopts +menuselect/menuselect --enable app_setcallerid menuselect.makeopts +# read -p "Setting asterisk options completed, Press enter to continue" + make make install make samples @@ -391,7 +432,7 @@ ${APTITUDE_INSTALL} \ sipsak \ mysql-client mysql-server \ apache2 \ - php5-cli libapache2-mod-php5 php5-mysql php5-ldap \ + php5-cli libapache2-mod-php5 php5-mysql php5-ldap php5-curl \ python2.6 \ python-mysqldb \ sox libsox-fmt-all mpg123 diff --git a/opt/gemeinschaft/dialplan-scripts/in-user-get-ringer.agi b/opt/gemeinschaft/dialplan-scripts/in-user-get-ringer.agi index c604adf2d..40e5ac88c 100755 --- a/opt/gemeinschaft/dialplan-scripts/in-user-get-ringer.agi +++ b/opt/gemeinschaft/dialplan-scripts/in-user-get-ringer.agi @@ -208,6 +208,23 @@ elseif (strToLower(subStr($user['phone_type'],0,6)) === 'tiptel') { } } +} +elseif (strToLower(subStr($user['phone_type'],0,7)) === 'yealink') { + + $ringtones = _get_ringers( $user['id'] ); + + if (@$ringtones[$source]['file']) { + gs_agi_set_variable( 'ringer', ('<'. GS_PROV_SCHEME .'://'. GS_PROV_HOST . (GS_PROV_PORT ? ':'.GS_PROV_PORT : '') . GS_PROV_PATH .'ringtones/'. $ringtones[$source]['file'] .'-tiptel.wav>') ); + } elseif (array_key_exists('bellcore', $ringtones[$source])) { + + if (@$ringtones[$source]['bellcore'] == 1) exit(); + if (@$ringtones[$source]['bellcore'] != 0) { + gs_agi_set_variable( 'ringer', ('Bellcore-dr'. $ringtones[$source]['bellcore'] ) ); + } else { + gs_agi_set_variable( 'ringer', ('Bellcore-dr0') ); + } + } + } else { diff --git a/opt/gemeinschaft/dialplan-scripts/out-route.agi b/opt/gemeinschaft/dialplan-scripts/out-route.agi index c2ed28fc4..dacae1736 100755 --- a/opt/gemeinschaft/dialplan-scripts/out-route.agi +++ b/opt/gemeinschaft/dialplan-scripts/out-route.agi @@ -70,6 +70,19 @@ $user_id = (int)trim($argv[4]); include_once( GS_DIR .'inc/db_connect.php' ); +// Map user for use by IAXmodem if configured +if ($argv[4] == 'IAXmodem') { + # use map user from gemeinschaft.php + + $db = gs_db_slave_connect(); + if (! $db) gs_agi_err( 'DB error' ); + + $user_id = (int)$db->executeGetOne( 'SELECT `id` FROM `users` WHERE `user`=\''. $db->escape(gs_get_conf('GS_FAX_MAP_IAXMODEM_USER')) .'\'' ); + if ($user_id < 1) $user_id=0; +} +else { + $user_id = (int)trim($argv[4]); +} $qualify_cid = true; diff --git a/opt/gemeinschaft/etc/asterisk/iax-nodes.conf.php b/opt/gemeinschaft/etc/asterisk/iax-nodes.conf.php index 70ef9ffce..a91af7fac 100755 --- a/opt/gemeinschaft/etc/asterisk/iax-nodes.conf.php +++ b/opt/gemeinschaft/etc/asterisk/iax-nodes.conf.php @@ -134,6 +134,7 @@ $params['permit' ] = null; $codecs_allow = array(); + $codecs_allow['g722' ] = false; $codecs_allow['alaw' ] = true; $codecs_allow['ulaw' ] = false; diff --git a/opt/gemeinschaft/etc/asterisk/sip-nodes.conf.php b/opt/gemeinschaft/etc/asterisk/sip-nodes.conf.php index 85d9a3568..71cab40e2 100755 --- a/opt/gemeinschaft/etc/asterisk/sip-nodes.conf.php +++ b/opt/gemeinschaft/etc/asterisk/sip-nodes.conf.php @@ -138,6 +138,7 @@ $params['permit' ] = null; $codecs_allow = array(); + $codecs_allow['g722' ] = false; $codecs_allow['alaw' ] = true; $codecs_allow['ulaw' ] = false; diff --git a/opt/gemeinschaft/etc/asterisk/sip_notify.conf b/opt/gemeinschaft/etc/asterisk/sip_notify.conf index ab36a3b0d..ae758bc22 100644 --- a/opt/gemeinschaft/etc/asterisk/sip_notify.conf +++ b/opt/gemeinschaft/etc/asterisk/sip_notify.conf @@ -122,3 +122,11 @@ Content-Length=>0 ;Content-Length=>0 +;------------------------------- Yealink +[yealink-check-cfg] +Event=>check-sync\;reboot=false + +[yealink-check-cfg-reboot] +Event=>check-sync\;reboot=true + + diff --git a/opt/gemeinschaft/htdocs/gui/mod/admin_users.php b/opt/gemeinschaft/htdocs/gui/mod/admin_users.php index f6aa2d8ef..54d35bae0 100644 --- a/opt/gemeinschaft/htdocs/gui/mod/admin_users.php +++ b/opt/gemeinschaft/htdocs/gui/mod/admin_users.php @@ -36,6 +36,8 @@ include_once( GS_DIR .'inc/gs-fns/gs_user_external_number_del.php' ); include_once( GS_DIR .'inc/gs-fns/gs_pickupgroup_user_add.php' ); include_once( GS_DIR .'inc/gs-fns/gs_callblocking_set.php' ); +include_once( GS_DIR .'inc/gs-fns/gs_user_ip_by_ext.php' ); +include_once( GS_DIR .'inc/gs-fns/gs_user_phonemodel_get.php' ); include_once( GS_DIR .'inc/group-fns.php' ); require_once( GS_DIR .'inc/boi-soap/boi-api.php' ); include_once( GS_DIR .'lib/utf8-normalize/gs_utf_normal.php' ); @@ -1028,6 +1030,24 @@ function count_users_logged_in( $DB ) { ← + + : + + + + +   + + + + : + + + + +   + + diff --git a/opt/gemeinschaft/htdocs/gui/mod/inc_keyprof.php b/opt/gemeinschaft/htdocs/gui/mod/inc_keyprof.php index 32ef66661..e2205af8b 100644 --- a/opt/gemeinschaft/htdocs/gui/mod/inc_keyprof.php +++ b/opt/gemeinschaft/htdocs/gui/mod/inc_keyprof.php @@ -69,6 +69,12 @@ $phone_types['snom-710'] = 'Snom 710'; if (in_array('*', $enabled_models) || in_array('715', $enabled_models)) $phone_types['snom-715'] = 'Snom 715'; + if (in_array('*', $enabled_models) || in_array('d305', $enabled_models)) + $phone_types['snom-d305'] = 'Snom D305'; + if (in_array('*', $enabled_models) || in_array('d315', $enabled_models)) + $phone_types['snom-d315'] = 'Snom D315'; + if (in_array('*', $enabled_models) || in_array('d375', $enabled_models)) + $phone_types['snom-d375'] = 'Snom D375'; } /* # Maybe there will be some reason for enabling keys on Snom M3 phones in future. @@ -114,7 +120,21 @@ if (in_array('*', $enabled_models) || in_array('ip286', $enabled_models)) $phone_types['tiptel-ip286'] = 'Tiptel IP 286'; } - +if (gs_get_conf('GS_YEALINK_PROV_ENABLED')) { + $enabled_models = preg_split('/[,\\s]+/', gs_get_conf('GS_PROV_MODELS_ENABLED_YEALINK')); + if (in_array('*', $enabled_models) || in_array('yealink-sip-t42g', $enabled_models)) + $phone_types['yealink-sip-t42g' ] = 'Yealink SIP T42G'; + if (in_array('*', $enabled_models) || in_array('yealink-sip-t46g', $enabled_models)) + $phone_types['yealink-sip-t46g' ] = 'Yealink SIP T46G'; + if (in_array('*', $enabled_models) || in_array('yealink-sip-t48g', $enabled_models)) + $phone_types['yealink-sip-t48g' ] = 'Yealink SIP T48G'; + if (in_array('*', $enabled_models) || in_array('yealink-sip-t42s', $enabled_models)) + $phone_types['yealink-sip-t42s' ] = 'Yealink SIP T42S'; + if (in_array('*', $enabled_models) || in_array('yealink-sip-t46s', $enabled_models)) + $phone_types['yealink-sip-t46s' ] = 'Yealink SIP T46S'; + if (in_array('*', $enabled_models) || in_array('yealink-sip-t46u', $enabled_models)) + $phone_types['yealink-sip-t46u' ] = 'Yealink SIP T46U'; + } $key_functions_snom = array( 'none' => __('Leer'), # none @@ -235,6 +255,36 @@ unset($key_functions_tiptel[$keyfn]); } +$key_functions_yealink = array( + 'f0' => __('Leer'), + 'f13' => __('Zielwahl'), # SpeedDial + 'f16' => __('BLF'), # BLF + //'f1' => __('Konferenz'), # Conference + //'f2' => __('Forward'), # Forward + 'f3' => __('Übergabe'), # Transfer + 'f4' => __('Halten'), # Hold + 'f5' => __('Nicht stören'), # DND + //'f6' => __('Redial'), # Redial + //'f7' => __('CallReturn'), # Call Return + //'f8' => __('SMS'), # SMS + //'f9' => __('CallPickup'), # Call Pickup + //'f10' => __('CallPark'), # Call Park + //'f11' => __('Custom'), # Custom + //'f12' => __('Voicemail'), # Voicemail + //'f14' => __('Intercom'), # Intercom + //'f15' => __('Leitung'), # Line (for line key only) + //'f17' => __('URL'), # URL + //'f18' => __('GroupListening'), # Group Listening + //'f19' => __('PublicHold'), # Public Hold + //'f20' => __('PrivateHold'), # Private Hold + //'f27' => __('XML Browser'), # XML Browser +); +$key_function_none_yealink = 'f0'; +$key_functions_blacklist = preg_split('/[\\s,]+/', gs_get_conf('GS_YEALINK_PROV_KEY_BLACKLIST')); +foreach ($key_functions_blacklist as $keyfn) { + if (array_key_exists($keyfn, $key_functions_yealink)) + unset($key_functions_yealink[$keyfn]); +} $key_default = array( @@ -285,6 +335,9 @@ elseif (array_key_exists('snom-710', $phone_types)) $phone_type = 'snom-710'; elseif (array_key_exists('snom-715', $phone_types)) $phone_type = 'snom-715'; elseif (array_key_exists('snom-821', $phone_types)) $phone_type = 'snom-821'; + elseif (array_key_exists('snom-d305', $phone_types)) $phone_type = 'snom-d305'; + elseif (array_key_exists('snom-d315', $phone_types)) $phone_type = 'snom-d315'; + elseif (array_key_exists('snom-d375', $phone_types)) $phone_type = 'snom-d375'; } else if (gs_get_conf('GS_SIEMENS_PROV_ENABLED')) { if (array_key_exists('siemens-os20', $phone_types)) $phone_type = 'siemens-os20'; @@ -307,8 +360,16 @@ if (array_key_exists('tiptel-ip284', $phone_types)) $phone_type = 'tiptel-ip284'; elseif (array_key_exists('tiptel-ip286', $phone_types)) $phone_type = 'tiptel-ip286'; } + if (gs_get_conf('GS_YEALINK_PROV_ENABLED')) { + if (array_key_exists('yealink-sip-t42g', $phone_types)) $phone_type = 'yealink-sip-t42g'; + elseif (array_key_exists('yealink-sip-t46g', $phone_types)) $phone_type = 'yealink-sip-t46g'; + elseif (array_key_exists('yealink-sip-t48g', $phone_types)) $phone_type = 'yealink-sip-t48g'; + elseif (array_key_exists('yealink-sip-t42s', $phone_types)) $phone_type = 'yealink-sip-t42s'; + elseif (array_key_exists('yealink-sip-t46s', $phone_types)) $phone_type = 'yealink-sip-t46s'; + elseif (array_key_exists('yealink-sip-t46u', $phone_types)) $phone_type = 'yealink-sip-t46u'; + } } -if (in_array($phone_type, array('snom-300', 'snom-320', 'snom-360', 'snom-370', 'snom-870', 'snom-760', 'snom-720', 'snom-725', 'snom-710', 'snom-715', 'snom-821'), true)) { +if (in_array($phone_type, array('snom-300', 'snom-320', 'snom-360', 'snom-370', 'snom-870', 'snom-760', 'snom-720', 'snom-725', 'snom-710', 'snom-715', 'snom-821', 'snom-d305', 'snom-d315', 'snom-d375'), true)) { $phone_layout = 'snom'; $key_function_none = $key_function_none_snom; } elseif (in_array($phone_type, array('siemens-os20', 'siemens-os40', 'siemens-os60', 'siemens-os80'), true)) { @@ -323,6 +384,9 @@ } elseif (in_array($phone_type, array('tiptel-ip284', 'tiptel-ip286'), true)) { $phone_layout = 'tiptel'; $key_function_none = $key_function_none_tiptel; +} elseif (in_array($phone_type, array('yealink-sip-t42g', 'yealink-sip-t46g', 'yealink-sip-t48g', 'yealink-sip-t42s', 'yealink-sip-t46s', 'yealink-sip-t46u'), true)) { + $phone_layout = 'yealink'; + $key_function_none = $key_function_none_yealink; } else { $phone_layout = false; $key_function_none = false; @@ -1035,6 +1099,16 @@ function gs_dlg_abort() //$key_levels[0]['to' ] = 15; break; } + switch ($phone_type) { + case 'snom-d305': + case 'snom-d315': + $key_levels = array( + 0 => array('from'> 0, + 'to' => 1, 'shifted'=>false, + 'title' => htmlEnt($phone_type_title)) + ); + break; + } break; case 'siemens': //if ($show_ext_modules >= 0) { @@ -1264,6 +1338,127 @@ function gs_dlg_abort() 'title'=> __('Erweiterungs-Modul') .' 3 '. __('Spalte') .' 2') ); } + break; + case 'yealink': + switch($phone_type) { + case 'yealink-sip-t46g': + $key_levels = array( + 0 => array('from'=> 1, 'to'=> 27, 'shifted'=>false, + 'title'=> htmlEnt($phone_type_title)) + ); + break; + case 'yealink-sip-t46s': + $key_levels = array( + 0 => array('from'=> 1, 'to'=> 27, 'shifted'=>false, + 'title'=> htmlEnt($phone_type_title)) + ); + break; + case 'yealink-sip-t46u': + $key_levels = array( + 0 => array('from'=> 1, 'to'=> 27, 'shifted'=>false, + 'title'=> htmlEnt($phone_type_title)) + ); + break; + case 'yealink-sip-t48g': + $key_levels = array( + 0 => array('from'=> 1, 'to'=> 29, 'shifted'=>false, + 'title'=> htmlEnt($phone_type_title)) + ); + break; + case 'yealink-sip-t42g': + $show_ext_modules=0; + $key_levels = array( + 0 => array('from'=> 1, 'to'=> 15, 'shifted'=>false, + 'title'=> htmlEnt($phone_type_title)) + ); + break; + case 'yealink-sip-t42s': + $show_ext_modules=0; + $key_levels = array( + 0 => array('from'=> 1, 'to'=> 15, 'shifted'=>false, + 'title'=> htmlEnt($phone_type_title)) + ); + break; + } + // EXT43 with 3 layers + if ($phone_type == 'yealink-sip-t46u') { + if ($show_ext_modules >= 1) { + $key_levels += array( + 1 => array('from'=> 101, 'to'=> 120, 'shifted'=>false, + 'title'=> __('Erweiterungs-Modul') .' 1 '. __('Ebene') .' 1') + ); + $key_levels += array( + 2 => array('from'=> 121, 'to'=> 140, 'shifted'=>false, + 'title'=> __('Erweiterungs-Modul') .' 1 '. __('Ebene') .' 2') + ); + $key_levels += array( + 3 => array('from'=> 141, 'to'=> 160, 'shifted'=>false, + 'title'=> __('Erweiterungs-Modul') .' 1 '. __('Ebene') .' 3') + ); + } + if ($show_ext_modules >= 2) { + $key_levels += array( + 4 => array('from'=> 201, 'to'=> 220, 'shifted'=>false, + 'title'=> __('Erweiterungs-Modul') .' 2 '. __('Ebene') .' 1') + ); + $key_levels += array( + 5 => array('from'=> 221, 'to'=> 240, 'shifted'=>false, + 'title'=> __('Erweiterungs-Modul') .' 2 '. __('Ebene') .' 2') + ); + $key_levels += array( + 6 => array('from'=> 241, 'to'=> 260, 'shifted'=>false, + 'title'=> __('Erweiterungs-Modul') .' 2 '. __('Ebene') .' 3') + ); + } + if ($show_ext_modules >= 3) { + $key_levels += array( + 7 => array('from'=> 301, 'to'=> 320, 'shifted'=>false, + 'title'=> __('Erweiterungs-Modul') .' 3 '. __('Ebene') .' 1') + ); + $key_levels += array( + 8 => array('from'=> 321, 'to'=> 340, 'shifted'=>false, + 'title'=> __('Erweiterungs-Modul') .' 3 '. __('Ebene') .' 2') + ); + $key_levels += array( + 9 => array('from'=> 341, 'to'=> 360, 'shifted'=>false, + 'title'=> __('Erweiterungs-Modul') .' 3 '. __('Ebene') .' 3') + ); + } + } + // EXT40 with 2 layers + else { + if ($show_ext_modules >= 1) { + $key_levels += array( + 1 => array('from'=> 101, 'to'=> 120, 'shifted'=>false, + 'title'=> __('Erweiterungs-Modul') .' 1 '. __('Ebene') .' 1') + ); + $key_levels += array( + 2 => array('from'=> 121, 'to'=> 140, 'shifted'=>false, + 'title'=> __('Erweiterungs-Modul') .' 1 '. __('Ebene') .' 2') + ); + } + if ($show_ext_modules >= 2) { + $key_levels += array( + 3 => array('from'=> 201, 'to'=> 220, 'shifted'=>false, + 'title'=> __('Erweiterungs-Modul') .' 2 '. __('Ebene') .' 1') + ); + $key_levels += array( + 4 => array('from'=> 221, 'to'=> 240, 'shifted'=>false, + 'title'=> __('Erweiterungs-Modul') .' 2 '. __('Ebene') .' 2') + ); + } + if ($show_ext_modules >= 3) { + $key_levels += array( + 5 => array('from'=> 301, 'to'=> 320, 'shifted'=>false, + 'title'=> __('Erweiterungs-Modul') .' 3 '. __('Ebene') .' 1') + ); + $key_levels += array( + 6 => array('from'=> 321, 'to'=> 340, 'shifted'=>false, + 'title'=> __('Erweiterungs-Modul') .' 3 '. __('Ebene') .' 2') + ); + } + } + break; } @@ -1331,6 +1526,10 @@ function gs_dlg_abort() switch ($key_level_idx) { case 0: $left = 0; $right = 11; break; } + case ('snom-d305' || 'snom-d315'): + switch ($key_level_idx) { + case 0: $left = 0; $right = 1; break; + } default: switch ($key_level_idx) { case 0: $left = 0; $right = 6; break; @@ -1345,7 +1544,7 @@ function gs_dlg_abort() for ($i=$key_level_info['from']; $i<=$key_level_info['to']; ++$i) { if ($phone_layout === 'snom') { - if ($phone_type === 'snom-760' || $phone_type === 'snom-870' || $phone_type == 'snom-720' || $phone_type == 'snom-725' || $phone_type == 'snom-710' || $phone_type == 'snom-715' || $phone_type == 'snom-821') { + if ($phone_type === 'snom-760' || $phone_type === 'snom-870' || $phone_type == 'snom-720' || $phone_type == 'snom-725' || $phone_type == 'snom-710' || $phone_type == 'snom-715' || $phone_type == 'snom-821' || $phone_type == 'snom-d305' || $phone_type == 'snom-d315') { $knum = $i; $knump = str_pad($knum, 3, '0', STR_PAD_LEFT); }else { @@ -1435,7 +1634,7 @@ function gs_dlg_abort() echo ' $title) { //if ($can_write || $function === $key['function']) { diff --git a/opt/gemeinschaft/htdocs/gui/mod/prov_phones.php b/opt/gemeinschaft/htdocs/gui/mod/prov_phones.php index 00d180f2c..53d2614b8 100644 --- a/opt/gemeinschaft/htdocs/gui/mod/prov_phones.php +++ b/opt/gemeinschaft/htdocs/gui/mod/prov_phones.php @@ -59,6 +59,9 @@ function _mac_addr_display( $mac ) $phone_types['snom-870' ] = 'Snom 870'; $phone_types['snom-760' ] = 'Snom 760'; $phone_types['snom-720' ] = 'Snom 720'; + $phone_types['snom-d305' ] = 'Snom D305'; + $phone_types['snom-d315' ] = 'Snom D315'; + $phone_types['snom-d375' ] = 'Snom D375'; } if (gs_get_conf('GS_SNOM_PROV_M3_ACCOUNTS')) { $phone_types['snom-m3' ] = 'Snom M3'; @@ -100,6 +103,14 @@ function _mac_addr_display( $mac ) $phone_types['tiptel-ip284' ] = 'Tiptel IP 284'; $phone_types['tiptel-ip286' ] = 'Tiptel IP 286'; } +if (gs_get_conf('GS_YEALINK_PROV_ENABLED')) { + $phone_types['yealink-sip-t42g' ] = 'Yealink SIP T42G'; + $phone_types['yealink-sip-t46g' ] = 'Yealink SIP T46G'; + $phone_types['yealink-sip-t48g' ] = 'Yealink SIP T48G'; + $phone_types['yealink-sip-t42s' ] = 'Yealink SIP T42S'; + $phone_types['yealink-sip-t46s' ] = 'Yealink SIP T46S'; + $phone_types['yealink-sip-t46u' ] = 'Yealink SIP T46U'; +} if (gs_get_conf('GS_POLYCOM_PROV_ENABLED')) { $phone_types['polycom-spip-300'] = 'Polycom SoundPoint IP 300'; $phone_types['polycom-spip-500'] = 'Polycom SoundPoint IP 500'; diff --git a/opt/gemeinschaft/htdocs/gui/mod/prov_provparams.php b/opt/gemeinschaft/htdocs/gui/mod/prov_provparams.php index 58be1fa42..904bbd03e 100644 --- a/opt/gemeinschaft/htdocs/gui/mod/prov_provparams.php +++ b/opt/gemeinschaft/htdocs/gui/mod/prov_provparams.php @@ -65,6 +65,14 @@ $phone_types['aastra-55i'] = 'Aastra 55i'; $phone_types['aastra-57i'] = 'Aastra 57i'; } +if (gs_get_conf('GS_YEALINK_PROV_ENABLED')) { + $phone_types['yealink-sip-t42g' ] = 'Yealink SIP T42G'; + $phone_types['yealink-sip-t46g' ] = 'Yealink SIP T46G'; + $phone_types['yealink-sip-t48g' ] = 'Yealink SIP T48G'; + $phone_types['yealink-sip-t42s' ] = 'Yealink SIP T42S'; + $phone_types['yealink-sip-t46s' ] = 'Yealink SIP T46S'; + $phone_types['yealink-sip-t46u' ] = 'Yealink SIP T46U'; +} if (gs_get_conf('GS_GRANDSTREAM_PROV_ENABLED')) { $phone_types['grandstream-ht287' ] = 'Grandstream HT 287'; $phone_types['grandstream-bt110' ] = 'Grandstream BT 110'; diff --git a/opt/gemeinschaft/htdocs/gui/mod/routing_gws-iax.php b/opt/gemeinschaft/htdocs/gui/mod/routing_gws-iax.php index fddd1fc5b..03eadc247 100644 --- a/opt/gemeinschaft/htdocs/gui/mod/routing_gws-iax.php +++ b/opt/gemeinschaft/htdocs/gui/mod/routing_gws-iax.php @@ -447,6 +447,7 @@ function confirm_delete() { echo '', __('Codecs') ,':',"\n"; echo '',"\n"; $codecs = array( + 'g722' => 'G.722', 'alaw' => 'G.711a', 'ulaw' => 'G.711u', 'gsm' => 'GSM' @@ -456,7 +457,7 @@ function confirm_delete() { echo '',"\n"; - echo '',"\n"; + echo '
',"\n"; } echo '   (', htmlEnt(__('Standard')) ,': ', htmlEnt('G.711a') ,')',"\n"; echo '',"\n"; diff --git a/opt/gemeinschaft/htdocs/gui/mod/routing_gws-sip.php b/opt/gemeinschaft/htdocs/gui/mod/routing_gws-sip.php index f09a6f983..61590cf45 100644 --- a/opt/gemeinschaft/htdocs/gui/mod/routing_gws-sip.php +++ b/opt/gemeinschaft/htdocs/gui/mod/routing_gws-sip.php @@ -457,6 +457,7 @@ function confirm_delete() { echo '', __('Codecs') ,':',"\n"; echo '',"\n"; $codecs = array( + 'g722' => 'G.722', 'alaw' => 'G.711a', 'ulaw' => 'G.711u', 'gsm' => 'GSM', @@ -469,7 +470,7 @@ function confirm_delete() { echo '',"\n"; - echo '',"\n"; + echo '
',"\n"; } echo '   (', htmlEnt(__('Standard')) ,': ', htmlEnt('G.711a') ,')',"\n"; echo '',"\n"; diff --git a/opt/gemeinschaft/htdocs/prov/snom/settings.php b/opt/gemeinschaft/htdocs/prov/snom/settings.php index 1fc3f36b8..4901c9b4f 100644 --- a/opt/gemeinschaft/htdocs/prov/snom/settings.php +++ b/opt/gemeinschaft/htdocs/prov/snom/settings.php @@ -121,7 +121,7 @@ function _settings_err( $msg='' ) $ua = trim( @$_SERVER['HTTP_USER_AGENT'] ); if (! preg_match('/^Mozilla/i', $ua) -|| ! preg_match('/snom[0-9]{3}/i', $ua) ) { +|| ! preg_match('/snomd?[0-9]{3}/i', $ua) ) { gs_log( GS_LOG_WARNING, "Phone with MAC \"$mac\" (Snom) has invalid User-Agent (\"". $ua ."\")" ); # don't explain this to the users _settings_err( 'No! See log for details.' ); @@ -134,15 +134,15 @@ function _settings_err( $msg='' ) # user-agents: # 360: "Mozilla/4.0 (compatible; snom360-SIP 6.5.2; snom360 ramdisk v3.31; snom360 linux 3.25)" # 370: "Mozilla/4.0 (compatible; snom370-SIP 7.1.2)" -if (preg_match('/snom([1-9][0-9]{2})/i', $ua, $m)) # e.g. "snom360" - $phone_model = $m[1]; +if (preg_match('/snom(d?[1-9][0-9]{2})/i', $ua, $m)) # e.g. "snom360" + $phone_model = strtolower($m[1]); else $phone_model = 'unknown'; $phone_type = 'snom-'.$phone_model; # e.g. "snom-360" # to be used when auto-adding the phone -$fw_vers = (preg_match('/snom[0-9]{3}-SIP\s+(\d+\.\d+\.\d+)/', $ua, $m)) +$fw_vers = (preg_match('/snomd?[0-9]{3}-SIP\s+(\d+\.(\d+\.){1,3}\d+)/i', $ua, $m)) ? $m[1] : '0.0.0'; $fw_vers_nrml = _snom_normalize_version( $fw_vers ); @@ -725,8 +725,8 @@ function _settings_out() } } psetting('dnd_mode' , $dnd_mode, true); -psetting('dnd_on_code' , 'dnd-on'); -psetting('dnd_off_code' , 'dnd-off'); +psetting('dnd_on_code' , 'dnd-on@'. $host); +psetting('dnd_off_code' , 'dnd-off@'. $host); psetting('preselection_nr' , ''); @@ -964,6 +964,17 @@ function _settings_out() setting('fkey', 4, 'keyevent F_TRANSFER', array('context'=>'active')); setting('fkey', 5, 'keyevent F_MUTE', array('context'=>'active')); } +if ($phone_model == 'd305' || $phone_model == 'd315') { + psetting('status_msgs_that_are_blocked', ''); + psetting('dkey_fkey1', 'url '. $prov_url_snom .'dial-log.php?user=$user_name1', array('context'=>'active')); + psetting('dkey_fkey2', 'url '. $prov_url_snom .'pb.php?m=$mac&u=$user_name1', array('context'=>'active')); + psetting('gui_fkey1', 'keyevent F_CALL_LIST'); + psetting('gui_fkey2', 'keyevent F_ADR_BOOK'); + psetting('gui_fkey3', 'keyevent F_SETTINGS'); + setting('fkey', 2, 'url '. $prov_url_snom .'pb.php?m=$mac&u=$user_name1', array('context'=>'active')); + setting('fkey', 3, 'keyevent F_TRANSFER', array('context'=>'active')); + setting('fkey', 4, 'keyevent F_MUTE', array('context'=>'active')); +} if (($phone_model == '710') || ($phone_model == '715')) { psetting('dkey_fkey1', 'url '. $prov_url_snom .'dial-log.php?user=$user_name1', array('context'=>'active')); psetting('dkey_fkey2', 'url '. $prov_url_snom .'pb.php?m=$mac&u=$user_name1', array('context'=>'active')); diff --git a/opt/gemeinschaft/htdocs/prov/tiptel/settings.php b/opt/gemeinschaft/htdocs/prov/tiptel/settings.php index 78f1976a8..6ab296f6d 100644 --- a/opt/gemeinschaft/htdocs/prov/tiptel/settings.php +++ b/opt/gemeinschaft/htdocs/prov/tiptel/settings.php @@ -89,6 +89,8 @@ function _settings_err( $msg='' ) if (! gs_get_conf('GS_TIPTEL_PROV_ENABLED')) { gs_log( GS_LOG_DEBUG, "Tiptel provisioning not enabled" ); _settings_err( 'Not enabled.' ); +} else { + gs_log( GS_LOG_DEBUG, "Tiptel provisioning enabled" ); } diff --git a/opt/gemeinschaft/htdocs/prov/yealink/.htaccess b/opt/gemeinschaft/htdocs/prov/yealink/.htaccess new file mode 100644 index 000000000..25444214d --- /dev/null +++ b/opt/gemeinschaft/htdocs/prov/yealink/.htaccess @@ -0,0 +1,28 @@ +# Gemeinschaft +# $Revision: 1 $ + +# Provisioning for Tiptel / Yealink *requires* mod_rewrite in order to work! + + + RewriteEngine on + + # The phone asks for + # C.cfg + + # Rewrite requests for .txt + # xx.72 Firmware requests 001565xxxxxxC.cfg + RewriteRule ^(001565[0-9a-f]*)C.cfg$ settings.php?mac=$1 [L] + + # xx.73 Firmware requests 001565xxxxxx.cfg + RewriteRule ^(001565[0-9a-f]*).cfg$ settings.php?mac=$1 [L] + + # newer Yealink phones have 805ec0xxxxxx.cfg + RewriteRule ^(805ec0[0-9a-f]*).cfg$ settings.php?mac=$1 [L] + + # even newer Yealink phones have 805e0cxxxxxx.cfg + RewriteRule ^(805e0c[0-9a-f]*).cfg$ settings.php?mac=$1 [L] + + # PB + # RewriteRule ^pb.([0-9]*).(imported|prv|gs).([0-9]*).xml$ pb.php?u=$1&t=$2&p=$3 [L] + + diff --git a/opt/gemeinschaft/htdocs/prov/yealink/dial-log.php b/opt/gemeinschaft/htdocs/prov/yealink/dial-log.php new file mode 100644 index 000000000..cbac12a33 --- /dev/null +++ b/opt/gemeinschaft/htdocs/prov/yealink/dial-log.php @@ -0,0 +1,234 @@ + +* +* based on Snom by +* Stefan Wintermeyer +* Philipp Kempgen +* Peter Kozak +* +* 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., 51 Franklin Street, Fifth Floor, Boston, +* MA 02110-1301, USA. +\*******************************************************************/ + +# caution: earlier versions of Snom firmware do not like +# indented XML + +define( 'GS_VALID', true ); /// this is a parent file +require_once( dirName(__FILE__) .'/../../../inc/conf.php' ); +include_once( GS_DIR .'inc/db_connect.php' ); +include_once( GS_DIR .'inc/gettext.php' ); +include_once( GS_DIR .'inc/langhelper.php' ); +require_once( GS_DIR .'inc/string.php' ); + +header( 'Expires: 0' ); +header( 'Pragma: no-cache' ); +header( 'Cache-Control: private, no-cache, must-revalidate' ); +header( 'Vary: *' ); + +function yealinkXmlEsc( $str ) +{ + return htmlEnt( $str ); +} + +function _ob_send() +{ + if (! headers_sent()) { + header( 'Content-Type: application/xml' ); + header( 'Content-Length: '. (int)@ob_get_length() ); + } + @ob_end_flush(); + die(); +} + +function _err( $msg='' ) +{ + @ob_end_clean(); + ob_start(); + echo + '', "\n", + '', "\n", + '', __('Fehler'), '', "\n", + '', yealinkXmlEsc( __('Fehler') .': '. $msg ), '', "\n", + '', "\n"; + _ob_send(); +} + + +if (! gs_get_conf('GS_YEALINK_PROV_ENABLED')) { + gs_log( GS_LOG_DEBUG, "Yealink provisioning not enabled" ); + _err( 'Not enabled.' ); +} + + +$user = trim( @ $_REQUEST['user'] ); +if (! preg_match('/^\d+$/', $user)) + _err( 'Not a valid SIP user.' ); + +$mac = preg_replace('/[^\dA-Z]/', '', strToUpper(trim( @$_REQUEST['mac'] ))); + +$type = trim( @ $_REQUEST['type'] ); +if (! in_array( $type, array('in','out','missed','queue'), true )) + $type = false; + +$db = gs_db_slave_connect(); + +# get user_id +# +$user_id = (int)$db->executeGetOne( 'SELECT `_user_id` FROM `ast_sipfriends` WHERE `name`=\''. $db->escape($user) .'\'' ); +if ($user_id < 1) + _err( 'Unknown user.' ); + + +$remote_addr = @$_SERVER['REMOTE_ADDR']; +$remote_addr_check = $db->executeGetOne( 'SELECT `current_ip` FROM `users` WHERE `id`='. $user_id ); +if ($remote_addr != $remote_addr_check) _err( 'Not authorized' ); + +unset($remote_addr_check); +unset($remote_addr); +unset($user_id_check); + +// setup i18n stuff +gs_setlang( gs_get_lang_user($db, $user, GS_LANG_FORMAT_GS) ); +gs_loadtextdomain( 'gemeinschaft-gui' ); +gs_settextdomain( 'gemeinschaft-gui' ); + +$typeToTitle = array( + 'out' => __("Gew\xC3\xA4hlt"), + 'missed' => __("Verpasst"), + 'in' => __("Angenommen"), + 'queue' => __("Warteschlangen") +); + +ob_start(); + + +$url_yealink_dl = GS_PROV_SCHEME .'://'. GS_PROV_HOST . (GS_PROV_PORT ? ':'.GS_PROV_PORT : '') . GS_PROV_PATH .'yealink/dial-log.php'; + +#################################### INITIAL SCREEN { +if (! $type) { + + # delete outdated entries + # + $db->execute( 'DELETE FROM `dial_log` WHERE `user_id`='. $user_id .' AND `timestamp`<'. (time()-(int)GS_PROV_DIAL_LOG_LIFE) ); + + + + echo '', "\n"; + echo + '', "\n", + '', __('Anruflisten') ,'', "\n"; + + foreach ($typeToTitle as $t => $title) { + + $num_calls = (int)$db->executeGetOne( 'SELECT COUNT(*) FROM `dial_log` WHERE `user_id`='. $user_id .' AND `type`=\''. $t .'\'' ); + //if ($num_calls > 0) { + echo + "\n", + '', "\n", + '', yealinkXmlEsc( $title ) ,'', "\n", + '', $url_yealink_dl ,'?user=',$user, '&mac=',$mac, '&type=',$t, '', "\n", + '', "\n"; + //} + } + + echo + "\n", + ''; + +} +#################################### INITIAL SCREEN } + + + +#################################### DIAL LOG { +else { + + echo '', "\n"; + if ($type === 'queue'){ + $query = + 'SELECT + `timestamp` `ts`, `number`, `remote_name`, `remote_user_id` + FROM `dial_log` + WHERE + `user_id`='. $user_id .' AND + `type`=\''. $type .'\' + ORDER BY `ts` DESC + LIMIT 20'; + } else { + $query = + 'SELECT + MAX(`timestamp`) `ts`, `number`, `remote_name`, `remote_user_id`, + COUNT(*) `num_calls` + FROM `dial_log` + WHERE + `user_id`='. $user_id .' AND + `type`=\''. $type .'\' + GROUP BY `number` + ORDER BY `ts` DESC + LIMIT 20'; + } + $rs = $db->execute( $query ); + + echo + '', + '', yealinkXmlEsc( $typeToTitle[$type] ) , + ($rs->numRows() == 0 ? ' ('.yealinkXmlEsc(__('keine')).')' : '') , + '', "\n"; + + while ($r = $rs->fetchRow()) { + + $entry_name = $r['number']; + if ($r['remote_name'] != '') { + $entry_name .= ' '. $r['remote_name']; + } + if (date('dm') == date('dm', (int)$r['ts'])) + $when = date('H:i', (int)$r['ts']); + else + $when = date('d.m.', (int)$r['ts']); + $entry_name = $when .' '. $entry_name; + if ($r['num_calls'] > 1) { + $entry_name .= ' ('. $r['num_calls'] .')'; + } + echo + "\n", + '', "\n", + '', yealinkXmlEsc( $entry_name ) ,'', "\n", + '', yealinkXmlEsc( $r['number'] ) ,'', "\n", + '', "\n"; + + } + + echo + "\n", + ''; + +} +#################################### DIAL LOG } + + +_ob_send(); + +?> diff --git a/opt/gemeinschaft/htdocs/prov/yealink/fw/readme_firmware.txt b/opt/gemeinschaft/htdocs/prov/yealink/fw/readme_firmware.txt new file mode 100644 index 000000000..e551a374b --- /dev/null +++ b/opt/gemeinschaft/htdocs/prov/yealink/fw/readme_firmware.txt @@ -0,0 +1,5 @@ +Place Yealink firmware images in this folder. + +Use filename format "aa.bb.cc.dd.rom", e.g. "28.80.00.95.rom" for T46G and +"35.80.00.95.rom" for T48G. + diff --git a/opt/gemeinschaft/htdocs/prov/yealink/pb_on_phone.php b/opt/gemeinschaft/htdocs/prov/yealink/pb_on_phone.php new file mode 100644 index 000000000..4db131806 --- /dev/null +++ b/opt/gemeinschaft/htdocs/prov/yealink/pb_on_phone.php @@ -0,0 +1,183 @@ + +* +* based on Tiptel by +* Sebastian Ertz +* +* 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., 51 Franklin Street, Fifth Floor, Boston, +* MA 02110-1301, USA. +\*******************************************************************/ + +define( 'GS_VALID', true ); /// this is a parent file + +require_once( dirName(__FILE__) .'/../../../inc/conf.php' ); +//require_once( GS_DIR .'inc/util.php' ); +//require_once( GS_DIR .'inc/gs-lib.php' ); +require_once( GS_DIR .'inc/prov-fns.php' ); +set_error_handler('err_handler_die_on_err'); +require_once( GS_DIR .'inc/string.php' ); +require_once( GS_DIR .'inc/db_connect.php' ); +include_once( GS_DIR .'inc/group-fns.php' ); + +header( 'Expires: 0' ); +header( 'Pragma: no-cache' ); +header( 'Cache-Control: private, no-cache, must-revalidate' ); +header( 'Vary: *' ); + + +function yealinkXmlEsc( $str ) +{ + return htmlEnt( $str ); +} + +function _err( $msg='' ) +{ + @ob_end_clean(); + @ob_start(); + echo '',"\n"; + if (! headers_sent()) { + header( 'Content-Type: text/plain; charset=utf-8' ); + header( 'Content-Length: '. (int)@ob_get_length() ); + } + @ob_end_flush(); + exit(1); +} + +function getUserID( $ext ) +{ + global $db; + + if (! preg_match('/^\d+$/', $ext)) + _err( 'Invalid username' ); + + $user_id = (int)$db->executeGetOne( 'SELECT `_user_id` FROM `ast_sipfriends` WHERE `name`=\''. $db->escape($ext) .'\'' ); + if ($user_id < 1) + _err( 'Unknown user' ); + return $user_id; +} + +if (! gs_get_conf('GS_YEALINK_PROV_ENABLED')) { + gs_log( GS_LOG_DEBUG, "Yealink provisioning not enabled" ); + _err( 'Not enabled' ); +} + + +$type = trim( @$_REQUEST['t'] ); +if (! in_array( $type, array('gs','prv','imported'), true )) { + _err( 'Not allowed' ); +} + + +$mac = strToUpper(trim( @$_REQUEST['m'] )); + +//FIXME - we need authentication here + +$requester = gs_prov_check_trust_requester(); +if (! $requester['allowed']) { + _err( 'No! See log for details.' ); +} + +# connect to db +$db = gs_db_slave_connect(); +if (! $db) { + gs_log( GS_LOG_WARNING, "Phone with MAC \"$mac\" (Yealink) ask for phonebook - Could not connect to DB" ); + _err( 'No! See log for details.' ); +} + + +# get user_id +$user = trim( @$_REQUEST['u'] ); +$user_id = getUserID( $user ); + + +if ($type === 'gs') { # INTERNAL phonebook + $user_groups = gs_group_members_groups_get(array($user_id), 'user'); + $permission_groups = gs_group_permissions_get($user_groups, 'phonebook_user'); + $group_members = gs_group_members_get($permission_groups); + + $pb = array( + 'type' => 'gs', + 'title' => gs_get_conf('GS_PB_INTERNAL_TITLE', __("Intern")), + 'query' => 'SELECT `u`.`lastname` `ln`, `u`.`firstname` `fn`, `s`.`name` `ext` + FROM + `users` `u` JOIN + `ast_sipfriends` `s` ON (`s`.`_user_id`=`u`.`id`) + WHERE + `u`.`id` IN ('.implode(',', $group_members).') AND + `u`.`id`!='.$user_id.' + ORDER BY `u`.`lastname`, `u`.`firstname`' + ); +} +elseif ($type ==='prv') { # PRIVATE phonebook + $pb = array( + 'type' => 'prv', + 'title' => gs_get_conf('GS_PB_PRIVATE_TITLE', __("Pers\xC3\xB6nlich")), + 'query' => 'SELECT `pb`.`lastname` `ln`, `pb`.`firstname` `fn`, `pb`.`number` `ext` + FROM + `pb_prv` `pb` + WHERE `pb`.`user_id`='.$user_id.' + ORDER BY `pb`.`lastname`, `pb`.`firstname`' + ); +} +elseif ($type === 'imported') { # IMPORTED phonebook + if (! gs_get_conf('GS_PB_IMPORTED_ENABLED')) + _err( 'Not allowed' ); + + $pb = array( + 'type' => 'imported', + 'title' => gs_get_conf('GS_PB_IMPORTED_TITLE', __("Extern")), + 'query' => 'SELECT `lastname` `ln`, `firstname` `fn`, `number` `ext` + FROM `pb_ldap` + ORDER BY `lastname`, `firstname`' + ); +} + + +ob_start(); + +echo '' ,"\n"; +echo '' ,"\n"; + +$rs = $db->execute( $pb['query'] ); + +if ( $rs && $rs->numRows() !== 0 ) { + while ($r = $rs->fetchRow()) { + $lastname = $r['ln']; + $firstname = $r['fn']; + $number = $r['ext']; + + echo '' , + ''. yealinkXmlEsc($lastname) .', '. yealinkXmlEsc($firstname) . '', + ''. yealinkXmlEsc($number). "", + '' ,"\n"; + } +} + +echo '' ,"\n"; + +if (! headers_sent()) { + header( 'Content-Type: application/xml' ); + header( 'Content-Length: '. (int)@ob_get_length() ); +} +@ob_end_flush(); + +?> diff --git a/opt/gemeinschaft/htdocs/prov/yealink/readme_dhcp.txt b/opt/gemeinschaft/htdocs/prov/yealink/readme_dhcp.txt new file mode 100644 index 000000000..5f98db5f1 --- /dev/null +++ b/opt/gemeinschaft/htdocs/prov/yealink/readme_dhcp.txt @@ -0,0 +1,36 @@ +Sample DHCP Server Config (edit IPs to fit your needs): + + + +subnet 192.168.x.0 netmask 255.255.255.0 { + range 192.168.x.100 192.168.x.150; + + # Snom-Phones, MAC starts with 00:04:13 + if binary-to-ascii(16, 32, "", substring(hardware, 0, 4)) = "1000413" { + log(info, "request from snom phone, setting proper options."); + # GS3 + option tftp-server-name "http://192.168.x.250"; + option bootfile-name "/gemeinschaft/prov/snom/settings.php?mac={mac}"; + } + + # Yealink-Phones, MAC starts with 00:15:65 + if binary-to-ascii(16, 32, "", substring(hardware, 0, 4)) = "1001565" { + log(info, "request from yealink phone, setting proper options."); + # GS3 + option tftp-server-name "http://192.168.x.250/gemeinschaft/prov/yealink/$MAC.cfg"; + } + # Yealink-Phones, MAC starts with 80:5e:c0 + if binary-to-ascii(16, 32, "", substring(hardware, 0, 4)) = "1805ec0" { + log(info, "request from yealink phone, setting proper options."); + # GS3 + option tftp-server-name "http://192.168.9.1/gemeinschaft/prov/yealink/$MAC.cfg"; + } + # Yealink-Phones, MAC starts with 80:5e:0c + if binary-to-ascii(16, 32, "", substring(hardware, 0, 4)) = "1805e0c" { + log(info, "request from yealink phone, setting proper options."); + # GS3 + option tftp-server-name "http://192.168.9.1/gemeinschaft/prov/yealink/$MAC.cfg"; + } + +} + diff --git a/opt/gemeinschaft/htdocs/prov/yealink/settings.php b/opt/gemeinschaft/htdocs/prov/yealink/settings.php new file mode 100644 index 000000000..37c8bec1e --- /dev/null +++ b/opt/gemeinschaft/htdocs/prov/yealink/settings.php @@ -0,0 +1,1107 @@ + +* Mirco Bartels +* +* based on Tiptel provisioning by +* Sebastian Ertz +* +* 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., 51 Franklin Street, Fifth Floor, Boston, +* MA 02110-1301, USA. +\*******************************************************************/ + +define( 'GS_VALID', true ); /// this is a parent file + +header( 'Expires: 0' ); +header( 'Pragma: no-cache' ); +header( 'Cache-Control: private, no-cache, must-revalidate' ); +header( 'Vary: *' ); + + +require_once( dirName(__FILE__) .'/../../../inc/conf.php' ); +require_once( GS_DIR .'inc/util.php' ); +require_once( GS_DIR .'inc/gs-lib.php' ); +require_once( GS_DIR .'inc/prov-fns.php' ); +require_once( GS_DIR .'inc/quote_shell_arg.php' ); +set_error_handler('err_handler_die_on_err'); + +function _yealink_astlang_to_yealinklang($langcode) +{ + $lang_default = 'German'; + + $lang_transtable = array( + 'de' => 'German', + 'en' => 'English', + 'us' => 'English', + ); + + $lang_ret = $lang_transtable[$langcode]; + if(strlen($lang_ret) == 0) + return $lang_default; + + return $lang_ret; +} + +function _yealink_normalize_version( $fwvers ) +{ + $tmp = explode('.', $fwvers); + $v0 = str_pad((int)@$tmp[0], 2, '0', STR_PAD_LEFT); + $v1 = str_pad((int)@$tmp[1], 2, '0', STR_PAD_LEFT); + $v2 = str_pad((int)@$tmp[2], 2, '0', STR_PAD_LEFT); + $v3 = str_pad((int)@$tmp[3], 2, '0', STR_PAD_LEFT); + return $v0.'.'.$v1.'.'.$v2.'.'.$v3; +} + +function _yealink_fwcmp( $fwvers1, $fwvers2 ) +{ + //$fwvers1 = _yealink_normalize_version( $fwvers1 ); # we trust it has been normalized! + $fwvers2 = _yealink_normalize_version( $fwvers2 ); + return strCmp($fwvers1, $fwvers2); +} + +function _settings_err( $msg='' ) +{ + @ob_end_clean(); + @ob_start(); + echo '# ', ($msg != '' ? $msg : 'Error') ,"\n"; + gs_log( GS_LOG_DEBUG, $msg ); + if (! headers_sent()) { + header( 'Content-Type: text/plain; charset=utf-8' ); + header( 'Content-Length: '. (int)@ob_get_length() ); + } + @ob_end_flush(); + exit(1); +} + +// Tiptel and Yealink share OUI from MAC address. So redirect Tiptel phones to Tiptel provisioning. +function _redirect_tiptel() +{ + $prov_url_tiptel = GS_PROV_SCHEME .'://'. GS_PROV_HOST . (GS_PROV_PORT ? ':'.GS_PROV_PORT : '') . GS_PROV_PATH.'tiptel/'.$_REQUEST['mac'].'.cfg'; + + gs_log( GS_LOG_DEBUG, 'Redirecting to Tiptel Provisoning: '.$prov_url_tiptel ); + + $options = array('http' => array('user_agent' => @$_SERVER['HTTP_USER_AGENT'])); + $context = stream_context_create($options); + $response = file_get_contents($prov_url_tiptel, false, $context); + + ob_start(); + echo $response; + if (! headers_sent()) { + header( 'Content-Type: text/plain; charset=utf-8' ); + header( 'Content-Length: '. (int)@ob_get_length() ); + } + @ob_end_flush(); + exit(1); +} + +if (! gs_get_conf('GS_YEALINK_PROV_ENABLED')) { + gs_log( GS_LOG_DEBUG, "Yealink provisioning not enabled" ); + _settings_err( 'Not enabled.' ); +} + +$requester = gs_prov_check_trust_requester(); +if (! $requester['allowed']) { + _settings_err( 'No! See log for details.' ); +} + +$mac = preg_replace( '/[^0-9A-F]/', '', strToUpper( @$_REQUEST['mac'] ) ); +if (strLen($mac) !== 12) { + gs_log( GS_LOG_NOTICE, "Yealink provisioning: Invalid MAC address \"$mac\" (wrong length)" ); + # don't explain this to the users + _settings_err( 'No! See log for details.' ); +} +if (hexDec(subStr($mac,0,2)) % 2 == 1) { + gs_log( GS_LOG_NOTICE, "Yealink provisioning: Invalid MAC address \"$mac\" (multicast address)" ); + # don't explain this to the users + _settings_err( 'No! See log for details.' ); +} +if ($mac === '000000000000') { + gs_log( GS_LOG_NOTICE, "Yealink provisioning: Invalid MAC address \"$mac\" (huh?)" ); + # don't explain this to the users + _settings_err( 'No! See log for details.' ); +} + +# make sure the phone is a Yealink: +# +if ((subStr($mac,0,6) !== '001565') && (subStr($mac,0,6) !== '805EC0') && (subStr($mac,0,6) !== '805E0C')) { + gs_log( GS_LOG_NOTICE, "Yealink provisioning: MAC address \"$mac\" is not a Yealink phone" ); + # don't explain this to the users + _settings_err( 'No! See log for details.' ); +} + +# HTTP_USER_AGENTs +# +# e.g. yealink SIP-T46G: "Yealink SIP-T46G 28.72.0.25 00:15:65:5b:53:84" +# +$ua = trim( @$_SERVER['HTTP_USER_AGENT'] ); +$ua_parts = explode(' ', $ua); +# redirect Tiptel phones to Tiptel provisioning +if (strToLower(@$ua_parts[0]) == 'tiptel') { + gs_log( GS_LOG_WARNING, "Phone with MAC \"$mac\" (Tiptel) has invalid User-Agent (\"". $ua ."\"); Redirecting to Tiptel provisioning!" ); + + _redirect_tiptel(); +} +else if (strToLower(@$ua_parts[0]) !== 'yealink') { + gs_log( GS_LOG_WARNING, "Phone with MAC \"$mac\" (Yealink) has invalid User-Agent (\"". $ua ."\")" ); + # don't explain this to the users + _settings_err( 'No! See log for details.' ); +} + +gs_log( GS_LOG_DEBUG, "Yealink model $ua found." ); + +# find out the type of the phone: +if (preg_match('/SIP-(T42G|T46G|T48G|T42S|T46S|T46U)/', @$ua_parts[1], $m)) { # e.g. "SIP-T46G", "SIP-T48G" or "SIP-T22P" + $phone_model = 'SIP-'.$m[1]; + $phone_model_config = 'SIP_'.$m[1]; +} +else + $phone_model = 'unknown'; + +$phone_type = 'yealink-'.strToLower($phone_model); # e.g. "yealink-sip-t46g" or "yealink-sip-t48g" +# to be used when auto-adding the phone + +# find out the firmware version of the phone +$fw_vers = (preg_match('/(\d+\.\d+\.\d+\.\d+)/', @$ua_parts[2], $m)) + ? $m[1] : '0.0.0.0'; + +$fw_vers_nrml = _yealink_normalize_version( $fw_vers ); + +gs_log( GS_LOG_DEBUG, "Yealink phone \"$mac\" asks for settings (UA: ...\"$ua\") - model: $phone_model" ); + +$prov_url_yealink = GS_PROV_SCHEME .'://'. GS_PROV_HOST . (GS_PROV_PORT ? ':'.GS_PROV_PORT : '') . GS_PROV_PATH .'yealink/'; + + +require_once( GS_DIR .'inc/db_connect.php' ); +require_once( GS_DIR .'inc/nobody-extensions.php' ); +include_once( GS_DIR .'inc/gs-fns/gs_callforward_get.php' ); +include_once( GS_DIR .'inc/gs-fns/gs_keys_get.php' ); +include_once( GS_DIR .'inc/gs-fns/gs_prov_params_get.php' ); +include_once( GS_DIR .'inc/gs-fns/gs_user_prov_params_get.php' ); +include_once( GS_DIR .'inc/cron-rule.php' ); + + +$settings = array(); + +function psetting( $param, $val='' ) +{ + global $settings; + + $settings[$param] = $val; +} + +function _settings_out() //TODO Variablen l�schen (warte auf RE von Yealink) +{ + global $settings; + + echo "#!version:1.0.0.1\n"; + + foreach ($settings as $param => $val) { + echo $param .' = '. $val . "\n"; + } +} + + +$db = gs_db_master_connect(); +if (! $db) { + gs_log( GS_LOG_WARNING, "Yealink phone asks for settings - Could not connect to DB" ); + _settings_err( 'Could not connect to DB.' ); +} + +# do we know the phone? +# +$user_id = @gs_prov_user_id_by_mac_addr( $db, $mac ); +if ($user_id < 1) { + if (! GS_PROV_AUTO_ADD_PHONE) { + gs_log( GS_LOG_NOTICE, "New phone $mac not added to DB. Enable PROV_AUTO_ADD_PHONE" ); + _settings_err( 'Unknown phone. (Enable PROV_AUTO_ADD_PHONE in order to auto-add)' ); + } + gs_log( GS_LOG_NOTICE, "Adding new Yealink phone $mac to DB" ); + + $user_id = @gs_prov_add_phone_get_nobody_user_id( $db, $mac, $phone_type, $requester['phone_ip'] ); + if ($user_id < 1) { + gs_log( GS_LOG_WARNING, "Failed to add nobody user for new phone $mac" ); + _settings_err( 'Failed to add nobody user for new phone.' ); + } +} + + +# is it a valid user id? +# +$num = (int)$db->executeGetOne( 'SELECT COUNT(*) FROM `users` WHERE `id`='. $user_id ); +if ($num < 1) + $user_id = 0; + +if ($user_id < 1) { + # something bad happened, nobody (not even a nobody user) is logged + # in at that phone. assign the default nobody user of the phone: + $user_id = @gs_prov_assign_default_nobody( $db, $mac, null ); + if ($user_id < 1) { + _settings_err( 'Failed to assign nobody account to phone '. $mac ); + } +} + + +# get host for user +# +$host = @gs_prov_get_host_for_user_id( $db, $user_id ); +if (! $host) { + _settings_err( 'Failed to find host.' ); +} +$pbx = $host; # $host might be changed if SBC configured + + +# who is logged in at that phone? +# +$user = @gs_prov_get_user_info( $db, $user_id ); +if (! is_array($user)) { + _settings_err( 'DB error.' ); +} + + +# store the current firmware version and type information in the database: +# +@$db->execute( + 'UPDATE `phones` SET '. + '`firmware_cur`=\''. $db->escape($fw_vers_nrml) .'\', '. + '`type`=\''. $db->escape($phone_type) .'\' '. + 'WHERE `mac_addr`=\''. $db->escape($mac) .'\'' + ); + + +# firmware update +# +if (! gs_get_conf('GS_YEALINK_PROV_FW_UPDATE')) { + gs_log( GS_LOG_DEBUG, 'Yealink firmware update not enabled' ); +} else { + # get phone_id + $phone_id = (int)$db->executeGetOne( 'SELECT `id` FROM `phones` WHERE `mac_addr`=\''. $db->escape($mac) .'\'' ); + + # do we have to update to a default version? + # + $fw_was_upgraded_manually = (int)$db->executeGetOne( + 'SELECT `fw_manual_update` '. + 'FROM `phones` '. + 'WHERE `id`='. $phone_id + ); + if ($fw_was_upgraded_manually) { + gs_log( GS_LOG_DEBUG, "Phone $mac: Firmware was upgraded \"manually\". Not scheduling an upgrade." ); + } else { + $fw_default_vers = _yealink_normalize_version(trim(gs_get_conf('GS_YEALINK_PROV_FW_DEFAULT_'.strToUpper($phone_model_config)))); + if (in_array($fw_default_vers, array(null, false,''), true)) { + gs_log( GS_LOG_DEBUG, "Phone $mac: No default firmware set in config file" ); + } elseif (subStr($fw_default_vers,0,2) === '00') { + gs_log( GS_LOG_DEBUG, "Phone $mac: Bad default firmware set in config file: $fw_default_vers" ); + } else { + if ($fw_vers_nrml != $fw_default_vers) { + gs_log( GS_LOG_NOTICE, "Phone $mac: The Firmware version ($fw_vers_nrml) differs from the default version ($fw_default_vers), scheduling an upgrade ..." ); + # simply add a provisioning job to the database. This is done to be clean and we cann trace the job. + $ok = $db->execute( + 'INSERT INTO `prov_jobs` ('. + '`id`, '. + '`inserted`, '. + '`running`, '. + '`trigger`, '. + '`phone_id`, '. + '`type`, '. + '`immediate`, '. + '`minute`, '. + '`hour`, '. + '`day`, '. + '`month`, '. + '`dow`, '. + '`data` '. + ') VALUES ('. + 'NULL, '. + ((int)time()) .', '. + '0, '. + '\'client\', '. + ((int)$phone_id) .', '. + '\'firmware\', '. + '0, '. + '\'*\', '. + '\'*\', '. + '\'*\', '. + '\'*\', '. + '\'*\', '. + '\''. $db->escape($fw_default_vers) .'\''. + ')' + ); + } + } + } + + # check provisioning jobs + # + $rs = $db->execute( + 'SELECT `id`, `running`, `minute`, `hour`, `day`, `month`, `dow`, `data` '. + 'FROM `prov_jobs` '. + 'WHERE `phone_id`='.$phone_id.' AND `type`=\'firmware\' '. + 'ORDER BY `running` DESC, `inserted`' ); + /*if (! $rs) { + gs_log( GS_LOG_WARNING, "DB error" ); + return; + }*/ + while ($job = $rs->fetchRow()) { + if ($job['running']) { + break; + } + + # check cron rule + $c = new CronRule(); + $ok = $c->set_Rule( $job['minute'] .' '. $job['hour'] .' '. $job['day'] .' '. $job['month'] .' '. $job['dow'] ); + if (! $ok) { + gs_log( GS_LOG_WARNING, "Phone $mac: Job ".$job['id']." has a bad cron rule (". $c->errMsg ."). Deleting ..." ); + $db->execute( 'DELETE FROM `prov_jobs` WHERE `id`='.((int)$job['id']).' AND `running`=0' ); + unset($c); + continue; + } + if (! $c->validate_time()) { + gs_log( GS_LOG_DEBUG, "Phone $mac: Job ".$job['id'].": Rule does not match" ); + unset($c); + continue; + } + unset($c); + gs_log( GS_LOG_DEBUG, "Phone $mac: Job ".$job['id'].": Rule match" ); + + $fw_new_vers = _yealink_normalize_version( $job['data'] ); + if (subStr($fw_new_vers,0,2)=='00') { + gs_log( GS_LOG_NOTICE, "Phone $mac: Bad new fw version $fw_new_vers" ); + $db->execute( 'DELETE FROM `prov_jobs` WHERE `id`='.((int)$job['id']).' AND `running`=0' ); + continue; + } + if ( (subStr($fw_new_vers,0,2) != '18' && $phone_model === 'ip28xs') + || (subStr($fw_new_vers,0,2) != '09' && $phone_model === 'ip280') + || (subStr($fw_new_vers,0,2) != '06' && $phone_model === 'ip284') + || (subStr($fw_new_vers,0,2) != '02' && $phone_model === 'ip286') ) { + gs_log( GS_LOG_NOTICE, "Phone $mac: Bad new fw version $fw_new_vers for $phone_model" ); + $db->execute( 'DELETE FROM `prov_jobs` WHERE `id`='.((int)$job['id']).' AND `running`=0' ); + continue; + } + $firmware_path = '/opt/gemeinschaft/htdocs/prov/yealink/fw/'.$fw_new_vers.'.rom'; + if ( ! file_exists($firmware_path) || ! is_readable($firmware_path) ) { + gs_log( GS_LOG_NOTICE, "Phone $mac: ".$firmware_path." not exits or not readable" ); + $db->execute( 'DELETE FROM `prov_jobs` WHERE `id`='.((int)$job['id']).' AND `running`=0' ); + continue; + } + if ( $fw_new_vers == $fw_vers_nrml ) { + gs_log( GS_LOG_NOTICE, "Phone $mac: FW $fw_vers_nrml == $fw_new_vers" ); + $db->execute( 'DELETE FROM `prov_jobs` WHERE `id`='.((int)$job['id']).' AND `running`=0' ); + continue; + } + + gs_log( GS_LOG_NOTICE, "Phone $mac: Upgrade FW $fw_vers_nrml -> $fw_new_vers" ); + + # Configure + ###It configures the access URL of the firmware file. + ###The default value is blank.It takes effect after a reboot. + psetting('firmware.url', $prov_url_yealink.'fw/'.$fw_new_vers.'.rom'); + + break; + } +} + + +# store the user's current IP address in the database: +# +if (! @gs_prov_update_user_ip( $db, $user_id, $requester['phone_ip'] )) { + gs_log( GS_LOG_WARNING, 'Failed to store current IP addr of user ID '. $user_id ); +} + + +# get SIP proxy to be set as the phone's outbound proxy +# +$sip_proxy_and_sbc = gs_prov_get_wan_outbound_proxy( $db, $requester['phone_ip'], $user_id ); +if ($sip_proxy_and_sbc['sip_server_from_wan'] != '') { + $host = $sip_proxy_and_sbc['sip_server_from_wan']; +} + + +# get extension without route prefix +# +if (gs_get_conf('GS_BOI_ENABLED')) { + $hp_route_prefix = (string)$db->executeGetOne( + 'SELECT `value` FROM `host_params` '. + 'WHERE '. + '`host_id`='. (int)$user['host_id'] .' AND '. + '`param`=\'route_prefix\'' + ); + $user_ext = (subStr($user['name'],0,strLen($hp_route_prefix)) === $hp_route_prefix) + ? subStr($user['name'], strLen($hp_route_prefix)) : $user['name']; + gs_log( GS_LOG_DEBUG, "Mapping ext. ". $user['name'] ." to $user_ext for provisioning - route_prefix: $hp_route_prefix, host id: ". $user['host_id'] ); +} else { + $hp_route_prefix = ''; + $user_ext = $user['name']; +} + +# Phonetype Check +if ( in_array($phone_type, array('yealink-sip-t42g','yealink-sip-t46g','yealink-sip-t48g','yealink-sip-t42s','yealink-sip-t46s','yealink-sip-t46u'), true) ) { + + ##################################################################### + # Common provisioning parameters (applicable to SIP-T28P/T26P/T22P/T20P/T21P/T19P/T46G/T42G/T41P IP phones running firmware version 72 or later) + ##################################################################### + + # Language + ##It configures the language of the web user interface. + ##Chinese_S is only applicable to SIP-T19P, SIP-T21P and SIP-T46G IP phones. + ##Chinese_T is only applicable to SIP-T46G IP phones. + ##French, Portuguese and Spanish are not applicable to SIP-T19P and SIP-T21P IP phones. + psetting('lang.wui', 'English'); + ##It configures the language of the phone user interface. + ##Chinese_S and Chinese_T are only applicable to SIP-T19P, SIP-T21P and SIP-T46G IP phones. + ##The default value is English. + psetting('lang.gui', _yealink_astlang_to_yealinklang($user['language'])); + + # Network LLDP enable (for identifying IP phone on LLDP-enabled switches) + psetting('network.lldp.enable', '1'); + psetting('network.lldp.packet_interval', '60'); + + # Remote Phonebook + ###X ranges from 1 to 5 + ###remote_phonebook.data.X.url = + ###remote_phonebook.data.X.name = + + $i=1; + # Intern + psetting('remote_phonebook.data.'.$i.'.url', $prov_url_yealink.'pb_on_phone.php?u='.$user_ext.'&t=gs'); + psetting('remote_phonebook.data.'.$i.'.name', 'Intern'); + $i++; + + if (gs_get_conf('GS_PB_IMPORTED_ENABLED')) { + # Firma + psetting('remote_phonebook.data.'.$i.'.url', $prov_url_yealink.'pb_on_phone.php?u='.$user_ext.'&t=imported'); + psetting('remote_phonebook.data.'.$i.'.name', 'Firma'); + $i++; + }; + + # Personal + psetting('remote_phonebook.data.'.$i.'.url', $prov_url_yealink.'pb_on_phone.php?u='.$user_ext.'&t=prv'); + psetting('remote_phonebook.data.'.$i.'.name', 'Pers�nlich'); + $i++; + + # empty 4 and 5 + psetting('remote_phonebook.data.'.$i.'.url', ''); + psetting('remote_phonebook.data.'.$i.'.name', ''); + $i++; + + psetting('remote_phonebook.data.'.$i.'.url', ''); + psetting('remote_phonebook.data.'.$i.'.name', ''); + + psetting('remote_phonebook.display_name', 'Telefonbuch'); + + ###Super Search recommended by Yealink support + psetting('remote_phonebook.super_search.enable', '1'); + psetting('directory.search_type', '1'); + + + # Show Remote Phonebook on Home Screen + psetting('programablekey.2.type', '47'); + psetting('programablekey.2.line', '1'); + psetting('programablekey.2.value', ''); + psetting('programablekey.2.label', 'Tel.buch'); + + ##It enables or disables the phone to perform a remote phone book search when receiving an incoming call. + ##0-Disabled,1-Enabled. + ##The default value is 0. + psetting('features.remote_phonebook.enable', '1'); + ##It enables or disables the phone to perform a remote phone book search when accessing. + ##0-Disabled,1-Enabled. + ##The default value is 0. + psetting('features.remote_phonebook.enter_update_enable', '1'); + ##It configures the interval (in seconds) for the phone to update the data of the remote phone book from the remote phone book server. + ##The default value is 21600.Integer from 3600 to 2592000. + psetting('features.remote_phonebook.flash_time', '3600'); + + # Ringtone + # exp.: tftp://192.168.1.100/Ring9.wav + # http://192.168.178.26/gemeinschaft/prov/ringtones/admin-int-fgz-tiptel.wav + #psetting('ringtone.url', 'http://192.168.178.26/gemeinschaft/prov/ringtones/admin-int-fgz-tiptel.wav'); + #psetting('ringtone.delete', ''); + #Delete all the custom ringtones uploaded through auto provisioning + #psetting('ringtone.delete', 'http://localhost/all'); + + # Country Tone + # Custom,Australia,Austria, Brazil,Belgium,China, Czech,Denmark,Finland,France,Germany,Great Britain,Greece,Hungary,Lithuania,India, Italy,Japan,Mexico, New Zealand, + # Netherlands,Norway,Portugal,Spain,Switzerland,Sweden,Russia, UnitedStates, Chile,Czech ETSI + psetting('voice.tone.country', 'Germany'); + + # Sending volume + # integer range from -50 to 50, default is 0 + # handset is a bit quiet, so so raise it up a bit + psetting('voice.handfree_send', '0'); + psetting('voice.handset_send', '10'); + psetting('voice.headset_send', '0'); + + # DND + psetting('features.dnd.enable', '0'); + psetting('features.dnd.on_code', 'dnd-on'); + psetting('features.dnd.off_code', 'dnd-off'); + + # Display own Extension + psetting('features.show_default_account', '1'); + + # Security + ###Define the login username and password of the user, var and administrator. + ###If you change the username of the administrator from "admin" to "admin1", your new administrator's username should be configured as: security.user_name.admin = admin1. + ###If you change the password of the administrator from "admin" to "admin1pwd", your new administrator's password should be configured as: security.user_password = admin1:admin1pwd. + ###The following examples change the user's username to "user23" and the user's password to "user23pwd". + ###security.user_name.user = user23 + ###security.user_password = user23:user23pwd + ###The following examples change the var's username to "var55" and the var's password to "var55pwd". + ###security.user_name.var = var55 + ###security.user_password = var55:var55pwd + #psetting('security.user_name.user', ''); + #psetting('security.user_name.admin', ''); + #psetting('security.user_name.var', ''); + psetting('security.user_password', 'admin:'.gs_get_conf('GS_YEALINK_PROV_HTTP_PASS')); + + # Reboot on SIP NOTIFY + # 0=reboot, if additional parameter "reboot=true" was given, 1=reboot always, 2=ignore SIP NOTIFY message + psetting('sip.notify_reboot_enable', '0'); + + + # Transfer + psetting('transfer.blind_tran_on_hook_enable', '1'); + psetting('transfer.on_hook_trans_enable', '1'); + psetting('transfer.semi_attend_tran_enable', '1'); + + # DSS Key press on active call: 0=new call 1=attended transfer 2=blind transfer + psetting('transfer.dsskey_deal_type', '1'); + + # Enables or disables custom soft keys layout feature. + psetting('phone_setting.custom_softkey_enable', '1'); + + # DSS extended key length + psetting('features.config_dsskey_length', '1'); + + # blf_and_callpark_idle_led_enable + psetting('features.blf_and_callpark_idle_led_enable', '1'); + + # push XML server + psetting('push_xml.server', $host); + + # features.action_uri_limit_ip + psetting('features.action_uri_limit_ip', 'any'); + + # RTCP-XR features + psetting('phone_setting.vq_rtcpxr.session_report.enable', '1'); + psetting('phone_setting.vq_rtcpxr.interval_report.enable', '1'); + psetting('phone_setting.vq_rtcpxr_interval_period', '20'); + psetting('phone_setting.vq_rtcpxr.states_show_on_web.enable', '1'); + psetting('voice.rtcp_xr.enable', '1'); + + # Disable Warnings Display (Default Password set, Network, ...) + psetting('phone_setting.warnings_display.mode', '0'); + + ##################################################################### + # MAC-specific provisioning parameters (applicable to SIP-T28P/T26P/T22P/T20P/T21P/T19P/T46G/T42G/T41P IP phones running firmware version 72 or later) + ##################################################################### + # Account1 Basic Settings + psetting('account.1.enable', '1'); # 0 = disable, 1 = enable + psetting('account.1.label', $user_ext .' '. mb_subStr($user['firstname'],0,1) .'. '. $user['lastname']); + psetting('account.1.display_name', $user['callerid']); + psetting('account.1.auth_name', $user_ext); + psetting('account.1.user_name', $user_ext); + psetting('account.1.password', $user['secret']); + psetting('account.1.outbound_proxy_enable', '0'); # 0 = disable, 1 = enable + psetting('account.1.outbound_host', ''); + psetting('account.1.outbound_port', '5061'); + ##It configures the local SIP port for account 1. The default value is 5060. + psetting('account.1.sip_listen_port', '5060'); + ##It configures the transport type for account 1. 0-UDP,1-TCP,2-TLS,3-DNS-NAPTR + psetting('account.1.transport', '0'); ##The default value is 0. + + // # Failback + psetting('account.1.sip_server.1.address', $host); + psetting('account.1.sip_server.1.port', '5060'); + psetting('account.1.sip_server.1.expires', '120'); + + // # Register Advanced + // ##It configures the SIP server type for account X.0-Default,2-BroadSoft,4-Cosmocom,6-UCAP + // ##The default value is 0. + psetting('account.1.sip_server_type', '0'); + + psetting('voice_mail.number.1', 'voicemail'); + psetting('account.1.subscribe_mwi', '1'); + psetting('account.1.display_mwi.enable', '1'); + psetting('account.1.subscribe_mwi_to_vm', '1'); + + # Codecs + psetting('account.1.codec.1.enable', '1'); + psetting('account.1.codec.2.enable', '1'); + psetting('account.1.codec.3.enable', '1'); + psetting('account.1.codec.4.enable', '0'); + psetting('account.1.codec.5.enable', '0'); + psetting('account.1.codec.6.enable', '0'); + psetting('account.1.codec.7.enable', '0'); + psetting('account.1.codec.8.enable', '0'); + psetting('account.1.codec.9.enable', '0'); + psetting('account.1.codec.10.enable', '0'); + psetting('account.1.codec.11.enable', '0'); + + psetting('account.1.codec.1.payload_type', 'PCMA'); + psetting('account.1.codec.2.payload_type', 'PCMU'); + psetting('account.1.codec.3.payload_type', 'G722'); + psetting('account.1.codec.4.payload_type', 'G723_53'); + psetting('account.1.codec.5.payload_type', 'G723_63'); + psetting('account.1.codec.6.payload_type', 'G729'); + psetting('account.1.codec.7.payload_type', 'iLBC'); + psetting('account.1.codec.8.payload_type', 'G726-16'); + psetting('account.1.codec.9.payload_type', 'G726-24'); + psetting('account.1.codec.10.payload_type', 'G726-32'); + psetting('account.1.codec.11.payload_type', 'G726-40'); + + psetting('account.1.codec.1.priority', '2'); + psetting('account.1.codec.2.priority', '3'); + psetting('account.1.codec.3.priority', '1'); + psetting('account.1.codec.4.priority', '0'); + psetting('account.1.codec.5.priority', '0'); + psetting('account.1.codec.6.priority', '0'); + psetting('account.1.codec.7.priority', '0'); + psetting('account.1.codec.8.priority', '0'); + psetting('account.1.codec.9.priority', '0'); + psetting('account.1.codec.10.priority', '0'); + psetting('account.1.codec.11.priority', '0'); + + psetting('account.1.codec.1.rtpmap', '8'); # PCMA + psetting('account.1.codec.2.rtpmap', '0'); # PCMU + psetting('account.1.codec.3.rtpmap', '9'); # G722 + psetting('account.1.codec.4.rtpmap', '4'); # G723_53 + psetting('account.1.codec.5.rtpmap', '4'); # G723_63 + psetting('account.1.codec.6.rtpmap', '18'); # G729 + psetting('account.1.codec.7.rtpmap', '106'); # iLBC + psetting('account.1.codec.8.rtpmap', '103'); # G726-16 + psetting('account.1.codec.9.rtpmap', '104'); # G726-24 + psetting('account.1.codec.10.rtpmap', '102'); # G726-32 + psetting('account.1.codec.11.rtpmap', '105'); # G726-40 + + psetting('account.1.ptime', '20'); # 20ms + + // psetting('account.1.unregister_on_reboot', ''); + // psetting('account.1.sip_trust_ctrl', ''); + // psetting('account.1.proxy_require', ''); + // psetting('account.1.srv_ttl_timer_enable', ''); + // psetting('account.1.register_mac', '1'); # 0 = disable, 1 = enable + // psetting('account.1.register_line', '1'); # 0 = disable, 1 = enable + // psetting('account.1.reg_fail_retry_interval', '30'); # 0 to 1800, default 30 + + // # NAT + // ##It enables or disables the NAT traversal for account X.0-Disabled,1-Enabled + // ##The default value is 0. + // psetting('account.1.nat.nat_traversal', ''); + // ##It configures the IP address or domain name of the STUN server for account X. + // ##The default value is blank. + // psetting('account.1.nat.stun_server', ''); + // ##It configures the port of the STUN server for account X. + // ##The default value is 3478. + // psetting('account.1.nat.stun_port', ''); + // ##It configures the type of keep-alive packets sent by the phone to the NAT device to keep the communication port open so that NAT can continue to function for account X. + // ##The default value is 1. + // psetting('account.1.nat.udp_update_enable', ''); + // ##It configures the keep-alive interval (in seconds) for account X. + // ##The default value is 30.Integer from 15 to 2147483647 + // psetting('account.1.nat.udp_update_time', ''); + // ##It enables or disables NAT Rport feature for account X.0-Disabled,1-Enabled + // ##The default value is 0. + // psetting('account.1.nat.rport', ''); + + // # Pickup + // ##It enables or disables the phone to pick up a call according to the SIP header of dialog-info for account X + // ##0-Disabled,1-Enabled. + // ##The default value is 0. + // Must be DISABLED to work on Asterisk PBX + psetting('account.1.dialoginfo_callpickup', '0'); + // ##It configures the group pickup code for account X. + // ##The default value is blank. + psetting('account.1.group_pickup_code', ''); + // ##It configures the directed pickup code for account X. + // ##The default value is blank. + psetting('account.1.direct_pickup_code', '*81*'); + + + # DTMF 0=Inband 1=RFC2833 2=SIP INFO 3=RFC2833+SIP INFO + psetting('account.1.dtmf.type', '1'); + + # DTMF Info Type 1=DTMF-Relay 2=DTMF 3=Telephone-Event + psetting('account.1.dtmf.info_type', '1'); + + # allow alert info URL + psetting('account.1.alert_info_url_enable', '1'); + + # CID Source. 0-FROM 1-PAI 2-PAI-FROM 3-RPID-PAI-FROM 4-PAI-RPID-FROM 5-RPID-FROM + psetting('account.1.cid_source', '3'); + + # Time + ##It configures the time zone.For more available time zones, refer to Time Zones on page 215. + ##The default value is +8. + psetting('local_time.time_zone', '+1'); + psetting('local_time.time_zone_name', 'Germany(Berlin)'); + ##It configures the time zone name.For more available time zone names, refer to Time Zones on page 215. + ##The default time zone name is China(Beijing). + psetting('local_time.ntp_server1', gs_get_conf('GS_YEALINK_PROV_NTP')); + psetting('local_time.ntp_server2', gs_get_conf('GS_YEALINK_PROV_NTP')); # override default chinese NTP server + ## NTP setting fron DHCP has high priority + psetting('local_time.manual_ntp_srv_prior','0'); + psetting('local_time.interval' , strval(rand(980,1020))); # default 1000 + psetting('local_time.time_format', '1'); + psetting('local_time.date_format', '5'); # 0-WWW MMM DD; 1-DD-MMM-YY; 2-YYYY-MM-DD; 3-DD/MM/YYYY; 4-MM/DD/YY; 5-DD MMM YYYY; 6-WWW DD MMM + + ####################################################################################### + ## Features Pickup(Except T20P model) ## + ####################################################################################### + ##It enables or disables the phone to display the GPickup soft key when the phone is in the pre-dialing screen. + ##0-Disabled,1-Enabled. + ##The default value is 0. + psetting('features.pickup.group_pickup_enable', '0'); + + ##It configures the group call pickup code. + ##The default value is blank. + psetting('features.pickup.group_pickup_code', ''); + + ##It enables or disables the phone to display the DPickup soft key when the phone is in the pre-dialing screen. + ##0-Disabled,1-Enabled. + ##The default value is 0. + psetting('features.pickup.direct_pickup_enable', '1'); + + ##It configures the directed call pickup code. + ##The default value is blank. + psetting('features.pickup.direct_pickup_code', '*81*'); + + ##It enables or disables the phone to display a visual alert when the monitored user receives an incoming call. + ##0-Disabled,1-Enabled. + ##The default value is 0. + psetting('features.pickup.blf_visual_enable', '0'); + + ##It enables or disables the phone to play an audio alert when the monitored user receives an incoming call. + ##0-Disabled,1-Enabled. + ##The default value is 0. + psetting('features.pickup.blf_audio_enable', '0'); + + ##################################################################### + # Keys and Device specific settings + ##################################################################### + + switch ($phone_type) { + case 'yealink-sip-t42g': + $max_keys=15; + break; + case 'yealink-sip-t46g': + $max_keys=27; + psetting('screensaver.wait_time', '21600'); + break; + case 'yealink-sip-t48g': + $max_keys=29; + psetting('screensaver.wait_time', '21600'); + break; + case 'yealink-sip-t42s': + $max_keys=15; + break; + case 'yealink-sip-t46s': + $max_keys=27; + psetting('screensaver.wait_time', '21600'); + break; + case 'yealink-sip-t46u': + $max_keys=27; + psetting('screensaver.wait_time', '21600'); + break; + } + + # RESET KEYS + for ($i=1; $i <= $max_keys; $i++) { + psetting('linekey.'.$i.'.line', '0'); + psetting('linekey.'.$i.'.value', ''); + psetting('linekey.'.$i.'.pickup_value', ''); + psetting('linekey.'.$i.'.extension', ''); + psetting('linekey.'.$i.'.type', '0'); + psetting('linekey.'.$i.'.xml_phonebook', '0'); + psetting('linekey.'.$i.'.label', ''); + } + + # TODO: RESET PROGRAMMABLE KEYS? + # Programable Key 1 (default "History") > GS History + # Programable Key 5 (UP Key)(default "History") > GS History + # Programable Key 6 (DOWN Key)(default "Phonebook") > XML Phonebook + psetting('programablekey.1.type', '27'); # XML Browser + psetting('programablekey.1.value', $prov_url_yealink.'dial-log.php?user='.$user_ext ); + psetting('programablekey.1.label', 'Anrufliste'); + psetting('programablekey.5.type', '27'); # XML Browser + psetting('programablekey.5.value', $prov_url_yealink.'dial-log.php?user='.$user_ext ); + psetting('programablekey.5.label', 'Anrufliste'); + + psetting('programablekey.6.type', '47'); # XML Phonebook + psetting('programablekey.6.value', '' ); + psetting('programablekey.6.label', 'Tel.Buch'); + + # max 6 EXP40 Modules allowed + # get max configured EXP40 count to speed up provisioning + $max_ext_modules = (int)$db->executeGetOne( 'SELECT `g`.`show_ext_modules` FROM `users` `u` JOIN `user_groups` `g` ON (`g`.`id`=`u`.`group_id`) WHERE `u`.`id`='.$user_id ); + if ($max_ext_modules >6) { $max_ext_modules=6; } + + + # RESET EXP KEYS on EXP40 + if ($phone_type == 'yealink-sip-t46g' || $phone_type == 'yealink-sip-t48g' || $phone_type == 'yealink-sip-t46s') { + for ($j=1; $j<=$max_ext_modules; $j++) { + for ($i=1; $i <= 40; $i++) { + psetting('expansion_module.'.$j.'.key.'.$i.'.line', '0'); + psetting('expansion_module.'.$j.'.key.'.$i.'.value', ''); + psetting('expansion_module.'.$j.'.key.'.$i.'.type', '0'); + psetting('expansion_module.'.$j.'.key.'.$i.'.label', ''); + } + } + } + + # RESET EXP KEYS on EXP43 + if ($phone_type == 'yealink-sip-t46u') { + # max 3 EXP43 Modules allowed + # get max configured EXP43 count to speed up provisioning + if ($max_ext_modules >3) { $max_ext_modules=3; } + + for ($j=1; $j<=$max_ext_modules; $j++) { + for ($i=1; $i <= 60; $i++) { + psetting('expansion_module.'.$j.'.key.'.$i.'.line', '0'); + psetting('expansion_module.'.$j.'.key.'.$i.'.value', ''); + psetting('expansion_module.'.$j.'.key.'.$i.'.type', '0'); + psetting('expansion_module.'.$j.'.key.'.$i.'.label', ''); + } + } + } + + + $softkeys = null; + $GS_Softkeys = gs_get_key_prov_obj( $phone_type ); + if ($GS_Softkeys->set_user( $user['user'] )) { + if ($GS_Softkeys->retrieve_keys( $phone_type, array( + '{GS_PROV_HOST}' => gs_get_conf('GS_PROV_HOST'), + '{GS_P_PBX}' => $pbx, + '{GS_P_EXTEN}' => $user_ext, + '{GS_P_ROUTE_PREFIX}' => $hp_route_prefix, + '{GS_P_USER}' => $user['user'] + ) )) { + $softkeys = $GS_Softkeys->get_keys(); + } + } + if (! is_array($softkeys)) { + gs_log( GS_LOG_WARNING, 'Failed to get softkeys' ); + } else { + gs_log( GS_LOG_DEBUG, 'Num Softkeys to set: '.count($softkeys) ); + + foreach ($softkeys as $key_name => $key_defs) { + if (array_key_exists('slf', $key_defs)) { + $key_def = $key_defs['slf']; + } elseif (array_key_exists('inh', $key_defs)) { + $key_def = $key_defs['inh']; + } else { + continue; + } + + # $key_name is Fxxyy , where xx is extension module and yy is key index + $key_idx = (int)lTrim(subStr($key_name,3),'0'); + $key_exp = (int)lTrim(subStr($key_name,1,2),'0'); + # gs_log( GS_LOG_DEBUG, 'Softkey '.$key_name.' -> Exp='.$key_exp.' Idx='.$key_idx ); + if ($key_def['function'] === 'f0') continue; + + ####################################################################################### + ## Line Keys ## + ####################################################################################### + if ($key_idx >= 1 && $key_idx <= $max_keys && $key_exp == 0) { + gs_log( GS_LOG_DEBUG, 'Set LineKey('.$key_idx.') value=\''.$key_def['data'].'\' type=\''.subStr($key_def['function'],1).'\' label=\''.$key_def['label'].'\'' ); + + ###It configures the desired line to apply the key feature.Integer from 1 to 6 + psetting('linekey.'.$key_idx.'.line', 1); + ###It configures the value of the line key feature. + ###For example, when setting the key feature to BLF, it configures the number of the monitored user. + ###The default value is blank. + psetting('linekey.'.$key_idx.'.value', $key_def['data']); + # for BLF + if (subStr($key_def['function'],1) == 16 ) { + ###It configures the pickup code for BLF feature or conference ID followed by the # sign for Meet-Me conference feature. + ###It only applies to BLF and Meet-Me conference features. + ###The default value is blank + psetting('linekey.'.$key_idx.'.pickup_value', '*81*'); + } + ###It configures the key feature for the line key X. + #The valid types are: + #0-NA 1-Conference 2-Forward 3-Transfer 4-Hold 5-DND 7-Call Return 8-SMS 9-Directed Pickup + #10-Call Park 11-DTMF 12-Voice Mail 13-Speed Dial 14-Intercom 15-Line 16-BLF 17-URL 18-Group Listening + #20-Private Hold 22-XML Group 23-Group Pickup 24-Multicast Paging 25-Record 27-XML Browser + #34-Hot Desking 35-URL Record 38-LDAP 39-BLF List + #40-Prefix 41-Zero Touch 42-ACD 45-Local Group 46-Network Group 49-Custom Button + #50-Keypad Lock 55-Meet-Me Conference 56-Retrieve Park 57-Hoteling 58-ACD Grace 59-Sisp Code + #60-Emergency 61-Directory + #---- + #0-NA ��Only for T41/T42/T46) + #22-XML Group (Not support T20) + #38-LDAP (Not support T20) + #46-Network Group (Not support T20) + #8-SMS (Only support T21/T46/T22/T26/T28) + #17-URL (Only support T41/T42/T46) + #49-Custom Button (Only support T20/T22/T26/T28) + psetting('linekey.'.$key_idx.'.type', subStr($key_def['function'],1)); + ###It configures the desired local group/XML group/network group for the line key X. + ###It only applies to the Local Group, XML Group and Network Group features. + ###XML Group and Network Group features are not applicable to SIP-T20P IP phones. + // psetting('linekey.'.$key_idx.'.xml_phonebook', '0'); + ###It configures the label displayed on the LCD screen for each line key. + ###The default value is blank. + psetting('linekey.'.$key_idx.'.label', $key_def['label']); + } + ####################################################################################### + ## Expansion Keys ## + ####################################################################################### + else if ($key_idx >= 1 && $key_idx <= 40 && $key_exp >= 1 && $key_exp <=6) { + gs_log( GS_LOG_DEBUG, 'Set ExpKey('.$key_idx.') value=\''.$key_def['data'].'\' type=\''.subStr($key_def['function'],1).'\' label=\''.$key_def['label'].'\'' ); + ###It configures the desired line to apply the key feature.Integer from 1 to 6 + psetting('expansion_module.'.$key_exp.'.key.'.$key_idx.'.line', 1); + ###It configures the value of the line key feature. + ###For example, when setting the key feature to BLF, it configures the number of the monitored user. + ###The default value is blank. + psetting('expansion_module.'.$key_exp.'.key.'.$key_idx.'.value', $key_def['data']); + # for BLF + if (subStr($key_def['function'],1) == 16 ) { + ###It configures the pickup code for BLF feature or conference ID followed by the # sign for Meet-Me conference feature. + ###It only applies to BLF and Meet-Me conference features. + ###The default value is blank + psetting('expansion_module.'.$key_exp.'.key.'.$key_idx.'.pickup_value', '*81*'); + } + ###It configures the key feature for the line key X. + #The valid types are: + #0-NA 1-Conference 2-Forward 3-Transfer 4-Hold 5-DND 7-Call Return 8-SMS 9-Directed Pickup + #10-Call Park 11-DTMF 12-Voice Mail 13-Speed Dial 14-Intercom 15-Line 16-BLF 17-URL 18-Group Listening + #20-Private Hold 22-XML Group 23-Group Pickup 24-Multicast Paging 25-Record 27-XML Browser + #34-Hot Desking 35-URL Record 38-LDAP 39-BLF List + #40-Prefix 41-Zero Touch 42-ACD 45-Local Group 46-Network Group 49-Custom Button + #50-Keypad Lock 55-Meet-Me Conference 56-Retrieve Park 57-Hoteling 58-ACD Grace 59-Sisp Code + #60-Emergency 61-Directory + #---- + #0-NA ��Only for T41/T42/T46) + #22-XML Group (Not support T20) + #38-LDAP (Not support T20) + #46-Network Group (Not support T20) + #8-SMS (Only support T21/T46/T22/T26/T28) + #17-URL (Only support T41/T42/T46) + #49-Custom Button (Only support T20/T22/T26/T28) + psetting('expansion_module.'.$key_exp.'.key.'.$key_idx.'.type', subStr($key_def['function'],1)); + ###It configures the desired local group/XML group/network group for the line key X. + ###It only applies to the Local Group, XML Group and Network Group features. + ###XML Group and Network Group features are not applicable to SIP-T20P IP phones. + // psetting('linekey.'.$key_idx.'.xml_phonebook', '0'); + ###It configures the label displayed on the LCD screen for each line key. + ###The default value is blank. + psetting('expansion_module.'.$key_exp.'.key.'.$key_idx.'.label', $key_def['label']); + + } + # TODO: Programmable Keys + # TODO: Keys on Expansion Modul + } + } +} + + +##################################################################### +# Override provisioning parameters (group profile) +##################################################################### +$prov_params = null; +$GS_ProvParams = gs_get_prov_params_obj( $phone_type ); +if ($GS_ProvParams->set_user( $user['user'] )) { + if ($GS_ProvParams->retrieve_params( $phone_type, array( + '{GS_PROV_HOST}' => gs_get_conf('GS_PROV_HOST'), + '{GS_P_PBX}' => $pbx, + '{GS_P_EXTEN}' => $user_ext, + '{GS_P_ROUTE_PREFIX}' => $hp_route_prefix, + '{GS_P_USER}' => $user['user'] + ) )) { + $prov_params = $GS_ProvParams->get_params(); + } +} + +gs_log( GS_LOG_DEBUG, "Retrieved ".count($prov_params)." Group-Profile parameters for phone_type: ".$phone_type ); + +if (! is_array($prov_params)) { + gs_log( GS_LOG_WARNING, 'Failed to get provisioning parameters (group)' ); +} else { + foreach ($prov_params as $param_name => $param_arr) { + foreach ($param_arr as $param_index => $param_value) { + if ($param_index == -1) { + # not an array + if (! array_key_exists($param_name, $settings)) { + # new parameter + gs_log( GS_LOG_DEBUG, "Group prov. param \"$param_name\": \"$param_value\"" ); + } else { + # override parameter + gs_log( GS_LOG_DEBUG, "Overriding group prov. param \"$param_name\": \"$param_value\"" ); + } + + psetting($param_name, $param_value); + } else { + # array + gs_log( GS_LOG_NOTICE, "Group prov. param \"$param_name\"[$param_index]: Yealink does not support arrays" ); + } + } + } +} +unset($prov_params); +unset($GS_ProvParams); + + +##################################################################### +# Override provisioning parameters (user profile) +##################################################################### +$prov_params = @gs_user_prov_params_get( $user['user'], $phone_type ); + +gs_log( GS_LOG_DEBUG, "Retrieved ".count($prov_params)." User-Profile parameters for phone_type: ".$phone_type.", user: ".$user['user'] ); + +if (! is_array($prov_params)) { + gs_log( GS_LOG_WARNING, 'Failed to get provisioning parameters (user)' ); +} else { + foreach ($prov_params as $p) { + if ($p['index'] === null + || $p['index'] == -1) { + # not an array + if (! array_key_exists($p['param'], $settings)) { + # new parameter + gs_log( GS_LOG_DEBUG, 'User prov. param "'.$p['param'].'": "'.$p['value'].'"' ); + } else { + # override parameter + gs_log( GS_LOG_DEBUG, 'Overriding user prov. param "'.$p['param'].'": "'.$p['value'].'"' ); + } + + psetting($p['param'], $p['value']); + } else { + # array + gs_log( GS_LOG_NOTICE, 'User prov. param "'.$p['param'].'"['.$p['index'].']: Yealink does not support arrays"' ); + } + } +} +unset($prov_params); + + +##################################################################### +# output +##################################################################### +ob_start(); +_settings_out(); +if (! headers_sent()) { + header( 'Content-Type: text/plain; charset=utf-8' ); + # avoid chunked transfer-encoding + header( 'Content-Length: '. (int)@ob_get_length() ); +} +@ob_flush(); + +?> diff --git a/opt/gemeinschaft/inc/conf.php b/opt/gemeinschaft/inc/conf.php index 6dde6d673..5afa37b4a 100644 --- a/opt/gemeinschaft/inc/conf.php +++ b/opt/gemeinschaft/inc/conf.php @@ -127,7 +127,6 @@ function gs_get_conf( $key, $default=null ) return @defined($key) ? constant($key) : $default; } - $conf = '/etc/gemeinschaft/gemeinschaft.php'; if (! file_exists( $conf )) { trigger_error( "Config file \"$conf\" not found!\n", E_USER_ERROR ); @@ -140,7 +139,6 @@ function gs_get_conf( $key, $default=null ) } } - function _gscnf( $param, $default=null ) { if (@array_key_exists($param, $GLOBALS)) { @@ -245,6 +243,7 @@ function _gscnf( $param, $default=null ) _gscnf( 'PROV_MODELS_ENABLED_AASTRA' , '*' ); # / '51i,53i,55i,57i' _gscnf( 'PROV_MODELS_ENABLED_GRANDSTREAM' , '*' ); # / 'gxp2000,gxp2020'... _gscnf( 'PROV_MODELS_ENABLED_TIPTEL' , '*' ); # / 'ip280,ip284,ip286' +_gscnf( 'PROV_MODELS_ENABLED_YEALINK' , '*' ); # / 'yealink-sip-t46g,yealink-sip-t48g' _gscnf( 'PROV_MODELS_ENABLED_POLYCOM' , '*' ); # / 'spip-550,spip-670', ... _gscnf( 'SNOM_PROV_ENABLED' , false ); @@ -332,6 +331,20 @@ function _gscnf( $param, $default=null ) _gscnf( 'TIPTEL_PROV_FW_DEFAULT_IP286' , null ); _gscnf( 'TIPTEL_PROV_KEY_BLACKLIST' , '' ); +_gscnf( 'YEALINK_PROV_ENABLED' , false ); +_gscnf( 'YEALINK_PROV_HTTP_PASS' , '' ); +_gscnf( 'YEALINK_PROV_NTP' , gs_get_conf('GS_PROV_HOST','') ); +_gscnf( 'YEALINK_PROV_FW_UPDATE' , false ); +_gscnf( 'YEALINK_PROV_FW_DEFAULT_SIP_T42G', null ); +_gscnf( 'YEALINK_PROV_FW_DEFAULT_SIP_T46G', null ); +_gscnf( 'YEALINK_PROV_FW_DEFAULT_SIP_T48G', null ); +_gscnf( 'YEALINK_PROV_FW_DEFAULT_SIP_T42S', null ); +_gscnf( 'YEALINK_PROV_FW_DEFAULT_SIP_T46S', null ); +_gscnf( 'YEALINK_PROV_FW_DEFAULT_SIP_T46U', null ); +//_gscnf( 'YEALINK_PROV_FW_DEFAULT_IP284' , null ); +//_gscnf( 'YEALINK_PROV_FW_DEFAULT_IP286' , null ); +_gscnf( 'YEALINK_PROV_KEY_BLACKLIST' , '' ); + _gscnf( 'CANONIZE_OUTBOUND' , true ); _gscnf( 'CANONIZE_INTL_PREFIX' , '00' ); _gscnf( 'CANONIZE_COUNTRY_CODE' , '49' ); @@ -398,6 +411,7 @@ function _gscnf( $param, $default=null ) _gscnf( 'FAX_HYLAFAX_PASS' , '' ); _gscnf( 'FAX_HYLAFAX_PATH' , '/var/spool/hylafax/' ); _gscnf( 'FAX_INIT_DOCDIR' , '/tmp/' ); +_gscnf( 'FAX_MAP_IAXMODEM_USER' , '' ); _gscnf( 'BOI_ENABLED' , false ); diff --git a/opt/gemeinschaft/inc/gs-fns/gs_prov_params_get.php b/opt/gemeinschaft/inc/gs-fns/gs_prov_params_get.php index d9a65fddd..4e310f7bd 100644 --- a/opt/gemeinschaft/inc/gs-fns/gs_prov_params_get.php +++ b/opt/gemeinschaft/inc/gs-fns/gs_prov_params_get.php @@ -70,8 +70,7 @@ function gs_prov_params_get( $username, $phone_type ) if (! is_array($path)) return new GsError( 'DB error.' ); foreach ($path as $group) { - if ($group['prov_param_profile_id'] > 0) { - + if ($group['prov_param_profile_id'] > 0) { //echo 'Get group\'s prov param profile, id '. $group['prov_param_profile_id'] ."\n"; $rs = $db->execute( 'SELECT `param`, `index`, `value` '. @@ -90,7 +89,31 @@ function gs_prov_params_get( $username, $phone_type ) } } } - + + # get keys for phonetype + if($user['group_id'] < 1) { + $mptt = new YADB_MPTT($db, 'user_groups', 'lft', 'rgt', 'title'); + $group = $mptt->_db_query( 'SELECT * FROM user_groups WHERE `title`=\''. $db->escape($phone_type) .'\'' ); + if (! $group) + return new GsError( 'DB error.' ); + if ($group['prov_param_profile_id'] > 0) { + //echo 'Get group\'s prov param profile, id '. $group['prov_param_profile_id'] ."\n"; + $rs = $db->execute( + 'SELECT `param`, `index`, `value` '. + 'FROM `prov_params` '. + 'WHERE '. + '`profile_id`='. $group['prov_param_profile_id'] .' AND '. + '`phone_type`=\''. $db->escape($phone_type) .'\' '. + 'ORDER BY `param`, `index`' ); + while ($r = $rs->fetchRow()) { + $r['_set_by'] = 'g'; + $r['_setter'] = $user['group_id']; + + $params[$r['param']][$r['index']] = $r['value']; + } + } + } + return $params; } diff --git a/opt/gemeinschaft/inc/gs-fns/gs_prov_phone_checkcfg.php b/opt/gemeinschaft/inc/gs-fns/gs_prov_phone_checkcfg.php index 462378d04..5f5bc8f6e 100644 --- a/opt/gemeinschaft/inc/gs-fns/gs_prov_phone_checkcfg.php +++ b/opt/gemeinschaft/inc/gs-fns/gs_prov_phone_checkcfg.php @@ -235,6 +235,9 @@ function _gs_prov_phone_checkcfg_by_ip_do( $ip, $reboot=true ) if (gs_get_conf('GS_TIPTEL_PROV_ENABLED')) { _gs_prov_phone_checkcfg_by_ip_do_tiptel( $ip, $reboot ); } + if (gs_get_conf('GS_YEALINK_PROV_ENABLED')) { + _gs_prov_phone_checkcfg_by_ip_do_yealink( $ip, $reboot ); + } //return $err == 0; return true; @@ -318,9 +321,69 @@ function _gs_prov_phone_checkcfg_by_ip_do_grandstream( $ip, $reboot=true ) { if (_gs_prov_phone_checkcfg_exclude_ip( $ip )) return; + $db = @gs_db_slave_connect(); + if (! $db) { + gs_log(GS_LOG_WARNING, 'Failed to connect to DB'); + return; + } + + $type = @$db->executeGetOne(' + SELECT + `p`.`type` + FROM + `users` `u` + JOIN + `phones` `p` ON (`p`.`user_id` = `u`.`id`) + WHERE + `u`.`current_ip` = \''. $db->escape($ip) .'\' + '); + + $model = strtoupper( str_replace( 'grandstream-', '', $type ) ); + + if ( preg_match('/^GXP21([0-9]{2})$/', $model) ) { + reboot_grandstream21xx( $ip, $model ); + return; + } + @ exec( '/opt/gemeinschaft/sbin/gs-grandstream-reboot --ip='. qsa($ip) .' >>/dev/null 2>>/dev/null &', $out, $err ); } +function reboot_grandstream21xx($ip_addr, $model) +{ + $socket = fsockopen("$ip_addr","23", $errno, $errstr, 1000); + if (!$socket) { + // echo "$errstr ($errno)
\n"; + exit; + } + read_up_to("Grandstream $model Command Shell Copyright 2011",$socket); + fputs($socket, "admin\r\n"); + read_up_to("$model",$socket); + fputs($socket, "reboot\r\n"); + read_up_to("Rebooting",$socket); + fputs($socket, "exit\r\n"); + read_up_to("endlessssssssss",$socket); //this is just to keep it until reboot command execute + fclose($socket); +} + +function read_up_to($string,$socket) +{ + $max_loop = 30; + $resp = ""; + while (!feof($socket)) + { + if ($max_loop<0) + break; + $max_loop--; + $resp .= fgets($socket, 10); + // echo $resp."
"; + if (strstr($resp,$string)) + { + // echo "found" . $resp . "
"; + break; + } + } +} + function _gs_prov_phone_checkcfg_by_ip_do_polycom( $ip, $reboot=true ) { if (_gs_prov_phone_checkcfg_exclude_ip( $ip )) return; @@ -372,6 +435,27 @@ function _gs_prov_phone_checkcfg_by_ip_do_tiptel( $ip, $reboot=true ) @ exec( '/opt/gemeinschaft/sbin/gs-tiptel-reboot --ip='. qsa($ip) .' >>/dev/null 2>>/dev/null &', $out, $err ); } +function _gs_prov_phone_checkcfg_by_ip_do_yealink( $ip, $reboot=true ) +{ + if (_gs_prov_phone_checkcfg_exclude_ip( $ip )) return; + + gs_log(GS_LOG_DEBUG, "Send yealink update config \"$ip\""); + + $url = 'http://' . qsa($ip) .'/servlet'; + + //open connection + $ch = curl_init(); + + //set the url, number of POST vars, POST data + curl_setopt($ch,CURLOPT_URL,$url); + curl_setopt($ch,CURLOPT_POST,3); + curl_setopt($ch,CURLOPT_POSTFIELDS,'p=settings-autop&q=write&now=true'); + + //execute post + $result = curl_exec($ch); + +} + // PRIVATE: function _gs_prov_phone_checkcfg_by_ext_do( $ext, $reboot=true ) { @@ -434,7 +518,9 @@ function _gs_prov_phone_checkcfg_by_ext_do( $ext, $reboot=true ) if (gs_get_conf('GS_TIPTEL_PROV_ENABLED')) { _gs_prov_phone_checkcfg_by_ext_do_tiptel( $ext, $reboot ); } - + if (gs_get_conf('GS_YEALINK_PROV_ENABLED')) { + _gs_prov_phone_checkcfg_by_ext_do_yealink( $ext, $reboot ); + } //return $err == 0; return true; } @@ -548,7 +634,28 @@ function _gs_prov_phone_checkcfg_by_ext_do_aastra( $ext, $reboot=true ) function _gs_prov_phone_checkcfg_by_ext_do_grandstream( $ext, $reboot=true ) { - //FIXME + $db = @gs_db_slave_connect(); + if (! $db) { + gs_log(GS_LOG_WARNING, 'Failed to connect to DB'); + return; + } + + $ip = @$db->executeGetOne( + 'SELECT + `u`.`current_ip` + FROM + `ast_sipfriends` `s` + JOIN + `users` `u` ON (`u`.`id`=`s`.`_user_id`) + WHERE `s`.`name`=\''. $db->escape($ext) .'\'' + ); + + if (! $ip || ! preg_match('/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/', $ip)) { + gs_log(GS_LOG_WARNING, 'Bad IP'); + return; + } + + _gs_prov_phone_checkcfg_by_ip_do_grandstream( $ip, $reboot); } function _gs_prov_phone_checkcfg_by_ext_do_polycom( $ext, $reboot=true ) @@ -574,4 +681,22 @@ function _gs_prov_phone_checkcfg_by_ext_do_tiptel( $ext, $reboot=true ) //FIXME } +function _gs_prov_phone_checkcfg_by_ext_do_yealink( $ext, $reboot=true ) +{ + $sip_notify = $reboot ? 'yealink-check-cfg-reboot' : 'yealink-check-cfg'; + @exec( 'sudo asterisk -rx \'sip notify '. $sip_notify .' '. $ext .'\' >>/dev/null 2>>/dev/null &', $out, $err ); + + $hosts = @gs_hosts_get(false); + if (isGsError($hosts)) { + gs_log(GS_LOG_WARNING, 'Failed to get hosts - '. $hosts->getMsg()); + } elseif (! is_array($hosts)) { + gs_log(GS_LOG_WARNING, 'Failed to get hosts'); + } else { + $cmd = 'asterisk -rx \'sip notify '. $sip_notify .' '. $ext .'\''; + foreach ($hosts as $host) { + @exec( 'sudo ssh -o StrictHostKeyChecking=no -o BatchMode=yes -l root '. qsa($host['host']) .' '. qsa($cmd) .' >>/dev/null 2>>/dev/null &' ); + } + } +} + ?> \ No newline at end of file