Index: /modules/branches/2.6/miscapps/i18n/sv_SE/LC_MESSAGES/miscapps.po =================================================================== --- /modules/branches/2.6/miscapps/i18n/sv_SE/LC_MESSAGES/miscapps.po (revision 6940) +++ /modules/branches/2.6/miscapps/i18n/sv_SE/LC_MESSAGES/miscapps.po (revision 6940) @@ -0,0 +1,94 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: FreePBX miscapps\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2008-10-05 12:08+0200\n" +"PO-Revision-Date: 2008-10-10 22:41+0100\n" +"Last-Translator: Mikael Carlsson \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Poedit-Language: Swedish\n" +"X-Poedit-Country: SWEDEN\n" + +#: functions.inc.php:144 +#, php-format +msgid "Misc Application: %s" +msgstr "Övrig applikation: %s" + +#: page.miscapps.php:74 +#: page.miscapps.php:98 +#: page.miscapps.php:116 +msgid "Add Misc Application" +msgstr "LÀgg till Övrig applikation" + +#: page.miscapps.php:96 +#: page.miscapps.php:116 +msgid "Edit Misc Application" +msgstr "Redigera Övrig applikation" + +#: page.miscapps.php:101 +msgid "Misc Applications are for adding feature codes that you can dial from internal phones that go to various destinations available in FreePBX. This is in contrast to the Misc Destinations module, which is for creating destinations that can be used by other FreePBX modules to dial internal numbers or feature codes." +msgstr "Övriga applikationer Àr till för att lÀgga till funktionskoder som du kan ringa frÃ¥n interna telefoner som kan gÃ¥ till olika destinationer inom FreePBX. Detta Àr i kontrast med Övrig destination, som Àr för att skapa destinationer som kan anvÀndas av FreePBX övriga moduler för att ringa interna nummer eller funktionskoder." + +#: page.miscapps.php:106 +msgid "Conflicting Extensions" +msgstr "Konfliktande anknytningar" + +#: page.miscapps.php:118 +msgid "Description" +msgstr "Beskrivning" + +#: page.miscapps.php:118 +msgid "The name of this application" +msgstr "Kort beskrivning pÃ¥ denna applikation" + +#: page.miscapps.php:122 +msgid "Feature Code" +msgstr "Funktionskod" + +#: page.miscapps.php:122 +msgid "The feature code/extension users can dial to access this application. This can also be modified on the Feature Codes page." +msgstr "Funktionskoden/anknytningen anvÀndare kan ringa för att fÃ¥ Ã¥tkomst till denna applikation. Denna kan Àven modifieras pÃ¥ sidan Funktionskoder." + +#: page.miscapps.php:126 +msgid "Feature Status" +msgstr "Funktionsstatus" + +#: page.miscapps.php:126 +msgid "If this code is enabled or not." +msgstr "Om denna kod Àr aktiv eller inte." + +#: page.miscapps.php:128 +msgid "Enabled" +msgstr "Aktiverad" + +#: page.miscapps.php:129 +msgid "Disabled" +msgstr "Avaktiverad" + +#: page.miscapps.php:133 +msgid "Destination" +msgstr "Destination" + +#: page.miscapps.php:141 +msgid "Submit Changes" +msgstr "Spara Àndringar" + +#: page.miscapps.php:142 +msgid "Delete" +msgstr "Ta bort" + +#: page.miscapps.php:154 +msgid "Invalid description specified" +msgstr "Ogiltig beskrivning angiven" + +msgid "Misc Applications" +msgstr "Övriga applikationer" + Index: /modules/branches/2.6/miscapps/i18n/miscapps.pot =================================================================== --- /modules/branches/2.6/miscapps/i18n/miscapps.pot (revision 6940) +++ /modules/branches/2.6/miscapps/i18n/miscapps.pot (revision 6940) @@ -0,0 +1,97 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2008-10-05 12:08+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" + +#: functions.inc.php:144 +#, php-format +msgid "Misc Application: %s" +msgstr "" + +#: page.miscapps.php:74 page.miscapps.php:98 page.miscapps.php:116 +msgid "Add Misc Application" +msgstr "" + +#: page.miscapps.php:96 page.miscapps.php:116 +msgid "Edit Misc Application" +msgstr "" + +#: page.miscapps.php:101 +msgid "" +"Misc Applications are for adding feature codes that you can dial from " +"internal phones that go to various destinations available in FreePBX. This " +"is in contrast to the Misc Destinations module, which is " +"for creating destinations that can be used by other FreePBX modules to dial " +"internal numbers or feature codes." +msgstr "" + +#: page.miscapps.php:106 +msgid "Conflicting Extensions" +msgstr "" + +#: page.miscapps.php:118 +msgid "Description" +msgstr "" + +#: page.miscapps.php:118 +msgid "The name of this application" +msgstr "" + +#: page.miscapps.php:122 +msgid "Feature Code" +msgstr "" + +#: page.miscapps.php:122 +msgid "" +"The feature code/extension users can dial to access this application. This " +"can also be modified on the Feature Codes page." +msgstr "" + +#: page.miscapps.php:126 +msgid "Feature Status" +msgstr "" + +#: page.miscapps.php:126 +msgid "If this code is enabled or not." +msgstr "" + +#: page.miscapps.php:128 +msgid "Enabled" +msgstr "" + +#: page.miscapps.php:129 +msgid "Disabled" +msgstr "" + +#: page.miscapps.php:133 +msgid "Destination" +msgstr "" + +#: page.miscapps.php:141 +msgid "Submit Changes" +msgstr "" + +#: page.miscapps.php:142 +msgid "Delete" +msgstr "" + +#: page.miscapps.php:154 +msgid "Invalid description specified" +msgstr "" + +#: module.xml +msgid "Misc Applications" +msgstr "" Index: /modules/branches/2.6/miscapps/i18n/it_IT/LC_MESSAGES/miscapps.po =================================================================== --- /modules/branches/2.6/miscapps/i18n/it_IT/LC_MESSAGES/miscapps.po (revision 5363) +++ /modules/branches/2.6/miscapps/i18n/it_IT/LC_MESSAGES/miscapps.po (revision 5363) @@ -0,0 +1,126 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: 1.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2007-01-26 14:18+0100\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Francesco Romano\n" +"Language-Team: Italian\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=ISO-8859-1\n" +"Content-Transfer-Encoding: 8bit\n" + +#: page.miscapps.php:79 +msgid "" +"Misc Applications are for adding feature codes that you can dial from " +"internal phones that go to various destinations available in FreePBX. This " +"is in contrast to the Misc Destinations module, which is " +"for creating destinations that can be used by other FreePBX modules to dial " +"internal numbers or feature codes." +msgstr "Le Applicazioni Varie possono essere utilizzate per impostare dei servizi consultabili direttamente dai telefoni scegliendo una delle varie destinazioni disponibili in FreePBX. Non è la stessa cosa del modulo Destinazioni Varie, che serve a creare destinazioni da poter essere utilizzate da altri moduli FreePBX, per chiamare per esempio numeri interni o altri servizi." + +#: page.miscapps.php:88 +msgid "Edit Misc Application" +msgstr "Modifica Applicazione Varia" + +#: page.miscapps.php:88 +msgid "Add Misc Application" +msgstr "Aggiungi Applicazione Varia" + +#: page.miscapps.php:90 +msgid "Description" +msgstr "Descrizione" + +#: page.miscapps.php:90 +msgid "The name of this application" +msgstr "Il nome di questa applicazione" + +#: page.miscapps.php:94 +msgid "Feature Code" +msgstr "Codice Servizio" + +#: page.miscapps.php:94 +msgid "" +"The feature code/extension users can dial to access this application. This " +"can also be modified on the Feature Codes page." +msgstr "Il codice/estensione che gli utenti dovranno digitare per accedere a questa applicazione. Questa può essere anche modificata nella pagina Codici Servizi." + +#: page.miscapps.php:98 +msgid "Feature Status" +msgstr "Stato Servizio" + +#: page.miscapps.php:98 +msgid "If this code is enabled or not." +msgstr "Se questo codice è attivo o no." + +#: page.miscapps.php:105 +msgid "Destination" +msgstr "Destinazione" + +#: page.miscapps.php:114 +msgid "Delete" +msgstr "Elimina" + +msgid "Core" +msgstr "Sistema" + +msgid "Conferences" +msgstr "Conferenze" + +msgid "Phonebook Directory" +msgstr "Rubrica" + +msgid "Queues" +msgstr "Code" + +msgid "Ring Groups" +msgstr "Gruppi di chiamata" + +msgid "Speed dial functions" +msgstr "Selezione breve" + +msgid "Time Conditions" +msgstr "Condizioni Temporali" + +msgid "Custom Contexts" +msgstr "Contesti Personalizzati" + +msgid "Extended Routing" +msgstr "Rotte specifiche" + +msgid "Custom App
ADVANCED USERS ONLY

Uses Goto() to send caller to a custom context.

The context name should start with \"custom-\", and be in the format custom-context,extension,priority. Example entry:

custom-myapp,s,1

The [custom-myapp] context would need to be created and included in extensions_custom.conf
" +msgstr "Applicazione PersonalizzataSOLO UTENTI AVANZATI
Utilizzare Goto() per inviare la chiamata verso un contesto personalizzato.

Il nome del contesto deve iniziare per \"custom-\" e deve essere nel formato custom-contesto,extension,priorità. Esempio:

custom-app,s,1

Il contesto [custom-app] deve poi essere creato e incluso nel file extensions_custom.conf
" + + +msgid "Submit Changes" +msgstr "Invia" + +msgid "Edit" +msgstr "Modifica" + +msgid "Enabled" +msgstr "Attivato" + +msgid "Disabled" +msgstr "Disattivato" + +msgid "Add Misc. Application" +msgstr "Aggiungi Applicazione Varia" + +msgid "Voicemail" +msgstr "Casella Vocale" + +msgid "Extensions" +msgstr "Interni" + +msgid "Day Night Mode" +msgstr "Controllo Giorno Notte" + +msgid "Terminate Call" +msgstr "Termina Chiamata" Index: /modules/branches/2.6/miscapps/i18n/ru_RU/LC_MESSAGES/miscapps.po =================================================================== --- /modules/branches/2.6/miscapps/i18n/ru_RU/LC_MESSAGES/miscapps.po (revision 5780) +++ /modules/branches/2.6/miscapps/i18n/ru_RU/LC_MESSAGES/miscapps.po (revision 5780) @@ -0,0 +1,134 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , 2008. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: 1.4\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2008-01-29 15:07+0100\n" +"PO-Revision-Date: 2008-01-29 15:07+0100\n" +"Last-Translator: Alexander Kozyrev\n" +"Language-Team: Russian\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=ISO-8859-5\n" +"Content-Transfer-Encoding: 8bit\n" + +#: page.miscapps.php:96 page.miscapps.php:116 +msgid "Edit Misc Application" +msgstr "ž×ÜÕÝØâì ÀÐ×ÛØçÝÞÕ ßàØÛÞÖÕÝØÕ" + +#: page.miscapps.php:98 +msgid "Add MIsc Application" +msgstr "ŽÞÑÐÒØâì ÀÐ×ÛØçÝÞÕ ßàØÛÞÖÕÝØÕ" + +#: page.miscapps.php:101 +msgid "" +"Misc Applications are for adding feature codes that you can dial from " +"internal phones that go to various destinations available in FreePBX. This " +"is in contrast to the Misc Destinations module, which is " +"for creating destinations that can be used by other FreePBX modules to dial " +"internal numbers or feature codes." +msgstr "" +"ÀÐ×ÛØçÝëÕ ßàØÛÞÖÕÝØï ÔÞÑÐÒÛïîâ ÚÞÔë Ú âÐÑÛØæÕ ÁÕàÒØáÝëå ÚÞÔÞÒ, á ßÞÜÞéìî " +"ÚÞâÞàëå ÜÞÖÝÞ ßÞßÐÔÐâì ÒÞ ÒáÕ ÒÞ×ÜÞÖÝëÕ ÝÐßàÐÒÛÕÝØï, ÔÞáâãßÝëÕ ÒÞ FreePBX. " +"ÍâÞ ÝÕ áÞÒáÕÜ âÞÖÕ, çâÞ Ø ÜÞÔãÛì ÀÐ×ÛØçÝëÕ ÝÐßàÐÒÛÕÝØï, " +"ÚÞâÞàëÙ áÛãÖØâ ÔÛï áÞ×ÔÐÝØï ÝÐßàÐÒÛÕÝØÙ, ØáßÞÛì×ãÕÜëå ×ÐâÕÜ Ò ÔàãÓØå ÜÞÔãÛïå " +"FreePBX, ÝÐ ÚÞâÞàëÕ ÜÞÖÝÞ ÒëåÞÔØâì çÕàÕ× ÒÝãâàÕÝÝØÕ ÝÞÜÕàÐ ØÛØ ÁÕàÒØáÝëÕ ÚÞÔë." + +#: page.miscapps.php:106 +msgid "Conflicting Extensions" +msgstr "ºÞÝäÛØÚâãîéØÕ ÒÝãâàÕÝÝØÕ ÝÞÜÕàÐ" + +#: page.miscapps.php:116 +msgid "Add Misc Application" +msgstr "ŽÞÑÐÒØâì ÀÐ×ÛØçÝÞÕ ßàØÛÞÖÕÝØÕ" + +#: page.miscapps.php:118 +msgid "Description" +msgstr "ŸßØáÐÝØÕ" + +#: page.miscapps.php:118 +msgid "The name of this application" +msgstr "œÐ×ÒÐÝØÕ ßàØÛÞÖÕÝØï" + +#: page.miscapps.php:122 +msgid "Feature Code" +msgstr "ÁÕàÒØáÝëÙ ÚÞÔ" + +#: page.miscapps.php:122 +msgid "" +"The feature code/extension users can dial to access this application. This " +"can also be modified on the Feature Codes page." +msgstr "" +"ÁÕàÒØáÝëÙ ÚÞÔ ØÛØ ÒÝãâàÕÝÝØÙ ÝÞÜÕà, çÕàÕ× ÚÞâÞàëÙ ÑãÔÕâ Òë×ëÒÐâìáï íâÞ ßàØÛÞÖÕÝØÕ. " +"ÍâÞ ÜÞÖÕâ àÕÔÐÚâØàÞÒÐâìáï Ò áÕ򾯯 ÁÕàÒØáÝëÕ ÚÞÔë." + +#: page.miscapps.php:126 +msgid "Feature Status" +msgstr "ÁâÐâãá ÞßæØØ" + +#: page.miscapps.php:126 +msgid "If this code is enabled or not." +msgstr "µáÛØ ÚÞÔ ÐÚâØÒØàÞÒÐÝ ØÛØ ÝÕâ" + +#: page.miscapps.php:133 +msgid "Destination" +msgstr "œÐßàÐÒÛÕÝØÕ" + +#: page.miscapps.php:142 +msgid "Delete" +msgstr "ÃÔÐÛØâì" + +msgid "Day Night Mode" +msgstr "ŽÝÕÒÝÞÙ/œÞçÝÞÙ àÕÖØÜ" + +msgid "Terminate Call" +msgstr "ÂÕàÜØÝØàÞÒÐâì ×ÒÞÝÞÚ" + +msgid "Extensions" +msgstr "²ÝãâàÕÝÝØÕ ÝÞÜÕàÐ" + +msgid "Voicemail" +msgstr "³ÞÛÞáÞÒÐï ßÞçâÐ" + +msgid "Core" +msgstr "ŸáÝÞÒÝÐï" + +msgid "IVR" +msgstr "žÝâÕàÐÚâØÒÝÞÕ ÜÕÝî" + +msgid "Languages" +msgstr "Ï×ëÚØ" + +msgid "Conferences" +msgstr "ºÞÝäÕàÕÝæØØ" + +msgid "Phonebook Directory" +msgstr "ÂÕÛÕäÞÝÝÐï ÚÝØÓÐ" + +msgid "Queues" +msgstr "ŸçÕàÕÔØ" + +msgid "Ring Groups" +msgstr "³àãßßë Òë×ÞÒÐ" + +msgid "Speed dial functions" +msgstr "ÄãÝ򾯯 ÑëáâàÞÓÞ ÝÐÑÞàÐ" + +msgid "Time Conditions" +msgstr "¿àÐÒØÛÐ ßÞ ÒàÕÜÕÝØ" + +msgid "Custom Applications" +msgstr "ÁßÕæØÐÛìÝÞÕ ßàØÛÞÖÕÝØÕ" + +msgid "Extended Routing" +msgstr "ÀÐáèØàÕÝÝÐï ÜÐàèàãâØ×ÐæØï" + +msgid "Misc Destinations" +msgstr "ÀÐ×ÛØçÝëÕ ÝÐßàÐÒÛÕÝØï" + +msgid "Submit Changes" +msgstr "¿àØÜÕÝØâì Ø×ÜÕÝÕÝØï" Index: /modules/branches/2.6/miscapps/uninstall.php =================================================================== --- /modules/branches/2.6/miscapps/uninstall.php (revision 4583) +++ /modules/branches/2.6/miscapps/uninstall.php (revision 4583) @@ -0,0 +1,17 @@ +\n"; +} + +echo "dropping table miscapps.."; +sql("DROP TABLE IF EXISTS `miscapps`"); +echo "done
\n"; + +?> Index: /modules/branches/2.6/miscapps/page.miscapps.php =================================================================== --- /modules/branches/2.6/miscapps/page.miscapps.php (revision 6940) +++ /modules/branches/2.6/miscapps/page.miscapps.php (revision 6940) @@ -0,0 +1,170 @@ +getDefault() != $ext) { + $usage_arr = framework_check_extension_usage($ext); + if (!empty($usage_arr)) { + $conflict_url = framework_display_extension_usage_alert($usage_arr); + } + } + if (empty($conflict_url)) { + miscapps_edit($miscapp_id, $description, $ext, $dest, $enabled); + needreload(); + redirect_standard('extdisplay'); + } + break; + case 'delete': + miscapps_delete($miscapp_id); + needreload(); + redirect_standard(); + break; +} + + +?> + + +
+ +
+ +"._("Edit Misc Application").""; +} else { + echo "

"._("Add Misc Application")."

"; +} + +$helptext = _("Misc Applications are for adding feature codes that you can dial from internal phones that go to various destinations available in FreePBX. This is in contrast to the Misc Destinations module, which is for creating destinations that can be used by other FreePBX modules to dial internal numbers or feature codes."); +echo $helptext; +?> + +"._("Conflicting Extensions").""; + echo implode('
',$conflict_url); + } +?> + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

:
:
:

:

" tabindex=""> + '; } ?> +
+
+ + + Index: /modules/branches/2.6/miscapps/install.sql =================================================================== --- /modules/branches/2.6/miscapps/install.sql (revision 4245) +++ /modules/branches/2.6/miscapps/install.sql (revision 4245) @@ -0,0 +1,1 @@ +-- empty file - see http://freepbx.org/trac/ticket/1277 Index: /modules/branches/2.6/miscapps/module.xml =================================================================== --- /modules/branches/2.6/miscapps/module.xml (revision 7027) +++ /modules/branches/2.6/miscapps/module.xml (revision 7027) @@ -0,0 +1,37 @@ + + miscapps + Misc Applications + 2.5.0.3 + setup + Internal Options & Configuration + + Adds the ability to create feature codes that can go to any FreePBX destination (such as an IVR or queue) + + + Misc Applications + + + *2.5.0.3* localization enclosures, spelling + *2.5.0.2* spelling, Swedish + *2.5.0.1* #3138 Sqlite3 fixes + *2.5.0* #2845 tabindex + *2.4.0.2* #2843 Russian Translation + *2.4.0.1* added depends on 2.4.0 + *2.4.0* Extension / dest registry, it translation + *0.2.3.5* #2305 Feature Status broken + *0.2.3.3* fixed some undefined variables, bump for rc1 + *0.2.3.2* #2177: removed apparently corrupted newline at end of file + *0.2.3.1* added proper uninstall, removes any feature codes and then table + *0.2.3* #1902 miscapp always sets/pulls default code now regardless of custom override in featurecodes + *0.2.2* added SQLite3 support, fixes http://freepbx.org/trac/ticket/1775 + *0.2.1.1* changed freePBX to FreePBX + *0.2.1* merge findmefollow/core extension destinations if any + *0.2* Fix bug with adding new apps + *0.1.1* Fixed publish location for trunk/2.3 repository + + + 2.4.0 + + release/2.5/miscapps-2.5.0.3.tgz + bdb4d4fbe78bb2123f70d87ccbf24400 + Index: /modules/branches/2.6/miscapps/functions.inc.php =================================================================== --- /modules/branches/2.6/miscapps/functions.inc.php (revision 6940) +++ /modules/branches/2.6/miscapps/functions.inc.php (revision 6940) @@ -0,0 +1,151 @@ + 'app-miscapps-'.$row['miscapps_id'], + 'description'=> 'Misc Application: '.$row['description'], + 'source' => 'Misc Applications', + ); + } + return $contexts; +} + +function miscapps_get_config($engine) { + global $ext; + switch ($engine) { + case 'asterisk': + foreach (miscapps_list(true) as $row) { + if ($row['enabled']) { + $ext->add('app-miscapps-'.$row['miscapps_id'], $row['ext'], '', new ext_noop('Running miscapp '.$row['miscapps_id'].': '.$row['description'])); + $ext->add('app-miscapps-'.$row['miscapps_id'], $row['ext'], '', new ext_goto($row['dest'])); + + $ext->addInclude('from-internal-additional', 'app-miscapps-'.$row['miscapps_id']); + } + } + break; + } +} + + +/** Get a list of all miscapps + * Optional parameter is get_ext. Potentially slow, because each row is extracted from the featurecodes table + * one-by-one + */ +function miscapps_list($get_ext = false) { + global $db; + $sql = "SELECT miscapps_id, description, dest FROM miscapps ORDER BY description "; + $results = $db->getAll($sql, DB_FETCHMODE_ASSOC); + if(DB::IsError($results)) { + die_freepbx($results->getMessage()."

Error selecting from miscapps"); + } + + if ($get_ext) { + foreach (array_keys($results) as $idx) { + $fc = new featurecode('miscapps', 'miscapp_'.$results[$idx]['miscapps_id']); + $results[$idx]['ext'] = $fc->getDefault(); + $results[$idx]['enabled'] = $fc->isEnabled(); + } + } + + return $results; +} + +function miscapps_get($miscapps_id) { + global $db; + $sql = "SELECT miscapps_id, description, ext, dest FROM miscapps WHERE miscapps_id = ".$db->escapeSimple($miscapps_id); + $row = $db->getRow($sql, DB_FETCHMODE_ASSOC); + if(DB::IsError($row)) { + die_freepbx($row->getMessage()."

Error selecting row from miscapps"); + } + + // we want to get the ext from featurecodes + $fc = new featurecode('miscapps', 'miscapp_'.$row['miscapps_id']); + $row['ext'] = $fc->getDefault(); + $row['enabled'] = $fc->isEnabled(); + + return $row; +} + +function miscapps_add($description, $ext, $dest) { + global $db; + $sql = "INSERT INTO miscapps (description, ext, dest) VALUES (". + "'".$db->escapeSimple($description)."', ". + "'".$db->escapeSimple($ext)."', ". + "'".$db->escapeSimple($dest)."')"; + $result = $db->query($sql); + if(DB::IsError($result)) { + die_freepbx($result->getMessage().$sql); + } + //get id.. + $miscapps_id = $db->getOne('SELECT LAST_INSERT_ID()'); + if (DB::IsError($miscapps_id)) { + //TODO -- handle this + } + + $fc = new featurecode('miscapps', 'miscapp_'.$miscapps_id); + $fc->setDescription($description); + $fc->setDefault($ext, true); + $fc->update(); +} + +function miscapps_delete($miscapps_id) { + global $db; + $sql = "DELETE FROM miscapps WHERE miscapps_id = ".$db->escapeSimple($miscapps_id); + $result = $db->query($sql); + if(DB::IsError($result)) { + die_freepbx($result->getMessage().$sql); + } + + $fc = new featurecode('miscapps', 'miscapp_'.$miscapps_id); + $fc->delete(); +} + +function miscapps_edit($miscapps_id, $description, $ext, $dest, $enabled=true) { + global $db; + $sql = "UPDATE miscapps SET ". + "description = '".$db->escapeSimple($description)."', ". + "ext = '".$db->escapeSimple($ext)."', ". + "dest = '".$db->escapeSimple($dest)."' ". + "WHERE miscapps_id = ".$db->escapeSimple($miscapps_id); + $result = $db->query($sql); + if(DB::IsError($result)) { + die_freepbx($result->getMessage().$sql); + } + + $fc = new featurecode('miscapps', 'miscapp_'.$miscapps_id); + $fc->setDescription($description); + $fc->setDefault($ext, true); + $fc->setEnabled($enabled); + $fc->update(); +} + +function miscapps_check_destinations($dest=true) { + global $active_modules; + + $destlist = array(); + if (is_array($dest) && empty($dest)) { + return $destlist; + } + $sql = "SELECT miscapps_id, dest, description FROM miscapps "; + if ($dest !== true) { + $sql .= "WHERE dest in ('".implode("','",$dest)."')"; + } + $results = sql($sql,"getAll",DB_FETCHMODE_ASSOC); + + $type = isset($active_modules['miscapps']['type'])?$active_modules['miscapps']['type']:'setup'; + + foreach ($results as $result) { + $thisdest = $result['dest']; + $thisid = $result['miscapps_id']; + $destlist[] = array( + 'dest' => $thisdest, + 'description' => sprintf(_("Misc Application: %s"),$result['description']), + 'edit_url' => 'config.php?display=miscapps&type='.$type.'&extdisplay='.urlencode($thisid), + ); + } + return $destlist; +} + +?> Index: /modules/branches/2.6/miscapps/install.php =================================================================== --- /modules/branches/2.6/miscapps/install.php (revision 4767) +++ /modules/branches/2.6/miscapps/install.php (revision 4767) @@ -0,0 +1,37 @@ +query($sql); +if(DB::IsError($check)) { + die_freepbx("Can not create miscdests table\n"); +} +$results = array(); +$sql = "SELECT miscapps_id, dest FROM miscapps"; +$results = $db->getAll($sql, DB_FETCHMODE_ASSOC); +if (!DB::IsError($results)) { // error - table must not be there + foreach ($results as $result) { + $old_dest = $result['dest']; + $miscapps_id = $result['miscapps_id']; + + $new_dest = merge_ext_followme(trim($old_dest)); + if ($new_dest != $old_dest) { + $sql = "UPDATE miscapps SET dest = '$new_dest' WHERE miscapps_id = $miscapps_id AND dest = '$old_dest'"; + $results = $db->query($sql); + if(DB::IsError($results)) { + die_freepbx($results->getMessage()); + } + } + } +} + +?> Index: /modules/branches/2.6/fw_fop/module.xml =================================================================== --- /modules/branches/2.6/fw_fop/module.xml (revision 6495) +++ /modules/branches/2.6/fw_fop/module.xml (revision 6495) @@ -0,0 +1,17 @@ + + fw_fop + FreePBX FOP Framework + 2.5.0 + no + no + + *2.5.0* First release of fw_fop + + + This module provides a facility to install bug fixes to the FOP code that is not otherwise housed in a module, it used to be part of framework but has been removed to isolate FOP from Framework updates. + + setup + Basic + release/2.5/fw_fop-2.5.0.tgz + 8e0813a411d46cd23f180b89ddc56b44 + Index: /modules/branches/2.6/fw_fop/install.php =================================================================== --- /modules/branches/2.6/fw_fop/install.php (revision 6858) +++ /modules/branches/2.6/fw_fop/install.php (revision 6858) @@ -0,0 +1,93 @@ +'cp -rf' from src: '$src' to dst: '$dst'...details follow
"; + foreach ($errors as $error) { + echo "$error
"; + } +} + +if (! function_exists('out')) { + function out($text) { + echo $text."
"; + } +} + +if (! function_exists('outn')) { + function outn($text) { + echo $text; + } +} + +if (! function_exists('error')) { + function error($text) { + echo "[ERROR] ".$text."
"; + } +} + +if (! function_exists('fatal')) { + function fatal($text) { + echo "[FATAL] ".$text."
"; + exit(1); + } +} + +if (! function_exists('debug')) { + function debug($text) { + global $debug; + + if ($debug) echo "[DEBUG-preDB] ".$text."
"; + } +} + +global $amp_conf; +global $asterisk_conf; + +$debug = false; +$dryrun = false; + +/** verison_compare that works with freePBX version numbers + * included here because there are some older versions of functions.inc.php that do not have + * it included as it was added during 2.3.0beta1 + */ +if (!function_exists('version_compare_freepbx')) { + function version_compare_freepbx($version1, $version2, $op = null) { + $version1 = str_replace("rc","RC", strtolower($version1)); + $version2 = str_replace("rc","RC", strtolower($version2)); + if (!is_null($op)) { + return version_compare($version1, $version2, $op); + } else { + return version_compare($version1, $version2); + } + } +} + +/* + * fw_fop install script + */ + $bin_source = dirname(__FILE__)."/bin/*"; + $bin_dest = $amp_conf['AMPBIN'] + + $htdocs_panel_source = dirname(__FILE__)."/htdocs_panel/*"; + + // There was a past bug where FOPWEBROOT was pointing to AMPWEBROOT so if that is the case then hardcode + // and force to panel here. + // + $htdocs_panel_dest = $amp_conf['FOPWEBROOT']; + if ($htdocs_panel_dest == $amp_conf['AMPWEBROOT']) { + $htdocs_panel_dest .= "/panel"; + } + + exec("cp -rf $htdocs_panel_source $htdocs_panel_dest 2>&1",$out,$ret); + if ($ret != 0) { + fw_fop_print_errors($htdocs_panel_source, $htdocs_panel_dest, $out); + } + + exec("cp -rf $bin_source $bin_dest 2>&1",$out,$ret); + if ($ret != 0) { + fw_fop_print_errors($htdocs_panel_source, $bin_dest, $out); + } + +?> Index: /modules/branches/2.6/donotdisturb/i18n/sv_SE/LC_MESSAGES/donotdisturb.po =================================================================== --- /modules/branches/2.6/donotdisturb/i18n/sv_SE/LC_MESSAGES/donotdisturb.po (revision 7051) +++ /modules/branches/2.6/donotdisturb/i18n/sv_SE/LC_MESSAGES/donotdisturb.po (revision 7051) @@ -0,0 +1,35 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: FreePBX donotdisturb\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2008-09-09 12:43+0200\n" +"PO-Revision-Date: 2008-09-09 13:25+0100\n" +"Last-Translator: Mikael Carlsson \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Poedit-Language: Swedish\n" +"X-Poedit-Country: SWEDEN\n" + +#: install.php:4 +msgid "DND Activate" +msgstr "Aktivera Stör-ej" + +#: install.php:12 +msgid "DND Deactivate" +msgstr "Avaktivera Stör-ej" + +#: install.php:20 +msgid "DND Toggle" +msgstr "StÀll om Stör-ej" + +#: module.xml:3 +msgid "Do-Not-Disturb (DND)" +msgstr "Stör-ej (DND)" + Index: /modules/branches/2.6/donotdisturb/i18n/donotdisturb.pot =================================================================== --- /modules/branches/2.6/donotdisturb/i18n/donotdisturb.pot (revision 6891) +++ /modules/branches/2.6/donotdisturb/i18n/donotdisturb.pot (revision 6891) @@ -0,0 +1,33 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2008-09-17 11:14+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" + +#: install.php:4 +msgid "DND Activate" +msgstr "" + +#: install.php:12 +msgid "DND Deactivate" +msgstr "" + +#: install.php:20 +msgid "DND Toggle" +msgstr "" + +#: module.xml +msgid "Do-Not-Disturb (DND)" +msgstr "" Index: /modules/branches/2.6/donotdisturb/i18n/ru_RU/LC_MESSAGES/donotdisturb.po =================================================================== --- /modules/branches/2.6/donotdisturb/i18n/ru_RU/LC_MESSAGES/donotdisturb.po (revision 7051) +++ /modules/branches/2.6/donotdisturb/i18n/ru_RU/LC_MESSAGES/donotdisturb.po (revision 7051) @@ -0,0 +1,35 @@ +# Russian freePBX ver. translation +# Copyright (c) 2006-2008 PostMet Corporation +# This file is distributed under the same license as the freePBX package. +# Alexander Kozyrev , Sergey Nikolayev , 2006-2008. +# +# žáßÞÛì×ÞÒÐâì iconv amp.new -f UTF-8 -t ISO-8859-5 -o amp.po +# fuzzy +msgid "" +msgstr "" +"Project-Id-Version: 1.3\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2008-10-05 21:45+0100\n" +"PO-Revision-Date: 2008-10-19 16:38+0100\n" +"Last-Translator: Alexander Kozyrev \n" +"Language-Team: Russian \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=iso-8859-5\n" +"Content-Transfer-Encoding: 8bit\n" + + +#: install.php:4 +msgid "DND Activate" +msgstr "°ÚâØÒØàÞÒÐâì àÕÖØÜ œÕ ÑÕáßÞÚÞØâì " + +#: install.php:12 +msgid "DND Deactivate" +msgstr "ŽÕÐÚâØÒØàÞÒÐâì àÕÖØÜ œÕ ÑÕáßÞÚÞØâì " + +#: install.php:20 +msgid "DND Toggle" +msgstr "¿ÕàÕÚÛîçØâì àÕÖØÜ œÕ ÑÕáßÞÚÞØâì " + +#: module.xml +msgid "Do-Not-Disturb (DND)" +msgstr "ÀÕÖØÜ œÕ ÑÕáßÞÚÞØâì (DND)" Index: /modules/branches/2.6/donotdisturb/uninstall.php =================================================================== --- /modules/branches/2.6/donotdisturb/uninstall.php (revision 5858) +++ /modules/branches/2.6/donotdisturb/uninstall.php (revision 5858) @@ -0,0 +1,30 @@ +delete(); +unset($fcc); + +// Register FeatureCode - Deactivate +$fcc = new featurecode('donotdisturb', 'dnd_off'); +$fcc->delete(); +unset($fcc); + +// Register FeatureCode - Activate +$fcc = new featurecode('donotdisturb', 'dnd_toggle'); +$fcc->delete(); +unset($fcc); + +// remove all D-N-D options in effect on extensions +if ($astman) { + $astman->database_deltree('DND'); +} else { + fatal("Cannot connect to Asterisk Manager with ".$amp_conf["AMPMGRUSER"]."/".$amp_conf["AMPMGRPASS"]); +} + +?> Index: /modules/branches/2.6/donotdisturb/module.xml =================================================================== --- /modules/branches/2.6/donotdisturb/module.xml (revision 7022) +++ /modules/branches/2.6/donotdisturb/module.xml (revision 7022) @@ -0,0 +1,23 @@ + + donotdisturb + Do-Not-Disturb (DND) + 2.5.0.5 + + *2.5.0.5* #3274 + *2.5.0.4* #3215, localization fixes + *2.5.0.3* localization, xml description, Swedish + *2.5.0.2* #2969 change default value to *76 + *2.5.0.1* #2909 Add DND hints + *2.5.0* added toggle and support for func_devstate + *2.4.0* bunp for 2.4 + *1.0.2.2* changed category + *1.0.2.1* bump for rc1 + *1.0.2* changed ${CALLERID(number)} to ${AMPUSER} to accomodate CID number masquerading + *1.0.1* First release for 2.2 + + Provides donotdisturb featurecodes + setup + Internal Options & Configuration + release/2.5/donotdisturb-2.5.0.5.tgz + db24bae455ee51f3e8a5f0f7733defe7 + Index: /modules/branches/2.6/donotdisturb/functions.inc.php =================================================================== --- /modules/branches/2.6/donotdisturb/functions.inc.php (revision 6972) +++ /modules/branches/2.6/donotdisturb/functions.inc.php (revision 6972) @@ -0,0 +1,172 @@ +addGlobal('DNDDEVSTATE','TRUE'); + } + + if (is_array($featurelist = featurecodes_getModuleFeatures($modulename))) { + foreach($featurelist as $item) { + $featurename = $item['featurename']; + $fname = $modulename.'_'.$featurename; + if (function_exists($fname)) { + $fcc = new featurecode($modulename, $featurename); + $fc = $fcc->getCodeActive(); + unset($fcc); + + if ($fc != '') + $fname($fc); + } else { + $ext->add('from-internal-additional', 'debug', '', new ext_noop($modulename.": No func $fname")); + var_dump($item); + } + } + } + + $fcc = new featurecode($modulename, 'dnd_toggle'); + $dnd_code = $fcc->getCodeActive(); + unset($fcc); + + // Create hints context for DND codes so a device can subscribe to the DND state + // + if ($amp_conf['USEDEVSTATE'] && $dnd_code != '') { + $ext->addInclude('from-internal-additional','ext-dnd-hints'); + $contextname = 'ext-dnd-hints'; + $device_list = core_devices_list("all", false, true); + foreach ($device_list as $device) { + $ext->add($contextname, $dnd_code.$device['id'], '', new ext_goto("1",$dnd_code,"app-dnd-toggle")); + $ext->addHint($contextname, $dnd_code.$device['id'], "Custom:DEVDND".$device['id']); + } + } + + break; + } +} + +function donotdisturb_dnd_on($c) { + global $ext; + global $amp_conf; + global $version; + + $DEVSTATE = version_compare($version, "1.6", "ge") ? "DEVICE_STATE" : "DEVSTATE"; + + $id = "app-dnd-on"; // The context to be included + + $ext->addInclude('from-internal-additional', $id); // Add the include from from-internal + + $ext->add($id, $c, '', new ext_answer('')); // $cmd,1,Answer + $ext->add($id, $c, '', new ext_wait('1')); // $cmd,n,Wait(1) + $ext->add($id, $c, '', new ext_macro('user-callerid')); // $cmd,n,Macro(user-callerid) + $ext->add($id, $c, '', new ext_setvar('DB(DND/${AMPUSER})', 'YES')); // $cmd,n,Set(...=YES) + if ($amp_conf['USEDEVSTATE']) { + $ext->add($id, $c, '', new ext_setvar('STATE', 'BUSY')); + $ext->add($id, $c, '', new ext_gosub('1', 'sstate', $id)); + } + $ext->add($id, $c, '', new ext_playback('do-not-disturb&activated')); // $cmd,n,Playback(...) + $ext->add($id, $c, '', new ext_macro('hangupcall')); // $cmd,n,Macro(user-callerid) + if ($amp_conf['USEDEVSTATE']) { + $c = 'sstate'; + $ext->add($id, $c, '', new ext_setvar($DEVSTATE.'(Custom:DND${AMPUSER})', '${STATE}')); + $ext->add($id, $c, '', new ext_dbget('DEVICES','AMPUSER/${AMPUSER}/device')); + $ext->add($id, $c, '', new ext_gotoif('$["${DEVICES}" = "" ]', 'return')); + $ext->add($id, $c, '', new ext_setvar('LOOPCNT', '${FIELDQTY(DEVICES,&)}')); + $ext->add($id, $c, '', new ext_setvar('ITER', '1')); + $ext->add($id, $c, 'begin', new ext_setvar($DEVSTATE.'(Custom:DEVDND${CUT(DEVICES,&,${ITER})})','${STATE}')); + $ext->add($id, $c, '', new ext_setvar('ITER', '$[${ITER} + 1]')); + $ext->add($id, $c, '', new ext_gotoif('$[${ITER} <= ${LOOPCNT}]', 'begin')); + $ext->add($id, $c, 'return', new ext_return()); + } +} + +function donotdisturb_dnd_off($c) { + global $ext; + global $amp_conf; + global $version; + + $DEVSTATE = version_compare($version, "1.6", "ge") ? "DEVICE_STATE" : "DEVSTATE"; + + $id = "app-dnd-off"; // The context to be included + + $ext->addInclude('from-internal-additional', $id); // Add the include from from-internal + + $ext->add($id, $c, '', new ext_answer('')); // $cmd,1,Answer + $ext->add($id, $c, '', new ext_wait('1')); // $cmd,n,Wait(1) + $ext->add($id, $c, '', new ext_macro('user-callerid')); // $cmd,n,Macro(user-callerid) + $ext->add($id, $c, '', new ext_dbdel('DND/${AMPUSER}')); // $cmd,n,DBdel(..) + if ($amp_conf['USEDEVSTATE']) { + $ext->add($id, $c, '', new ext_setvar('STATE', 'NOT_INUSE')); + $ext->add($id, $c, '', new ext_gosub('1', 'sstate', $id)); + } + $ext->add($id, $c, '', new ext_playback('do-not-disturb&de-activated')); // $cmd,n,Playback(...) + $ext->add($id, $c, '', new ext_macro('hangupcall')); // $cmd,n,Macro(user-callerid) + if ($amp_conf['USEDEVSTATE']) { + $c = 'sstate'; + $ext->add($id, $c, '', new ext_setvar($DEVSTATE.'(Custom:DND${AMPUSER})', '${STATE}')); + $ext->add($id, $c, '', new ext_dbget('DEVICES','AMPUSER/${AMPUSER}/device')); + $ext->add($id, $c, '', new ext_gotoif('$["${DEVICES}" = "" ]', 'return')); + $ext->add($id, $c, '', new ext_setvar('LOOPCNT', '${FIELDQTY(DEVICES,&)}')); + $ext->add($id, $c, '', new ext_setvar('ITER', '1')); + $ext->add($id, $c, 'begin', new ext_setvar($DEVSTATE.'(Custom:DEVDND${CUT(DEVICES,&,${ITER})})','${STATE}')); + $ext->add($id, $c, '', new ext_setvar('ITER', '$[${ITER} + 1]')); + $ext->add($id, $c, '', new ext_gotoif('$[${ITER} <= ${LOOPCNT}]', 'begin')); + $ext->add($id, $c, 'return', new ext_return()); + } +} + +function donotdisturb_dnd_toggle($c) { + global $ext; + global $amp_conf; + global $version; + + $DEVSTATE = version_compare($version, "1.6", "ge") ? "DEVICE_STATE" : "DEVSTATE"; + + $id = "app-dnd-toggle"; // The context to be included + $ext->addInclude('from-internal-additional', $id); // Add the include from from-internal + + $ext->add($id, $c, '', new ext_answer('')); + $ext->add($id, $c, '', new ext_wait('1')); + $ext->add($id, $c, '', new ext_macro('user-callerid')); + + $ext->add($id, $c, '', new ext_gotoif('$["${DB(DND/${AMPUSER})}" = ""]', 'activate', 'deactivate')); + + $ext->add($id, $c, 'activate', new ext_setvar('DB(DND/${AMPUSER})', 'YES')); + if ($amp_conf['USEDEVSTATE']) { + $ext->add($id, $c, '', new ext_setvar('STATE', 'BUSY')); + $ext->add($id, $c, '', new ext_gosub('1', 'sstate', $id)); + } + $ext->add($id, $c, '', new ext_playback('do-not-disturb&activated')); + $ext->add($id, $c, '', new ext_macro('hangupcall')); + + $ext->add($id, $c, 'deactivate', new ext_dbdel('DND/${AMPUSER}')); + if ($amp_conf['USEDEVSTATE']) { + $ext->add($id, $c, '', new ext_setvar('STATE', 'NOT_INUSE')); + $ext->add($id, $c, '', new ext_gosub('1', 'sstate', $id)); + } + $ext->add($id, $c, '', new ext_playback('do-not-disturb&de-activated')); + $ext->add($id, $c, '', new ext_macro('hangupcall')); + if ($amp_conf['USEDEVSTATE']) { + $c = 'sstate'; + $ext->add($id, $c, '', new ext_setvar($DEVSTATE.'(Custom:DND${AMPUSER})', '${STATE}')); + $ext->add($id, $c, '', new ext_dbget('DEVICES','AMPUSER/${AMPUSER}/device')); + $ext->add($id, $c, '', new ext_gotoif('$["${DEVICES}" = "" ]', 'return')); + $ext->add($id, $c, '', new ext_setvar('LOOPCNT', '${FIELDQTY(DEVICES,&)}')); + $ext->add($id, $c, '', new ext_setvar('ITER', '1')); + $ext->add($id, $c, 'begin', new ext_setvar($DEVSTATE.'(Custom:DEVDND${CUT(DEVICES,&,${ITER})})','${STATE}')); + $ext->add($id, $c, '', new ext_setvar('ITER', '$[${ITER} + 1]')); + $ext->add($id, $c, '', new ext_gotoif('$[${ITER} <= ${LOOPCNT}]', 'begin')); + $ext->add($id, $c, 'return', new ext_return()); + } +} + +?> Index: /modules/branches/2.6/donotdisturb/install.php =================================================================== --- /modules/branches/2.6/donotdisturb/install.php (revision 6891) +++ /modules/branches/2.6/donotdisturb/install.php (revision 6891) @@ -0,0 +1,31 @@ +setDescription('DND Activate'); +$fcc->setDefault('*78'); +$fcc->update(); +unset($fcc); + +// Register FeatureCode - Deactivate +$fcc = new featurecode('donotdisturb', 'dnd_off'); +$fcc->setDescription('DND Deactivate'); +$fcc->setDefault('*79'); +$fcc->update(); +unset($fcc); + +// Register FeatureCode - Activate +$fcc = new featurecode('donotdisturb', 'dnd_toggle'); +$fcc->setDescription('DND Toggle'); +$fcc->setDefault('*76'); +$fcc->update(); +unset($fcc); + +?> Index: /modules/branches/2.6/disa/i18n/sv_SE/LC_MESSAGES/disa.po =================================================================== --- /modules/branches/2.6/disa/i18n/sv_SE/LC_MESSAGES/disa.po (revision 6961) +++ /modules/branches/2.6/disa/i18n/sv_SE/LC_MESSAGES/disa.po (revision 6961) @@ -0,0 +1,153 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: FreePBX disa\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2008-10-06 12:57+0200\n" +"PO-Revision-Date: 2008-09-28 11:22+0100\n" +"Last-Translator: Mikael Carlsson \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Poedit-Language: Swedish\n" +"X-Poedit-Country: SWEDEN\n" + +#: functions.inc.php:34 +#, php-format +msgid "DISA: %s" +msgstr "DISA: %s" + +#: page.disa.php:46 page.disa.php:65 page.disa.php:98 +msgid "Add DISA" +msgstr "LÀgg till DISA" + +#: page.disa.php:59 +msgid "deleted" +msgstr "borttagen" + +#: page.disa.php:70 +#, php-format +msgid "Delete DISA %s" +msgstr "Ta bort DISA %s" + +#: page.disa.php:98 +msgid "Edit DISA" +msgstr "Redigera DISA" + +#: page.disa.php:101 +msgid "DISA name:" +msgstr "Namn pÃ¥ DISA:" + +#: page.disa.php:101 +msgid "Give this DISA a brief name to help you identify it." +msgstr "Skriv in ett kortfattat namn för denna DISA." + +#: page.disa.php:106 +msgid "PIN" +msgstr "PIN-kod" + +#: page.disa.php:106 +msgid "The user will be prompted for this number." +msgstr "AnvÀndaren kommer att fÃ¥ en frÃ¥ga om detta nummer" + +#: page.disa.php:106 +msgid "If you wish to have multiple PIN's, seperate them with commas" +msgstr "Om du vill ha flera PIN-koder, separera dom med komma" + +#: page.disa.php:110 +msgid "Response Timeout" +msgstr "Tidsutlösning för svar" + +#: page.disa.php:110 +msgid "" +"The maximum amount of time it will wait before hanging up if the user has " +"dialled an incomplete or invalid number. Default of 10 seconds" +msgstr "" +"Den maximala tiden innan samtalet avslutas om anvÀndaren har tryckt " +"felaktiga eller ofullstÀndiga siffror. Standard Àr 10 sekunder." + +#: page.disa.php:114 +msgid "Digit Timeout" +msgstr "Tidsutlösning för siffra" + +#: page.disa.php:114 +msgid "" +"The maximum amount of time permitted between digits when the user is typing " +"in an extension. Default of 5" +msgstr "" +"Det maximalt antal sekunder som tillÃ¥ts mellan siffrorna nÀr en anvÀndare " +"trycker in en anknytning. Standard Àr 5 sekunder." + +#: page.disa.php:118 +msgid "Require Confirmation" +msgstr "KrÀver bekrÀftelse" + +#: page.disa.php:118 +msgid "" +"Require Confirmation before prompting for password. Used when your PSTN " +"connection appears to answer the call immediately" +msgstr "" +"KrÀver bekrÀftelse innan frÃ¥ga om lösenord. AnvÀnds nÀr din koppling mot " +"telenÀtet verkar svara omedelbart pÃ¥ samtalet." + +#: page.disa.php:122 +msgid "Caller ID" +msgstr "Nummerpresentation" + +#: page.disa.php:122 +msgid "" +"(Optional) When using this DISA, the users CallerID will be set to this. " +"Format is \"User Name\" <5551234>" +msgstr "" +"(Valfritt) NÀr du anvÀnder denna DISA kommer nummerpresentationen sÀttas " +"till detta. Formatet Àr \"Namn\" <123456>" + +#: page.disa.php:126 +msgid "Context" +msgstr "Sammanhang" + +#: page.disa.php:126 +msgid "" +"(Experts Only) Sets the context that calls will originate from. Leave this " +"as from-internal unless you know what you're doing." +msgstr "" +"(Endast experter) SÀtter sammanhanget samtalet ska komma frÃ¥n. Om du inte " +"vet nÃ¥got om detta, lÀmna detta till from-internal." + +#: page.disa.php:130 +msgid "Allow Hangup" +msgstr "TillÃ¥t avsluta" + +#: page.disa.php:130 +#, php-format +msgid "" +"Allow the current call to be disconnected and dial tone presented for a new " +"call by pressing the Hangup feature code: %s while in a call" +msgstr "" +"TillÃ¥ter att pÃ¥gÃ¥ende samtal kopplas ner och ett nytt samtal kan pÃ¥börjas " +"genom att trycka funktionskoden Avsluta samtal: %s" + +#: page.disa.php:134 +msgid "Submit Changes" +msgstr "Spara Àndringar" + +#: page.disa.php:145 +msgid "Please enter a valid DISA Name" +msgstr "Skriv in ett giltigt namn för denna DISA" + +#: page.disa.php:146 +msgid "Please enter a valid DISA PIN" +msgstr "Skriv in en giltig PIN-kod för denna DISA" + +#: page.disa.php:147 +msgid "Please enter a valid Caller ID or leave it blank" +msgstr "Skriv in en giltig nummerpresentation eller lÀmna fÀltet tomt" + +#: page.disa.php:148 +msgid "Context cannot be blank" +msgstr "Sammanhanget kan inte vara tomt" Index: /modules/branches/2.6/disa/i18n/he_IL/LC_MESSAGES/disa.po =================================================================== --- /modules/branches/2.6/disa/i18n/he_IL/LC_MESSAGES/disa.po (revision 3441) +++ /modules/branches/2.6/disa/i18n/he_IL/LC_MESSAGES/disa.po (revision 3441) @@ -0,0 +1,102 @@ +# Hebrew version for DISA FreePBX Module. +# Copyright (C) 2006 +# This file is distributed under the same license as the PACKAGE package. +# Shimi , 2006. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: FreePBX 2.2.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2006-10-17 17:20+0300\n" +"PO-Revision-Date: 2006-10-17 17:30+0300\n" +"Last-Translator: Shimi \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: page.disa.php:43 page.disa.php:63 page.disa.php:72 +msgid "Add" +msgstr "הוסף" + +#: page.disa.php:56 +msgid "deleted" +msgstr "נמחק" + +#: page.disa.php:65 +msgid "Delete" +msgstr "מחק" + +#: page.disa.php:72 +msgid "Edit" +msgstr "עךוך" + +#: page.disa.php:75 +msgid "name:" +msgstr "שם:" + +#: page.disa.php:75 +msgid "Give this DISA a brief name to help you identify it." +msgstr "תן ל-DISA זה שם ק׊ך שיעזוך לך לזהות אותו." + +#: page.disa.php:80 +msgid "PIN" +msgstr "סיסמא" + +#: page.disa.php:80 +msgid "The user will be prompted for this number." +msgstr "המשתמש יתבקש להכניס מס׀ך זה" + +#: page.disa.php:80 +msgid "If you wish to have multiple PIN's, seperate them with commas" +msgstr "אם ב׹שונך לישו׹ מס׀ך סיסמאות, ה׀ךד אותן ב׀סיקים" + +#: page.disa.php:84 +msgid "Response Timeout" +msgstr "זמן המתנה לתגובה" + +#: page.disa.php:84 +msgid "" +"The maximum amount of time it will wait before hanging up if the user has " +"dialled an incomplete or invalid number. Default of 10 seconds" +msgstr "הזמן המקסימלי שהמעךכת תמתין ל׀ני ניתוק אוטומטי אם המשתמש חייג מס׀ך לא שלם או שגוי. בךיךת המחדל היא 10 שניות" + +#: page.disa.php:88 +msgid "Digit Timeout" +msgstr "זמן המתנה לס׀ךה" + +#: page.disa.php:88 +msgid "" +"The maximum amount of time permitted between digits when the user is typing " +"in an extension. Default of 5" +msgstr "הזמן המקסימלי המותך בין ס׀ךות כשהמשתמש מחייג לשלוחה. בךיךת המחדל היא 5" + +#: page.disa.php:92 +msgid "Require Confirmation" +msgstr "דךוש אישוך" + +#: page.disa.php:92 +msgid "" +"Require Confirmation before prompting for password. Used when your PSTN " +"connection appears to answer the call immediately" +msgstr "דךוש אישוך ל׀ני בקשת סיסמא. נמ׊א בשימוש כאשך נ׹אה שהשיחה נענתה באו׀ן מיידי" + +#: page.disa.php:96 +msgid "Caller ID" +msgstr "שיחה מזוהה" + +#: page.disa.php:96 +msgid "" +"(Optional) When using this DISA, the users CallerID will be set to this. " +"Format is \"User Name\" <5551234>" +msgstr "(ךשות) כאשך משתמשים ב DISA זה, השיחות שת׊אנה ד׹ך ה DISA יושגו עם זיהוי שיחה מזוהה שתקבע כאן. ה׀וךמט הוא \"User Name\" <5551234>" + +#: page.disa.php:100 +msgid "Context" +msgstr "הקשך (context)" + +#: page.disa.php:100 +msgid "" +"(Experts Only) Sets the context that calls will originate from. Leave this " +"as from-internal unless you know what you're doing." +msgstr "(למומחים בלבד) מגדי׹ את ההקשך (context( שממנו י׹אה מקו׹ השיחה. השאך עךך זה בתוך from-internal אלא אם כן אתה באמת יודע מה אתה עושה." Index: /modules/branches/2.6/disa/i18n/it_IL/LC_MESSAGES/disa.po =================================================================== --- /modules/branches/2.6/disa/i18n/it_IL/LC_MESSAGES/disa.po (revision 5363) +++ /modules/branches/2.6/disa/i18n/it_IL/LC_MESSAGES/disa.po (revision 5363) @@ -0,0 +1,106 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: 1.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2007-01-26 10:40+0100\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Francesco Romano\n" +"Language-Team: Italian\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=ISO-8859-1\n" +"Content-Transfer-Encoding: 8bit\n" + +#: page.disa.php:46 page.disa.php:66 page.disa.php:75 +msgid "Add" +msgstr "Aggiungi" + +#: page.disa.php:59 +msgid "deleted" +msgstr "eliminato" + +#: page.disa.php:68 +msgid "Delete" +msgstr "Elimina" + +#: page.disa.php:75 +msgid "Edit" +msgstr "Modifica" + +#: page.disa.php:78 +msgid "name:" +msgstr "Nome:" + +#: page.disa.php:78 +msgid "Give this DISA a brief name to help you identify it." +msgstr "Dare al DISA un nome breve per una facile identificazione." + +#: page.disa.php:83 +msgid "PIN" +msgstr "PIN" + +#: page.disa.php:83 +msgid "The user will be prompted for this number." +msgstr "All'utente sarà richiesto questo numero." + +#: page.disa.php:83 +msgid "If you wish to have multiple PIN's, seperate them with commas" +msgstr "Si possono anche inserire più PIN, da separare con le virgole" + +#: page.disa.php:87 +msgid "Response Timeout" +msgstr "Timeout Risposta" + +#: page.disa.php:87 +msgid "" +"The maximum amount of time it will wait before hanging up if the user has " +"dialled an incomplete or invalid number. Default of 10 seconds" +msgstr "Il tempo massimo di tempo che il sistema attende prima di riagganciare se un utente ha digitato un numero incompleto o sbagliato. Predefinito è 10 secondi." + +#: page.disa.php:91 +msgid "Digit Timeout" +msgstr "Timeout Digitazione" + +#: page.disa.php:91 +msgid "" +"The maximum amount of time permitted between digits when the user is typing " +"in an extension. Default of 5" +msgstr "Il tempo massimo tra una digitazione e l'altra. Predefinito è 5 secondi." + +#: page.disa.php:95 +msgid "Require Confirmation" +msgstr "Richiedi Conferma" + +#: page.disa.php:95 +msgid "" +"Require Confirmation before prompting for password. Used when your PSTN " +"connection appears to answer the call immediately" +msgstr "Richiede Conferma prima della password. E' utilizzato quando la propria connessione PSTN sembra rispondere immediatamente alla chiamata." + +#: page.disa.php:99 +msgid "Caller ID" +msgstr "ID Chiamante" + +#: page.disa.php:99 +msgid "" +"(Optional) When using this DISA, the users CallerID will be set to this. " +"Format is \"User Name\" <5551234>" +msgstr "(Opzionale) Quando viene utilizzato il DISA, l'utente avrà questo ID Chiamante. Il Formato è \"Nome Utente\" <5551234>" + +#: page.disa.php:103 +msgid "Context" +msgstr "Contesto" + +#: page.disa.php:103 +msgid "" +"(Experts Only) Sets the context that calls will originate from. Leave this " +"as from-internal unless you know what you're doing." +msgstr "(Solo Esperti) Impostare il contesto da cui partiranno le chiamate. Lasciare questo su 'from-internal' se non si è sicuri." + +msgid "Submit Changes" +msgstr "Invia" Index: /modules/branches/2.6/disa/i18n/disa.pot =================================================================== --- /modules/branches/2.6/disa/i18n/disa.pot (revision 6961) +++ /modules/branches/2.6/disa/i18n/disa.pot (revision 6961) @@ -0,0 +1,140 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2008-10-06 12:57+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" + +#: functions.inc.php:34 +#, php-format +msgid "DISA: %s" +msgstr "" + +#: page.disa.php:46 page.disa.php:65 page.disa.php:98 +msgid "Add DISA" +msgstr "" + +#: page.disa.php:59 +msgid "deleted" +msgstr "" + +#: page.disa.php:70 +#, php-format +msgid "Delete DISA %s" +msgstr "" + +#: page.disa.php:98 +msgid "Edit DISA" +msgstr "" + +#: page.disa.php:101 +msgid "DISA name:" +msgstr "" + +#: page.disa.php:101 +msgid "Give this DISA a brief name to help you identify it." +msgstr "" + +#: page.disa.php:106 +msgid "PIN" +msgstr "" + +#: page.disa.php:106 +msgid "The user will be prompted for this number." +msgstr "" + +#: page.disa.php:106 +msgid "If you wish to have multiple PIN's, seperate them with commas" +msgstr "" + +#: page.disa.php:110 +msgid "Response Timeout" +msgstr "" + +#: page.disa.php:110 +msgid "" +"The maximum amount of time it will wait before hanging up if the user has " +"dialled an incomplete or invalid number. Default of 10 seconds" +msgstr "" + +#: page.disa.php:114 +msgid "Digit Timeout" +msgstr "" + +#: page.disa.php:114 +msgid "" +"The maximum amount of time permitted between digits when the user is typing " +"in an extension. Default of 5" +msgstr "" + +#: page.disa.php:118 +msgid "Require Confirmation" +msgstr "" + +#: page.disa.php:118 +msgid "" +"Require Confirmation before prompting for password. Used when your PSTN " +"connection appears to answer the call immediately" +msgstr "" + +#: page.disa.php:122 +msgid "Caller ID" +msgstr "" + +#: page.disa.php:122 +msgid "" +"(Optional) When using this DISA, the users CallerID will be set to this. " +"Format is \"User Name\" <5551234>" +msgstr "" + +#: page.disa.php:126 +msgid "Context" +msgstr "" + +#: page.disa.php:126 +msgid "" +"(Experts Only) Sets the context that calls will originate from. Leave this " +"as from-internal unless you know what you're doing." +msgstr "" + +#: page.disa.php:130 +msgid "Allow Hangup" +msgstr "" + +#: page.disa.php:130 +#, php-format +msgid "" +"Allow the current call to be disconnected and dial tone presented for a new " +"call by pressing the Hangup feature code: %s while in a call" +msgstr "" + +#: page.disa.php:134 +msgid "Submit Changes" +msgstr "" + +#: page.disa.php:145 +msgid "Please enter a valid DISA Name" +msgstr "" + +#: page.disa.php:146 +msgid "Please enter a valid DISA PIN" +msgstr "" + +#: page.disa.php:147 +msgid "Please enter a valid Caller ID or leave it blank" +msgstr "" + +#: page.disa.php:148 +msgid "Context cannot be blank" +msgstr "" Index: /modules/branches/2.6/disa/i18n/ru_RU/LC_MESSAGES/disa.po =================================================================== --- /modules/branches/2.6/disa/i18n/ru_RU/LC_MESSAGES/disa.po (revision 7044) +++ /modules/branches/2.6/disa/i18n/ru_RU/LC_MESSAGES/disa.po (revision 7044) @@ -0,0 +1,144 @@ +# Russian freePBX ver. translation +# Copyright (c) 2006-2008 PostMet Corporation +# This file is distributed under the same license as the freePBX package. +# Alexander Kozyrev , Sergey Nikolayev , 2006-2008. +# +# žáßÞÛì×ÞÒÐâì iconv amp.new -f UTF-8 -t ISO-8859-5 -o amp.po +# fuzzy +msgid "" +msgstr "" +"Project-Id-Version: 1.3\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2007-04-19 21:45+0100\n" +"PO-Revision-Date: 2008-01-16 16:38+0100\n" +"Last-Translator: Alexander Kozyrev \n" +"Language-Team: Russian \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=iso-8859-5\n" +"Content-Transfer-Encoding: 8bit\n" + +#: page.disa.php:46 page.disa.php:66 page.disa.php:75 +msgid "Add" +msgstr "ŽÞÑÐÒØâì" + +#: page.disa.php:59 +msgid "deleted" +msgstr "ãÔÐÛÕÝÞ" + +#: page.disa.php:68 +msgid "Delete" +msgstr "ÃÔÐÛØâì" + +#: page.disa.php:75 +msgid "Edit" +msgstr "ž×ÜÕÝØâì" + +#: page.disa.php:78 +msgid "name:" +msgstr "ÝÐ×ÒÐÝØÕ:" + +#: page.disa.php:78 +msgid "Give this DISA a brief name to help you identify it." +msgstr "¿àØáÒÞÙâÕ ÚÞàÞâÚÞÕ ÝÐ×ÒÐÝØÕ ÔÛï DISA ÔÛï ØÔÕÝâØäØÚÐæØØ." + +#: page.disa.php:83 +msgid "PIN" +msgstr "PIN" + +#: page.disa.php:83 +msgid "The user will be prompted for this number." +msgstr "¿ÞÛì×ÞÒÐâÕÛì ÑãÔÕâ ÒÒÞÔØâì íâÞâ ÝÞÜÕà." + +#: page.disa.php:83 +msgid "If you wish to have multiple PIN's, seperate them with commas" +msgstr "µáÛØ åÞâØâÕ ØáßÞÛì×ÞÒÐâì ÝÕáÚÞÛìÚÞ ÝÞÜÕàÞÒ PIN, ãÚÐÖØâÕ Øå àÐ×ÔÕÛïï ×ÐßïâÞÙ." + +#: page.disa.php:87 +msgid "Response Timeout" +msgstr "ÂÐÙÜÐãâ ÝÐ ÞâÒÕâ" + +#: page.disa.php:87 +msgid "" +"The maximum amount of time it will wait before hanging up if the user has " +"dialled an incomplete or invalid number. Default of 10 seconds" +msgstr "" +"ŒÐÚáØÜÐÛìÝÞÕ ÒàÕÜï ÞÖØÔÐÝØï ÔÛï ßÞÛì×ÞÒÐâÕÛï, ßàØ ÒÒÞÔÕ ÝÞÜÕàÞÒ PIN. ¿Þ ãÜÞÛçÐÝØî - 10 áÕÚ." + +#: page.disa.php:91 +msgid "Digit Timeout" +msgstr "ÂÐÙÜÐãâ ÜÕÖÔã æØäàÐÜØ" + +#: page.disa.php:91 +msgid "" +"The maximum amount of time permitted between digits when the user is typing " +"in an extension. Default of 5" +msgstr "" +"ŒÐÚáØÜÐÛìÝÞÕ ÒàÕÜï ÜÕÖÔã æØäàÐÜØ Ò ßàÞæÕááÕ ÝÐÑÞàÐ. ¿Þ ãÜÞÛçÐÝØî - 5 áÕÚ." + +#: page.disa.php:95 +msgid "Require Confirmation" +msgstr "ÂàÕÑãÕâáï ßÞÔâÒÕàÖÔÕÝØÕ" + +#: page.disa.php:95 +msgid "" +"Require Confirmation before prompting for password. Used when your PSTN " +"connection appears to answer the call immediately" +msgstr "" +"ÂàÕÑãÕâáï ßÞÔâÒÕàÖÔÕÝØÕ ßàÕÖÔÕ çÕÜ ßàÕÔÛÐÓÐâì ÝÐÑàÐâì ßÐàÞÛì. žáßÞÛì×ãÕâáï, ÚÞÓÔÐ ÒåÞÔïéØÙ " +"Òë×ÞÒ Ø× ÂÄŸ¿ ÝÕÜÕÔÛÕÝÝÞ áÞÕÔØÝïÕâáï." + +#: page.disa.php:99 +msgid "Caller ID" +msgstr "œÞÜÕà žŽ" + +#: page.disa.php:99 +msgid "" +"(Optional) When using this DISA, the users CallerID will be set to this. " +"Format is \"User Name\" <5551234>" +msgstr "" +"(ŸßæØÞÝÐÛìÝÞ) µáÛØ ØáßÞÛì×ãÕâáï íâÐ DISA, âÞ œÞÜÕà žŽ ÑãÔÕâ Ø×ÜÕÝñÝ ÝÐ ãÚÐ×ÐÝÝëÙ ×ÔÕáì. " +"ÄÞàÜÐâ \"žÜï ÄÐÜØÛØï\" <5551234>" + +#: page.disa.php:103 +msgid "Context" +msgstr "ºÞÝâÕÚáâ" + +#: page.disa.php:103 +msgid "" +"(Experts Only) Sets the context that calls will originate from. Leave this " +"as from-internal unless you know what you're doing." +msgstr "" +"(ÂÞÛìÚÞ ÔÛï íÚáßÕàâÞÒ) ÃáâÐÝÞÒØâì ÚÞÝâÕÚáâ, Ø× ÚÞâÞàÞÓÞ ÑãÔãâ ÞàØÓØÝØàÞÒÐâìáï ×ÒÞÝÚØ. " +"ŸáâÐÒØâì ÚÐÚ Õáâì - from-internal Þ×ÝÐçÐÕâ, çâÞ Òë ×ÝÐÕâÕ, çâÞ ÔÕÛÐÕâÕ." + +#: page.disa.php:130 +msgid "Allow Hangup" +msgstr "ÀÐ×àÕèØâì ßàÕàëÒÐÝØÕ ×ÒÞÝÚÐ" + +#: page.disa.php:130 +#, php-format +msgid "" +"Allow the current call to be disconnected and dial tone presented for a new " +"call by pressing the Hangup feature code: %s while in a call" +msgstr "" +"ÀÐ×àÕèØâì ßàÕàëÒÐâì âÕÚãéØÙ ×ÒÞÝÞÚ Ø ßàÕÔÞáâÐÒØâì ÔÛØÝÝëÙ ÓãÔÞÚ (º¿²) ÔÛï ÝÞÒÞÓÞ " +"×ÒÞÝÚÐ ÝÐÑÞàÞÜ áÕàÒØáÝÞÓÞ ÚÞÔÐ ¿ÞÛÞÖØâì âàãÑÚã: %s " + +msgid "Submit Changes" +msgstr "¿àØÜÕÝØâì Ø×ÜÕÝÕÝØï" + +#: page.disa.php:145 +msgid "Please enter a valid DISA Name" +msgstr "²ÒÕÔØâÕ àÐ×àÕèñÝÝÞÕ ÝÐ×ÒÐÝØÕ ÔÛï DISA " + +#: page.disa.php:146 +msgid "Please enter a valid DISA PIN" +msgstr "²ÒÕÔØâÕ àÐ×àÕèñÝÝëÙ PIN ÔÛï DISA " + +#: page.disa.php:147 +msgid "Please enter a valid Caller ID or leave it blank" +msgstr "²ÒÕÔØâÕ àÐ×àÕèñÝÝëÙ œÞÜÕà žŽ ÔÛï DISA " + +#: page.disa.php:148 +msgid "Context cannot be blank" +msgstr "ºÞÝâÕÚáâ ÝÕ ÜÞÖÕâ Ñëâì ßãáâëÜ" Index: /modules/branches/2.6/disa/page.disa.php =================================================================== --- /modules/branches/2.6/disa/page.disa.php (revision 6870) +++ /modules/branches/2.6/disa/page.disa.php (revision 6870) @@ -0,0 +1,176 @@ + +// +//This program is free software; you can redistribute it and/or +//modify it under the terms of version 2 the GNU General Public +//License as published by the Free Software Foundation. +// +//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. + + +$action = isset($_REQUEST['action'])?$_REQUEST['action']:''; +$itemid = isset($_REQUEST['itemid'])?$_REQUEST['itemid']:''; +$dispnum = "disa"; //used for switch on config.php + +//if submitting form, update database +switch ($action) { + case "add": + disa_add($_POST); + needreload(); + redirect_standard(); + break; + case "delete": + $oldItem = disa_get($itemid); + disa_del($itemid); + needreload(); + redirect_standard(); + break; + case "edit": //just delete and re-add + disa_edit($itemid,$_POST); + needreload(); + redirect_standard('itemid'); + break; +} + + +$disas = disa_list(); +?> + +
+ + + + +
+

DISA '.$oldItem["displayname"].' '._("deleted").'!

'; +} else { + //get details for this time condition + $thisItem = disa_get($itemid); +?> + +

+ '.$tlabel.''; +?> + + +
: + + +getCodeActive(); + unset($fcc); + if ($hangup_code == "") { + $hangup_code = '*'; + } +?> +
+ + + _deptname ?>"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

tabindex=""/>
"); ?>
tabindex=""/>

" tabindex="">
+ + + +
+ + Index: /modules/branches/2.6/disa/module.xml =================================================================== --- /modules/branches/2.6/disa/module.xml (revision 7021) +++ /modules/branches/2.6/disa/module.xml (revision 7021) @@ -0,0 +1,35 @@ + + disa + DISA + 2.5.1.6 + setup + Internal Options & Configuration + + DISA + + DISA Allows you 'Direct Inward System Access'. This gives you the ability to have an option on an IVR that gives you a dial tone, and you're able to dial out from the freePBX machine as if you were connected to a standard extension. It appears as a Destination. + + *2.5.1.6* localizatoin string enclosures + *2.5.1.5* #3138 Sqlite3 fixes + *2.5.1.4* #3090 replace str_replace with addslashes to better protect all input in sql + *2.5.1.3* #3074 play busy and allow another call when trunk reports busy + *2.5.1.2* #2996, #3056 allow all numbers to be dialed and update tooltip + *2.5.1.1* #2955 check if pinset file exists to avoid warnings + *2.5.1* #2922, #2949 allow consecutive calls once DISA is entered + *2.5.0* #1784, #2845 tabindex, added delete and add icons + *2.4.0.3* #2859 DISA CID not being set on trunks with default trunk CID set + *2.4.0.2* #2843 Russian Translation + *2.4.0.1* added depends on 2.4.0 + *2.4.0* #2463 no password cid fix, extension/dest registry, it translation + *2.2.3* #2463 Set CID when no pin, added support for Destination Registry + *2.2.2.2* #2172 deprecated use of |, changed category + *2.2.2.1* bump for rc1 + *2.2.2* bump so higher that 2.2 branch + *2.2* First release for FreePBX 2.2 - Fixed compatibility issue with new UI + + + 2.4.0 + + release/2.5/disa-2.5.1.6.tgz + b96cb2e1d6ccea253e1803eb08e1f8a3 + Index: /modules/branches/2.6/disa/functions.inc.php =================================================================== --- /modules/branches/2.6/disa/functions.inc.php (revision 6961) +++ /modules/branches/2.6/disa/functions.inc.php (revision 6961) @@ -0,0 +1,204 @@ + 'disa,'.$result['disa_id'].',1', 'description' => $result['displayname']); + } + return $extens; + } else { + return null; + } +} + +function disa_getdest($exten) { + return array('disa,'.$exten.',1'); +} + +function disa_getdestinfo($dest) { + global $active_modules; + + if (substr(trim($dest),0,5) == 'disa,') { + $exten = explode(',',$dest); + $exten = $exten[1]; + $thisexten = disa_get($exten); + if (empty($thisexten)) { + return array(); + } else { + //$type = isset($active_modules['announcement']['type'])?$active_modules['announcement']['type']:'setup'; + return array('description' => sprintf(_("DISA: %s"),$thisexten['displayname']), + 'edit_url' => 'config.php?display=disa&itemid='.urlencode($exten), + ); + } + } else { + return false; + } +} + +// This actually generates the dialplan +function disa_get_config($engine) { + global $ext; + switch($engine) { + case "asterisk": + $disalist = disa_list(); + if(is_array($disalist)) { + foreach($disalist as $item) { + $nopass = false; + + // delete it incase there was one from before (of course if it was deleted??? + // this should all be done properly in class, see pinsets, but for now ... + // + $filename = "/etc/asterisk/disa-".$item['disa_id'].".conf"; + if (file_exists($filename)) { + unlink($filename); + } + if (isset($item['pin']) && !empty($item['pin']) && (strtolower($item['pin']) != 'no-password')) { + // Create the disa-$id.conf file + $fh = fopen($filename, "w+"); + $pinarr = explode(',' , $item['pin'] ); + if (count($pinarr) > 1) { + $is_file = true; + foreach($pinarr as $pin) { + // Don't support remote MWI, too easy for users to break. + fwrite($fh, "$pin\n"); + } + fclose($fh); + chmod($filename, 0660); + } else { + $is_file = false; + } + } else { + $nopass = true; + } + + $thisitem = disa_get(ltrim($item['disa_id'])); + // add dialplan + + if ($thisitem['needconf'] == 'CHECKED') { + $ext->add('disa', $item['disa_id'], '', new ext_setvar('RESCOUNT', '1')); + $ext->add('disa', $item['disa_id'], 'loop', new ext_gotoif('$[ ${RESCOUNT} > 5]', 'end')); + $ext->add('disa', $item['disa_id'], '', new ext_read('RRES', 'press-1', '1', ',1,3')); + $ext->add('disa', $item['disa_id'], '', new ext_setvar('RESCOUNT', '$[${RESCOUNT}+1]')); + $ext->add('disa', $item['disa_id'], '', new ext_gotoif('$["x${RRES}"="x"]', 'loop')); + } + if (!$nopass) { + if ($is_file) { + $ext->add('disa', $item['disa_id'], '', new ext_authenticate('/etc/asterisk/disa-'.$item['disa_id'].'.conf')); + } else { + $ext->add('disa', $item['disa_id'], '', new ext_authenticate($item['pin'])); + } + } + $ext->add('disa', $item['disa_id'], '', new ext_setvar('_DISA', '"disa,'.$item['disa_id'].',newcall"')); + $ext->add('disa', $item['disa_id'], 'newcall', new ext_setvar('_DISACONTEXT', $thisitem['context'])); + $ext->add('disa', $item['disa_id'], '', new ext_setvar('_KEEPCID', 'TRUE')); + if ($thisitem['hangup'] == 'CHECKED') { + $ext->add('disa', $item['disa_id'], '', new ext_setvar('_HANGUP', 'Hg')); + } + $ext->add('disa', $item['disa_id'], '', new ext_setvar('TIMEOUT(digit)', $thisitem['digittimeout'])); + $ext->add('disa', $item['disa_id'], '', new ext_setvar('TIMEOUT(response)', $thisitem['resptimeout'])); + + if ($item['cid']) { + $ext->add('disa', $item['disa_id'], '', new ext_setvar('CALLERID(all)', $item['cid'])); + } + $ext->add('disa', $item['disa_id'], '', new ext_disa('no-password,disa-dial')); + + $ext->add('disa', $item['disa_id'], 'end', new ext_hangup('')); + } + + + $context = 'disa-dial'; + $exten = '_.'; + $ext->add($context, $exten, '', new ext_noop('called ${EXTEN} in ${DISACONTEXT} by ${DISA}')); + $ext->add($context, $exten, '', new ext_dial('Local/${EXTEN}@${DISACONTEXT}', '300,${HANGUP}')); // Regular Trunk Dial + $ext->add($context, $exten, '', new ext_gosub('1', 's-${DIALSTATUS}')); + $ext->add($context, $exten, '', new ext_goto('${DISA}')); + + $exten = 's-ANSWER'; + $ext->add($context, $exten, '', new ext_return()); + + $exten = 's-CANCEL'; + $ext->add($context, $exten, '', new ext_return()); + + $exten = 's-BUSY'; + $ext->add($context, $exten, '', new ext_playtones('busy')); + $ext->add($context, $exten, '', new ext_wait('3')); + $ext->add($context, $exten, '', new ext_return()); + + $exten = '_s-.'; + $ext->add($context, $exten, '', new ext_noop('DISA Dial failed due to ${DIALSTATUS} - returning to dial tone')); + $ext->add($context, $exten, '', new ext_playtones('congestion')); + $ext->add($context, $exten, '', new ext_wait('3')); + $ext->add($context, $exten, '', new ext_stopplaytones()); + $ext->add($context, $exten, '', new ext_return()); + } + break; + } +} + +function disa_list() { + $results = sql("SELECT * FROM disa","getAll",DB_FETCHMODE_ASSOC); + if(is_array($results)){ + foreach($results as $result){ + // check to see if we have a dept match for the current AMP User. + if (!isset($results['deptname']) || checkDept($result['deptname'])){ + // return this item's dialplan destination, and the description + $allowed[] = $result; + } + } + } + if (isset($allowed)) { + return $allowed; + } else { + return null; + } +} + +function disa_get($id){ + //get all the variables for the meetme + $results = sql("SELECT * FROM disa WHERE disa_id = '$id'","getRow",DB_FETCHMODE_ASSOC); + return $results; +} + +function disa_chk($post) { + return true; +} + +function disa_add($post) { + global $db; + if(!disa_chk($post)) { + return null; + } + extract($post); + if (!isset($needconf)) + $needconf = ''; + if(empty($displayname)) { + $displayname = "unnamed"; + } + $results = sql("INSERT INTO disa (displayname,pin,cid,context,resptimeout,digittimeout,needconf,hangup) values ('".$db->escapeSimple($displayname)."','".$db->escapeSimple($pin)."','".$db->escapeSimple($cid)."','".$db->escapeSimple($context)."', '".$db->escapeSimple($resptimeout)."', '".$db->escapeSimple($digittimeout)."', '$needconf', '$hangup')"); +} + +function disa_del($id) { + $results = sql("DELETE FROM disa WHERE disa_id = \"$id\"","query"); + unlink("/etc/asterisk/disa-{$id}.conf"); +} + +function disa_edit($id, $post) { + global $db; + if (!disa_chk($post)) { + return null; + } + extract($post); + if (!isset($needconf)) { + $needconf = ''; + } + if(empty($displayname)) { + $displayname = "unnamed"; + } + $results = sql("UPDATE disa set displayname = '".$db->escapeSimple($displayname)."', pin = '".$db->escapeSimple($pin)."', cid = '".$db->escapeSimple($cid)."', context = '".$db->escapeSimple($context)."', resptimeout = '".$db->escapeSimple($resptimeout)."', digittimeout = '".$db->escapeSimple($digittimeout)."', needconf = \"$needconf\", hangup = \"$hangup\" where disa_id = '$id'"); +} +?> Index: /modules/branches/2.6/disa/uninstall.sql =================================================================== --- /modules/branches/2.6/disa/uninstall.sql (revision 1864) +++ /modules/branches/2.6/disa/uninstall.sql (revision 1864) @@ -0,0 +1,1 @@ +DROP TABLE disa; Index: /modules/branches/2.6/disa/install.php =================================================================== --- /modules/branches/2.6/disa/install.php (revision 6176) +++ /modules/branches/2.6/disa/install.php (revision 6176) @@ -0,0 +1,63 @@ +query($sql); +if (DB::IsError($check)) { + die( "Can not create `disa` table: " . $check->getMessage() . "\n"); +} + + +// Manage upgrade from DISA 1.0 +// r2.0 Add Timeouts and add wait for confirmation +$sql = "SELECT digittimeout FROM disa"; +$check = $db->getRow($sql, DB_FETCHMODE_ASSOC); +if(DB::IsError($check)) { + // add new fields - Digit Timeout + $sql = 'ALTER TABLE disa ADD COLUMN digittimeout INT DEFAULT "5"'; + $result = $db->query($sql); + if(DB::IsError($result)) { + die_freepbx($result->getDebugInfo()); + } + // Response Timeout + $sql = 'ALTER TABLE disa ADD COLUMN resptimeout INT DEFAULT "10"'; + $result = $db->query($sql); + if(DB::IsError($result)) { + die_freepbx($result->getDebugInfo()); + } + $sql = 'ALTER TABLE disa ADD COLUMN needconf VARCHAR ( 10 ) DEFAULT ""'; + $result = $db->query($sql); + if(DB::IsError($result)) { + die_freepbx($result->getDebugInfo()); + } +} + +//update to 2.5, add hangup +// ALTER TABLE `disa` CHANGE `hangup` `hangup` VARCHAR( 10 ) + +$sql = "SELECT hangup FROM disa"; +$check = $db->getRow($sql, DB_FETCHMODE_ASSOC); +if(DB::IsError($check)) { + $sql = 'ALTER TABLE `disa` ADD COLUMN `hangup` VARCHAR( 10 )'; + $result = $db->query($sql); + if(DB::IsError($result)) { + die_freepbx($result->getDebugInfo()); + } +} + +?> Index: /modules/branches/2.6/fw_fopsvn.pl =================================================================== --- /modules/branches/2.6/fw_fopsvn.pl (revision 6498) +++ /modules/branches/2.6/fw_fopsvn.pl (revision 6498) @@ -0,0 +1,33 @@ +#!/usr/bin/perl + +# This script (sculpted from publish.pl) will check the last tarball (which must be there) +# based on the fw_fop xml version number and then run svn log against all updates since +# fw_fop was last published. +# +$rver = "2.5"; +$fw_fop = "fw_fop"; + +$moddir = 'fw_fop'; + +my $reldir = "release/"; + + open FH, "$moddir/module.xml"; + $newxml = ""; + $vers = "unset"; + while () { + if ($vers == 'unset' && /(.+)<\/version>/) { $vers = $1; } + $newxml .= $_; + } + close FH; + + die "Don't know version of $moddir" if ($vers eq "unset"); + # Automatically check in any files that were modified but weren't checked into SVN + + # Now we know the version. Get the svnversion.txt from the last update. + $filename = "../../$reldir"."$rver/$fw_fop-$vers.tgz"; + print "CHECKING VERSION: ..... "; + #print "CHECKING VERSION WITH: tar -zxOf $filename $moddir/svnversion.txt: ... "; + system("tar -zxOf ".$filename." ".$moddir."/svnversion.txt"); + print "Geting svn log since that version for $rver : .... \n\n"; + $svnver = system("svn log http://svn.freepbx.org/freepbx/branches/$rver/amp_conf/htdocs_panel -r `tar -zxOf ".$filename." ".$moddir."/svnversion.txt | sed -e s/SVN\\\ VERSION://`:HEAD"); + Index: /modules/branches/2.6/findmefollow/i18n/sv_SE/LC_MESSAGES/findmefollow.po =================================================================== --- /modules/branches/2.6/findmefollow/i18n/sv_SE/LC_MESSAGES/findmefollow.po (revision 6944) +++ /modules/branches/2.6/findmefollow/i18n/sv_SE/LC_MESSAGES/findmefollow.po (revision 6944) @@ -0,0 +1,400 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: FreePBX findmefollow\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2008-10-05 23:10+0200\n" +"PO-Revision-Date: 2008-10-11 17:11+0100\n" +"Last-Translator: Mikael Carlsson \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Poedit-Language: Swedish\n" +"X-Poedit-Country: SWEDEN\n" + +#: functions.inc.php:385 +msgid "Edit Follow Me Settings" +msgstr "Redigera Följ-mig" + +#: functions.inc.php:388 +#: functions.inc.php:392 +msgid "Add Follow Me Settings" +msgstr "LÀgg till Följ-mig" + +#: functions.inc.php:420 +#, php-format +msgid "Follow-Me: %s (%s)" +msgstr "Följ-mig: %s (%s)" + +#: install.php:4 +msgid "Findme Follow Toggle" +msgstr "StÀll om Följ-mig" + +#: install.php:141 +#: uninstall.php:31 +msgid "Cannot connect to Asterisk Manager with " +msgstr "Kan inte koppla upp mot Asterisk hanterare" + +#: install.php:159 +msgid "Checking if recordings need migration.." +msgstr "Kontrollerar om inspelningar behöver migreras.." + +#: install.php:165 +msgid "migrating" +msgstr "migrerar" + +#: install.php:166 +msgid "adding annmsg_id field.." +msgstr "lÀgger till fÀltet annmsg_id.." + +#: install.php:170 +#: install.php:179 +#: install.php:188 +#: install.php:200 +#: install.php:216 +#: install.php:226 +#: install.php:242 +#: install.php:252 +#: install.php:268 +msgid "fatal error" +msgstr "allvarligt fel" + +#: install.php:173 +#: install.php:182 +#: install.php:191 +#: install.php:282 +#: install.php:290 +#: install.php:298 +msgid "ok" +msgstr "ok" + +#: install.php:175 +msgid "adding remotealert_id field.." +msgstr "LÀgger till fÀltet remotealert_id.." + +#: install.php:184 +msgid "adding toolate_id field.." +msgstr "lÀgger till fÀltet toolate_id" + +#: install.php:196 +msgid "migrate annmsg to ids.." +msgstr "migrerar annsmg till ids..." + +#: install.php:220 +#: install.php:246 +#: install.php:272 +#, php-format +msgid "migrated %s entries" +msgstr "migrerat %s poster" + +#: install.php:222 +msgid "migrate remotealert to ids.." +msgstr "migrerar remotealerts till ids.." + +#: install.php:248 +msgid "migrate toolate to ids.." +msgstr "migrerar toolate till ids.." + +#: install.php:276 +msgid "dropping annmsg field.." +msgstr "kastar fÀltet annmsg" + +#: install.php:280 +msgid "no annmsg field???" +msgstr "inget annmsg fÀlt???" + +#: install.php:284 +msgid "dropping remotealert field.." +msgstr "kastar fÀltet remotealert" + +#: install.php:288 +msgid "no remotealert field???" +msgstr "inget remotealert fÀlt???" + +#: install.php:292 +msgid "dropping toolate field.." +msgstr "kastar fÀltet toolate.." + +#: install.php:296 +msgid "no toolate field???" +msgstr "inget toolate fÀlt???" + +#: install.php:302 +msgid "already migrated" +msgstr "redan migrerad" + +#: page.findmefollow.php:71 +msgid "Warning! Extension" +msgstr "Varning! Anknytning" + +#: page.findmefollow.php:71 +msgid "is not allowed for your account" +msgstr "Àr inte tillåtet för din anknytning" + +#: page.findmefollow.php:121 +#: page.findmefollow.php:124 +#: page.findmefollow.php:157 +msgid "Follow Me" +msgstr "Följ-mig" + +#: page.findmefollow.php:121 +msgid "Choose a user/extension:" +msgstr "VÀlj en anvÀndare/anknytning:" + +#: page.findmefollow.php:124 +msgid "deleted" +msgstr "borttagen" + +#: page.findmefollow.php:154 +msgid "Delete Entries" +msgstr "Ta bort val" + +#: page.findmefollow.php:164 +msgid "User" +msgstr "AnvÀndare" + +#: page.findmefollow.php:168 +msgid "Extension" +msgstr "Anknytning" + +#: page.findmefollow.php:171 +#, php-format +msgid "Edit %s" +msgstr "Redigera %s" + +#: page.findmefollow.php:171 +#, php-format +msgid "Edit %s %s" +msgstr "Redigera %s %s" + +#: page.findmefollow.php:180 +msgid "Edit Follow Me" +msgstr "Redigera Följ-mig" + +#: page.findmefollow.php:180 +msgid "Add Follow Me" +msgstr "LÀgg till Följ-mig" + +#: page.findmefollow.php:188 +msgid "group number" +msgstr "gruppnummer" + +#: page.findmefollow.php:188 +msgid "The number users will dial to ring extensions in this ring group" +msgstr "Nummer som ska anvÀndas för att ringa anknytningar i denna ringgrupp" + +#: page.findmefollow.php:194 +msgid "Disable" +msgstr "Avaktivera" + +#: page.findmefollow.php:194 +msgid "By default (not checked) any call to this extension will go to this Follow-Me instead, including directory calls by name from IVRs. If checked, calls will go only to the extension.
However, destinations that specify FollowMe will come here.
Checking this box is often used in conjunction with VmX Locater, where you want a call to ring the extension, and then only if the caller chooses to find you do you want it to come here." +msgstr "Som standard (inte aktiverad) kommer alla samtal till denna anknytning gå till Följ-mig. Om den Àr aktiverad kommer samtalen bara att gå till denna anknytning.
Men, destinationer som anger Följ-mig kommer hit.
Aktivering av detta val anvÀnds ofta i samband med VmX Lokatorn, nÀr du vill att samtalet ska ringa denna anknytning, och endast om uppringaren vÀljer att hitta dig kommer den hit." + +#: page.findmefollow.php:199 +msgid "Initial Ring Time:" +msgstr "Ringtid" + +#: page.findmefollow.php:200 +msgid "This is the number of seconds to ring the primary extension prior to proceeding to the follow-me list. The extension can also be included in the follow-me list. A 0 setting will bypass this." +msgstr "Det antal sekunder som det ska ringa den primÀra anknytningen innan det ringer på Följ-mig listan, sÀtt 0 för att hoppa över denna tid. Denna anknytning kan vara inkluderad i Följ-mig listan." + +#: page.findmefollow.php:217 +msgid "Ring Strategy:" +msgstr "Ringstrategi:" + +#: page.findmefollow.php:219 +msgid "ringallv2" +msgstr "ringallv2" + +#: page.findmefollow.php:219 +msgid "ring primary extension for initial ring time followed by all additional extensions until one answers" +msgstr "Ring på den primÀra anknytningen den tid som anges i Ringtid, dÀrefter alla Följ-mig anknytningarna tills någon av dom svarar" + +#: page.findmefollow.php:220 +msgid "ringall" +msgstr "ringall" + +#: page.findmefollow.php:220 +msgid "ring all available channels until one answers (default)" +msgstr "Ring alla tillgÀngliga nummer tills någon svarar (standard)" + +#: page.findmefollow.php:221 +msgid "hunt" +msgstr "hunt" + +#: page.findmefollow.php:221 +msgid "take turns ringing each available extension" +msgstr "Ring anknytningarna i tur och ordning" + +#: page.findmefollow.php:222 +msgid "memoryhunt" +msgstr "memoryhunt" + +#: page.findmefollow.php:222 +msgid "ring first extension in the list, then ring the 1st and 2nd extension, then ring 1st 2nd and 3rd extension in the list.... etc." +msgstr "Ring första numret i listan, sedan 1:a och 2:a, dÀrefter 1:a, 2:a och 3:e, ...... osv." + +#: page.findmefollow.php:223 +msgid "*-prim" +msgstr "*-prim" + +#: page.findmefollow.php:223 +msgid "these modes act as described above. However, if the primary extension (first in list) is occupied, the other extensions will not be rung. If the primary is FreePBX DND, it won't be rung. If the primary is FreePBX CF unconditional, then all will be rung" +msgstr "Gör som i lÀgena ovan. Men, om den primÀra anknytningen (första numret i listan) Àr upptagen, kommer inga andra nummer att ringas. Om den primÀra anknytningen Àr FreePBX Stör-ej kommer en inte att ringas. Om den primÀra FreePBX Konstant Vidarekopplad, kommer alla att ringas." + +#: page.findmefollow.php:224 +msgid "firstavailable" +msgstr "första tillgÀngliga" + +#: page.findmefollow.php:224 +msgid "ring only the first available channel" +msgstr "ring bara den första tillgÀngliga kanalen" + +#: page.findmefollow.php:225 +msgid "firstnotonphone" +msgstr "första-inte-upptagen" + +#: page.findmefollow.php:225 +msgid "ring only the first channel which is not off hook - ignore CW" +msgstr "ring bara den första kanalen som inte Àr upptagen - ignorera Samtal vÀntar" + +#: page.findmefollow.php:244 +msgid "Ring Time (max 60 sec)" +msgstr "Ringtid (max 60 sek)" + +#: page.findmefollow.php:246 +msgid "Time in seconds that the phones will ring. For all hunt style ring strategies, this is the time for each iteration of phone(s) that are rung" +msgstr "Tid i sekunder som telefonen kommer att ringa. För alla hunt-strategier Àr detta tiden för varje runda av telefoner som rings" + +#: page.findmefollow.php:254 +msgid "Follow-Me List" +msgstr "Följ-mig lista" + +#: page.findmefollow.php:254 +msgid "List extensions to ring, one per line, or use the Extension Quick Pick below.

You can include an extension on a remote system, or an external number by suffixing a number with a pound (#). ex: 2448089# would dial 2448089 on the appropriate trunk (see Outbound Routing)." +msgstr "Lista anknytningar att ringa, en per rad, eller vÀlj i snabblistan nedan.

Du kan inkludera en anknytning på ett fjÀrrsystem, eller ett externt nummer genom att lÀgga till en fyrkant (#) i slutet på numret. T.ex. 040592400# kommer att ringa 040592400." + +#: page.findmefollow.php:269 +msgid "Extension Quick Pick" +msgstr "Snabblista med anknytningar" + +#: page.findmefollow.php:271 +msgid "Choose an extension to append to the end of the extension list above." +msgstr "VÀlj en anknytning att lÀgga till sist i listan." + +#: page.findmefollow.php:277 +msgid "(pick extension)" +msgstr "(vÀlj anknytning)" + +#: page.findmefollow.php:290 +#: page.findmefollow.php:308 +msgid "Announcement:" +msgstr "Meddelande:" + +#: page.findmefollow.php:290 +msgid "Message to be played to the caller before dialing this group.

To add additional recordings please use the \"System Recordings\" MENU to the left" +msgstr "Meddelande som ska spelas upp för uppringaren innan det kommer att ringa denna grupp.

För att lÀgga till inspelningar, vÀlj \"Systeminspelningar\" i menyn till vÀnster." + +#: page.findmefollow.php:296 +msgid "None" +msgstr "Inget" + +#: page.findmefollow.php:308 +msgid "Message to be played to the caller before dialing this group.

You must install and enable the \"Systems Recordings\" Module to edit this option" +msgstr "Meddelande som kommer att spelas upp för uppringaren innan det ringer denna grupp.

Du måste ha installerat och aktiverat modulen \"Systeminspelningar\" för att redigera detta val." + +#: page.findmefollow.php:319 +msgid "Play Music On Hold?" +msgstr "Spela Pausmusik?" + +#: page.findmefollow.php:319 +msgid "If you select a Music on Hold class to play, instead of 'Ring', they will hear that instead of Ringing while they are waiting for someone to pick up." +msgstr "Om du valt Pausmusik i stÀllet för 'Ring' kommer uppringaren att höra musik i stÀllet för ringljud under tiden de vÀntar på att samtalet ska besvaras." + +#: page.findmefollow.php:325 +msgid "Ring" +msgstr "Ring" + +#: page.findmefollow.php:338 +msgid "CID Name Prefix" +msgstr "Prefix för nummerpresentation" + +#: page.findmefollow.php:338 +msgid "You can optionally prefix the Caller ID name when ringing extensions in this group. ie: If you prefix with \"Sales:\", a call from John Doe would display as \"Sales:John Doe\" on the extensions that ring." +msgstr "Du kan vÀlja att skriva in ett prefix för nummerpresentation för anknytningarna i denna grupp. Om du valt att skriva \"Support\", kommer det att för ett samtal från 040123456 att stå \"Support:040123456\" på alla uppringda anknytningars textfönster." + +#: page.findmefollow.php:343 +msgid "Alert Info" +msgstr "Alertinfo" + +#: page.findmefollow.php:343 +msgid "You can optionally include an Alert Info which can create distinctive rings on SIP phones." +msgstr "Du kan valfritt ange en Alertinfo som anvÀnds för att låta SIP-telefoner ringa annan signal." + +#: page.findmefollow.php:348 +msgid "Confirm Calls" +msgstr "BekrÀfta samtal" + +#: page.findmefollow.php:348 +msgid "Enable this if you're calling external numbers that need confirmation - eg, a mobile phone may go to voicemail which will pick up the call. Enabling this requires the remote side push 1 on their phone before the call is put through. This feature only works with the ringall/ringall-prim ring strategy" +msgstr "Aktivera detta om du ringer externa nummer som du vill ha bekrÀftelse från, t.ex. en mobiltelefon som ingen svarar i kommer att gå till röstbrevlådan som i sin tur kommer att svara på samtalet. Aktivering av detta val krÀver att den uppringda trycker siffran 1 innan samtalet kopplas upp. Denna funktion fungerar bara med ringall/ringall-prim strategierna." + +#: page.findmefollow.php:356 +msgid "Remote Announce:" +msgstr "FjÀrrmeddelande:" + +#: page.findmefollow.php:356 +msgid "Message to be played to the person RECEIVING the call, if 'Confirm Calls' is enabled.

To add additional recordings use the \"System Recordings\" MENU to the left" +msgstr "Meddelande att spela upp för den UPPRINGDE om 'BekrÀfta samtal' Àr aktiverat.

För att lÀgga till inspelningar vÀljer du \"Systeminspelningar\" i menyn till vÀnster." + +#: page.findmefollow.php:362 +#: page.findmefollow.php:379 +msgid "Default" +msgstr "Standard" + +#: page.findmefollow.php:373 +msgid "Too-Late Announce:" +msgstr "För-sent meddelande" + +#: page.findmefollow.php:373 +msgid "Message to be played to the person RECEIVING the call, if the call has already been accepted before they push 1.

To add additional recordings use the \"System Recordings\" MENU to the left" +msgstr "Meddelande att spela upp för den UPPRINGDE, om samtalet redan har besvarats av annan part, innan denna uppringda har tryckt 1.

För att lÀgga till inspelningar vÀljer du \"Systeminspelningar\"i menyn till vÀnster." + +#: page.findmefollow.php:391 +msgid "Destination if no answer" +msgstr "Destination vid inget svar" + +#: page.findmefollow.php:399 +msgid "Submit Changes" +msgstr "Spara Àndringar" + +#: page.findmefollow.php:426 +msgid "Invalid Group Number specified" +msgstr "Ogiltigt gruppnummer angivet" + +#: page.findmefollow.php:427 +msgid "Please enter an extension list." +msgstr "Skriv in en anknytningslista" + +#: page.findmefollow.php:428 +msgid "Invalid prefix. Valid characters: a-z A-Z 0-9 : _ -" +msgstr "Ogiltig prefix. GodkÀnda tecken Àr a-z A-Z 0-9 : _ -" + +#: page.findmefollow.php:429 +msgid "Invalid time specified" +msgstr "Ogiltig tid angiven" + +#: page.findmefollow.php:430 +msgid "Time must be between 1 and 60 seconds" +msgstr "Tiden mÃ¥ste vara mellan 1 till 60 sekunder" + +#: page.findmefollow.php:431 +msgid "Only ringall, ringallv2, hunt and the respective -prim versions are supported when confirmation is checked" +msgstr "Endast ringall, ringallv2, hunt och respektive -prim stöds nÀr bekrÀftelse krÀvs" + Index: /modules/branches/2.6/findmefollow/i18n/he_IL/LC_MESSAGES/findmefollow.po =================================================================== --- /modules/branches/2.6/findmefollow/i18n/he_IL/LC_MESSAGES/findmefollow.po (revision 3441) +++ /modules/branches/2.6/findmefollow/i18n/he_IL/LC_MESSAGES/findmefollow.po (revision 3441) @@ -0,0 +1,209 @@ +# Hebrew version for Find Me Follow FreePBX Module. +# Copyright (C) 2006 +# This file is distributed under the same license as the PACKAGE package. +# Shimi , 2006. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: FreePBX 2.2.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2006-10-17 17:20+0300\n" +"PO-Revision-Date: 2006-10-17 17:30+0300\n" +"Last-Translator: Shimi \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: page.findmefollow.php:65 +msgid "Warning! Extension" +msgstr "אזה׹ה! שלוחה" + +#: page.findmefollow.php:65 +msgid "is not allowed for your account" +msgstr "אינה מוךשית עבוך חשבונך" + +#: page.findmefollow.php:101 +msgid "$gresult[1]" +msgstr "" + +#: page.findmefollow.php:112 page.findmefollow.php:115 +#: page.findmefollow.php:144 +msgid "Follow Me" +msgstr "עקוב אח׹י" + +#: page.findmefollow.php:115 +msgid "deleted" +msgstr "נמחק" + +#: page.findmefollow.php:141 +msgid "Delete Entries" +msgstr "מחק ךשומות" + +#: page.findmefollow.php:166 +msgid "Edit Follow Me" +msgstr "עךוך עקוב אח׹י" + +#: page.findmefollow.php:166 +msgid "Add Follow Me" +msgstr "הוסף עקוב אח׹י" + +#: page.findmefollow.php:174 +msgid "group number" +msgstr "מס׀ך קבושה" + +#: page.findmefollow.php:174 +msgid "The number users will dial to ring extensions in this ring group" +msgstr "המס׀ך שאליו משתמשים יחייגו כדי לחייג לשלוחות בקבו׊ת שלשול זו" + +#: page.findmefollow.php:180 +msgid "Initial Ring Time:" +msgstr "זמן שלשול ךאשוני:" + +#: page.findmefollow.php:181 +msgid "" +"This is the number of seconds to ring the primary extension prior to " +"proceeding to the follow-me list. The extension can also be included in the " +"follow-me list. A 0 setting will bypass this." +msgstr "מס׀ך השניות שיש לשלשל לשלוחה הךאשית ל׀ני שממשיכים לךשימת העקוב-אח׹י. השלוחה יכולה להיכלל גם בךשימת העקוב-אח׹י. הגדךת 0 תעקוף זאת." + +#: page.findmefollow.php:199 +msgid "ring strategy:" +msgstr "אסטךטגיית שלשול:" + +#: page.findmefollow.php:201 +msgid "ringall" +msgstr "שלשל בכל השלוחות" + +#: page.findmefollow.php:201 +msgid "ring all available channels until one answers (default)" +msgstr "שלשל בכל העךו׊ים הזמינים עד שמישהו יענה (בךיךת מחדל)" + +#: page.findmefollow.php:202 +msgid "hunt" +msgstr "שיד" + +#: page.findmefollow.php:202 +msgid "take turns ringing each available extension" +msgstr "עבוך בתוך ושלשל בכל שלוחה זמינה" + +#: page.findmefollow.php:203 +msgid "memoryhunt" +msgstr "שיד עם זיכ׹ון" + +#: page.findmefollow.php:203 +msgid "" +"ring first extension in the list, then ring the 1st and 2nd extension, then " +"ring 1st 2nd and 3rd extension in the list.... etc." +msgstr "שלשל לשלוחה הךאשונה בךשימה, לאח׹ מכן שלשל לךאשונה ולשנייה, לאח׹ מכן לךאשונה לשנייה ולשלישית, וכך הלאה." + +#: page.findmefollow.php:204 +msgid "*-prim" +msgstr "" + +#: page.findmefollow.php:204 +msgid "" +"these modes act as described above. However, if the primary extension (first " +"in list) is occupied, the other extensions will not be rung. If the primary " +"is freepbx DND, it won't be run. If the primary is freepbx CF unconditional, " +"then all will be rung" +msgstr "משבים אלו יתנהגו כמתואך לעיל. אך, אם השלוחה הךאשית (הךאשונה בךשימה) נמ׊את בשימוש, לא יהיה שלשול לשלוחות האחךות. אם השלוחה הךאשית מוגדךת במשב נא-לא-לה׀ךיע, כנ\"ל. אם השלוחה הךאשית מוגדךת במעךכת במשב עקוב-אח׹י-בכל-משב, אזי כל השלוחות ת׊ל׊לנה." + +#: page.findmefollow.php:220 +msgid "Alert Info" +msgstr "מידע התךאה" + +#: page.findmefollow.php:224 +msgid "Confirm Calls" +msgstr "אשך שיחות" + +#: page.findmefollow.php:225 +msgid "System Recordings not installed. Option Disabled" +msgstr "מודול הקלטות מעךכת לא מותקן. הא׀שךות מבוטלת" + +#: page.findmefollow.php:231 +msgid "Remote Announce:" +msgstr "הכ׹זה למ׹וחק:" + +#: page.findmefollow.php:231 +msgid "" +"Message to be played to the person RECEIVING the call, if 'Confirm Calls' is " +"enabled.

To add additional recordings use the \"System Recordings\" " +"MENU to the left" +msgstr "הודעה אשך תושמע לאדם שמקבל את השיחה, אם הא׀שךות 'אשך שיחות' מו׀עלת.

כדי להוסיף הקלטות נוס׀ות, השתמש בת׀ךיט \"הקלטות מעךכת\" שב׊ד שמאל" + +#: page.findmefollow.php:237 page.findmefollow.php:254 +#: page.findmefollow.php:298 +msgid "None" +msgstr "אין" + +#: page.findmefollow.php:248 +msgid "Too-Late Announce:" +msgstr "הכךזת יותך-מדי-מאוח׹:" + +#: page.findmefollow.php:248 +msgid "" +"Message to be played to the person RECEIVING the call, if the call has " +"already been accepted before they push 1.

To add additional " +"recordings use the \"System Recordings\" MENU to the left" +msgstr "הודעה שתושמע לאדם שמקבל את השיחה, אם השיחה כב׹ התקבלה ל׀ני שהוא לחץ 1.

כדי להוסיף הקלטות נוס׀ות, השתמש בת׀ךיט \"הקלטות מעךכת\" שב׊ד שמאל" + +#: page.findmefollow.php:266 +msgid "extension list" +msgstr "ךשימת שלוחות" + +#: page.findmefollow.php:266 +msgid "" +"List extensions to ring, one per line.

You can include an extension " +"on a remote system, or an external number by suffixing a number with a pound " +"(#). ex: 2448089# would dial 2448089 on the appropriate trunk (see " +"Outbound Routing)." +msgstr "ךשימת שלוחות שיש לשלשל אליהן, אחת בשוךה.

אתה יכול לכלול שלוחה על מעךכת מךוחקת, או מס׀ך חישוני, על ידי הקדמת המס׀ך בסולמית (#). לדוגמא: #2448089 יחייג למס׀ך 2448089 ד׹ך מסוף הישיאה המתאים (׹אה ניתוב החושה)" + +#: page.findmefollow.php:281 +msgid "CID name prefix" +msgstr "קידומת שם זיהוי שיחות" + +#: page.findmefollow.php:287 +msgid "ring time (max 60 sec)" +msgstr "זמן שלשול (מקס 60 שניות)" + +#: page.findmefollow.php:292 page.findmefollow.php:310 +msgid "announcement:" +msgstr "הכ׹זה:" + +#: page.findmefollow.php:292 +msgid "" +"Message to be played to the caller before dialing this group.

To add " +"additional recordings please use the \"System Recordings\" MENU to the left" +msgstr "הודעה שתושמע למתקשך ל׀ני החיוג לקבושה זו.

כדי להוסיף הקלטות נוס׀ות, אנא השתמש בת׀ךיט \"הודעות מעךכת\" אשך בשד שמאל" + +#: page.findmefollow.php:310 +msgid "" +"Message to be played to the caller before dialing this group.

You " +"must install and enable the \"Systems Recordings\" Module to edit this option" +msgstr "הודעה אשך תושמע למתקשך ל׀ני החיוג לקבושה זו.

אתה חייב להתקין ולה׀עיל את המודול \"הקלטות מעךכת\" כדי לעךוך א׀שךות זו" + +#: page.findmefollow.php:320 +msgid "Play Music On Hold?" +msgstr "נגן מוסיקת המתנה?" + +#: page.findmefollow.php:320 +msgid "" +"If you select a Music on Hold class to play, instead of 'Ring', they will " +"hear that instead of Ringing while they are waiting for someone to pick up. " +"Note this DOES NOT WORK with call confirmation, due to limitations of " +"Asterisk" +msgstr "אם תבחך סוג מוסיקה לנגינה, במקום 'שלשול', הם ישמעו מוסיקה זו במקום שלשול בזמן שהם ממתינים שמישהו י׹ים את הטל׀ון. שים לב שזה לא עובד עם אישוך שיחות, בגלל מגבלות של אסטךיסק" + +#: page.findmefollow.php:326 +msgid "Ring" +msgstr "שלשול" + +#: page.findmefollow.php:338 +msgid "Destination if no answer" +msgstr "יעד אם אין מענה" + +#: install.php:67 uninstall.php:31 +msgid "Cannot connect to Asterisk Manager with " +msgstr "לא משליח להתחבך למנהל האסטךיסק עם " Index: /modules/branches/2.6/findmefollow/i18n/it_IL/LC_MESSAGES/findmefollow.po =================================================================== --- /modules/branches/2.6/findmefollow/i18n/it_IL/LC_MESSAGES/findmefollow.po (revision 5363) +++ /modules/branches/2.6/findmefollow/i18n/it_IL/LC_MESSAGES/findmefollow.po (revision 5363) @@ -0,0 +1,329 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: 1.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2007-01-26 12:34+0100\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Francesco Romano\n" +"Language-Team: Italian\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=ISO-8859-1\n" +"Content-Transfer-Encoding: 8bit\n" + +#: install.php:66 uninstall.php:30 +msgid "Cannot connect to Asterisk Manager with " +msgstr "Impossibile connettersi al manager di Asterisk con " + +#: page.findmefollow.php:68 +msgid "Warning! Extension" +msgstr "Attenzione! L'Interno" + +#: page.findmefollow.php:68 +msgid "is not allowed for your account" +msgstr "non possiede i permessi" + +#: page.findmefollow.php:107 +msgid "$gresult[1]" +msgstr "" + +#: page.findmefollow.php:118 page.findmefollow.php:121 +#: page.findmefollow.php:150 +msgid "Follow Me" +msgstr "Seguimi" + +#: page.findmefollow.php:121 +msgid "deleted" +msgstr "Eliminato" + +#: page.findmefollow.php:147 +msgid "Delete Entries" +msgstr "Elimina voci" + +#: page.findmefollow.php:172 +msgid "Edit Follow Me" +msgstr "Modifica Seguimi" + +#: page.findmefollow.php:172 +msgid "Add Follow Me" +msgstr "Aggiungi Seguimi" + +#: page.findmefollow.php:180 +msgid "group number" +msgstr "Numero gruppo" + +#: page.findmefollow.php:180 +msgid "The number users will dial to ring extensions in this ring group" +msgstr "" + +#: page.findmefollow.php:186 +msgid "Initial Ring Time:" +msgstr "Tempo inziale di squillo:" + +#: page.findmefollow.php:187 +msgid "" +"This is the number of seconds to ring the primary extension prior to " +"proceeding to the follow-me list. The extension can also be included in the " +"follow-me list. A 0 setting will bypass this." +msgstr "Questo è il numero di secondi di squillo per l'interno primario prima di far procedere la chiamata nella lista seguimi. L'interno può anche essere incluso nella lista. 0 per passarlo direttamente." + +#: page.findmefollow.php:205 +msgid "ring strategy:" +msgstr "Strategia squillo:" + +msgid "rinallv2" +msgstr "" + +msgid "ring primary extension for initial ring time followed by all additional extensions until one answers" +msgstr "squilla l'interno primario per il tempo iniziale di squillo seguito dagli altri interni fino a quando uno non risponde" + +#: page.findmefollow.php:207 +msgid "ringall" +msgstr "" + +#: page.findmefollow.php:207 +msgid "ring all available channels until one answers (default)" +msgstr "chiama tutti i canali disponibili fino a quando un interno non risponde (predefinito)" + +#: page.findmefollow.php:208 +msgid "hunt" +msgstr "" + +#: page.findmefollow.php:208 +msgid "take turns ringing each available extension" +msgstr "chiama a circolo tutti gli interni disponibili" + +#: page.findmefollow.php:209 +msgid "memoryhunt" +msgstr "" + +#: page.findmefollow.php:209 +msgid "" +"ring first extension in the list, then ring the 1st and 2nd extension, then " +"ring 1st 2nd and 3rd extension in the list.... etc." +msgstr "chiama il primo interno della lista, poi il primo e il secondo, poi il primo, il secondo e il terzo... ecc." + +#: page.findmefollow.php:210 +msgid "*-prim" +msgstr "" + +#: page.findmefollow.php:210 +msgid "" +"these modes act as described above. However, if the primary extension (first " +"in list) is occupied, the other extensions will not be rung. If the primary " +"is freepbx DND, it won't be run. If the primary is freepbx CF unconditional, " +"then all will be rung" +msgstr "queste modalità sono attuate come descritto sopra. Però, se l'interno primario (il primo della lista è occupato, gli altri interni non saranno chiamati. Se il primario ha attivato il Non Disturbare di FreePBX, non andrà avanti. Se il primario è un Trasferimento di Chiamata incondizionato attivato su FreePBX, tutti squilleranno." + +#: page.findmefollow.php:226 +msgid "Alert Info" +msgstr "" + +#: page.findmefollow.php:230 +msgid "Confirm Calls" +msgstr "Conferma Chiamate" + +#: page.findmefollow.php:231 +msgid "System Recordings not installed. Option Disabled" +msgstr "Registrazioni di Sistema non installate. Optione Disabilitata." + +#: page.findmefollow.php:237 +msgid "Remote Announce:" +msgstr "Annuncio Remoto:" + +#: page.findmefollow.php:237 +msgid "" +"Message to be played to the person RECEIVING the call, if 'Confirm Calls' is " +"enabled.

To add additional recordings use the \"System Recordings\" " +"MENU to the left" +msgstr "Il messaggio da riprodurre alla persona che RICEVE la chiamata, se è stato attivo 'Conferma Chiamate'

Per aggiungere ulteriori registrazioni utilizzare \"Registrazioni di Sistema\" nel MENU di sinistra" + +#: page.findmefollow.php:243 page.findmefollow.php:260 +msgid "Default" +msgstr "Predefinito" + +#: page.findmefollow.php:254 +msgid "Too-Late Announce:" +msgstr "Annuncio Troppo-Tardi" + +#: page.findmefollow.php:254 +msgid "" +"Message to be played to the person RECEIVING the call, if the call has " +"already been accepted before they push 1.

To add additional " +"recordings use the \"System Recordings\" MENU to the left" +msgstr "Il messaggio da riprodurre alla persona che RICEVE la chiamata, se la chiamata è già stata accettata prima di premere il tasto.

Per aggiungere ulteriori registrazioni utilizzare \"Registrazioni di Sistema\" nel MENU di sinistra" + +#: page.findmefollow.php:272 +msgid "extension list" +msgstr "Lista interni" + +#: page.findmefollow.php:272 +msgid "" +"List extensions to ring, one per line.

You can include an extension " +"on a remote system, or an external number by suffixing a number with a pound " +"(#). ex: 2448089# would dial 2448089 on the appropriate trunk (see " +"Outbound Routing)." +msgstr "Inserire gli interni o numeri da chiamare, uno per riga.

Per includere numeri esterni, inserire cancelletto (#) alla fine del numero. Es.: per chiamare 06123456789 bisgona inserire 006123456789# (se nelle Rotte in uscita è stato inserito lo 0 per le chiamate esterne)." + +#: page.findmefollow.php:287 +msgid "CID name prefix" +msgstr "Prefisso ID Chiamante" + +msgid "You can optionally prefix the Caller ID name when ringing extensions in this group. ie: If you prefix with \"Sales:\", a call from John Doe would display as \"Sales:John Doe\" on the extensions that ring." +msgstr "Come opzione si puo' inserire un prefisso prima dell'identificativo chiamante. Es.: se si inserisce \"Commerciale:\", una chiamata per Mario Rossi sarà visualizzata come \"Commerciale:Mario Rossi\" sul display del telefono che squilla." + +#: page.findmefollow.php:293 +msgid "ring time (max 60 sec)" +msgstr "Tempo di squilli (max 60 sec)" + +#: page.findmefollow.php:298 page.findmefollow.php:316 +msgid "announcement:" +msgstr "Annuncio:" + +#: page.findmefollow.php:298 +msgid "" +"Message to be played to the caller before dialing this group.

To add " +"additional recordings please use the \"System Recordings\" MENU to the left" +msgstr "Messaggio da riprodurre al chiamante prima di chiamare questo gruppo.

Per aggiungere ulteriori registrazioni utilizzare \"Registrazioni di Sistema\" nel MENU di sinistra" + +#: page.findmefollow.php:304 +msgid "None" +msgstr "Nessuno" + +#: page.findmefollow.php:316 +msgid "" +"Message to be played to the caller before dialing this group.

You " +"must install and enable the \"Systems Recordings\" Module to edit this option" +msgstr "Messaggio da rirprodurre al chiamante prima di chiamare questo gruppo.

Per utilizzare questa opzione, bisogna aver prima installato e attivato il modulo \"Registrazioni di Sistema\"" + +#: page.findmefollow.php:326 +msgid "Play Music On Hold?" +msgstr "Riproduci Musica di Attesa?" + +#: page.findmefollow.php:326 +msgid "" +"If you select a Music on Hold class to play, instead of 'Ring', they will " +"hear that instead of Ringing while they are waiting for someone to pick up." +msgstr "Se si seleziona una classe di Musica di Attesa, invece che 'Squillo', l'utente ascolterà questa mentre è in attesa di una risposta." + +#: page.findmefollow.php:332 +msgid "Ring" +msgstr "Squillo" + +#: page.findmefollow.php:344 +msgid "Destination if no answer" +msgstr "Destinzione se nessuna risposta" + +msgid "Core" +msgstr "Sistema" + +msgid "Conferences" +msgstr "Conferenze" + +msgid "Phonebook Directory" +msgstr "Rubrica" + +msgid "Queues" +msgstr "Code" + +msgid "Ring Groups" +msgstr "Gruppi di chiamata" + +msgid "Speed dial functions" +msgstr "Selezione breve" + +msgid "Time Conditions" +msgstr "Condizioni Temporali" + +msgid "Custom Contexts" +msgstr "Contesti Personalizzati" + +msgid "Extended Routing" +msgstr "Rotte specifiche" + +msgid "Custom App
ADVANCED USERS ONLY

Uses Goto() to send caller to a custom context.

The context name should start with \"custom-\", and be in the format custom-context,extension,priority. Example entry:

custom-myapp,s,1

The [custom-myapp] context would need to be created and included in extensions_custom.conf
" +msgstr "Applicazione PersonalizzataSOLO UTENTI AVANZATI
Utilizzare Goto() per inviare la chiamata verso un contesto personalizzato.

Il nome del contesto deve iniziare per \"custom-\" e deve essere nel formato custom-contesto,extension,priorità. Esempio:

custom-app,s,1

Il contesto [custom-app] deve poi essere creato e incluso nel file extensions_custom.conf" +"However, destinations that specify FollowMe will come here.
" +"Checking this box is often used in conjunction with VmX Locater, where you want a call to ring the extension, and then only if the caller chooses to find you do you want it to come here." +msgstr "Nell'impostazione predefinita (non selezionato) tutte le chiamate su questo interno andranno al Seguimi, incluse le chiamate da un IVR. Se selezionato, le chiamate andranno solo all'interno.
Questa opzione è di solito usata insieme al VmX Locator, dove si puo' scegliere se inviare il chiamante al seguimi." + +msgid "Ring Strategy:" +msgstr "Strategia di Squillo:" + +msgid "(edit)" +msgstr "(modifica)" + +msgid "Edit Extension %s" +msgstr "Modifica Interno %s" + +msgid "Edit Follow Me Settings" +msgstr "Modifica impostazioni Seguimi" + +#: page.ringgroups.php:187 +msgid "firstavailable" +msgstr "" + +#: page.ringgroups.php:187 +msgid "ring only the first available channel" +msgstr "squilla solo il primo disponibile" + +#: page.ringgroups.php:188 +msgid "firstnotonphone" +msgstr "" + +#: page.ringgroups.php:188 +msgid "ring only the first channel which is not offhook - ignore CW" +msgstr "squilla solo il primo che è al telefono - ignora Avviso di Chiamata" Index: /modules/branches/2.6/findmefollow/i18n/findmefollow.pot =================================================================== --- /modules/branches/2.6/findmefollow/i18n/findmefollow.pot (revision 6944) +++ /modules/branches/2.6/findmefollow/i18n/findmefollow.pot (revision 6944) @@ -0,0 +1,427 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2008-10-05 23:10+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" + +#: functions.inc.php:385 +msgid "Edit Follow Me Settings" +msgstr "" + +#: functions.inc.php:388 functions.inc.php:392 +msgid "Add Follow Me Settings" +msgstr "" + +#: functions.inc.php:420 +#, php-format +msgid "Follow-Me: %s (%s)" +msgstr "" + +#: install.php:4 +msgid "Findme Follow Toggle" +msgstr "" + +#: install.php:141 uninstall.php:31 +msgid "Cannot connect to Asterisk Manager with " +msgstr "" + +#: install.php:159 +msgid "Checking if recordings need migration.." +msgstr "" + +#: install.php:165 +msgid "migrating" +msgstr "" + +#: install.php:166 +msgid "adding annmsg_id field.." +msgstr "" + +#: install.php:170 install.php:179 install.php:188 install.php:200 +#: install.php:216 install.php:226 install.php:242 install.php:252 +#: install.php:268 +msgid "fatal error" +msgstr "" + +#: install.php:173 install.php:182 install.php:191 install.php:282 +#: install.php:290 install.php:298 +msgid "ok" +msgstr "" + +#: install.php:175 +msgid "adding remotealert_id field.." +msgstr "" + +#: install.php:184 +msgid "adding toolate_id field.." +msgstr "" + +#: install.php:196 +msgid "migrate annmsg to ids.." +msgstr "" + +#: install.php:220 install.php:246 install.php:272 +#, php-format +msgid "migrated %s entries" +msgstr "" + +#: install.php:222 +msgid "migrate remotealert to ids.." +msgstr "" + +#: install.php:248 +msgid "migrate toolate to ids.." +msgstr "" + +#: install.php:276 +msgid "dropping annmsg field.." +msgstr "" + +#: install.php:280 +msgid "no annmsg field???" +msgstr "" + +#: install.php:284 +msgid "dropping remotealert field.." +msgstr "" + +#: install.php:288 +msgid "no remotealert field???" +msgstr "" + +#: install.php:292 +msgid "dropping toolate field.." +msgstr "" + +#: install.php:296 +msgid "no toolate field???" +msgstr "" + +#: install.php:302 +msgid "already migrated" +msgstr "" + +#: page.findmefollow.php:71 +msgid "Warning! Extension" +msgstr "" + +#: page.findmefollow.php:71 +msgid "is not allowed for your account" +msgstr "" + +#: page.findmefollow.php:121 page.findmefollow.php:124 +#: page.findmefollow.php:157 +msgid "Follow Me" +msgstr "" + +#: page.findmefollow.php:121 +msgid "Choose a user/extension:" +msgstr "" + +#: page.findmefollow.php:124 +msgid "deleted" +msgstr "" + +#: page.findmefollow.php:154 +msgid "Delete Entries" +msgstr "" + +#: page.findmefollow.php:164 +msgid "User" +msgstr "" + +#: page.findmefollow.php:168 +msgid "Extension" +msgstr "" + +#: page.findmefollow.php:171 +#, php-format +msgid "Edit %s" +msgstr "" + +#: page.findmefollow.php:171 +#, php-format +msgid "Edit %s %s" +msgstr "" + +#: page.findmefollow.php:180 +msgid "Edit Follow Me" +msgstr "" + +#: page.findmefollow.php:180 +msgid "Add Follow Me" +msgstr "" + +#: page.findmefollow.php:188 +msgid "group number" +msgstr "" + +#: page.findmefollow.php:188 +msgid "The number users will dial to ring extensions in this ring group" +msgstr "" + +#: page.findmefollow.php:194 +msgid "Disable" +msgstr "" + +#: page.findmefollow.php:194 +msgid "" +"By default (not checked) any call to this extension will go to this Follow-" +"Me instead, including directory calls by name from IVRs. If checked, calls " +"will go only to the extension.
However, destinations that specify " +"FollowMe will come here.
Checking this box is often used in conjunction " +"with VmX Locater, where you want a call to ring the extension, and then only " +"if the caller chooses to find you do you want it to come here." +msgstr "" + +#: page.findmefollow.php:199 +msgid "Initial Ring Time:" +msgstr "" + +#: page.findmefollow.php:200 +msgid "" +"This is the number of seconds to ring the primary extension prior to " +"proceeding to the follow-me list. The extension can also be included in the " +"follow-me list. A 0 setting will bypass this." +msgstr "" + +#: page.findmefollow.php:217 +msgid "Ring Strategy:" +msgstr "" + +#: page.findmefollow.php:219 +msgid "ringallv2" +msgstr "" + +#: page.findmefollow.php:219 +msgid "" +"ring primary extension for initial ring time followed by all additional " +"extensions until one answers" +msgstr "" + +#: page.findmefollow.php:220 +msgid "ringall" +msgstr "" + +#: page.findmefollow.php:220 +msgid "ring all available channels until one answers (default)" +msgstr "" + +#: page.findmefollow.php:221 +msgid "hunt" +msgstr "" + +#: page.findmefollow.php:221 +msgid "take turns ringing each available extension" +msgstr "" + +#: page.findmefollow.php:222 +msgid "memoryhunt" +msgstr "" + +#: page.findmefollow.php:222 +msgid "" +"ring first extension in the list, then ring the 1st and 2nd extension, then " +"ring 1st 2nd and 3rd extension in the list.... etc." +msgstr "" + +#: page.findmefollow.php:223 +msgid "*-prim" +msgstr "" + +#: page.findmefollow.php:223 +msgid "" +"these modes act as described above. However, if the primary extension (first " +"in list) is occupied, the other extensions will not be rung. If the primary " +"is FreePBX DND, it won't be rung. If the primary is FreePBX CF " +"unconditional, then all will be rung" +msgstr "" + +#: page.findmefollow.php:224 +msgid "firstavailable" +msgstr "" + +#: page.findmefollow.php:224 +msgid "ring only the first available channel" +msgstr "" + +#: page.findmefollow.php:225 +msgid "firstnotonphone" +msgstr "" + +#: page.findmefollow.php:225 +msgid "ring only the first channel which is not off hook - ignore CW" +msgstr "" + +#: page.findmefollow.php:244 +msgid "Ring Time (max 60 sec)" +msgstr "" + +#: page.findmefollow.php:246 +msgid "" +"Time in seconds that the phones will ring. For all hunt style ring " +"strategies, this is the time for each iteration of phone(s) that are rung" +msgstr "" + +#: page.findmefollow.php:254 +msgid "Follow-Me List" +msgstr "" + +#: page.findmefollow.php:254 +msgid "" +"List extensions to ring, one per line, or use the Extension Quick Pick below." +"

You can include an extension on a remote system, or an external " +"number by suffixing a number with a pound (#). ex: 2448089# would dial " +"2448089 on the appropriate trunk (see Outbound Routing)." +msgstr "" + +#: page.findmefollow.php:269 +msgid "Extension Quick Pick" +msgstr "" + +#: page.findmefollow.php:271 +msgid "Choose an extension to append to the end of the extension list above." +msgstr "" + +#: page.findmefollow.php:277 +msgid "(pick extension)" +msgstr "" + +#: page.findmefollow.php:290 page.findmefollow.php:308 +msgid "Announcement:" +msgstr "" + +#: page.findmefollow.php:290 +msgid "" +"Message to be played to the caller before dialing this group.

To add " +"additional recordings please use the \"System Recordings\" MENU to the left" +msgstr "" + +#: page.findmefollow.php:296 +msgid "None" +msgstr "" + +#: page.findmefollow.php:308 +msgid "" +"Message to be played to the caller before dialing this group.

You " +"must install and enable the \"Systems Recordings\" Module to edit this option" +msgstr "" + +#: page.findmefollow.php:319 +msgid "Play Music On Hold?" +msgstr "" + +#: page.findmefollow.php:319 +msgid "" +"If you select a Music on Hold class to play, instead of 'Ring', they will " +"hear that instead of Ringing while they are waiting for someone to pick up." +msgstr "" + +#: page.findmefollow.php:325 +msgid "Ring" +msgstr "" + +#: page.findmefollow.php:338 +msgid "CID Name Prefix" +msgstr "" + +#: page.findmefollow.php:338 +msgid "" +"You can optionally prefix the Caller ID name when ringing extensions in this " +"group. ie: If you prefix with \"Sales:\", a call from John Doe would display " +"as \"Sales:John Doe\" on the extensions that ring." +msgstr "" + +#: page.findmefollow.php:343 +msgid "Alert Info" +msgstr "" + +#: page.findmefollow.php:343 +msgid "" +"You can optionally include an Alert Info which can create distinctive rings " +"on SIP phones." +msgstr "" + +#: page.findmefollow.php:348 +msgid "Confirm Calls" +msgstr "" + +#: page.findmefollow.php:348 +msgid "" +"Enable this if you're calling external numbers that need confirmation - eg, " +"a mobile phone may go to voicemail which will pick up the call. Enabling " +"this requires the remote side push 1 on their phone before the call is put " +"through. This feature only works with the ringall/ringall-prim ring strategy" +msgstr "" + +#: page.findmefollow.php:356 +msgid "Remote Announce:" +msgstr "" + +#: page.findmefollow.php:356 +msgid "" +"Message to be played to the person RECEIVING the call, if 'Confirm Calls' is " +"enabled.

To add additional recordings use the \"System Recordings\" " +"MENU to the left" +msgstr "" + +#: page.findmefollow.php:362 page.findmefollow.php:379 +msgid "Default" +msgstr "" + +#: page.findmefollow.php:373 +msgid "Too-Late Announce:" +msgstr "" + +#: page.findmefollow.php:373 +msgid "" +"Message to be played to the person RECEIVING the call, if the call has " +"already been accepted before they push 1.

To add additional " +"recordings use the \"System Recordings\" MENU to the left" +msgstr "" + +#: page.findmefollow.php:391 +msgid "Destination if no answer" +msgstr "" + +#: page.findmefollow.php:399 +msgid "Submit Changes" +msgstr "" + +#: page.findmefollow.php:426 +msgid "Invalid Group Number specified" +msgstr "" + +#: page.findmefollow.php:427 +msgid "Please enter an extension list." +msgstr "" + +#: page.findmefollow.php:428 +msgid "Invalid prefix. Valid characters: a-z A-Z 0-9 : _ -" +msgstr "" + +#: page.findmefollow.php:429 +msgid "Invalid time specified" +msgstr "" + +#: page.findmefollow.php:430 +msgid "Time must be between 1 and 60 seconds" +msgstr "" + +#: page.findmefollow.php:431 +msgid "" +"Only ringall, ringallv2, hunt and the respective -prim versions are " +"supported when confirmation is checked" +msgstr "" Index: /modules/branches/2.6/findmefollow/i18n/ru_RU/LC_MESSAGES/findmefollow.po =================================================================== --- /modules/branches/2.6/findmefollow/i18n/ru_RU/LC_MESSAGES/findmefollow.po (revision 6877) +++ /modules/branches/2.6/findmefollow/i18n/ru_RU/LC_MESSAGES/findmefollow.po (revision 6877) @@ -0,0 +1,417 @@ +# Russian freePBX ver. translation +# Copyright (c) 2006-2008 PostMet Corporation +# This file is distributed under the same license as the freePBX package. +# Alexander Kozyrev , Sergey Nikolayev , 2006-2008. +# +# žáßÞÛì×ÞÒÐâì iconv amp.new -f UTF-8 -t ISO-8859-5 -o amp.po +# fuzzy +msgid "" +msgstr "" +"Project-Id-Version: 1.3\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2007-04-19 21:45+0100\n" +"PO-Revision-Date: 2008-01-31 16:38+0100\n" +"Last-Translator: Alexander Kozyrev \n" +"Language-Team: Russian \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=iso-8859-5\n" +"Content-Transfer-Encoding: 8bit\n" + +#: functions.inc.php:388 functions.inc.php:392 +msgid "Add Follow Me Settings" +msgstr "ŽÞÑÐÒØâì ÝÐáâàÞÙÚØ äãÝ򾯯 ÁÛÕÔãÙâÕ áîÔÐ" + +#: install.php:44 +msgid "Findme Follow Toggle" +msgstr "¿ÕàÕÚÛîçÕÝØÕ œÐÙâØ ÜÕÝï âãâ" + +#: install.php:66 uninstall.php:30 +msgid "Cannot connect to Asterisk Manager with " +msgstr "œÕÒÞ×ÜÞÖÝÞ áÞÕÔØÝØâáï á Asterisk Manager ÚÐÚ " + +#: page.findmefollow.php:68 +msgid "Warning! Extension" +msgstr "²ÝØÜÐÝØÕ! ²ÝãâàÕÝÝØÙ ÝÞÜÕà" + +#: page.findmefollow.php:68 +msgid "is not allowed for your account" +msgstr "ÝÕ àÐ×àÕèÕÝ Ú ØáßÞÛì×ÞÒÐÝØî Ò ÒÐèÕÜ ÐÚÚÐãÝâÕ" + +#: page.findmefollow.php:107 +msgid "$gresult[1]" +msgstr "" + +#: page.findmefollow.php:118 page.findmefollow.php:121 +#: page.findmefollow.php:150 +msgid "Follow Me" +msgstr "ÁÛÕÔãÙâÕ áîÔÐ" + +#: page.findmefollow.php:121 +msgid "deleted" +msgstr "ãÔÐÛÕÝÞ" + +#: page.findmefollow.php:147 +msgid "Delete Entries" +msgstr "ÃÔÐÛØâì ×Ðߨáì" + +#: page.findmefollow.php:172 +msgid "Edit Follow Me" +msgstr "ž×ÜÕÝØâì ãÚÐ×ÐÝØÕ ÁÛÕÔãÙâÕ áîÔÐ" + +#: page.findmefollow.php:172 +msgid "Add Follow Me" +msgstr "ŽÞÑÐÒØâì ãÚÐ×ÐÝØÕ ÁÛÕÔãÙâÕ áîÔÐ" + +#: page.findmefollow.php:180 +msgid "group number" +msgstr "ÓàãßßÞÒÞÙ ÝÞÜÕà" + +#: page.findmefollow.php:180 +msgid "The number users will dial to ring extensions in this ring group" +msgstr "œÞÜÕà, ÝÐ ÚÞâÞàëÙ ÜÞÖÝÞ ßÞ×ÒÞÝØâì áàÐ×ã ÒÞ Òáî Óàãßßã Òë×ÞÒÐ" + +#: page.findmefollow.php:186 +msgid "Initial Ring Time:" +msgstr "œÐçÐÛìÝÞÕ ÒàÕÜï ×ÒÞÝÚÐ:" + +#: page.findmefollow.php:187 +msgid "" +"This is the number of seconds to ring the primary extension prior to " +"proceeding to the follow-me list. The extension can also be included in the " +"follow-me list. A 0 setting will bypass this." +msgstr "" +"²àÕÜï Ò áÕÚãÝÔÐå, Ò âÕçÕÝØÕ ÚÞâÞàÞÓÞ ×ÒÞÝÞÚ ÞâàÐÑÐâëÒÐÕâ ÝÐ ßÕàÒÞÜ ÝÐ×ÝÐçÕÝØØ " +"(ÒÝãâàÕÝÝÕÜ ÝÞÜÕàÕ), ßÞáÛÕ çÕÓÞ áÛÕÔãÕâ ßÞ ÝÐßàÐÒÛÕÝØî, ×ÐÔÐÝÝÞÜã ãÚÐ×ÐÝØÕÜ " +"ÁÛÕÔãÙâÕ áîÔÐ. ·ÝÐçÕÝØÕ 0 ÑãÔÕâ ßàÞßãáÚÐâì ßÕàÒëÙ èÐÓ." + +#: page.findmefollow.php:205 +msgid "ring strategy:" +msgstr "áâàÐâÕÓØï ×ÒÞÝÚÞÒ:" + +msgid "rinallv2" +msgstr "1-×ÒÞÝïâ-ÒáÕ" + +msgid "ring primary extension for initial ring time followed by all additional extensions until one answers" +msgstr "" +"×ÒÕÝØâ ßÕàÒëÙ ÒÝãâàÕÝÝØÙ ÝÞÜÕà ÒâÕçÕÝØÕ ãÚÐ×ÐÝÝÞÓÞ ÒàÕÜÕÝØ (ÒëèÕ), ×ÐâÕÜ ÒáÕ ÒÝãâàÕÝÝØÕ " +"ÝÞÜÕàÐ Ø× áߨáÚÐ, ßÞÚÐ ÚâÞ ÛØÑÞ ÞÔØÝ ÝÕ ÞâÒÕâØâ" + +#: page.findmefollow.php:207 +msgid "ringall" +msgstr "×ÒÞÝïâ-ÒáÕ" + +#: page.findmefollow.php:207 +msgid "ring all available channels until one answers (default)" +msgstr "×ÒÞÝïâ ÒáÕ ÔÞáâãßÝëÕ ÝÞÜÕàÐ Ø× áߨáÚÐ, ßÞÚÐ ÚâÞ ÛØÑÞ ÞÔØÝ ÝÕ ÞâÒÕâØâ." + +#: page.findmefollow.php:208 +msgid "hunt" +msgstr "áÕàØÙÝÞÕ-ØáÚÐÝØÕ" + +#: page.findmefollow.php:208 +msgid "take turns ringing each available extension" +msgstr "×ÒÞÝÞÚ ßÞáâãßÐÕâ ÝÐ ÛîÑÞÙ ÔÞáâãßÝëÙ Ø× ÝÞÜÕàÞÒ ßÞ áߨáÚã" + +#: page.findmefollow.php:209 +msgid "memoryhunt" +msgstr "ßàÞÓàÕáá-áÕàØÙÝÞÕ-ØáÚÐÝØÕ" + +#: page.findmefollow.php:209 +msgid "" +"ring first extension in the list, then ring the 1st and 2nd extension, then " +"ring 1st 2nd and 3rd extension in the list.... etc." +msgstr "" +"·ÒÞÝØâ ßÕàÒëÙ ÒÝãâàÕÝÝØÙ ÝÞÜÕà Ò áߨáÚÕ, ×ÐâÕÜ ßÕàÒëÙ Ø ÒâÞàÞÙ, ×ÐâÕÜ ßÕàÒëÙ, ÒâÞàÞÙ " +"Ø âàÕâØÙ Ò áߨáÚÕ, Ø âÐÚ ÔÐÛÕÕ." + +#: page.ringgroups.php:186 +msgid "*-prim" +msgstr "*-ßàØÜ" + +#: page.ringgroups.php:186 +msgid "" +"These modes act as described above. However, if the primary extension (first " +"in list) is occupied, the other extensions will not be rung. If the primary " +"is FreePBX DND, it won't be rung. If the primary is FreePBX CF " +"unconditional, then all will be rung" +msgstr "" +"ÍâÞâ àÕÖØÜ àÐÑÞâÐÕâ âÐÚ ÖÕ, ÚÐÚ ÒëèÕÞߨáÐÝÝëÕ, ×Ð ØáÚÛîçÕÝØÕÜ âÞÓÞ, çâÞ ÕáÛØ ßÕàÒëÙ " +"ÒÝãâàÕÝÝØÙ ÝÞÜÕà Ø× áߨáÚÐ ×ÐÝïâ, áÛÕÔãîéØÕ ßÞ áߨáÚã ÝÕ ÑãÔãâ ×ÒÞÝØâì. ÂÐÚÖÕ ×ÐÒØáØâ Þâ " +"ãáâÐÝÞÒÞÚ 'œÕ ÑÕáßÞÚÞØâì' Ø '¿ÕàÕÝÐßàÐÒÛÕÝØÕ' ÝÐ ßÕàÒÞÜ ÒÝãâàÕÝÝÕÜ ÝÞÜÕàÕ áߨáÚÐ. µáÛØ " +"DND, âÞ ßÞØáÚ Ò ÓàãßßÕ ÝÐ íâÞÜ ×ÐÚÐÝçØÒÐÕâáï. µáÛØ CF (ßÕàÕÝÐßàÐÒÛÕÝØÕ) ÝÕ ßÕàÕÝÐßàÐÒØâ, " +"âÞ ßÞØáÚ Ò ÓàãßßÕ ßàÞÔÞÛÖØâáï." + +#: page.ringgroups.php:187 +msgid "firstavailable" +msgstr "ßÕàÒëÙ-ÔÞáâãßÝëÙ" + +#: page.ringgroups.php:187 +msgid "ring only the first available channel" +msgstr "×ÒÞÝØâ ßÕàÒëÙ ÔÞáâãßÝëÙ ÚÐÝÐÛ" + +#: page.ringgroups.php:188 +msgid "firstnotonphone" +msgstr "ßÕàÒëÙ-ÝÐ-âÕÛÕäÞÝÕ" + +#: page.ringgroups.php:188 +msgid "ring only the first channel which is not offhook - ignore CW" +msgstr "×ÒÞÝØâ ßÕàÒëÙ âÕÛÕäÞÝ, ã ÚÞâÞàÞÓÞ ÝÕ áÝïâÐ âàãÑÚÐ - äÞàÒÐàÔØÝÓ ØÓÝÞàØàãÕâáï" + + +#: page.findmefollow.php:226 +msgid "Alert Info" +msgstr "ŽÞßÞÛÝØâÕÛìÝÐï ØÝäÞàÜÐæØï" + +#: page.findmefollow.php:230 +msgid "Confirm Calls" +msgstr "¿ÞÔâÒÕàÖÔÐâì Òë×ÞÒë" + +#: page.findmefollow.php:231 +msgid "System Recordings not installed. Option Disabled" +msgstr "·Ðߨáì áÞÞÑéÕÝØÙ ÝÕ ßàÞØÝáâÐÛÛØàÞÒÐÝÐ. ŸßæØï ÝÕÔÞáâãßÝÐ" + +#: page.findmefollow.php:237 +msgid "Remote Announce:" +msgstr "ÃÔÐÛñÝÝÞÕ ßàØÒÕâáâÒØÕ:" + +#: page.findmefollow.php:237 +msgid "" +"Message to be played to the person RECEIVING the call, if 'Confirm Calls' is " +"enabled.

To add additional recordings use the \"System Recordings\" " +"MENU to the left" +msgstr "" +"ÁÞÞÑéÕÝØÕ, ÚÞâÞàÞÕ ÑãÔÕâ ÒÞáßàÞØ×ÒÕÔÕÝÞ ÔÛï ÐÔàÕáÐâÐ ×ÒÞÝÚÐ, ÕáÛØ ×ÐÔÕÙáâÒÞÒÐÝÐ ÞßæØï " +"¿ÞÔâÒÕàÖÔÕÝØÕ Òë×ÞÒÐ.

ŽÞÑÐÒØâì ×Ðߨáì ÜÞÖÝÞ Ò áÕ򾯯 ·Ðߨáì áÞÞÑéÕÝØÙ Ò ÜÕÝî áÛÕÒÐ." + +#: page.findmefollow.php:243 page.findmefollow.php:260 +msgid "Default" +msgstr "¿Þ ãÜÞÛçÐÝØî" + +#: page.findmefollow.php:254 +msgid "Too-Late Announce:" +msgstr "ÁÞÞÑéÕÝØÕ ÃÖÕ-ßÞ×ÔÝÞ" + +#: page.findmefollow.php:254 +msgid "" +"Message to be played to the person RECEIVING the call, if the call has " +"already been accepted before they push 1.

To add additional " +"recordings use the \"System Recordings\" MENU to the left" +msgstr "" +"ÁÞÞÑéÕÝØÕ ÒÞáßàÞØ×ÒÞÔØâáï ÔÛï ßàØÝïÒèÕÓÞ íâÞâ ×ÒÞÝÞÚ, ÕáÛØ ×ÒÞÝÞÚ ãÖÕ ßàØÝïâ ßàÕÖÔÕ çÕÜ ÞÝ ãáßÕÛ " +"ÝÐÖÐâì 1.

ŽÛï áÞ×ÔÐÝØï âÐÚÞÓÞ áÞÞÑéÕÝØï ØáßÞÛì×ãÙâÕ àÐ×ÔÕÛ ÜÕÝî ·Ðߨáì áÞÞÑéÕÝØÙ." + +#: page.findmefollow.php:272 +msgid "extension list" +msgstr "áߨáÞÚ ÝÞÜÕàÞÒ" + +#: page.findmefollow.php:249 +msgid "" +"List extensions to ring, one per line, or use the Extension Quick Pick below." +"

You can include an extension on a remote system, or an external " +"number by suffixing a number with a pound (#). ex: 2448089# would dial " +"2448089 on the appropriate trunk (see Outbound Routing)." +msgstr "" +"»Øáâ ÝÞÜÕàÞÒ, ßÞ ÞÔÝÞÜã Ò áâàÞÚÕ, ØÛØ ÒÞáßÞÛì×ãÙâÕáì ²ëÑÞàÞÜ Ø× ÜÕÝî ÝØÖÕ çâÞÑë ÔÞÑÐÒØâì Ò " +"áߨáÞÚ

ŒÞÖÝÞ ÒÚÛîçÐâì ÝÞÜÕàÐ Ø× ÔàãÓØå ãÔÐÛñÝÝëå áØáâÕÜ, ØÛØ ÒÝÕèÝØÕ ÝÞÜÕàÐ, á " +"ØáßÞÛì×ÞÒÐÝØÕÜ ×ÝÐÚÐ # Ò ÚÐçÕáâÒÕ áãääØÚáÐ. œÐßàØÜÕà: 2448089# ÝÐÑÕàñâ ÝÞÜÕà 2448089 ÝÐ " +"ÛîÑÞÜ ÒÝÕèÝÕÜ âàÐÝÚÕ, ßÞßÐÔÐîéÕÜ Ò ßàÐÒØÛÐ žáåÞÔïéÕÙ ÜÐàèàãâØ×ÐæØØ.

·ÐÔÕÙáâÒãîâáï " +"âÞÛìÚÞ äÐÚâØçÕáÚØÕ ÒÝãâàÕÝÝØÕ ÝÞÜÕàÐ. µáÛØ åÞâØâÕ ØáßÞÛì×ÞÒÐâì ßàØ íâÞÜ ßÞáâÞàÞÝÝØÕ ÚÐÝÐÛë " +"(çâÞÑë ×ÒÞÝØâì ÝÐ follow-me ØÛØ Ò ÔàãÓØÕ Óàãßßë Òë×ÞÒÐ, ØÛØ ÞçÕàÕÔØ, ßàÞáâÞ áâÐÒìâÕ ×ÝÐÚ # " +"Ò ÚÞÝæÕ ÝÞÜÕàÐ. œÞ ÑãÔâÕ ÞáâÞàÞÖÝë! ÍâÞ àÕÚãàáØï, Ø áØáâÕÜÐ ÜÞÖÕâ ×ÐÔãèØâìáï." + +#: page.findmefollow.php:287 +msgid "CID name prefix" +msgstr "¿àÕäØÚá žŽ ØÜÕÝØ" + +msgid "You can optionally prefix the Caller ID name when ringing extensions in this group. " +"ie: If you prefix with \"Sales:\", a call from John Doe would display as \"Sales:John Doe\" " +"on the extensions that ring." +msgstr "" +"ŸßæØÞÝÐÛìÝÞ, ÜÞÖÝÞ ØáßÞÛì×ÞÒÐâì ÚÐÚÞÙ-âÞ ßàÕäØÚá ÔÛï ×ÒÞÝÚÐ Ò íâã Óàãßßã. œÐßàØÜÕà, ÕáÛØ íâÞ ÓàãßßÐ " +"\"Sales:\", âÞ, ãáâÐÝÞÒØÒ âÐÚÞÙ ßàÕäØÚá ÔÛï íâÞÙ Óàãßßë, ÜÞÖÝÞ ÒØÔÕâì, ÕáÛØ ×ÒÞÝØâ John Doe, âÞ " +"Üë ãÒØÔØÜ ÝÐ ÔØáßÛÕÕ Sales:John Doe." + +#: page.findmefollow.php:293 +msgid "ring time (max 60 sec)" +msgstr "ÒàÕÜï Òë×ÞÒÐ (ÜÐÚá. 60 áÕÚ.)" + +#: page.findmefollow.php:241 +msgid "" +"Time in seconds that the phones will ring. For all hunt style ring " +"strategies, this is the time for each iteration of phone(s) that are rung" +msgstr "" +"²àÕÜï Ò áÕÚãÝÔÐå, Ò âÕçÕÝØÕ ÚÞâÞàÞÓÞ âÕÛÕäÞÝë ÑãÔãâ ×ÒÞÝØâì. ŽÛï ÒáÕå ÒØÔÞÒ " +"áâàÐâÕÓØÙ áÕàØÙÝÞÓÞ ØáÚÐÝØï íâÞ ÒàÕÜï ×ÒÞÝÚÐ ßÞÒâÞàïÕâáï ÔÛï ÒáÕå âÕÛÕäÞÝÞÒ, " +"ÚÞâÞàëÕ ÒÚÛîçÕÝë Ò áÕàØî." + +#: page.findmefollow.php:298 page.findmefollow.php:316 +msgid "announcement:" +msgstr "ßàØÒÕâáâÒØÕ:" + +#: page.findmefollow.php:298 +msgid "" +"Message to be played to the caller before dialing this group.

To add " +"additional recordings please use the \"System Recordings\" MENU to the left" +msgstr "" +"ÁÞÞÑéÕÝØÕ, ÚÞâÞàÞÕ ÒÞáßàÞØ×ÒÞÔØâáï ßÞ×ÒÞÝØÒèÕÜã ßàÕÖÔÕ, çÕÜ ×ÒÞÝÞÚ ßÕàÙÔñâ Ò " +"Óàãßßã.

ŽÛï áÞ×ÔÐÝØï âÐÚÞÓÞ áÞÞÑéÕÝØï ØáßÞÛì×ãÙâÕ àÐ×ÔÕÛ ÜÕÝî ·Ðߨáì áÞÞÑéÕÝØÙ." + +#: page.findmefollow.php:304 +msgid "None" +msgstr "œÕâ" + +#: page.findmefollow.php:316 +msgid "" +"Message to be played to the caller before dialing this group.

You " +"must install and enable the \"Systems Recordings\" Module to edit this option" +msgstr "" +"ÁÞÞÑéÕÝØÕ, ÚÞâÞàÞÕ ÒÞáßàÞØ×ÒÞÔØâáï ßÞ×ÒÞÝØÒèÕÜã ßàÕÖÔÕ, çÕÜ ×ÒÞÝÞÚ ßÕàÙÔñâ Ò " +"Óàãßßã.

œÕÞÑåÞÔØÜÞ ØÝáâÐÛÛØàÞÒÐâì ÜÞÔãÛì ·Ðߨáì áÞÞÑéÕÝØÙ çâÞÑë ÜÕÝïâì " +"çâÞ-ÛØÑÞ Ò íâÞÙ ÞßæØØ." + +#: page.findmefollow.php:326 +msgid "Play Music On Hold?" +msgstr "Œã×ëÚã Ò ÞÖØÔÐÝØØ?" + +#: page.findmefollow.php:326 +msgid "" +"If you select a Music on Hold class to play, instead of 'Ring', they will " +"hear that instead of Ringing while they are waiting for someone to pick up." +msgstr "" +"µáÛØ ÒëÑàÐÝ ÚÛÐáá Œã×ëÚØ Ò ÞÖØÔÐÝØØ ÒÜÕáâÞ ßàÞáâÞÓÞ áØÓÝÐÛÐ Òë×ÞÒÐ, âÞ ßÞ×ÒÞÝØÒèØÙ " +"ÑãÔÕâ áÛãèÐâì Üã×ëÚã, ßÞÚÐ ÚâÞ-âÞ ÝÕ ßÞÔÝØÜÕâ âàãÑÚã." + +#: page.findmefollow.php:332 +msgid "Ring" +msgstr "·ÒÞÝÞÚ" + +#: page.findmefollow.php:344 +msgid "Destination if no answer" +msgstr "œÐ×ÝÐçÕÝØÕ ÕáÛØ ÝÕâ ÞâÒÕâÐ" + +msgid "Misc Destinations" +msgstr "ÀÐ×ÛØçÝëÕ ÝÐßàÐÒÛÕÝØï" + +msgid "IVR" +msgstr "žÝâÕàÐÚâØÒÝÞÕ ÜÕÝî" + +msgid "Languages" +msgstr "Ï×ëÚØ" + +msgid "Conferences" +msgstr "ºÞÝäÕàÕÝæØØ" + +msgid "Phonebook Directory" +msgstr "ÂÕÛÕäÞÝÝÐï ÚÝØÓÐ" + +msgid "Queues" +msgstr "ŸçÕàÕÔØ" + +msgid "Ring Groups" +msgstr "³àãßßë Òë×ÞÒÐ" + +msgid "Speed dial functions" +msgstr "ÄãÝ򾯯 ÑëáâàÞÓÞ ÝÐÑÞàÐ" + +msgid "Time Conditions" +msgstr "¿àÐÒØÛÐ ßÞ ÒàÕÜÕÝØ" + +msgid "Custom Application" +msgstr "ÁßÕæØÐÛìÝÞÕ ßàØÛÞÖÕÝØÕ" + +msgid "Extended Routing" +msgstr "ÀÐáèØàÕÝÝÐï ÜÐàèàãâØ×ÐæØï" + +msgid "Custom App
ADVANCED USERS ONLY

Uses Goto() to send caller to " +"a custom context.

The context name should start with \"custom-\", and be in " +"the format custom-context,extension,priority. Example " +"entry:

custom-myapp,s,1

The [custom-myapp] context would " +"need to be created and included in extensions_custom.conf
" +msgstr "" +"ŸáÞÑëÕ ßàØÛÞÖÕÝØï
Ÿ»ÌºŸ Ÿ¿Ëœˌ ¿Ÿ»Ì·Ÿ²°Âµ»ÏŒ
žáßÞÛì×ãÙâÕ ÞßÕàÐÝÔ " +"Goto() ÔÛï ßÕàÕÝÐßàÐÒÛÕÝØï Ò custom ÚÞÝâÕÚáâ.

œÐ×ÒÐÝØÕ ÚÞÝâÕÚáâÐ ÔÞÛÖÝÞ " +"ÝÐçØÝÐâìáï á \"custom-\" Ø Ñëâì Ò äÞàÜÐâÕ custom-context,extension,ßàØÞàØâÕâ. " +"œÐßàØÜÕà:
custom-app,s,1
ºÞÝâÕÚáâ [custom-app] ÔÞÛÖÕÝ Ñëâì áÞ×ÔÐÝ " +"Ò extensions_custom.conf" +"However, destinations that specify FollowMe will come here.
" +"Checking this box is often used in conjunction with VmX Locater, where you want a call to ring the extension, and then only if the caller chooses to find you do you want it to come here." +msgstr "" +"¿Þ ãÜÞÛçÐÝØî (ÝÕ ÞâÜÕçÕÝÞ) ÒáÕ ×ÒÞÝÚØ ßÞáâãßÐîâ Ò ÜÞÔãÛì 'ÁÛÕÔãÙâÕ áîÔÐ', " +"ÒÚÛîçÐï ×ÒÞÝÚØ á ßÞØáÚÞÜ ßÞ ØÜÕÝØ Ò žÝâÕàÐÚâØÒÝëå ÜÕÝî. œÞ ÕáÛØ ÞâÜÕçÕÝÞ, " +"×ÒÞÝÞÚ ßÞáâãßÐÕâ ßàïÜÞ ÝÐ ãÚÐ×ÐÝëÙ ÝÞÜÕà.
² ÛîÑÞÜ áÛãçÐÕ, ÝÐ×ÝÐçÕÝØÕ, ãÚÐ×ÐÝÝÞÕ Ò " +"'ÁÛÕÔãÙâÕ áîÔÐ' ÑãÔÕâ ØáßÞÛÝïâìáï. žáßÞÛì×ÞÒÐÝØÕ íâÞÙ ÞßæØØ çÐáâÞ ÞßàÐÒÔÐÝÞ ÒÜÕáâÕ á " +"VmX »ÞÚÐâÞàÞÜ, ÓÔÕ ÜÞÖÝÞ ßàÞáâÞ ÝÐßàÐÒØâì ×ÒÞÝÞÚ ÝÐ ÒÝãâàÕÝÝØÙ ÝÞÜÕà, ßÞÛì×ÞÒÐâÕÛì " +"ÚÞâÞàÞÓÞ ÜÞÖÕâ ÝÕßÞáàÕÔáâÒÕÝÝÞ áÐÜ ãÚÐ×Ðâì, åÞçÕâ ÛØ ÞÝ, èâÞÑë ßÞáâãßÐîéØÕ ×ÒÞÝÚØ " +"ÝÐåÞÔØÛØ ÕÓÞ ÒÕ×ÔÕ, ØÛØ ÝÕâ." + +msgid "Ring Strategy:" +msgstr "ÁâàÐâÕÓØï ÔÞ×ÒÞÝÐ:" + +msgid "(edit)" +msgstr "(Ø×ÜÕÝØâì)" + +msgid "Edit Extension %s" +msgstr "ž×ÜÕÝØâì ÝÞÜÕà %s" + +msgid "Edit Follow Me Settings" +msgstr "ž×ÜÕÝØâì ãáâÐÝÞÒÚØ 'ÁÛÕÔãÙâÕ áîÔÐ'" + Index: /modules/branches/2.6/findmefollow/uninstall.php =================================================================== --- /modules/branches/2.6/findmefollow/uninstall.php (revision 6158) +++ /modules/branches/2.6/findmefollow/uninstall.php (revision 6158) @@ -0,0 +1,36 @@ +delete(); +unset($fcc); + +$sql = "SELECT * FROM users"; +$userresults = sql($sql,"getAll",DB_FETCHMODE_ASSOC); + +//add details to astdb +if ($astman) { + foreach($userresults as $usr) { + extract($usr); + $astman->database_deltree("AMPUSER/".$grpnum."/followme"); + } +} else { + echo _("Cannot connect to Asterisk Manager with ").$amp_conf["AMPMGRUSER"]."/".$amp_conf["AMPMGRPASS"]; +} + +sql('DROP TABLE IF EXISTS findmefollow'); + +?> Index: /modules/branches/2.6/findmefollow/module.xml =================================================================== --- /modules/branches/2.6/findmefollow/module.xml (revision 7023) +++ /modules/branches/2.6/findmefollow/module.xml (revision 7023) @@ -0,0 +1,41 @@ + + findmefollow + Follow Me + 2.5.1.7 + + *2.5.1.7* #3274, localization string enclosures + *2.5.1.6* #3246, #3215, localization fixes + *2.5.1.5* #3222 sqlite3 + *2.5.1.4* localization, Swedish + *2.5.1.3* #3177 don't auto-add vmbox dest to users with novm + *2.5.1.2* #3152, #3165, set voicemail as default dest on new followme + *2.5.1.1* #2987, #3006, #3029 sqlite3 install, spelling, cidprefix missing fix + *2.5.1* #2065 Migrate recordings to recording ids + *2.5.0.1* #2391, #2908, #2845, #1791, added delete and add icons + *2.5.0* Add enable/disable featurecode with blf support, new confirmation sound file announces cid availability + *2.4.14.2* #2604, #2843 fix mal-formed html tags, Russian Translation + *2.4.14.1* added depends on 2.4.0 + *2.4.14* Extension/dest registry, extension quickpick, added hunt strategy with confirmation, it trans, formatting changes + *2.4.13.2* #2193 moh path hardcoded + *2.4.13.1* bump for rc1 + *2.4.13* added xml attribute needsenginedb, #1961 enabled to work with extension numbers leading with 0s + *2.4.12.3* #2057 don't strip CID prefix if no prefix is being added + *2.4.12.2* merge findmefollow/core extension destinations if any, and remove findmefollow destinations as a destination since they are handled by core + *2.4.12.1* #2002 IF() statement can't handle : in the string and can't escape them anyhow + *2.4.12* CHANGELOG TRUNCATED See SVN Repository + + + 2.5.0alpha1 + recordings ge 3.3.8 + + setup + Inbound Call Control + + Much like a ring group, but works on individual extensions. When someone calls the extension, it can be setup to ring for a number of seconds before trying to ring other extensions and/or external numbers, or to ring all at once, or in other various 'hunt' configurations. Most commonly used to ring someone's cell phone if they don't answer their extension. + + + Follow Me + + release/2.5/findmefollow-2.5.1.7.tgz + 670f11e54579853a42a962130eea5820 + Index: /modules/branches/2.6/findmefollow/functions.inc.php =================================================================== --- /modules/branches/2.6/findmefollow/functions.inc.php (revision 6972) +++ /modules/branches/2.6/findmefollow/functions.inc.php (revision 6972) @@ -0,0 +1,493 @@ +addGlobal('FMDEVSTATE','TRUE'); + } + + $fcc = new featurecode('findmefollow', 'fmf_toggle'); + $fmf_code = $fcc->getCodeActive(); + unset($fcc); + + if ($fmf_code != '') { + findmefollow_fmf_toggle($fmf_code); + } + + $ext->addInclude('from-internal-additional','ext-findmefollow'); + $ext->addInclude('from-internal-additional','fmgrps'); + $contextname = 'ext-findmefollow'; + + // Before creating all the contexts, let's make a list of hints if needed + // + if ($amp_conf['USEDEVSTATE'] && $fmf_code != '') { + $device_list = core_devices_list("all", false, true); + foreach ($device_list as $device) { + $ext->add($contextname, $fmf_code.$device['id'], '', new ext_goto("1",$fmf_code,"app-fmf-toggle")); + $ext->addHint($contextname, $fmf_code.$device['id'], "Custom:FOLLOWME".$device['id']); + } + } + + $ringlist = findmefollow_full_list(); + if (is_array($ringlist)) { + foreach($ringlist as $item) { + $grpnum = ltrim($item['0']); + $grp = findmefollow_get($grpnum); + + $strategy = $grp['strategy']; + $grptime = $grp['grptime']; + $grplist = $grp['grplist']; + $postdest = $grp['postdest']; + $grppre = (isset($grp['grppre'])?$grp['grppre']:''); + $annmsg_id = $grp['annmsg_id']; + $dring = $grp['dring']; + + $needsconf = $grp['needsconf']; + $remotealert_id = $grp['remotealert_id']; + $toolate_id = $grp['toolate_id']; + $ringing = $grp['ringing']; + $pre_ring = $grp['pre_ring']; + + if($ringing == 'Ring' || empty($ringing) ) { + $dialopts = '${DIAL_OPTIONS}'; + } else { + // We need the DIAL_OPTIONS variable + $sops = sql("SELECT value from globals where variable='DIAL_OPTIONS'", "getRow"); + $dialopts = "m(${ringing})".str_replace('r', '', $sops[0]); + } + + // Direct target to Follow-Me come here bypassing the followme/ddial conditional check + // + $ext->add($contextname, 'FM'.$grpnum, '', new ext_goto("FM$grpnum","$grpnum")); + + // + // If the followme is configured for extension dialing to go to the the extension and not followme then + // go there. This is often used in VmX Locater functionality when the user does not want the followme + // to automatically be called but only if chosen by the caller as an alternative to going to voicemail + // + $ext->add($contextname, $grpnum, '', new ext_gotoif('$[ "${DB(AMPUSER/'.$grpnum.'/followme/ddial)}" = "EXTENSION" ]', 'ext-local,'.$grpnum.',1')); + $ext->add($contextname, $grpnum, 'FM'.$grpnum, new ext_macro('user-callerid')); + + // block voicemail until phone is answered at which point a macro should be called on the answering + // line to clear this flag so that subsequent transfers can occur, if already set by a the caller + // then don't change. + // + $ext->add($contextname, $grpnum, '', new ext_gotoif('$["foo${BLKVM_OVERRIDE}" = "foo"]', 'skipdb')); + $ext->add($contextname, $grpnum, '', new ext_gotoif('$["${DB(${BLKVM_OVERRIDE})}" = "TRUE"]', 'skipov')); + + $ext->add($contextname, $grpnum, 'skipdb', new ext_setvar('__NODEST', '')); + $ext->add($contextname, $grpnum, '', new ext_setvar('__BLKVM_OVERRIDE', 'BLKVM/${EXTEN}/${CHANNEL}')); + $ext->add($contextname, $grpnum, '', new ext_setvar('__BLKVM_BASE', '${EXTEN}')); + $ext->add($contextname, $grpnum, '', new ext_setvar('DB(${BLKVM_OVERRIDE})', 'TRUE')); + + // Remember if NODEST was set later, but clear it in case the call is answered so that subsequent + // transfers work. + // + $ext->add($contextname, $grpnum, 'skipov', new ext_setvar('RRNODEST', '${NODEST}')); + $ext->add($contextname, $grpnum, 'skipvmblk', new ext_setvar('__NODEST', '${EXTEN}')); + + // deal with group CID prefix + // but strip only if you plan on setting a new one + if ($grppre != '') { + $ext->add($contextname, $grpnum, '', new ext_gotoif('$["foo${RGPREFIX}" = "foo"]', 'REPCID')); + $ext->add($contextname, $grpnum, '', new ext_gotoif('$["${RGPREFIX}" != "${CALLERID(name):0:${LEN(${RGPREFIX})}}"]', 'REPCID')); + $ext->add($contextname, $grpnum, '', new ext_noop('Current RGPREFIX is ${RGPREFIX}....stripping from Caller ID')); + $ext->add($contextname, $grpnum, '', new ext_setvar('CALLERID(name)', '${CALLERID(name):${LEN(${RGPREFIX})}}')); + $ext->add($contextname, $grpnum, '', new ext_setvar('_RGPREFIX', '')); + $ext->add($contextname, $grpnum, 'REPCID', new ext_noop('CALLERID(name) is ${CALLERID(name)}')); + $ext->add($contextname, $grpnum, '', new ext_setvar('_RGPREFIX', $grppre)); + $ext->add($contextname, $grpnum, '', new ext_setvar('CALLERID(name)','${RGPREFIX}${CALLERID(name)}')); + } + // recording stuff + $ext->add($contextname, $grpnum, '', new ext_setvar('RecordMethod','Group')); + $ext->add($contextname, $grpnum, '', new ext_macro('record-enable','${DB(AMPUSER/'."$grpnum/followme/grplist)}".',${RecordMethod}')); + + // MODIFIED (PL) + // Add Alert Info if set but don't override and already set value (could be from ringgroup, directdid, etc.) + // + if ((isset($dring) ? $dring : '') != '') { + // If ALERTINFO is set, then skip to the next set command. This was modified to two lines because the previous + // IF() couldn't handle ':' as part of the string. The jump to PRIORITY+2 allows for now destination label + // which is needed in the 2.3 version. + $ext->add($contextname, $grpnum, '', new ext_gotoif('$["x${ALERT_INFO}"!="x"]','$[${PRIORITY}+2])}')); + $ext->add($contextname, $grpnum, '', new ext_setvar("__ALERT_INFO", str_replace(';', '\;', $dring) )); + } + // If pre_ring is set, then ring this number of seconds prior to moving on + if ((isset($strategy) ? substr($strategy,0,strlen('ringallv2')) : '') != 'ringallv2') { + $ext->add($contextname, $grpnum, '', new ext_gotoif('$[$[ "${DB(AMPUSER/'.$grpnum.'/followme/prering)}" = "0" ] | $[ "${DB(AMPUSER/'.$grpnum.'/followme/prering)}" = "" ]] ', 'skipsimple')); + $ext->add($contextname, $grpnum, '', new ext_macro('simple-dial',$grpnum.',${DB(AMPUSER/'."$grpnum/followme/prering)}")); + } + + // group dial + $ext->add($contextname, $grpnum, 'skipsimple', new ext_setvar('RingGroupMethod',$strategy)); + $ext->add($contextname, $grpnum, '', new ext_setvar('_FMGRP',$grpnum)); + if ((isset($annmsg_id) ? $annmsg_id : '')) { + $annmsg = recordings_get_file($annmsg_id); + // should always answer before playing anything, shouldn't we ? + $ext->add($contextname, $grpnum, '', new ext_gotoif('$[$["${DIALSTATUS}" = "ANSWER"] | $["foo${RRNODEST}" != "foo"]]','DIALGRP')); + $ext->add($contextname, $grpnum, '', new ext_answer('')); + $ext->add($contextname, $grpnum, '', new ext_wait(1)); + $ext->add($contextname, $grpnum, '', new ext_playback($annmsg)); + } + + // Create the confirm target + $len=strlen($grpnum)+4; + $remotealert = recordings_get_file($remotealert_id); + $toolate = recordings_get_file($toolate_id); + $ext->add("fmgrps", "_RG-${grpnum}-.", '', new ext_macro('dial','${DB(AMPUSER/'."$grpnum/followme/grptime)},". + "M(confirm^${remotealert}^${toolate}^${grpnum})$dialopts".',${EXTEN:'.$len.'}')); + + // If grpconf == ENABLED call with confirmation ELSE call normal + $ext->add($contextname, $grpnum, 'DIALGRP', new + ext_gotoif('$[ "${DB(AMPUSER/'.$grpnum.'/followme/grpconf)}" = "ENABLED" ]', 'doconfirm')); + + // Normal call + if ((isset($strategy) ? substr($strategy,0,strlen('ringallv2')) : '') != 'ringallv2') { + $ext->add($contextname, $grpnum, '', new ext_macro('dial','${DB(AMPUSER/'."$grpnum/followme/grptime)},$dialopts,".'${DB(AMPUSER/'."$grpnum/followme/grplist)}")); + } else { + $ext->add($contextname, $grpnum, '', new ext_macro('dial','$[ ${DB(AMPUSER/'.$grpnum.'/followme/grptime)} + ${DB(AMPUSER/'.$grpnum.'/followme/prering)} ],'.$dialopts.',${DB(AMPUSER/'.$grpnum.'/followme/grplist)}')); + } + $ext->add($contextname, $grpnum, '', new ext_goto('nextstep')); + + // Call Confirm call + if ((isset($strategy) ? substr($strategy,0,strlen('ringallv2')) : '') != 'ringallv2') { + $ext->add($contextname, $grpnum, 'doconfirm', new ext_macro('dial-confirm','${DB(AMPUSER/'."$grpnum/followme/grptime)},$dialopts,".'${DB(AMPUSER/'."$grpnum/followme/grplist)},".$grpnum)); + } else { + $ext->add($contextname, $grpnum, 'doconfirm', new ext_macro('dial-confirm','$[ ${DB(AMPUSER/'.$grpnum.'/followme/grptime)} + ${DB(AMPUSER/'.$grpnum.'/followme/prering)} ],'.$dialopts.',${DB(AMPUSER/'.$grpnum.'/followme/grplist)},'.$grpnum)); + } + + $ext->add($contextname, $grpnum, 'nextstep', new ext_setvar('RingGroupMethod','')); + + // Did the call come from a queue or ringgroup, if so, don't go to the destination, just end and let + // the queue or ringgroup decide what to do next + // + $ext->add($contextname, $grpnum, '', new ext_gotoif('$["foo${RRNODEST}" != "foo"]', 'nodest')); + $ext->add($contextname, $grpnum, '', new ext_setvar('__NODEST', '')); + + $ext->add($contextname, $grpnum, '', new ext_dbdel('${BLKVM_OVERRIDE}')); + + // where next? + if ((isset($postdest) ? $postdest : '') != '') { + $ext->add($contextname, $grpnum, '', new ext_goto($postdest)); + } else { + $ext->add($contextname, $grpnum, '', new ext_hangup('')); + } + $ext->add($contextname, $grpnum, 'nodest', new ext_noop('SKIPPING DEST, CALL CAME FROM Q/RG: ${RRNODEST}')); + } + } + break; + } +} + +function findmefollow_add($grpnum,$strategy,$grptime,$grplist,$postdest,$grppre='',$annmsg_id='',$dring,$needsconf,$remotealert_id,$toolate_id,$ringing,$pre_ring,$ddial) { + global $amp_conf; + global $astman; + global $db; + + $sql = "INSERT INTO findmefollow (grpnum, strategy, grptime, grppre, grplist, annmsg_id, postdest, dring, needsconf, remotealert_id, toolate_id, ringing, pre_ring) VALUES ('".$db->escapeSimple($grpnum)."', '".$db->escapeSimple($strategy)."', ".$db->escapeSimple($grptime).", '".$db->escapeSimple($grppre)."', '".$db->escapeSimple($grplist)."', '".$db->escapeSimple($annmsg_id)."', '".$db->escapeSimple($postdest)."', '".$db->escapeSimple($dring)."', '$needsconf', '$remotealert_id', '$toolate_id', '$ringing', '$pre_ring')"; + $results = sql($sql); + + if ($astman) { + $astman->database_put("AMPUSER",$grpnum."/followme/prering",isset($pre_ring)?$pre_ring:''); + $astman->database_put("AMPUSER",$grpnum."/followme/grptime",isset($grptime)?$grptime:''); + $astman->database_put("AMPUSER",$grpnum."/followme/grplist",isset($grplist)?$grplist:''); + + $needsconf = isset($needsconf)?$needsconf:''; + $confvalue = ($needsconf == 'CHECKED')?'ENABLED':'DISABLED'; + $astman->database_put("AMPUSER",$grpnum."/followme/grpconf",$confvalue); + + $ddial = isset($ddial)?$ddial:''; + $ddialvalue = ($ddial == 'CHECKED')?'EXTENSION':'DIRECT'; + $astman->database_put("AMPUSER",$grpnum."/followme/ddial",$ddialvalue); + } else { + fatal("Cannot connect to Asterisk Manager with ".$amp_conf["AMPMGRUSER"]."/".$amp_conf["AMPMGRPASS"]); + } +} + +function findmefollow_del($grpnum) { + global $amp_conf; + global $astman; + global $db; + + $results = sql("DELETE FROM findmefollow WHERE grpnum = '".$db->escapeSimple($grpnum)."'","query"); + + if ($astman) { + $astman->database_deltree("AMPUSER/".$grpnum."/followme"); + } else { + fatal("Cannot connect to Asterisk Manager with ".$amp_conf["AMPMGRUSER"]."/".$amp_conf["AMPMGRPASS"]); + } +} + +function findmefollow_full_list() { + $results = sql("SELECT grpnum FROM findmefollow ORDER BY CAST(grpnum as UNSIGNED)","getAll",DB_FETCHMODE_ASSOC); + foreach ($results as $result) { + if (isset($result['grpnum']) && checkRange($result['grpnum'])) { + $grps[] = array($result['grpnum']); + } + } + if (isset($grps)) + return $grps; + else + return null; +} + +function findmefollow_list($get_all=false) { + + global $db; + $sql = "SELECT grpnum FROM findmefollow ORDER BY CAST(grpnum as UNSIGNED)"; + $results = $db->getCol($sql); + if(DB::IsError($results)) { + $results = null; + } + if (isset($results)) { + foreach($results as $result) { + if ($get_all || checkRange($result)){ + $grps[] = $result; + } + } + } + if (isset($grps)) { + return $grps; + } + else { + return null; + } +} + +// This gets the list of all active users so that the Find Me Follow display can limit the options to only created users. +// the returned arrays contain [0]:extension [1]:name +// +// This was pulled straight out of previous 1.x version, might need cleanup laster +// +function findmefollow_allusers() { + global $db; + $sql = "SELECT extension,name FROM users ORDER BY extension"; + $results = $db->getAll($sql); + if(DB::IsError($results)) { + $results = null; + } + foreach($results as $result){ + if (checkRange($result[0])){ + $users[] = array($result[0],$result[1]); + } + } + if (isset($users)) sort($users); + return $users; +} + +// Only check astdb if check_astdb is not 0. For some reason, this fails if the asterisk manager code +// is included (executed) by all calls to this function. This results in silently not generating the +// extensions_additional.conf file. page.findmefollow.php does set it to 1 which means that when running +// the GUI, any changes not reflected in SQL will be detected and written back to SQL so that they are +// in sync. Ideally, anything that changes the astdb should change SQL. (in some ways, these should both +// not be here but ... +// +// Need to go back and confirm at some point that the $check_astdb error is still there and deal with it. +// as variables like $ddial get introduced to only be in astdb, the result array will not include them +// if not able to get to astdb. (I suspect in 2.2 and beyond this may all be fixed). +// +function findmefollow_get($grpnum, $check_astdb=0) { + global $amp_conf; + global $astman; + global $db; + + $results = sql("SELECT grpnum, strategy, grptime, grppre, grplist, annmsg_id, postdest, dring, needsconf, remotealert_id, toolate_id, ringing, pre_ring, voicemail FROM findmefollow INNER JOIN `users` ON `extension` = `grpnum` WHERE grpnum = '".$db->escapeSimple($grpnum)."'","getRow",DB_FETCHMODE_ASSOC); + if (!isset($results['voicemail'])) { + $results['voicemail'] = sql("SELECT `voicemail` FROM `users` WHERE `extension` = '".$db->escapeSimple($grpnum)."'","getOne"); + } + + if ($check_astdb) { + if ($astman) { + $astdb_prering = $astman->database_get("AMPUSER",$grpnum."/followme/prering"); + $astdb_grptime = $astman->database_get("AMPUSER",$grpnum."/followme/grptime"); + $astdb_grplist = $astman->database_get("AMPUSER",$grpnum."/followme/grplist"); + $astdb_grpconf = $astman->database_get("AMPUSER",$grpnum."/followme/grpconf"); + } else { + fatal("Cannot connect to Asterisk Manager with ".$amp_conf["AMPMGRUSER"]."/".$amp_conf["AMPMGRPASS"]); + } + $astdb_ddial = $astman->database_get("AMPUSER",$grpnum."/followme/ddial"); + // If the values are different then use what is in astdb as it may have been changed. + // + $changed=0; + if (($astdb_prering != $results['pre_ring']) && ($astdb_prering >= 0)) { + $results['pre_ring'] = $astdb_prering; + $changed=1; + } + if (($astdb_grptime != $results['grptime']) && ($astdb_grptime > 0)) { + $results['grptime'] = $astdb_grptime; + $changed=1; + } + if ((trim($astdb_grplist) != trim($results['grplist'])) && (trim($astdb_grplist) != '')) { + $results['grplist'] = $astdb_grplist; + $changed=1; + } + + if (trim($astdb_grpconf) == 'ENABLED') { + $confvalue = 'CHECKED'; + } elseif (trim($astdb_grpconf) == 'DISABLED') { + $confvalue = ''; + } else { + //Bogus value, should not get here but treat as disabled + $confvalue = ''; + } + if ($confvalue != trim($results['needsconf'])) { + $results['needsconf'] = $confvalue; + $changed=1; + } + + // Not in sql so no sanity check needed + // + if (trim($astdb_ddial) == 'EXTENSION') { + $ddial = 'CHECKED'; + } elseif (trim($astdb_ddial) == 'DIRECT') { + $ddial = ''; + } else { + //Bogus value, should not get here but treat as disabled + $ddial = ''; + } + $results['ddial'] = $ddial; + + if ($changed) { + $sql = "UPDATE findmefollow SET grptime = '".$results['grptime']."', grplist = '". + $db->escapeSimple(trim($results['grplist']))."', pre_ring = '".$results['pre_ring']. + "', needsconf = '".$results['needsconf']."' WHERE grpnum = '".$db->escapeSimple($grpnum)."' LIMIT 1"; + $sql_results = sql($sql); + } + } // if check_astdb + + return $results; +} + +function findmefollow_configpageinit($dispnum) { + global $currentcomponent; + + if ( ($dispnum == 'users' || $dispnum == 'extensions') ) { + $currentcomponent->addguifunc('findmefollow_configpageload'); + } +} + +function findmefollow_configpageload() { + global $currentcomponent; + + $viewing_itemid = isset($_REQUEST['extdisplay'])?$_REQUEST['extdisplay']:null; + $action = isset($_REQUEST['action'])?$_REQUEST['action']:null; + if ( $viewing_itemid != '' && $action != 'del') { + $set_findmefollow = findmefollow_list(); + $grpURL = $_SERVER['PHP_SELF'].'?'.'display=findmefollow&extdisplay=GRP-'.$viewing_itemid; + if (is_array($set_findmefollow)) { + if (in_array($viewing_itemid,$set_findmefollow)) { + $grpTEXT = _("Edit Follow Me Settings"); + $icon = "images/user_go.png"; + } else { + $grpTEXT = _("Add Follow Me Settings"); + $icon = "images/user_add.png"; + } + } else { + $grpTEXT = _("Add Follow Me Settings"); + $icon = "images/user_add.png"; + } + $label = ' '.$grpTEXT.''; + $currentcomponent->addguielem('_top', new gui_link('findmefollowlink', $label, $grpURL)); + } +} + +function findmefollow_check_destinations($dest=true) { + global $active_modules; + + $destlist = array(); + if (is_array($dest) && empty($dest)) { + return $destlist; + } + $sql = "SELECT grpnum, postdest, name FROM findmefollow INNER JOIN users ON grpnum = extension "; + if ($dest !== true) { + $sql .= "WHERE postdest in ('".implode("','",$dest)."')"; + } + $results = sql($sql,"getAll",DB_FETCHMODE_ASSOC); + + //$type = isset($active_modules['announcement']['type'])?$active_modules['announcement']['type']:'setup'; + + foreach ($results as $result) { + $thisdest = $result['postdest']; + $thisid = $result['grpnum']; + $destlist[] = array( + 'dest' => $thisdest, + 'description' => sprintf(_("Follow-Me: %s (%s)"),$thisid,$result['name']), + 'edit_url' => 'config.php?display=findmefollow&extdisplay=GRP-'.urlencode($thisid), + ); + } + return $destlist; +} + +function findmefollow_recordings_usage($recording_id) { + global $active_modules; + + $results = sql("SELECT `grpnum` FROM `findmefollow` WHERE `annmsg_id` = '$recording_id' OR `remotealert_id` = '$recording_id' OR `toolate_id` = '$recording_id'","getAll",DB_FETCHMODE_ASSOC); + if (empty($results)) { + return array(); + } else { + //$type = isset($active_modules['ivr']['type'])?$active_modules['ivr']['type']:'setup'; + foreach ($results as $result) { + $usage_arr[] = array( + 'url_query' => 'config.php?display=findmefollow&extdisplay=GRP-'.urlencode($result['grpnum']), + 'description' => "Follow-Me User: ".$result['grpnum'], + ); + } + return $usage_arr; + } +} + +function findmefollow_fmf_toggle($c) { + global $ext; + global $amp_conf; + global $version; + + $DEVSTATE = version_compare($version, "1.6", "ge") ? "DEVICE_STATE" : "DEVSTATE"; + + $id = "app-fmf-toggle"; // The context to be included + $ext->addInclude('from-internal-additional', $id); // Add the include from from-internal + + $ext->add($id, $c, '', new ext_goto('start','s',$id)); + $c = 's'; + + $ext->add($id, $c, 'start', new ext_answer('')); + $ext->add($id, $c, '', new ext_wait('1')); + $ext->add($id, $c, '', new ext_macro('user-callerid')); + + $ext->add($id, $c, '', new ext_gotoif('$["${DB(AMPUSER/${AMPUSER}/followme/ddial)}" = "EXTENSION"]', 'activate')); + $ext->add($id, $c, '', new ext_gotoif('$["${DB(AMPUSER/${AMPUSER}/followme/ddial)}" = "DIRECT"]', 'deactivate','end')); + + $ext->add($id, $c, 'deactivate', new ext_setvar('DB(AMPUSER/${AMPUSER}/followme/ddial)', 'EXTENSION')); + if ($amp_conf['USEDEVSTATE']) { + $ext->add($id, $c, '', new ext_setvar('STATE', 'NOT_INUSE')); + $ext->add($id, $c, '', new ext_gosub('1', 'sstate', $id)); + } + $ext->add($id, $c, '', new ext_playback('followme&de-activated')); + $ext->add($id, $c, 'end', new ext_macro('hangupcall')); + + $ext->add($id, $c, 'activate', new ext_setvar('DB(AMPUSER/${AMPUSER}/followme/ddial)', 'DIRECT')); + if ($amp_conf['USEDEVSTATE']) { + $ext->add($id, $c, '', new ext_setvar('STATE', 'INUSE')); + $ext->add($id, $c, '', new ext_gosub('1', 'sstate', $id)); + } + $ext->add($id, $c, '', new ext_playback('followme&activated')); + $ext->add($id, $c, '', new ext_macro('hangupcall')); + + if ($amp_conf['USEDEVSTATE']) { + $c = 'sstate'; + $ext->add($id, $c, '', new ext_dbget('DEVICES','AMPUSER/${AMPUSER}/device')); + $ext->add($id, $c, '', new ext_gotoif('$["${DEVICES}" = "" ]', 'return')); + $ext->add($id, $c, '', new ext_setvar('LOOPCNT', '${FIELDQTY(DEVICES,&)}')); + $ext->add($id, $c, '', new ext_setvar('ITER', '1')); + $ext->add($id, $c, 'begin', new ext_setvar($DEVSTATE.'(Custom:FOLLOWME${CUT(DEVICES,&,${ITER})})','${STATE}')); + $ext->add($id, $c, '', new ext_setvar('ITER', '$[${ITER} + 1]')); + $ext->add($id, $c, '', new ext_gotoif('$[${ITER} <= ${LOOPCNT}]', 'begin')); + $ext->add($id, $c, 'return', new ext_return()); + } +} +?> Index: /modules/branches/2.6/findmefollow/page.findmefollow.php =================================================================== --- /modules/branches/2.6/findmefollow/page.findmefollow.php (revision 6678) +++ /modules/branches/2.6/findmefollow/page.findmefollow.php (revision 6678) @@ -0,0 +1,467 @@ +javascript:alert('". _("Warning! Extension")." ".$account." "._("is not allowed for your account").".');"; + } else { + //add group + if ($action == 'addGRP') { + findmefollow_add($account,$strategy,$grptime,implode("-",$grplist),$goto,$grppre,$annmsg_id,$dring,$needsconf,$remotealert_id,$toolate_id,$ringing,$pre_ring,$ddial); + + needreload(); + redirect_standard(); + } + + //del group + if ($action == 'delGRP') { + findmefollow_del($account); + needreload(); + redirect_standard(); + } + + //edit group - just delete and then re-add the extension + if ($action == 'edtGRP') { + findmefollow_del($account); + findmefollow_add($account,$strategy,$grptime,implode("-",$grplist),$goto,$grppre,$annmsg_id,$dring,$needsconf,$remotealert_id,$toolate_id,$ringing,$pre_ring,$ddial); + + needreload(); + redirect_standard('extdisplay'); + } + } +} +?> +
+ + + +
+

'._("Follow Me").'


'._('Choose a user/extension:').'








'; + } +elseif ($action == 'delGRP') { + echo '

'._("Follow Me").' '.$account.' '._("deleted").'!









'; +} else { + if ($extdisplay != "") { + // We need to populate grplist with the existing extension list. + $extdisplay = ltrim($extdisplay,'GRP-'); + + $thisgrp = findmefollow_get($extdisplay, 1); + $grpliststr = isset($thisgrp['grplist']) ? $thisgrp['grplist'] : ''; + $grplist = explode("-", $grpliststr); + + $strategy = isset($thisgrp['strategy']) ? $thisgrp['strategy'] : ''; + $grppre = isset($thisgrp['grppre']) ? $thisgrp['grppre'] : ''; + $grptime = isset($thisgrp['grptime']) ? $thisgrp['grptime'] : ''; + $annmsg_id = isset($thisgrp['annmsg_id']) ? $thisgrp['annmsg_id'] : ''; + $dring = isset($thisgrp['dring']) ? $thisgrp['dring'] : ''; + $remotealert_id = isset($thisgrp['remotealert_id']) ? $thisgrp['remotealert_id'] : ''; + $needsconf = isset($thisgrp['needsconf']) ? $thisgrp['needsconf'] : ''; + $toolate_id = isset($thisgrp['toolate_id']) ? $thisgrp['toolate_id'] : ''; + $ringing = isset($thisgrp['ringing']) ? $thisgrp['ringing'] : ''; + $pre_ring = isset($thisgrp['pre_ring']) ? $thisgrp['pre_ring'] : ''; + $ddial = isset($thisgrp['ddial']) ? $thisgrp['ddial'] : ''; + $goto = isset($thisgrp['postdest'])?$thisgrp['postdest']:((isset($thisgrp['voicemail']) && $thisgrp['voicemail'] != 'novm')?"ext-local,vmu$extdisplay,1":''); + unset($grpliststr); + unset($thisgrp); + + $delButton = " +
+ + + + +
"; + + echo "

"._("Follow Me").": ".$extdisplay."

"; + + + // Copied straight out of old code,let's see if it works? + // + if (isset($amp_conf["AMPEXTENSIONS"]) && ($amp_conf["AMPEXTENSIONS"] == "deviceanduser")) { + $editURL = $_SERVER['PHP_SELF'].'?display=users&extdisplay='.$extdisplay; + $EXTorUSER = _("User"); + } + else { + $editURL = $_SERVER['PHP_SELF'].'?display=extensions&extdisplay='.$extdisplay; + $EXTorUSER = _("Extension"); + } + + $label = ' '.sprintf(_("Edit %s %s"),$EXTorUSER, $extdisplay).''; + echo "

".$label."

"; + echo "

".$delButton."

"; + } + ?> +
+ + "> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

:
However, destinations that specify FollowMe will come here.
Checking this box is often used in conjunction with VmX Locater, where you want a call to ring the extension, and then only if the caller chooses to find you do you want it to come here.')?>
:
tabindex=""/>
+ + + + +
+ + + :
+ :
+ :
+ :
+ :
+ :
+ :
+
+
+
+ +
+ + + + + +
:

You can include an extension on a remote system, or an external number by suffixing a number with a pound (#). ex: 2448089# would dial 2448089 on the appropriate trunk (see Outbound Routing).")?>

+ 20) ? 20 : $rows); +?> + +
+ + + + + + + +

To add additional recordings please use the \"System Recordings\" MENU to the left")?>
+ +

You must install and enable the \"Systems Recordings\" Module to edit this option")?>
+ + +
+ +
:
:
: + tabindex=""/> +

To add additional recordings use the \"System Recordings\" MENU to the left")?>
+ +

To add additional recordings use the \"System Recordings\" MENU to the left")?>
+ +

:

" tabindex="">
+
+ + + Index: /modules/branches/2.6/findmefollow/install.php =================================================================== --- /modules/branches/2.6/findmefollow/install.php (revision 6892) +++ /modules/branches/2.6/findmefollow/install.php (revision 6892) @@ -0,0 +1,306 @@ +"; + } +} + +if (! function_exists("outn")) { + function outn($text) { + echo $text; + } +} + +$sql = " +CREATE TABLE IF NOT EXISTS `findmefollow` +( + `grpnum` VARCHAR( 20 ) NOT NULL , + `strategy` VARCHAR( 50 ) NOT NULL , + `grptime` SMALLINT NOT NULL , + `grppre` VARCHAR( 100 ) NULL , + `grplist` VARCHAR( 255 ) NOT NULL , + `annmsg_id` INTEGER, + `postdest` VARCHAR( 255 ) NULL , + `dring` VARCHAR ( 255 ) NULL , + `remotealert_id` INTEGER, + `needsconf` VARCHAR ( 10 ), + `toolate_id` INTEGER, + `pre_ring` SMALLINT NOT NULL DEFAULT 0, + PRIMARY KEY (`grpnum`) +) +"; +$check = $db->query($sql); +if(DB::IsError($check)) { + die_freepbx("Can not create annoucment table"); +} + +//TODO: Also need to create all the states if enabled + +$fcc = new featurecode('findmefollow', 'fmf_toggle'); +$fcc->setDescription('Findme Follow Toggle'); +$fcc->setDefault('*21'); +$fcc->update(); +unset($fcc); + +// Adding support for a pre_ring before follow-me group +$sql = "SELECT pre_ring FROM findmefollow"; +$check = $db->getRow($sql, DB_FETCHMODE_ASSOC); +if(DB::IsError($check)) { + // add new field + $sql = "ALTER TABLE findmefollow ADD pre_ring SMALLINT( 6 ) NOT NULL DEFAULT 0 ;"; + $result = $db->query($sql); + if(DB::IsError($result)) { die_freepbx($result->getDebugInfo()); } +} +// If there is no needsconf then this is a really old upgrade. We create the 2 old fields +// here and then the migration code below will change them as needed but will work properly +// since it now has the fields it is expecting +// +$sql = "SELECT needsconf FROM findmefollow"; +$check = $db->getRow($sql, DB_FETCHMODE_ASSOC); +if(DB::IsError($check)) { + // add new field + $sql = "ALTER TABLE findmefollow ADD remotealert VARCHAR( 80 ) NULL ;"; + $result = $db->query($sql); + if(DB::IsError($result)) { die_freepbx($result->getDebugInfo()); } + + $sql = "ALTER TABLE findmefollow ADD needsconf VARCHAR( 10 ) NULL ;"; + $result = $db->query($sql); + if(DB::IsError($result)) { die_freepbx($result->getDebugInfo()); } + + $sql = "ALTER TABLE findmefollow ADD toolate VARCHAR( 80 ) NULL ;"; + $result = $db->query($sql); + if(DB::IsError($result)) { die_freepbx($result->getDebugInfo()); } +} +// Version 2.1 upgrade. Add support for ${DIALOPTS} override, playing MOH +$sql = "SELECT ringing FROM findmefollow"; +$check = $db->getRow($sql, DB_FETCHMODE_ASSOC); +if(DB::IsError($check)) { + // add new field + $sql = "ALTER TABLE findmefollow ADD ringing VARCHAR( 80 ) NULL ;"; + $result = $db->query($sql); + if(DB::IsError($result)) { die_freepbx($result->getDebugInfo()); } +} +// increase size for older installs, ignore sqlite3, doesn't support ALTER...CHANGE syntax, table created properly above +if($amp_conf["AMPDBENGINE"] != "sqlite3") { + $db->query("ALTER TABLE findmefollow CHANGE dring dring VARCHAR( 255 ) NULL"); +} +$results = array(); +$sql = "SELECT grpnum, postdest FROM findmefollow"; +$results = $db->getAll($sql, DB_FETCHMODE_ASSOC); +if (!DB::IsError($results)) { // error - table must not be there + foreach ($results as $result) { + $old_dest = $result['postdest']; + $grpnum = $result['grpnum']; + + $new_dest = merge_ext_followme(trim($old_dest)); + if ($new_dest != $old_dest) { + $sql = "UPDATE findmefollow SET postdest = '$new_dest' WHERE grpnum = '$grpnum' AND postdest = '$old_dest'"; + $results = $db->query($sql); + if(DB::IsError($results)) { + die_freepbx($results->getMessage()); + } + } + } +} + +// this function builds the AMPUSER//followme tree for each user who has a group number +// it's purpose is to convert after an upgrade + + +// TODO, is this needed...? +// is this global...? what if we include this files +// from a function...? + +$sql = "SELECT * FROM findmefollow"; +$userresults = sql($sql,"getAll",DB_FETCHMODE_ASSOC); + +//add details to astdb +if ($astman) { + foreach($userresults as $usr) { + extract($usr); + + $astman->database_put("AMPUSER",$grpnum."/followme/prering",isset($pre_ring)?$pre_ring:''); + $astman->database_put("AMPUSER",$grpnum."/followme/grptime",isset($grptime)?$grptime:''); + $astman->database_put("AMPUSER",$grpnum."/followme/grplist",isset($grplist)?$grplist:''); + $confvalue = ($needsconf == 'CHECKED')?'ENABLED':'DISABLED'; + $astman->database_put("AMPUSER",$grpnum."/followme/grpconf",isset($needsconf)?$confvalue:''); + $ddial = $astman->database_get("AMPUSER",$grpnum."/followme/ddial"); + $ddial = ($ddial == 'EXTENSION' || $ddial == 'DIRECT')?$ddial:'DIRECT'; + $astman->database_put("AMPUSER",$grpnum."/followme/ddial",$ddial); + } +} else { + echo _("Cannot connect to Asterisk Manager with ").$amp_conf["AMPMGRUSER"]."/".$amp_conf["AMPMGRPASS"]; +} + +// Version 2.4.13 change (#1961) +// Ignore sqlite3, doesn't support ALTER...CHANGE syntax, table created properly above +if($amp_conf["AMPDBENGINE"] != "sqlite3") { + $sql = "ALTER TABLE `findmefollow` CHANGE `grpnum` `grpnum` VARCHAR( 20 ) NOT NULL"; + $results = $db->query($sql); + if(DB::IsError($results)) { + echo $results->getMessage(); + return false; + } +} + +// Version 2.5 migrate to recording ids +// +// Do not do upgrades for sqlite3. Assume full support begins in 2.5 and our CREATE syntax is correct +if($amp_conf["AMPDBENGINE"] != "sqlite3") { + outn(_("Checking if recordings need migration..")); + $sql = "SELECT annmsg_id FROM findmefollow"; + $check = $db->getRow($sql, DB_FETCHMODE_ASSOC); + if(DB::IsError($check)) { + // Add recording_id field + // + out(_("migrating")); + outn(_("adding annmsg_id field..")); + $sql = "ALTER TABLE findmefollow ADD annmsg_id INTEGER"; + $result = $db->query($sql); + if(DB::IsError($result)) { + out(_("fatal error")); + die_freepbx($result->getDebugInfo()); + } else { + out(_("ok")); + } + outn(_("adding remotealert_id field..")); + $sql = "ALTER TABLE findmefollow ADD remotealert_id INTEGER"; + $result = $db->query($sql); + if(DB::IsError($result)) { + out(_("fatal error")); + die_freepbx($result->getDebugInfo()); + } else { + out(_("ok")); + } + outn(_("adding toolate_id field..")); + $sql = "ALTER TABLE findmefollow ADD toolate_id INTEGER"; + $result = $db->query($sql); + if(DB::IsError($result)) { + out(_("fatal error")); + die_freepbx($result->getDebugInfo()); + } else { + out(_("ok")); + } + + // Get all the valudes and replace them with recording_id + // + outn(_("migrate annmsg to ids..")); + $sql = "SELECT `grpnum`, `annmsg` FROM `findmefollow`"; + $results = $db->getAll($sql, DB_FETCHMODE_ASSOC); + if(DB::IsError($results)) { + out(_("fatal error")); + die_freepbx($results->getDebugInfo()); + } + $migrate_arr = array(); + $count = 0; + foreach ($results as $row) { + if (trim($row['annmsg']) != '') { + $rec_id = recordings_get_or_create_id($row['annmsg'], 'findmefollow'); + $migrate_arr[] = array($rec_id, $row['grpnum']); + $count++; + } + } + if ($count) { + $compiled = $db->prepare('UPDATE `findmefollow` SET `annmsg_id` = ? WHERE `grpnum` = ?'); + $result = $db->executeMultiple($compiled,$migrate_arr); + if(DB::IsError($result)) { + out(_("fatal error")); + die_freepbx($result->getDebugInfo()); + } + } + out(sprintf(_("migrated %s entries"),$count)); + + outn(_("migrate remotealert to ids..")); + $sql = "SELECT `grpnum`, `remotealert` FROM `findmefollow`"; + $results = $db->getAll($sql, DB_FETCHMODE_ASSOC); + if(DB::IsError($results)) { + out(_("fatal error")); + die_freepbx($results->getDebugInfo()); + } + $migrate_arr = array(); + $count = 0; + foreach ($results as $row) { + if (trim($row['remotealert']) != '') { + $rec_id = recordings_get_or_create_id($row['remotealert'], 'findmefollow'); + $migrate_arr[] = array($rec_id, $row['grpnum']); + $count++; + } + } + if ($count) { + $compiled = $db->prepare('UPDATE `findmefollow` SET `remotealert_id` = ? WHERE `grpnum` = ?'); + $result = $db->executeMultiple($compiled,$migrate_arr); + if(DB::IsError($result)) { + out(_("fatal error")); + die_freepbx($result->getDebugInfo()); + } + } + out(sprintf(_("migrated %s entries"),$count)); + + outn(_("migrate toolate to ids..")); + $sql = "SELECT `grpnum`, `toolate` FROM `findmefollow`"; + $results = $db->getAll($sql, DB_FETCHMODE_ASSOC); + if(DB::IsError($results)) { + out(_("fatal error")); + die_freepbx($results->getDebugInfo()); + } + $migrate_arr = array(); + $count = 0; + foreach ($results as $row) { + if (trim($row['toolate']) != '') { + $rec_id = recordings_get_or_create_id($row['toolate'], 'findmefollow'); + $migrate_arr[] = array($rec_id, $row['grpnum']); + $count++; + } + } + if ($count) { + $compiled = $db->prepare('UPDATE `findmefollow` SET `toolate_id` = ? WHERE `grpnum` = ?'); + $result = $db->executeMultiple($compiled,$migrate_arr); + if(DB::IsError($result)) { + out(_("fatal error")); + die_freepbx($result->getDebugInfo()); + } + } + out(sprintf(_("migrated %s entries"),$count)); + + // Now remove the old recording field replaced by new id field + // + outn(_("dropping annmsg field..")); + $sql = "ALTER TABLE `findmefollow` DROP `annmsg`"; + $result = $db->query($sql); + if(DB::IsError($result)) { + out(_("no annmsg field???")); + } else { + out(_("ok")); + } + outn(_("dropping remotealert field..")); + $sql = "ALTER TABLE `findmefollow` DROP `remotealert`"; + $result = $db->query($sql); + if(DB::IsError($result)) { + out(_("no remotealert field???")); + } else { + out(_("ok")); + } + outn(_("dropping toolate field..")); + $sql = "ALTER TABLE `findmefollow` DROP `toolate`"; + $result = $db->query($sql); + if(DB::IsError($result)) { + out(_("no toolate field???")); + } else { + out(_("ok")); + } + + } else { + out(_("already migrated")); + } +} + +?> Index: /modules/branches/2.6/pinsets/i18n/sv_SE/LC_MESSAGES/pinsets.po =================================================================== --- /modules/branches/2.6/pinsets/i18n/sv_SE/LC_MESSAGES/pinsets.po (revision 6761) +++ /modules/branches/2.6/pinsets/i18n/sv_SE/LC_MESSAGES/pinsets.po (revision 6761) @@ -0,0 +1,100 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: Freeà +BX pinsets\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2008-09-17 11:39+0200\n" +"PO-Revision-Date: 2008-09-17 14:08+0100\n" +"Last-Translator: Mikael Carlsson \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Poedit-Language: Swedish\n" +"X-Poedit-Country: SWEDEN\n" + +#: functions.inc.php:291 +msgid "PIN Set" +msgstr "PIN-kod" + +#: functions.inc.php:291 +msgid "Optional: Select a PIN set to use. If using this option, leave the Route Password field blank." +msgstr "Valfritt: VÀlj en PIN-kod. Om du vÀljer en PIN-kod, lÀmna dÃ¥ fÀltet Lösenord för vÀg tomt" + +#: functions.inc.php:294 +msgid "None" +msgstr "Ingen" + +#: page.pinsets.php:50 +msgid "Add Password Set" +msgstr "LÀgg till PIN-kod(er)" + +#: page.pinsets.php:63 +msgid "PIN Set " +msgstr "PIN-kod" + +#: page.pinsets.php:63 +msgid "deleted" +msgstr "borttagen" + +#: page.pinsets.php:76 +msgid "Delete PIN Set" +msgstr "Ta bort PIN-kod" + +#: page.pinsets.php:81 +msgid "PIN Set:" +msgstr "PIN-kod:" + +#: page.pinsets.php:81 +msgid "Add PIN Set" +msgstr "LÀgg till PIN-kod" + +#: page.pinsets.php:83 +msgid "PIN Sets are used to manage lists of PINs that can be used to access restricted features such as Outbound Routes. The PIN can also be added to the CDR record's 'accountcode' field." +msgstr "PIN-koder hanterad de listor med koder som kan anvÀndas pÃ¥ diverse stÀlle i FreePBX sÃ¥som UtgÃ¥ende vÀgar. PIN-koderna kan ocksÃ¥ visas i samtalsregistret i fÀltet 'accountcode' om detta vÀljs." + +#: page.pinsets.php:93 +msgid "Edit PIN Set" +msgstr "Redigera PIN-koder" + +#: page.pinsets.php:93 +msgid "New PIN Set" +msgstr "Ny PIN-kod" + +#: page.pinsets.php:100 +msgid "PIN Set Description:" +msgstr "Beskrivning för PIN-kod:" + +#: page.pinsets.php:104 +msgid "Record In CDR?:" +msgstr "LÀgga till i CDR?:" + +#: page.pinsets.php:104 +msgid "Select this box if you would like to record the PIN in the call detail records when used" +msgstr "Markera detta val om du vill lÀgga till i samtalsregistret vilken PIN.kod som anvÀndes" + +#: page.pinsets.php:108 +msgid "PIN List:" +msgstr "PIN-kodlista:" + +#: page.pinsets.php:108 +msgid "Enter a list of one or more PINs. One PIN per line." +msgstr "Skriv in en eller flera PIN-koder. En PIN-kod per rad." + +#: page.pinsets.php:115 +msgid "Submit Changes" +msgstr "Spara Àndringar" + +#: page.pinsets.php:128 +msgid "Please enter a valid Description" +msgstr "Skriv in en giltig beskrivining" + +#: module.xml +msgid "PIN Sets" +msgstr "PIN-koder" + Index: /modules/branches/2.6/pinsets/i18n/he_IL/LC_MESSAGES/pinsets.po =================================================================== --- /modules/branches/2.6/pinsets/i18n/he_IL/LC_MESSAGES/pinsets.po (revision 3441) +++ /modules/branches/2.6/pinsets/i18n/he_IL/LC_MESSAGES/pinsets.po (revision 3441) @@ -0,0 +1,77 @@ +# Hebrew version for PIN Sets FreePBX Module. +# Copyright (C) 2006 +# This file is distributed under the same license as the PACKAGE package. +# Shimi , 2006. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: FreePBX 2.2.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2006-10-17 17:20+0300\n" +"PO-Revision-Date: 2006-10-17 17:30+0300\n" +"Last-Translator: Shimi \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: page.pinsets.php:47 +msgid "Add Password Set" +msgstr "הוסף סט סיסמאות" + +#: page.pinsets.php:60 +msgid "PIN Set " +msgstr "סט סיסמא " + +#: page.pinsets.php:60 +msgid "deleted" +msgstr "נמחק" + +#: page.pinsets.php:73 +msgid "Delete PIN Set" +msgstr "מחק סט סיסמא" + +#: page.pinsets.php:78 +msgid "PIN Set:" +msgstr "סט סיסמא:" + +#: page.pinsets.php:78 +msgid "Add PIN Set" +msgstr "הוסף סט סיסמא" + +#: page.pinsets.php:80 +msgid "" +"PIN Sets are used to manage lists of PINs that can be used to access " +"restricted features such as Outbound Routes. The PIN can also be added to " +"the CDR record's 'accountcode' field." +msgstr "בסטי סיסמאות משתמשים כדי לנהל ךשימות של סיסמאות שבהן ניתן להשתמש בתכונות מוגבלות, כמו למשל ניתוב שיחות יו׊אות. כמו כן, ניתן להוסיף את הסיסמא לשדה 'accountcode' בךישומי השיחות של המעךכת." + +#: page.pinsets.php:90 +msgid "Edit PIN Set" +msgstr "עךוך סט סיסמאות" + +#: page.pinsets.php:90 +msgid "New PIN Set" +msgstr "סט סיסמאות חדש" + +#: page.pinsets.php:97 +msgid "PIN Set Description:" +msgstr "תיאוך סט סיסמאות:" + +#: page.pinsets.php:101 +msgid "Record In CDR?:" +msgstr "ךשום בךישום שיחות?:" + +#: page.pinsets.php:101 +msgid "" +"Select this box if you would like to record the PIN in the call detail " +"records when used" +msgstr "סמן תיבה זו אם ב׹שונך לךשום את הסיסמא ב׀יךוט ךישומי השיחות כאשך יש בה שימוש" + +#: page.pinsets.php:105 +msgid "PIN List:" +msgstr "ךשימת סיסמאות:" + +#: page.pinsets.php:105 +msgid "Enter a list of one or more PINs. One PIN per line." +msgstr "הכנס ךשימה של סיסמא אחת או יותך. סיסמא אחת בכל שוךה." Index: /modules/branches/2.6/pinsets/i18n/it_IL/LC_MESSAGES/pinsets.po =================================================================== --- /modules/branches/2.6/pinsets/i18n/it_IL/LC_MESSAGES/pinsets.po (revision 5363) +++ /modules/branches/2.6/pinsets/i18n/it_IL/LC_MESSAGES/pinsets.po (revision 5363) @@ -0,0 +1,81 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: 1.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2007-02-01 16:13+0100\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Francesco Romano\n" +"Language-Team: Italian\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=ISO-8859-1\n" +"Content-Transfer-Encoding: 8bit\n" + +#: page.pinsets.php:50 +msgid "Add Password Set" +msgstr "Aggiungi Gruppo PIN" + +#: page.pinsets.php:63 +msgid "PIN Set " +msgstr "Gruppo PIN" + +#: page.pinsets.php:63 +msgid "deleted" +msgstr "eliminato" + +#: page.pinsets.php:76 +msgid "Delete PIN Set" +msgstr "Elimina Gruppo PIN" + +#: page.pinsets.php:81 +msgid "PIN Set:" +msgstr "Gruppo PIN:" + +#: page.pinsets.php:81 +msgid "Add PIN Set" +msgstr "Aggiungi Gruppo PIN" + +#: page.pinsets.php:83 +msgid "" +"PIN Sets are used to manage lists of PINs that can be used to access " +"restricted features such as Outbound Routes. The PIN can also be added to " +"the CDR record's 'accountcode' field." +msgstr "In questa pagina è possibile gestire i Gruppi PIN, utilizzati per restringere l'accesso a particolari servizi come per esempio le Rotte in Uscita. Il PIN può essere anche inserito nel campo CDR 'accountcode' dell'utente." + +#: page.pinsets.php:93 +msgid "Edit PIN Set" +msgstr "Modifica Gruppo PIN" + +#: page.pinsets.php:93 +msgid "New PIN Set" +msgstr "Nuovo Gruppo PIN" + +#: page.pinsets.php:100 +msgid "PIN Set Description:" +msgstr "Descrizione Gruppo PIN" + +#: page.pinsets.php:104 +msgid "Record In CDR?:" +msgstr "Registra nel CDR?:" + +#: page.pinsets.php:104 +msgid "" +"Select this box if you would like to record the PIN in the call detail " +"records when used" +msgstr "Spuntare questa casella se si vogliono registrare i PIN nel dettaglio delle chiamate" + +#: page.pinsets.php:108 +msgid "PIN List:" +msgstr "Lista PIN:" + +#: page.pinsets.php:108 +msgid "Enter a list of one or more PINs. One PIN per line." +msgstr "Immettere in lista uno o più PIN. Uno per riga." + +msgid "Submit Changes" +msgstr "Invia" Index: /modules/branches/2.6/pinsets/i18n/pinsets.pot =================================================================== --- /modules/branches/2.6/pinsets/i18n/pinsets.pot (revision 6761) +++ /modules/branches/2.6/pinsets/i18n/pinsets.pot (revision 6761) @@ -0,0 +1,104 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2008-09-17 11:39+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" + +#: functions.inc.php:291 +msgid "PIN Set" +msgstr "" + +#: functions.inc.php:291 +msgid "" +"Optional: Select a PIN set to use. If using this option, leave the Route " +"Password field blank." +msgstr "" + +#: functions.inc.php:294 +msgid "None" +msgstr "" + +#: page.pinsets.php:50 +msgid "Add Password Set" +msgstr "" + +#: page.pinsets.php:63 +msgid "PIN Set " +msgstr "" + +#: page.pinsets.php:63 +msgid "deleted" +msgstr "" + +#: page.pinsets.php:76 +msgid "Delete PIN Set" +msgstr "" + +#: page.pinsets.php:81 +msgid "PIN Set:" +msgstr "" + +#: page.pinsets.php:81 +msgid "Add PIN Set" +msgstr "" + +#: page.pinsets.php:83 +msgid "" +"PIN Sets are used to manage lists of PINs that can be used to access " +"restricted features such as Outbound Routes. The PIN can also be added to " +"the CDR record's 'accountcode' field." +msgstr "" + +#: page.pinsets.php:93 +msgid "Edit PIN Set" +msgstr "" + +#: page.pinsets.php:93 +msgid "New PIN Set" +msgstr "" + +#: page.pinsets.php:100 +msgid "PIN Set Description:" +msgstr "" + +#: page.pinsets.php:104 +msgid "Record In CDR?:" +msgstr "" + +#: page.pinsets.php:104 +msgid "" +"Select this box if you would like to record the PIN in the call detail " +"records when used" +msgstr "" + +#: page.pinsets.php:108 +msgid "PIN List:" +msgstr "" + +#: page.pinsets.php:108 +msgid "Enter a list of one or more PINs. One PIN per line." +msgstr "" + +#: page.pinsets.php:115 +msgid "Submit Changes" +msgstr "" + +#: page.pinsets.php:128 +msgid "Please enter a valid Description" +msgstr "" + +#: module.xml +msgid "PIN Sets" +msgstr "" Index: /modules/branches/2.6/pinsets/i18n/ru_RU/LC_MESSAGES/pinsets.po =================================================================== --- /modules/branches/2.6/pinsets/i18n/ru_RU/LC_MESSAGES/pinsets.po (revision 6975) +++ /modules/branches/2.6/pinsets/i18n/ru_RU/LC_MESSAGES/pinsets.po (revision 6975) @@ -0,0 +1,102 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , 2008. +# +#, fuzzy + +msgid "" +msgstr "" +"Project-Id-Version: 1.4\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2008-01-29 15:07+0100\n" +"PO-Revision-Date: 2008-10-13 15:07+0100\n" +"Last-Translator: Alexander Kozyrev\n" +"Language-Team: Russian\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=ISO-8859-5\n" +"Content-Transfer-Encoding: 8bit\n" + +#: functions.php:291 +msgid "PIN Set" +msgstr "»Øáâ PIN-ÚÞÔÞÒ" + +#: functions.inc.php:291 +msgid "" +"Optional: Select a PIN set to use. If using this option, leave the Route " +"Password field blank." +msgstr "" +"ŸßæØÞÝÐÛìÝÞ: ÒëÑàÐâì ÛØáâ PIN-ÚÞÔÞÒ. µáÛØ ØáßÞÛì×ãÕâáï íâÐ ÞßæØï - ÝÕÞÑåÞÔØÜÞ " +"ÞáâÐÒÛïâì ßÞÛÕ ¿ÐàÞÛì ÝÐ ÜÐàèàãâÕ ßãáâëÜ." + +#: functions.inc.php:294 +msgid "None" +msgstr "œÕâ" + +#: page.pinsets.php:50 +msgid "Add Password Set" +msgstr "ŽÞÑÐÒØâì ÛØáâ PIN-ÚÞÔÞÒ" + +#: page.pinsets.php:63 +msgid "PIN Set " +msgstr "»Øáâ PIN-ÚÞÔÞÒ" + +#: page.pinsets.php:63 +msgid "deleted" +msgstr "ãÔÐÛÕÝÞ" + +#: page.pinsets.php:76 +msgid "Delete PIN Set" +msgstr "ÃÔÐÛØâì ÛØáâ PIN-ÚÞÔÞÒ" + +#: page.pinsets.php:81 +msgid "PIN Set:" +msgstr "œÐÑÞà PIN:" + +#: page.pinsets.php:81 +msgid "Add PIN Set" +msgstr "ŽÞÑÐÒØâì ÛØáâ PIN-ÚÞÔÞÒ" + +#: page.pinsets.php:83 +msgid "" +"PIN Sets are used to manage lists of PINs that can be used to access " +"restricted features such as Outbound Routes. The PIN can also be added to " +"the CDR record's 'accountcode' field." +msgstr "" +"ŒÞÔãÛì áߨáÚÞÒ PIN-ÚÞÔÞÒ ØáßÞÛì×ãÕâáï ÔÛï ÞàÓÐÝØ×ÐæØØ ÔÞáâãßÐ Ú áßÕæØÐÛìÝëÜ " +"ØáåÞÔïéØÜ ÜÐàèàãâÐÜ á ÞÓàÐÝØçÕÝÝëÜØ ßàÐÒÐÜØ. ÁÐÜ ÝÐÑØàÐÕÜëÙ PIN-ÚÞÔ ÜÞÖÝÞ ÔÞÑÐÒÛïâì " +"âÐÚÖÕ Ò Þâçñâ Þ ×ÒÞÝÚÐå Ò áßÕæØÐÛìÝÞÕ ßÞÛÕ 'accountcode'." + +#: page.pinsets.php:93 +msgid "Edit PIN Set" +msgstr "ž×ÜÕÝØâì ÛØáâ PIN-ÚÞÔÞÒ" + +#: page.pinsets.php:93 +msgid "New PIN Set" +msgstr "œÞÒëÙ ÛØáâ PIN-ÚÞÔÞÒ" + +#: page.pinsets.php:100 +msgid "PIN Set Description:" +msgstr "ŸßØáÐÝØÕ:" + +#: page.pinsets.php:104 +msgid "Record In CDR?:" +msgstr "·ÐߨáëÒÐâì Ò CDR?" + +#: page.pinsets.php:104 +msgid "" +"Select this box if you would like to record the PIN in the call detail " +"records when used" +msgstr "" +"²ëÑÕàØâÕ íâã ÞßæØî, ÕáÛØ ÝãÖÝÞ ×ÐߨáëÒÐâì PIN Ò ÖãàÝÐÛ ×ÒÞÝÚÞÒ ÔÛï ÔÕâÐÛØ×ÐæØØ." + +#: page.pinsets.php:108 +msgid "PIN List:" +msgstr "ÁߨáÞÚ PIN:" + +#: page.pinsets.php:108 +msgid "Enter a list of one or more PINs. One PIN per line." +msgstr "²ÒÕÔØâÕ PIN-ÚÞÔë Ò áߨáÞÚ, ßÞ ÞÔÝÞÜã Ò áâàÞÚÕ." + +msgid "Submit Changes" +msgstr "¿àØÜÕÝØâì Ø×ÜÕÝÕÝØï" Index: /modules/branches/2.6/pinsets/uninstall.php =================================================================== --- /modules/branches/2.6/pinsets/uninstall.php (revision 4587) +++ /modules/branches/2.6/pinsets/uninstall.php (revision 4587) @@ -0,0 +1,18 @@ +\n"; +} + +echo "dropping table pinsets.."; +sql('DROP TABLE IF EXISTS `pinsets`'); +echo "done
\n"; + + +?> Index: /modules/branches/2.6/pinsets/install.sql =================================================================== --- /modules/branches/2.6/pinsets/install.sql (revision 4241) +++ /modules/branches/2.6/pinsets/install.sql (revision 4241) @@ -0,0 +1,1 @@ +-- empty file, because of http://freepbx.org/trac/ticket/1277 Index: /modules/branches/2.6/pinsets/module.xml =================================================================== --- /modules/branches/2.6/pinsets/module.xml (revision 6918) +++ /modules/branches/2.6/pinsets/module.xml (revision 6918) @@ -0,0 +1,27 @@ + + pinsets + PIN Sets + 2.5.0.1 + setup + Internal Options & Configuration + Allow creation of lists of PINs (numbers for passwords) that can be used by other modules (eg, trunks). + + *2.5.0.1* #3240, #3258 + *2.5.0* #2845, #2764 tabindex + *2.4.0.1* #2843 Russian Translation + *2.4.0* bump for 2.4 + *1.2.3* #2393 add support for pinless dialing + *1.2.2.2* #2172 deprecated use of | + *1.2.2.1* bump for rc1 + *1.2.2* Put None label in menu hook + *1.2.1* #1770 added proper uninstall + *1.2* Add SQLite3 support, fixes http://freepbx.org/trac/ticket/1778 + *1.1* Add he_IL translation, add naftali5's fixes where pinsets were being lost when moved around. + *1.0.11* Stop potential error where a random pinset is appearing when creating a new trunk + + + PIN Sets + + release/2.5/pinsets-2.5.0.1.tgz + 599da0b32fa4fc492c47bcdc396a1afc + Index: /modules/branches/2.6/pinsets/functions.inc.php =================================================================== --- /modules/branches/2.6/pinsets/functions.inc.php (revision 6911) +++ /modules/branches/2.6/pinsets/functions.inc.php (revision 6911) @@ -0,0 +1,353 @@ +_conf classes, +// which can be used in _get_conf below. +class pinsets_conf { + // return an array of filenames to write + // files named like pinset_N + var $_pinsets = array(); + + function get_filename() { + $files = array(); + foreach (array_keys($this->_pinsets) as $pinset) { + $files[] = 'pinset_'.$pinset; + } + return $files; + } + + function addPinsets($setid, $pins) { + $this->_pinsets[$setid] = $pins; + } + + // return the output that goes in each of the files + function generateConf($file) { + $setid = ltrim($file,'pinset_'); + $output = $this->_pinsets[$setid]; + return $output; + } +} + +/* Generates passwd files for pinsets + We call this with retrieve_conf +*/ +function pinsets_get_config($engine) { + global $ext; // is this the best way to pass this? + global $asterisk_conf; + global $pinsets_conf; // our pinsets object (created in retrieve_conf) + switch($engine) { + case "asterisk": + $allpinsets = pinsets_list(true); + if(is_array($allpinsets)) { + foreach($allpinsets as $item) { + // write our own pin list files + $pinsets_conf->addPinsets($item['pinsets_id'],$item['passwords']); + } + + // write out a macro that handles the authenticate + $ext->add('macro-pinsets', 's', '', new ext_gotoif('${ARG2} = 1','cdr,1')); + $ext->add('macro-pinsets', 's', '', new ext_execif('$["${DB(AMPUSER/${AMPUSER}/pinless)}" != "NOPASSWD"]', 'Authenticate',$asterisk_conf['astetcdir'].'/pinset_${ARG1}')); + $ext->add('macro-pinsets', 's', '', new ext_execif('$["${DB(AMPUSER/${AMPUSER}/pinless)}" != "NOPASSWD"]', 'ResetCDR')); + // authenticate with the CDR option (a) + $ext->add('macro-pinsets', 'cdr', '', new ext_execif('$["${DB(AMPUSER/${AMPUSER}/pinless)}" != "NOPASSWD"]', 'Authenticate',$asterisk_conf['astetcdir'].'/pinset_${ARG1},a')); + $ext->add('macro-pinsets', 'cdr', '', new ext_execif('$["${DB(AMPUSER/${AMPUSER}/pinless)}" != "NOPASSWD"]', 'ResetCDR')); + } + break; + } +} + +function pinsets_hookGet_config($engine) { + global $ext; + switch($engine) { + case "asterisk": + $hooklist = pinsets_list(true); + if(is_array($hooklist)) { + foreach($hooklist as $thisitem) { + + // get the used_by field + if(empty($thisitem['used_by'])) { + $usedby = ""; + } else { + $usedby = $thisitem['used_by']; + } + + // create an array from usedby + $arrUsedby = explode(',',$usedby); + + if(is_array($arrUsedby)){ + foreach($arrUsedby as $strUsedby){ + // if it's an outbound route + if(strpos($strUsedby,'routing_') !== false) { + $route = substr($strUsedby,8); + $context = 'outrt-'.$route; + + // get all the routes that are in this context + $routes = core_routing_getroutepatterns($route); + + // we need to manipulate each route/extension + foreach($routes as $rt) { + //strip the pipe out as that's what we use for the dialplan extension + $extension = str_replace('|','',$rt); + // If there are any wildcards in there, add a _ to the start + if (preg_match("/\.|z|x|\[|\]/i", $extension)) { $extension = "_".$extension; } + $ext->splice($context, $extension, 1, new ext_macro('pinsets', $thisitem['pinsets_id'].','.$thisitem['addtocdr'])); + } + + } + } + } + + } + } + break; + } +} + + +//get the existing meetme extensions +function pinsets_list($getAll=false) { + $results = sql("SELECT * FROM pinsets","getAll",DB_FETCHMODE_ASSOC); + if(is_array($results)){ + foreach($results as $result){ + // check to see if we have a dept match for the current AMP User. + if ($getAll || checkDept($result['deptname'])){ + // return this item's dialplan destination, and the description + $allowed[] = $result; + } + } + } + if (isset($allowed)) { + return $allowed; + } else { + return null; + } +} + +function pinsets_get($id){ + $results = sql("SELECT * FROM pinsets WHERE pinsets_id = '$id'","getRow",DB_FETCHMODE_ASSOC); + return $results; +} + +function pinsets_del($id){ + global $asterisk_conf; + + $filename = $asterisk_conf['astetcdir'].'/pinset_'.$id; + if (file_exists($filename)) { + unlink($filename); + } + + $results = sql("DELETE FROM pinsets WHERE pinsets_id = '$id'","query"); +} + +function pinsets_add($post){ + if(!pinsets_chk($post)) + return false; + extract($post); + $passwords = pinsets_clean($passwords); + if(empty($description)) $description = 'Unnamed'; + $results = sql("INSERT INTO pinsets (description,passwords,addtocdr,deptname) values (\"$description\",\"$passwords\",\"$addtocdr\",\"$deptname\")"); +} + +function pinsets_edit($id,$post){ + if(!pinsets_chk($post)) + return false; + extract($post); + $passwords = pinsets_clean($passwords); + if(empty($description)) $description = 'Unnamed'; + $results = sql("UPDATE pinsets SET description = \"$description\", passwords = \"$passwords\", addtocdr = \"$addtocdr\", deptname = \"$deptname\" WHERE pinsets_id = \"$id\""); +} + +// clean and remove duplicates +function pinsets_clean($passwords) { + + $passwords = explode("\n",$passwords); + + if (!$passwords) { + $passwords = null; + } + + foreach (array_keys($passwords) as $key) { + //trim it + $passwords[$key] = trim($passwords[$key]); + + // remove invalid chars + $passwords[$key] = preg_replace("/[^0-9#*]/", "", $passwords[$key]); + + // remove blanks + if ($passwords[$key] == "") unset($passwords[$key]); + } + + // check for duplicates, and re-sequence + $passwords = array_values(array_unique($passwords)); + + if (is_array($passwords)) + return implode($passwords,"\n"); + else + return ""; +} + +// ensures post vars is valid +function pinsets_chk($post){ + return true; +} + +//removes a pinset from a route and shifts priority for all outbound routing pinsets +function pinsets_adjustroute($route,$action,$routepinset='',$direction='',$newname='') { + $priority = (int)substr($route,0,3); + //create a selection of available pinsets + $pinsets = pinsets_list(); + // loop through all the pinsets + if(is_array($pinsets)){ + foreach($pinsets as $pinset) { + + // get the used_by field + if(empty($pinset['used_by'])) { + $usedby = ""; + } else { + $usedby = $pinset['used_by']; + } + + // remove the target if it's already in this row's used_by field + //$usedby = str_replace("routing_{$route}","",$usedby); + + // create an array from usedby + $arrUsedby = explode(',',$usedby); + + for($i=0;$i $priority) { + $newpriority = str_pad($usedbypriority - 1, 3, "0", STR_PAD_LEFT); + $arrUsedby[$i] = 'routing_'.$newpriority.'-'.$usedbyroute; + } + break; + case 'prioritizeroute'; + $addpriority = ($direction=='up')?-1:1; + $usedbypriority = (int)substr($arrUsedby[$i],8,3); + $usedbyroute = substr($arrUsedby[$i],12); + if ($priority + $addpriority == $usedbypriority) { + $newpriority = str_pad($priority, 3, "0", STR_PAD_LEFT); + $arrUsedby[$i] = 'routing_'.$newpriority.'-'.$usedbyroute; + } + if ($arrUsedby[$i] == "routing_{$route}") { + $newpriority = str_pad($priority + $addpriority, 3, "0", STR_PAD_LEFT); + $arrUsedby[$i] = 'routing_'.$newpriority.'-'.$usedbyroute; + } + + break; + case 'renameroute'; + if ($arrUsedby[$i] == "routing_{$route}") { + $newpriority = str_pad($priority, 3, "0", STR_PAD_LEFT); + $arrUsedby[$i] = 'routing_'.$newpriority.'-'.$newname; + } + break; + case 'editroute'; + $usedbyroute = (int)substr($arrUsedby[$i],12); + if ($arrUsedby[$i] == "routing_{$route}") { + unset($arrUsedby[$i]); + } + break; + } + } + } + + // save the route in the selected pin + if ($routepinset == $pinset['pinsets_id'] && $action == 'editroute') { + $arrUsedby[] = 'routing_'.$route; + } + + // remove any duplicates + $arrUsedby = array_values(array_unique($arrUsedby)); + + // create a new string + $strUsedby = implode($arrUsedby,','); + + // Insure there's no leading or trailing commas + $strUsedby = trim ($strUsedby, ','); + + + // store the used_by column in the DB + sql("UPDATE pinsets SET used_by = \"{$strUsedby}\" WHERE pinsets_id = \"{$pinset['pinsets_id']}\""); + } + } +} + +// provide hook for routing +function pinsets_hook_core($viewing_itemid, $target_menuid) { + switch ($target_menuid) { + // only provide display for outbound routing + case 'routing': + //create a selection of available pinsets + $pinsets = pinsets_list(); + $hookhtml = ' + + '._("PIN Set").''._('Optional: Select a PIN set to use. If using this option, leave the Route Password field blank.').': + + + + + '; + return $hookhtml; + break; + default: + return false; + break; + } +} + +function pinsets_hookProcess_core($viewing_itemid, $request) { + + // Record any hook selections made by target modules + // We'll add these to the pinset's "used_by" column in the format _ + // multiple targets could select a single pinset, so we'll comma delimiter them + + // this is really a crappy way to store things. + // Any module that is hooked by pinsets when submitted will result in all the "used_by" fields being re-written + switch ($request['display']) { + case 'routing': + // if routing was using post for the form (incl delete), i wouldn't need all these conditions + // if(isset($request['Submit']) || (isset($request['action']) && ($request['action'] == "delroute" || $request['action'] == "prioritizeroute" || $request['action'] == "renameroute"))) { + + $action = (isset($request['action']))?$request['action']:null; + $route = $viewing_itemid; + if (isset($request['reporoutekey']) && $action == 'prioritizeroute') { + $outbound_routes = core_routing_getroutenames(); + $route = $outbound_routes[(int)$request['reporoutekey']][0]; + } + if (isset($request['Submit']) ) { + $action = (isset($action))?$action:'editroute'; + } + if (isset($action)) { + $direction = (isset($request['reporoutedirection']))?$request['reporoutedirection']:null; + $newname = (isset($request['newroutename']))?$request['newroutename']:null; + pinsets_adjustroute($route,$action,$request['pinsets'],$direction,$newname); + } + + break; + } +} + + +?> Index: /modules/branches/2.6/pinsets/page.pinsets.php =================================================================== --- /modules/branches/2.6/pinsets/page.pinsets.php (revision 5919) +++ /modules/branches/2.6/pinsets/page.pinsets.php (revision 5919) @@ -0,0 +1,141 @@ + + +
+ + +
+ +
+

'._("PIN Set ").' '.$itemid.' '._("deleted").'!

'; +} else { + if ($itemid){ + //get details for this time condition + $thisItem = pinsets_get($itemid); + } + + $delURL = $_SERVER['PHP_SELF'].'?'.$_SERVER['QUERY_STRING'].'&action=delete'; + $delButton = " +
+ + + + +
"; + +?> + +

+ +

+ + + +
+ + + _deptname ?>"> + + + + + + + + + + + + + + + + + + + + + + + + +

tabindex="">
+ +

" tabindex="">
+ + + +
+ Index: /modules/branches/2.6/pinsets/install.php =================================================================== --- /modules/branches/2.6/pinsets/install.php (revision 4767) +++ /modules/branches/2.6/pinsets/install.php (revision 4767) @@ -0,0 +1,22 @@ +query($sql); +if(DB::IsError($check)) { + die_freepbx("Can not create `pinsets` table\n"); +} + +?> Index: /modules/branches/2.6/mk_i18n_structure =================================================================== --- /modules/branches/2.6/mk_i18n_structure (revision 5781) +++ /modules/branches/2.6/mk_i18n_structure (revision 5781) @@ -0,0 +1,28 @@ +#!/bin/bash +# +# Helper utility to create directory structure add a bunch of translation files for the modules +# +# usage looks like: +# +# ./mk_i18n_structure ru_RU /tmp/Russian +# +# where ru_RU would be the language, and /tmp/Russian whould be where all the files +# have been placed + +for i in *; do + echo $i: + if [ -d $i ] && [ -a ${2}/${i}.mo ] && [ -a ${2}/${i}.po ]; then + if [ ! -d ${i}/i18n ]; then + svn mkdir ${i}/i18n + fi + if [ ! -d ${i}/i18n/$1 ]; then + svn mkdir ${i}/i18n/$1 + svn mkdir ${i}/i18n/$1/LC_MESSAGES + fi + cp $2/$i.mo $i/i18n/$1/LC_MESSAGES/ + cp $2/$i.po $i/i18n/$1/LC_MESSAGES/ + svn add $i/i18n/$1/LC_MESSAGES/$i.mo + svn add $i/i18n/$1/LC_MESSAGES/$i.po + fi +done + Index: /modules/branches/2.6/core/XML_Unserializer.php =================================================================== --- /modules/branches/2.6/core/XML_Unserializer.php (revision 4538) +++ /modules/branches/2.6/core/XML_Unserializer.php (revision 4538) @@ -0,0 +1,856 @@ + + * @copyright 1997-2005 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: Unserializer.php,v 1.39 2005/09/28 11:19:56 schst Exp $ + * @link http://pear.php.net/package/XML_Serializer + * @see XML_Unserializer + */ + +/** + * uses PEAR error managemt + */ +//require_once 'PEAR.php'; + +/** + * uses XML_Parser to unserialize document + */ +//require_once 'XML/Parser.php'; + +/** + * option: Convert nested tags to array or object + * + * Possible values: + * - array + * - object + * - associative array to define this option per tag name + */ +define('XML_UNSERIALIZER_OPTION_COMPLEXTYPE', 'complexType'); + +/** + * option: Name of the attribute that stores the original key + * + * Possible values: + * - any string + */ +define('XML_UNSERIALIZER_OPTION_ATTRIBUTE_KEY', 'keyAttribute'); + +/** + * option: Name of the attribute that stores the type + * + * Possible values: + * - any string + */ +define('XML_UNSERIALIZER_OPTION_ATTRIBUTE_TYPE', 'typeAttribute'); + +/** + * option: Name of the attribute that stores the class name + * + * Possible values: + * - any string + */ +define('XML_UNSERIALIZER_OPTION_ATTRIBUTE_CLASS', 'classAttribute'); + +/** + * option: Whether to use the tag name as a class name + * + * Possible values: + * - true or false + */ +define('XML_UNSERIALIZER_OPTION_TAG_AS_CLASSNAME', 'tagAsClass'); + +/** + * option: Name of the default class + * + * Possible values: + * - any string + */ +define('XML_UNSERIALIZER_OPTION_DEFAULT_CLASS', 'defaultClass'); + +/** + * option: Whether to parse attributes + * + * Possible values: + * - true or false + */ +define('XML_UNSERIALIZER_OPTION_ATTRIBUTES_PARSE', 'parseAttributes'); + +/** + * option: Key of the array to store attributes (if any) + * + * Possible values: + * - any string + * - false (disabled) + */ +define('XML_UNSERIALIZER_OPTION_ATTRIBUTES_ARRAYKEY', 'attributesArray'); + +/** + * option: string to prepend attribute name (if any) + * + * Possible values: + * - any string + * - false (disabled) + */ +define('XML_UNSERIALIZER_OPTION_ATTRIBUTES_PREPEND', 'prependAttributes'); + +/** + * option: key to store the content, if XML_UNSERIALIZER_OPTION_ATTRIBUTES_PARSE is used + * + * Possible values: + * - any string + */ +define('XML_UNSERIALIZER_OPTION_CONTENT_KEY', 'contentName'); + +/** + * option: map tag names + * + * Possible values: + * - associative array + */ +define('XML_UNSERIALIZER_OPTION_TAG_MAP', 'tagMap'); + +/** + * option: list of tags that will always be enumerated + * + * Possible values: + * - indexed array + */ +define('XML_UNSERIALIZER_OPTION_FORCE_ENUM', 'forceEnum'); + +/** + * option: Encoding of the XML document + * + * Possible values: + * - UTF-8 + * - ISO-8859-1 + */ +define('XML_UNSERIALIZER_OPTION_ENCODING_SOURCE', 'encoding'); + +/** + * option: Desired target encoding of the data + * + * Possible values: + * - UTF-8 + * - ISO-8859-1 + */ +define('XML_UNSERIALIZER_OPTION_ENCODING_TARGET', 'targetEncoding'); + +/** + * option: Callback that will be applied to textual data + * + * Possible values: + * - any valid PHP callback + */ +define('XML_UNSERIALIZER_OPTION_DECODE_FUNC', 'decodeFunction'); + +/** + * option: whether to return the result of the unserialization from unserialize() + * + * Possible values: + * - true + * - false (default) + */ +define('XML_UNSERIALIZER_OPTION_RETURN_RESULT', 'returnResult'); + +/** + * option: set the whitespace behaviour + * + * Possible values: + * - XML_UNSERIALIZER_WHITESPACE_KEEP + * - XML_UNSERIALIZER_WHITESPACE_TRIM + * - XML_UNSERIALIZER_WHITESPACE_NORMALIZE + */ +define('XML_UNSERIALIZER_OPTION_WHITESPACE', 'whitespace'); + +/** + * Keep all whitespace + */ +define('XML_UNSERIALIZER_WHITESPACE_KEEP', 'keep'); + +/** + * remove whitespace from start and end of the data + */ +define('XML_UNSERIALIZER_WHITESPACE_TRIM', 'trim'); + +/** + * normalize whitespace + */ +define('XML_UNSERIALIZER_WHITESPACE_NORMALIZE', 'normalize'); + +/** + * option: whether to ovverride all options that have been set before + * + * Possible values: + * - true + * - false (default) + */ +define('XML_UNSERIALIZER_OPTION_OVERRIDE_OPTIONS', 'overrideOptions'); + +/** + * option: list of tags, that will not be used as keys + */ +define('XML_UNSERIALIZER_OPTION_IGNORE_KEYS', 'ignoreKeys'); + +/** + * option: whether to use type guessing for scalar values + */ +define('XML_UNSERIALIZER_OPTION_GUESS_TYPES', 'guessTypes'); + +/** + * error code for no serialization done + */ +define('XML_UNSERIALIZER_ERROR_NO_UNSERIALIZATION', 151); + +/** + * XML_Unserializer + * + * class to unserialize XML documents that have been created with + * XML_Serializer. To unserialize an XML document you have to add + * type hints to the XML_Serializer options. + * + * If no type hints are available, XML_Unserializer will guess how + * the tags should be treated, that means complex structures will be + * arrays and tags with only CData in them will be strings. + * + * + * require_once 'XML/Unserializer.php'; + * + * // be careful to always use the ampersand in front of the new operator + * $unserializer = &new XML_Unserializer(); + * + * $unserializer->unserialize($xml); + * + * $data = $unserializer->getUnserializedData(); + * + * + * + * @category XML + * @package XML_Serializer + * @author Stephan Schmidt + * @copyright 1997-2005 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 0.18.0 + * @link http://pear.php.net/package/XML_Serializer + * @see XML_Serializer + */ +class XML_Unserializer extends PEAR +{ + /** + * list of all available options + * + * @access private + * @var array + */ + var $_knownOptions = array( + XML_UNSERIALIZER_OPTION_COMPLEXTYPE, + XML_UNSERIALIZER_OPTION_ATTRIBUTE_KEY, + XML_UNSERIALIZER_OPTION_ATTRIBUTE_TYPE, + XML_UNSERIALIZER_OPTION_ATTRIBUTE_CLASS, + XML_UNSERIALIZER_OPTION_TAG_AS_CLASSNAME, + XML_UNSERIALIZER_OPTION_DEFAULT_CLASS, + XML_UNSERIALIZER_OPTION_ATTRIBUTES_PARSE, + XML_UNSERIALIZER_OPTION_ATTRIBUTES_ARRAYKEY, + XML_UNSERIALIZER_OPTION_ATTRIBUTES_PREPEND, + XML_UNSERIALIZER_OPTION_CONTENT_KEY, + XML_UNSERIALIZER_OPTION_TAG_MAP, + XML_UNSERIALIZER_OPTION_FORCE_ENUM, + XML_UNSERIALIZER_OPTION_ENCODING_SOURCE, + XML_UNSERIALIZER_OPTION_ENCODING_TARGET, + XML_UNSERIALIZER_OPTION_DECODE_FUNC, + XML_UNSERIALIZER_OPTION_RETURN_RESULT, + XML_UNSERIALIZER_OPTION_WHITESPACE, + XML_UNSERIALIZER_OPTION_IGNORE_KEYS, + XML_UNSERIALIZER_OPTION_GUESS_TYPES + ); + /** + * default options for the serialization + * + * @access private + * @var array + */ + var $_defaultOptions = array( + XML_UNSERIALIZER_OPTION_COMPLEXTYPE => 'array', // complex types will be converted to arrays, if no type hint is given + XML_UNSERIALIZER_OPTION_ATTRIBUTE_KEY => '_originalKey', // get array key/property name from this attribute + XML_UNSERIALIZER_OPTION_ATTRIBUTE_TYPE => '_type', // get type from this attribute + XML_UNSERIALIZER_OPTION_ATTRIBUTE_CLASS => '_class', // get class from this attribute (if not given, use tag name) + XML_UNSERIALIZER_OPTION_TAG_AS_CLASSNAME => true, // use the tagname as the classname + XML_UNSERIALIZER_OPTION_DEFAULT_CLASS => 'stdClass', // name of the class that is used to create objects + XML_UNSERIALIZER_OPTION_ATTRIBUTES_PARSE => false, // parse the attributes of the tag into an array + XML_UNSERIALIZER_OPTION_ATTRIBUTES_ARRAYKEY => false, // parse them into sperate array (specify name of array here) + XML_UNSERIALIZER_OPTION_ATTRIBUTES_PREPEND => '', // prepend attribute names with this string + XML_UNSERIALIZER_OPTION_CONTENT_KEY => '_content', // put cdata found in a tag that has been converted to a complex type in this key + XML_UNSERIALIZER_OPTION_TAG_MAP => array(), // use this to map tagnames + XML_UNSERIALIZER_OPTION_FORCE_ENUM => array(), // these tags will always be an indexed array + XML_UNSERIALIZER_OPTION_ENCODING_SOURCE => null, // specify the encoding character of the document to parse + XML_UNSERIALIZER_OPTION_ENCODING_TARGET => null, // specify the target encoding + XML_UNSERIALIZER_OPTION_DECODE_FUNC => null, // function used to decode data + XML_UNSERIALIZER_OPTION_RETURN_RESULT => false, // unserialize() returns the result of the unserialization instead of true + XML_UNSERIALIZER_OPTION_WHITESPACE => XML_UNSERIALIZER_WHITESPACE_TRIM, // remove whitespace around data + XML_UNSERIALIZER_OPTION_IGNORE_KEYS => array(), // List of tags that will automatically be added to the parent, instead of adding a new key + XML_UNSERIALIZER_OPTION_GUESS_TYPES => false // Whether to use type guessing + ); + + /** + * current options for the serialization + * + * @access public + * @var array + */ + var $options = array(); + + /** + * unserialized data + * + * @access private + * @var string + */ + var $_unserializedData = null; + + /** + * name of the root tag + * + * @access private + * @var string + */ + var $_root = null; + + /** + * stack for all data that is found + * + * @access private + * @var array + */ + var $_dataStack = array(); + + /** + * stack for all values that are generated + * + * @access private + * @var array + */ + var $_valStack = array(); + + /** + * current tag depth + * + * @access private + * @var int + */ + var $_depth = 0; + + /** + * XML_Parser instance + * + * @access private + * @var object XML_Parser + */ + var $_parser = null; + + /** + * constructor + * + * @access public + * @param mixed $options array containing options for the unserialization + */ + function XML_Unserializer($options = null) + { + if (is_array($options)) { + $this->options = array_merge($this->_defaultOptions, $options); + } else { + $this->options = $this->_defaultOptions; + } + } + + /** + * return API version + * + * @access public + * @static + * @return string $version API version + */ + function apiVersion() + { + return '0.18.0'; + } + + /** + * reset all options to default options + * + * @access public + * @see setOption(), XML_Unserializer(), setOptions() + */ + function resetOptions() + { + $this->options = $this->_defaultOptions; + } + + /** + * set an option + * + * You can use this method if you do not want to set all options in the constructor + * + * @access public + * @see resetOption(), XML_Unserializer(), setOptions() + */ + function setOption($name, $value) + { + $this->options[$name] = $value; + } + + /** + * sets several options at once + * + * You can use this method if you do not want to set all options in the constructor + * + * @access public + * @see resetOption(), XML_Unserializer(), setOption() + */ + function setOptions($options) + { + $this->options = array_merge($this->options, $options); + } + + /** + * unserialize data + * + * @access public + * @param mixed $data data to unserialize (string, filename or resource) + * @param boolean $isFile data should be treated as a file + * @param array $options options that will override the global options for this call + * @return boolean $success + */ + function unserialize($data, $isFile = false, $options = null) + { + $this->_unserializedData = null; + $this->_root = null; + + // if options have been specified, use them instead + // of the previously defined ones + if (is_array($options)) { + $optionsBak = $this->options; + if (isset($options[XML_UNSERIALIZER_OPTION_OVERRIDE_OPTIONS]) && $options[XML_UNSERIALIZER_OPTION_OVERRIDE_OPTIONS] == true) { + $this->options = array_merge($this->_defaultOptions, $options); + } else { + $this->options = array_merge($this->options, $options); + } + } else { + $optionsBak = null; + } + + $this->_valStack = array(); + $this->_dataStack = array(); + $this->_depth = 0; + + $this->_createParser(); + + if (is_string($data)) { + if ($isFile) { + $result = $this->_parser->setInputFile($data); + if (PEAR::isError($result)) { + return $result; + } + $result = $this->_parser->parse(); + } else { + $result = $this->_parser->parseString($data,true); + } + } else { + $this->_parser->setInput($data); + $result = $this->_parser->parse(); + } + + if ($this->options[XML_UNSERIALIZER_OPTION_RETURN_RESULT] === true) { + $return = $this->_unserializedData; + } else { + $return = true; + } + + if ($optionsBak !== null) { + $this->options = $optionsBak; + } + + if (PEAR::isError($result)) { + return $result; + } + + return $return; + } + + /** + * get the result of the serialization + * + * @access public + * @return string $serializedData + */ + function getUnserializedData() + { + if ($this->_root === null) { + return $this->raiseError('No unserialized data available. Use XML_Unserializer::unserialize() first.', XML_UNSERIALIZER_ERROR_NO_UNSERIALIZATION); + } + return $this->_unserializedData; + } + + /** + * get the name of the root tag + * + * @access public + * @return string $rootName + */ + function getRootName() + { + if ($this->_root === null) { + return $this->raiseError('No unserialized data available. Use XML_Unserializer::unserialize() first.', XML_UNSERIALIZER_ERROR_NO_UNSERIALIZATION); + } + return $this->_root; + } + + /** + * Start element handler for XML parser + * + * @access private + * @param object $parser XML parser object + * @param string $element XML element + * @param array $attribs attributes of XML tag + * @return void + */ + function startHandler($parser, $element, $attribs) + { + if (isset($attribs[$this->options[XML_UNSERIALIZER_OPTION_ATTRIBUTE_TYPE]])) { + $type = $attribs[$this->options[XML_UNSERIALIZER_OPTION_ATTRIBUTE_TYPE]]; + $guessType = false; + } else { + $type = 'string'; + if ($this->options[XML_UNSERIALIZER_OPTION_GUESS_TYPES] === true) { + $guessType = true; + } else { + $guessType = false; + } + } + + if ($this->options[XML_UNSERIALIZER_OPTION_DECODE_FUNC] !== null) { + $attribs = array_map($this->options[XML_UNSERIALIZER_OPTION_DECODE_FUNC], $attribs); + } + + $this->_depth++; + $this->_dataStack[$this->_depth] = null; + + if (is_array($this->options[XML_UNSERIALIZER_OPTION_TAG_MAP]) && isset($this->options[XML_UNSERIALIZER_OPTION_TAG_MAP][$element])) { + $element = $this->options[XML_UNSERIALIZER_OPTION_TAG_MAP][$element]; + } + + $val = array( + 'name' => $element, + 'value' => null, + 'type' => $type, + 'guessType' => $guessType, + 'childrenKeys' => array(), + 'aggregKeys' => array() + ); + + if ($this->options[XML_UNSERIALIZER_OPTION_ATTRIBUTES_PARSE] == true && (count($attribs) > 0)) { + $val['children'] = array(); + $val['type'] = $this->_getComplexType($element); + $val['class'] = $element; + + if ($this->options[XML_UNSERIALIZER_OPTION_GUESS_TYPES] === true) { + $attribs = $this->_guessAndSetTypes($attribs); + } + if ($this->options[XML_UNSERIALIZER_OPTION_ATTRIBUTES_ARRAYKEY] != false) { + $val['children'][$this->options[XML_UNSERIALIZER_OPTION_ATTRIBUTES_ARRAYKEY]] = $attribs; + } else { + foreach ($attribs as $attrib => $value) { + $val['children'][$this->options[XML_UNSERIALIZER_OPTION_ATTRIBUTES_PREPEND].$attrib] = $value; + } + } + } + + $keyAttr = false; + + if (is_string($this->options[XML_UNSERIALIZER_OPTION_ATTRIBUTE_KEY])) { + $keyAttr = $this->options[XML_UNSERIALIZER_OPTION_ATTRIBUTE_KEY]; + } elseif (is_array($this->options[XML_UNSERIALIZER_OPTION_ATTRIBUTE_KEY])) { + if (isset($this->options[XML_UNSERIALIZER_OPTION_ATTRIBUTE_KEY][$element])) { + $keyAttr = $this->options[XML_UNSERIALIZER_OPTION_ATTRIBUTE_KEY][$element]; + } elseif (isset($this->options[XML_UNSERIALIZER_OPTION_ATTRIBUTE_KEY]['#default'])) { + $keyAttr = $this->options[XML_UNSERIALIZER_OPTION_ATTRIBUTE_KEY]['#default']; + } elseif (isset($this->options[XML_UNSERIALIZER_OPTION_ATTRIBUTE_KEY]['__default'])) { + // keep this for BC + $keyAttr = $this->options[XML_UNSERIALIZER_OPTION_ATTRIBUTE_KEY]['__default']; + } + } + + if ($keyAttr !== false && isset($attribs[$keyAttr])) { + $val['name'] = $attribs[$keyAttr]; + } + + if (isset($attribs[$this->options[XML_UNSERIALIZER_OPTION_ATTRIBUTE_CLASS]])) { + $val['class'] = $attribs[$this->options[XML_UNSERIALIZER_OPTION_ATTRIBUTE_CLASS]]; + } + + array_push($this->_valStack, $val); + } + + /** + * Try to guess the type of several values and + * set them accordingly + * + * @access private + * @param array array, containing the values + * @return array array, containing the values with their correct types + */ + function _guessAndSetTypes($array) + { + foreach ($array as $key => $value) { + $array[$key] = $this->_guessAndSetType($value); + } + return $array; + } + + /** + * Try to guess the type of a value and + * set it accordingly + * + * @access private + * @param string character data + * @return mixed value with the best matching type + */ + function _guessAndSetType($value) + { + if ($value === 'true') { + return true; + } + if ($value === 'false') { + return false; + } + if ($value === 'NULL') { + return null; + } + if (preg_match('/^[-+]?[0-9]{1,}$/', $value)) { + return intval($value); + } + if (preg_match('/^[-+]?[0-9]{1,}\.[0-9]{1,}$/', $value)) { + return doubleval($value); + } + return (string)$value; + } + + /** + * End element handler for XML parser + * + * @access private + * @param object XML parser object + * @param string + * @return void + */ + function endHandler($parser, $element) + { + $value = array_pop($this->_valStack); + switch ($this->options[XML_UNSERIALIZER_OPTION_WHITESPACE]) { + case XML_UNSERIALIZER_WHITESPACE_KEEP: + $data = $this->_dataStack[$this->_depth]; + break; + case XML_UNSERIALIZER_WHITESPACE_NORMALIZE: + $data = trim(preg_replace('/\s\s+/m', ' ', $this->_dataStack[$this->_depth])); + break; + case XML_UNSERIALIZER_WHITESPACE_TRIM: + default: + $data = trim($this->_dataStack[$this->_depth]); + break; + } + + // adjust type of the value + switch(strtolower($value['type'])) { + + // unserialize an object + case 'object': + if (isset($value['class'])) { + $classname = $value['class']; + } else { + $classname = ''; + } + // instantiate the class + if ($this->options[XML_UNSERIALIZER_OPTION_TAG_AS_CLASSNAME] === true && class_exists($classname)) { + $value['value'] = &new $classname; + } else { + $value['value'] = &new $this->options[XML_UNSERIALIZER_OPTION_DEFAULT_CLASS]; + } + if (trim($data) !== '') { + if ($value['guessType'] === true) { + $data = $this->_guessAndSetType($data); + } + $value['children'][$this->options[XML_UNSERIALIZER_OPTION_CONTENT_KEY]] = $data; + } + + // set properties + foreach ($value['children'] as $prop => $propVal) { + // check whether there is a special method to set this property + $setMethod = 'set'.$prop; + if (method_exists($value['value'], $setMethod)) { + call_user_func(array(&$value['value'], $setMethod), $propVal); + } else { + $value['value']->$prop = $propVal; + } + } + // check for magic function + if (method_exists($value['value'], '__wakeup')) { + $value['value']->__wakeup(); + } + break; + + // unserialize an array + case 'array': + if (trim($data) !== '') { + if ($value['guessType'] === true) { + $data = $this->_guessAndSetType($data); + } + $value['children'][$this->options[XML_UNSERIALIZER_OPTION_CONTENT_KEY]] = $data; + } + if (isset($value['children'])) { + $value['value'] = $value['children']; + } else { + $value['value'] = array(); + } + break; + + // unserialize a null value + case 'null': + $data = null; + break; + + // unserialize a resource => this is not possible :-( + case 'resource': + $value['value'] = $data; + break; + + // unserialize any scalar value + default: + if ($value['guessType'] === true) { + $data = $this->_guessAndSetType($data); + } else { + settype($data, $value['type']); + } + + $value['value'] = $data; + break; + } + $parent = array_pop($this->_valStack); + if ($parent === null) { + $this->_unserializedData = &$value['value']; + $this->_root = &$value['name']; + return true; + } else { + // parent has to be an array + if (!isset($parent['children']) || !is_array($parent['children'])) { + $parent['children'] = array(); + if (!in_array($parent['type'], array('array', 'object'))) { + $parent['type'] = $this->_getComplexType($parent['name']); + if ($parent['type'] == 'object') { + $parent['class'] = $parent['name']; + } + } + } + + if (in_array($element, $this->options[XML_UNSERIALIZER_OPTION_IGNORE_KEYS])) { + $ignoreKey = true; + } else { + $ignoreKey = false; + } + + if (!empty($value['name']) && $ignoreKey === false) { + // there already has been a tag with this name + if (in_array($value['name'], $parent['childrenKeys']) || in_array($value['name'], $this->options[XML_UNSERIALIZER_OPTION_FORCE_ENUM])) { + // no aggregate has been created for this tag + if (!in_array($value['name'], $parent['aggregKeys'])) { + if (isset($parent['children'][$value['name']])) { + $parent['children'][$value['name']] = array($parent['children'][$value['name']]); + } else { + $parent['children'][$value['name']] = array(); + } + array_push($parent['aggregKeys'], $value['name']); + } + array_push($parent['children'][$value['name']], $value['value']); + } else { + $parent['children'][$value['name']] = &$value['value']; + array_push($parent['childrenKeys'], $value['name']); + } + } else { + array_push($parent['children'], $value['value']); + } + array_push($this->_valStack, $parent); + } + + $this->_depth--; + } + + /** + * Handler for character data + * + * @access private + * @param object XML parser object + * @param string CDATA + * @return void + */ + function cdataHandler($parser, $cdata) + { + if ($this->options[XML_UNSERIALIZER_OPTION_DECODE_FUNC] !== null) { + $cdata = call_user_func($this->options[XML_UNSERIALIZER_OPTION_DECODE_FUNC], $cdata); + } + $this->_dataStack[$this->_depth] .= $cdata; + } + + /** + * get the complex type, that should be used for a specified tag + * + * @access private + * @param string name of the tag + * @return string complex type ('array' or 'object') + */ + function _getComplexType($tagname) + { + if (is_string($this->options[XML_UNSERIALIZER_OPTION_COMPLEXTYPE])) { + return $this->options[XML_UNSERIALIZER_OPTION_COMPLEXTYPE]; + } + if (isset($this->options[XML_UNSERIALIZER_OPTION_COMPLEXTYPE][$tagname])) { + return $this->options[XML_UNSERIALIZER_OPTION_COMPLEXTYPE][$tagname]; + } + if (isset($this->options[XML_UNSERIALIZER_OPTION_COMPLEXTYPE]['#default'])) { + return $this->options[XML_UNSERIALIZER_OPTION_COMPLEXTYPE]['#default']; + } + return 'array'; + } + + /** + * create the XML_Parser instance + * + * @access private + * @return boolean + */ + function _createParser() + { + if (is_object($this->_parser)) { + $this->_parser->free(); + unset($this->_parser); + } + $this->_parser = &new XML_Parser($this->options[XML_UNSERIALIZER_OPTION_ENCODING_SOURCE], 'event', $this->options[XML_UNSERIALIZER_OPTION_ENCODING_TARGET]); + $this->_parser->folding = false; + $this->_parser->setHandlerObj($this); + return true; + } +} +?> Index: /modules/branches/2.6/core/page.devices.php =================================================================== --- /modules/branches/2.6/core/page.devices.php (revision 6768) +++ /modules/branches/2.6/core/page.devices.php (revision 6768) @@ -0,0 +1,21 @@ + +
+checkSection('999') ? _("Device") : false; +drawListMenu($devices, $skip, $type, $display, $extdisplay, $description); +?> +
Index: /modules/branches/2.6/core/module.xml =================================================================== --- /modules/branches/2.6/core/module.xml (revision 7068) +++ /modules/branches/2.6/core/module.xml (revision 7068) @@ -0,0 +1,61 @@ + + core + setup + Basic + Core + 2.5.1.0 + no + no + + *2.5.1.0* #3304, #3276, #3299 + *2.5.0.4* #3299 + *2.5.0.3* #3266, #3267, #3281, #3042 (vm-callme context), localiztion fixes + *2.5.0.2* #3219, #3241, #3240, #3251, #3215, localization fixes + *2.5.0.1* minor bug not showing extensions + *2.5.0.0* #3211, and final release + *2.5.0rc3.3* #3193, #3200, localization fixes, Swedish + *2.5.0rc3.2* #3124, #3180 + *2.5.0rc3.1* #3173, #3077 auto-blkvm, auto-confirm to auto generation, visual feedback to DAHDI compatibility + *2.5.0rc3.0* #3150, #3152, #3142, #3167, #3077 (DAHDI Support) + *2.5.0rc2.5* #3129, #3144, #3146 and some streamling of dialout-trunk and outbound-callerid + *2.5.0rc2.4* #3128, #3140 sqlite3 fix and fixed typo introduced in dialparties.agi + *2.5.0rc2.3* #3130, #2750, #3128, #3131 (requires r6519) added master recording disable (can be performance booster) + *2.5.0rc2.2* lots of changed to be updated + *2.5.0rc2.1* #3115, #3116 remove warning and add t option to nv_faxdetect + *2.5.0rc2.0* #3091, #3099, #3100 Added return from voicemail/busy to IVR support, added CID Priority Route Inbound Route option + *2.5.0rc1.1* #3060, #3072, #3078 mixmonitor recording dir typo, move disallow=all to top of all sip, iax sections, file call screening nomemory + *2.5.0rc1.0* #3053 allow routing in CIDs like Private, Blocked, Restricted, etc. and bump to rc1 + *2.5.0beta1.4* #3046, #3019, #3047, #3040 + *2.5.0beta1.3* #2530 typo _GLOBALS should be GLOBALS, clean up conflicts when creating users/extensions + *2.5.0beta1.2* #2913 Add pre-answer delay option to incoming routes, rearrange the order of options on incoming screen + *2.5.0beta1.1* #2991, #2999, #2993, #3020, #3002, #3041, #2996, #3029, #3031 + *2.5.0beta1.0* #2976, #2778, #2413, #2974, #2962, #2894, #2073 + *2.5.0alpha1.1* #2930, #2938, #2922, #2939, #1568, #2949, #2779, #2953, #1911, #2807 + *2.5.0alpha1.0* #2853, #2925, #2391, #2785, #2923, #2671, #2585, #2908, #2909, #2510, #2976, #2845, #1715, #2760, #2926, #2927, #2838, also added misc icons, links between users/devices + *2.4.0.4* #2857, #2848, #2791, #2449 + *2.4.0.3* #2851 forwarded/followme/ringgroup calls originating from outside fail + *2.4.0.2* #2702, #2759, #2763, #2801, #2747, #2828, #2604, #2841, #2835 - review svn log or tickets for details + *2.4.0.1* #2693 fix DID editing creating new DID route introduced from #2664 fix + *2.4.0.0* CHANGELOG TRUNCATED See SVN Repository + + + 2.5.0rc3 + + + /usr/sbin/asterisk + + + Extensions + Users + Devices + Inbound Routes + Zap Channel DIDs + Outbound Routes + Trunks + General Settings + Administrators + FreePBX Support + + release/2.5/core-2.5.1.0.tgz + 7b2d584403f6ee1fa96f1518b021ac6e + Index: /modules/branches/2.6/core/page.trunks.php =================================================================== --- /modules/branches/2.6/core/page.trunks.php (revision 6717) +++ /modules/branches/2.6/core/page.trunks.php (revision 6717) @@ -0,0 +1,858 @@ +unserialize($str); + $xmldata = $xml->getUnserializedData(); + + if (isset($xmldata['lca-data']['prefix'])) { + + if ($action == 'populatenpanxx10') { + // 10 digit dialing + // - add area code to 7 digits + // - match local 10 digits + // - add 1 to anything else + $dialrules[] = $matches[1].'NXXXXXX'; + // add NPA to 7-digits + foreach ($xmldata['lca-data']['prefix'] as $prefix) { + $dialrules[] = $prefix['npa'].'+'.$prefix['nxx'].'XXXX'; + } + foreach ($xmldata['lca-data']['prefix'] as $prefix) { + $dialrules[] = $prefix['npa'].$prefix['nxx'].'XXXX'; + } + // if a number was not matched as local, dial it with '1' prefix + $dialrules[] = '1+NXXNXXXXXX'; + } else { + // 7 digit dialing + // - drop area code from local numbers + // - match local 7 digit numbers + // - add 1 to everything else + foreach ($xmldata['lca-data']['prefix'] as $prefix) { + $dialrules[] = $prefix['npa'].'|'.$prefix['nxx'].'XXXX'; + } + foreach ($xmldata['lca-data']['prefix'] as $prefix) { + $dialrules[] = $prefix['nxx'].'XXXX'; + } + $dialrules[] = '1+NXXNXXXXXX'; + $dialrules[] = '1'.$matches[1].'+NXXXXXX'; + } + + // check for duplicates, and re-sequence + $dialrules = array_values(array_unique($dialrules)); + } else { + $errormsg = _("Error fetching prefix list for: "). $_REQUEST["npanxx"]; + } + + } else { + // what a horrible error message... :p + $errormsg = _("Invalid format for NPA-NXX code (must be format: NXXNXX)"); + } + + if (isset($errormsg)) { + echo ""; + unset($errormsg); + } + break; +} + +//get all rows from globals +$sql = "SELECT * FROM globals"; +$globals = $db->getAll($sql); +if(DB::IsError($globals)) { + die_freepbx($globals->getMessage()); +} + +//create a set of variables that match the items in global[0] +foreach ($globals as $global) { + ${trim($global[0])} = htmlentities($global[1]); +} + +?> +
+ + + +
+ + +

+ $baseURL.'tech=ZAP', 'tlabel' => _("Add Zap Trunk").(ast_with_dahdi()?" ("._("DAHDI compatibility mode").")":"" )), + array('url'=> $baseURL.'tech=IAX2', 'tlabel' => _("Add IAX2 Trunk")), + array('url'=> $baseURL.'tech=SIP', 'tlabel' => _("Add SIP Trunk")), + array('url'=> $baseURL.'tech=ENUM', 'tlabel' => _("Add ENUM Trunk")), + array('url'=> $baseURL.'tech=DUNDI', 'tlabel' => _("Add DUNDi Trunk")), + array('url'=> $baseURL.'tech=CUSTOM', 'tlabel' => _("Add Custom Trunk")), + ); + foreach ($trunks as $trunk) { + $label = ' '.$trunk['tlabel'].''; + echo "".$label."

"; + } +} else { + if ($extdisplay) { + //list($trunk_tech, $trunk_name) = explode("/",$tname); + //if ($trunk_tech == "IAX2") $trunk_tech = "IAX"; // same thing + $tech = core_trunks_getTrunkTech($trunknum); + + $outcid = ${"OUTCID_".$trunknum}; + $maxchans = ${"OUTMAXCHANS_".$trunknum}; + $dialoutprefix = ${"OUTPREFIX_".$trunknum}; + $keepcid = isset(${"OUTKEEPCID_".$trunknum})?${"OUTKEEPCID_".$trunknum}:''; + $failtrunk = isset(${"OUTFAIL_".$trunknum})?${"OUTFAIL_".$trunknum}:''; + $failtrunk_enable = ($failtrunk == "")?'':'CHECKED'; + $disabletrunk = isset(${"OUTDISABLE_".$trunknum})?${"OUTDISABLE_".$trunknum}:''; + + + if ($tech!="enum") { + + if (!isset($channelid)) { + $channelid = core_trunks_getTrunkTrunkName($trunknum); + } + + if ($tech!="custom" && $tech!="dundi") { // custom trunks will not have user/peer details in database table + // load from db + if (!isset($peerdetails)) { + $peerdetails = core_trunks_getTrunkPeerDetails($trunknum); + } + + if (!isset($usercontext)) { + $usercontext = core_trunks_getTrunkUserContext($trunknum); + } + + if (!isset($userconfig)) { + $userconfig = core_trunks_getTrunkUserConfig($trunknum); + } + + if (!isset($register)) { + $register = core_trunks_getTrunkRegister($trunknum); + } + } + } + + if (count($dialrules) == 0) { + if ($temp = core_trunks_getDialRules($trunknum)) { + foreach ($temp as $key=>$val) { + // extract all ruleXX keys + if (preg_match("/^rule\d+$/",$key)) { + $dialrules[] = $val; + } + } + } + unset($temp); + } + + + $upper_tech = strtoupper($tech); + echo "

".sprintf(_("Edit %s Trunk"),$upper_tech).($upper_tech == 'ZAP' && ast_with_dahdi()?" ("._("DAHDI compatibility Mode").")":"")."

"; + $tlabel = sprintf(_("Delete Trunk %s"),substr($channelid,0,20)); + $label = ' '.$tlabel.''; +?> +

+ 0) { + echo " "._("In use by")." ".$num_routes." ".($num_routes == 1 ? _("route") : _("routes")).""; + foreach($routes as $route=>$priority) { + echo _("Route")." ".$route.": "._("Sequence")." ".$priority."
"; + } + echo "
"; + } else { + echo " "._("WARNING:")." "._("This trunk is not used by any routes!").""; + echo _("This trunk will not be able to be used for outbound calls until a route is setup that uses it. Click on Outbound Routes to setup routing."); + echo ""; + } + + } else { + // set defaults + $outcid = ""; + $maxchans = ""; + $dialoutprefix = ""; + + if ($tech == "zap") { + $channelid = "g0"; + } else { + $channelid = ""; + } + + // only for iax2/sip + $peerdetails = "host=***provider ip address***\nusername=***userid***\nsecret=***password***\ntype=peer"; + $usercontext = ""; + $userconfig = "secret=***password***\ntype=user\ncontext=from-trunk"; + $register = ""; + + $localpattern = "NXXXXXX"; + $lddialprefix = "1"; + $areacode = ""; + + $upper_tech = strtoupper($tech); + echo "

".sprintf("Add %s Trunk",$upper_tech).($upper_tech == 'ZAP' && ast_with_dahdi()?" ("._("DAHDI compatibility mode").")":"")."

"; + } +switch ($tech) { + case 'dundi': + $helptext = _('FreePBX offers limited support for DUNDi trunks and additional manual configuration is required. The trunk name should correspond to the [mappings] section of the remote dundi.conf systems. For example, you may have a mapping on the remote system, and corresponding configurations in dundi.conf locally, that looks as follows:

[mappings]
priv => dundi-extens,0,IAX2,priv:${SECRET}@218.23.42.26/${NUMBER},noparital

In this example, you would create this trunk and name it priv. You would then create the corresponding IAX2 trunk with proper settings to work with DUNDi. This can be done by making an IAX2 trunk in FreePBX or by using the iax_custom.conf file.
The dundi-extens context in this example must be created in extensions_custom.conf. This can simply include contexts such as ext-local, ext-intercom-users, ext-paging and so forth to provide access to the corresponding extensions and features provided by these various contexts and generated by FreePBX.'); + break; + default: + $helptext = ''; +} +if ($helptext != '') { + if ($extdisplay) { + echo "

"; + } + echo $helptext; +} + +?> + +
');"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +*/?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+
+

Format: \"caller name\" <#######>. You can also use the magic string 'hidden' to hide the CallerID sent out over Digital lines ONLY (E1/T1/J1/BRI/SIP/IAX)")?>

: +
+ +
+


: +
+ tabindex=""/> +
+ + : + + : + + + +
: + + OnClick='disable_verify(disabletrunk); return true;'> +
: + + type="text" size="20" name="failtrunk" value=""/> + OnClick='disable_field(failtrunk,failtrunk_enable); return true;'> +
+

+
+


+ X   
+ Z   
+ N   
+ [1237-9] 
+ .   
+ |    + +   

+ +
: +
+
+ + " tabindex=""/> +
+ +
+
+
+
: +
+
+ Dial rulesThe area code this trunk is in.: +   + + +
+ The dialing pattern to make a 'local' call."): + + + +
+ The prefix for dialing long-distance numbers. In north america, this should be \"1\".")?>: + + + +
+ The area code this trunk is in. Any 7-digit numbers that don't match a number in the below list will have dialprefix+areacode added to them. ")?>: + + + +
+ This should be a list of local areacodes + prefixes to use for local dialing.")?>: +   +
+ +
+ Do a lookup from http://members.dandy.net/~czg/search.html to find all local-reachable area codes and phone numbers.")?>: +

+
+
Most users should leave this option blank.")?>
: +
+ +
+

+
+

The default setting is g0 (group zero).")?>

: +
+ + +
+ $OUTNUM$
examples:
")?>CAPI/XXXXXXXX/$OUTNUM$
H323/$OUTNUM$@XX.XX.XX.XX
OH323/$OUTNUM$@XX.XX.XX.XX:XXXX
vpb/1-1/$OUTNUM$
: +
+ + +
+ : + + + +
+


: +
+ +
+

You may need to add to the default lines listed below, depending on your provider.

WARNING: Order is important as it will be retained. For example, if you use the \"allow/deny\" directives make sure deny comes first.")?>

: +
+ +
+

+
+

This USER Context will be used to define the below user details.")?>
: +
+ +
+



WARNING: Order is important as it will be retained. For example, if you use the \"allow/deny\" directives make sure deny + comes first.")?>

: +
+ +
+

+
+

example:

username:password@switch.voipprovider.com.

Many providers will require you to provide a DID number, ex: username:password@switch.voipprovider.com/didnumber in order for any DID matching to work.")?>

: +
+ +
+
" tabindex="">
+
+ + + +
+ + + Index: /modules/branches/2.6/core/page.routing.php =================================================================== --- /modules/branches/2.6/core/page.routing.php (revision 6845) +++ /modules/branches/2.6/core/page.routing.php (revision 6845) @@ -0,0 +1,677 @@ + Copyright (C) 2005 Ron Hartmann (rhartmann@vercomsystems.com) +// Asterisk Management Portal Copyright (C) 2004 Coalescent Systems Inc. (info@coalescentsystems.ca) +// +//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. + +$display='routing'; +$extdisplay=isset($_REQUEST['extdisplay'])?$_REQUEST['extdisplay']:''; +$action = isset($_REQUEST['action'])?$_REQUEST['action']:''; + +$repotrunkdirection = isset($_REQUEST['repotrunkdirection'])?$_REQUEST['repotrunkdirection']:''; +$repotrunkkey = isset($_REQUEST['repotrunkkey'])?$_REQUEST['repotrunkkey']:''; + + +$dialpattern = array(); +if (isset($_REQUEST["dialpattern"])) { + //$dialpattern = $_REQUEST["dialpattern"]; + $dialpattern = explode("\n",$_REQUEST["dialpattern"]); + + if (!$dialpattern) { + $dialpattern = array(); + } + + foreach (array_keys($dialpattern) as $key) { + //trim it + $dialpattern[$key] = trim($dialpattern[$key]); + + // remove blanks + if ($dialpattern[$key] == "") unset($dialpattern[$key]); + + // remove leading underscores (we do that on backend) + if ($dialpattern[$key][0] == "_") $dialpattern[$key] = substr($dialpattern[$key],1); + } + + // check for duplicates, and re-sequence + $dialpattern = array_values(array_unique($dialpattern)); +} + +if ( (isset($_REQUEST['reporoutedirection'])) && (isset($_REQUEST['reporoutekey']))) { + $routepriority = core_routing_getroutenames(); + $routepriority = core_routing_setroutepriority($routepriority, $_REQUEST['reporoutedirection'], $_REQUEST['reporoutekey']); +} + +$trunkpriority = array(); +if (isset($_REQUEST["trunkpriority"])) { + $trunkpriority = $_REQUEST["trunkpriority"]; + + if (!$trunkpriority) { + $trunkpriority = array(); + } + + // delete blank entries and reorder + foreach (array_keys($trunkpriority) as $key) { + if (empty($trunkpriority[$key])) { + // delete this empty + unset($trunkpriority[$key]); + + } else if (($key==($repotrunkkey-1)) && ($repotrunkdirection=="up")) { + // swap this one with the one before (move up) + $temptrunk = $trunkpriority[$key]; + $trunkpriority[ $key ] = $trunkpriority[ $key+1 ]; + $trunkpriority[ $key+1 ] = $temptrunk; + + } else if (($key==($repotrunkkey)) && ($repotrunkdirection=="down")) { + // swap this one with the one after (move down) + $temptrunk = $trunkpriority[ $key+1 ]; + $trunkpriority[ $key+1 ] = $trunkpriority[ $key ]; + $trunkpriority[ $key ] = $temptrunk; + } + } + unset($temptrunk); + $trunkpriority = array_values($trunkpriority); // resequence our numbers + $trunkpriority = array_unique($trunkpriority); // resequence our numbers +} + +$routename = isset($_REQUEST["routename"]) ? $_REQUEST["routename"] : ""; +$routepass = isset($_REQUEST["routepass"]) ? $_REQUEST["routepass"] : ""; +$emergency = isset($_REQUEST["emergency"]) ? $_REQUEST["emergency"] : ""; +$intracompany = isset($_REQUEST["intracompany"]) ? $_REQUEST["intracompany"] : ""; +$mohsilence = isset($_REQUEST["mohsilence"]) ? $_REQUEST["mohsilence"] : ""; + +//if submitting form, update database +switch ($action) { + case "addroute": + core_routing_add($routename, $dialpattern, $trunkpriority,"new", $routepass, $emergency, $intracompany, $mohsilence); + needreload(); + redirect_standard(); + break; + case "editroute": + core_routing_edit($routename, $dialpattern, $trunkpriority, $routepass, $emergency, $intracompany, $mohsilence); + needreload(); + redirect_standard('extdisplay'); + break; + case "delroute": + core_routing_del($extdisplay); + // re-order the routes to make sure that there are no skipped numbers. + // example if we have 001-test1, 002-test2, and 003-test3 then delete 002-test2 + // we do not want to have our routes as 001-test1, 003-test3 we need to reorder them + // so we are left with 001-test1, 002-test3 + $routepriority = core_routing_getroutenames(); + $routepriority = core_routing_setroutepriority($routepriority, '',''); + needreload(); + redirect_standard(); + break; + case 'renameroute': + if (core_routing_rename($routename, $_REQUEST["newroutename"])) { + needreload(); + } else { + echo ""; + } + $route_prefix=substr($routename,0,4); + $extdisplay=$route_prefix.$_REQUEST["newroutename"]; + + break; + case 'prioritizeroute': + needreload(); + break; + case 'populatenpanxx': + if (preg_match("/^([2-9]\d\d)-?([2-9]\d\d)$/", $_REQUEST["npanxx"], $matches)) { + // first thing we do is grab the exch: + $ch = curl_init(); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_URL, "http://www.localcallingguide.com/xmllocalprefix.php?npa=".$matches[1]."&nxx=".$matches[2]); + curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Linux; FreePBX Local Trunks Configuration)"); + $str = curl_exec($ch); + curl_close($ch); + + // quick 'n dirty - nabbed from PEAR + require_once($amp_conf['AMPWEBROOT'] . '/admin/modules/core/XML_Parser.php'); + require_once($amp_conf['AMPWEBROOT'] . '/admin/modules/core/XML_Unserializer.php'); + + $xml = new xml_unserializer; + $xml->unserialize($str); + $xmldata = $xml->getUnserializedData(); + + if (isset($xmldata['lca-data']['prefix'])) { + // we do the loops separately so patterns are grouped together + + // match 1+NPA+NXX (dropping 1) + foreach ($xmldata['lca-data']['prefix'] as $prefix) { + $dialpattern[] = '1|'.$prefix['npa'].$prefix['nxx'].'XXXX'; + } + // match NPA+NXX + foreach ($xmldata['lca-data']['prefix'] as $prefix) { + $dialpattern[] = $prefix['npa'].$prefix['nxx'].'XXXX'; + } + // match 7-digits + foreach ($xmldata['lca-data']['prefix'] as $prefix) { + $dialpattern[] = $prefix['nxx'].'XXXX'; + } + + // check for duplicates, and re-sequence + $dialpattern = array_values(array_unique($dialpattern)); + } else { + $errormsg = _("Error fetching prefix list for: "). $_REQUEST["npanxx"]; + } + + } else { + // what a horrible error message... :p + $errormsg = _("Invalid format for NPA-NXX code (must be format: NXXNXX)"); + } + + if (isset($errormsg)) { + echo ""; + unset($errormsg); + } + break; +} + + + +//get all rows from globals +$sql = "SELECT * FROM globals"; +$globals = $db->getAll($sql); +if(DB::IsError($globals)) { +die_freepbx($globals->getMessage()); +} + +//create a set of variables that match the items in global[0] +foreach ($globals as $global) { + ${trim($global[0])} = htmlentities($global[1]); +} + +?> +
+ + + +
+
    +
  • href="config.php?display=">
  • +\n\t\t$key " . substr($tresult[0],4)."\n"; + + if ($key > 0) + echo "\t\t" .  _("Move Up") .
+				"\n"; + else + echo "\t\t\n"; + + // move down + if ($key < ($positions-1)) + echo "\t\t','down')\" alt='" . _("Move Down") . + "' style='float:none; margin-left:0px; margin-bottom:0px;' width='9' height='11'>\n"; + else + echo "\t\t\n"; + echo "\t\n"; +} // foreach +?> +
+
+ +
+ +"._("Edit Route").""; +} else { + echo "

"._("Add Route")."

"; +} + +// build trunks associative array +foreach (core_trunks_list() as $temp) { + $trunks[$temp[0]] = $temp[1]; + $trunkstate[$temp[0]] = $temp[2]; +} + +if ($extdisplay) { // editing + $tlabel = sprintf(_("Delete Route %s"),substr($extdisplay,4)); + $label = ' '.$tlabel.''; +?> +

+ + +
');"> + + + + + + + + + + + + + + + + +hookHtml; +?> + + + + + + + + + + + + + + + + + +$pattern) { +?> + + + + + + + + + + + + + + + + + + + + + + + + + +$trunk) { +?> + + + + + 3) ? 3 : count($trunks))); + +for ($i=0; $i < $num_new_boxes; $i++) { +?> + + + + + + + + + + + + + + + +
+


: +
+ + + " style="font-size:10px;" /> + + + + +
:
A numerical password, or the path to an Authenticate password file can be used.

Leave this field blank to not prompt for password.
")?>
")?>: tabindex=""/>
")?>: tabindex=""/>
+ +
+


+ X   
+ Z   
+ N   
+ [1237-9] 
+ .   
+ |    +
+
+ + +
+ + +
  +
"> +
+ +
+ + " /> +
+ +
+
+
: + + +
+ +
+
For Dial Patterns that match long distance numbers, for example, you'd want to pick the cheapest routes for long distance (ie, VoIP trunks first) followed by more expensive routes (POTS lines).")?>
+
   + + + + + 0) {?> + <?php echo _(" style="float:none; margin-left:0px; margin-bottom:0px;" width="9" height="11"> + + + + <?php echo _(" style="float:none; margin-left:0px; margin-bottom:0px;" width="9" height="11"> + + + +
  + +
+ "> +
+
"> +
+
+ + + +
+ Index: /modules/branches/2.6/core/page.zapchandids.php =================================================================== --- /modules/branches/2.6/core/page.zapchandids.php (revision 5919) +++ /modules/branches/2.6/core/page.zapchandids.php (revision 5919) @@ -0,0 +1,157 @@ + +
+ +
+ +
+ +"._("Edit Zap Channel: ").$channel.""; +} else { + echo "

"._("Add Zap Channel")."

"; +} + +$helptext = _("Zap Channel DIDs allow you to assign a DID to specific Zap Channels. You can supply the same DID to multiple channels. This would be a common scenario if you have multiple POTS lines that are on a hunt group from your provider. You MUST assign the channel's context to from-zaptel for these settings to have effect. It will be a line that looks like:

context = from-zaptel

in your zapata.conf configuration effecting the specified channel(s). Once you have assigned DIDs you can use standard Inbound Routes with the specified DIDs to route your calls."); +echo "

".$helptext."

\n"; +?> +
+ + + + + + + + + + + + + + + + + + + + + + + + +

:
:
:

" tabindex=""> + '; } ?> +
+
+ + + Index: /modules/branches/2.6/core/install.php =================================================================== --- /modules/branches/2.6/core/install.php (revision 6889) +++ /modules/branches/2.6/core/install.php (revision 6889) @@ -0,0 +1,259 @@ +"; + } +} + +if (! function_exists("outn")) { + function outn($text) { + echo $text; + } +} + +function did_migrate($incoming){ + global $db; + + foreach ($incoming as $key => $val) { + ${$key} = $db->escapeSimple($val); + } + + // Check to make sure the did is not being used elsewhere + // + $sql = "SELECT * FROM incoming WHERE cidnum = '' AND extension = '$extension'"; + $existing = $db->getAll($sql, DB_FETCHMODE_ASSOC); + if(DB::IsError($existing)) { + outn(sprintf(_("ERROR: trying to check if %s already in use"),$extension)); + return false; + } + if (empty($existing)) { + $sql="INSERT INTO incoming (cidnum,extension,destination,faxexten,faxemail,answer,wait,privacyman,alertinfo, ringing, mohclass, description, grppre) values ('$cidnum','$extension','$destination','$faxexten','$faxemail','$answer','$wait','$privacyman','$alertinfo', '$ringing', '$mohclass', '$description', '$grppre')"; + sql($sql); + return true; + } else { + return false; + } +} + +$fcc = new featurecode('core', 'userlogon'); +$fcc->setDescription('User Logon'); +$fcc->setDefault('*11'); +$fcc->update(); +unset($fcc); + +$fcc = new featurecode('core', 'userlogoff'); +$fcc->setDescription('User Logoff'); +$fcc->setDefault('*12'); +$fcc->update(); +unset($fcc); + +$fcc = new featurecode('core', 'zapbarge'); +$fcc->setDescription('ZapBarge'); +$fcc->setDefault('888'); +$fcc->update(); +unset($fcc); + +$fcc = new featurecode('core', 'chanspy'); +$fcc->setDescription('ChanSpy'); +$fcc->setDefault('555'); +$fcc->update(); +unset($fcc); + +$fcc = new featurecode('core', 'simu_pstn'); +$fcc->setDescription('Simulate Incoming Call'); +$fcc->setDefault('7777'); +$fcc->update(); +unset($fcc); + +$fcc = new featurecode('core', 'simu_fax'); +$fcc->setDescription('Dial System FAX'); +$fcc->setDefault('666'); +$fcc->update(); +unset($fcc); + +$fcc = new featurecode('core', 'pickup'); +$fcc->setDescription('Directed Call Pickup'); +$fcc->setDefault('**'); +$fcc->update(); +unset($fcc); + +$fcc = new featurecode('core', 'pickupexten'); +$fcc->setDescription('Asterisk General Call Pickup'); +$fcc->setDefault('*8'); +$fcc->update(); +unset($fcc); + +$fcc = new featurecode('core', 'blindxfer'); +$fcc->setDescription('In-Call Asterisk Blind Transfer'); +$fcc->setDefault('##'); +$fcc->update(); +unset($fcc); + +$fcc = new featurecode('core', 'atxfer'); +$fcc->setDescription('In-Call Asterisk Attended Transfer'); +$fcc->setDefault('*2'); +$fcc->update(); +unset($fcc); + +$fcc = new featurecode('core', 'automon'); +$fcc->setDescription('In-Call Asterisk Toggle Call Recording'); +$fcc->setDefault('*1'); +$fcc->update(); +unset($fcc); + +$fcc = new featurecode('core', 'disconnect'); +$fcc->setDescription('In-Call Asterisk Disconnect Code'); +$fcc->setDefault('**'); +$fcc->update(); +unset($fcc); + + +// Version 2.5 Upgrade needs to migrate directdid user info to incoming table +// +outn(_("Checking if directdids need migrating..")); +$sql = "SELECT `directdid` FROM `users`"; +$check = $db->getRow($sql, DB_FETCHMODE_ASSOC); +if(!DB::IsError($check)) { + out(_("starting migration")); + $errors = 0; + $sql = "SELECT * FROM `users` WHERE `directdid` != '' AND `directdid` IS NOT NULL"; + $direct_dids_arr = $db->getAll($sql, DB_FETCHMODE_ASSOC); + if(!DB::IsError($direct_dids_arr)) { + foreach ($direct_dids_arr as $direct_dids) { + $did_vars['destination'] = 'from-did-direct,'.$direct_dids['extension'].',1'; + $did_vars['extension'] = $direct_dids['directdid']; + $did_vars['cidnum'] = ''; + $did_vars['faxexten'] = $direct_dids['faxexten']; + $did_vars['faxemail'] = $direct_dids['faxemail']; + $did_vars['answer'] = $direct_dids['answer']; + $did_vars['wait'] = $direct_dids['wait']; + $did_vars['privacyman'] = $direct_dids['privacyman']; + $did_vars['alertinfo'] = $direct_dids['didalert']; + $did_vars['ringing'] = ''; + $did_vars['mohclass'] = $direct_dids['mohclass']; + $did_vars['description'] = _("User: ").$direct_dids['extension']; + $did_vars['grppre'] = ''; + if (!did_migrate($did_vars)) { + out(sprintf(_("ERROR: failed to insert %s for user %s"),$direct_dids['directdid'],$direct_dids['extension'])); + $errors++; + } + } + if ($errors) { + out(sprintf(_("There were %s failures migrating directdids, users table not being changed"),$errors)); + } else { + $migrate_array = array('directdid', 'didalert', 'mohclass', 'faxexten', 'faxemail', 'answer', 'wait', 'privacyman'); + foreach ($migrate_array as $field) { + outn(sprintf(_("Removing field %s from users table.."),$field)); + $sql = "ALTER TABLE `users` DROP `".$field."`"; + $results = $db->query($sql); + if (DB::IsError($results)) { + out(_("not present")); + } else { + out(_("removed")); + } + } + } + } else { + out(_("ERROR: could not access user table to migrate directdids to incoming table, aborting")); + } +} else { + out(_("already done")); +} + +// Add callgroup, pickupgroup to zap + +outn(_("updating zap callgroup, pickupgroup..")); +$sql = "SELECT `id` FROM `devices` WHERE `tech` = 'zap'"; +$results = $db->getCol($sql); +if(DB::IsError($results)) { + $results = null; +} +$count_pickup = 0; +$count_callgroup = 0; +if (isset($results) && !empty($results)) { + foreach ($results as $device) { + // if the insert fails then it is already there since it will violate the primary key but that is ok + // + $sql = "INSERT INTO `zap` (`id`, `keyword`, `data`, `flags`) VALUES ('$device', 'callgroup', '', '0')"; + $try = $db->query($sql); + if(!DB::IsError($try)) { + $count_pickup++; + } + $sql = "INSERT INTO `zap` (`id`, `keyword`, `data`, `flags`) VALUES ('$device', 'pickupgroup', '', '0')"; + $try = $db->query($sql); + if(!DB::IsError($try)) { + $count_callgroup++; + } + } +} +if ($count_callgroup || $count_pickup) { + out(sprintf(_("updated %s callgroups, %s pickupgroups"),$count_callgroup,$count_pickup)); +} else { + out(_("not needed")); +} + +// 2.5 new field +// +outn(_("checking for delay_answer field ..")); +$sql = "SELECT `delay_answer` FROM `incoming`"; +$check = $db->getRow($sql, DB_FETCHMODE_ASSOC); +if(DB::IsError($check)) { + $sql = "ALTER TABLE `incoming` ADD `delay_answer` INT(2) DEFAULT NULL"; + $result = $db->query($sql); + if(DB::IsError($result)) { + out(_("fatal error")); + die_freepbx($result->getDebugInfo()); + } else { + out(_("added")); + } +} else { + out(_("already exists")); +} + +outn(_("checking for pricid field ..")); +$sql = "SELECT `pricid` FROM `incoming`"; +$check = $db->getRow($sql, DB_FETCHMODE_ASSOC); +if(DB::IsError($check)) { + $sql = "ALTER TABLE `incoming` ADD `pricid` VARCHAR(20) DEFAULT NULL"; + $result = $db->query($sql); + if(DB::IsError($result)) { + out(_("fatal error")); + die_freepbx($result->getDebugInfo()); + } else { + out(_("added")); + } +} else { + out(_("already exists")); +} + +// Add variable RECORDING_STATE use to globally disable recording +// TODO: move this to the upgrade script so it only has to be done +// once in a major upgrade when we move to next major release +// +outn("Checking for Global var RECORDING_STATE.."); +$nrows = $db->getOne("SELECT count(*) from globals where variable='RECORDING_STATE'"); +if (!$nrows) { + $db->query("insert into globals values ('RECORDING_STATE', 'ENABLED')"); + out(_("Created")); +} else { + out(_("Already exists!")); +} + +?> Index: /modules/branches/2.6/core/page.ampusers.php =================================================================== --- /modules/branches/2.6/core/page.ampusers.php (revision 6904) +++ /modules/branches/2.6/core/page.ampusers.php (revision 6904) @@ -0,0 +1,281 @@ + $module) { + //create an array of module sections to display + if (isset($module['items']) && is_array($module['items'])) { + foreach($module['items'] as $itemKey => $item) { + $listKey = (!empty($item['display']) ? $item['display'] : $itemKey); + $item['rawname'] = $module['rawname']; + $module_list[ $listKey ] = $item; + } + } + } +} + +// extensions vs device/users ... module_list setting +if (isset($amp_conf["AMPEXTENSIONS"]) && ($amp_conf["AMPEXTENSIONS"] == "deviceanduser")) { + unset($module_list["extensions"]); +} else { + unset($module_list["devices"]); + unset($module_list["users"]); +} + +// no more adding the APPLY Changes bar to module list because array_multisort messes up integer array keys +// $module_list['99'] = array('category' => NULL, 'name' => _("Apply Changes Bar")); + +// changed from $module_name to $admin_module_name because the former is used by framework +foreach ($module_list as $key => $row) { + $module_category[$key] = $row['category']; + $admin_module_name[$key] = $row['name']; +} +array_multisort($module_category, SORT_ASC, $admin_module_name, SORT_ASC, $module_list); + +$sections = array(); +if (isset($_REQUEST["sections"])) { + if (is_array($_REQUEST["sections"])) { + $sections = $_REQUEST["sections"]; + } else { + //TODO do we even need this?? + $sections = explode(";",$_REQUEST["sections"]); + } +} + +//if submitting form, update database +switch ($action) { + case "addampuser": + core_ampusers_add($username, $password, $extension_low, $extension_high, $deptname, $sections); + //indicate 'need reload' link in footer.php + needreload(); + redirect_standard(); + break; + case "editampuser": + core_ampusers_del($userdisplay); + core_ampusers_add($username, $password, $extension_low, $extension_high, $deptname, $sections); + //indicate 'need reload' link in footer.php + needreload(); + redirect_standard('userdisplay'); + break; + case "delampuser": + core_ampusers_del($userdisplay); + //indicate 'need reload' link in footer.php + needreload(); + $userdisplay = ""; // go "add" screen + redirect_standard(); + break; +} + +?> +
+ + + +
+ +"._("Edit Administrator").""; + + $user = getAmpUser($userdisplay); + + $username = $user["username"]; + $password = $user["password"]; + $extension_high = $user["extension_high"]; + $extension_low = $user["extension_low"]; + $deptname = $user["deptname"]; + $sections = $user["sections"]; + + $tlabel = sprintf(_("Delete User: %s"),$userdisplay); + $label = ' '.$tlabel.''; +?> +

+"._("Add Administrator").""; + } +?> + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+
+ '._("NOTE:").''._("AUTHTYPE is not set to 'database' in /etc/amportal.conf - note that this module is not currently providing access control, and changing passwords here or adding users will have no effect unless AUTHTYPE is set to 'database'.") ?>

+
+ Create a unique username for this new user")?>: + + +
+ Create a password for this new user")?>: + + +
+
+

+
+ Restrict this user's view of Digital Receptionist menus and System Recordings to only those for this department.")?>: + + +
+ Restrict this user's view to only Extensions, Ring Groups, and Queues within this range.")?>: + + +  to + +
+ Select the Admin Sections this user should have access to.")?>: + + +
+
" onclick="checkAmpUser(ampuserEdit, '')" tabindex="">
+
+
+ + + Index: /modules/branches/2.6/core/page.extensions.php =================================================================== --- /modules/branches/2.6/core/page.extensions.php (revision 6796) +++ /modules/branches/2.6/core/page.extensions.php (revision 6796) @@ -0,0 +1,22 @@ + + +
+checkSection('999') ? _("Extension") : false; +drawListMenu($extens, $skip, $type, $display, $extdisplay, $description); +?> +
+
Index: /modules/branches/2.6/core/page.did.php =================================================================== --- /modules/branches/2.6/core/page.did.php (revision 7046) +++ /modules/branches/2.6/core/page.did.php (revision 7046) @@ -0,0 +1,372 @@ + +
+ + +
+
    +
  • href="config.php?display=">
  • +
  • href="config.php?display=">
  • +
  • href="config.php?display=">
  • +
  • href="config.php?display=">
  • +
  • href="config.php?display=">

  • + $did_items) { + $did_dest = split(',',$did_items['destination']); + if (!isset($did_dest[0]) || $did_dest[0] != 'from-did-direct') { + unset($inroutes[$key]); + } + } + break; + case 'incoming': + foreach ($inroutes as $key => $did_items) { + $did_dest = split(',',$did_items['destination']); + if (!isset($did_dest[0]) || $did_dest[0] == 'from-did-direct') { + unset($inroutes[$key]); + } + } + break; + case 'unassigned': + foreach ($inroutes as $key => $did_items) { + if (isset($did_items['destination']) && $did_items['destination'] != '') { + unset($inroutes[$key]); + } + } + break; + default: +} +if (isset($inroutes)) { + foreach ($inroutes as $inroute) { + $displaydid = ( empty($inroute['extension'])? _("any DID") : $inroute['extension'] ); + $displaycid = ( empty($inroute['cidnum'])? _("any CID") : $inroute['cidnum'] ); + $desc = ( empty($inroute['description'])? "" : $inroute['description']."
    " ); + echo "\t
  • {$desc} {$displaydid} / {$displaycid}
  • \n"; + } +} +?> +
+
+ +
+

Route '.$extdisplay.' '._("deleted").'!









'; + } else { +?> + +

:

+ '.$tlabel.''; + echo "

".$label."

"; + // If this is a direct did, e.g. from-did-direct,nnn,1 then make a link to the extension + // + $did_dest = split(',',$destination); + if (isset($did_dest[0]) && $did_dest[0] == 'from-did-direct') { + + if (isset($amp_conf["AMPEXTENSIONS"]) && ($amp_conf["AMPEXTENSIONS"] == "deviceanduser")) { + $editURL = $_SERVER['PHP_SELF'].'?display=users&extdisplay='.$did_dest[1]; + $EXTorUSER = _("User"); + } + else { + $editURL = $_SERVER['PHP_SELF'].'?display=extensions&extdisplay='.$did_dest[1]; + $EXTorUSER = _("Extension"); + } + $result = core_users_get($did_dest[1]); + $label = ' '.sprintf(_("Edit %s %s (%s)"),$EXTorUSER, $did_dest[1],$result['name']).''; + echo "

".$label."

"; + } +?> + +

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +hookHtml; +?> + + + + + + +

:

Leave this blank to match calls with any or no DID info.

You can also use a pattern match (eg _2[345]X) to match a range of numbers')?>
:

Leave this field blank to match any or no CID info. In addition to standard dial sequences, you can also put Private, Blocked, Unknown, Restricted, Anonymous and Unavailable in order to catch these special cases if the Telco transmits them.')?>
:
: tabindex=""/>

:
:
: + +
: tabindex=""/>
:

: + +

+
The FreePBX default is defined in General Settings.")?>
: +
+ +
+
Leave this blank to use the FreePBX default in General Settings.")?>
: +
+ +
: + +
:

+
" tabindex="">   + " >
+
+ +
+ Index: /modules/branches/2.6/core/page.users.php =================================================================== --- /modules/branches/2.6/core/page.users.php (revision 2617) +++ /modules/branches/2.6/core/page.users.php (revision 2617) @@ -0,0 +1,48 @@ + + +
+ +
+ + + + Index: /modules/branches/2.6/core/XML_Parser.php =================================================================== --- /modules/branches/2.6/core/XML_Parser.php (revision 2070) +++ /modules/branches/2.6/core/XML_Parser.php (revision 2070) @@ -0,0 +1,685 @@ + | +// | Tomas V.V.Cox | +// | Stephan Schmidt | +// +----------------------------------------------------------------------+ +// +// $Id: Parser.php,v 1.26 2005/09/23 11:51:10 schst Exp $ + +/** + * XML Parser class. + * + * This is an XML parser based on PHP's "xml" extension, + * based on the bundled expat library. + * + * @category XML + * @package XML_Parser + * @author Stig Bakken + * @author Tomas V.V.Cox + * @author Stephan Schmidt + */ + +/** + * uses PEAR's error handling + */ +//require_once 'PEAR.php'; + +/** + * resource could not be created + */ +define('XML_PARSER_ERROR_NO_RESOURCE', 200); + +/** + * unsupported mode + */ +define('XML_PARSER_ERROR_UNSUPPORTED_MODE', 201); + +/** + * invalid encoding was given + */ +define('XML_PARSER_ERROR_INVALID_ENCODING', 202); + +/** + * specified file could not be read + */ +define('XML_PARSER_ERROR_FILE_NOT_READABLE', 203); + +/** + * invalid input + */ +define('XML_PARSER_ERROR_INVALID_INPUT', 204); + +/** + * remote file cannot be retrieved in safe mode + */ +define('XML_PARSER_ERROR_REMOTE', 205); + +/** + * XML Parser class. + * + * This is an XML parser based on PHP's "xml" extension, + * based on the bundled expat library. + * + * Notes: + * - It requires PHP 4.0.4pl1 or greater + * - From revision 1.17, the function names used by the 'func' mode + * are in the format "xmltag_$elem", for example: use "xmltag_name" + * to handle the tags of your xml file. + * + * @category XML + * @package XML_Parser + * @author Stig Bakken + * @author Tomas V.V.Cox + * @author Stephan Schmidt + * @todo create XML_Parser_Namespace to parse documents with namespaces + * @todo create XML_Parser_Pull + * @todo Tests that need to be made: + * - mixing character encodings + * - a test using all expat handlers + * - options (folding, output charset) + * - different parsing modes + */ +class XML_Parser extends PEAR +{ + // {{{ properties + + /** + * XML parser handle + * + * @var resource + * @see xml_parser_create() + */ + var $parser; + + /** + * File handle if parsing from a file + * + * @var resource + */ + var $fp; + + /** + * Whether to do case folding + * + * If set to true, all tag and attribute names will + * be converted to UPPER CASE. + * + * @var boolean + */ + var $folding = true; + + /** + * Mode of operation, one of "event" or "func" + * + * @var string + */ + var $mode; + + /** + * Mapping from expat handler function to class method. + * + * @var array + */ + var $handler = array( + 'character_data_handler' => 'cdataHandler', + 'default_handler' => 'defaultHandler', + 'processing_instruction_handler' => 'piHandler', + 'unparsed_entity_decl_handler' => 'unparsedHandler', + 'notation_decl_handler' => 'notationHandler', + 'external_entity_ref_handler' => 'entityrefHandler' + ); + + /** + * source encoding + * + * @var string + */ + var $srcenc; + + /** + * target encoding + * + * @var string + */ + var $tgtenc; + + /** + * handler object + * + * @var object + */ + var $_handlerObj; + + // }}} + // {{{ constructor + + /** + * Creates an XML parser. + * + * This is needed for PHP4 compatibility, it will + * call the constructor, when a new instance is created. + * + * @param string $srcenc source charset encoding, use NULL (default) to use + * whatever the document specifies + * @param string $mode how this parser object should work, "event" for + * startelement/endelement-type events, "func" + * to have it call functions named after elements + * @param string $tgenc a valid target encoding + */ + function XML_Parser($srcenc = null, $mode = 'event', $tgtenc = null) + { + XML_Parser::__construct($srcenc, $mode, $tgtenc); + } + // }}} + + /** + * PHP5 constructor + * + * @param string $srcenc source charset encoding, use NULL (default) to use + * whatever the document specifies + * @param string $mode how this parser object should work, "event" for + * startelement/endelement-type events, "func" + * to have it call functions named after elements + * @param string $tgenc a valid target encoding + */ + function __construct($srcenc = null, $mode = 'event', $tgtenc = null) + { + $this->PEAR('XML_Parser_Error'); + + $this->mode = $mode; + $this->srcenc = $srcenc; + $this->tgtenc = $tgtenc; + } + // }}} + + /** + * Sets the mode of the parser. + * + * Possible modes are: + * - func + * - event + * + * You can set the mode using the second parameter + * in the constructor. + * + * This method is only needed, when switching to a new + * mode at a later point. + * + * @access public + * @param string mode, either 'func' or 'event' + * @return boolean|object true on success, PEAR_Error otherwise + */ + function setMode($mode) + { + if ($mode != 'func' && $mode != 'event') { + $this->raiseError('Unsupported mode given', XML_PARSER_ERROR_UNSUPPORTED_MODE); + } + + $this->mode = $mode; + return true; + } + + /** + * Sets the object, that will handle the XML events + * + * This allows you to create a handler object independent of the + * parser object that you are using and easily switch the underlying + * parser. + * + * If no object will be set, XML_Parser assumes that you + * extend this class and handle the events in $this. + * + * @access public + * @param object object to handle the events + * @return boolean will always return true + * @since v1.2.0beta3 + */ + function setHandlerObj(&$obj) + { + $this->_handlerObj = &$obj; + return true; + } + + /** + * Init the element handlers + * + * @access private + */ + function _initHandlers() + { + if (!is_resource($this->parser)) { + return false; + } + + if (!is_object($this->_handlerObj)) { + $this->_handlerObj = &$this; + } + switch ($this->mode) { + + case 'func': + xml_set_object($this->parser, $this->_handlerObj); + xml_set_element_handler($this->parser, array(&$this, 'funcStartHandler'), array(&$this, 'funcEndHandler')); + break; + + case 'event': + xml_set_object($this->parser, $this->_handlerObj); + xml_set_element_handler($this->parser, 'startHandler', 'endHandler'); + break; + default: + return $this->raiseError('Unsupported mode given', XML_PARSER_ERROR_UNSUPPORTED_MODE); + break; + } + + + /** + * set additional handlers for character data, entities, etc. + */ + foreach ($this->handler as $xml_func => $method) { + if (method_exists($this->_handlerObj, $method)) { + $xml_func = 'xml_set_' . $xml_func; + $xml_func($this->parser, $method); + } + } + } + + // {{{ _create() + + /** + * create the XML parser resource + * + * Has been moved from the constructor to avoid + * problems with object references. + * + * Furthermore it allows us returning an error + * if something fails. + * + * @access private + * @return boolean|object true on success, PEAR_Error otherwise + * + * @see xml_parser_create + */ + function _create() + { + if ($this->srcenc === null) { + $xp = @xml_parser_create(); + } else { + $xp = @xml_parser_create($this->srcenc); + } + if (is_resource($xp)) { + if ($this->tgtenc !== null) { + if (!@xml_parser_set_option($xp, XML_OPTION_TARGET_ENCODING, + $this->tgtenc)) { + return $this->raiseError('invalid target encoding', XML_PARSER_ERROR_INVALID_ENCODING); + } + } + $this->parser = $xp; + $result = $this->_initHandlers($this->mode); + if ($this->isError($result)) { + return $result; + } + xml_parser_set_option($xp, XML_OPTION_CASE_FOLDING, $this->folding); + + return true; + } + return $this->raiseError('Unable to create XML parser resource.', XML_PARSER_ERROR_NO_RESOURCE); + } + + // }}} + // {{{ reset() + + /** + * Reset the parser. + * + * This allows you to use one parser instance + * to parse multiple XML documents. + * + * @access public + * @return boolean|object true on success, PEAR_Error otherwise + */ + function reset() + { + $result = $this->_create(); + if ($this->isError( $result )) { + return $result; + } + return true; + } + + // }}} + // {{{ setInputFile() + + /** + * Sets the input xml file to be parsed + * + * @param string Filename (full path) + * @return resource fopen handle of the given file + * @throws XML_Parser_Error + * @see setInput(), setInputString(), parse() + * @access public + */ + function setInputFile($file) + { + /** + * check, if file is a remote file + */ + if (eregi('^(http|ftp)://', substr($file, 0, 10))) { + if (!ini_get('allow_url_fopen')) { + return $this->raiseError('Remote files cannot be parsed, as safe mode is enabled.', XML_PARSER_ERROR_REMOTE); + } + } + + $fp = @fopen($file, 'rb'); + if (is_resource($fp)) { + $this->fp = $fp; + return $fp; + } + return $this->raiseError('File could not be opened.', XML_PARSER_ERROR_FILE_NOT_READABLE); + } + + // }}} + // {{{ setInputString() + + /** + * XML_Parser::setInputString() + * + * Sets the xml input from a string + * + * @param string $data a string containing the XML document + * @return null + **/ + function setInputString($data) + { + $this->fp = $data; + return null; + } + + // }}} + // {{{ setInput() + + /** + * Sets the file handle to use with parse(). + * + * You should use setInputFile() or setInputString() if you + * pass a string + * + * @param mixed $fp Can be either a resource returned from fopen(), + * a URL, a local filename or a string. + * @access public + * @see parse() + * @uses setInputString(), setInputFile() + */ + function setInput($fp) + { + if (is_resource($fp)) { + $this->fp = $fp; + return true; + } + // see if it's an absolute URL (has a scheme at the beginning) + elseif (eregi('^[a-z]+://', substr($fp, 0, 10))) { + return $this->setInputFile($fp); + } + // see if it's a local file + elseif (file_exists($fp)) { + return $this->setInputFile($fp); + } + // it must be a string + else { + $this->fp = $fp; + return true; + } + + return $this->raiseError('Illegal input format', XML_PARSER_ERROR_INVALID_INPUT); + } + + // }}} + // {{{ parse() + + /** + * Central parsing function. + * + * @return true|object PEAR error returns true on success, or a PEAR_Error otherwise + * @access public + */ + function parse() + { + /** + * reset the parser + */ + $result = $this->reset(); + if ($this->isError($result)) { + return $result; + } + // if $this->fp was fopened previously + if (is_resource($this->fp)) { + + while ($data = fread($this->fp, 4096)) { + if (!$this->_parseString($data, feof($this->fp))) { + $error = &$this->raiseError(); + $this->free(); + return $error; + } + } + // otherwise, $this->fp must be a string + } else { + if (!$this->_parseString($this->fp, true)) { + $error = &$this->raiseError(); + $this->free(); + return $error; + } + } + $this->free(); + + return true; + } + + /** + * XML_Parser::_parseString() + * + * @param string $data + * @param boolean $eof + * @return bool + * @access private + * @see parseString() + **/ + function _parseString($data, $eof = false) + { + return xml_parse($this->parser, $data, $eof); + } + + // }}} + // {{{ parseString() + + /** + * XML_Parser::parseString() + * + * Parses a string. + * + * @param string $data XML data + * @param boolean $eof If set and TRUE, data is the last piece of data sent in this parser + * @throws XML_Parser_Error + * @return Pear Error|true true on success or a PEAR Error + * @see _parseString() + */ + function parseString($data, $eof = false) + { + if (!isset($this->parser) || !is_resource($this->parser)) { + $this->reset(); + } + + if (!$this->_parseString($data, $eof)) { + $error = &$this->raiseError(); + $this->free(); + return $error; + } + + if ($eof === true) { + $this->free(); + } + return true; + } + + /** + * XML_Parser::free() + * + * Free the internal resources associated with the parser + * + * @return null + **/ + function free() + { + if (isset($this->parser) && is_resource($this->parser)) { + xml_parser_free($this->parser); + unset( $this->parser ); + } + if (isset($this->fp) && is_resource($this->fp)) { + fclose($this->fp); + } + unset($this->fp); + return null; + } + + /** + * XML_Parser::raiseError() + * + * Throws a XML_Parser_Error + * + * @param string $msg the error message + * @param integer $ecode the error message code + * @return XML_Parser_Error + **/ + function raiseError($msg = null, $ecode = 0) + { + $msg = !is_null($msg) ? $msg : $this->parser; + $err = &new XML_Parser_Error($msg, $ecode); + return parent::raiseError($err); + } + + // }}} + // {{{ funcStartHandler() + + function funcStartHandler($xp, $elem, $attribs) + { + $func = 'xmltag_' . $elem; + if (strchr($func, '.')) { + $func = str_replace('.', '_', $func); + } + if (method_exists($this->_handlerObj, $func)) { + call_user_func(array(&$this->_handlerObj, $func), $xp, $elem, $attribs); + } elseif (method_exists($this->_handlerObj, 'xmltag')) { + call_user_func(array(&$this->_handlerObj, 'xmltag'), $xp, $elem, $attribs); + } + } + + // }}} + // {{{ funcEndHandler() + + function funcEndHandler($xp, $elem) + { + $func = 'xmltag_' . $elem . '_'; + if (strchr($func, '.')) { + $func = str_replace('.', '_', $func); + } + if (method_exists($this->_handlerObj, $func)) { + call_user_func(array(&$this->_handlerObj, $func), $xp, $elem); + } elseif (method_exists($this->_handlerObj, 'xmltag_')) { + call_user_func(array(&$this->_handlerObj, 'xmltag_'), $xp, $elem); + } + } + + // }}} + // {{{ startHandler() + + /** + * + * @abstract + */ + function startHandler($xp, $elem, &$attribs) + { + return NULL; + } + + // }}} + // {{{ endHandler() + + /** + * + * @abstract + */ + function endHandler($xp, $elem) + { + return NULL; + } + + + // }}}me +} + +/** + * error class, replaces PEAR_Error + * + * An instance of this class will be returned + * if an error occurs inside XML_Parser. + * + * There are three advantages over using the standard PEAR_Error: + * - All messages will be prefixed + * - check for XML_Parser error, using is_a( $error, 'XML_Parser_Error' ) + * - messages can be generated from the xml_parser resource + * + * @package XML_Parser + * @access public + * @see PEAR_Error + */ +class XML_Parser_Error extends PEAR_Error +{ + // {{{ properties + + /** + * prefix for all messages + * + * @var string + */ + var $error_message_prefix = 'XML_Parser: '; + + // }}} + // {{{ constructor() + /** + * construct a new error instance + * + * You may either pass a message or an xml_parser resource as first + * parameter. If a resource has been passed, the last error that + * happened will be retrieved and returned. + * + * @access public + * @param string|resource message or parser resource + * @param integer error code + * @param integer error handling + * @param integer error level + */ + function XML_Parser_Error($msgorparser = 'unknown error', $code = 0, $mode = PEAR_ERROR_RETURN, $level = E_USER_NOTICE) + { + if (is_resource($msgorparser)) { + $code = xml_get_error_code($msgorparser); + $msgorparser = sprintf('%s at XML input line %d:%d', + xml_error_string($code), + xml_get_current_line_number($msgorparser), + xml_get_current_column_number($msgorparser)); + } + $this->PEAR_Error($msgorparser, $code, $mode, $level); + } + // }}} +} +?> Index: /modules/branches/2.6/core/agi-bin/fixlocalprefix =================================================================== --- /modules/branches/2.6/core/agi-bin/fixlocalprefix (revision 6187) +++ /modules/branches/2.6/core/agi-bin/fixlocalprefix (revision 6187) @@ -0,0 +1,253 @@ +#!/usr/bin/php -q +get_variable( $value ); + + if ($r['result'] == 1) + { + $result = $r['data']; + return $result; + } + else + return ''; +} + +function parse_conf($filename, &$conf, &$section) { + if (is_null($conf)) { + $conf = array(); + } + if (is_null($section)) { + $section = "general"; + } + + if (file_exists($filename)) { + $fd = fopen($filename, "r"); + while ($line = fgets($fd, 1024)) { + if (preg_match("/^\s*([a-zA-Z0-9-_]+)\s*=\s*(.*?)\s*([;#].*)?$/",$line,$matches)) { + // name = value + // option line + $conf[$section][ $matches[1] ] = $matches[2]; + } else if (preg_match("/^\s*\[(.+)\]/",$line,$matches)) { + // section name + $section = strtolower($matches[1]); + } else if (preg_match("/^\s*#include\s+(.*)\s*([;#].*)?/",$line,$matches)) { + // include another file + + if ($matches[1][0] == "/") { + // absolute path + $filename = $matches[1]; + } else { + // relative path + $filename = dirname($filename)."/".$matches[1]; + } + + parse_conf($filename, $conf, $section); + } + } + } +} + +function sanitizeNumber($number) { + global $agi; + if (strpos($number,"-") !== false) { + $agi->verbose("Stripping hyphens"); + $number = str_replace("-","",$number); + } + return $number; +} + +function fixNumber($pattern, $number, &$agi) { + // valid chars in a pattern are 0-9XNZwW#*\.\[\]\-\+\| + $chars = '0-9XNZwW#*\.\[\]\-'; //escaped pcre-ready + + // convert x n and z to uppercase + $regex = str_replace(array('x','n','z'), array('X','N','Z'), $pattern); + // sanitize the pattern - remove any non-pattern chars + $regex = preg_replace("/[^0-9XNZwW#*\.\[\]\-\+\|]/", "", $regex); + // Also kill the '-' characters outside of groups + $regex = preg_replace("/((?:\[[^\]]*\])*)([^\[\]\-]*)-?/", "$1$2", $regex); + + $agi->verbose('Using pattern '.$regex, 4); + // attempt to grab the pieces of the pattern + if (preg_match('/^(([0-9XNZwW#*\.\[\]\-]+)\|)?(([0-9XNZwW#*\.\[\]\-]+)\+)?([0-9XNZwW#*\.\[\]\-]*)$/', $regex, $matches)) { + // one of NXXXXXX, 613|NXXXXXX 1+NXXXXXX 613|1+NXXXXXX, + // matches[2] = drop (eg 613), matches[4] = prefix (eg 1), matches[5] = rest of number (eg NXXXXX) + + $drop = $matches[2]; + $prefix = $matches[4]; + $static = $matches[5]; + } else if (preg_match('/^(([0-9XNZwW#*\.\[\]\-]+)\+)?(([0-9XNZwW#*\.\[\]\-]+)\|)?([0-9XNZwW#*\.\[\]\-]*)$/', $regex, $matches)) { + // one of NXXXXXX, 613|NXXXXXX 1+NXXXXXX 1+613|NXXXXXX + // matches[2] = prefix (eg 1), matches[4] = drop (eg 613), matches[5] = rest of number (eg NXXXXX) + + $drop = $matches[4]; + $prefix = $matches[2]; + $static = $matches[5]; + } else { + if (!is_null($agi)) { + $agi->verbose('Could not understand pattern "'.$pattern.'" ('.$regex.')', 1); + } + return false; + } + + // convert asterisk pattern matching into perl regular expression + $regex = str_replace( + array( + "X", + "Z", + "N", + ".", + "*", + ), + array( + "[0-9]", + "[1-9]", + "[2-9]", + "[0-9#*]+", + "\*", + ), + // note, we're doing a subpattern match on the static portion so it can be extracted later + $drop.'('.$static.')'); + + if (preg_match('/^'.$regex.'$/', $number, $matches)) { + return $prefix.$matches[1]; + } + return false; +} + +/**********************************************************************************************************************/ + +$agi = new AGI(); + +$localprefix_file = get_var($agi, "ASTETCDIR")."/localprefixes.conf"; + +if (file_exists($localprefix_file)) { + parse_conf($localprefix_file, $conf, $section); + if (count($conf) == 0) { +// $agi->verbose("Could not parse ".$localprefix_file); + exit(1); + } +} else { + $agi->verbose("Could not open ".$localprefix_file); + exit(1); +} + +$r = $agi->get_variable("DIAL_NUMBER"); +if ($r["result"] == 0) { + $agi->verbose("DIAL_NUMBER not set -- nothing to do"); + exit(1); +} +$number = $r["data"]; + +$number = sanitizeNumber($number); + +$r = $agi->get_variable("DIAL_TRUNK"); +if ($r["result"] == 0) { + $agi->verbose("DIAL_TRUNK not set -- nothing to do"); + exit(1); +} +$trunk = $r["data"]; + + +if (isset($conf["trunk-$trunk"])) { + foreach ($conf["trunk-$trunk"] as $key=>$rule) { + // extract all ruleXX keys + //$agi->conlog("$key = $rule"); + if (preg_match("/^rule\d+$/",$key)) { + // $rule is a dial rule + + if (($newnum = fixNumber($rule, $number, $agi)) !== false) { + $agi->verbose('Dialpattern '.$rule.' matched. '.$number.' -> '.$newnum, 2); + $agi->set_variable("DIAL_NUMBER", $newnum); + + // reverted back form r2080 (r2081 on trac) so that any pattern match will end + // the loop. This needs to stay like this for backwards compatibility and often + // patterns are used to avoid matching substitution rules for exception cases. + exit(0); + } // else, it didn't match this rule + } // else, this isn't a rule + } +} // else, no config for this section + +// we just exit with no changes to the variable. +exit(0); + +?> Index: /modules/branches/2.6/core/agi-bin/dialparties.agi =================================================================== --- /modules/branches/2.6/core/agi-bin/dialparties.agi (revision 6730) +++ /modules/branches/2.6/core/agi-bin/dialparties.agi (revision 6730) @@ -0,0 +1,778 @@ +#!/usr/bin/php -q + +// +// 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. +// +// Amended by Coalescent Systems Inc. Sept, 2004 +// to include support for DND, Call Waiting, and CF to external trunk +// info@coalescentsystems.ca +// +// This script has been ported to PHP by +// Diego Iastrubni and the FreePBX community + +/* --------WARNING--------- + * + * This script is auto-copied from an included module and will get overwritten. + * If you modify it, you must change it to write only, in the agi-bin directory, + * to keep it from getting changed. + */ + +require_once "phpagi.php"; +require_once "phpagi-asmanager.php"; + +$ext = array(); // Hash that will contain our list of extensions to call +$ext_hunt = array(); // Hash that will contain our list of extensions to call used by huntgroup +$cidnum = ""; // Caller ID Number for this call +$cidname = ""; // Caller ID Name for this call +$timer = ""; // Call timer for Dial command +$dialopts = ""; // options for dialing +$rc = ""; // Catch return code +$priority = ""; // Next priority +$rgmethod = ""; // If Ring Group what ringing method was chosen +$screen = false; // initialize screen variable +$dsarray = array(); // This will hold all the dial strings, used to check for duplicate extensions + +$AGI = new AGI(); +debug("Starting New Dialparties.agi", 1); + +// Get required channels variables that used to come from amportal.conf +$ampmgruser = get_var( $AGI, "AMPMGRUSER" ); +$ampmgrpass = get_var( $AGI, "AMPMGRPASS" ); +$cwinusebusy = get_var( $AGI, "CWINUSEBUSY" ); +$ast_version = get_var( $AGI, "ASTVERSION" ); +$chan_dahdi = get_var( $AGI, "ASTCHANDAHDI" ); + +$cwignore = get_var( $AGI, "CWIGNORE" ); +$cwignore = strtoupper(trim($cwignore)); + +// Clear it now so subsequent transfers don't honor it any longer +// +if ($cwignore) { + $AGI->set_variable('__CWIGNORE',""); +} +$cfignore = get_var( $AGI, "CFIGNORE" ); +$cfignore = strtoupper(trim($cfignore)); + +$astman = new AGI_AsteriskManager( ); +if (!$astman->connect("127.0.0.1", $ampmgruser , $ampmgrpass)) { + exit (1); +} + +$priority = get_var( $AGI, "priority" ) + 1; + +// Caller ID info is stored in $request in AGI class, passed from Asterisk +$cidnum = $AGI->request['agi_callerid']; +$cidname = $AGI->request['agi_calleridname']; +debug("Caller ID name is '$cidname' number is '$cidnum'", 1); + +$queue_wait = get_var( $AGI, "QUEUEWAIT" ); +if ($queue_wait != '') { + $saved_cidname = get_var( $AGI, "SAVEDCIDNAME" ); + $elapsed = round((time() - $queue_wait)/60,0); + if ($saved_cidname == '') { + $AGI->set_variable('__SAVEDCIDNAME',$cidname); + $AGI->set_variable('CALLERID(name)',"M$elapsed:$cidname"); + } else { + $AGI->set_variable('CALLERID(name)',"M$elapsed:$saved_cidname"); + } +} + +// From this point forward, Set KEEPCID in the channel so subsequent calls, CF, etc. retain the incoming +// CID that get sent down channel local. +$AGI->set_variable('__KEEPCID','TRUE'); + +// Set to '' in case it was previously set +// +$AGI->set_variable('DIALSTATUS_CW',''); + +$timer = get_var( $AGI, "ARG1" ); +$dialopts = get_var( $AGI, "ARG2" ); +$rgmethod = get_var( $AGI, "RingGroupMethod" ); +$rgmethod = trim($rgmethod); + +$alertinfo = get_var( $AGI, "ALERT_INFO" ); +if ($alertinfo) { + debug("Setting Alert-Info: $alertinfo", 4); + $AGI->set_alertinfo($alertinfo); +} + +$sippheader = get_var( $AGI, "SIPADDHEADER" ); +if ($sippheader) { + $fields = explode(':',$sippheader,2); + debug("Setting sipheader ".$fields[0].": ".$fields[1], 4); + $AGI->exec_sipaddheader($fields[0], $fields[1]); +} + +$pr_dialstatus = get_var( $AGI, "PR_DIALSTATUS" ); + +$fmgrp = get_var( $AGI, "FMGRP" ); +$nodest = get_var( $AGI, "NODEST" ); +if (empty($nodest)) { + $nodest = ''; +} + +$ringgroup_index = get_var( $AGI, "RINGGROUP_INDEX" ); +$use_confirmation = get_var( $AGI, "USE_CONFIRMATION" ); +if (empty($use_confirmation)) { + $use_confirmation = "FALSE"; +} +debug("USE_CONFIRMATION: '$use_confirmation'", 5); +debug("RINGGROUP_INDEX: '$ringgroup_index'", 5); + +if (empty($timer)) { + $timer = 0; +} +if (empty($dialopts)) { + $dialopts = ""; +} +if (empty($rgmethod)) { + $rgmethod = "none"; +} + +debug("Methodology of ring is '$rgmethod'", 1); + +// reset the ringgroup method to its fundamental algorithm and pull out if +// master mode. + +$recall_mastermode=$rgmethod; + +switch ($rgmethod) { + case 'ringall-prim': + $rgmethod = "ringall"; + $mastermode = 1; + break; + case 'hunt-prim': + $rgmethod = "hunt"; + $mastermode = 1; + break; + case 'memoryhunt-prim': + $rgmethod = "memoryhunt"; + $mastermode = 1; + break; + case 'ringallv2-prim': + $rgmethod = "ringallv2"; + $mastermode = 1; + break; + default: + $mastermode = 0; + $pr_dialstatus = ""; // not relevant if not mastermode, clear it so dnd doesn't propagate, and other +} + +// call confirmation only works with ringall and ringall-prim. The javascripts in ringgroups +// and follow-me should enforce this. If that has been overridden then force ringall. +// Keep this code after the matermode check above, since they will at least get mastermode +// if they set a -prim mode in one of the others +// +if ( ($use_confirmation != "FALSE") && ($rgmethod != "ringall") && ($rgmethod != "ringallv2") && ($rgmethod != "hunt") ) { + debug("Unsupported RingMethod: '$rgmethod' resetting to ringall", 1); + $rgmethod = "ringall"; +} + +// Start with Arg Count set to 3 as two args are used +$arg_cnt = 3; +while($arg = get_var($AGI,"ARG". $arg_cnt)) { + // not sure why, dialparties will get stuck in a loop if noresponse + if ($arg == '-') { + debug("get_variable got a \"noresponse\"! Exiting",3); + exit($arg_cnt); + } + $extarray = split( '-', $arg ); + foreach ( $extarray as $k ) { + $ext[] = $k; + debug("Added extension $k to extension map", 3); + } + $arg_cnt++; +} + +// FollowMe Preparation for Pre-Ring: +// +// If the primary extension is in the ringgroup list, then it should be rung +// during both the pre-ring time and the list time, so it's real prering time +// is the entire time. If it is not in the list, then it should only ring +// for the pre-ring time. This section determines the times and then adds it +// to the list if not already there, so that the dialstring is computed +// appropriately. This section also makes sure that the primary extension +// is at the top of the list. +// +// Notes before I forget. The primary may have been in the list and screwed +// above. So ... do I need to move this up, probably. +// +if ($rgmethod == "ringallv2" && $fmgrp != "") { + + $fmgrp_primaryremoved = 0; + + $fmgrp_prering = $AGI->database_get('AMPUSER', $fmgrp."/followme/prering"); + $fmgrp_prering = $fmgrp_prering['data'] > 1 ? $fmgrp_prering['data'] : 2; + + $fmgrp_grptime = $AGI->database_get('AMPUSER', $fmgrp."/followme/grptime"); + $fmgrp_grptime = $fmgrp_grptime['data']; + debug("got fmgrp_prering: $fmgrp_prering, fmgrp_grptime: $fmgrp_grptime",4); + + $fmgrp_totalprering = $fmgrp_grptime + $fmgrp_prering; + debug("fmgrp_totalprering: $fmgrp_totalprering",4); + + if (in_array($fmgrp, $ext)) { + debug("found extension in pre-ring and array",4); + $fmgrp_realprering = $fmgrp_totalprering; + if ($ext[0] != $fmgrp) { + $tmpx=array_flip($ext); + unset($ext[$tmpx[$fmgrp]]); + array_unshift($ext,$fmgrp); + } + } else { + debug("extension not in group list, ringging only during prering time",4); + $fmgrp_realprering = $fmgrp_prering; + array_unshift($ext,$fmgrp); + } + debug("ringallv2 ring times: REALPRERING: $fmgrp_realprering, PRERING: $fmgrp_prering",4); +} +$already_screened = get_var( $AGI, "SCREEN" ); // If this is the second pass through dialparties.agi, we don't want to double-screen the caller +$from_outside = get_var( $AGI, "FROM_DID" ); +$astvarlibdir = get_var( $AGI, "ASTVARLIBDIR" ); +// If this isn't a ring group, check to see if the user has call screening on +// Only screen calls if the primary extension is called, or it's follow-me is called, not ring groups +if(($from_outside != '') && isset($ext[0]) && ($rgmethod == "none" || $fmgrp == $ext[0]) && !$already_screened) { + $screen_call = $AGI->database_get('AMPUSER', $ext[0]."/screen"); + $screen_call = $screen_call['data']; + if (strlen($screen_call)) { + if($screen_call == 'nomemory' && $cidnum != '') { // This can't go in the dialplan because macro-dial can get called multiple times + // Do a security check, we only numeric callerid numbers, otherwise code could be incjected in a cidnum field + // that could result in an arbitrary command being executed in this remove operation. + if (ctype_digit($cidnum)) { + exec("rm -f $astvarlibdir/sounds/priv-callerintros/$cidnum.*"); + } + } + $screen = true; + $AGI->set_variable('__SCREEN',$screen_call); + $AGI->set_variable('__SCREEN_EXTEN',$ext[0]); + debug("Extension $k has call screening on", 4); + } else { + debug("Extension $k has call screening off", 4); + } +} +// IF THE FIRST EXTENSION IS CALL FORWARD ENABLED (put in logic) then we don't do master mode +// which means we reset the flag here after detecting that and just say we are not in master +// mode and all is well. That means the loop below needs to be modified to detect the first +// extension and do this if the case. + +// Check for call forwarding first +// If call forward is enabled, we use chan_local +// Hacky. We should be using an associative array, shouldn't we? +$count = 0; +foreach ($ext as $k) { + $cf = $AGI->database_get('CF',$k); + $cf = $cf['data']; + // + // TODO: If ringgoup tells us to ignore CF then don't do this + // + if (strlen($cf)) { + // append a hash sign so we can send out on chan_local below unless cfingore is set + if ($cfignore) { + unset($ext[$count]); + debug("Extension $k has call forward set to $cf", 1); + $AGI->set_variable('DIALSTATUS','NOANSWER'); + } else { + $ext[$count] = $cf.'#'; + debug("Extension $k has call forward set to $cf", 1); + } + + // if this is the primary extension and CF enabled, then cancel mastermode + // whether it is or not, no need to check. + // + if ($count == 0) { + $mastermode = 0; + $pr_dialstatus = ""; // not relevant if not mastermode, clear it so dnd doesn't propagate, and other + debug("Primary ext is CF so disabling mastermode if it was set", 4); + } + } + else { + debug("Extension $k cf is disabled", 3); + } + $count++; +} + +// IF DND AND we process it as a DND (no CF enabled) then we need to some how flag that ALL THE REST +// should now be ignored and not processed if in master mode (and this primary). Do this by setting some +// sort of flag that says master mode DND so skip everything else below (set them all to ""). +// + +// Hacky. +$count = 0; +$dndprimary = 0; +// Now check for DND +foreach ( $ext as $k ) { + if ( (substr($k,-1)!='#') ) { + // no point in doing if cf is enabled + $dnd = $AGI->database_get('DND',$k); + $dnd = $dnd['data']; + if (strlen($dnd) || $pr_dialstatus == "BUSY") { + debug("Extension $k has do not disturb enabled, or followme pre-ring returned busy", 2); + unset($ext[$count]); + $AGI->set_variable('DIALSTATUS','BUSY'); + // if this is primary set dndprimary and figure out if needed below + // + if ($count == 0 && $mastermode) { + $dndprimary = 1; + debug("Primary extension is DND, so if mastermode, all should be dnd", 4); + } + if ($count == 0) { + $fmgrp_primaryremoved = 1; + } + } + else { + debug("Extension $k do not disturb is disabled", 3); + } + } + $count++; +} + +// Main calling loop +// +$skipremaining = 0; // used to allow primary to ring but skip the rest +$ds = ''; +foreach ( $ext as $k ) { + // mastermode description: + // + // if mastermode is set then the first extension will be examined and mastermode will be reset so that the others + // are left alone. If the remaining extensions are not to be tried, skpremaining will be set to 1 which will + // result in dndprimary being set to 1 thus diabling the remaining list. + // + // if cf unconditional was already detected on the primary, then mastermode will have been reset at this point + // since that will negate the mastermode concpet. + // + // if dnd was set on the primary then dndprimary will already be set resulting in a completly blanked out list + // since dnd on the primary means don't bother me on any. + + // Don't bother checking these if we will be blanking the extnum anyhow + if ($skipremaining == 1) { + $dndprimary = 1; + } + if ($dndprimary == 0) { + // TODO what are these comments...? do we need to remove them...? + $extnum = $k; + + // CWIGNORE is sent down the channel when all extensions should be treated as if they do not have + // call waiting enabled. This is used primarily by Queue type setups (sometimes Ring Groups) when + // you want to assure that calls go on to the next agent if the current one is on the phone instead + // of ringing their line constantly. + // + if ($cwignore) { + $exthascw = 0; + } else { + $exthascw = $AGI->database_get('CW', $extnum);// ? 1 : 0; + $exthascw = $exthascw['data']? 1:0; + } + + $extcfb = $AGI->database_get('CFB', $extnum);//? 1 : 0; + $extcfb = $extcfb['data']; + $exthascfb = (strlen($extcfb) > 0) ? 1 : 0; + $extcfu = $AGI->database_get('CFU', $extnum);// ? 1 : 0; + $extcfu = $extcfu['data']; + $exthascfu = (strlen($extcfu) > 0) ? 1 : 0; + + // Dump details in level 4 + debug("extnum $extnum has: cw: $exthascw; hascfb: $exthascfb [$extcfb] hascfu: $exthascfu [$extcfu]",4); + + // check if mastermode and then reset here. If mastermode, this will be the first extension so + // the state is checked and a decision is made as to what to do. We have gotten all the cf variables + // above. If CF unconditional was set, we never get here because we alread reset mastermode. If DND + // were set then we never get here becasue didprimary was set + if ($mastermode == 1) { + $mastermode = 0; + $extstate = is_ext_avail($extnum); + debug("Extension $extnum has ExtensionState: $extstate",1); + + if ( ($exthascw == 1) && ($extstate == 1) ) { + // process this one extension but the remaining should be skipped since there is cw and + // the extension is occupied. This will try this extension but not the others. + $skipremaining = 1; + debug("In mastermode with cw enabled so $extnum will be tried and others skipped",4); + } elseif ( ($exthascw == 0) && ($extstate == 1) ) { + // no cw, ext is busy. So if cfb is set, it will forward there and if not, it will be + // ignored as normal behavior. In either case, we skip the remaining numbers. + $skipremaining = 1; + debug("In mastermode with cw disabled so $extnum will be processed in case cfb set",4); + } + // All other cases should act like normal. Unavailable, not busy, ringing, etc. + // should not be effected + } + } // end if ($dndprimary == 0) + // $dndprimary == 1 so clear the extension + else { + // clear the current extension if dndprimary has been set. This will only be the case if in mastermode so no need to check + // that. Use this to skip remaining extensions also if just ringing the primary. + $extnum = ''; + } + + // if CF is not in use and $dndprimary is not set otherwise $extnum has been cleared and nothing to do + // + if ( (substr($k,-1)!='#') && $dndprimary == 0) { + // CW is not in use or CFB is in use on this extension, then we need to check! + if ( ($exthascw == 0) || ($exthascfb == 1) || ($exthascfu == 1) ) { + // get ExtensionState: 0-idle; 1-busy; 4-unavail; 8-ringing <--- these are unconfirmed + $extstate = is_ext_avail($extnum); + debug("Extension $extnum has ExtensionState: $extstate",1); + + // Ext has CFU and is Unavailable + if ( ($exthascfu == 1) && ($extstate == 4) ) { + // If part of a ring group, then just do what CF does, otherwise needs to + // drop back to dialplan with NOANSWER + + // + // If cfignore is set, then we don't honor any CF settings + // + if ($rgmethod != '' && $rgmethod != 'none' && !$cfignore) { + debug("Extension $extnum has call forward on no answer set and is unavailable and is part of a Ring Group forwarding to '$extcfu'",1); + $extnum = $extcfu . '#'; # same method as the normal cf, i.e. send to Local + } else { + debug("Extension $extnum has call forward on no answer set and is unavailable",1); + $extnum = ''; + $AGI->set_variable('DIALSTATUS','NOANSWER'); + } + } elseif ( ($exthascw == 0) || ($exthascfb == 1) ) { + debug("Checking CW and CFB status for extension $extnum",3); + // extension in use + if ($extstate > 0 && $extstate != 4) { + debug("Extension $extnum is not available to be called", 1); + // extension in use + + // don't honor any CF settings when $cfignore is set + // + if ($exthascfb == 1 && !$cfignore) { + debug("Extension $extnum has call forward on busy set to $extcfb",1); + $extnum = $extcfb . '#'; # same method as the normal cf, i.e. send to Local + // CW not in use + } elseif ($exthascw == 0) { + debug("Extension $extnum has call waiting disabled",1); + $extnum = ''; + $AGI->set_variable('DIALSTATUS','BUSY'); + } else { + debug("Extension $extnum has call waiting enabled",1); + } + } + // -1 means couldn't read status usually due to missing HINT + } elseif ($extstate < 0) { + debug("ExtensionState for $extnum could not be read...assuming ok",3); + } else { + debug("Extension $extnum is available",1); + } + } elseif ($rgmethod == "none" && $exthascw == 1 && $cwinusebusy) { + $extstate = is_ext_avail($extnum); + if ($extstate == 1) { + $AGI->set_variable('DIALSTATUS_CW','BUSY'); + debug("Extension $extnum has call waiting enabled with state: $extstate",1); + } + // get ExtensionState: 0-idle; 1-busy; 4-unavail; 8-ringing <--- these are unconfirmed + } elseif ( ($exthascw == 1) && ($rgmethod == 'firstnotonphone') ) { + $extstate = is_ext_avail($extnum); + debug("Extension $extnum has ExtensionState: $extstate",1); + // CW in use - but blocked for hunt + if ($extstate == 1) { + debug("Extension $extnum has call waiting enabled but blocked for hunt",1); + $extnum = ''; + $AGI->set_variable('DIALSTATUS','BUSY'); + } + } + } + + if ($extnum != '') { + // Still got an extension to be called? + // check if we already have a dial string for this extension + // if so, ignore it as it's pointless ringing it twice ! + $realext = str_replace("#", "", $extnum); + if ( isset($dsarray[$realext]) ) { + debug("Extension '$realext' already in the dialstring, ignoring duplicate",1); + } else { + $dsarray[$realext] = 1; // could be dial string i suppose but currently only using for duplicate check + $extds = get_dial_string( $AGI, $extnum, $use_confirmation, $ringgroup_index); + if (strlen($extds)) { + $ds .= $extds . '&'; + } + // Update Caller ID for calltrace application + if ((substr($k,-1)!='#') && (($rgmethod != "hunt") && ($rgmethod != "memoryhunt") && ($rgmethod != "firstavailable") && ($rgmethod != "firstnotonphone")) ) { + if ( isset($cidnum) && is_numeric($cidnum) ) { + $rc = $AGI->database_put('CALLTRACE', $k, $cidnum); + if ($rc['result'] == 1) { + debug("dbset CALLTRACE/$k to $cidnum", 3); + } else { + debug("Failed to DbSet CALLTRACE/$k to $cidnum ({$rc['result']})", 1); + } + } else { + // We don't care about retval, this key may not exist + $AGI->database_del('CALLTRACE', $k); + debug("DbDel CALLTRACE/$k - Caller ID is not defined", 3); + } + } else { + $ext_hunt[$k]=$extds; // Need to have the extension HASH set with technology for hunt group ring + } + } + } +} // end foreach ( $ext as $k ) + +$dial_filtered = implode('-',array_keys($dsarray)); +$AGI->set_variable('FILTERED_DIAL',$dial_filtered); +debug("Filtered ARG3: $dial_filtered", 3); + +$dshunt = ''; +$loops = 0; +$myhuntmember = ""; + +/** Here we setup the Channel Variables that are used to do the dialing, in all cases you will have: + * ${HuntMembers} set to the number of phones to ring + * ${HuntMemberN} set to the dial pattern that should be dialed. (N is 0, 1, 2 etc.) + */ +if (($rgmethod == "hunt") || ($rgmethod == "memoryhunt") || ($rgmethod == "firstavailable") || ($rgmethod == "firstnotonphone")) { + if ($cidnum) { + $AGI->set_variable('CALLTRACE_HUNT',$cidnum); + } + foreach ($extarray as $k ) { + // we loop through the original array to get the extensions in order of importance + if ($ext_hunt[$k]) { + //If the original array is included in the extension hash then set variables + $myhuntmember="HuntMember"."$loops"; + if (($rgmethod == "hunt") || ($rgmethod == "firstavailable") || ($rgmethod == "firstnotonphone")) { + $AGI->set_variable($myhuntmember,$ext_hunt[$k]); + } elseif ($rgmethod == "memoryhunt") { + if ($loops==0) { + $dshunt =$ext_hunt[$k]; + } else { + $dshunt .='&'.$ext_hunt[$k]; + } + $AGI->set_variable($myhuntmember,$dshunt); + } + $loops += 1; + } + } +} + +$ds = chop($ds," &"); + +if ($nodest != '' && $use_confirmation == 'FALSE') { + if (strpos($dialopts,"M(auto-blkvm)") > 0 || strpos($dialopts,"M(auto-blkvm)") === 0 || + strpos($dialopts,"M(auto-confirm") > 0 || strpos($dialopts,"M(auto-confirm") === 0 || + strpos($dialopts,"M(confirm") > 0 || strpos($dialopts,"M(confirm") === 0) { + debug("NODEST: $nodest blkvm enabled macro already in dialopts: $dialopts",4); + } else { + $dialopts .= "M(auto-blkvm)"; + debug("NODEST: $nodest adding M(auto-blkvm) to dialopts: $dialopts",4); + } +} + +// FollowMe Changes: +// +// We need to determine if the generated dialstring can be dialed as is. This will be the case if there are no +// or is only a single extension to dial. +// +// First, unset any blank fields so we know how many extensions there are to call. +// +// If mastermode (skipremaining == 1) was triggered then we just set the ringtime to what the primary extension +// should ring for and let this dialstring go. +// +// If there is only one extension in the list, then we need to determine how long to ring it (depending on if it +// was the primary or another extension, then let the generated dialstring ring it. +// +// Otherwise, we need to re-create the dialstring to be processed by our special dialplan that will ring the +// primary extension and hold the group list for the required delay. Also - if we are in a call confirmation mode +// then we need to reset the call confirm variables with one level of inheritance so that they remain in the new +// channels but don't get further propogated after that. We also clear it for the remainder of this instance since +// we are not yet triggering further actions until the next call. +// +// Notes: $fmgrp_primaryremoved is set to 1 if the primary has been removed from the list so we know that it was dnd-ed. +// this only matters in non-prim mode, where we need to know if the remaining list contains the primary extension +// or not. +// +if ($rgmethod == 'ringallv2') { + $count = 0; + foreach ($ext as $x) { + if ($x == '') { + unset($ext[$count]); + } + $count++; + } + + if (($skipremaining == 1) || (count($ext) == 1 && $fmgrp_primaryremoved == 0)) { + $timer = $fmgrp_realprering; + } elseif (count($ext) == 1 && $fmgrp_primaryremoved == 1) { + $timer = $fmgrp_grptime; + } elseif (count($ext) == 1) { + $timer = $fmgrp_totalprering; // not sure what would trigger this ? + } else { + $timer = $fmgrp_totalprering; + $ds = "Local/FMPR-".array_shift($ext)."@from-internal&Local/FMGL-".implode('-',$ext)."@from-internal"; + + $fmgrp_fmunique = $AGI->request['agi_channel']; + $AGI->set_variable('_FMUNIQUE',$fmgrp_fmunique); + $AGI->set_variable('_RingGroupMethod',"ringall"); + $fmgrp_prering -= 2; + $AGI->set_variable('_FMPRERING',$fmgrp_prering); + $AGI->set_variable('_FMREALPRERING',$fmgrp_realprering); + $AGI->set_variable('_FMGRPTIME',$fmgrp_grptime); + $AGI->set_variable('_FMPRIME',($recall_mastermode == "ringallv2")?"FALSE":"TRUE"); + + debug("FMUNIQUE: $fmgrp_fmunique, FMRERING: $fmgrp_prering, FMREALPRERING: $fmgrp_realprering, FMGRPTIME: $fmgrp_grptime",6); + + if ($use_confirmation != 'FALSE') { + $AGI->set_variable('_USE_CONFIRMATION',$use_confirmation); + $AGI->set_variable('_RINGGROUP_INDEX',$ringgroup_index); + $use_confirmation = 'FALSE'; + } + } +} + +if ($nodest != '' && $use_confirmation == 'FALSE') { + if (strpos($dialopts,"M(auto-blkvm)") > 0 || strpos($dialopts,"M(auto-blkvm)") === 0 || + strpos($dialopts,"M(auto-confirm") > 0 || strpos($dialopts,"M(auto-confirm") === 0 || + strpos($dialopts,"M(confirm") > 0 || strpos($dialopts,"M(confirm") === 0) { + debug("NODEST: $nodest blkvm enabled macro already in dialopts: $dialopts",4); + } else { + $dialopts .= "M(auto-blkvm)"; + debug("NODEST: $nodest adding M(auto-blkvm) to dialopts: $dialopts",4); + } +} + +if (!strlen($ds)) { + $AGI->noop(''); +} else { + // Asterisk 1.6 uses , instead of | and 1.4 can't recieve a , in the ds. + // + if (version_compare($ast_version, "1.6", "ge")) { + $ds_seperator = ','; + } else { + $ds_seperator = '|'; + } + + if (($rgmethod == "hunt") || ($rgmethod == "memoryhunt") || ($rgmethod == "firstavailable") || ($rgmethod == "firstnotonphone")) { + $ds = $ds_seperator; + if ($timer) { + $ds .= $timer; + } + $ds .= $ds_seperator . $dialopts; // pound to transfer, provide ringing + $AGI->set_variable('ds',$ds); + $AGI->set_variable("HuntMembers",$loops); + $AGI->set_priority("huntdial"); // dial command was at priority 20 where dialplan handles calling a ringgroup with strategy of "hunt" or "MemoryHunt" + } else { + $ds .= $ds_seperator; + if ($timer) { + $ds .= $timer; + if (trim($use_confirmation) != "FALSE") { + $AGI->set_variable('__RT',$timer); + } + } + $ds .= $ds_seperator . $dialopts; // pound to transfer, provide ringing + if ($screen) { + $ds .= "p"; + } + if (trim($use_confirmation) != "FALSE") { + $AGI->set_variable('__RG_IDX',$ringgroup_index); + if ( isset($cidnum) && is_numeric($cidnum) ) { + $AGI->set_variable('__CALLCONFIRMCID',$cidnum); + } else { + $AGI->set_variable('__CALLCONFIRMCID',"999"); + } + } + $AGI->set_variable('ds',$ds); + $AGI->set_priority("normdial"); // dial command was at priority 10 + } +} + +// sanity check make sure dialstatus is set to something +// +if (! $ds) { + $dialstatus = get_var( $AGI, "DIALSTATUS" ); + if (! $dialstatus) { + debug("Setting default NOANSWER DIALSTATUS since no extensions available",1); + $AGI->set_variable('DIALSTATUS','NOANSWER'); + } +} + +$astman->disconnect(); + +// EOF dialparties.agi +exit( 0 ); + +// helper functions +function get_var( $agi, $value) { + $r = $agi->get_variable( $value ); + + if ($r['result'] == 1) { + $result = $r['data']; + return $result; + } + return ''; +} + +function get_dial_string( $agi, $extnum, $use_confirmation, $ringgroup_index ) { + global $chan_dahdi; + $dialstring = ''; + + if (strpos($extnum,'#') != 0) { + // "#" used to identify external numbers in forwards and callgourps + // If using call confirmation, need to put the # back into the new dialstring + // we then place all external calls (denoted with a # at the end) through + // the [grps] extension for the RINGGROUP_INDEX that was called. This + // triggers the call confirmation macro along with the required messages + // that were set. + // + $extnum = str_replace("#", "", $extnum); + if (trim($use_confirmation) == "FALSE") { + $dialstring = 'Local/'.$extnum.'@from-internal/n'; + } else { + $dialstring = 'Local/RG-'.$ringgroup_index.'-'.$extnum.'#@from-internal'; + } + debug("Built External dialstring component for $extnum: $dialstring", 4); + } else { + $device_str = sprintf("%s/device", $extnum); + $device = $agi->database_get('AMPUSER',$device_str); + $device = $device['data']; + + // a user can be logged into multipe devices, append the dial string for each + $device_array = split( '&', $device ); + foreach ($device_array as $adevice) { + if (trim($use_confirmation) == "FALSE") { + $dds = $agi->database_get('DEVICE',$adevice.'/dial'); + if ($chan_dahdi) { + $dialstring .= str_replace('ZAP/', 'DAHDI/', $dds['data']); + } else { + $dialstring .= $dds['data']; + } + $dialstring .= '&'; + } else { + $dialstring .= 'Local/LC-'.$adevice.'@from-internal&'; + } + } + $dialstring = trim($dialstring," &"); + } + return $dialstring; +} + +function debug($string, $level=3) { + global $AGI; + $AGI->verbose($string, $level); +} + +function mycallback( $rc ) { + debug("User hung up. (rc=" . $rc . ")", 1); + exit ($rc); +} + +function is_ext_avail( $extnum ) { + global $astman; + + $status = $astman->ExtensionState( $extnum, 'from-internal' ); + + $status = $status['Status']; + debug("ExtensionState: $status", 4); + return $status; +} + +?> Index: /modules/branches/2.6/core/agi-bin/directory =================================================================== --- /modules/branches/2.6/core/agi-bin/directory (revision 4457) +++ /modules/branches/2.6/core/agi-bin/directory (revision 4457) @@ -0,0 +1,520 @@ +#!/usr/bin/php -q +get_variable( $value ); + + if ($r['result'] == 1) + { + $result = $r['data']; + return $result; + } + else + return ''; +} + +function output(&$var) { + if (DEBUG) { + global $logfile; + + if (!isset($logfile)) return false; + + ob_start(); + var_dump($var); + $output = ob_get_contents(); + ob_end_clean(); + fwrite($logfile, $output); + } +} + + +function parse_voicemailconf($filename, &$vmconf, &$section) { + if (is_null($vmconf)) { + $vmconf = array(); + } + if (is_null($section)) { + $section = "general"; + } + + if (file_exists($filename)) { + $fd = fopen($filename, "r"); + while ($line = fgets($fd, 1024)) { + if (preg_match("/^\s*(\d+)\s*=>\s*(\d+),(.*),(.*),(.*),(.*)\s*([;#].*)?/",$line,$matches)) { + // "mailbox=>password,name,email,pager,options" + // this is a voicemail line + $vmconf[$section][ $matches[1] ] = array("mailbox"=>$matches[1], + "pwd"=>$matches[2], + "name"=>$matches[3], + "email"=>$matches[4], + "pager"=>$matches[5], + ); + + // parse options + foreach (explode("|",$matches[6]) as $opt) { + $temp = explode("=",$opt); + if (isset($temp[1])) { + list($key,$value) = $temp; + $vmconf[$section][ $matches[1] ]["options"][$key] = $value; + } + } + } else if (preg_match("/^\s*(\d+)\s*=>\s*dup,(.*)\s*([;#].*)?/",$line,$matches)) { + // "mailbox=>dup,name" + // duplace name line + $vmconf[$section][ $matches[1] ]["dups"][] = $matches[2]; + } else if (preg_match("/^\s*#include\s+(.*)\s*([;#].*)?/",$line,$matches)) { + // include another file + + if ($matches[1][0] == "/") { + // absolute path + $filename = $matches[1]; + } else { + // relative path + $filename = dirname($filename)."/".$matches[1]; + } + + parse_voicemailconf($filename, $vmconf, $section); + + } else if (preg_match("/^\s*\[(.+)\]/",$line,$matches)) { + // section name + $section = strtolower($matches[1]); + } else if (preg_match("/^\s*([a-zA-Z0-9-_]+)\s*=\s*(.*?)\s*([;#].*)?$/",$line,$matches)) { + // name = value + // option line + $vmconf[$section][ $matches[1] ] = $matches[2]; + } + } + } +} + + +/** Play a bunch of files, optionally accepting input and looping + * @param $files The file/files to play (for multiple files, pass array) + * @param $escape_digits The DTMF tones that can be pressed & returned, ie, "123*" + * @param $timeout The timeout waiting for a digit, or 0 to not wait at all. + * @param $max_digits Maximum number of digits to get. **NOT IMPLEMENTED YET.. 1 only** + * @param $loop False for no loop, or an integer >0 being the number of times to loop. + * @param $loopreturn Value to return when the loop expires +*/ +function stream_multiple($files, $escape_digits = "", $timeout = 0, $max_digits = 1, $loop = false, $loopreturn = 0) { + global $agi; + + if (!is_array($files)) { + $files = array($files); + } + + $i = 0; + do { + foreach ($files as $file) { + $agi->verbose("-- Playing '".$file."' (language 'en')"); + $r = $agi->stream_file($file, $escape_digits); + $agi->conlog("stream_multiple: $file returned ".$r["result"]); + switch ($r["result"]) { + case 0: // they did nothing + break; + case -1: // they hungup + $agi->verbose("remote user hungup"); + return -1; + break; + default: // they pressed a key + return $r["result"]; + break; + } + } + + if ($timeout > 0) { + $r = $agi->wait_for_digit($timeout); + if (($r["result"] != 0) || (!$loop)) { + // return only if the reult is not 0 (timeout) + // or we're not doing a loop + return $r["result"]; + } + } + + if ($loop && (++$i > $loop)) { + return $loopreturn; + } + } while ($loop); + + return 0; +} + +/** If $file.(wav|WAV|gsm|GSM) exists + */ +function sound_file_exists($file) { + global $agi; + + foreach (array("gsm","GSM","wav","WAV") as $ext) { + if (file_exists($file.".".$ext)) { + $agi->verbose("Found ".$file.".".$ext, 2); + return true; + } + } + return false; +} + +function string_to_digits($string) { + $out = ""; + + for($i=0; $iget_data($intro, 4000, NUM_DIGITS); + + if (($r["result"] == "0") && $operator) { + // operator + $agi->verbose("Dropping to operator"); + // switch to o,1 in the current context + $agi->set_extension("o"); + $agi->set_priority("1"); + // exiting application immediately! + exit(0); + } + $digits = $r["result"]; + + usleep(500); // pause a bit, so digit presses get cleared + + if ($digits !== "") { + // they entered SOMETHING, reset our loop + $loop = 0; + } + + $i = 0; + $digit = false; + if (isset($directory[$digits]) && isset($directory[$digits][$i])) { + $loop = 0; // reset loop counter + do { + $match = & $directory[$digits][$i]; + + $maindirname = sprintf($voicemail_dir, $match["context"], $match["ext"]); + + if (sound_file_exists($maindirname."/greet")) { + $r = $agi->stream_file($maindirname."/greet",$escape_digits); + if ($r["result"] > 0) $digit = $r["result"]; + } else { + $digit = say_alpha($match["name"],$escape_digits); + } + + if (!$digit) { + $digit = stream_multiple("dir-instr", $escape_digits, 3000); + } + + switch ($digit) { + case D_1: // dial this + if ($say_exten) { + $agi->stream_file("pls-hold-while-try"); + $agi->stream_file("to-extension"); + + $agi->say_digits($match["ext"]); + } + $agi->conlog("Dial ".$match["ext"]); + + $agi->set_context($dial_context); + $agi->set_extension($match["ext"]); + $agi->set_priority("1"); + exit(0); + break; + case D_STAR: // not correct + $i += 1; + break; + case D_0: // operator + if ($operator) { + $agi->verbose("Dropping to operator"); + // switch to o,1 in the current context + $agi->set_extension("o"); + $agi->set_priority("1"); + // exiting application immediately! + exit(0); + } + break; + case -1: // hungup + $agi->conlog("User hungup"); + exit(1); + break; + case 0: // no response + $loop++; + break; + case -2: // loop timed out + $agi->stream_file("goodbye"); + $agi->hangup(); + exit(0); + break; + } + + if ($digit !== 0) { + $loop = 0; + } + $digit = false; + } while (isset($directory[$digits][$i]) && ($loop < MAX_REPEAT)); + + if (!isset($directory[$digits][$i])) { + $agi->stream_file("dir-nomore"); + $loop = 0; // reset our loop counter so it doesn't hangup + } + } else if (!empty($digits) || ($digits === "0")) { + // strict type checking as they may have entered "0" (string) which is empty() + $agi->stream_file("dir-nomatch"); + } // else, we timed out + + $loop++; + } +} + +/******************************************************************************/ + +$agi = new AGI; + +$directory_file = get_var($agi, "ASTETCDIR")."/voicemail.conf"; + +// where is voicemail stored? +$voicemail_dir = get_var($agi, "ASTSPOOLDIR")."/voicemail/%s/%d"; + +// where should we store logs? (fixes #1912) +$log_dir = get_var($agi, "ASTLOGDIR"); + +if (DEBUG) $logfile = fopen( $log_dir . "/directory.log","w"); + +$vmconf = array(); +$null = null; +parse_voicemailconf($directory_file, $vmconf, $null); + + +if (!$argv[1]) { + $agi->verbose("Notice: vm-context not specified. Using 'default'"); + $vm_context = "default"; +} else { + $vm_context = trim($argv[1]); +} + +if (!isset($vmconf[$vm_context]) && ($vm_context != "general")) { + // we make an exception for "general" context,as it just includes other contexts + $agi->verbose("Cannot find context ".$vm_context." in ".$directory_file); + exit(1); +} + +if (isset($argv[2])) { + $dial_context = trim($argv[2]); +} else { + $dial_context = $vm_context; +} + +$operator = false; +$dir_type = DIR_FIRST; +$say_exten = false; + +if (isset($argv[3])) { + for($i=0; $i$arr) { + // skip if it's general context -- this doesn't contain mailboxes + if ($context == "general") continue; + + foreach ($arr as $key=>$box) { + // we could do if !isset($boxes[$key]) to NOT override mailboxes + + // add in the context, otherwise we don't know what it is + $box["context"] = $context; + + $boxes[$key] = $box; + } + } +} else { + $boxes = &$vmconf[$vm_context]; +} + +$directory = array(); +foreach ($boxes as $box) { + if (!empty($box["name"])) { + $name = explode(" ",$box["name"]); + + if (isset($box["context"])) { + $context = $box["context"]; + } else { + $context = $vm_context; + } + + switch ($dir_type) { + case DIR_FIRST: // first name only + $digits = string_to_digits($name[0]); + $directory[$digits][] = array("ext"=>$box["mailbox"], "name"=>$box["name"], "context"=>$context); + break; + case DIR_BOTH: // all names + foreach ($name as $temp) { + $digits = string_to_digits($temp); + $directory[$digits][] = array("ext"=>$box["mailbox"], "name"=>$box["name"], "context"=>$context); + } + break; + case DIR_LAST: default: // last name only + $digits = string_to_digits(end($name)); + $directory[$digits][] = array("ext"=>$box["mailbox"], "name"=>$box["name"], "context"=>$context); + break; + } + } +} + +if (DEBUG) { + output($argv); + output($dir_type); + output($directory); +} + +do_directory($dir_type, $directory, $dial_context, $say_exten, $operator); + +?> Index: /modules/branches/2.6/core/agi-bin/checksound.agi =================================================================== --- /modules/branches/2.6/core/agi-bin/checksound.agi (revision 4521) +++ /modules/branches/2.6/core/agi-bin/checksound.agi (revision 4521) @@ -0,0 +1,67 @@ +#!/usr/bin/php -q + vmx,n,TrySystem(/bin/ls ${ASTSPOOLDIR}/voicemail/${VMCONTEXT}/${ARG1}/${MODE}.[wW][aA][vV]) + */ + +require_once "phpagi.php"; + +$AGI = new AGI(); +$file = $argv[1]; + +if (file_exists($file.".wav") || file_exists($file.".WAV")) { + $AGI->set_variable('SYSTEMSTATUS','SUCCESS'); +} else { + $AGI->set_variable('SYSTEMSTATUS','APPERROR'); + debug("VmX requires: $file.wav or .WAV exist in order to function",1); +} + +// EOF dialparties.agi +exit( 0 ); + +// helper functions +function get_var( $agi, $value) +{ + $r = $agi->get_variable( $value ); + + if ($r['result'] == 1) + { + $result = $r['data']; + return $result; + } + else + return ''; +} + +function debug($string, $level=3) +{ + global $AGI; + $AGI->verbose($string, $level); +} + +?> Index: /modules/branches/2.6/core/agi-bin/list-item-remove.php =================================================================== --- /modules/branches/2.6/core/agi-bin/list-item-remove.php (revision 4291) +++ /modules/branches/2.6/core/agi-bin/list-item-remove.php (revision 4291) @@ -0,0 +1,58 @@ +#!/usr/bin/php -q +verbose("Missing list"); + exit(1); +} + +if (!isset($argv[2])) { + $agi->verbose("Missing item"); + exit(1); +} + +if (!isset($argv[3])) { + $agi->verbose("Missing return var name"); + exit(1); +} + +$arglist = $argv[1]; +$argitem = $argv[2]; +$argvarname = $argv[3]; + +if (isset($argv[4])) { + $argsep = "&"; +} else { + $argsep = $argv[4]; +} + +$newlist = str_replace($argitem.$argsep, "", $arglist.$argsep); + +if (substr($newlist, -1, 1) == $argsep) { + $newlist = substr($newlist, 0, -1); +} + +$agi->set_variable($argvarname, $newlist); +?> Index: /modules/branches/2.6/core/agi-bin/recordingcheck =================================================================== --- /modules/branches/2.6/core/agi-bin/recordingcheck (revision 6521) +++ /modules/branches/2.6/core/agi-bin/recordingcheck (revision 6521) @@ -0,0 +1,132 @@ +#!/usr/bin/php -q +get_variable("ARG2"); + +switch($type['data']) { + case "Group": + + $r = $agi->get_variable("ARG1"); + if ($r["result"] == 0) { + $agi->verbose("Extension List not set -- nothing to do"); + exit(1); + } + $extenlist = $r["data"]; + + $agi->set_variable("RecEnable", "DISABLED"); //disable by default + + $list = explode("-",$extenlist); + if(!empty($list)) { + foreach($list as $exten) { + $setting = $agi->database_get("AMPUSER",$exten."/recording"); + if ($setting["result"] == 0) { + $agi->verbose("No DB Entry AMPUSER/$exten/recording - Not Recording for $exten, checking for others"); + continue; + } + //explode recording vars + $recording = explode("|",$setting["data"]); + $recout = substr($recording[0],4); + $recin = substr($recording[1],3); + if ($recin == "Always") { + $agi->verbose("Recording enable for ".$exten); + $agi->verbose("CALLFILENAME=g{$exten}-{$timestamp}-{$uniqueid}"); + $agi->set_variable("CALLFILENAME","g{$exten}-{$timestamp}-{$uniqueid}"); + $agi->set_priority('record'); + exit(0); + } + } + } else { + $agi->verbose("Extension List is empty -- nothing to do"); + exit(1); + } + + break; + case "OUT": + $exten = $agi->get_variable("ARG1"); + + $options = $agi->database_get("AMPUSER","{$exten['data']}/recording"); + + if ($options["result"] == "0") { + $agi->verbose("No AMPUSER db entry for ".$exten["data"].". Not recording"); + exit(1); + } + + //explode recording vars + $recording = explode("|",$options["data"]); + $recout = substr($recording[0],4); + $recin = substr($recording[1],3); + + if($recout == "Always") { + $agi->verbose("Outbound recording enabled."); + $agi->verbose("CALLFILENAME=OUT{$exten['data']}-{$timestamp}-{$uniqueid}"); + $agi->set_variable("CALLFILENAME","OUT{$exten['data']}-{$timestamp}-{$uniqueid}"); + $agi->set_priority('record'); + exit(0); + } else { + $agi->verbose("Outbound recording not enabled"); + exit(1); + } + break; + case "IN": + $exten = $agi->get_variable("ARG1"); + $options = $agi->database_get("AMPUSER","{$exten['data']}/recording"); + + if ($options["result"] == "0") { + $agi->verbose("No AMPUSER db entry for ".$exten["data"].". Not recording"); + exit(1); + } + //explode recording vars + $recording = explode("|",$options["data"]); + $recout = substr($recording[0],4); + $recin = substr($recording[1],3); + + if($recin == "Always") { + $agi->verbose("Inbound recording enabled."); + $agi->verbose("CALLFILENAME={$timestamp}-{$uniqueid}"); + $agi->set_variable("CALLFILENAME","{$timestamp}-{$uniqueid}"); + $agi->set_priority('record'); + exit(0); + } else { + $agi->verbose("Inbound recording not enabled"); + exit(1); + } + break; +} + +// we just exit with no changes to the variable. +exit(1); + +?> Index: /modules/branches/2.6/core/agi-bin/user_login_out.agi =================================================================== --- /modules/branches/2.6/core/agi-bin/user_login_out.agi (revision 7043) +++ /modules/branches/2.6/core/agi-bin/user_login_out.agi (revision 7043) @@ -0,0 +1,442 @@ +#!/usr/bin/php -q +connect("127.0.0.1", $ampmgruser , $ampmgrpass)) { + exit (1); + } + + $action = get_action(); + $this_device = get_this_device(); + + switch ($action) { + case 'login': + case 'logon': + $new_user = get_login_user(); + debug("Logging in user $new_user to device $this_device"); + user_login($this_device, $new_user); + break; + case 'logout': + debug("Logging out current user from device $this_device"); + user_logout($this_device); + break; + default: + debug("Got unknown action: $action, exiting"); + } + exit; + + /* +exten => s,n,System(rm -f ${ASTSPOOLDIR}/voicemail/device/${CALLERID(number)}) +exten => s,n,System(/bin/ln -s ${ASTSPOOLDIR}/voicemail/${DB(AMPUSER/${AMPUSER}/voicemail)}/${AMPUSER}/ ${ASTSPOOLDIR}/voicemail/device/${CALLERID(number)}) +*/ + + + // Get the requested action (login or logout) + // + function get_action() { + global $argv; + return strtolower(trim($argv['1'])); + //return get_var('ARG1'); + } + + // Get the device passed in (basically CID) + // + function get_this_device() { + global $argv; + return trim($argv['2']); + //return get_var('ARG2'); + } + + // Get the user to login to a device + // + function get_login_user() { + global $argv; + return trim($argv['3']); + //return get_var('ARG3'); + } + + // Login a new user to a device. If there is a current user + // log them out first. + // + function user_login($this_device, $new_user) { + debug("user_login: this_device: $this_device, new_user: $new_user",8); + + $current_user = get_logged_in_user($this_device); + if ($current_user != $new_user) { + if ($current_user != '') { + debug("Logging out current user $current_user from device $this_device so $new_user can login",5); + remove_user($this_device); + } + insert_user($new_user, $this_device); + } else { + debug("User $new_user is already logged into device $this_device",5); + } + } + + // Logout the current user. If device has a default user, log + // them in. + // + function user_logout($this_device) { + debug("user_logout: this_device: $this_device",8); + + $current_user = get_logged_in_user($this_device); + $default_user = get_default_user($this_device); + + debug("current_user: $current_user, default_user: $default_user",8); + + if ($current_user != $default_user) { + remove_user($this_device); + if ($default_user != '') { + debug("Logging in default user $default_user to device $this_device",5); + insert_user($default_user, $this_device); + } + } + } + + // Insert a specificed user into a specified device and then + // update the hint for that user to reflect the new device(s) + // and update the voicemial link + // + function insert_user($user, $device) { + debug("insert_user: user: $user, device: $device",8); + global $agi; + global $astspooldir; + global $fm_devstate; + global $dnd_devstate; + global $DEVSTATE; + + set_device_user($device, $user); + $previous_devices = get_devices($user); + $new_devices = insert_device($previous_devices,$device); + debug("insert_user: Setting user $user to devices $new_devices",5); + set_user_devices($user, $new_devices); + set_hint($user, $new_devices); + $agi->exec("UserEvent", "\"UserDeviceAdded|Data: {$user},{$device}\""); + + if ($fm_devstate) { + debug("insert_user: Setting FollowMe DEVSTATES for device $device",5); + $agi->set_variable($DEVSTATE.'(Custom:FOLLOWME'.$device.')',get_followme_state($user)); + } + if ($dnd_devstate) { + debug("insert_user: Setting DND DEVSTATES for device $device",5); + $agi->set_variable($DEVSTATE.'(Custom:DEVDND'.$device.')',get_dnd_state($user)); + } + + $vmcontext = get_voicemail_context($user); + if ($vmcontext != 'novm') { + exec("/bin/ln -s {$astspooldir}/voicemail/{$vmcontext}/{$user}/ {$astspooldir}/voicemail/device/$device", $output, $ret); + if ($ret) { + debug("Got Return code: $ret trying to: /bin/ln -s {$astspooldir}/voicemail/{$vmcontext}/{$user}/ {$astspooldir}/voicemail/device/$device",5); + } + } + } + + // Remove the current user from a device and then update + // the hint of that current user to reflect their current devices + // + function remove_user($device) { + debug("remove_user: device: $device",8); + global $agi; + global $astspooldir; + global $fm_devstate; + global $dnd_devstate; + global $DEVSTATE; + + $current_user = get_user($device); + if ($current_user != '') { + $current_devices = get_devices($current_user); + $new_devices = remove_device($current_devices,$device); + debug("remove_user: Setting user $current_user to devices $new_devices",5); + set_user_devices($current_user, $new_devices); + set_hint($current_user, $new_devices); + $agi->exec("UserEvent", "\"UserDeviceRemoved|Data: {$current_user},{$device}\""); + exec("/bin/rm -f {$astspooldir}/voicemail/device/$device",$output, $ret); + + debug("Setting device $device states to INVALID before deleting them",5); + if ($fm_devstate) { + debug("Setting device $device FollowMe state to INVALID before deleting",5); + $agi->set_variable($DEVSTATE.'(Custom:FOLLOWME'.$device.')','INVALID'); + } + if ($dnd_devstate) { + debug("Setting device $device DND state to INVALID before deleting",5); + $agi->set_variable($DEVSTATE.'(Custom:DEVDND'.$device.')','INVALID'); + } + // I thought they should then be deleted, but they still end up there probably because setting them to invalid re-creates them + // + //$agi->database_deltree('CustomDevstate','FOLLOWME'.$device); + //$agi->database_deltree('CustomDevstate','DEVDND'.$device); + if ($ret) { + debug("Got Return code: $ret trying to remove: {$astspooldir}/voicemail/device/$device",5); + } + set_device_user($device, 'none'); + } + } + + // Set the hint for a user based on the devices in their AMPUSER object + // + function set_hint($user, $devices) { + debug("set_hint: user: $user, devices: $devices",8); + global $astman; + global $agi; + global $dnd_devstate; + global $intercom_code; + global $ast_version14; + + // If Asterisk version >= 1.4, syntax change is 'dialplan add extension ...' vs. 'add extension ...' + $dp_pre = ($ast_version14) ? 'dialplan ' : ''; + + if ($devices) { + $dial_string = get_dial_string($devices); + if ($dnd_devstate) { + $dial_string .= "&Custom:DND$user"; + } + debug("Setting user $user hint to $dial_string",5); + $response = $astman->send_request('Command',array('Command'=>$dp_pre."add extension {$user},hint,{$dial_string} into ext-local replace")); + if ($intercom_code != 'nointercom' && $intercom_code != '') { + $response = $astman->send_request('Command',array('Command'=>$dp_pre."add extension {$intercom_code}{$user},hint,{$dial_string} into ext-local replace")); + } + } else { + debug("Removing hint for user $user",5); + $response = $astman->send_request('Command',array('Command'=>$dp_pre."remove extension {$user}@ext-local hint")); + if ($intercom_code != 'nointercom' && $intercom_code != '') { + $response = $astman->send_request('Command',array('Command'=>$dp_pre."remove extension {$intercom_code}{$user}@ext-local hint")); + } + } + } + + // Get the actual technology dialstrings from the DEVICE objects (used + // to create proper hints) + // + function get_dial_string($devices) { + $dialstring = ""; + + debug("get_dial_string: devices: $devices",8); + global $agi; + + $device_array = explode( '&', $devices ); + foreach ($device_array as $adevice) { + $dds = $agi->database_get('DEVICE',$adevice.'/dial'); + $dialstring .= $dds['data'].'&'; + } + return trim($dialstring," &"); + } + + // Insert a new device into a devices string and return the new string + // + function insert_device($devices, $new_device) { + debug("insert_device: devices: $devices, new_device: $new_device",8); + + // We could just append it but this assures no bugs duplicate the device + // + if (trim($new_device) != '') { + $device_arr = explode('&',$devices); + $device_arr[] = $new_device; + $device_arr = array_unique($device_arr); + return implode('&',$device_arr); + } else { + return $devices; + } + } + + // Remove a new device from a devices string and return the new string + // + function remove_device($devices, $remove_device) { + debug("remove_device: devices: $devices, remove_device: $remove_device",8); + + $device_arr = explode('&',$devices); + $device_arr_hash = array_flip($device_arr); + unset($device_arr_hash[$remove_device]); + $new_device_arr = array_flip($device_arr_hash); + $new_devices = implode('&', $new_device_arr); + return $new_devices; + } + + // Get the currently logged in user of a device returning blank + // in no logins + // + function get_logged_in_user($device) { + debug("get_logged_in_user: device: $device",8); + global $agi; + + $user = $agi->database_get('DEVICE',$device.'/user'); + if ($user['result'] == 1 && trim($user['data']) != 'none') { + debug("get_logged_in_user: got user: ".$user['data'],8); + return trim($user['data']); + } + return ''; + } + + // Get the designated default user for the device or blank if none + // + function get_default_user($device) { + debug("get_default_user: device: $device",8); + global $agi; + + $default_user = $agi->database_get('DEVICE',$device.'/default_user'); + if ($default_user['result'] == 1 && trim($default_user['data']) != 'none') { + return trim($default_user['data']); + } + return ''; + } + + // Get the list of current devices for this user + // + function get_devices($user) { + debug("get_devices: user: $user", 8); + global $agi; + + $devices = $agi->database_get('AMPUSER',$user.'/device'); + if ($devices['result'] == 1) { + debug("get_devices: got: ".$devices['data'], 8); + return trim($devices['data']); + } + return ''; + } + + // Get the voicemail context for this user + // + function get_voicemail_context($user) { + debug("get_voicemail_context: user: $user", 8); + global $agi; + + $devices = $agi->database_get('AMPUSER',$user.'/voicemail'); + if ($devices['result'] == 1) { + return trim($devices['data']); + } + return 'novm'; + } + + // Get the user currently associated with this device or blank if none + // + function get_user($device) { + debug("get_user: device: $device", 8); + global $agi; + + $user = $agi->database_get('DEVICE',$device.'/user'); + if ($user['result'] == 1 && trim($user['data']) != 'none') { + debug("get_user: got: ".$user['data'], 8); + return trim($user['data']); + } + debug("get_user: no user found", 8); + return ''; + } + + function get_followme_state($user) { + global $agi; + + $fm_state = $agi->database_get('AMPUSER',$user.'/followme/ddial'); + if ($fm_state['result'] != 1) { + $ret = 'INVALID'; + } else { + switch (trim($fm_state['data'])) { + case 'EXTENSION': + $ret = 'NOT_INUSE'; + break; + case 'DIRECT': + $ret = 'INUSE'; + break; + default: + $ret = 'INVALID'; + } + } + debug("get_followme_state: user $user got state ".$fm_state['data']." returning $ret",8); + return $ret; + } + + function get_dnd_state($user) { + global $agi; + + $dnd_state = $agi->database_get('DND',$user); + if ($dnd_state['result'] != 1) { + $ret = 'NOT_INUSE'; + } else { + if (strtoupper(trim($dnd_state['data'])) == 'YES') { + $ret = 'INUSE'; + } else { + $ret = 'NOT_INUSE'; + } + } + debug("get_dnd_state: user $user got state ".$dnd_state['data']." returning $ret",8); + return $ret; + } + + // Inserts device info into AMPUSER object for specificed user + // + function set_user_devices($user, $devices) { + debug("set_user_devices: user: $user, devices: $devices", 8); + global $agi; + if (empty($devices)) { + debug("No more devices associated with $user, deletting /device key", 8); + $agi->database_del('AMPUSER',$user.'/device'); + } else { + debug("set_user_devices: assigning $devices to $user /device key", 8); + $agi->database_put('AMPUSER',$user.'/device',$devices); + } + } + + // Inserts user into DEVICE object for specified device + // + function set_device_user($device, $user) { + debug("set_device_user: device: $device, user: $user", 8); + global $agi; + $agi->database_put('DEVICE',$device.'/user',$user); + } + + // Get a channel variable + // + function get_var($value) { + global $agi; + + $r = $agi->get_variable( $value ); + if ($r['result'] == 1) { + $result = $r['data']; + return trim($result); + } + return ''; + } + + function debug($string, $level=3) { + global $agi; + $agi->verbose($string, $level); + } Index: /modules/branches/2.6/core/agi-bin/enumlookup.agi =================================================================== --- /modules/branches/2.6/core/agi-bin/enumlookup.agi (revision 6188) +++ /modules/branches/2.6/core/agi-bin/enumlookup.agi (revision 6188) @@ -0,0 +1,146 @@ +#!/usr/bin/php -q + +// Released under Version 2 of the GPL +// Originally written for use with FreePBX. + +// Based on e164.org's enum.php script, available on http://www.e164.org/enum.phps + +/* --------WARNING--------- + * + * This script is auto-copied from an included module and will get overwritten. + * If you modify it, you must change it to write only, in the agi-bin directory, + * to keep it from getting changed. + */ + +require_once "phpagi.php"; + +$AGI = new AGI(); +$lookup = get_var( $AGI, "DIAL_NUMBER" ); + +$enums = Array( + 'e164.org', + //'e164.arpa', + //'e164.info', +); + +// Go through the ENUM providers and look for the number. + +$dialstr = ""; + +foreach ($enums as $enum) { + // Are we using php5 and can use get_dns_record? + if (function_exists("dns_get_record")) { + $arr = get_php5($lookup, $enum); + // else, do we have Pear Net DNS? + // Disabled, as I couldn't easily get it working on my machine + //} elseif ((@include 'Net/DNS.php') =='OK') { + // $arr = get_pear($arpa); + } else { + @exec('dig -h > /dev/null 2>&1 ', $res, $var); + if ($var != 127) { + $arr = get_dig($lookup, $enum); + } else { + $AGI->verbose("ENUM LOOKUPS DISABLED due to php5 not being installed AND no dig command", "0"); + } + } + if (isset($arr[0])) { + foreach($arr as $key => $row) { + $order[$key] = $row["order"]; + $prio[$key] = $row["prio"]; + $nextURI[] = $row['URI']; + $row['URI'] = count($nextURI) - 1; + $arr[$key] = $row; + } + array_multisort($order, SORT_ASC, SORT_NUMERIC, $prio, SORT_ASC, SORT_NUMERIC, $arr); + foreach ($arr as $key => $row) { + if (eregi('SIP|IAX', $row['tech'])) { + $URI = $row['URI']; + $dialstr .= $nextURI[$URI]."|"; + } + } + } +} + +$AGI->verbose("Setting DIALARR to $dialstr", 3); +$AGI->set_variable("DIALARR", $dialstr); + +function get_dig($lookup, $enum) { + global $AGI; + + $AGI->verbose("Looking up $lookup on $enum via shell command DIG",3);; + $arpa = ""; + for ($i = 0; $i < strlen($lookup); $i++) { + $arpa = $lookup[$i].".".$arpa; + } + $lines = trim(`/usr/bin/dig +short ${arpa}${enum} naptr`); + $lines = explode("\n", $lines); + foreach($lines as $line) { + $line = trim($line); + if (preg_match("/^;;/", $line)) + continue; + if (!isset($arr)) $arr = array(); + $line = str_replace("\t", " ", $line); + while(strstr($line, " ")) + $line = str_replace(" ", " ", $line); + $line = str_replace("\"", "", $line); + $line = str_replace("\'", "", $line); + $line = str_replace(" ", "|", $line); + $bits = explode("|", $line); + $bit = explode("!", stripslashes($bits[4])); + $URI = ereg_replace($bit[1], $bit[2], "+".$lookup); + if($URI[3] == ":") + $URI[3] = "/"; + if($URI[4] == ":") + $URI[4] = "/"; + $arr[] = array("order" => $bits[0], "prio" => $bits[1], "tech" => $bits[3], "URI" => $URI); + } + if (isset($arr[0])) { + return $arr; + } else { + return null; + } +} + +function get_php5($lookup, $enum) { + global $AGI; + + $AGI->verbose("Looking up $lookup on $enum via dns_get_record",3); + + $arpa = ""; + for ($i = 0; $i < strlen($lookup); $i++) { + $arpa = $lookup[$i].".".$arpa; + } + $res = dns_get_record("$arpa$enum", DNS_NAPTR); + foreach ($res as $entry) { + if (!isset($arr)) $arr = array(); + $bit = explode("!", $entry['regex']); + $URI = ereg_replace($bit[1], $bit[2], "+".$lookup); + if($URI[3] == ":") $URI[3] = "/"; + if($URI[4] == ":") $URI[4] = "/"; + $arr[] = array("order" => $entry['order'], "prio" => $entry['pref'], "tech" => $entry['services'], "URI" => $URI); + } + if (isset($arr[0])) { + return $arr; + } else { + return null; + } +} + + +// helper functions +function get_var( $agi, $value) +{ + $r = $agi->get_variable( $value ); + + if ($r['result'] == 1) + { + $result = $r['data']; + return $result; + } + else return ''; +} + +?> Index: /modules/branches/2.6/core/functions.inc.php =================================================================== --- /modules/branches/2.6/core/functions.inc.php (revision 7014) +++ /modules/branches/2.6/core/functions.inc.php (revision 7014) @@ -0,0 +1,4827 @@ +generate_sip_general_additional($version); + break; + case 'sip_additional.conf': + return $this->generate_sip_additional($version); + break; + case 'sip_registrations.conf': + return $this->generate_sip_registrations($version); + break; + case 'iax_general_additional.conf': + return $this->generate_iax_general_additional($version); + break; + case 'iax_additional.conf': + return $this->generate_iax_additional($version); + break; + case 'iax_registrations.conf': + return $this->generate_iax_registrations($version); + break; + case 'chan_dahdi_additional.conf': + return $this->generate_zapata_additional($version); + break; + case 'zapata_additional.conf': + return $this->generate_zapata_additional($version); + break; + case 'features_general_additional.conf': + return $this->generate_featuregeneral_additional($version); + break; + case 'features_applicationmap_additional.conf': + return $this->generate_applicationmap_additional($version); + break; + case 'features_featuremap_additional.conf': + return $this->generate_featuremap_additional($version); + break; + } + } + + function addSipGeneral($key, $value) { + $this->_sip_general[] = array('key' => $key, 'value' => $value); + } + + function generate_sip_general_additional($ast_version) { + $output = ''; + + if (isset($this->_sip_general) && is_array($this->_sip_general)) { + foreach ($this->_sip_general as $values) { + $output .= $values['key']."=".$values['value']."\n"; + } + } + return $output; + } + + function addIaxGeneral($key, $value) { + $this->_iax_general[] = array('key' => $key, 'value' => $value); + } + + function generate_iax_general_additional($ast_version) { + $output = ''; + + if (isset($this->_iax_general) && is_array($this->_iax_general)) { + foreach ($this->_iax_general as $values) { + $output .= $values['key']."=".$values['value']."\n"; + } + } + return $output; + } + + function addFeatureGeneral($key, $value) { + $this->_featuregeneral[] = array('key' => $key, 'value' => $value); + } + + function generate_featuregeneral_additional($ast_version) { + $output = ''; + + if (isset($this->_featuregeneral) && is_array($this->_featuregeneral)) { + foreach ($this->_featuregeneral as $values) { + $output .= $values['key']."=".$values['value']."\n"; + } + } + return $output; + } + + function addFeatureMap($key, $value) { + $this->_featuremap[] = array('key' => $key, 'value' => $value); + } + + function generate_featuremap_additional($ast_version) { + $output = ''; + + if (isset($this->_featuremap) && is_array($this->_featuremap)) { + foreach ($this->_featuremap as $values) { + $output .= $values['key']."=".$values['value']."\n"; + } + } + return $output; + } + + function addApplicationMap($key, $value) { + $this->_applicationmap[] = array('key' => $key, 'value' => $value); + } + + function generate_applicationmap_additional($ast_version) { + $output = ''; + + if (isset($this->_applicationmap) && is_array($this->_applicationmap)) { + foreach ($this->_applicationmap as $values) { + $output .= $values['key']."=".$values['value']."\n"; + } + } + return $output; + } + + function generate_sip_additional($ast_version) { + global $db; + + $table_name = "sip"; + $additional = ""; + $output = ""; + + // Asterisk 1.4 requires call-limit be set for hints to work properly + // + if (version_compare($ast_version, "1.4", "ge")) { + $call_limit = "call-limit=50\n"; + $ver12 = false; + } else { + $call_limit = ""; + $ver12 = true; + } + + $sql = "SELECT keyword,data from $table_name where id=-1 and keyword <> 'account' and flags <> 1"; + $results = $db->getAll($sql, DB_FETCHMODE_ASSOC); + if(DB::IsError($results)) { + die($results->getMessage()); + } + foreach ($results as $result) { + if ($ver12) { + $additional .= $result['keyword']."=".$result['data']."\n"; + } else { + $option = $result['data']; + switch (strtolower($result['keyword'])) { + case 'insecure': + if ($option == 'very') + $additional .= "insecure=port,invite\n"; + else if ($option == 'yes') + $additional .= "insecure=port\n"; + else + $additional .= $result['keyword']."=$option\n"; + break; + case 'allow': + case 'disallow': + if ($option != '') + $additional .= $result['keyword']."=$option\n"; + break; + default: + $additional .= $result['keyword']."=$option\n"; + } + } + } + + $sql = "SELECT data,id from $table_name where keyword='account' and flags <> 1 group by data"; + $results = $db->getAll($sql, DB_FETCHMODE_ASSOC); + if(DB::IsError($results)) { + die($results->getMessage()); + } + + foreach ($results as $result) { + $account = $result['data']; + $id = $result['id']; + $output .= "[$account]\n"; + + $sql = "SELECT keyword,data from $table_name where id='$id' and keyword <> 'account' and flags <> 1 order by flags, keyword DESC"; + $results2_pre = $db->getAll($sql, DB_FETCHMODE_ASSOC); + if(DB::IsError($results2_pre)) { + die($results2->getMessage()); + } + + // Move all 'disallow=all' to the top to avoid errors + // + $results2 = array(); + foreach ($results2_pre as $element) { + $options = explode("&", $element['data']); + foreach ($options as $option) { + if ($element['keyword'] == 'disallow' && $option == 'all') { + array_unshift($results2,array('keyword'=>$element['keyword'],'data'=>$option)); + } else { + $results2[] = array('keyword'=>$element['keyword'],'data'=>$option); + } + } + } + unset($results2_pre); + + foreach ($results2 as $result2) { + $option = $result2['data']; + if ($ver12) { + $output .= $result2['keyword']."=$option\n"; + } else { + switch (strtolower($result2['keyword'])) { + case 'insecure': + if ($option == 'very') + $output .= "insecure=port,invite\n"; + else if ($option == 'yes') + $output .= "insecure=port\n"; + else + $output .= $result2['keyword']."=$option\n"; + break; + case 'allow': + case 'disallow': + if ($option != '') + $output .= $result2['keyword']."=$option\n"; + break; + case 'record_in': + case 'record_out': + break; + default: + $output .= $result2['keyword']."=$option\n"; + } + } + } + if ($call_limit && (substr($id,0,4) != "9999" | $id < 99990)) { + + $output .= $call_limit; + } + $output .= $additional."\n"; + } + return $output; + } + + function generate_sip_registrations($ast_version) { + global $db; + + $table_name = "sip"; + $output = ""; + + // items with id like 9999999% get put in registrations file + // + $sql = "SELECT keyword,data from $table_name where id LIKE '9999999%' and keyword <> 'account' and flags <> 1"; + $results = $db->getAll($sql, DB_FETCHMODE_ASSOC); + if(DB::IsError($results)) { + die($results->getMessage()); + } + + foreach ($results as $result) { + $output .= $result['keyword']."=".$result['data']."\n"; + } + + return $output; + } + + function generate_iax_additional($ast_version) { + global $db; + + $table_name = "iax"; + $additional = ""; + $output = ""; + + $ver12 = version_compare($ast_version, '1.4', 'lt'); + + $sql = "SELECT keyword,data from $table_name where id=-1 and keyword <> 'account' and flags <> 1"; + $results = $db->getAll($sql, DB_FETCHMODE_ASSOC); + if(DB::IsError($results)) { + die($results->getMessage()); + } + foreach ($results as $result) { + if ($ver12) { + $additional .= $result['keyword']."=".$result['data']."\n"; + } else { + $option = $result['data']; + switch ($result['keyword']) { + case 'notransfer': + if (strtolower($option) == 'yes') { + $additional .= "transfer=no\n"; + } else if (strtolower($option) == 'no') { + $additional .= "transfer=yes\n"; + } else if (strtolower($option) == 'mediaonly') { + $additional .= "transfer=mediaonly\n"; + } else { + $additional .= $result['keyword']."=$option\n"; + } + break; + case 'allow': + case 'disallow': + if ($option != '') + $additional .= $result['keyword']."=$option\n"; + break; + default: + $additional .= $result['keyword']."=$option\n"; + } + } + } + + $sql = "SELECT data,id from $table_name where keyword='account' and flags <> 1 group by data"; + $results = $db->getAll($sql, DB_FETCHMODE_ASSOC); + if(DB::IsError($results)) { + die($results->getMessage()); + } + + foreach ($results as $result) { + $account = $result['data']; + $id = $result['id']; + $output .= "[$account]\n"; + + $sql = "SELECT keyword,data from $table_name where id='$id' and keyword <> 'account' and flags <> 1 order by flags, keyword DESC"; + $results2_pre = $db->getAll($sql, DB_FETCHMODE_ASSOC); + if(DB::IsError($results2)) { + die($results2_pre->getMessage()); + } + + // Move all 'disallow=all' to the top to avoid errors + // + $results2 = array(); + foreach ($results2_pre as $element) { + $options = explode("&", $element['data']); + foreach ($options as $option) { + if ($element['keyword'] == 'disallow' && $option == 'all') { + array_unshift($results2,array('keyword'=>$element['keyword'],'data'=>$option)); + } else { + $results2[] = array('keyword'=>$element['keyword'],'data'=>$option); + } + } + } + unset($results2_pre); + + foreach ($results2 as $result2) { + $option = $result2['data']; + if ($ver12) { + $output .= $result2['keyword']."=$option\n"; + } else { + switch ($result2['keyword']) { + case 'notransfer': + if (strtolower($option) == 'yes') { + $output .= "transfer=no\n"; + } else if (strtolower($option) == 'no') { + $output .= "transfer=yes\n"; + } else if (strtolower($option) == 'mediaonly') { + $output .= "transfer=mediaonly\n"; + } else { + $output .= $result2['keyword']."=$option\n"; + } + break; + case 'allow': + case 'disallow': + if ($option != '') + $output .= $result2['keyword']."=$option\n"; + break; + case 'record_in': + case 'record_out': + break; + default: + $output .= $result2['keyword']."=$option\n"; + } + } + } + $output .= $additional."\n"; + } + return $output; + } + + function generate_iax_registrations($ast_version) { + global $db; + + $table_name = "iax"; + $output = ""; + + // items with id like 9999999% get put in the registration file + // + $sql = "SELECT keyword,data from $table_name where id LIKE '9999999%' and keyword <> 'account' and flags <> 1"; + $results = $db->getAll($sql, DB_FETCHMODE_ASSOC); + if(DB::IsError($results)) { + die($results->getMessage()); + } + + foreach ($results as $result) { + $output .= $result['keyword']."=".$result['data']."\n"; + } + + return $output; + } + + function generate_zapata_additional($ast_version) { + global $db; + + $table_name = "zap"; + + $additional = ""; + $output = ''; + + $sql = "SELECT keyword,data from $table_name where id=-1 and keyword <> 'account' and flags <> 1"; + $results = $db->getAll($sql, DB_FETCHMODE_ASSOC); + if(DB::IsError($results)) { + die($results->getMessage()); + } + foreach ($results as $result) { + $additional .= $result['keyword']."=".$result['data']."\n"; + } + + $sql = "SELECT data,id from $table_name where keyword='account' and flags <> 1 group by data"; + $results = $db->getAll($sql, DB_FETCHMODE_ASSOC); + if(DB::IsError($results)) { + die($results->getMessage()); + } + + foreach ($results as $result) { + $account = $result['data']; + $id = $result['id']; + $output .= ";;;;;;[$account]\n"; + + $sql = "SELECT keyword,data from $table_name where id=$id and keyword <> 'account' and flags <> 1 order by keyword DESC"; + $results2 = $db->getAll($sql, DB_FETCHMODE_ASSOC); + if(DB::IsError($results2)) { + die($results2->getMessage()); + } + $zapchannel=""; + foreach ($results2 as $result2) { + switch ($result2['keyword']) { + case 'channel': + $zapchannel = $result2['data']; + break; + + // These are not zapata.conf variables so keep out of file + case 'record_out': + case 'record_in': + case 'dial': + break; + default: + $output .= $result2['keyword']."=".$result2['data']."\n"; + } + } + $output .= "channel=>$zapchannel\n"; + $output .= $additional."\n"; + } + return $output; + } +} + +// The destinations this module provides +// returns a associative arrays with keys 'destination' and 'description' +function core_destinations() { + //static destinations + $extens = array(); + $category = 'Terminate Call'; + $extens[] = array('destination' => 'app-blackhole,hangup,1', 'description' => 'Hangup', 'category' => $category); + $extens[] = array('destination' => 'app-blackhole,congestion,1', 'description' => 'Congestion', 'category' => $category); + $extens[] = array('destination' => 'app-blackhole,busy,1', 'description' => 'Busy', 'category' => $category); + $extens[] = array('destination' => 'app-blackhole,zapateller,1', 'description' => 'Play SIT Tone (Zapateller)', 'category' => $category); + $extens[] = array('destination' => 'app-blackhole,musiconhold,1', 'description' => 'Put caller on hold forever', 'category' => $category); + $extens[] = array('destination' => 'app-blackhole,ring,1', 'description' => 'Play ringtones to caller until they hangup', 'category' => $category); + + //get the list of meetmes + $results = core_users_list(); + + if (isset($results) && function_exists('voicemail_getVoicemail')) { + //get voicemail + $uservm = voicemail_getVoicemail(); + $vmcontexts = array_keys($uservm); + foreach ($results as $thisext) { + $extnum = $thisext[0]; + // search vm contexts for this extensions mailbox + foreach ($vmcontexts as $vmcontext) { + if(isset($uservm[$vmcontext][$extnum])){ + //$vmname = $uservm[$vmcontext][$extnum]['name']; + //$vmboxes[$extnum] = array($extnum, '"' . $vmname . '" <' . $extnum . '>'); + $vmboxes[$extnum] = true; + } + } + } + } + + // return an associative array with destination and description + // core provides both users and voicemail boxes as destinations + if (isset($results)) { + foreach($results as $result) { + $extens[] = array('destination' => 'from-did-direct,'.$result['0'].',1', 'description' => ' <'.$result['0'].'> '.$result['1'], 'category' => 'Extensions'); + if(isset($vmboxes[$result['0']])) { + $extens[] = array('destination' => 'ext-local,vmb'.$result['0'].',1', 'description' => '<'.$result[0].'> '.$result[1].' (busy)', 'category' => 'Voicemail'); + $extens[] = array('destination' => 'ext-local,vmu'.$result['0'].',1', 'description' => '<'.$result[0].'> '.$result[1].' (unavail)', 'category' => 'Voicemail'); + $extens[] = array('destination' => 'ext-local,vms'.$result['0'].',1', 'description' => '<'.$result[0].'> '.$result[1].' (no-msg)', 'category' => 'Voicemail'); + } + } + } + + if (isset($extens)) + return $extens; + else + return null; +} + +function core_getdest($exten) { + $dests[] = 'from-did-direct,'.$exten.',1'; + if (!function_exists('voicemail_mailbox_get')) { + return $dests; + } + $box = voicemail_mailbox_get($exten); + if ($box == null) { + return $dests; + } + $dests[] = 'ext-local,vmb'.$exten.',1'; + $dests[] = 'ext-local,vmu'.$exten.',1'; + $dests[] = 'ext-local,vms'.$exten.',1'; + + return $dests; +} + +function core_getdestinfo($dest) { + global $active_modules; + + // Check for Extension Number Destinations + // + if (substr(trim($dest),0,16) == 'from-did-direct,') { + $exten = explode(',',$dest); + $exten = $exten[1]; + $thisexten = core_users_get($exten); + if (empty($thisexten)) { + return array(); + } else { + //$type = isset($active_modules['announcement']['type'])?$active_modules['announcement']['type']:'setup'; + $display = ($amp_conf['AMPEXTENSIONS'] == "deviceanduser")?'users':'extensions'; + return array('description' => sprintf(_("User Extension %s: %s"),$exten,$thisexten['name']), + 'edit_url' => "config.php?type=setup&display=$display&extdisplay=".urlencode($exten)."&skip=0", + ); + } + + // Check for voicemail box destinations + // + } else if (substr(trim($dest),0,12) == 'ext-local,vm') { + $exten = explode(',',$dest); + $exten = substr($exten[1],3); + if (!function_exists('voicemail_mailbox_get')) { + return array(); + } + $thisexten = core_users_get($exten); + if (empty($thisexten)) { + return array(); + } + $box = voicemail_mailbox_get($exten); + if ($box == null) { + return array(); + } + $display = ($amp_conf['AMPEXTENSIONS'] == "deviceanduser")?'users':'extensions'; + return array('description' => 'User Extension '.$exten.': '.$thisexten['name'], + 'edit_url' => "config.php?type=setup&display=$display&extdisplay=".urlencode($exten)."&skip=0", + ); + + // Check for blackhole Termination Destinations + // + } else if (substr(trim($dest),0,14) == 'app-blackhole,') { + $exten = explode(',',$dest); + $exten = $exten[1]; + + switch ($exten) { + case 'hangup': + $description = 'Hangup'; + break; + case 'congestion': + $description = 'Congestion'; + break; + case 'busy': + $description = 'Busy'; + break; + case 'zapateller': + $description = 'Play SIT Tone (Zapateller)'; + break; + case 'musiconhold': + $description = 'Put caller on hold forever'; + break; + case 'ring': + $description = 'Play ringtones to caller'; + break; + default: + $description = false; + } + if ($description) { + return array('description' => 'Core: '.$description, + 'edit_url' => false, + ); + } else { + return array(); + } + + // None of the above, so not one of ours + // + } else { + return false; + } +} +/* Generates dialplan for "core" components (extensions & inbound routing) + We call this with retrieve_conf +*/ +function core_get_config($engine) { + global $ext; // is this the best way to pass this? + global $version; // this is not the best way to pass this, this should be passetd together with $engine + global $engineinfo; + global $amp_conf; + global $core_conf; + global $chan_dahdi; + + $modulename = "core"; + + switch($engine) { + case "asterisk": + + // Now add to sip_general_addtional.conf + // + if (isset($core_conf) && is_a($core_conf, "core_conf")) { + $core_conf->addSipGeneral('disallow','all'); + $core_conf->addSipGeneral('allow','ulaw'); + $core_conf->addSipGeneral('allow','alaw'); + $core_conf->addSipGeneral('context','from-sip-external'); + $core_conf->addSipGeneral('callerid','Unknown'); + $core_conf->addSipGeneral('notifyringing','yes'); + if (version_compare($version, '1.4', 'ge')) { + $core_conf->addSipGeneral('notifyhold','yes'); + $core_conf->addSipGeneral('limitonpeers','yes'); + $core_conf->addSipGeneral('tos_sip','cs3'); // Recommended setting from doc/ip-tos.txt + $core_conf->addSipGeneral('tos_audio','ef'); // Recommended setting from doc/ip-tos.txt + $core_conf->addSipGeneral('tos_video','af41'); // Recommended setting from doc/ip-tos.txt + } else { + $core_conf->addSipGeneral('tos','0x68'); // This really doesn't do anything with astersk not running as root + } + $core_conf->addIaxGeneral('disallow','all'); + $core_conf->addIaxGeneral('allow','ulaw'); + $core_conf->addIaxGeneral('allow','alaw'); + $core_conf->addIaxGeneral('allow','gsm'); + $core_conf->addIaxGeneral('mailboxdetail','yes'); + if (version_compare($version, '1.4', 'ge')) { + $core_conf->addIaxGeneral('tos','ef'); // Recommended setting from doc/ip-tos.txt + } + + $fcc = new featurecode($modulename, 'blindxfer'); + $code = $fcc->getCodeActive(); + unset($fcc); + if ($code != '') { + $core_conf->addFeatureMap('blindxfer',$code); + } + + $fcc = new featurecode($modulename, 'atxfer'); + $code = $fcc->getCodeActive(); + unset($fcc); + if ($code != '') { + $core_conf->addFeatureMap('atxfer',$code); + } + + $fcc = new featurecode($modulename, 'automon'); + $code = $fcc->getCodeActive(); + unset($fcc); + if ($code != '') { + $core_conf->addFeatureMap('automon',$code); + } + + $fcc = new featurecode($modulename, 'disconnect'); + $code = $fcc->getCodeActive(); + unset($fcc); + if ($code != '') { + $core_conf->addFeatureMap('disconnect',$code); + } + + $fcc = new featurecode($modulename, 'pickupexten'); + $code = $fcc->getCodeActive(); + unset($fcc); + if ($code != '') { + $core_conf->addFeatureGeneral('pickupexten',$code); + } + } + + // FeatureCodes + $fcc = new featurecode($modulename, 'userlogon'); + $fc_userlogon = $fcc->getCodeActive(); + unset($fcc); + + $fcc = new featurecode($modulename, 'userlogoff'); + $fc_userlogoff = $fcc->getCodeActive(); + unset($fcc); + + $fcc = new featurecode($modulename, 'zapbarge'); + $fc_zapbarge = $fcc->getCodeActive(); + unset($fcc); + + $fcc = new featurecode($modulename, 'chanspy'); + $fc_chanspy = $fcc->getCodeActive(); + unset($fcc); + + $fcc = new featurecode($modulename, 'simu_pstn'); + $fc_simu_pstn = $fcc->getCodeActive(); + unset($fcc); + + $fcc = new featurecode($modulename, 'simu_fax'); + $fc_simu_fax = $fcc->getCodeActive(); + unset($fcc); + + $fcc = new featurecode($modulename, 'pickup'); + $fc_pickup = $fcc->getCodeActive(); + unset($fcc); + + // Log on / off -- all in one context + if ($fc_userlogoff != '' || $fc_userlogon != '') { + $ext->addInclude('from-internal-additional', 'app-userlogonoff'); // Add the include from from-internal + + if ($fc_userlogoff != '') { + $ext->add('app-userlogonoff', $fc_userlogoff, '', new ext_macro('user-logoff')); + $ext->add('app-userlogonoff', $fc_userlogoff, '', new ext_hangup('')); + } + + if ($fc_userlogon != '') { + $ext->add('app-userlogonoff', $fc_userlogon, '', new ext_macro('user-logon')); + $ext->add('app-userlogonoff', $fc_userlogon, '', new ext_hangup('')); + + $clen = strlen($fc_userlogon); + $fc_userlogon = "_$fc_userlogon."; + $ext->add('app-userlogonoff', $fc_userlogon, '', new ext_macro('user-logon,${EXTEN:'.$clen.'}')); + $ext->add('app-userlogonoff', $fc_userlogon, '', new ext_hangup('')); + } + } + + // Call pickup using app_pickup - Note that '**xtn' is hard-coded into the GXPs and SNOMs as a number to dial + // when a user pushes a flashing BLF. + // + // We need to add ringgoups to this so that if an extension is part of a ringgroup, we can try to pickup that + // extension by trying the ringgoup which is what the pickup application is going to respond to. + // + // NOTICE: this may be confusing, we check if this is a BRI build of Asterisk and use dpickup instead of pickup + // if it is. So we simply assign the varaible $ext_pickup which one it is, and use that variable when + // creating all the extnesions below. So those are "$ext_pickup" on purpose! + // + if ($fc_pickup != '') { + $ext->addInclude('from-internal-additional', 'app-pickup'); + $fclen = strlen($fc_pickup); + $ext_pickup = (strstr($engineinfo['raw'], 'BRI')) ? 'ext_dpickup' : 'ext_pickup'; + + $fcc = new featurecode('paging', 'intercom-prefix'); + $intercom_code = $fcc->getCodeActive(); + unset($fcc); + + + $ext->add('app-pickup', "_$fc_pickup.", '', new ext_NoOp('Attempt to Pickup ${EXTEN:'.$fclen.'} by ${CALLERID(num)}')); + $ext->add('app-pickup', "_$fc_pickup.", '', new $ext_pickup('${EXTEN:'.$fclen.'}')); + $ext->add('app-pickup', "_$fc_pickup.", '', new $ext_pickup('${EXTEN:'.$fclen.'}@from-internal')); + $ext->add('app-pickup', "_$fc_pickup.", '', new $ext_pickup('${EXTEN:'.$fclen.'}@from-did-direct')); + $ext->add('app-pickup', "_$fc_pickup.", '', new $ext_pickup('FMPR-${EXTEN:'.$fclen.'}')); + $ext->add('app-pickup', "_$fc_pickup.", '', new $ext_pickup('FMPR-${EXTEN:'.$fclen.'}@from-internal')); + $ext->add('app-pickup', "_$fc_pickup.", '', new $ext_pickup('FMPR-${EXTEN:'.$fclen.'}@from-did-direct')); + if ($intercom_code != '') { + $ext->add('app-pickup', "_{$fc_pickup}{$intercom_code}.", '', new $ext_pickup('${EXTEN:'.strlen($fc_pickup.$intercom_code).'}')); + $ext->add('app-pickup', "_{$fc_pickup}{$intercom_code}.", '', new $ext_pickup('${EXTEN:'.strlen($fc_pickup.$intercom_code).'}@from-internal')); + $ext->add('app-pickup', "_{$fc_pickup}{$intercom_code}.", '', new $ext_pickup('${EXTEN:'.strlen($fc_pickup.$intercom_code).'}@from-did-direct')); + $ext->add('app-pickup', "_{$fc_pickup}{$intercom_code}.", '', new $ext_pickup('FMPR-${EXTEN:'.strlen($fc_pickup.$intercom_code).'}')); + $ext->add('app-pickup', "_{$fc_pickup}{$intercom_code}.", '', new $ext_pickup('FMPR-${EXTEN:'.strlen($fc_pickup.$intercom_code).'}@from-internal')); + $ext->add('app-pickup', "_{$fc_pickup}{$intercom_code}.", '', new $ext_pickup('FMPR-${EXTEN:'.strlen($fc_pickup.$intercom_code).'}@from-did-direct')); + } + $ext->add('app-pickup', "_$fc_pickup.", '', new ext_hangup('')); + // In order to do call pickup in ringgroups, we will need to try the ringgoup number + // when doing call pickup for that ringgoup so we must see who is a member of what ringgroup + // and then generate the dialplan + // + $rg_members = array(); + if (function_exists('ringgroups_list')) { + $rg_list = ringgroups_list(true); + foreach ($rg_list as $item) { + $thisgrp = ringgroups_get($item['grpnum']); + $grpliststr = $thisgrp['grplist']; + $grplist = explode("-", $grpliststr); + foreach ($grplist as $exten) { + if (strpos($exten,"#") === false) { + $rg_members[$exten][] = $item['grpnum']; + } + } + } + } + // Now we have a hash of extensions and what ringgoups they are members of + // so we need to generate the callpickup dialplan for these specific extensions + // to try the ringgoup. + foreach ($rg_members as $exten => $grps) { + $ext->add('app-pickup', "$fc_pickup".$exten, '', new $ext_pickup($exten)); + $ext->add('app-pickup', "$fc_pickup".$exten, '', new $ext_pickup($exten.'@from-internal')); + $ext->add('app-pickup', "$fc_pickup".$exten, '', new $ext_pickup($exten.'@from-did-direct')); + $ext->add('app-pickup', "$fc_pickup".$exten, '', new $ext_pickup('FMPR-'.$exten)); + $ext->add('app-pickup', "$fc_pickup".$exten, '', new $ext_pickup('FMPR-'.$exten.'@from-internal')); + $ext->add('app-pickup', "$fc_pickup".$exten, '', new $ext_pickup('FMPR-'.$exten.'@from-did-direct')); + foreach ($grps as $grp) { + $ext->add('app-pickup', "$fc_pickup".$exten, '', new $ext_pickup($grp.'@from-internal')); + } + $ext->add('app-pickup', "$fc_pickup".$exten, '', new ext_hangup('')); + } + } + + + // zap barge + if ($fc_zapbarge != '') { + $ext->addInclude('from-internal-additional', 'app-zapbarge'); // Add the include from from-internal + + $ext->add('app-zapbarge', $fc_zapbarge, '', new ext_macro('user-callerid')); + $ext->add('app-zapbarge', $fc_zapbarge, '', new ext_setvar('GROUP()','${CALLERID(number)}')); + $ext->add('app-zapbarge', $fc_zapbarge, '', new ext_answer('')); + $ext->add('app-zapbarge', $fc_zapbarge, '', new ext_wait(1)); + $ext->add('app-zapbarge', $fc_zapbarge, '', new ext_zapbarge('')); + $ext->add('app-zapbarge', $fc_zapbarge, '', new ext_hangup('')); + } + + // chan spy + if ($fc_chanspy != '') { + $ext->addInclude('from-internal-additional', 'app-chanspy'); // Add the include from from-internal + $ext->add('app-chanspy', $fc_chanspy, '', new ext_macro('user-callerid')); + $ext->add('app-chanspy', $fc_chanspy, '', new ext_answer('')); + $ext->add('app-chanspy', $fc_chanspy, '', new ext_wait(1)); + $ext->add('app-chanspy', $fc_chanspy, '', new ext_chanspy('')); + $ext->add('app-chanspy', $fc_chanspy, '', new ext_hangup('')); + } + + // Simulate options (ext-test) + if ($fc_simu_pstn != '' || $fc_simu_fax != '') { + $ext->addInclude('from-internal-additional', 'ext-test'); // Add the include from from-internal + + if ($fc_simu_pstn != '') { + if (ctype_digit($fc_simu_pstn)) { + $ext->add('ext-test', $fc_simu_pstn, '', new ext_goto('1', '${EXTEN}', 'from-pstn')); + } else { + $ext->add('ext-test', $fc_simu_pstn, '', new ext_goto('1', 's', 'from-pstn')); + } + } + + if ($fc_simu_fax != '') { + $ext->add('ext-test', $fc_simu_fax, '', new ext_goto('1', 'in_fax', 'ext-fax')); + } + + $ext->add('ext-test', 'h', '', new ext_macro('hangupcall')); + } + + /* Always have Fax detection in ext-did, no matter what */ + + $ext->addInclude('ext-did', 'ext-did-0001'); // Add the include from from-internal + $ext->addInclude('ext-did', 'ext-did-0002'); // Add the include from from-internal + $ext->add('ext-did-0001', 'fax', '', new ext_goto('1','in_fax','ext-fax')); + $ext->add('ext-did-0002', 'fax', '', new ext_goto('1','in_fax','ext-fax')); + $ext->add('ext-did', 'fax', '', new ext_goto('1','in_fax','ext-fax')); + + /* inbound routing extensions */ + $didlist = core_did_list(); + if(is_array($didlist)){ + $catchall = false; + $catchall_context='ext-did-catchall'; + foreach($didlist as $item) { + if (trim($item['destination']) == '') { + continue; + } + $exten = trim($item['extension']); + $cidnum = trim($item['cidnum']); + + // If the user put in just a cid number for routing, we add _. pattern to catch + // all DIDs with that CID number. Asterisk will complain about _. being dangerous + // but we don't want to limit this to just numberic as someone may be trying to + // route a non-numeric did + // + if ($cidnum != '' && $exten == '') { + $exten = '_.'; + $pricid = ($item['pricid']) ? true:false; + } else if (($cidnum != '' && $exten != '') || ($cidnum == '' && $exten == '')) { + $pricid = true; + } else { + $pricid = false; + } + $context = ($pricid) ? "ext-did-0001":"ext-did-0002"; + + $exten = (empty($exten)?"s":$exten); + $exten = $exten.(empty($cidnum)?"":"/".$cidnum); //if a CID num is defined, add it + + $ext->add($context, $exten, '', new ext_setvar('__FROM_DID','${EXTEN}')); + // always set callerID name + $ext->add($context, $exten, '', new ext_gotoif('$[ "${CALLERID(name)}" != "" ] ','cidok')); + $ext->add($context, $exten, '', new ext_setvar('CALLERID(name)','${CALLERID(num)}')); + $ext->add($context, $exten, 'cidok', new ext_noop('CallerID is ${CALLERID(all)}')); + + if (!empty($item['mohclass']) && trim($item['mohclass']) != 'default') { + $ext->add($context, $exten, '', new ext_setmusiconhold($item['mohclass'])); + $ext->add($context, $exten, '', new ext_setvar('__MOHCLASS',$item['mohclass'])); + } + + // If we require RINGING, signal it as soon as we enter. + if ($item['ringing'] === "CHECKED") { + $ext->add($context, $exten, '', new ext_ringing('')); + } + if ($item['delay_answer']) { + $ext->add($context, $exten, '', new ext_wait($item['delay_answer'])); + } + + if ($exten == "s") { + //if the exten is s, then also make a catchall for undefined DIDs + $catchaccount = "_.".(empty($cidnum)?"":"/".$cidnum); + if ($catchaccount =="_." && ! $catchall) { + $catchall = true; + $ext->add($catchall_context, $catchaccount, '', new ext_NoOp('Catch-All DID Match - Found ${EXTEN} - You probably want a DID for this.')); + $ext->add($catchall_context, $catchaccount, '', new ext_goto('1','s','ext-did')); + } + } + + if ($item['faxexten'] != "default") { + $ext->add($context, $exten, '', new ext_setvar('FAX_RX',$item['faxexten'])); + } + if (!empty($item['faxemail'])) { + $ext->add($context, $exten, '', new ext_setvar('FAX_RX_EMAIL',$item['faxemail'])); + } + if ($item['answer'] == "1") { + $ext->add($context, $exten, '', new ext_answer('')); + $ext->add($context, $exten, '', new ext_wait($item['wait'])); + } + if ($item['answer'] == "2") { // NVFaxDetect + $ext->add($context, $exten, '', new ext_answer('')); + $ext->add($context, $exten, '', new ext_playtones('ring')); + $ext->add($context, $exten, '', new ext_nvfaxdetect($item['wait']."|t")); + } + if ($item['privacyman'] == "1") { + $ext->add($context, $exten, '', new ext_macro('privacy-mgr')); + } else { + // if privacymanager is used, this is not necessary as it will not let blocked/anonymous calls through + // otherwise, we need to save the caller presence to set it properly if we forward the call back out the pbx + // note - the indirect table could go away as of 1.4.20 where it is fixed so that SetCallerPres can take + // the raw format. + // + if (version_compare($version, "1.6", "lt")) { + $ext->add($context, $exten, '', new ext_setvar('__CALLINGPRES_SV','${CALLINGPRES_${CALLINGPRES}}')); + } else { + $ext->add($context, $exten, '', new ext_setvar('__CALLINGPRES_SV','${CALLERPRES()}')); + } + $ext->add($context, $exten, '', new ext_setcallerpres('allowed_not_screened')); + } + if (!empty($item['alertinfo'])) { + $ext->add($context, $exten, '', new ext_setvar("__ALERT_INFO", str_replace(';', '\;', $item['alertinfo']))); + } + // Add CID prefix, no need to do checks for existing pre-pends, this is an incoming did so this should + // be the first time the CID is manipulated. We set _RGPREFIX which is the same used throughout the different + // modules. + // + // TODO: If/When RGPREFIX is added to trunks, then see code in ringgroups to strip prefix if added here. + // + // TODO: core FreePBX documentation about this standard. (and probably rename from RGPREFIX to CIDPREFIX) + // + if (!empty($item['grppre'])) { + $ext->add($context, $exten, '', new ext_setvar('_RGPREFIX', $item['grppre'])); + $ext->add($context, $exten, '', new ext_setvar('CALLERID(name)','${RGPREFIX}${CALLERID(name)}')); + } + + //the goto destination + // destination field in 'incoming' database is backwards from what ext_goto expects + $goto_context = strtok($item['destination'],','); + $goto_exten = strtok(','); + $goto_pri = strtok(','); + $ext->add($context, $exten, '', new ext_goto($goto_pri,$goto_exten,$goto_context)); + + } + // If there's not a catchall, make one with an error message + if (!$catchall) { + $ext->add($catchall_context, 's', '', new ext_noop("No DID or CID Match")); + $ext->add($catchall_context, 's', 'a2', new ext_answer('')); + $ext->add($catchall_context, 's', '', new ext_wait('2')); + $ext->add($catchall_context, 's', '', new ext_playback('ss-noservice')); + $ext->add($catchall_context, 's', '', new ext_sayalpha('${FROM_DID}')); + $ext->add($catchall_context, 's', '', new ext_hangup('')); + $ext->add($catchall_context, '_.', '', new ext_setvar('__FROM_DID', '${EXTEN}')); + $ext->add($catchall_context, '_.', '', new ext_noop('Received an unknown call with DID set to ${EXTEN}')); + $ext->add($catchall_context, '_.', '', new ext_goto('a2','s')); + $ext->add($catchall_context, 'h', '', new ext_hangup('')); + } + + } + + // Now create macro-from-zaptel-nnn for each defined channel to route it to the DID routing + // Send it to from-trunk so it is handled as other dids would be handled. + // + foreach (core_zapchandids_list() as $row) { + $channel = $row['channel']; + $did = $row['did']; + + $zap_context = "macro-from-zaptel-{$channel}"; + $ext->add($zap_context, 's', '', new ext_noop('Entering '.$zap_context.' with DID = ${DID} and setting to: '.$did)); + $ext->add($zap_context, 's', '', new ext_setvar('__FROM_DID',$did)); + $ext->add($zap_context, 's', '', new ext_goto('1',$did,'from-trunk')); + } + + /* user extensions */ + $ext->addInclude('from-internal-additional','ext-local'); + + // If running in Dynamic mode, this will insert the hints through an Asterisk #exec call. + // which require "execincludes=yes" to be set in the [options] section of asterisk.conf + // + + $fcc = new featurecode('paging', 'intercom-prefix'); + $intercom_code = $fcc->getCodeActive(); + unset($fcc); + + $intercom_code = ($intercom_code == '') ? 'nointercom' : $intercom_code; + + // Pass the code so agi scripts like user_login_logout know to generate hints + // + $ext->addGlobal('INTERCOMCODE',$intercom_code); + + if ($amp_conf['DYNAMICHINTS']) { + if ($amp_conf['USEDEVSTATE'] && function_exists('donotdisturb_get_config')) { + $add_dnd = ' dnd'; + } else { + $add_dnd = ''; + } + $ext->addExec('ext-local',$amp_conf['AMPBIN'].'/generate_hints.php '.$intercom_code.$add_dnd); + } + $userlist = core_users_list(); + if (is_array($userlist)) { + foreach($userlist as $item) { + $exten = core_users_get($item[0]); + $vm = ((($exten['voicemail'] == "novm") || ($exten['voicemail'] == "disabled") || ($exten['voicemail'] == "")) ? "novm" : $exten['extension']); + + if (isset($exten['ringtimer']) && $exten['ringtimer'] != 0) + $ext->add('ext-local', $exten['extension'], '', new ext_setvar('__RINGTIMER',$exten['ringtimer'])); + + $ext->add('ext-local', $exten['extension'], '', new ext_macro('exten-vm',$vm.",".$exten['extension'])); + + if($vm != "novm") { + $ext->add('ext-local', $exten['extension'], '', new ext_goto('1','vmret')); + $ext->add('ext-local', '${VM_PREFIX}'.$exten['extension'], '', new ext_macro('vm',$vm.',DIRECTDIAL,${IVR_RETVM}')); + $ext->add('ext-local', '${VM_PREFIX}'.$exten['extension'], '', new ext_goto('1','vmret')); + $ext->add('ext-local', 'vmb'.$exten['extension'], '', new ext_macro('vm',$vm.',BUSY,${IVR_RETVM}')); + $ext->add('ext-local', 'vmb'.$exten['extension'], '', new ext_goto('1','vmret')); + $ext->add('ext-local', 'vmu'.$exten['extension'], '', new ext_macro('vm',$vm.',NOANSWER,${IVR_RETVM}')); + $ext->add('ext-local', 'vmu'.$exten['extension'], '', new ext_goto('1','vmret')); + $ext->add('ext-local', 'vms'.$exten['extension'], '', new ext_macro('vm',$vm.',NOMESSAGE,${IVR_RETVM}')); + $ext->add('ext-local', 'vms'.$exten['extension'], '', new ext_goto('1','vmret')); + } else { + // If we return from teh macro, it means we are suppose to return to the IVR + // + $ext->add('ext-local', $exten['extension'], '', new ext_goto('1','return','${IVR_CONTEXT}')); + } + + // Create the hints if running in normal mode + // + if (!$amp_conf['DYNAMICHINTS']) { + $hint = core_hint_get($exten['extension']); + $dnd_string = ($amp_conf['USEDEVSTATE'] && function_exists('donotdisturb_get_config')) ? "&Custom:DND".$exten['extension'] : ''; + if (!empty($hint)) { + $ext->addHint('ext-local', $exten['extension'], $hint.$dnd_string); + if ($intercom_code != '') { + $ext->addHint('ext-local', $intercom_code.$exten['extension'], $hint.$dnd_string); + } + } else if ($dnd_string) { + $ext->addHint('ext-local', $exten['extension'], "&Custom:DND".$exten['extension']); + if ($intercom_code != '') { + $ext->addHint('ext-local', $intercom_code.$exten['extension'], "&Custom:DND".$exten['extension']); + } + } + } + if ($exten['sipname']) { + $ext->add('ext-local', $exten['sipname'], '', new ext_goto('1',$item[0],'from-internal')); + } + // Now make a special context for the IVR inclusions of local extension dialing so that + // when people use the Queues breakout ability, and break out to someone's extensions, voicemail + // works. + // + $ivr_context = 'from-did-direct-ivr'; + $ext->add($ivr_context, $exten['extension'],'', new ext_execif('$["${BLKVM_OVERRIDE}" != ""]','dbDel','${BLKVM_OVERRIDE}')); + $ext->add($ivr_context, $exten['extension'],'', new ext_setvar('__NODEST', '')); + $ext->add($ivr_context, $exten['extension'],'', new ext_goto('1',$exten['extension'],'from-did-direct')); + if($vm != "novm") { + $ext->add($ivr_context, '${VM_PREFIX}'.$exten['extension'],'', new ext_execif('$["${BLKVM_OVERRIDE}" != ""]','dbDel','${BLKVM_OVERRIDE}')); + $ext->add($ivr_context, '${VM_PREFIX}'.$exten['extension'],'', new ext_setvar('__NODEST', '')); + $ext->add($ivr_context, '${VM_PREFIX}'.$exten['extension'],'', new ext_macro('vm',$vm.',DIRECTDIAL,${IVR_RETVM}')); + $ext->add($ivr_context, '${VM_PREFIX}'.$exten['extension'],'', new ext_gotoif('$["${IVR_RETVM}" = "RETURN" & "${IVR_CONTEXT}" != ""]','ext-local,vmret,playret')); + } + } + $ext->add('ext-local', 'vmret', '', new ext_gotoif('$["${IVR_RETVM}" = "RETURN" & "${IVR_CONTEXT}" != ""]','playret')); + $ext->add('ext-local', 'vmret', '', new ext_hangup('')); + $ext->add('ext-local', 'vmret', 'playret', new ext_playback('exited-vm-will-be-transfered&silence/1')); + $ext->add('ext-local', 'vmret', '', new ext_goto('1','return','${IVR_CONTEXT}')); + } + + + // create from-trunk context for each trunk that adds counts to channels + // + $trunklist = core_trunks_list(true); + if (is_array($trunklist)) { + foreach ($trunklist as $trunkprops) { + if (trim($trunkprops['value']) == 'on') { + // value of on is disabled and for zap we don't create a context + continue; + } + switch ($trunkprops['tech']) { + case 'DUNDI': + $macro_name = 'macro-dundi-'.substr($trunkprops['globalvar'],4); + $ext->addSwitch($macro_name,'DUNDI/'.$trunkprops['name']); + $ext->add($macro_name, 's', '', new ext_goto('1','${ARG1}')); + case 'IAX': + case 'IAX2': + case 'SIP': + $trunkgroup = $trunkprops['globalvar']; + $trunkcontext = "from-trunk-".strtolower($trunkprops['tech'])."-".$trunkprops['name']; + $ext->add($trunkcontext, '_.', '', new ext_setvar('GROUP()',$trunkgroup)); + $ext->add($trunkcontext, '_.', '', new ext_goto('1','${EXTEN}','from-trunk')); + break; + default: + } + } + } + + /* dialplan globals */ + // modules should NOT use the globals table to store anything! + // modules should use $ext->addGlobal("testvar","testval"); in their module_get_config() function instead + // I'm cheating for core functionality - do as I say, not as I do ;-) + + // Auto add these globals to give access to agi scripts and other needs, unless defined in the global table. + // + $amp_conf_globals = array( + "ASTETCDIR", + "ASTMODDIR", + "ASTVARLIBDIR", + "ASTAGIDIR", + "ASTSPOOLDIR", + "ASTRUNDIR", + "ASTLOGDIR", + "CWINUSEBUSY", + "AMPMGRUSER", + "AMPMGRPASS" + ); + + $disable_recording = false; + + $sql = "SELECT * FROM globals"; + $globals = sql($sql,"getAll",DB_FETCHMODE_ASSOC); + foreach($globals as $global) { + $value = $global['value']; + if ($chan_dahdi && substr($value, 0, 4) === 'ZAP/') { + $value = 'DAHDI/' . substr($value, 4); + } + $ext->addGlobal($global['variable'],$value); + + // now if for some reason we have a variable in the global table + // that is in our $amp_conf_globals list, then remove it so we + // don't duplicate, the sql table will take precedence + // + if (array_key_exists($global['variable'],$amp_conf_globals)) { + $rm_keys = array_keys($amp_conf_globals,$global['variable']); + foreach ($rm_keys as $index) { + unset($amp_conf_globals[$index]); + } + } + if (($global['variable'] == 'RECORDING_STATE') && (strtoupper($global['value']) == 'DISABLED')) { + $disable_recording = true; + } + } + foreach ($amp_conf_globals as $global) { + if (isset($amp_conf[$global])) { + $value = $amp_conf[$global]; + if ($value === true || $value === false) { + $value = ($value) ? 'true':'false'; + } + $ext->addGlobal($global, $value); + out("Added to globals: $global = $value"); + } + } + // Put the asterisk version in a global for agi etc. + $ext->addGlobal('ASTVERSION', $version); + // Put the use of chan_dahdi in a global for dialparties + $ext->addGlobal('ASTCHANDAHDI', $chan_dahdi ? '1' : '0'); + + // Create CallingPresTable to deal with difference that ${CALINGPRES} returns vs. what + // SetCallerPres() accepts. This is a workaround that gets resolved in 1.6 where + // function CALLINGPRES() is consistent. + // This should be fixed in 1.4.20 but for now we keep it in until 1.6 + // + if (version_compare($version, "1.6", "lt")) { + $ext->addGlobal('CALLINGPRES_0', 'allowed_not_screened'); + $ext->addGlobal('CALLINGPRES_1', 'allowed_passed_screen'); + $ext->addGlobal('CALLINGPRES_2', 'allowed_failed_screen'); + $ext->addGlobal('CALLINGPRES_3', 'allowed'); + $ext->addGlobal('CALLINGPRES_32', 'prohib_not_screened'); + $ext->addGlobal('CALLINGPRES_33', 'prohib_passed_screen'); + $ext->addGlobal('CALLINGPRES_34', 'prohib_failed_screen'); + $ext->addGlobal('CALLINGPRES_35', 'prohib'); + $ext->addGlobal('CALLINGPRES_67', 'unavailable'); + } + + // Let's create globals for each trunk to determine which one's have fixlocalprefix settings. + // this allows us to skip calling the agi script if there are no rules to process saving + // on performance + // + $conf = core_trunks_readDialRulesFile(); + if (is_array($conf)) { + foreach ($conf as $trunknum => $entries) { + $trunkname = substr($trunknum,6); + $ext->addGlobal("PREFIX_TRUNK_$trunkname",count($entries)); + } + } + + // Generate macro-record-enable, if recording is disabled then we just make it a stub + // Otherwise we make it right + // + $context = 'macro-record-enable'; + $exten = 's'; + if ($disable_recording) { + $ext->add($context, $exten, '', new ext_macroexit()); + } else { + $ext->add($context, $exten, '', new ext_gotoif('$["${BLINDTRANSFER}" = ""]', 'check')); + $ext->add($context, $exten, '', new ext_resetcdr('w')); + $ext->add($context, $exten, '', new ext_stopmonitor()); + $ext->add($context, $exten, 'check', new ext_agi('recordingcheck,${STRFTIME(${EPOCH},,%Y%m%d-%H%M%S)},${UNIQUEID}')); + $ext->add($context, $exten, '', new ext_macroexit()); + // keep this 999 in case people have issues updating their recording script + $ext->add($context, $exten, 'record', new ext_mixmonitor('${MIXMON_DIR}${CALLFILENAME}.${MIXMON_FORMAT}','','${MIXMON_POST}'),'1',998); + } + + /* outbound routes */ + // modules should use their own table for storage (and module_get_config() to add dialplan) + // modules should NOT use the extension table to store anything! + $sql = "SELECT application FROM extensions where context = 'outbound-allroutes' ORDER BY application"; + $outrts = sql($sql,"getAll",DB_FETCHMODE_ASSOC); + $ext->addInclude('from-internal-additional','outbound-allroutes'); + $ext->add('outbound-allroutes', 'foo', '', new ext_noop('bar')); + foreach($outrts as $outrt) { + $ext->addInclude('outbound-allroutes',$outrt['application']); + $sql = "SELECT * FROM extensions where context = '".$outrt['application']."' ORDER BY extension, CAST(priority AS UNSIGNED) ASC"; + $thisrt = sql($sql,"getAll",DB_FETCHMODE_ASSOC); + $lastexten = false; + foreach($thisrt as $exten) { + //if emergencyroute, then set channel var + if(strpos($exten['args'],"EMERGENCYROUTE") !== false) + $ext->add($outrt['application'], $exten['extension'], '', new ext_setvar("EMERGENCYROUTE",substr($exten['args'],15))); + if(strpos($exten['args'],"INTRACOMPANYROUTE") !== false) + $ext->add($outrt['application'], $exten['extension'], '', new ext_setvar("INTRACOMPANYROUTE",substr($exten['args'],18))); + // Don't set MOHCLASS if already set, threre may be a feature code that overrode it + if(strpos($exten['args'],"MOHCLASS") !== false) + $ext->add($outrt['application'], $exten['extension'], '', new ext_setvar("MOHCLASS", '${IF($["x${MOHCLASS}"="x"]?'.substr($exten['args'],9).':${MOHCLASS})}' )); + if(strpos($exten['args'],"dialout-trunk") !== false || strpos($exten['args'],"dialout-enum") !== false || strpos($exten['args'],"dialout-dundi") !== false) { + if ($exten['extension'] !== $lastexten) { + + // If NODEST is set, clear it. No point in remembering since dialout-trunk will just end in the + // bit bucket. But if answered by an outside line with transfer capability, we want NODEST to be + // clear so a subsequent transfer to an internal extension works and goes to voicmail or other + // destinations. + // + // Then do one call to user-callerid and record-enable instead of each time as in the past + // + $ext->add($outrt['application'], $exten['extension'], '', new ext_macro('user-callerid,SKIPTTL')); + $ext->add($outrt['application'], $exten['extension'], '', new ext_setvar("_NODEST","")); + $ext->add($outrt['application'], $exten['extension'], '', new ext_macro('record-enable,${AMPUSER},OUT')); + $lastexten = $exten['extension']; + } + $ext->add($outrt['application'], $exten['extension'], '', new ext_macro($exten['args'])); + } + if(strpos($exten['args'],"outisbusy") !== false) + $ext->add($outrt['application'], $exten['extension'], '', new ext_macro("outisbusy")); + } + } + + general_generate_indications(); + + // "blackhole" destinations + $ext->add('app-blackhole', 'hangup', '', new ext_noop('Blackhole Dest: Hangup')); + $ext->add('app-blackhole', 'hangup', '', new ext_hangup()); + + $ext->add('app-blackhole', 'zapateller', '', new ext_noop('Blackhole Dest: Play SIT Tone')); + $ext->add('app-blackhole', 'zapateller', '', new ext_answer()); + $ext->add('app-blackhole', 'zapateller', '', new ext_zapateller()); + // Should hangup ? + // $ext->add('app-blackhole', 'zapateller', '', new ext_hangup()); + + $ext->add('app-blackhole', 'musiconhold', '', new ext_noop('Blackhole Dest: Put caller on hold forever')); + $ext->add('app-blackhole', 'musiconhold', '', new ext_answer()); + $ext->add('app-blackhole', 'musiconhold', '', new ext_musiconhold()); + + $ext->add('app-blackhole', 'congestion', '', new ext_noop('Blackhole Dest: Congestion')); + $ext->add('app-blackhole', 'congestion', '', new ext_answer()); + $ext->add('app-blackhole', 'congestion', '', new ext_playtones('congestion')); + $ext->add('app-blackhole', 'congestion', '', new ext_congestion()); + $ext->add('app-blackhole', 'congestion', '', new ext_hangup()); + + $ext->add('app-blackhole', 'busy', '', new ext_noop('Blackhole Dest: Busy')); + $ext->add('app-blackhole', 'busy', '', new ext_answer()); + $ext->add('app-blackhole', 'busy', '', new ext_playtones('busy')); + $ext->add('app-blackhole', 'busy', '', new ext_busy()); + $ext->add('app-blackhole', 'busy', '', new ext_hangup()); + + $ext->add('app-blackhole', 'ring', '', new ext_noop('Blackhole Dest: Ring')); + $ext->add('app-blackhole', 'ring', '', new ext_answer()); + $ext->add('app-blackhole', 'ring', '', new ext_playtones('ring')); + $ext->add('app-blackhole', 'ring', '', new ext_wait(300)); + $ext->add('app-blackhole', 'ring', '', new ext_hangup()); + + if ($amp_conf['AMPBADNUMBER'] !== false) { + $context = 'bad-number'; + $exten = '_X.'; + $ext->add($context, $exten, '', new extension('ResetCDR()')); + $ext->add($context, $exten, '', new extension('NoCDR()')); + $ext->add($context, $exten, '', new ext_wait('1')); + $ext->add($context, $exten, '', new ext_playback('silence/1&cannot-complete-as-dialed&check-number-dial-again,noanswer')); + $ext->add($context, $exten, '', new ext_wait('1')); + $ext->add($context, $exten, '', new ext_congestion('20')); + $ext->add($context, $exten, '', new ext_hangup()); + } + + /* + ;------------------------------------------------------------------------ + ; [macro-confirm] + ;------------------------------------------------------------------------ + ; CONTEXT: macro-confirm + ; PURPOSE: added default message if none supplied + ; + ; Follom-Me and Ringgroups provide an option to supply a message to be + ; played as part of the confirmation. These changes have added a default + ; message if none is supplied. + ; + ;------------------------------------------------------------------------ + */ + $context = 'macro-confirm'; + $exten = 's'; + + $ext->add($context, $exten, '', new ext_setvar('LOOPCOUNT','0')); + $ext->add($context, $exten, '', new ext_setvar('__MACRO_RESULT','ABORT')); + $ext->add($context, $exten, '', new ext_setvar('MSG1','${IF($["foo${ARG1}" != "foo"]?${ARG1}:"incoming-call-1-accept-2-decline")}')); + if (version_compare($version, "1.4", "ge")) { + $ext->add($context, $exten, 'start', new ext_background('${MSG1},m,${CHANNEL(language)},macro-confirm')); + } else { + $ext->add($context, $exten, 'start', new ext_background('${MSG1},m,${LANGUAGE},macro-confirm')); + } + $ext->add($context, $exten, '', new ext_read('INPUT', '', 1, '', '', 4)); + $ext->add($context, $exten, '', new ext_gotoif('$[${LEN(${INPUT})} > 0]', '${INPUT},1', 't,1')); + + $exten = '1'; + $ext->add($context, $exten, '', new ext_gotoif('$["${DB_EXISTS(RG/${ARG3}/${UNIQCHAN})}" = "0"]', 'toolate,1')); + $ext->add($context, $exten, '', new ext_dbdel('RG/${ARG3}/${UNIQCHAN}')); + $ext->add($context, $exten, '', new ext_dbdel('${BLKVM_OVERRIDE}')); + $ext->add($context, $exten, '', new ext_setvar('__MACRO_RESULT','')); + $ext->add($context, $exten, 'exitopt1', new ext_macroexit()); + + $exten = '2'; + $ext->add($context, $exten, '', new ext_goto(1, 'noanswer')); + + $exten = '3'; + $ext->add($context, $exten, '', new ext_saydigits('${CALLCONFIRMCID}')); + $ext->add($context, $exten, '', new ext_gotoif('$["${DB_EXISTS(RG/${ARG3}/${UNIQCHAN})}" = "0"]', 'toolate,1','s,start')); + + $exten = 't'; + $ext->add($context, $exten, '', new ext_gotoif('$["${DB_EXISTS(RG/${ARG3}/${UNIQCHAN})}" = "0"]', 'toolate,1')); + $ext->add($context, $exten, '', new ext_setvar('LOOPCOUNT','$[ ${LOOPCOUNT} + 1 ]')); + $ext->add($context, $exten, '', new ext_gotoif('$[ ${LOOPCOUNT} < 5 ]', 's,start','noanswer,1')); + + $exten = '_X'; + if (version_compare($version, "1.4", "ge")) { + $ext->add($context, $exten, '', new ext_background('invalid,m,${CHANNEL(language)},macro-confirm')); + } else { + $ext->add($context, $exten, '', new ext_background('invalid,m,${LANGUAGE},macro-confirm')); + } + $ext->add($context, $exten, '', new ext_gotoif('$["${DB_EXISTS(RG/${ARG3}/${UNIQCHAN})}" = "0"]', 'toolate,1')); + $ext->add($context, $exten, '', new ext_setvar('LOOPCOUNT','$[ ${LOOPCOUNT} + 1 ]')); + $ext->add($context, $exten, '', new ext_gotoif('$[ ${LOOPCOUNT} < 5 ]', 's,start','noanswer,1')); + + $exten = 'noanswer'; + $ext->add($context, $exten, '', new ext_setvar('__MACRO_RESULT','ABORT')); + $ext->add($context, $exten, 'exitnoanswer', new ext_macroexit()); + + $exten = 'toolate'; + $ext->add($context, $exten, '', new ext_setvar('MSG2','${IF($["foo${ARG2}" != "foo"]?${ARG2}:"incoming-call-no-longer-avail")}')); + $ext->add($context, $exten, '', new ext_playback('${MSG2}')); + $ext->add($context, $exten, '', new ext_setvar('__MACRO_RESULT','ABORT')); + $ext->add($context, $exten, 'exittoolate', new ext_macroexit()); + + $exten = 'h'; + $ext->add($context, $exten, '', new ext_macro('hangupcall')); + + /* + ;------------------------------------------------------------------------ + ; [macro-auto-confirm] + ;------------------------------------------------------------------------ + ; This macro is called from ext-local-confirm to auto-confirm a call so that other extensions + ; are aware that the call has been answered. + ; + ;------------------------------------------------------------------------ + */ + $context = 'macro-auto-confirm'; + $exten = 's'; + $ext->add($context, $exten, '', new ext_setvar('__MACRO_RESULT','')); + $ext->add($context, $exten, '', new ext_dbdel('${BLKVM_OVERRIDE}')); + $ext->add($context, $exten, '', new ext_dbdel('RG/${ARG1}/${UNIQCHAN}')); + + + /* + ;------------------------------------------------------------------------ + ; [macro-auto-blkvm] + ;------------------------------------------------------------------------ + ; This macro is called for any extension dialed form a queue, ringgroup + ; or followme, so that the answering extension can clear the voicemail block + ; override allow subsequent transfers to properly operate. + ; + ;------------------------------------------------------------------------ + */ + $context = 'macro-auto-blkvm'; + $exten = 's'; + $ext->add($context, $exten, '', new ext_setvar('__MACRO_RESULT','')); + $ext->add($context, $exten, '', new ext_dbdel('${BLKVM_OVERRIDE}')); + + /* + ;------------------------------------------------------------------------ + ; [sub-pincheck] + ;------------------------------------------------------------------------ + ; This subroutine checks the pincode and then resets the CDR from that point + ; if the pincode passes. This way the billsec and duration fields are set + ; properly for pin dialing. + ; + ; ${ARG3} is the pincode if this was called, used by dialout-trunk, dialout-enum + ; and dialout-dundi + ; + ;------------------------------------------------------------------------ + */ + $context = 'sub-pincheck'; + $exten = 's'; + $ext->add($context, $exten, '', new ext_authenticate('${ARG3}')); + $ext->add($context, $exten, '', new ext_resetcdr('')); + $ext->add($context, $exten, '', new ext_return('')); + + + /* + * dialout using a trunk, using pattern matching (don't strip any prefix) + * arg1 = trunk number, arg2 = number, arg3 = route password + * + * MODIFIED (PL) + * + * Modified both Dial() commands to include the new TRUNK_OPTIONS from the general + * screen of AMP + */ + + $context = 'macro-dialout-trunk'; + $exten = 's'; + + $ext->add($context, $exten, '', new ext_set('DIAL_TRUNK', '${ARG1}')); + $ext->add($context, $exten, '', new ext_gosubif('$[$["${ARG3}" != ""] & $["${DB(AMPUSER/${AMPUSER}/pinless)}" != "NOPASSWD"]]','sub-pincheck,s,1')); + $ext->add($context, $exten, '', new ext_gotoif('$["x${OUTDISABLE_${DIAL_TRUNK}}" = "xon"]', 'disabletrunk,1')); + $ext->add($context, $exten, '', new ext_set('DIAL_NUMBER', '${ARG2}')); // fixlocalprefix depends on this + $ext->add($context, $exten, '', new ext_set('DIAL_TRUNK_OPTIONS', '${DIAL_OPTIONS}')); // will be reset to TRUNK_OPTIONS if not intra-company + $ext->add($context, $exten, '', new ext_set('OUTBOUND_GROUP', 'OUT_${DIAL_TRUNK}')); + $ext->add($context, $exten, '', new ext_gotoif('$["${OUTMAXCHANS_${DIAL_TRUNK}}foo" = "foo"]', 'nomax')); + $ext->add($context, $exten, '', new ext_gotoif('$[ ${GROUP_COUNT(OUT_${DIAL_TRUNK})} >= ${OUTMAXCHANS_${DIAL_TRUNK}} ]', 'chanfull')); + $ext->add($context, $exten, 'nomax', new ext_gotoif('$["${INTRACOMPANYROUTE}" = "YES"]', 'skipoutcid')); // Set to YES if treated like internal + $ext->add($context, $exten, '', new ext_set('DIAL_TRUNK_OPTIONS', '${TRUNK_OPTIONS}')); + $ext->add($context, $exten, '', new ext_macro('outbound-callerid', '${DIAL_TRUNK}')); + $ext->add($context, $exten, 'skipoutcid', new ext_execif('$["${PREFIX_TRUNK_${DIAL_TRUNK}}" != ""]','AGI','fixlocalprefix')); // this sets DIAL_NUMBER to the proper dial string for this trunk + $ext->add($context, $exten, '', new ext_set('OUTNUM', '${OUTPREFIX_${DIAL_TRUNK}}${DIAL_NUMBER}')); // OUTNUM is the final dial number + $ext->add($context, $exten, '', new ext_set('custom', '${CUT(OUT_${DIAL_TRUNK},:,1)}')); // Custom trunks are prefixed with "AMP:" + + // Back to normal processing, whether intracompany or not. + // But add the macro-setmusic if we don't want music on this outbound call + $ext->add($context, $exten, '', new ext_execif('$[$["${MOHCLASS}" != "default"] & $["${MOHCLASS}" != ""]]', 'Set', 'DIAL_TRUNK_OPTIONS=M(setmusic^${MOHCLASS})${DIAL_TRUNK_OPTIONS}')); + + // This macro call will always be blank and is provided as a hook for customization required prior to making a call + // such as adding SIP header information or other requirements. All the channel variables from above are present + + $ext->add($context, $exten, 'gocall', new ext_macro('dialout-trunk-predial-hook')); + $ext->add($context, $exten, '', new ext_gotoif('$["${PREDIAL_HOOK_RET}" = "BYPASS"]', 'bypass,1')); + + $ext->add($context, $exten, '', new ext_gotoif('$["${custom}" = "AMP"]', 'customtrunk')); + $ext->add($context, $exten, '', new ext_dial('${OUT_${DIAL_TRUNK}}/${OUTNUM}', '300,${DIAL_TRUNK_OPTIONS}')); // Regular Trunk Dial + $ext->add($context, $exten, '', new ext_goto(1, 's-${DIALSTATUS}')); + + $ext->add($context, $exten, 'customtrunk', new ext_set('pre_num', '${CUT(OUT_${DIAL_TRUNK},$,1)}')); + $ext->add($context, $exten, '', new ext_set('the_num', '${CUT(OUT_${DIAL_TRUNK},$,2)}')); // this is where we expect to find string OUTNUM + $ext->add($context, $exten, '', new ext_set('post_num', '${CUT(OUT_${DIAL_TRUNK},$,3)}')); + $ext->add($context, $exten, '', new ext_gotoif('$["${the_num}" = "OUTNUM"]', 'outnum', 'skipoutnum')); // if we didn't find "OUTNUM", then skip to Dial + $ext->add($context, $exten, 'outnum', new ext_set('the_num', '${OUTNUM}')); // replace "OUTNUM" with the actual number to dial + $ext->add($context, $exten, 'skipoutnum', new ext_dial('${pre_num:4}${the_num}${post_num}', '300,${DIAL_TRUNK_OPTIONS}')); + $ext->add($context, $exten, '', new ext_goto(1, 's-${DIALSTATUS}')); + + $ext->add($context, $exten, 'chanfull', new ext_noop('max channels used up')); + + $exten = 's-BUSY'; + $ext->add($context, $exten, '', new ext_noop('Dial failed due to trunk reporting BUSY - giving up')); + $ext->add($context, $exten, '', new ext_playtones('busy')); + $ext->add($context, $exten, '', new ext_busy(20)); + + $exten = 's-NOANSWER'; + $ext->add($context, $exten, '', new ext_noop('Dial failed due to trunk reporting NOANSWER - giving up')); + $ext->add($context, $exten, '', new ext_playtones('congestion')); + $ext->add($context, $exten, '', new ext_congestion(20)); + + $exten = 's-CANCEL'; + $ext->add($context, $exten, '', new ext_noop('Dial failed due to trunk reporting CANCEL - giving up')); + $ext->add($context, $exten, '', new ext_playtones('congestion')); + $ext->add($context, $exten, '', new ext_congestion(20)); + + $exten = 's-CHANUNAVAIL'; + $ext->add($context, $exten, '', new ext_gotoif('$["x${OUTFAIL_${ARG1}}" = "x"]', 'noreport')); + $ext->add($context, $exten, '', new ext_agi('${OUTFAIL_${ARG1}}')); + $ext->add($context, $exten, 'noreport', new ext_noop('TRUNK Dial failed due to ${DIALSTATUS} (hangupcause: ${HANGUPCAUSE}) - failing through to other trunks')); + + $exten = '_s-.'; + $ext->add($context, $exten, '', new ext_gotoif('$["x${OUTFAIL_${ARG1}}" = "x"]', 'noreport')); + $ext->add($context, $exten, '', new ext_agi('${OUTFAIL_${ARG1}}')); + $ext->add($context, $exten, 'noreport', new ext_noop('TRUNK Dial failed due to ${DIALSTATUS} - failing through to other trunks')); + + $ext->add($context, 'disabletrunk', '', new ext_noop('TRUNK: ${OUT_${DIAL_TRUNK}} DISABLED - falling through to next trunk')); + $ext->add($context, 'bypass', '', new ext_noop('TRUNK: ${OUT_${DIAL_TRUNK}} BYPASSING because dialout-trunk-predial-hook')); + + $ext->add($context, 'h', '', new ext_macro('hangupcall')); + + + + + $context = 'macro-dialout-dundi'; + $exten = 's'; + + /* + * Dialout Dundi Trunk + */ + $ext->add($context, $exten, '', new ext_set('DIAL_TRUNK', '${ARG1}')); + $ext->add($context, $exten, '', new ext_gosubif('$[$["${ARG3}" != ""] & $["${DB(AMPUSER/${AMPUSER}/pinless)}" != "NOPASSWD"]]','sub-pincheck,s,1')); + $ext->add($context, $exten, '', new ext_gotoif('$["x${OUTDISABLE_${DIAL_TRUNK}}" = "xon"]', 'disabletrunk,1')); + $ext->add($context, $exten, '', new ext_set('DIAL_NUMBER', '${ARG2}')); // fixlocalprefix depends on this + $ext->add($context, $exten, '', new ext_set('DIAL_TRUNK_OPTIONS', '${DIAL_OPTIONS}')); // will be reset to TRUNK_OPTIONS if not intra-company + $ext->add($context, $exten, '', new ext_set('OUTBOUND_GROUP', 'OUT_${DIAL_TRUNK}')); + $ext->add($context, $exten, '', new ext_gotoif('$["${OUTMAXCHANS_${DIAL_TRUNK}}foo" = "foo"]', 'nomax')); + $ext->add($context, $exten, '', new ext_gotoif('$[ ${GROUP_COUNT(OUT_${DIAL_TRUNK})} >= ${OUTMAXCHANS_${DIAL_TRUNK}} ]', 'chanfull')); + $ext->add($context, $exten, 'nomax', new ext_gotoif('$["${INTRACOMPANYROUTE}" = "YES"]', 'skipoutcid')); // Set to YES if treated like internal + $ext->add($context, $exten, '', new ext_set('DIAL_TRUNK_OPTIONS', '${TRUNK_OPTIONS}')); + $ext->add($context, $exten, '', new ext_macro('outbound-callerid', '${DIAL_TRUNK}')); + $ext->add($context, $exten, 'skipoutcid', new ext_execif('$["${PREFIX_TRUNK_${DIAL_TRUNK}}" != ""]','AGI','fixlocalprefix')); // this sets DIAL_NUMBER to the proper dial string for this trunk + $ext->add($context, $exten, '', new ext_set('OUTNUM', '${OUTPREFIX_${DIAL_TRUNK}}${DIAL_NUMBER}')); // OUTNUM is the final dial number + + // Back to normal processing, whether intracompany or not. + // But add the macro-setmusic if we don't want music on this outbound call + $ext->add($context, $exten, '', new ext_execif('$[$["${MOHCLASS}" != "default"] & $["${MOHCLASS}" != ""]]', 'Set', 'DIAL_TRUNK_OPTIONS=M(setmusic^${MOHCLASS})${DIAL_TRUNK_OPTIONS}')); + + // This macro call will always be blank and is provided as a hook for customization required prior to making a call + // such as adding SIP header information or other requirements. All the channel variables from above are present + + $ext->add($context, $exten, 'gocall', new ext_macro('dialout-dundi-predial-hook')); + $ext->add($context, $exten, '', new ext_gotoif('$["${PREDIAL_HOOK_RET}" = "BYPASS"]', 'bypass,1')); + + $ext->add($context, $exten, '', new ext_gotoif('$["${custom}" = "AMP"]', 'customtrunk')); + + $ext->add($context, $exten, '', new ext_macro('dundi-${DIAL_TRUNK}','${OUTNUM}')); + $ext->add($context, $exten, '', new ext_goto(1, 's-${DIALSTATUS}')); + + $ext->add($context, $exten, 'chanfull', new ext_noop('max channels used up')); + + $exten = 's-BUSY'; + $ext->add($context, $exten, '', new ext_noop('Dial failed due to trunk reporting BUSY - giving up')); + $ext->add($context, $exten, '', new ext_playtones('busy')); + $ext->add($context, $exten, '', new ext_busy(20)); + + $exten = 's-NOANSWER'; + $ext->add($context, $exten, '', new ext_noop('Dial failed due to trunk reporting NOANSWER - giving up')); + $ext->add($context, $exten, '', new ext_playtones('congestion')); + $ext->add($context, $exten, '', new ext_congestion(20)); + + $exten = 's-CANCEL'; + $ext->add($context, $exten, '', new ext_noop('Dial failed due to trunk reporting CANCEL - giving up')); + $ext->add($context, $exten, '', new ext_playtones('congestion')); + $ext->add($context, $exten, '', new ext_congestion(20)); + + $exten = '_s-.'; + $ext->add($context, $exten, '', new ext_gotoif('$["x${OUTFAIL_${ARG1}}" = "x"]', 'noreport')); + $ext->add($context, $exten, '', new ext_agi('${OUTFAIL_${ARG1}}')); + $ext->add($context, $exten, 'noreport', new ext_noop('TRUNK Dial failed due to ${DIALSTATUS} - failing through to other trunks')); + + $ext->add($context, 'disabletrunk', '', new ext_noop('TRUNK: ${OUT_${DIAL_TRUNK}} DISABLED - falling through to next trunk')); + $ext->add($context, 'bypass', '', new ext_noop('TRUNK: ${OUT_${DIAL_TRUNK}} BYPASSING because dialout-dundi-predial-hook')); + + $ext->add($context, 'h', '', new ext_macro('hangupcall')); + + + + /* + * sets the callerid of the device to that of the logged in user + * + * ${AMPUSER} is set upon return to the real user despite any aliasing that may + * have been set as a result of the AMPUSER//cidnum field. This is used by + * features like DND, CF, etc. to set the proper structure on aliased instructions + */ + $context = 'macro-user-callerid'; + $exten = 's'; + + //$ext->add($context, $exten, '', new ext_noop('user-callerid: ${CALLERID(name)} ${CALLERID(number)}')); + + // make sure AMPUSER is set if it doesn't get set below + $ext->add($context, $exten, '', new ext_set('AMPUSER', '${IF($["foo${AMPUSER}" = "foo"]?${CALLERID(number)}:${AMPUSER})}')); + $ext->add($context, $exten, '', new ext_gotoif('$["${CHANNEL:0:5}" = "Local"]', 'report')); + $ext->add($context, $exten, '', new ext_execif('$["${REALCALLERIDNUM:1:2}" = ""]', 'Set', 'REALCALLERIDNUM=${CALLERID(number)}')); + //$ext->add($context, $exten, 'start', new ext_noop('REALCALLERIDNUM is ${REALCALLERIDNUM}')); + $ext->add($context, $exten, '', new ext_set('AMPUSER', '${DB(DEVICE/${REALCALLERIDNUM}/user)}')); + $ext->add($context, $exten, '', new ext_set('AMPUSERCIDNAME', '${DB(AMPUSER/${AMPUSER}/cidname)}')); + $ext->add($context, $exten, '', new ext_gotoif('$["x${AMPUSERCIDNAME:1:2}" = "x"]', 'report')); + + // user may masquerade as a different user internally, so set the internal cid as indicated + // but keep the REALCALLERID which is used to determine their true identify and lookup info + // during outbound calls. + $ext->add($context, $exten, '', new ext_set('AMPUSERCID', '${IF($["${DB_EXISTS(AMPUSER/${AMPUSER}/cidnum)}" = "1"]?${DB_RESULT}:${AMPUSER})}')); + $ext->add($context, $exten, '', new ext_set('CALLERID(all)', '"${AMPUSERCIDNAME}" <${AMPUSERCID}>')); + $ext->add($context, $exten, '', new ext_set('REALCALLERIDNUM', '${DB(DEVICE/${REALCALLERIDNUM}/user)}')); + /* + * This is where to splice in things like setting the language based on a user's astdb setting, + * or where you might set the CID account code based on a user instead of the device settings. + */ + $ext->add($context, $exten, 'report', new ext_gotoif('$[ "${ARG1}" = "SKIPTTL" ]', 'continue')); + $ext->add($context, $exten, 'report2', new ext_set('__TTL', '${IF($["foo${TTL}" = "foo"]?64:$[ ${TTL} - 1 ])}')); + $ext->add($context, $exten, '', new ext_gotoif('$[ ${TTL} > 0 ]', 'continue')); + $ext->add($context, $exten, '', new ext_wait('${RINGTIMER}')); // wait for a while, to give it a chance to be picked up by voicemail + $ext->add($context, $exten, '', new ext_answer()); + $ext->add($context, $exten, '', new ext_wait('2')); + $ext->add($context, $exten, '', new ext_playback('im-sorry&an-error-has-occured&with&call-forwarding')); + $ext->add($context, $exten, '', new ext_macro('hangupcall')); + $ext->add($context, $exten, '', new ext_congestion(20)); + $ext->add($context, $exten, 'continue', new ext_noop('Using CallerID ${CALLERID(all)}')); + $ext->add($context, 'h', '', new ext_macro('hangupcall')); + + /* + * arg1 = trunk number, arg2 = number + * + * Re-written to use enumlookup.agi + */ + + $context = 'macro-dialout-enum'; + $exten = 's'; + + $ext->add($context, $exten, '', new ext_gosubif('$[$["${ARG3}" != ""] & $["${DB(AMPUSER/${AMPUSER}/pinless)}" != "NOPASSWD"]]','sub-pincheck,s,1')); + $ext->add($context, $exten, '', new ext_macro('outbound-callerid', '${ARG1}')); + $ext->add($context, $exten, '', new ext_set('OUTBOUND_GROUP', 'OUT_${ARG1}')); + $ext->add($context, $exten, '', new ext_gotoif('$["${OUTMAXCHANS_${ARG1}}foo" = "foo"]', 'nomax')); + $ext->add($context, $exten, '', new ext_gotoif('$[ ${GROUP_COUNT(OUT_${ARG1})} >= ${OUTMAXCHANS_${ARG1}} ]', 'nochans')); + $ext->add($context, $exten, 'nomax', new ext_set('DIAL_NUMBER', '${ARG2}')); + $ext->add($context, $exten, '', new ext_set('DIAL_TRUNK', '${ARG1}')); + $ext->add($context, $exten, '', new ext_execif('$["${PREFIX_TRUNK_${DIAL_TRUNK}}" != ""]','AGI','fixlocalprefix')); // this sets DIAL_NUMBER to the proper dial string for this trunk + // Replacement for asterisk's ENUMLOOKUP function + $ext->add($context, $exten, '', new ext_agi('enumlookup.agi')); + // Now we have the variable DIALARR set to a list of URI's that can be called, in order of priority + // Loop through them trying them in order. + $ext->add($context, $exten, 'dialloop', new ext_gotoif('$["foo${DIALARR}"="foo"]', 'end')); + $ext->add($context, $exten, '', new ext_set('TRYDIAL', '${CUT(DIALARR,%,1)}')); + $ext->add($context, $exten, '', new ext_set('DIALARR', '${CUT(DIALARR,%,2-)}')); + $ext->add($context, $exten, '', new ext_dial('${TRYDIAL}', '')); + $ext->add($context, $exten, '', new ext_noop('Dial exited in macro-enum-dialout with ${DIALSTATUS}')); + // Now, if we're still here, that means the Dial failed for some reason. + // If it's CONGESTION or CHANUNAVAIL we want to try again on a different + // different channel. If there's no more left, the dialloop tag will exit. + $ext->add($context, $exten, '', new ext_gotoif('$[ $[ "${DIALSTATUS}" = "CHANUNAVAIL" ] | $[ "${DIALSTATUS}" = "CONGESTION" ] ]', 'dialloop')); + // If we're here, then it's BUSY or NOANSWER or something and well, deal with it. + $ext->add($context, $exten, 'dialfailed', new ext_goto(1, 's-${DIALSTATUS}')); + // Here are the exit points for the macro. + $ext->add($context, $exten, 'nochans', new ext_noop('max channels used up')); + $ext->add($context, $exten, 'end', new ext_noop('Exiting macro-dialout-enum')); + $ext->add($context, 's-BUSY', '', new ext_noop('Trunk is reporting BUSY')); + $ext->add($context, 's-BUSY', '', new ext_busy(20)); + $ext->add($context, '_s-.', '', new ext_noop('Dial failed due to ${DIALSTATUS}')); + + /* + * overrides callerid out trunks + * arg1 is trunk + * macro-user-callerid should be called _before_ using this macro + */ + + $context = 'macro-outbound-callerid'; + $exten = 's'; + + // If we modified the caller presence, set it back. This allows anonymous calls to be internally prepended but keep + // their status if forwarded back out. Not doing this can result in the trunk CID being displayed vs. 'blocked call' + // + if (version_compare($version, "1.6", "lt")) { + $ext->add($context, $exten, '', new ext_execif('$["${CALLINGPRES_SV}" != ""]', 'SetCallerPres', '${CALLINGPRES_SV}')); + } else { + $ext->add($context, $exten, '', new ext_execif('$["${CALLINGPRES_SV}" != ""]', 'Set', 'CALLERPRES()=${CALLINGPRES_SV}')); + } + + // Keep the original CallerID number, for failover to the next trunk. + + $ext->add($context, $exten, '', new ext_execif('$["${REALCALLERIDNUM:1:2}" = ""]', 'Set', 'REALCALLERIDNUM=${CALLERID(number)}')); + // If this came through a ringgroup or CF, then we want to retain original CID unless + // OUTKEEPCID_${trunknum} is set. + // Save then CIDNAME while it is still intact in case we end up sending out this same CID + $ext->add($context, $exten, 'start', new ext_gotoif('$[ $["${REALCALLERIDNUM}" = ""] | $["${KEEPCID}" != "TRUE"] | $["${OUTKEEPCID_${ARG1}}" = "on"] ]', 'normcid')); // Set to TRUE if coming from ringgroups, CF, etc. + $ext->add($context, $exten, '', new ext_set('USEROUTCID', '${REALCALLERIDNUM}')); + //$ext->add($context, $exten, '', new ext_set('REALCALLERIDNAME', '${CALLERID(name)}')); + + // We now have to make sure the CID is valid. If we find an AMPUSER with the same CID, we assume it is an internal + // call (would be quite a conincidence if not) and go through the normal processing to get that CID. If a device + // is set for this CID, then it must be internal + // If we end up using USEROUTCID at the end, it may still be the REALCALLERIDNUM we saved above. That is determined + // if the two are equal, AND there is no CALLERID(name) present since it has been removed by the CALLERID(all)=${USEROUTCID} + // setting. If this is the case, then we put the orignal name back in to send out. Although the CNAME is not honored by most + // carriers, there are cases where it is so this preserves that information to be used by those carriers who do honor it. + $ext->add($context, $exten, '', new ext_gotoif('$["foo${DB(AMPUSER/${REALCALLERIDNUM}/device)}" = "foo"]', 'bypass')); + + $ext->add($context, $exten, 'normcid', new ext_set('USEROUTCID', '${DB(AMPUSER/${REALCALLERIDNUM}/outboundcid)}')); + $ext->add($context, $exten, 'bypass', new ext_set('EMERGENCYCID', '${DB(DEVICE/${REALCALLERIDNUM}/emergency_cid)}')); + $ext->add($context, $exten, '', new ext_set('TRUNKOUTCID', '${OUTCID_${ARG1}}')); + $ext->add($context, $exten, '', new ext_gotoif('$[ $["${EMERGENCYROUTE:1:2}" = ""] | $["${EMERGENCYCID:1:2}" = ""] ]', 'trunkcid')); // check EMERGENCY ROUTE + $ext->add($context, $exten, '', new ext_set('CALLERID(all)', '${EMERGENCYCID}')); // emergency cid for device + $ext->add($context, $exten, 'exit', new ext_macroexit()); + + + $ext->add($context, $exten, 'trunkcid', new ext_execif('$["${TRUNKOUTCID:1:2}" != ""]', 'Set', 'CALLERID(all)=${TRUNKOUTCID}')); + + $ext->add($context, $exten, 'usercid', new ext_gotoif('$["${USEROUTCID:1:2}" = ""]', 'exit')); // check CID override for extension + $ext->add($context, $exten, '', new ext_set('CALLERID(all)', '${USEROUTCID}')); + //$ext->add($context, $exten, '', new ext_gotoif('$["x${CALLERID(name)}"!="xhidden"]', 'checkname', 'hidecid')); // check CID blocking for extension + if (version_compare($version, "1.6", "lt")) { + $ext->add($context, $exten, 'hidecid', new ext_execif('$["${CALLERID(name)}"="hidden"]', 'SetCallerPres', 'prohib_passed_screen')); + } else { + $ext->add($context, $exten, 'hidecid', new ext_execif('$["${CALLERID(name)}"="hidden"]', 'Set', 'CALLERPRES()=prohib_passed_screen')); + } + //$ext->add($context, $exten, 'checkname', new ext_execif('$[ $[ "${CALLERID(number)}" = "${REALCALLERIDNUM}" ] & $[ "${CALLERID(name)}" = "" ] ]', 'Set', 'CALLERID(name)=${REALCALLERIDNAME}')); + + + /* + * Adds a dynamic agent/member to a Queue + * Prompts for call-back number - in not entered, uses CIDNum + */ + + $context = 'macro-agent-add'; + $exten = 's'; + + $ext->add($context, $exten, '', new ext_wait(1)); + $ext->add($context, $exten, '', new ext_macro('user-callerid', 'SKIPTTL')); + $ext->add($context, $exten, 'a3', new ext_read('CALLBACKNUM', 'agent-login')); // get callback number from user + $ext->add($context, $exten, '', new ext_gotoif('$["${CALLBACKNUM}" != ""]', 'a7')); // if user just pressed # or timed out, use cidnum + $ext->add($context, $exten, 'a5', new ext_set('CALLBACKNUM', '${AMPUSER}')); + $ext->add($context, $exten, '', new ext_execif('$["${CALLBACKNUM}" = ""]', 'Set', 'CALLBACKNUM=${CALLERID(number)}')); + $ext->add($context, $exten, '', new ext_gotoif('$["${CALLBACKNUM}" = ""]', 'a3')); // if still no number, start over + $ext->add($context, $exten, 'a7', new ext_gotoif('$["${CALLBACKNUM}" = "${ARG1}"]', 'invalid')); // Error, they put in the queue number + $ext->add($context, $exten, '', new ext_execif('$["${QREGEX}" != ""]', 'GotoIf', '$["${REGEX("${QREGEX}" ${CALLBACKNUM})}" = "0"]?invalid')); + $ext->add($context, $exten, '', new ext_execif('$["${ARG2}" != ""]', 'Authenticate', '${ARG2}')); + $ext->add($context, $exten, 'a9', new ext_addqueuemember('${ARG1}', 'Local/${CALLBACKNUM}@from-internal/n')); // using chan_local allows us to have agents over trunks + $ext->add($context, $exten, '', new ext_userevent('Agentlogin', 'Agent: ${CALLBACKNUM}')); + $ext->add($context, $exten, '', new ext_wait(1)); + $ext->add($context, $exten, '', new ext_playback('agent-loginok&with&extension')); + $ext->add($context, $exten, '', new ext_saydigits('${CALLBACKNUM}')); + $ext->add($context, $exten, '', new ext_hangup()); + $ext->add($context, $exten, '', new ext_macroexit()); + $ext->add($context, $exten, 'invalid', new ext_playback('pbx-invalid')); + $ext->add($context, $exten, '', new ext_goto('a3')); + + /* + * Removes a dynamic agent/member from a Queue + * Prompts for call-back number - in not entered, uses CIDNum + */ + + $context = 'macro-agent-del'; + + $ext->add($context, $exten, '', new ext_wait(1)); + $ext->add($context, $exten, '', new ext_macro('user-callerid', 'SKIPTTL')); + $ext->add($context, $exten, 'a3', new ext_read('CALLBACKNUM', 'agent-logoff')); // get callback number from user + $ext->add($context, $exten, '', new ext_gotoif('$["${CALLBACKNUM}" = ""]', 'a5', 'a7')); // if user just pressed # or timed out, use cidnum + $ext->add($context, $exten, 'a5', new ext_set('CALLBACKNUM', '${AMPUSER}')); + $ext->add($context, $exten, '', new ext_execif('$["${CALLBACKNUM}" = ""]', 'Set', 'CALLBACKNUM=${CALLERID(number)}')); + $ext->add($context, $exten, '', new ext_gotoif('$["${CALLBACKNUM}" = ""]', 'a3')); // if still no number, start over + $ext->add($context, $exten, 'a7', new ext_removequeuemember('${ARG1}', 'Local/${CALLBACKNUM}@from-internal/n')); + $ext->add($context, $exten, '', new ext_userevent('RefreshQueue')); + $ext->add($context, $exten, '', new ext_wait(1)); + $ext->add($context, $exten, '', new ext_playback('agent-loggedoff')); + $ext->add($context, $exten, '', new ext_hangup()); + + $context = 'macro-systemrecording'; + + //exten => s,1,Set(RECFILE=${IF($["${ARG2}" = ""]?/tmp/${AMPUSER}-ivrrecording:${ARG2})}) + $ext->add($context, 's', '', new ext_setvar('RECFILE','${IF($["${ARG2}" = ""]?/tmp/${AMPUSER}-ivrrecording:${ARG2})}')); + $ext->add($context, 's', '', new ext_execif('$["${ARG3}" != ""]','Authenticate','${ARG3}')); + $ext->add($context, 's', '', new ext_goto(1, '${ARG1}')); + + $exten = 'dorecord'; + + // Delete all versions of the current sound file (does not consider languages though + // otherwise you might have some versions that are not re-recorded + // + $ext->add($context, $exten, '', new ext_system('rm ${ASTVARLIBDIR}/sounds/${RECFILE}.*')); + $ext->add($context, $exten, '', new ext_record('${RECFILE}:wav')); + $ext->add($context, $exten, '', new ext_wait(1)); + $ext->add($context, $exten, '', new ext_goto(1, 'confmenu')); + + $exten = 'docheck'; + + $ext->add($context, $exten, '', new ext_playback('beep')); + if (version_compare($version, "1.4", "ge")) { + $ext->add($context, $exten, 'dc_start', new ext_background('${RECFILE},m,${CHANNEL(language)},macro-systemrecording')); + } else { + $ext->add($context, $exten, 'dc_start', new ext_background('${RECFILE},m,${LANGUAGE},macro-systemrecording')); + } + $ext->add($context, $exten, '', new ext_wait(1)); + $ext->add($context, $exten, '', new ext_goto(1, 'confmenu')); + + $exten = 'confmenu'; + if (version_compare($version, "1.4", "ge")) { + $ext->add($context, $exten, '', new ext_background('to-listen-to-it&press-1&to-rerecord-it&press-star&astcc-followed-by-pound,m,${CHANNEL(language)},macro-systemrecording')); + } else { + $ext->add($context, $exten, '', new ext_background('to-listen-to-it&press-1&to-rerecord-it&press-star&astcc-followed-by-pound,m,${LANGUAGE},macro-systemrecording')); + } + $ext->add($context, $exten, '', new ext_read('RECRESULT', '', 1, '', '', 4)); + $ext->add($context, $exten, '', new ext_gotoif('$["x${RECRESULT}"="x*"]', 'dorecord,1')); + $ext->add($context, $exten, '', new ext_gotoif('$["x${RECRESULT}"="x1"]', 'docheck,2')); + $ext->add($context, $exten, '', new ext_goto(1)); + + $ext->add($context, '1', '', new ext_goto('dc_start', 'docheck')); + $ext->add($context, '*', '', new ext_goto(1, 'dorecord')); + + $ext->add($context, 't', '', new ext_playback('goodbye')); + $ext->add($context, 't', '', new ext_hangup()); + + $ext->add($context, 'i', '', new ext_playback('pm-invalid-option')); + $ext->add($context, 'i', '', new ext_goto(1, 'confmenu')); + + $ext->add($context, 'h', '', new ext_hangup()); + + + $context = 'from-zaptel'; + $exten = '_X.'; + + $ext->add($context, $exten, '', new ext_set('DID', '${EXTEN}')); + $ext->add($context, $exten, '', new ext_goto(1, 's')); + + $exten = 's'; + $ext->add($context, $exten, '', new ext_noop('Entering from-zaptel with DID == ${DID}')); + // Some trunks _require_ a RINGING be sent before an Answer. + $ext->add($context, $exten, '', new ext_ringing()); + // If ($did == "") { $did = "s"; } + $ext->add($context, $exten, '', new ext_set('DID', '${IF($["${DID}"= ""]?s:${DID})}')); + $ext->add($context, $exten, '', new ext_noop('DID is now ${DID}')); + if ($chan_dahdi) { + $ext->add($context, $exten, '', new ext_gotoif('$["${CHANNEL:0:5}"="DAHDI"]', 'zapok', 'notzap')); + } else { + $ext->add($context, $exten, '', new ext_gotoif('$["${CHANNEL:0:3}"="Zap"]', 'zapok', 'notzap')); + } + $ext->add($context, $exten, 'notzap', new ext_goto('1', '${DID}', 'from-pstn')); + // If there's no ext-did,s,1, that means there's not a no did/no cid route. Hangup. + $ext->add($context, $exten, '', new ext_macro('Hangupcall', 'dummy')); + $ext->add($context, $exten, 'zapok', new ext_noop('Is a Zaptel Channel')); + if ($chan_dahdi) { + $ext->add($context, $exten, '', new ext_set('CHAN', '${CHANNEL:6}')); + } else { + $ext->add($context, $exten, '', new ext_set('CHAN', '${CHANNEL:4}')); + } + $ext->add($context, $exten, '', new ext_set('CHAN', '${CUT(CHAN,-,1)}')); + $ext->add($context, $exten, '', new ext_macro('from-zaptel-${CHAN}', '${DID},1')); + // If nothing there, then treat it as a DID + $ext->add($context, $exten, '', new ext_noop('Returned from Macro from-zaptel-${CHAN}')); + $ext->add($context, $exten, '', new ext_goto(1, '${DID}', 'from-pstn')); + $ext->add($context, 'fax', '', new ext_goto(1, 'in_fax', 'ext-fax')); + + /* + * vm-callme context plays voicemail over telephone for web click-to-call + * MSG and MBOX are channel variables that must be set when originating the call + */ + + $context = 'vm-callme'; + + $ext->add($context, 's', '', new ext_answer()); + $ext->add($context, 's', '', new ext_wait(1)); + $ext->add($context, 's', 'repeat', new ext_background('${MSG}&silence/2&vm-repeat')); + $ext->add($context, 's', '', new ext_waitexten(15)); + + $ext->add($context, '5', '', new ext_goto('repeat', 's')); + + $ext->add($context, '#', '', new ext_playback('vm-goodbye')); + $ext->add($context, '#', '', new ext_hangup()); + + $ext->add($context, 'i', '', new ext_playback('pm-invalid-option')); + $ext->add($context, 'i', '', new ext_goto('repeat', 's')); + + $ext->add($context, 't', '', new ext_playback('vm-goodbye')); + $ext->add($context, 't', '', new ext_hangup()); + + $ext->add($context, 'h', '', new ext_hangup()); + + /* end vm-callme context */ + + break; + } +} + +/* begin page.ampusers.php functions */ + +function core_ampusers_add($username, $password, $extension_low, $extension_high, $deptname, $sections) { + $sql = "INSERT INTO ampusers (username, password, extension_low, extension_high, deptname, sections) VALUES ("; + $sql .= "'".$username."',"; + $sql .= "'".$password."',"; + $sql .= "'".$extension_low."',"; + $sql .= "'".$extension_high."',"; + $sql .= "'".$deptname."',"; + $sql .= "'".implode(";",$sections)."');"; + + sql($sql,"query"); +} + +function core_ampusers_del($username) { + $sql = "DELETE FROM ampusers WHERE username = '".$username."'"; + sql($sql,"query"); +} + +function core_ampusers_list() { + $sql = "SELECT username FROM ampusers ORDER BY username"; + return sql($sql,"getAll"); +} + +/* end page.ampusers.php functions */ + + + + + + + + + +/* begin page.did.php functions */ + +function core_did_list($order='extension'){ + switch ($order) { + case 'description': + $sql = "SELECT * FROM incoming ORDER BY description,extension,cidnum"; + break; + case 'extension': + default: + $sql = "SELECT * FROM incoming ORDER BY extension,cidnum"; + } + return sql($sql,"getAll",DB_FETCHMODE_ASSOC); +} + +function core_did_get($extension="",$cidnum=""){ + $sql = "SELECT * FROM incoming WHERE cidnum = \"$cidnum\" AND extension = \"$extension\""; + return sql($sql,"getRow",DB_FETCHMODE_ASSOC); +} + +function core_did_del($extension,$cidnum){ + $sql="DELETE FROM incoming WHERE cidnum = \"$cidnum\" AND extension = \"$extension\""; + sql($sql); +} + +function core_did_edit($old_extension,$old_cidnum, $incoming){ + global $db; + + $old_extension = $db->escapeSimple(trim($old_extension)); + $old_cidnum = $db->escapeSimple(trim($old_cidnum)); + + $incoming['extension'] = trim($incoming['extension']); + $incoming['cidnum'] = trim($incoming['cidnum']); + + $extension = $db->escapeSimple($incoming['extension']); + $cidnum = $db->escapeSimple($incoming['cidnum']); + + // if did or cid changed, then check to make sure that this pair is not already being used. + // + if (($extension != $old_extension) || ($cidnum != $old_cidnum)) { + $existing=core_did_get($extension,$cidnum); + } + + if (empty($existing)) { + core_did_del($old_extension,$old_cidnum); + core_did_add($incoming); + return true; + } else { + echo ""; + } + return false; +} + +function core_did_add($incoming,$target=false){ + global $db; + foreach ($incoming as $key => $val) { ${$key} = $db->escapeSimple($val); } // create variables from request + + // Check to make sure the did is not being used elsewhere + // + $existing=core_did_get($extension,$cidnum); + + if (empty($existing)) { + $destination= ($target) ? $target : ${$goto0.'0'}; + $sql="INSERT INTO incoming (cidnum,extension,destination,faxexten,faxemail,answer,wait,privacyman,alertinfo, ringing, mohclass, description, grppre, delay_answer, pricid) values ('$cidnum','$extension','$destination','$faxexten','$faxemail','$answer','$wait','$privacyman','$alertinfo', '$ringing', '$mohclass', '$description', '$grppre', '$delay_answer', '$pricid')"; + sql($sql); + return true; + } else { + echo ""; + return false; + } +} + +/* end page.did.php functions */ + + +/* begin page.devices.php functions */ + +//get the existing devices +function core_devices_list($tech="all",$detail=false,$get_all=false) { + if (strtolower($detail) == 'full') { + $sql = "SELECT * FROM devices"; + } else { + $sql = "SELECT id,description FROM devices"; + } + switch (strtoupper($tech)) { + case "IAX": + $sql .= " WHERE tech = 'iax2'"; + break; + case "IAX2": + case "SIP": + case "ZAP": + $sql .= " WHERE tech = '".strtolower($tech)."'"; + break; + case "ALL": + default: + } + $sql .= ' ORDER BY id'; + $results = sql($sql,"getAll",DB_FETCHMODE_ASSOC); + + $extens = null; + foreach($results as $result){ + if ($get_all || checkRange($result['id'])){ + + $record = array(); + $record[0] = $result['id']; // for backwards compatibility + $record[1] = $result['description']; // for backwards compatibility + foreach ($result as $key => $value) { + $record[$key] = $value; + } + $extens[] = $record; + /* + $extens[] = array( + 0=>$result[0], // for backwards compatibility + 1=>$result[1], + 'id'=>$result[0], // FETCHMODE_ASSOC emulation + 'description'=>$result[1], + ); + */ + } + } + return $extens; +} + + +function core_devices_add($id,$tech,$dial,$devicetype,$user,$description,$emergency_cid=null,$editmode=false){ + global $amp_conf; + global $currentFile; + global $astman; + global $db; + + $display = isset($_REQUEST['display'])?$_REQUEST['display']:''; + + if (trim($id) == '' ) { + if ($display != 'extensions') { + echo ""; + } + return false; + } + + //ensure this id is not already in use + $devices = core_devices_list(); + if (is_array($devices)) { + foreach($devices as $device) { + if ($device[0] === $id) { + if ($display <> 'extensions') echo ""; + return false; + } + } + } + //unless defined, $dial is TECH/id + if ( $dial == '' ) { + //zap is an exception + if ( strtolower($tech) == "zap" ) { + $zapchan = $_REQUEST['devinfo_channel'] != '' ? $_REQUEST['devinfo_channel'] : $_REQUEST['channel']; + $dial = 'ZAP/'.$zapchan; + } else { + $dial = strtoupper($tech)."/".$id; + } + } + + //check to see if we are requesting a new user + if ($user == "new") { + $user = $id; + $jump = true; + } + + if(!get_magic_quotes_gpc()) { + if(!empty($emergency_cid)) + $emergency_cid = $db->escapeSimple($emergency_cid); + if(!empty($description)) + $description = $db->escapeSimple($description); + } + + //insert into devices table + $sql="INSERT INTO devices (id,tech,dial,devicetype,user,description,emergency_cid) values (\"$id\",\"$tech\",\"$dial\",\"$devicetype\",\"$user\",\"$description\",\"$emergency_cid\")"; + sql($sql); + + //add details to astdb + if ($astman) { + // if adding or editting a fixed device, user property should always be set + if ($devicetype == 'fixed' || !$editmode) { + $astman->database_put("DEVICE",$id."/user",$user); + } + // If changing from a fixed to an adhoc, the user property should be intialized + // to the new default, not remain as the previous fixed user + if ($editmode) { + $previous_type = $astman->database_get("DEVICE",$id."/type"); + if ($previous_type == 'fixed' && $devicetype == 'adhoc') { + $astman->database_put("DEVICE",$id."/user",$user); + } + } + $astman->database_put("DEVICE",$id."/dial",$dial); + $astman->database_put("DEVICE",$id."/type",$devicetype); + $astman->database_put("DEVICE",$id."/default_user",$user); + if($emergency_cid != '') { + $astman->database_put("DEVICE",$id."/emergency_cid","\"".$emergency_cid."\""); + } + + if ($user != "none") { + $existingdevices = $astman->database_get("AMPUSER",$user."/device"); + if (empty($existingdevices)) { + $astman->database_put("AMPUSER",$user."/device",$id); + } else { + $existingdevices_array = explode('&',$existingdevices); + if (!in_array($id, $existingdevices_array)) { + $existingdevices_array[]=$id; + $existingdevices = implode('&',$existingdevices_array); + $astman->database_put("AMPUSER",$user."/device",$existingdevices); + } + } + } + + } else { + fatal("Cannot connect to Asterisk Manager with ".$amp_conf["AMPMGRUSER"]."/".$amp_conf["AMPMGRPASS"]); + } + + // create a voicemail symlink if needed + $thisUser = core_users_get($user); + if(isset($thisUser['voicemail']) && ($thisUser['voicemail'] != "novm")) { + if(empty($thisUser['voicemail'])) { + $vmcontext = "default"; + } else { + $vmcontext = $thisUser['voicemail']; + } + + //voicemail symlink + exec("rm -f /var/spool/asterisk/voicemail/device/".$id); + exec("/bin/ln -s /var/spool/asterisk/voicemail/".$vmcontext."/".$user."/ /var/spool/asterisk/voicemail/device/".$id); + } + + //take care of sip/iax/zap config + $funct = "core_devices_add".strtolower($tech); + if(function_exists($funct)){ + $funct($id); + } + +/* if($user != "none") { + core_hint_add($user); + }*/ + + //if we are requesting a new user, let's jump to users.php + if (isset($jump)) { + echo(""); + } + return true; +} + +function core_devices_del($account,$editmode=false){ + global $amp_conf; + global $currentFile; + global $astman; + + //get all info about device + $devinfo = core_devices_get($account); + + //delete details to astdb + if ($astman) { + // If a user was selected, remove this device from the user + $deviceuser = $astman->database_get("DEVICE",$account."/user"); + if (isset($deviceuser) && $deviceuser != "none") { + // Remove the device record from the user's device list + $userdevices = $astman->database_get("AMPUSER",$deviceuser."/device"); + + // We need to remove just this user and leave the rest alone + $userdevicesarr = explode("&", $userdevices); + $userdevicesarr_hash = array_flip($userdevicesarr); + unset($userdevicesarr_hash[$account]); + $userdevicesarr = array_flip($userdevicesarr_hash); + $userdevices = implode("&", $userdevicesarr); + + if (empty($userdevices)) { + $astman->database_del("AMPUSER",$deviceuser."/device"); + } else { + $astman->database_put("AMPUSER",$deviceuser."/device",$userdevices); + } + } + if (! $editmode) { + $astman->database_del("DEVICE",$account."/dial"); + $astman->database_del("DEVICE",$account."/type"); + $astman->database_del("DEVICE",$account."/user"); + $astman->database_del("DEVICE",$account."/default_user"); + $astman->database_del("DEVICE",$account."/emergency_cid"); + } + + //delete from devices table + $sql="DELETE FROM devices WHERE id = \"$account\""; + sql($sql); + + //voicemail symlink + exec("rm -f /var/spool/asterisk/voicemail/device/".$account); + } else { + fatal("Cannot connect to Asterisk Manager with ".$amp_conf["AMPMGRUSER"]."/".$amp_conf["AMPMGRPASS"]); + } + + //take care of sip/iax/zap config + $funct = "core_devices_del".strtolower($devinfo['tech']); + if(function_exists($funct)){ + $funct($account); + } +} + +function core_devices_get($account){ + //get all the variables for the meetme + $sql = "SELECT * FROM devices WHERE id = '$account'"; + $results = sql($sql,"getRow",DB_FETCHMODE_ASSOC); + + //take care of sip/iax/zap config + $funct = "core_devices_get".strtolower($results['tech']); + if (!empty($results['tech']) && function_exists($funct)) { + $devtech = $funct($account); + if (is_array($devtech)){ + $results = array_merge($results,$devtech); + } + } + + return $results; +} + +// this function rebuilds the astdb based on device table contents +// used on devices.php if action=resetall +function core_devices2astdb(){ + global $astman; + global $amp_conf; + + $sql = "SELECT * FROM devices"; + $devresults = sql($sql,"getAll",DB_FETCHMODE_ASSOC); + + //add details to astdb + if ($astman) { + $astman->database_deltree("DEVICE"); + foreach ($devresults as $dev) { + extract($dev); + $astman->database_put("DEVICE",$id."/dial",$dial); + $astman->database_put("DEVICE",$id."/type",$devicetype); + $astman->database_put("DEVICE",$id."/user",$user); + $astman->database_put("DEVICE",$id."/default_user",$user); + if(trim($emergency_cid) != '') { + $astman->database_put("DEVICE",$id."/emergency_cid","\"".$emergency_cid."\""); + } + // If a user is selected, add this device to the user + if ($user != "none") { + $existingdevices = $astman->database_get("AMPUSER",$user."/device"); + if (!empty($existingdevices)) { + $existingdevices .= "&"; + } + $astman->database_put("AMPUSER",$user."/device",$existingdevices.$id); + } + + // create a voicemail symlink if needed + $thisUser = core_users_get($user); + if(isset($thisUser['voicemail']) && ($thisUser['voicemail'] != "novm")) { + if(empty($thisUser['voicemail'])) + $vmcontext = "default"; + else + $vmcontext = $thisUser['voicemail']; + //voicemail symlink + exec("rm -f /var/spool/asterisk/voicemail/device/".$id); + exec("/bin/ln -s /var/spool/asterisk/voicemail/".$vmcontext."/".$user."/ /var/spool/asterisk/voicemail/device/".$id); + } + } + return true; + } else { + return false; + } +} + +// this function rebuilds the astdb based on users table contents +// used on devices.php if action=resetall +function core_users2astdb(){ + global $amp_conf; + global $astman; + global $db; + + $sql = "SELECT * FROM users"; + $userresults = sql($sql,"getAll",DB_FETCHMODE_ASSOC); + + //add details to astdb + if ($astman) { + foreach($userresults as $usr) { + extract($usr); + $astman->database_put("AMPUSER",$extension."/password",$password); + $astman->database_put("AMPUSER",$extension."/ringtimer",$ringtimer); + $astman->database_put("AMPUSER",$extension."/noanswer",$noanswer); + $astman->database_put("AMPUSER",$extension."/recording",$recording); + $astman->database_put("AMPUSER",$extension."/outboundcid","\"".$db->escapeSimple($outboundcid)."\""); + $astman->database_put("AMPUSER",$extension."/cidname","\"".$db->escapeSimple($name)."\""); + $astman->database_put("AMPUSER",$extension."/voicemail","\"".$voicemail."\""); + } + return true; + } else { + return false; + } + +// TODO: this was... +// return $astman->disconnect(); +// is "true" the correct value...? +} + +//add to sip table +function core_devices_addsip($account) { + global $db; + global $currentFile; + + foreach ($_REQUEST as $req=>$data) { + if ( substr($req, 0, 8) == 'devinfo_' ) { + $keyword = substr($req, 8); + if ( $keyword == 'dial' && $data == '' ) { + $sipfields[] = array($account, $keyword, 'SIP/'.$account); + } elseif ($keyword == 'mailbox' && $data == '') { + $sipfields[] = array($account,'mailbox',$account.'@device'); + } else { + $sipfields[] = array($account, $keyword, $data); + } + } + } + + if ( !is_array($sipfields) ) { // left for compatibilty....lord knows why ! + $sipfields = array( + //array($account,'account',$account), + array($account,'accountcode',(isset($_REQUEST['accountcode']))?$_REQUEST['accountcode']:''), + array($account,'secret',(isset($_REQUEST['secret']))?$_REQUEST['secret']:''), + array($account,'canreinvite',(isset($_REQUEST['canreinvite']))?$_REQUEST['canreinvite']:'no'), + array($account,'context',(isset($_REQUEST['context']))?$_REQUEST['context']:'from-internal'), + array($account,'dtmfmode',(isset($_REQUEST['dtmfmode']))?$_REQUEST['dtmfmode']:''), + array($account,'host',(isset($_REQUEST['host']))?$_REQUEST['host']:'dynamic'), + array($account,'type',(isset($_REQUEST['type']))?$_REQUEST['type']:'friend'), + array($account,'mailbox',(isset($_REQUEST['mailbox']) && !empty($_REQUEST['mailbox']))?$_REQUEST['mailbox']:$account.'@device'), + array($account,'username',(isset($_REQUEST['username']))?$_REQUEST['username']:$account), + array($account,'nat',(isset($_REQUEST['nat']))?$_REQUEST['nat']:'yes'), + array($account,'port',(isset($_REQUEST['port']))?$_REQUEST['port']:'5060'), + array($account,'qualify',(isset($_REQUEST['qualify']))?$_REQUEST['qualify']:'yes'), + array($account,'callgroup',(isset($_REQUEST['callgroup']))?$_REQUEST['callgroup']:''), + array($account,'pickupgroup',(isset($_REQUEST['pickupgroup']))?$_REQUEST['pickupgroup']:''), + array($account,'disallow',(isset($_REQUEST['disallow']))?$_REQUEST['disallow']:''), + array($account,'allow',(isset($_REQUEST['allow']))?$_REQUEST['allow']:'') + //array($account,'record_in',(isset($_REQUEST['record_in']))?$_REQUEST['record_in']:'On-Demand'), + //array($account,'record_out',(isset($_REQUEST['record_out']))?$_REQUEST['record_out']:'On-Demand'), + //array($account,'callerid',(isset($_REQUEST['description']))?$_REQUEST['description']." <".$account.'>':'device'." <".$account.'>') + ); + } + + // Very bad + $sipfields[] = array($account,'account',$account); + $sipfields[] = array($account,'callerid',(isset($_REQUEST['description']) && $_REQUEST['description'])?$_REQUEST['description']." <".$account.'>':'device'." <".$account.'>'); + + // Where is this in the interface ?????? + $sipfields[] = array($account,'record_in',($_REQUEST['record_in'])?$_REQUEST['record_in']:'On-Demand'); + $sipfields[] = array($account,'record_out',($_REQUEST['record_out'])?$_REQUEST['record_out']:'On-Demand'); + + $compiled = $db->prepare('INSERT INTO sip (id, keyword, data) values (?,?,?)'); + $result = $db->executeMultiple($compiled,$sipfields); + if(DB::IsError($result)) { + die_freepbx($result->getDebugInfo()."

".'error adding to SIP table'); + } +} + +function core_devices_delsip($account) { + global $db; + global $currentFile; + + $sql = "DELETE FROM sip WHERE id = '$account'"; + $result = $db->query($sql); + + if(DB::IsError($result)) { + die_freepbx($result->getMessage().$sql); + } +} + +function core_devices_getsip($account) { + global $db; + $sql = "SELECT keyword,data FROM sip WHERE id = '$account'"; + $results = $db->getAssoc($sql); + if(DB::IsError($results)) { + $results = null; + } + + return $results; +} + +//add to iax table +function core_devices_addiax2($account) { + global $db; + global $currentFile; + + foreach ($_REQUEST as $req=>$data) { + if ( substr($req, 0, 8) == 'devinfo_' ) { + $keyword = substr($req, 8); + if ( $keyword == 'dial' && $data == '' ) { + $iaxfields[] = array($account, $keyword, 'IAX2/'.$account); + } elseif ($keyword == 'mailbox' && $data == '') { + $iaxfields[] = array($account,'mailbox',$account.'@device'); + } else { + $iaxfields[] = array($account, $keyword, $data); + } + } + } + + if ( !is_array($iaxfields) ) { // left for compatibilty....lord knows why ! + $iaxfields = array( + //array($account,'account',$account), + array($account,'secret',($_REQUEST['secret'])?$_REQUEST['secret']:''), + array($account,'notransfer',($_REQUEST['notransfer'])?$_REQUEST['notransfer']:'yes'), + array($account,'context',($_REQUEST['context'])?$_REQUEST['context']:'from-internal'), + array($account,'host',($_REQUEST['host'])?$_REQUEST['host']:'dynamic'), + array($account,'type',($_REQUEST['type'])?$_REQUEST['type']:'friend'), + array($account,'mailbox',($_REQUEST['mailbox'])?$_REQUEST['mailbox']:$account.'@device'), + array($account,'username',($_REQUEST['username'])?$_REQUEST['username']:$account), + array($account,'port',($_REQUEST['port'])?$_REQUEST['port']:'4569'), + array($account,'qualify',($_REQUEST['qualify'])?$_REQUEST['qualify']:'yes'), + array($account,'disallow',($_REQUEST['disallow'])?$_REQUEST['disallow']:''), + array($account,'allow',($_REQUEST['allow'])?$_REQUEST['allow']:''), + array($account,'accountcode',($_REQUEST['accountcode'])?$_REQUEST['accountcode']:'') + //array($account,'record_in',($_REQUEST['record_in'])?$_REQUEST['record_in']:'On-Demand'), + //array($account,'record_out',($_REQUEST['record_out'])?$_REQUEST['record_out']:'On-Demand'), + //array($account,'callerid',($_REQUEST['description'])?$_REQUEST['description']." <".$account.'>':'device'." <".$account.'>') + ); + } + + // Very bad + $iaxfields[] = array($account,'account',$account); + $iaxfields[] = array($account,'callerid',(isset($_REQUEST['description']) && $_REQUEST['description'] != '')?$_REQUEST['description']." <".$account.'>':'device'." <".$account.'>'); + // Asterisk treats no caller ID from an IAX device as 'hide callerid', and ignores the caller ID + // set in iax.conf. As we rely on this for pretty much everything, we need to specify the + // callerid as a variable which gets picked up in macro-callerid. + // Ref - http://bugs.digium.com/view.php?id=456 + $iaxfields[] = array($account,'setvar',"REALCALLERIDNUM=$account"); + + // Where is this in the interface ?????? + $iaxfields[] = array($account,'record_in',($_REQUEST['record_in'])?$_REQUEST['record_in']:'On-Demand'); + $iaxfields[] = array($account,'record_out',($_REQUEST['record_out'])?$_REQUEST['record_out']:'On-Demand'); + + $compiled = $db->prepare('INSERT INTO iax (id, keyword, data) values (?,?,?)'); + $result = $db->executeMultiple($compiled,$iaxfields); + if(DB::IsError($result)) { + die_freepbx($result->getMessage()."

error adding to IAX table"); + } +} + +function core_devices_deliax2($account) { + global $db; + global $currentFile; + + $sql = "DELETE FROM iax WHERE id = '$account'"; + $result = $db->query($sql); + + if(DB::IsError($result)) { + die_freepbx($result->getMessage().$sql); + } +} + +function core_devices_getiax2($account) { + global $db; + $sql = "SELECT keyword,data FROM iax WHERE id = '$account'"; + $results = $db->getAssoc($sql); + if(DB::IsError($results)) { + $results = null; + } + + return $results; +} + +function core_devices_addzap($account) { + global $db; + global $currentFile; + + foreach ($_REQUEST as $req=>$data) { + if ( substr($req, 0, 8) == 'devinfo_' ) { + $keyword = substr($req, 8); + if ( $keyword == 'dial' && $data == '' ) { + $zapchan = $_REQUEST['devinfo_channel'] != '' ? $_REQUEST['devinfo_channel'] : $_REQUEST['channel']; + $zapfields[] = array($account, $keyword, 'ZAP/'.$zapchan); + } elseif ($keyword == 'mailbox' && $data == '') { + $zapfields[] = array($account,'mailbox',$account.'@device'); + } else { + $zapfields[] = array($account, $keyword, $data); + } + } + } + + if ( !is_array($zapfields) ) { // left for compatibilty....lord knows why ! + $zapfields = array( + //array($account,'account',$account), + array($account,'context',($_REQUEST['context'])?$_REQUEST['context']:'from-internal'), + array($account,'mailbox',($_REQUEST['mailbox'])?$_REQUEST['mailbox']:$account.'@device'), + //array($account,'callerid',($_REQUEST['description'])?$_REQUEST['description']." <".$account.'>':'device'." <".$account.'>'), + array($account,'immediate',($_REQUEST['immediate'])?$_REQUEST['immediate']:'no'), + array($account,'signalling',($_REQUEST['signalling'])?$_REQUEST['signalling']:'fxo_ks'), + array($account,'echocancel',($_REQUEST['echocancel'])?$_REQUEST['echocancel']:'yes'), + array($account,'echocancelwhenbridged',($_REQUEST['echocancelwhenbridged'])?$_REQUEST['echocancelwhenbridged']:'no'), + array($account,'immediate',($_REQUEST['immediate'])?$_REQUEST['immediate']:'no'), + array($account,'echotraining',($_REQUEST['echotraining'])?$_REQUEST['echotraining']:'800'), + array($account,'busydetect',($_REQUEST['busydetect'])?$_REQUEST['busydetect']:'no'), + array($account,'busycount',($_REQUEST['busycount'])?$_REQUEST['busycount']:'7'), + array($account,'callprogress',($_REQUEST['callprogress'])?$_REQUEST['callprogress']:'no'), + //array($account,'record_in',($_REQUEST['record_in'])?$_REQUEST['record_in']:'On-Demand'), + //array($account,'record_out',($_REQUEST['record_out'])?$_REQUEST['record_out']:'On-Demand'), + array($account,'accountcode',(isset($_REQUEST['accountcode']))?$_REQUEST['accountcode']:''), + array($account,'callgroup',(isset($_REQUEST['callgroup']))?$_REQUEST['callgroup']:''), + array($account,'pickupgroup',(isset($_REQUEST['pickupgroup']))?$_REQUEST['pickupgroup']:''), + array($account,'channel',($_REQUEST['channel'])?$_REQUEST['channel']:'') + ); + } + + // Very bad + $zapfields[] = array($account,'account',$account); + $zapfields[] = array($account,'callerid',($_REQUEST['description'])?$_REQUEST['description']." <".$account.'>':'device'." <".$account.'>'); + + // Where is this in the interface ?????? + $zapfields[] = array($account,'record_in',($_REQUEST['record_in'])?$_REQUEST['record_in']:'On-Demand'); + $zapfields[] = array($account,'record_out',($_REQUEST['record_out'])?$_REQUEST['record_out']:'On-Demand'); + + $compiled = $db->prepare('INSERT INTO zap (id, keyword, data) values (?,?,?)'); + $result = $db->executeMultiple($compiled,$zapfields); + if(DB::IsError($result)) { + die_freepbx($result->getMessage()."

error adding to ZAP table"); + } +} + +function core_devices_delzap($account) { + global $db; + global $currentFile; + + $sql = "DELETE FROM zap WHERE id = '$account'"; + $result = $db->query($sql); + if(DB::IsError($result)) { + die_freepbx($result->getMessage().$sql); + } +} + +function core_devices_getzap($account) { + global $db; + $sql = "SELECT keyword,data FROM zap WHERE id = '$account'"; + $results = $db->getAssoc($sql); + if(DB::IsError($results)) { + $results = null; + } + return $results; +} +/* end page.devices.php functions */ + + + + +function core_hint_get($account){ + global $astman; + + $chan_dahdi = ast_with_dahdi(); + // We should always check the AMPUSER in case they logged into a device + // but we will fall back to the old methond if $astman not open although + // I'm pretty sure everything else will puke anyhow if not running + // + if ($astman) { + $device=$astman->database_get("AMPUSER",$account."/device"); + $device_arr = explode('&',$device); + $sql = "SELECT dial from devices where id in ('".implode("','",$device_arr)."')"; + } else { + $sql = "SELECT dial from devices where user = '{$account}'"; + } + $results = sql($sql,"getAll",DB_FETCHMODE_ASSOC); + + //create an array of strings + if (is_array($results)){ + foreach ($results as $result) { + if ($chan_dahdi) { + $dial[] = str_replace('ZAP', 'DAHDI', $result['dial']); + } else { + $dial[] = $result['dial']; + } + } + } + + //create a string with & delimiter + if (isset($dial) && is_array($dial)){ + $hint = implode($dial,"&"); + } else { + if (isset($results[0]['dial'])) { + $hint = $results[0]['dial']; + } else { + $hint = null; + } + } + + return $hint; +} + + + +/* begin page.users.php functions */ + +// get the existing extensions +// the returned arrays contain [0]:extension [1]:name +function core_users_list() { + $results = sql("SELECT extension,name,voicemail FROM users ORDER BY extension","getAll"); + + //only allow extensions that are within administrator's allowed range + foreach($results as $result){ + if (checkRange($result[0])){ + $extens[] = array($result[0],$result[1],$result[2]); + } + } + + if (isset($extens)) { + sort($extens); + return $extens; + } else { + return null; + } +} + +function core_check_extensions($exten=true) { + global $amp_conf; + + $extenlist = array(); + if (is_array($exten) && empty($exten)) { + return $extenlist; + } + $sql = "SELECT extension, name FROM users "; + if (is_array($exten)) { + $sql .= "WHERE extension in ('".implode("','",$exten)."')"; + } + $sql .= " ORDER BY extension"; + $results = sql($sql,"getAll",DB_FETCHMODE_ASSOC); + + foreach ($results as $result) { + $thisexten = $result['extension']; + $extenlist[$thisexten]['description'] = _("User Extension: ").$result['name']; + $extenlist[$thisexten]['status'] = 'INUSE'; + $display = ($amp_conf['AMPEXTENSIONS'] == "deviceanduser")?'users':'extensions'; + $extenlist[$thisexten]['edit_url'] = "config.php?type=setup&display=$display&extdisplay=".urlencode($thisexten)."&skip=0"; + } + return $extenlist; +} + +function core_check_destinations($dest=true) { + global $active_modules; + + $destlist = array(); + if (is_array($dest) && empty($dest)) { + return $destlist; + } + $sql = "SELECT extension, cidnum, description, destination FROM incoming "; + if ($dest !== true) { + $sql .= "WHERE destination in ('".implode("','",$dest)."')"; + } + $sql .= "ORDER BY extension, cidnum"; + $results = sql($sql,"getAll",DB_FETCHMODE_ASSOC); + + //$type = isset($active_modules['announcement']['type'])?$active_modules['announcement']['type']:'setup'; + + foreach ($results as $result) { + $thisdest = $result['destination']; + $thisid = $result['extension'].'/'.$result['cidnum']; + $destlist[] = array( + 'dest' => $thisdest, + 'description' => sprintf(_("Inbound Route: %s (%s)"),$result['description'],$thisid), + 'edit_url' => 'config.php?display=did&extdisplay='.urlencode($thisid), + ); + } + return $destlist; +} + +function core_sipname_check($sipname, $extension) { + global $db; + if (!isset($sipname) || trim($sipname)=='') + return true; + + $sql = "SELECT sipname FROM users WHERE sipname = '$sipname' AND extension != '$extension'"; + $results = $db->getRow($sql,DB_FETCHMODE_ASSOC); + if(DB::IsError($results)) { + die_freepbx($results->getMessage().$sql); + } + + if (isset($results['sipname']) && trim($results['sipname']) == $sipname) + return false; + else + return true; +} + +function core_users_add($vars, $editmode=false) { + extract($vars); + + global $db; + global $amp_conf; + global $astman; + + $thisexten = isset($thisexten) ? $thisexten : ''; + + if (trim($extension) == '' ) { + echo ""; + return false; + } + + //ensure this id is not already in use + $extens = core_users_list(); + if(is_array($extens)) { + foreach($extens as $exten) { + if ($exten[0]===$extension) { + echo ""; + return false; + } + } + } + + $newdid_name = isset($newdid_name) ? $db->escapeSimple($newdid_name) : ''; + $newdid = isset($newdid) ? $newdid : ''; + $newdid = preg_replace("/[^0-9._XxNnZz\[\]\-\+]/" ,"", trim($newdid)); + + $newdidcid = isset($newdidcid) ? trim($newdidcid) : ''; + if (!preg_match('/^priv|^block|^unknown|^restrict|^unavail|^anonym/',strtolower($newdidcid))) { + $newdidcid = preg_replace("/[^0-9._XxNnZz\[\]\-\+]/" ,"", $newdidcid); + } + + // Well more ugliness since the javascripts are already in here + if ($newdid != '' || $newdidcid != '') { + $existing = core_did_get($newdid, $newdidcid); + if (! empty($existing)) { + echo ""; + return false; + } + } + + $sipname = preg_replace("/\s/" ,"", trim($sipname)); + if (! core_sipname_check($sipname, $extension)) { + echo ""; + return false; + } + + //build the recording variable + $recording = "out=".$record_out."|in=".$record_in; + + //escape quotes and any other bad chars: + if(!get_magic_quotes_gpc()) { + $outboundcid = $db->escapeSimple($outboundcid); + $name = $db->escapeSimple($name); + } + + //if voicemail is enabled, set the box@context to use + //havn't checked but why is voicemail needed on users anyway? Doesn't exactly make it modular ! + if ( function_exists('voicemail_mailbox_get') ) { + $vmbox = voicemail_mailbox_get($extension); + if ( $vmbox == null ) { + $voicemail = "novm"; + } else { + $voicemail = $vmbox['vmcontext']; + } + } + + // Clean replace any <> with () in display name - should have javascript stopping this but ... + // + $name = preg_replace(array('//'), array('(',')'), trim($name)); + + //insert into users table + $sql="INSERT INTO users (extension,password,name,voicemail,ringtimer,noanswer,recording,outboundcid,sipname) values (\""; + $sql.= "$extension\", \""; + $sql.= isset($password)?$password:''; + $sql.= "\", \""; + $sql.= isset($name)?$name:''; + $sql.= "\", \""; + $sql.= isset($voicemail)?$voicemail:'default'; + $sql.= "\", \""; + $sql.= isset($ringtimer)?$ringtimer:''; + $sql.= "\", \""; + $sql.= isset($noanswer)?$noanswer:''; + $sql.= "\", \""; + $sql.= isset($recording)?$recording:''; + $sql.= "\", \""; + $sql.= isset($outboundcid)?$outboundcid:''; + $sql.= "\", \""; + $sql.= isset($sipname)?$sipname:''; + $sql.= "\")"; + sql($sql); + + //write to astdb + if ($astman) { + $cid_masquerade = (isset($cid_masquerade) && trim($cid_masquerade) != "")?trim($cid_masquerade):$extension; + $astman->database_put("AMPUSER",$extension."/password",isset($password)?$password:''); + $astman->database_put("AMPUSER",$extension."/ringtimer",isset($ringtimer)?$ringtimer:''); + $astman->database_put("AMPUSER",$extension."/noanswer",isset($noanswer)?$noanswer:''); + $astman->database_put("AMPUSER",$extension."/recording",isset($recording)?$recording:''); + $astman->database_put("AMPUSER",$extension."/outboundcid",isset($outboundcid)?"\"".$outboundcid."\"":''); + $astman->database_put("AMPUSER",$extension."/cidname",isset($name)?"\"".$name."\"":''); + $astman->database_put("AMPUSER",$extension."/cidnum",$cid_masquerade); + $astman->database_put("AMPUSER",$extension."/voicemail","\"".isset($voicemail)?$voicemail:''."\""); + switch ($call_screen) { + case '0': + $astman->database_del("AMPUSER",$extension."/screen"); + break; + case 'nomemory': + $astman->database_put("AMPUSER",$extension."/screen","\"nomemory\""); + break; + case 'memory': + $astman->database_put("AMPUSER",$extension."/screen","\"memory\""); + break; + default: + } + + if (!$editmode) { + $astman->database_put("AMPUSER",$extension."/device","\"".((isset($device))?$device:'')."\""); + } + + if (trim($callwaiting) == 'enabled') { + $astman->database_put("CW",$extension,"\"ENABLED\""); + } else if (trim($callwaiting) == 'disabled') { + $astman->database_del("CW",$extension); + } else { + echo "ERROR: this state should not exist
"; + } + + // Moved VmX setup to voicemail module since it is part of voicemail + // + } else { + fatal("Cannot connect to Asterisk Manager with ".$amp_conf["AMPMGRUSER"]."/".$amp_conf["AMPMGRPASS"]); + } + + // OK - got this far, if they entered a new inbound DID/CID let's deal with it now + // remember - in the nice and ugly world of this old code, $vars has been extracted + // newdid and newdidcid + + // Now if $newdid is set we need to add the DID to the routes + // + if ($newdid != '' || $newdidcid != '') { + $did_dest = 'from-did-direct,'.$extension.',1'; + $did_vars['extension'] = $newdid; + $did_vars['cidnum'] = $newdidcid; + $did_vars['faxexten'] = ''; + $did_vars['faxemail'] = ''; + $did_vars['answer'] = '0'; + $did_vars['wait'] = '0'; + $did_vars['privacyman'] = ''; + $did_vars['alertinfo'] = ''; + $did_vars['ringing'] = ''; + $did_vars['mohclass'] = 'default'; + $did_vars['description'] = $newdid_name; + $did_vars['grppre'] = ''; + $did_vars['delay_answer']= '0'; + $did_vars['pricid']= ''; + core_did_add($did_vars, $did_dest); + } + + return true; +} + +function core_users_get($extension){ + global $db; + global $amp_conf; + global $astman; + //get all the variables for the meetme + $sql = "SELECT * FROM users WHERE extension = '$extension'"; + $results = $db->getRow($sql,DB_FETCHMODE_ASSOC); + if(DB::IsError($results)) { + die_freepbx($results->getMessage().$sql); + } + if (empty($results)) { + return array(); + } + + //explode recording vars + $recording = explode("|",$results['recording']); + if (isset($recording[1])) { + $recout = substr($recording[0],4); + $recin = substr($recording[1],3); + $results['record_in']=$recin; + $results['record_out']=$recout; + } else { + $results['record_in']='Adhoc'; + $results['record_out']='Adhoc'; + } + if ($astman) { + $cw = $astman->database_get("CW",$extension); + $results['callwaiting'] = (trim($cw) == 'ENABLED') ? 'enabled' : 'disabled'; + $cid_masquerade=$astman->database_get("AMPUSER",$extension."/cidnum"); + $results['cid_masquerade'] = (trim($cid_masquerade) != "")?$cid_masquerade:$extension; + + $call_screen=$astman->database_get("AMPUSER",$extension."/screen"); + $results['call_screen'] = (trim($call_screen) != "")?$call_screen:'0'; + } else { + fatal("Cannot connect to Asterisk Manager with ".$amp_conf["AMPMGRUSER"]."/".$amp_conf["AMPMGRPASS"]); + } + + return $results; +} + +function core_users_del($extension, $editmode=false){ + global $db; + global $amp_conf; + global $astman; + + //delete from devices table + $sql="DELETE FROM users WHERE extension = \"$extension\""; + $results = $db->query($sql); + if(DB::IsError($results)) { + die_freepbx($results->getMessage().$sql); + } + + //delete details to astdb + if($astman) { + $astman->database_del("AMPUSER",$extension."/screen"); + } + if ($astman && !$editmode) { + // TODO just change this to delete everything + $astman->database_deltree("AMPUSER/".$extension); + } +} + +function core_users_directdid_get($directdid=""){ + return array(); +} + +function core_users_cleanastdb($extension) { + // This is called to remove any ASTDB traces of the user after a deletion. Otherwise, + // call forwarding, call waiting settings could hang around and bite someone if they + // recycle an extension. Is called from page.xtns and page.users. + global $amp_conf; + global $astman; + + if ($astman) { + $astman->database_del("CW",$extension); + $astman->database_del("CF",$extension); + $astman->database_del("CFB",$extension); + $astman->database_del("CFU",$extension); + + } else { + fatal("Cannot connect to Asterisk Manager with ".$amp_conf["AMPMGRUSER"]."/".$amp_conf["AMPMGRPASS"]); + } +} + +function core_users_edit($extension,$vars){ + global $db; + global $amp_conf; + global $astman; + + //I we are editing, we need to remember existing user<->device mapping, so we can delete and re-add + if ($astman) { + $ud = $astman->database_get("AMPUSER",$extension."/device"); + $current_vmcontext = $astman->database_get("AMPUSER",$extension."/voicemail"); + $new_vmcontext = isset($vars['vmcontext']) ? $vars['vmcontext'] : 'novm'; + $vars['device'] = $ud; + } else { + fatal("Cannot connect to Asterisk Manager with ".$amp_conf["AMPMGRUSER"]."/".$amp_conf["AMPMGRPASS"]); + } + + // clean and check the did to make sure it is not being used by another extension or in did routing + // + $newdid_name = isset($newdid_name) ? $db->escapeSimple($newdid_name) : ''; + $newdid = isset($vars['newdid']) ? $vars['newdid'] : ''; + $newdid = preg_replace("/[^0-9._XxNnZz\[\]\-\+]/" ,"", trim($newdid)); + + $newdidcid = isset($vars['newdidcid']) ? trim($vars['newdidcid']) : ''; + if (!preg_match('/^priv|^block|^unknown|^restrict|^unavail|^anonym/',strtolower($newdidcid))) { + $newdidcid = preg_replace("/[^0-9._XxNnZz\[\]\-\+]/" ,"", $newdidcid); + } + + // Well more ugliness since the javascripts are already in here + if ($newdid != '' || $newdidcid != '') { + $existing = core_did_get($newdid, $newdidcid); + if (! empty($existing)) { + echo ""; + return false; + } + } + + //delete and re-add + if (core_sipname_check($vars['sipname'],$extension)) { + core_users_del($extension, true); + core_users_add($vars, true); + + // If the vmcontext has changed, we need to change all the links. In extension mode, the link + // to the current fixed device will get changed, but none others will + // + if ($current_vmcontext != $new_vmcontext) { + $user_devices = explode('&',$ud); + foreach ($user_devices as $user_device) { + exec("rm -f /var/spool/asterisk/voicemail/device/".$user_device); + if ($new_context != 'novm') { + exec("/bin/ln -s /var/spool/asterisk/voicemail/".$new_vmcontext."/".$extension."/ /var/spool/asterisk/voicemail/device/".$user_device); + } + } + } + } + return true; +} + +function core_directdid_list(){ + return array(); +} + +function core_zapchandids_add($description, $channel, $did) { + global $db; + + + if (!ctype_digit(trim($channel)) || trim($channel) == '') { + echo ""; + return false; + } + if (trim($did) == '') { + echo ""; + return false; + } + + $description = q($description); + $channel = q($channel); + $did = q($did); + + $sql = "INSERT INTO zapchandids (channel, description, did) VALUES ($channel, $description, $did)"; + $results = $db->query($sql); + if (DB::IsError($results)) { + if ($results->getCode() == DB_ERROR_ALREADY_EXISTS) { + echo ""; + return false; + } else { + die_freepbx($results->getMessage()."

".$sql); + } + } + return true; +} + +function core_zapchandids_edit($description, $channel, $did) { + global $db; + + $description = q($description); + $channel = q($channel); + $did = q($did); + + $sql = "UPDATE zapchandids SET description = $description, did = $did WHERE channel = $channel"; + $results = $db->query($sql); + if (DB::IsError($results)) { + die_freepbx($results->getMessage()."

".$sql); + } + return true; +} + +function core_zapchandids_delete($channel) { + global $db; + + $channel = q($channel); + + $sql = "DELETE FROM zapchandids WHERE channel = $channel"; + $results = $db->query($sql); + if (DB::IsError($results)) { + die_freepbx($results->getMessage()."

".$sql); + } + return true; +} + +function core_zapchandids_list() { + global $db; + + $sql = "SELECT * FROM zapchandids ORDER BY channel"; + return sql($sql,"getAll",DB_FETCHMODE_ASSOC); +} + +function core_zapchandids_get($channel) { + global $db; + + $channel = q($channel); + + $sql = "SELECT * FROM zapchandids WHERE channel = $channel"; + return sql($sql,"getRow",DB_FETCHMODE_ASSOC); +} + +/* end page.users.php functions */ + + + + + +/* begin page.trunks.php functions */ + +// we're adding ,don't require a $trunknum +function core_trunks_add($tech, $channelid, $dialoutprefix, $maxchans, $outcid, $peerdetails, $usercontext, $userconfig, $register, $keepcid, $failtrunk, $disabletrunk) { + global $db; + + // find the next available ID + $trunknum = 1; + + // This is pretty ugle, will fix when we redo trunks and routes with proper uniqueids. + // get the list, sort them, then look for a hole and use it, or overflow to the end if + // not and use that + // + $trunk_hash = array(); + foreach(core_trunks_list() as $trunk) { + $trunknum = ltrim($trunk[0],"OUT_"); + $trunk_hash[] = $trunknum; + } + sort($trunk_hash); + $trunknum = 1; + foreach ($trunk_hash as $trunk_id) { + if ($trunk_id != $trunknum) { + break; + } + $trunknum++; + } + + core_trunks_backendAdd($trunknum, $tech, $channelid, $dialoutprefix, $maxchans, $outcid, $peerdetails, $usercontext, $userconfig, $register, $keepcid, $failtrunk, $disabletrunk); + + return $trunknum; +} + +function core_trunks_del($trunknum, $tech = null) { + global $db; + + if ($tech === null) { // in EditTrunk, we get this info anyways + $tech = core_trunks_getTrunkTech($trunknum); + } + + //delete from globals table + sql("DELETE FROM globals WHERE variable IN ('OUT_$trunknum','OUTCID_$trunknum','OUTMAXCHANS_$trunknum','OUTPREFIX_$trunknum','OUTKEEPCID_$trunknum','OUTFAIL_$trunknum','OUTDISABLE_$trunknum')"); + + // conditionally, delete from iax or sip + switch (strtolower($tech)) { + case "iax": + case "iax2": + sql("DELETE FROM iax WHERE id = '9999$trunknum' OR id = '99999$trunknum' OR id = '9999999$trunknum'"); + break; + case "sip": + sql("DELETE FROM sip WHERE id = '9999$trunknum' OR id = '99999$trunknum' OR id = '9999999$trunknum'"); + break; + } +} + +function core_trunks_edit($trunknum, $channelid, $dialoutprefix, $maxchans, $outcid, $peerdetails, $usercontext, $userconfig, $register, $keepcid, $failtrunk, $disabletrunk) { + //echo "editTrunk($trunknum, $channelid, $dialoutprefix, $maxchans, $outcid, $peerdetails, $usercontext, $userconfig, $register)"; + $tech = core_trunks_getTrunkTech($trunknum); + core_trunks_del($trunknum, $tech); + core_trunks_backendAdd($trunknum, $tech, $channelid, $dialoutprefix, $maxchans, $outcid, $peerdetails, $usercontext, $userconfig, $register, $keepcid, $failtrunk, $disabletrunk); +} + +// just used internally by addTrunk() and editTrunk() +//obsolete +function core_trunks_backendAdd($trunknum, $tech, $channelid, $dialoutprefix, $maxchans, $outcid, $peerdetails, $usercontext, $userconfig, $register, $keepcid, $failtrunk, $disabletrunk) { + global $db; + + if (is_null($dialoutprefix)) $dialoutprefix = ""; // can't be NULL + + //echo "backendAddTrunk($trunknum, $tech, $channelid, $dialoutprefix, $maxchans, $outcid, $peerdetails, $usercontext, $userconfig, $register)"; + + // change iax to "iax2" (only spot we actually store iax2, since its used by Dial()..) + $techtemp = ((strtolower($tech) == "iax") ? "iax2" : $tech); + $outval = (($techtemp == "custom") ? "AMP:".$channelid : strtoupper($techtemp).'/'.$channelid); + + + $glofields = array( + array('OUT_'.$trunknum, $outval), + array('OUTPREFIX_'.$trunknum, $dialoutprefix), + array('OUTMAXCHANS_'.$trunknum, $maxchans), + array('OUTCID_'.$trunknum, $outcid), + array('OUTKEEPCID_'.$trunknum, $keepcid), + array('OUTFAIL_'.$trunknum, $failtrunk), + array('OUTDISABLE_'.$trunknum, $disabletrunk), + ); + + unset($techtemp); + + $compiled = $db->prepare('INSERT INTO globals (variable, value) values (?,?)'); + $result = $db->executeMultiple($compiled,$glofields); + if(DB::IsError($result)) { + die_freepbx($result->getMessage()."

".$sql); + } + + $disable_flag = ($disabletrunk == "on")?1:0; + + switch (strtolower($tech)) { + case "iax": + case "iax2": + core_trunks_addSipOrIax($peerdetails,'iax',$channelid,$trunknum,$disable_flag); + if ($usercontext != ""){ + core_trunks_addSipOrIax($userconfig,'iax',$usercontext,'9'.$trunknum,$disable_flag); + } + if ($register != ""){ + core_trunks_addRegister($trunknum,'iax',$register,$disable_flag); + } + break; + case "sip": + core_trunks_addSipOrIax($peerdetails,'sip',$channelid,$trunknum,$disable_flag); + if ($usercontext != ""){ + core_trunks_addSipOrIax($userconfig,'sip',$usercontext,'9'.$trunknum,$disable_flag); + } + if ($register != ""){ + core_trunks_addRegister($trunknum,'sip',$register,$disable_flag); + } + break; + } +} + +function core_trunks_getTrunkTech($trunknum) { + + $results = sql("SELECT value FROM globals WHERE variable = 'OUT_".$trunknum."'","getAll"); + if (!$results) { + return false; + } + if(strpos($results[0][0],"AMP:") === 0) { //custom trunks begin with AMP: + $tech = "custom"; + } else { + $tech = strtolower( strtok($results[0][0],'/') ); // the technology. ie: ZAP/g0 is ZAP + + if ($tech == "iax2") $tech = "iax"; // same thing, here + } + return $tech; +} + +//add trunk info to sip or iax table +function core_trunks_addSipOrIax($config,$table,$channelid,$trunknum,$disable_flag=0) { + global $db; + + $confitem['account'] = $channelid; + $gimmieabreak = nl2br($config); + $lines = split('
',$gimmieabreak); + foreach ($lines as $line) { + $line = trim($line); + if (count(split('=',$line)) > 1) { + $tmp = split('=',$line,2); + $key=trim($tmp[0]); + $value=trim($tmp[1]); + if (isset($confitem[$key]) && !empty($confitem[$key])) + $confitem[$key].="&".$value; + else + $confitem[$key]=$value; + } + } + // rember 1=disabled so we start at 2 (1 + the first 1) + $seq = 1; + foreach($confitem as $k=>$v) { + $seq = ($disable_flag == 1) ? 1 : $seq+1; + $dbconfitem[]=array($k,$v,$seq); + } + $compiled = $db->prepare("INSERT INTO $table (id, keyword, data, flags) values ('9999$trunknum',?,?,?)"); + $result = $db->executeMultiple($compiled,$dbconfitem); + if(DB::IsError($result)) { + die_freepbx($result->getMessage()."

INSERT INTO $table (id, keyword, data, flags) values ('9999$trunknum',?,?,'$disable_flag')"); + } +} + +//Sort trunks for sqlite +function sort_trunks($a,$b) { + global $unique_trunks; + ereg("OUT_([0-9]+)",$unique_trunks[$a][0],$trunk_num1); + ereg("OUT_([0-9]+)",$unique_trunks[$b][0],$trunk_num2); + return ($trunk_num1[1] >= $trunk_num2[1]? 1:-1); +} + +//get unique trunks +function core_trunks_list($assoc = false) { + // TODO: $assoc default to true, eventually.. + + global $db; + global $amp_conf; + + // sqlite doesn't support the syntax required for the SQL so we have to do it the hard way + if ($amp_conf["AMPDBENGINE"] == "sqlite3") + { + $sqlstr = "SELECT variable, value FROM globals WHERE variable LIKE 'OUT\_%' ESCAPE '\'"; + $my_unique_trunks = sql($sqlstr,"getAll",DB_FETCHMODE_ASSOC); + + $sqlstr = "SELECT variable, value FROM globals WHERE variable LIKE 'OUTDISABLE\_%' ESCAPE '\'"; + $disable_states = sql($sqlstr,"getAll",DB_FETCHMODE_ASSOC); + + foreach($disable_states as $arr) { + $disable_states_assoc[$arr['variable']] = $arr['value']; + } + global $unique_trunks; + $unique_trunks = array(); + + foreach ($my_unique_trunks as $this_trunk) { + + $trunk_num = substr($this_trunk['variable'],4); + $this_state = (isset($disable_states_assoc['OUTDISABLE_'.$trunk_num]) ? $disable_states_assoc['OUTDISABLE_'.$trunk_num] : 'off'); + $unique_trunks[] = array($this_trunk['variable'], $this_trunk['value'], $this_state); + } + // sort this array using a custom function sort_trunks(), defined above + uksort($unique_trunks,"sort_trunks"); + // re-index the newly sorted array + foreach($unique_trunks as $arr) { + $unique_trunks_t[] = array($arr[0],$arr[1],$arr[2]); + } + $unique_trunks = $unique_trunks_t; + + } + else + { + $sqlstr = "SELECT t.variable, t.value, d.value state FROM `globals` t "; + $sqlstr .= "JOIN (SELECT x.variable, x.value FROM globals x WHERE x.variable LIKE 'OUTDISABLE\_%') d "; + $sqlstr .= "ON substring(t.variable,5) = substring(d.variable,12) WHERE t.variable LIKE 'OUT\_%' "; + $sqlstr .= "UNION ALL "; + $sqlstr .= "SELECT v.variable, v.value, concat(substring(v.value,1,0),'off') state FROM `globals` v "; + $sqlstr .= "WHERE v.variable LIKE 'OUT\_%' AND concat('OUTDISABLE_',substring(v.variable,5)) NOT IN "; + $sqlstr .= " ( SELECT variable from globals WHERE variable LIKE 'OUTDISABLE\_%' ) "; + $sqlstr .= "ORDER BY variable"; + //$unique_trunks = sql("SELECT * FROM globals WHERE variable LIKE 'OUT_%' ORDER BY variable","getAll"); + $unique_trunks = sql($sqlstr,"getAll"); + } + + //if no trunks have ever been defined, then create the proper variables with the default zap trunk + // TODO: this looks dumb, updated to remove deprecated values but why can't there be no trunks? + // + if (count($unique_trunks) == 0) + { + sql("INSERT INTO globals (variable, value) values ('OUT_1','ZAP/g0')"); + $unique_trunks[] = array('OUT_1','ZAP/g0'); + } + // asort($unique_trunks); + + if ($assoc) { + $trunkinfo = array(); + + foreach ($unique_trunks as $trunk) { + list($tech,$name) = explode('/',$trunk[1]); + $trunkinfo[$trunk[1]] = array( + 'name' => $name, + 'tech' => $tech, + 'globalvar' => $trunk[0], // ick + 'value' => $trunk[2], // ?? no idea what this is. + ); + } + return $trunkinfo; + } else { + return $unique_trunks; + } +} + +function core_trunks_addRegister($trunknum,$tech,$reg,$disable_flag=0) { + sql("INSERT INTO $tech (id, keyword, data, flags) values ('9999999$trunknum','register','$reg','$disable_flag')"); +} + + +function core_trunks_addDialRules($trunknum, $dialrules) { + $values = array(); + $i = 1; + foreach ($dialrules as $rule) { + $values["rule".$i++] = $rule; + } + + $conf = core_trunks_readDialRulesFile(); + + // rewrite for this trunk + $conf["trunk-".$trunknum] = $values; + + core_trunks_writeDialRulesFile($conf); +} + +function core_trunks_readDialRulesFile() { + global $amp_conf; + $localPrefixFile = $amp_conf['ASTETCDIR']."/localprefixes.conf"; + + core_trunks_parse_conf($localPrefixFile, $conf, $section); + + return $conf; +} + +function core_trunks_writeDialRulesFile($conf) { + global $amp_conf; + $localPrefixFile = $amp_conf['ASTETCDIR']."/localprefixes.conf"; + + $fd = fopen($localPrefixFile,"w"); + foreach ($conf as $section=>$values) { + fwrite($fd, "[".$section."]\n"); + foreach ($values as $key=>$value) { + fwrite($fd, $key."=".$value."\n"); + } + fwrite($fd, "\n"); + } + fclose($fd); +} + +function core_trunks_parse_conf($filename, &$conf, &$section) { + if (is_null($conf)) { + $conf = array(); + } + if (is_null($section)) { + $section = "general"; + } + + if (file_exists($filename)) { + $fd = fopen($filename, "r"); + while ($line = fgets($fd, 1024)) { + if (preg_match("/^\s*([a-zA-Z0-9-_]+)\s*=\s*(.*?)\s*([;#].*)?$/",$line,$matches)) { + // name = value + // option line + $conf[$section][ $matches[1] ] = $matches[2]; + } else if (preg_match("/^\s*\[(.+)\]/",$line,$matches)) { + // section name + $section = strtolower($matches[1]); + } else if (preg_match("/^\s*#include\s+(.*)\s*([;#].*)?/",$line,$matches)) { + // include another file + + if ($matches[1][0] == "/") { + // absolute path + $filename = $matches[1]; + } else { + // relative path + $filename = dirname($filename)."/".$matches[1]; + } + + core_trunks_parse_conf($filename, $conf, $section); + } + } + } +} + +function core_trunks_getTrunkTrunkName($trunknum) { + $results = sql("SELECT value FROM globals WHERE variable = 'OUT_".$trunknum."'","getAll"); + if (!$results) { + return false; + } + + if(strpos($results[0][0],"AMP:") === 0) { //custom trunks begin with AMP: + $tname = substr($results[0][0],4); + } else { + strtok($results[0][0],'/'); + $tname = strtok('/'); // the text _after_ technology. ie: ZAP/g0 is g0 + } + return $tname; +} + +//get and print peer details (prefixed with 4 9's) +function core_trunks_getTrunkPeerDetails($trunknum) { + global $db; + + $tech = core_trunks_getTrunkTech($trunknum); + + if ($tech == "zap") return ""; // zap has no details + + $results = sql("SELECT keyword,data FROM $tech WHERE id = '9999$trunknum' ORDER BY flags, keyword DESC","getAll"); + + foreach ($results as $result) { + if ($result[0] != 'account') { + if (isset($confdetail)) + $confdetail .= $result[0] .'='. $result[1] . "\n"; + else + $confdetail = $result[0] .'='. $result[1] . "\n"; + } + } + return $confdetail; +} + +//get trunk user context (prefixed with 5 9's) +function core_trunks_getTrunkUserContext($trunknum) { + $tech = core_trunks_getTrunkTech($trunknum); + if ($tech == "zap") return ""; // zap has no account + + $results = sql("SELECT keyword,data FROM $tech WHERE id = '99999$trunknum'","getAll"); + + foreach ($results as $result) { + if ($result[0] == 'account') { + $account = $result[1]; + } + } + return isset($account)?$account:null; +} + +//get and print user config (prefixed with 5 9's) +function core_trunks_getTrunkUserConfig($trunknum) { + global $db; + + $tech = core_trunks_getTrunkTech($trunknum); + + if ($tech == "zap") return ""; // zap has no details + + $results = sql("SELECT keyword,data FROM $tech WHERE id = '99999$trunknum' ORDER BY flags, keyword DESC","getAll"); + + foreach ($results as $result) { + if ($result[0] != 'account') { + if (isset($confdetail)) + $confdetail .= $result[0] .'='. $result[1] . "\n"; + else + $confdetail = $result[0] .'='. $result[1] . "\n"; + } + } + return isset($confdetail)?$confdetail:null; +} + +//get trunk account register string +function core_trunks_getTrunkRegister($trunknum) { + $tech = core_trunks_getTrunkTech($trunknum); + + if ($tech == "zap") return ""; // zap has no register + + $results = sql("SELECT keyword,data FROM $tech WHERE id = '9999999$trunknum'","getAll"); + + foreach ($results as $result) { + $register = $result[1]; + } + return isset($register)?$register:null; +} + +function core_trunks_getDialRules($trunknum) { + $conf = core_trunks_readDialRulesFile(); + if (isset($conf["trunk-".$trunknum])) { + return $conf["trunk-".$trunknum]; + } + return false; +} + +//get outbound routes for a given trunk +function core_trunks_gettrunkroutes($trunknum) { + global $amp_conf; + + if ($amp_conf["AMPDBENGINE"] == "sqlite3") + $sql_code = "SELECT DISTINCT context, priority FROM extensions WHERE context LIKE 'outrt-%' AND (args LIKE 'dialout-trunk,".$trunknum.",%' OR args LIKE 'dialout-enum,".$trunknum.",%' OR args LIKE 'dialout-dundi,".$trunknum.",%') ORDER BY context"; + else + $sql_code = "SELECT DISTINCT SUBSTRING(context,7), priority FROM extensions WHERE context LIKE 'outrt-%' AND (args LIKE 'dialout-trunk,".$trunknum.",%' OR args LIKE 'dialout-enum,".$trunknum.",%' OR args LIKE 'dialout-dundi,".$trunknum.",%') ORDER BY context"; + + $results = sql( $sql_code, "getAll" ); + + foreach ($results as $row) { + // original code was: + // $routes[$row[0]] = $row[1]; + // but substring is not supported in sqlite3. + // how about we remove the 2nd part of the "if"? and use the same code on all DB's? + + $t = ($amp_conf["AMPDBENGINE"] == "sqlite3") ? substr( $row[0], 7 ) : $row[0]; + $r = $row[1]; + $routes[ $r ] = $t; + + } + // array(routename=>priority) + return isset($routes)?$routes:null; +} + +function core_trunks_deleteDialRules($trunknum) { + $conf = core_trunks_readDialRulesFile(); + + // remove rules for this trunk + unset($conf["trunk-".$trunknum]); + + core_trunks_writeDialRulesFile($conf); +} + +/* end page.trunks.php functions */ + + +/* begin page.routing.php functions */ + +//get unique outbound route names +function core_routing_getroutenames() +{ + global $amp_conf; + + if ($amp_conf["AMPDBENGINE"] == "sqlite3") + { + // SUBSTRING is not supported under sqlite3, we need to filter + // this in php. I am not sure why "6" and not "7" + // but I don't really care -> it works :) + $results = sql("SELECT DISTINCT context FROM extensions WHERE context LIKE 'outrt-%' ORDER BY context ","getAll"); + foreach( array_keys($results) as $idx ) + { + $results[$idx][0] = substr( $results[$idx][0], 6); + } + } + else + { + // we SUBSTRING() to remove "outrt-" + $results = sql("SELECT DISTINCT SUBSTRING(context,7) FROM extensions WHERE context LIKE 'outrt-%' ORDER BY context ","getAll"); + } + + + //TODO: This needs to be yanked, should be in the upgrade script somewhere not here + // + if (count($results) == 0) { + // see if they're still using the old dialprefix method + if ($amp_conf["AMPDBENGINE"] == "sqlite3") { + $sql ="SELECT variable,value FROM globals WHERE variable LIKE 'DIAL\_OUT\_%' ESCAPE '\'"; + } + else { + $sql ="SELECT variable,value FROM globals WHERE variable LIKE 'DIAL\\\_OUT\\\_%'"; + } + $results = sql($sql,"getAll"); + // we SUBSTRING() to remove "outrt-" + + if (count($results) > 0) { + // yes, they are using old method, let's update + + // get the default trunk + $results_def = sql("SELECT value FROM globals WHERE variable = 'OUT'","getAll"); + + if (preg_match("/{OUT_(\d+)}/", $results_def[0][0], $matches)) { + $def_trunk = $matches[1]; + } else { + $def_trunk = ""; + } + + $default_patterns = array( // default patterns that used to be in extensions.conf + "NXXXXXX", + "NXXNXXXXXX", + "1800NXXXXXX", + "1888NXXXXXX", + "1877NXXXXXX", + "1866NXXXXXX", + "1NXXNXXXXXX", + "011.", + "911", + "411", + "311", + ); + + foreach ($results as $temp) { + // temp[0] is "DIAL_OUT_1" + // temp[1] is the dial prefix + + $trunknum = substr($temp[0],9); + + $name = "route".$trunknum; + + $trunks = array(1=>"OUT_".$trunknum); // only one trunk to use + + $patterns = array(); + foreach ($default_patterns as $pattern) { + $patterns[] = $temp[1]."|".$pattern; + } + + if ($trunknum == $def_trunk) { + // this is the default trunk, add the patterns with no prefix + $patterns = array_merge($patterns, $default_patterns); + } + + // add this as a new route + core_routing_add($name, $patterns, $trunks,"new"); + } + + + // delete old values + if ($amp_conf["AMPDBENGINE"] == "sqlite3") { + $sql = "DELETE FROM globals WHERE (variable LIKE 'DIAL\_OUT\_%') ESCAPE '\' OR (variable = 'OUT') "; + } + else { + $sql = "DELETE FROM globals WHERE (variable LIKE 'DIAL\\\_OUT\\\_%') OR (variable = 'OUT') "; + } + sql($sql); + + // we need to re-generate extensions_additional.conf + // i'm not sure how to do this from here + + // re-run our query + $results = sql("SELECT DISTINCT SUBSTRING(context,7) FROM extensions WHERE context LIKE 'outrt-%' ORDER BY context ","getAll"); + // we SUBSTRING() to remove "outrt-" + } + + } // else, it just means they have no routes. + + return $results; +} + +function core_routing_setroutepriority($routepriority, $reporoutedirection, $reporoutekey) +{ + global $db, $amp_conf; + $counter=-1; + foreach ($routepriority as $tresult) + { + $counter++; + if (($counter==($reporoutekey-1)) && ($reporoutedirection=="up")) { + // swap this one with the one before (move up) + $temproute = $routepriority[$counter]; + $routepriority[ $counter ] = $routepriority[ $counter+1 ]; + $routepriority[ $counter+1 ] = $temproute; + + } else if (($counter==($reporoutekey)) && ($reporoutedirection=="down")) { + // swap this one with the one after (move down) + $temproute = $routepriority[ $counter+1 ]; + $routepriority[ $counter+1 ] = $routepriority[ $counter ]; + $routepriority[ $counter ] = $temproute; + } + } + unset($temproute); + $routepriority = array_values($routepriority); // resequence our numbers + $counter=0; + foreach ($routepriority as $tresult) { + $order=core_routing_setroutepriorityvalue($counter++); + $sql = sprintf("Update extensions set context='outrt-%s-%s' WHERE context='outrt-%s'",$order,substr($tresult[0],4), $tresult[0]); + $result = $db->query($sql); + if(DB::IsError($result)) { + die_freepbx($result->getMessage()); + } + } + + // Delete and readd the outbound-allroutes entries + $sql = "delete from extensions WHERE context='outbound-allroutes'"; + $result = $db->query($sql); + if(DB::IsError($result)) { + die_freepbx($result->getMessage().$sql); + } + + $sql = "SELECT DISTINCT context FROM extensions WHERE context like 'outrt-%' ORDER BY context"; + $results = $db->getAll($sql); + if(DB::IsError($results)) { + die_freepbx($results->getMessage()); + } + + $priority_loops=1; + foreach ($results as $row) { + $sql = "INSERT INTO extensions (context, extension, priority, application, args, descr, flags) VALUES "; + $sql .= "('outbound-allroutes', "; + $sql .= "'include', "; + $sql .= "'".$priority_loops++."', "; + $sql .= "'".$row[0]."', "; + $sql .= "'', "; + $sql .= "'', "; + $sql .= "'2')"; + + //$sql = sprintf("Update extensions set application='outrt-%s-%s' WHERE context='outbound-allroutes' and application='outrt-%s'",$order,substr($tresult[0],4), $tresult[0]); + $result = $db->query($sql); + if(DB::IsError($result)) { + die_freepbx($result->getMessage(). $sql); + } + } + + if ( $amp_conf["AMPDBENGINE"] == "sqlite3") + $sql = "SELECT DISTINCT context FROM extensions WHERE context LIKE 'outrt-%' ORDER BY context "; + else + $sql = "SELECT DISTINCT SUBSTRING(context,7) FROM extensions WHERE context LIKE 'outrt-%' ORDER BY context "; + + // we SUBSTRING() to remove "outrt-" + $routepriority = $db->getAll($sql); + if(DB::IsError($routepriority)) { + die_freepbx($routepriority->getMessage()); + } + + // TODO: strip the context on the sqlite3 backend + // not sure where does it effects, since this is working on my setup... + // welcome to funky town + return ($routepriority); +} + +function core_routing_setroutepriorityvalue($key) +{ + $key=$key+1; + if ($key<10) + $prefix = sprintf("00%d",$key); + else if ((9<$key)&&($key<100)) + $prefix = sprintf("0%d",$key); + else if ($key>100) + $prefix = sprintf("%d",$key); + return ($prefix); +} + + +function core_routing_add($name, $patterns, $trunks, $method, $pass, $emergency = "", $intracompany = "", $mohsilence = "") { + + global $db; + + $trunktech=array(); + + // Make sure only valid characters are there, javascript should enforce this (and more) + // + $name = preg_replace("/[^a-zA-Z0-9_\-]/" ,"",$name); + + //Retrieve each trunk tech for later lookup + if ($amp_conf["AMPDBENGINE"] == "sqlite3") { + $sql="select * from globals WHERE variable LIKE 'OUT\_%' ESCAPE '\'"; + } + else { + $sql="select * from globals WHERE variable LIKE 'OUT\\_%'"; + } + $result = $db->getAll($sql); + if(DB::IsError($result)) { + die_freepbx($result->getMessage()); + } + foreach($result as $tr) { + $tech = strtok($tr[1], "/"); + $trunktech[$tr[0]]=$tech; + } + + if ($method=="new") { + $sql="select DISTINCT context FROM extensions WHERE context LIKE 'outrt-%' ORDER BY context"; + $routepriority = $db->getAll($sql); + if(DB::IsError($result)) { + die_freepbx($result->getMessage()); + } + $order=core_routing_setroutepriorityvalue(count($routepriority)); + $name = sprintf ("%s-%s",$order,$name); + } + $trunks = array_values($trunks); // probably already done, but it's important for our dialplan + + + foreach ($patterns as $pattern) { + if (false !== ($pos = strpos($pattern,"|"))) { + // we have a | meaning to not pass the digits on + // (ie, 9|NXXXXXX should use the pattern _9NXXXXXX but only pass NXXXXXX, not the leading 9) + + $pattern = str_replace("|","",$pattern); // remove all |'s + $exten = "EXTEN:".$pos; // chop off leading digit + } else { + // we pass the full dialed number as-is + $exten = "EXTEN"; + } + + if (!preg_match("/^[0-9*]+$/",$pattern)) { + // note # is not here, as asterisk doesn't recoginize it as a normal digit, thus it requires _ pattern matching + + // it's not strictly digits, so it must have patterns, so prepend a _ + $pattern = "_".$pattern; + } + + // 1st priority is emergency dialing variable (if set) + if(!empty($emergency)) { + $startpriority = 1; + $sql = "INSERT INTO extensions (context, extension, priority, application, args, descr) VALUES "; + $sql .= "('outrt-".$name."', "; + $sql .= "'".$pattern."', "; + $sql .= "'".$startpriority."', "; + $sql .= "'SetVar', "; + $sql .= "'EMERGENCYROUTE=YES', "; + $sql .= "'Use Emergency CID for device')"; + $result = $db->query($sql); + if(DB::IsError($result)) { + die_freepbx($result->getMessage()); + } + } else { + $startpriority = 0; + } + + // Next Priority (either first or second depending on above) + if(!empty($intracompany)) { + $startpriority += 1; + $sql = "INSERT INTO extensions (context, extension, priority, application, args, descr) VALUES "; + $sql .= "('outrt-".$name."', "; + $sql .= "'".$pattern."', "; + $sql .= "'".$startpriority."', "; + $sql .= "'SetVar', "; + $sql .= "'INTRACOMPANYROUTE=YES', "; + $sql .= "'Preserve Intenal CID Info')"; + $result = $db->query($sql); + if(DB::IsError($result)) { + die_freepbx($result->getMessage()); + } + } + + // Next Priority (either first, second or third depending on above) + if(!empty($mohsilence) && trim($mohsilence) != 'default') { + $startpriority += 1; + $sql = "INSERT INTO extensions (context, extension, priority, application, args, descr) VALUES "; + $sql .= "('outrt-".$name."', "; + $sql .= "'".$pattern."', "; + $sql .= "'".$startpriority."', "; + $sql .= "'SetVar', "; + $sql .= "'MOHCLASS=".$mohsilence."', "; + $sql .= "'Do not play moh on this route')"; + $result = $db->query($sql); + if(DB::IsError($result)) { + die_freepbx($result->getMessage()); + } + } + + $first_trunk = 1; + foreach ($trunks as $priority => $trunk) { + $priority += $startpriority; + $priority += 1; // since arrays are 0-based, but we want priorities to start at 1 + + $sql = "INSERT INTO extensions (context, extension, priority, application, args) VALUES "; + $sql .= "('outrt-".$name."', "; + $sql .= "'".$pattern."', "; + $sql .= "'".$priority."', "; + $sql .= "'Macro', "; + if ($first_trunk) + $pass_str = $pass; + else + $pass_str = ""; + + if ($trunktech[$trunk] == "ENUM") { + $sql .= "'dialout-enum,".substr($trunk,4).",\${".$exten."},".$pass_str."'"; // cut off OUT_ from $trunk + } else if ($trunktech[$trunk] == "DUNDI") { + $sql .= "'dialout-dundi,".substr($trunk,4).",\${".$exten."},".$pass_str."'"; // cut off OUT_ from $trunk + } else { + $sql .= "'dialout-trunk,".substr($trunk,4).",\${".$exten."},".$pass_str."'"; // cut off OUT_ from $trunk + } + $sql .= ")"; + + $result = $db->query($sql); + if(DB::IsError($result)) { + die_freepbx($result->getMessage()); + } + //To identify the first trunk in a pattern + //so that passwords are in the first trunk in + //each pattern + $first_trunk = 0; + } + + $priority += 1; + $sql = "INSERT INTO extensions (context, extension, priority, application, args, descr) VALUES "; + $sql .= "('outrt-".$name."', "; + $sql .= "'".$pattern."', "; + $sql .= "'".$priority."', "; + $sql .= "'Macro', "; + $sql .= "'outisbusy', "; + $sql .= "'No available circuits')"; + + $result = $db->query($sql); + if(DB::IsError($result)) { + die_freepbx($result->getMessage()); + } + } + + + // add an include=>outrt-$name to [outbound-allroutes]: + + // we have to find the first available priority.. priority doesn't really matter for the include, but + // there is a unique index on (context,extension,priority) so if we don't do this we can't put more than + // one route in the outbound-allroutes context. + $sql = "SELECT priority FROM extensions WHERE context = 'outbound-allroutes' AND extension = 'include'"; + $results = $db->getAll($sql); + if(DB::IsError($results)) { + die_freepbx($results->getMessage()); + } + $priorities = array(); + foreach ($results as $row) { + $priorities[] = $row[0]; + } + for ($priority = 1; in_array($priority, $priorities); $priority++); + + // $priority should now be the lowest available number + + $sql = "INSERT INTO extensions (context, extension, priority, application, args, descr, flags) VALUES "; + $sql .= "('outbound-allroutes', "; + $sql .= "'include', "; + $sql .= "'".$priority."', "; + $sql .= "'outrt-".$name."', "; + $sql .= "'', "; + $sql .= "'', "; + $sql .= "'2')"; + + $result = $db->query($sql); + if(DB::IsError($result)) { + die_freepbx($priority.$result->getMessage()); + } + +} + +function core_routing_edit($name, $patterns, $trunks, $pass, $emergency="", $intracompany = "", $mohsilence="") { + core_routing_del($name); + core_routing_add($name, $patterns, $trunks,"edit", $pass, $emergency, $intracompany, $mohsilence); +} + +function core_routing_del($name) { + global $db; + $sql = "DELETE FROM extensions WHERE context = 'outrt-".$name."'"; + $result = $db->query($sql); + if(DB::IsError($result)) { + die_freepbx($result->getMessage()); + } + + $sql = "DELETE FROM extensions WHERE context = 'outbound-allroutes' AND application = 'outrt-".$name."' "; + $result = $db->query($sql); + if(DB::IsError($result)) { + die_freepbx($result->getMessage()); + } + + return $result; +} + +function core_routing_rename($oldname, $newname) { + global $db; + + $route_prefix=substr($oldname,0,4); + $newname=$route_prefix.$newname; + $sql = "SELECT context FROM extensions WHERE context = 'outrt-".$newname."'"; + $results = $db->getAll($sql); + if (count($results) > 0) { + // there's already a route with this name + return false; + } + + $sql = "UPDATE extensions SET context = 'outrt-".$newname."' WHERE context = 'outrt-".$oldname."'"; + $result = $db->query($sql); + if(DB::IsError($result)) { + die_freepbx($result->getMessage()); + } + $mypriority=sprintf("%d",$route_prefix); + $sql = "UPDATE extensions SET application = 'outrt-".$newname."', priority = '$mypriority' WHERE context = 'outbound-allroutes' AND application = 'outrt-".$oldname."' "; + $result = $db->query($sql); + if(DB::IsError($result)) { + die_freepbx($result->getMessage()); + } + + return true; +} + +//get unique outbound route patterns for a given context +function core_routing_getroutepatterns($route) { + global $db; + $sql = "SELECT extension, args FROM extensions WHERE context = 'outrt-".$route."' AND (args LIKE 'dialout-trunk%' OR args LIKE 'dialout-enum%' OR args LIKE 'dialout-dundi%') ORDER BY extension "; + $results = $db->getAll($sql); + if(DB::IsError($results)) { + die_freepbx($results->getMessage()); + } + + $patterns = array(); + foreach ($results as $row) { + if ($row[0][0] == "_") { + // remove leading _ + $pattern = substr($row[0],1); + } else { + $pattern = $row[0]; + } + + if (preg_match("/{EXTEN:(\d+)}/", $row[1], $matches)) { + // this has a digit offset, we need to insert a | + $pattern = substr($pattern,0,$matches[1])."|".substr($pattern,$matches[1]); + } + + $patterns[] = $pattern; + } + return array_unique($patterns); +} + +//get unique outbound route trunks for a given context +function core_routing_getroutetrunks($route) { + global $db; + $sql = "SELECT DISTINCT args FROM extensions WHERE context = 'outrt-".$route."' AND (args LIKE 'dialout-trunk,%' OR args LIKE 'dialout-enum,%' OR args LIKE 'dialout-dundi,%') ORDER BY CAST(priority as UNSIGNED) "; + $results = $db->getAll($sql); + if(DB::IsError($results)) { + die_freepbx($results->getMessage()); + } + + $trunks = array(); + foreach ($results as $row) { + if (preg_match('/^dialout-trunk,(\d+)/', $row[0], $matches)) { + // check in_array -- even though we did distinct + // we still might get ${EXTEN} and ${EXTEN:1} if they used | to split a pattern + if (!in_array("OUT_".$matches[1], $trunks)) { + $trunks[] = "OUT_".$matches[1]; + } + } else if (preg_match('/^dialout-enum,(\d+)/', $row[0], $matches)) { + if (!in_array("OUT_".$matches[1], $trunks)) { + $trunks[] = "OUT_".$matches[1]; + } + } else if (preg_match('/^dialout-dundi,(\d+)/', $row[0], $matches)) { + if (!in_array("OUT_".$matches[1], $trunks)) { + $trunks[] = "OUT_".$matches[1]; + } + } + } + return $trunks; +} + + +//get password for this route +function core_routing_getroutepassword($route) { + global $db; + $sql = "SELECT DISTINCT args FROM extensions WHERE context = 'outrt-".$route."' AND (args LIKE 'dialout-trunk,%' OR args LIKE 'dialout-enum,%' OR args LIKE 'dialout-dundi,%') ORDER BY CAST(priority as UNSIGNED) "; + $results = $db->getOne($sql); + if(DB::IsError($results)) { + die_freepbx($results->getMessage()); + } + if (preg_match('/^.*,.*,.*,(\d+|\/\S+)/', $results, $matches)) { + $password = $matches[1]; + } else { + $password = ""; + } + + return $password; +} + +//get emergency state for this route +function core_routing_getrouteemergency($route) { + global $db; + $sql = "SELECT DISTINCT args FROM extensions WHERE context = 'outrt-".$route."' AND (args LIKE 'EMERGENCYROUTE%') "; + $results = $db->getOne($sql); + if(DB::IsError($results)) { + die_freepbx($results->getMessage()); + } + if (preg_match('/^.*=(.*)/', $results, $matches)) { + $emergency = $matches[1]; + } else { + $emergency = ""; + } + + return $emergency; +} + +//get intracompany routing status for this route +function core_routing_getrouteintracompany($route) { + + global $db; + $sql = "SELECT DISTINCT args FROM extensions WHERE context = 'outrt-".$route."' AND (args LIKE 'INTRACOMPANYROUTE%') "; + $results = $db->getOne($sql); + if(DB::IsError($results)) { + die_freepbx($results->getMessage()); + } + if (preg_match('/^.*=(.*)/', $results, $matches)) { + $intracompany = $matches[1]; + } else { + $intracompany = ""; + } + return $intracompany; +} + +//get mohsilence routing status for this route +function core_routing_getroutemohsilence($route) { + + global $db; + $sql = "SELECT DISTINCT args FROM extensions WHERE context = 'outrt-".$route."' AND (args LIKE 'MOHCLASS%') "; + $results = $db->getOne($sql); + if(DB::IsError($results)) { + die_freepbx($results->getMessage()); + } + if (preg_match('/^.*=(.*)/', $results, $matches)) { + $mohsilence = $matches[1]; + } else { + $mohsilence = ""; + } + return $mohsilence; +} + +function general_get_zonelist() { + return array( + array ( "name" => "Austria", "iso" => "at", "conf" => "ringcadence = 1000,5000\ndial = 420\nbusy = 420/400,0/400\nring = 420/1000,0/5000\ncongestion = 420/200,0/200\ncallwaiting = 420/40,0/1960\ndialrecall = 420\nrecord = 1400/80,0/14920\ninfo = 950/330,1450/330,1850/330,0/1000\nstutter = 380+420\n"), + array ( "name" => "Australia", "iso" => "au", "conf" => "ringcadence = 400,200,400,2000\ndial = 413+438\nbusy = 425/375,0/375\nring = 413+438/400,0/200,413+438/400,0/2000\ncongestion = 425/375,0/375,420/375,0/375\ncallwaiting = 425/200,0/200,425/200,0/4400\ndialrecall = 413+438\nrecord = !425/1000,!0/15000,425/360,0/15000\ninfo = 425/2500,0/500\nstd = !525/100,!0/100,!525/100,!0/100,!525/100,!0/100,!525/100,!0/100,!525/100\nfacility = 425\nstutter = 413+438/100,0/40\nringmobile = 400+450/400,0/200,400+450/400,0/2000\n"), + array ( "name" => "Brazil", "iso" => "br", "conf" => "ringcadence = 1000,4000\ndial = 425\nbusy = 425/250,0/250\nring = 425/1000,0/4000\ncongestion = 425/250,0/250,425/750,0/250\ncallwaiting = 425/50,0/1000\ndialrecall = 350+440\nrecord = 425/250,0/250\ninfo = 950/330,1400/330,1800/330\nstutter = 350+440\n"), + array ( "name" => "Belgium", "iso" => "be", "conf" => "ringcadence = 1000,3000\ndial = 425\nbusy = 425/500,0/500\nring = 425/1000,0/3000\ncongestion = 425/167,0/167\ncallwaiting = 1400/175,0/175,1400/175,0/3500\ndialrecall = !350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,350+440\nrecord = 1400/500,0/15000\ninfo = 900/330,1400/330,1800/330,0/1000\nstutter = 425/1000,0/250\n"), + array ( "name" => "Bulgaria", "iso" => "bg", "conf" => "ringcadence = 1000,4000\ndial = 425\nbusy = 425/500,0/500\nring = 425/1000,0/4000\ncongestion = 425/250,0/250\ncallwaiting = 425/150,0/150,425/150,0/4000\ndialrecall = !425/100,!0/100,!425/100,!0/100,!425/100,!0/100,425\nrecord = 1400/425,0/15000\ninfo = 950/330,1400/330,1800/330,0/1000\nstutter = 425/1500,0/100\n"), + array ( "name" => "Switzerland", "iso" => "ch", "conf" => "ringcadence = 1000,4000\ndial = 425\nbusy = 425/500,0/500\nring = 425/1000,0/4000\ncongestion = 425/200,0/200\ncallwaiting = 425/200,0/200,425/200,0/4000\ndialrecall = !425/100,!0/100,!425/100,!0/100,!425/100,!0/100,425\nrecord = 1400/80,0/15000\ninfo = 950/330,1400/330,1800/330,0/1000\nstutter = 425+340/1100,0/1100\n"), + array ( "name" => "Chile", "iso" => "cl", "conf" => "ringcadence = 1000,3000\ndial = 400\nbusy = 400/500,0/500\nring = 400/1000,0/3000\ncongestion = 400/200,0/200\ncallwaiting = 400/250,0/8750\ndialrecall = !400/100,!0/100,!400/100,!0/100,!400/100,!0/100,400\nrecord = 1400/500,0/15000\ninfo = 950/333,1400/333,1800/333,0/1000\nstutter = !400/100,!0/100,!400/100,!0/100,!400/100,!0/100,!400/100,!0/100,!400/100,!0/100,!400/100,!0/100,400\n"), + array ( "name" => "China", "iso" => "cn", "conf" => "ringcadence = 1000,4000\ndial = 450\nbusy = 450/350,0/350\nring = 450/1000,0/4000\ncongestion = 450/700,0/700\ncallwaiting = 450/400,0/4000\ndialrecall = 450\nrecord = 950/400,0/10000\ninfo = 450/100,0/100,450/100,0/100,450/100,0/100,450/400,0/400\nstutter = 450+425\n"), + array ( "name" => "Czech Republic", "iso" => "cz", "conf" => "ringcadence = 1000,4000\ndial = 425/330,0/330,425/660,0/660\nbusy = 425/330,0/330\nring = 425/1000,0/4000\ncongestion = 425/165,0/165\ncallwaiting = 425/330,0/9000\ndialrecall = !425/100,!0/100,!425/100,!0/100,!425/100,!0/100,425/330,0/330,425/660,0/660\nrecord = 1400/500,0/14000\ninfo = 950/330,0/30,1400/330,0/30,1800/330,0/1000\nstutter = 425/450,0/50\n"), + array ( "name" => "Germany", "iso" => "de", "conf" => "ringcadence = 1000,4000\ndial = 425\nbusy = 425/480,0/480\nring = 425/1000,0/4000\ncongestion = 425/240,0/240\ncallwaiting = !425/200,!0/200,!425/200,!0/5000,!425/200,!0/200,!425/200,!0/5000,!425/200,!0/200,!425/200,!0/5000,!425/200,!0/200,!425/200,!0/5000,!425/200,!0/200,!425/200,0\ndialrecall = !425/100,!0/100,!425/100,!0/100,!425/100,!0/100,425\nrecord = 1400/80,0/15000\ninfo = 950/330,1400/330,1800/330,0/1000\nstutter = 425+400\n"), + array ( "name" => "Denmark", "iso" => "dk", "conf" => "ringcadence = 1000,4000\ndial = 425\nbusy = 425/500,0/500\nring = 425/1000,0/4000\ncongestion = 425/200,0/200\ncallwaiting = !425/200,!0/600,!425/200,!0/3000,!425/200,!0/200,!425/200,0\ndialrecall = !425/100,!0/100,!425/100,!0/100,!425/100,!0/100,425\nrecord = 1400/80,0/15000\ninfo = 950/330,1400/330,1800/330,0/1000\nstutter = 425/450,0/50\n"), + array ( "name" => "Estonia", "iso" => "ee", "conf" => "ringcadence = 1000,4000\ndial = 425\nbusy = 425/300,0/300\nring = 425/1000,0/4000\ncongestion = 425/200,0/200\ncallwaiting = 950/650,0/325,950/325,0/30,1400/1300,0/2600\ndialrecall = 425/650,0/25\nrecord = 1400/500,0/15000\ninfo = 950/650,0/325,950/325,0/30,1400/1300,0/2600\nstutter = !425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,425\n"), + array ( "name" => "Finland", "iso" => "fi", "conf" => "ringcadence = 1000,4000\ndial = 425\nbusy = 425/300,0/300\nring = 425/1000,0/4000\ncongestion = 425/200,0/200\ncallwaiting = 425/150,0/150,425/150,0/8000\ndialrecall = 425/650,0/25\nrecord = 1400/500,0/15000\ninfo = 950/650,0/325,950/325,0/30,1400/1300,0/2600\nstutter = 425/650,0/25\n"), + array ( "name" => "France", "iso" => "fr", "conf" => "ringcadence = 1500,3500\ndial = 440\nbusy = 440/500,0/500\nring = 440/1500,0/3500\ncongestion = 440/250,0/250\ncallwait = 440/300,0/10000\ndialrecall = !350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,350+440\nrecord = 1400/500,0/15000\ninfo = !950/330,!1400/330,!1800/330\nstutter = !440/100,!0/100,!440/100,!0/100,!440/100,!0/100,!440/100,!0/100,!440/100,!0/100,!440/100,!0/100,440\n"), + array ( "name" => "Greece", "iso" => "gr", "conf" => "ringcadence = 1000,4000\ndial = 425/200,0/300,425/700,0/800\nbusy = 425/300,0/300\nring = 425/1000,0/4000\ncongestion = 425/200,0/200\ncallwaiting = 425/150,0/150,425/150,0/8000\ndialrecall = 425/650,0/25\nrecord = 1400/400,0/15000\ninfo = !950/330,!1400/330,!1800/330,!0/1000,!950/330,!1400/330,!1800/330,!0/1000,!950/330,!1400/330,!1800/330,!0/1000,0\nstutter = 425/650,0/25\n"), +array ( "name" => "Hong Kong", "iso" => "hk", "conf" => "ringcadence = 400,200,400,3000\ndial = 350+440\nbusy = 480+620/500,0/500\nring = 440+480/400,0/200,440+480/400,0/3000\ncongestion = 480+620/250,0/250\ncallwaiting = 440/300,0/10000\ndialrecall = !350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,350+440\nrecord = 1400/500,0/15000\ninfo = !950/330,!1400/330,!1800/330,0\nstutter = !350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,350+440\n"), + array ( "name" => "Hungary", "iso" => "hu", "conf" => "ringcadence = 1250,3750\ndial = 425\nbusy = 425/300,0/300\nring = 425/1250,0/3750\ncongestion = 425/300,0/300\ncallwaiting = 425/40,0/1960\ndialrecall = 425+450\nrecord = 1400/400,0/15000\ninfo = !950/330,!1400/330,!1800/330,!0/1000,!950/330,!1400/330,!1800/330,!0/1000,!950/330,!1400/330,!1800/330,!0/1000,0\nstutter = 350+375+400\n"), + array ( "name" => "India", "iso" => "in", "conf" => "ringcadence = 400,200,400,2000\ndial = 400*25\nbusy = 400/750,0/750\nring = 400*25/400,0/200,400*25/400,0/2000\ncongestion = 400/250,0/250\ncallwaiting = 400/200,0/100,400/200,0/7500\ndialrecall = !350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,350+440\nrecord = 1400/500,0/15000\ninfo = !950/330,!1400/330,!1800/330,0/1000\nstutter = !350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,350+440\n"), + array ( "name" => "Israel", "iso" => "il", "conf" => "ringcadence = 1000,3000\ndial = 414\nbusy = 414/500,0/500\nring = 414/1000,0/3000\ncongestion = 414/250,0/250\ncallwaiting = 414/100,0/100,414/100,0/100,414/600,0/3000 \ndialrecall = !414/100,!0/100,!414/100,!0/100,!414/100,!0/100,414\nrecord = 1400/500,0/15000\ninfo = 1000/330,1400/330,1800/330,0/1000\nstutter = !414/160,!0/160,!414/160,!0/160,!414/160,!0/160,!414/160,!0/160,!414/160,!0/160,!414/160,!0/160,!414/160,!0/160,!414/160,!0/160,!414/160,!0/160,!414/160,!0/160,414 \n"), + array ( "name" => "Italy", "iso" => "it", "conf" => "ringcadence = 1000,4000\ndial = 425/200,0/200,425/600,0/1000\nbusy = 425/500,0/500\nring = 425/1000,0/4000\ncongestion = 425/200,0/200\ncallwaiting = 425/400,0/100,425/250,0/100,425/150,0/14000\ndialrecall = 470/400,425/400\nrecord = 1400/400,0/15000\ninfo = !950/330,!1400/330,!1800/330,!0/1000,!950/330,!1400/330,!1800/330,!0/1000,!950/330,!1400/330,!1800/330,!0/1000,0\nstutter = 470/400,425/400\n"), + array ( "name" => "Japan", "iso" => "jp", "conf" => "ringcadence = 1000,2000\ndial = 400\nbusy = 400/500,0/500\nring = 400+15/1000,0/2000\ncongestion = 400/500,0/500\ncallwaiting = 400+16/500,0/8000\ndialrecall = !400/200,!0/200,!400/200,!0/200,!400/200,!0/200,400\nrecord = 1400/500,0/15000\ninfo = !950/330,!1400/330,!1800/330,0\nstutter = !400/100,!0/100,!400/100,!0/100,!400/100,!0/100,!400/100,!0/100,!400/100,!0/100,!400/100,!0/100,400\n"), + array ( "name" => "Lithuania", "iso" => "lt", "conf" => "ringcadence = 1000,4000\ndial = 425\nbusy = 425/350,0/350\nring = 425/1000,0/4000\ncongestion = 425/200,0/200\ncallwaiting = 425/150,0/150,425/150,0/4000\ndialrecall = 425/500,0/50\nrecord = 1400/500,0/15000\ninfo = !950/330,!1400/330,!1800/330,!0/1000,!950/330,!1400/330,!1800/330,!0/1000,!950/330,!1400/330,!1800/330,!0/1000,0\nstutter = !425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,425\n"), + array ( "name" => "Mexico", "iso" => "mx", "conf" => "ringcadence = 2000,4000\ndial = 425\nbusy = 425/250,0/250\nring = 425/1000,0/4000\ncongestion = 425/250,0/250\ncallwaiting = 425/200,0/600,425/200,0/10000\ndialrecall = !350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,350+440\nrecord = 1400/500,0/15000\ninfo = 950/330,0/30,1400/330,0/30,1800/330,0/1000\nstutter = !350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,350+440\n"), + array ( "name" => "Netherlands", "iso" => "nl", "conf" => "ringcadence = 1000,4000\ndial = 425\nbusy = 425/500,0/500\nring = 425/1000,0/4000\ncongestion = 425/250,0/250\ncallwaiting = 425/500,0/9500\ndialrecall = 425/500,0/50\nrecord = 1400/500,0/15000\ninfo = 950/330,1400/330,1800/330,0/1000\nstutter = 425/500,0/50\n"), + array ( "name" => "Norway", "iso" => "no", "conf" => "ringcadence = 1000,4000\ndial = 425\nbusy = 425/500,0/500\nring = 425/1000,0/4000\ncongestion = 425/200,0/200\ncallwaiting = 425/200,0/600,425/200,0/10000\ndialrecall = 470/400,425/400\nrecord = 1400/400,0/15000\ninfo = !950/330,!1400/330,!1800/330,!0/1000,!950/330,!1400/330,!1800/330,!0/1000,!950/330,!1400/330,!1800/330,!0/1000,0\nstutter = 470/400,425/400\n"), + array ( "name" => "New Zealand", "iso" => "nz", "conf" => "ringcadence = 400,200,400,2000\ndial = 400\nbusy = 400/250,0/250\nring = 400+450/400,0/200,400+450/400,0/2000\ncongestion = 400/375,0/375\ncallwaiting = !400/200,!0/3000,!400/200,!0/3000,!400/200,!0/3000,!400/200\ndialrecall = !400/100!0/100,!400/100,!0/100,!400/100,!0/100,400\nrecord = 1400/425,0/15000\ninfo = 400/750,0/100,400/750,0/100,400/750,0/100,400/750,0/400\nstutter = !400/100!0/100,!400/100,!0/100,!400/100,!0/100,!400/100!0/100,!400/100,!0/100,!400/100,!0/100,400\n"), + array ( "name" => "Philippines", "iso" => "phl", "conf" => "ringcadence = 1000,4000\ndial = 425\nbusy = 480+620/500,0/500\nring = 425+480/1000,0/4000\ncongestion = 480+620/250,0/250\ncallwaiting = 440/300,0/10000\ndialrecall = !350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,350+440\nrecord = 1400/500,0/15000\ninfo = !950/330,!1400/330,!1800/330,0\nstutter = !350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,350+440\n"), + array ( "name" => "Poland", "iso" => "pl", "conf" => "ringcadence = 1000,4000\ndial = 425\nbusy = 425/500,0/500\nring = 425/1000,0/4000\ncongestion = 425/500,0/500\ncallwaiting = 425/150,0/150,425/150,0/4000\ndialrecall = 425/500,0/50\nrecord = 1400/500,0/15000\ninfo = !950/330,!1400/330,!1800/330,!0/1000,!950/330,!1400/330,!1800/330,!0/1000,!950/330,!1400/330,!1800/330,!0/1000\nstutter = !425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,425\n"), + array ( "name" => "Portugal", "iso" => "pt", "conf" => "ringcadence = 1000,5000\ndial = 425\nbusy = 425/500,0/500\nring = 425/1000,0/5000\ncongestion = 425/200,0/200\ncallwaiting = 440/300,0/10000\ndialrecall = 425/1000,0/200\nrecord = 1400/500,0/15000\ninfo = 950/330,1400/330,1800/330,0/1000\nstutter = !425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,425\n"), + array ( "name" => "Russia / ex Soviet Union", "iso" => "ru", "conf" => "ringcadence = 800,3200\ndial = 425\nbusy = 425/350,0/350\nring = 425/800,0/3200\ncongestion = 425/350,0/350\ncallwaiting = 425/200,0/5000\ndialrecall = !350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,350+440\nrecord = 1400/500,0/15000\ninfo = !950/330,!1400/330,!1800/330,0\n"), + array ( "name" => "Singapore", "iso" => "sg", "conf" => "ringcadence = 400,200,400,2000\ndial = 425\nring = 425*24/400,0/200,425*24/400,0/2000 ; modulation should be 100%, not 90%\nbusy = 425/750,0/750\ncongestion = 425/250,0/250\ncallwaiting = 425*24/300,0/200,425*24/300,0/3200\nstutter = !425/200,!0/200,!425/600,!0/200,!425/200,!0/200,!425/600,!0/200,!425/200,!0/200,!425/600,!0/200,!425/200,!0/200,!425/600,!0/200,425\ninfo = 950/330,1400/330,1800/330,0/1000 ; not currently in use acc. to reference\ndialrecall = 425*24/500,0/500,425/500,0/2500 ; unspecified in IDA reference, use repeating Holding Tone A,B\nrecord = 1400/500,0/15000 ; unspecified in IDA reference, use 0.5s tone every 15s\nnutone = 425/2500,0/500\nintrusion = 425/250,0/2000\nwarning = 425/624,0/4376 ; end of period tone, warning\nacceptance = 425/125,0/125\nholdinga = !425*24/500,!0/500 ; followed by holdingb\nholdingb = !425/500,!0/2500\n"), + array ( "name" => "South Africa", "iso" => "za", "conf" => "ringcadence = 400,200,400,2000\ndial = 400*33\nbusy = 400/500,0/500\nring = 400*33/400,0/200,400*33/400,0/2000\ncongestion = 400/250,0/250\ncallwaiting = 400*33/250,0/250,400*33/250,0/250,400*33/250,0/250,400*33/250,0/250\ndialrecall = 350+440\nrecord = 1400/500,0/10000\ninfo = 950/330,1400/330,1800/330,0/330\nstutter =!400*33/100,!0/100,!400*33/100,!0/100,!400*33/100,!0/100,!400*33/100,!0/100,!400*33/100,!0/100,!400*33/100,!0/100,400*33 \n"), + array ( "name" => "Spain", "iso" => "es", "conf" => "ringcadence = 1500,3000\ndial = 425\nbusy = 425/200,0/200\nring = 425/1500,0/3000\ncongestion = 425/200,0/200,425/200,0/200,425/200,0/600\ncallwaiting = 425/175,0/175,425/175,0/3500\ndialrecall = !425/200,!0/200,!425/200,!0/200,!425/200,!0/200,425\nrecord = 1400/500,0/15000\ninfo = 950/330,0/1000\ndialout = 500\n\n"), + array ( "name" => "Sweden", "iso" => "se", "conf" => "ringcadence = 1000,5000\ndial = 425\nbusy = 425/250,0/250\nring = 425/1000,0/5000\ncongestion = 425/250,0/750\ncallwaiting = 425/200,0/500,425/200,0/9100\ndialrecall = !425/100,!0/100,!425/100,!0/100,!425/100,!0/100,425\nrecord = 1400/500,0/15000\ninfo = !950/332,!0/24,!1400/332,!0/24,!1800/332,!0/2024,!950/332,!0/24,!1400/332,!0/24,!1800/332,!0/2024,!950/332,!0/24,!1400/332,!0/24,!1800/332,!0/2024,!950/332,!0/24,!1400/332,!0/24,!1800/332,!0/2024,!950/332,!0/24,!1400/332,!0/24,!1800/332,0\nstutter = !425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,425\n"), + array ("name" => "Turkey", "iso" => "tr", "conf" => "ringcadance = 2000,4000\ndial = 450\nbusy = 450/500,0/500\nring = 450/2000,450/4000\ncongestion = 450/200,0/200,450/200,0/200,450/200,0/200,450/600,0/200\ncallwaiting = 450/200,0/600,450/200,0/8000\ndialrecall = 450/1000,0/250\nrecord = 1400/500,0/15000\ninfo = !950/300,!1400/300,!1800/300,!0/1000,!950/300,!1400/300,!1800/300,!0/1000,!950/300,!1400/300,!1800/300,!0/1000,0\n"), + array ( "name" => "United Kingdom", "iso" => "uk", "conf" => "ringcadence = 400,200,400,2000\ndial = 350+440\nspecialdial = 350+440/750,440/750\nbusy = 400/375,0/375\ncongestion = 400/400,0/350,400/225,0/525\nspecialcongestion = 400/200,1004/300\nunobtainable = 400\nring = 400+450/400,0/200,400+450/400,0/2000\ncallwaiting = 400/100,0/4000\nspecialcallwaiting = 400/250,0/250,400/250,0/250,400/250,0/5000\ncreditexpired = 400/125,0/125\nconfirm = 1400\nswitching = 400/200,0/400,400/2000,0/400\ninfo = 950/330,0/15,1400/330,0/15,1800/330,0/1000\nrecord = 1400/500,0/60000\nstutter = 350+440/750,440/750\n"), + array ( "name" => "United States / North America", "iso" => "us", "conf" => "ringcadence = 2000,4000\ndial = 350+440\nbusy = 480+620/500,0/500\nring = 440+480/2000,0/4000\ncongestion = 480+620/250,0/250\ncallwaiting = 440/300,0/10000\ndialrecall = !350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,350+440\nrecord = 1400/500,0/15000\ninfo = !950/330,!1400/330,!1800/330,0\nstutter = !350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,350+440\n"), + array ( "name" => "United States Circa 1950/ North America", "iso" => "us-old", "conf" => "ringcadence = 2000,4000\ndial = 600*120\nbusy = 500*100/500,0/500\nring = 420*40/2000,0/4000\ncongestion = 500*100/250,0/250\ncallwaiting = 440/300,0/10000\ndialrecall = !600*120/100,!0/100,!600*120/100,!0/100,!600*120/100,!0/100,600*120\nrecord = 1400/500,0/15000\ninfo = !950/330,!1400/330,!1800/330,0\nstutter = !600*120/100,!0/100,!600*120/100,!0/100,!600*120/100,!0/100,!600*120/100,!0/100,!600*120/100,!0/100,!600*120/100,!0/100,600*120\n"), + array ( "name" => "Taiwan", "iso" => "tw", "conf" => "ringcadence = 1000,4000\ndial = 350+440\nbusy = 480+620/500,0/500\nring = 440+480/1000,0/2000\ncongestion = 480+620/250,0/250\ncallwaiting = 350+440/250,0/250,350+440/250,0/3250\ndialrecall = 300/1500,0/500\nrecord = 1400/500,0/15000\ninfo = !950/330,!1400/330,!1800/330,0\nstutter = !350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,350+440\n"), + array ( "name" => "Venezuela / South America", "iso" => "ve", "conf" => "; Tone definition source for ve found on\n; Reference: http://www.itu.int/ITU-T/inr/forms/files/tones-0203.pdf\nringcadence = 1000,4000\ndial = 425\nbusy = 425/500,0/500\nring = 425/1000,0/4000\ncongestion = 425/250,0/250\ncallwaiting = 400+450/300,0/6000\ndialrecall = 425\nrecord = 1400/500,0/15000\ninfo = !950/330,!1440/330,!1800/330,0/1000\n"),); +} + +function general_display_zones($curzone) { + $zonelist = general_get_zonelist(); + echo ""; + +} + +function general_generate_indications() { + global $db; + global $asterisk_conf; + + $notify =& notifications::create($db); + + $sql = "SELECT value FROM globals WHERE variable='TONEZONE'"; + $result = $db->getRow($sql,DB_FETCHMODE_ASSOC); + + $filename = isset($asterisk_conf["astetcdir"]) && $asterisk_conf["astetcdir"] != '' ? rtrim($asterisk_conf["astetcdir"],DIRECTORY_SEPARATOR) : "/etc/asterisk"; + $filename .= "/indications.conf"; + + if (($fd = fopen($filename, "w")) === false) { + $desc = sprintf(_("Failed to open %s for writing, aborting attempt to write the country indications. The file may be readonly or the permissions may be incorrect."), $filename); + $notify->add_error('core','INDICATIONS',_("Failed to write indications.conf"), $desc); + return; + } + $notify->delete('core', 'INDICATIONS'); + + fwrite($fd, "[general]\ncountry=".$result['value']."\n\n"); + + $zonelist = general_get_zonelist(); + foreach ($zonelist as $zone) { + fwrite($fd, "[{$zone['iso']}]\n{$zone['conf']}\n\n"); + } + fclose($fd); +} +/* end page.routing.php functions */ + + + +// init registered 'your' config load and config process functions +function core_users_configpageinit($dispnum) { + global $currentcomponent; + global $amp_conf; + + if ( $dispnum == 'users' || $dispnum == 'extensions' ) { + // Setup option list we need + $currentcomponent->addoptlistitem('recordoptions', 'Adhoc', _("On Demand")); + $currentcomponent->addoptlistitem('recordoptions', 'Always', _("Always")); + $currentcomponent->addoptlistitem('recordoptions', 'Never', _("Never")); + $currentcomponent->setoptlistopts('recordoptions', 'sort', false); + + $currentcomponent->addoptlistitem('callwaiting', 'enabled', _("Enable")); + $currentcomponent->addoptlistitem('callwaiting', 'disabled', _("Disable")); + $currentcomponent->setoptlistopts('callwaiting', 'sort', false); + + $currentcomponent->addoptlistitem('call_screen', '0', _("Disable")); + $currentcomponent->addoptlistitem('call_screen', 'nomemory', _("Screen Caller: No Memory")); + $currentcomponent->addoptlistitem('call_screen', 'memory', _("Screen Caller: Memory")); + $currentcomponent->setoptlistopts('call_screen', 'sort', false); + + $currentcomponent->addoptlistitem('ringtime', '0', 'Default'); + for ($i=1; $i <= 120; $i++) { + $currentcomponent->addoptlistitem('ringtime', "$i", "$i"); + } + $currentcomponent->setoptlistopts('ringtime', 'sort', false); + + // Special CID handling to deal with Private, etc. + // + $js = + 'var mycid = thiscid.toLowerCase(); + if (isDialpattern(thiscid) || mycid.substring(0,4) == "priv" || mycid.substring(0,5) == "block" || mycid == "unknown" || mycid.substring(0,8) == "restrict" || mycid.substring(0,7) == "unavail" || mycid.substring(0,6) == "anonym") { return true } else { return false }; + '; + $currentcomponent->addjsfunc('isValidCID(thiscid)', $js); + + // Add the 'proces' functions + $currentcomponent->addguifunc('core_users_configpageload'); + // Ensure users is called in middle order ($sortorder = 5), this is to allow + // other modules to call stuff before / after the processing of users if needed + // e.g. Voicemail module needs to create mailbox BEFORE the users as the mailbox + // context is needed by the add users function + $currentcomponent->addprocessfunc('core_users_configprocess', 5); + } +} + +// Used below in usort +function dev_grp($a, $b) { + if ($a['devicetype'] == $b['devicetype']) { + return ($a['id'] < $b['id']) ? -1 : 1; + } else { + return ($a['devicetype'] > $b['devicetype']) ? -1 : 1; + } +} + +function core_users_configpageload() { + global $currentcomponent; + global $amp_conf; + + // Ensure variables possibly extracted later exist + $name = $outboundcid = $record_in = $record_out = $sipname = $cid_masquerade = $newdid_name = $newdid = $newdidcid = null; + + // Init vars from $_REQUEST[] + $display = isset($_REQUEST['display'])?$_REQUEST['display']:null;; + $action = isset($_REQUEST['action'])?$_REQUEST['action']:null; + $extdisplay = isset($_REQUEST['extdisplay'])?$_REQUEST['extdisplay']:null; + $tech_hardware = isset($_REQUEST['tech_hardware'])?$_REQUEST['tech_hardware']:null; + + if ( $action == 'del' ) { // Deleted + + $currentcomponent->addguielem('_top', new gui_subheading('del', $extdisplay.' '._("deleted"), false)); + + } elseif ( $display == 'extensions' && ($extdisplay == '' && $tech_hardware == '') ) { // Adding + + // do nothing as you want the Devices to handle this bit + + } else { + + $delURL = $_SERVER['PHP_SELF'].'?'.$_SERVER['QUERY_STRING'].'&action=del'; + + if ( is_string($extdisplay) ) { + + if (!isset($GLOBALS['abort']) || $GLOBALS['abort'] !== true) { + $extenInfo=core_users_get($extdisplay); + extract($extenInfo); + } + if (isset($deviceInfo) && is_array($deviceInfo)) + extract($deviceInfo); + + if ( $display == 'extensions' ) { + $currentcomponent->addguielem('_top', new gui_pageheading('title', _("Extension").": $extdisplay", false), 0); + if (!isset($GLOBALS['abort']) || $GLOBALS['abort'] !== true) { + $tlabel = sprintf(_("Delete Extension %s"),$extdisplay); + $label = ' '.$tlabel.''; + $currentcomponent->addguielem('_top', new gui_link('del', $label, $delURL, true, false), 0); + + $usage_list = framework_display_destination_usage(core_getdest($extdisplay)); + if (!empty($usage_list)) { + $currentcomponent->addguielem('_top', new gui_link_label('dests', $usage_list['text'], $usage_list['tooltip'], true), 0); + } + } + } else { + $currentcomponent->addguielem('_top', new gui_pageheading('title', _("User").": $extdisplay", false), 0); + if (!isset($GLOBALS['abort']) || $GLOBALS['abort'] !== true) { + $tlabel = sprintf(_("Delete User %s"),$extdisplay); + $label = ' '.$tlabel.''; + $currentcomponent->addguielem('_top', new gui_link('del', $label, $delURL, true, false), 0); + + $usage_list = framework_display_destination_usage(core_getdest($extdisplay)); + if (!empty($usage_list)) { + $currentcomponent->addguielem('_top', new gui_link_label('dests', $usage_list['text'], $usage_list['tooltip'], true), 0); + } + } + } + + } elseif ( $display != 'extensions' ) { + $currentcomponent->addguielem('_top', new gui_pageheading('title', _("Add User/Extension")), 0); + } + + // Setup vars for use in the gui later on + $fc_logon = featurecodes_getFeatureCode('core', 'userlogon'); + $fc_logoff = featurecodes_getFeatureCode('core', 'userlogoff'); + + $msgInvalidExtNum = _("Please enter a valid extension number."); + $msgInvalidCidNum = _("Please enter a valid CID Num Alias (must be a valid number)."); + $msgInvalidExtPwd = _("Please enter valid User Password using numbers only"); + $msgInvalidDispName = _("Please enter a valid Display Name"); + $msgInvalidOutboundCID = _("Please enter a valid Outbound CID"); + $msgInvalidPause = _("Please enter a valid pause time in seconds, using digits only"); + $msgInvalidDIDNum = _("You have entered a non-standard dialpattern for your DID. You can only enter standard dialpatterns. You must use the inbound routing form to enter non-standard patterns"); + $msgInvalidCIDNum = _("Please enter a valid Caller ID Number or leave it blank for your Assigned DID/CID pair"); + + // This is the actual gui stuff + $currentcomponent->addguielem('_top', new gui_hidden('action', ($extdisplay ? 'edit' : 'add'))); + $currentcomponent->addguielem('_top', new gui_hidden('extdisplay', $extdisplay)); + + if ( $display == 'extensions' ) { + $section = ($extdisplay ? _("Edit Extension") : _("Add Extension")); + } else { + $section = ($extdisplay ? _("Edit User") : _("Add User")); + } + if ( trim($extdisplay) != '' ) { + $currentcomponent->addguielem($section, new gui_hidden('extension', $extdisplay), 2); + } else { + $currentcomponent->addguielem($section, new gui_textbox('extension', $extdisplay, _("User Extension"), _("The extension number to dial to reach this user."), '!isInteger()', $msgInvalidExtNum, false), 3); + } + if ( $display != 'extensions' ) { + $currentcomponent->addguielem($section, new gui_password('password', $password, _("User Password"), _("A user will enter this password when logging onto a device.").' '.$fc_logon.' '._("logs into a device.").' '.$fc_logoff.' '._("logs out of a device."), '!isInteger() && !isWhitespace()', $msgInvalidExtPwd, true)); + // extra JS function check required for blank password warning -- call last in the onsubmit() function + $currentcomponent->addjsfunc('onsubmit()', "\treturn checkBlankUserPwd();\n", 9); + } + $currentcomponent->addguielem($section, new gui_textbox('name', $name, _("Display Name"), _("The caller id name for calls from this user will be set to this name. Only enter the name, NOT the number."), '!isAlphanumeric() || isWhitespace()', $msgInvalidDispName, false)); + $cid_masquerade = (trim($cid_masquerade) == $extdisplay)?"":$cid_masquerade; + $currentcomponent->addguielem($section, new gui_textbox('cid_masquerade', $cid_masquerade, _("CID Num Alias"), _("The CID Number to use for internal calls, if different from the extension number. This is used to masquerade as a different user. A common example is a team of support people who would like their internal callerid to display the general support number (a ringgroup or queue). There will be no effect on external calls."), '!isWhitespace() && !isInteger()', $msgInvalidCidNum, false)); + $currentcomponent->addguielem($section, new gui_textbox('sipname', $sipname, _("SIP Alias"), _("If you want to support direct sip dialing of users internally or through anonymous sip calls, you can supply a friendly name that can be used in addition to the users extension to call them."))); + + // If user mode, list devices associated with this user + // + if ($display == 'users' && trim($extdisplay != '')) { + $section = _("User Devices"); + $device_list = core_devices_list('all','full'); + + usort($device_list,'dev_grp'); + + $link_count = 0; + foreach ($device_list as $device_item) { + if ($device_item['user'] == $extdisplay) { + $editURL = $_SERVER['PHP_SELF'].'?type=setup&display=devices&skip=0&extdisplay='.$device_item['id']; + $device_icon = ($device_item['devicetype'] == 'fixed') ? 'images/telephone_key.png' : 'images/telephone_edit.png'; + $device_label = ' '; + $device_label .= _('Edit:'); + $device_label .= ' '.$device_item['id'].' '.$device_item['description']; + + $device_label = ' + Edit Device'.$device_label. + ' '; + + $currentcomponent->addguielem($section, new gui_link('dev'.$link_count++, $device_label, $editURL, true, false), 2); + } + } + } + + $section = _("Extension Options"); + $currentcomponent->addguielem($section, new gui_textbox('outboundcid', $outboundcid, _("Outbound CID"), _("Overrides the caller id when dialing out a trunk. Any setting here will override the common outbound caller id set in the Trunks admin.

Format: \"caller name\" <#######>

Leave this field blank to disable the outbound callerid feature for this user."), '!isCallerID()', $msgInvalidOutboundCID, true),3); + $ringtimer = (isset($ringtimer) ? $ringtimer : '0'); + $currentcomponent->addguielem($section, new gui_selectbox('ringtimer', $currentcomponent->getoptlist('ringtime'), $ringtimer, _("Ring Time"), _("Number of seconds to ring prior to going to voicemail. Default will use the value set in the General Tab. If no voicemail is configured this will be ignored."), false)); + if (!isset($callwaiting)) { + if ($amp_conf['ENABLECW']) { + $callwaiting = 'enabled'; + } else { + $callwaiting = 'disabled'; + } + } + $currentcomponent->addguielem($section, new gui_selectbox('callwaiting', $currentcomponent->getoptlist('callwaiting'), $callwaiting, _("Call Waiting"), _("Set the initial/current Call Waiting state for this user's extension"), false)); + $currentcomponent->addguielem($section, new gui_selectbox('call_screen', $currentcomponent->getoptlist('call_screen'), $call_screen, _("Call Screening"),_("Call Screening requires external callers to say their name, which will be played back to the user and allow the user to accept or reject the call. Screening with memory only verifies a caller for their caller-id once. Screening without memory always requires a caller to say their name. Either mode will always announce the caller based on the last introduction saved with that callerid. If any user on the system uses the memory option, when that user is called, the caller will be required to re-introduce themselves and all users on the system will have that new introduction associated with the caller's CallerId."), false)); + + $section = _("Assigned DID/CID"); + $currentcomponent->addguielem($section, new gui_textbox('newdid_name', $newdid_name, _("DID Description"), _("A description for this DID, such as \"Fax\"")), 4); + $currentcomponent->addguielem($section, new gui_textbox('newdid', $newdid, _("Add Inbound DID"), _("A direct DID that is associated with this extension. The DID should be in the same format as provided by the provider (e.g. full number, 4 digits for 10x4, etc).

Format should be: XXXXXXXXXX

.An optional CID can also be associated with this DID by setting the next box"),'!isDialpattern()',$msgInvalidDIDNum,true), 4); + $currentcomponent->addguielem($section, new gui_textbox('newdidcid', $newdidcid, _("Add Inbound CID"), _("Add a CID for more specific DID + CID routing. A DID must be specified in the above Add DID box. In addition to standard dial sequences, you can also put Private, Blocked, Unknown, Restricted, Anonymous and Unavailable in order to catch these special cases if the Telco transmits them."),"!frm_${display}_isValidCID()",$msgInvalidCIDNum,true), 4); + + $dids = core_did_list('extension'); + $did_count = 0; + foreach ($dids as $did) { + $did_dest = split(',',$did['destination']); + if (isset($did_dest[1]) && $did_dest[1] == $extdisplay) { + + $did_title = ($did['description'] != '') ? $did['description'] : _("DID / CID"); + + $addURL = $_SERVER['PHP_SELF'].'?type=setup&display=did&&extdisplay='.$did['extension'].'/'.$did['cidnum']; + $did_icon = 'images/email_edit.png'; + $did_label = trim($did['extension']) == '' ? ' Any DID' : ' '.$did['extension']; + if (trim($did['cidnum']) != '') { + $did_label .= ' / '.$did['cidnum']; + } + if (trim($did['description']) != '') { + $did_label .= ' ('.$did['description'].')'; + } + + $did_label = '  + '.$did_label. + ' '; + + $currentcomponent->addguielem($section, new gui_link('did_'.$did_count++, $did_label, $addURL, true, false), 4); + } + } + + $section = _("Recording Options"); + $currentcomponent->addguielem($section, new gui_selectbox('record_in', $currentcomponent->getoptlist('recordoptions'), $record_in, _("Record Incoming"), _("Record all inbound calls received at this extension."), false)); + $currentcomponent->addguielem($section, new gui_selectbox('record_out', $currentcomponent->getoptlist('recordoptions'), $record_out, _("Record Outgoing"), _("Record all outbound calls received at this extension."), false)); + } +} + +function core_users_configprocess() { + if ( !class_exists('agi_asteriskmanager') ) + include 'common/php-asmanager.php'; + + //create vars from the request + extract($_REQUEST); + + //make sure we can connect to Asterisk Manager + if (!checkAstMan()) { + return false; + } + + //check if the extension is within range for this user + if (isset($extension) && !checkRange($extension)){ + echo ""; + $GLOBALS['abort'] = true; + } else { + //if submitting form, update database + if (!isset($action)) $action = null; + switch ($action) { + case "add": + $conflict_url = array(); + $usage_arr = framework_check_extension_usage($_REQUEST['extension']); + if (!empty($usage_arr)) { + $GLOBALS['abort'] = true; + $conflict_url = framework_display_extension_usage_alert($usage_arr,true); + global $currentcomponent; + $id=0; + $currentcomponent->addguielem('_top', new gui_link_label('conflict', _("Conflicting Extensions"), _("The following extension numbers are in conflict, you can click on the item(s) below to edit the conflicting entity."), true)); + foreach ($conflict_url as $edit_link) { + $currentcomponent->addguielem('_top', new gui_link('conflict'.$i++, $edit_link['label'], $edit_link['url'])); + } + $msg = ($_REQUEST['display'] == 'users') ? _("Configure user again:") : _("Configure extension again:"); + $currentcomponent->addguielem('_top', new gui_subheading('conflict_end', $msg, false)); + unset($_REQUEST['action']); + redirect_standard_continue(); + } elseif (core_users_add($_REQUEST)) { + needreload(); + redirect_standard_continue(); + } else { + // really bad hack - but if core_users_add fails, want to stop core_devices_add + // Comment, this does not help everywhere. Other hooks functions can hook before + // this like voicemail! + // + $GLOBALS['abort'] = true; + } + break; + case "del": + core_users_del($extdisplay); + core_users_cleanastdb($extdisplay); + if (function_exists('findmefollow_del')) { + findmefollow_del($extdisplay); + } + needreload(); + redirect_standard_continue(); + break; + case "edit": + if (core_users_edit($extdisplay,$_REQUEST)) { + needreload(); + redirect_standard_continue('extdisplay'); + } else { + // really bad hack - but if core_users_edit fails, want to stop core_devices_edit + $GLOBALS['abort'] = true; + } + break; + } + } + return true; +} + + +function core_devices_configpageinit($dispnum) { + global $currentcomponent; + + if ( $dispnum == 'devices' || $dispnum == 'extensions' ) { + // Setup arrays for device types + $currentcomponent->addgeneralarray('devtechs'); + + // Some errors for the validation bits + $msgInvalidDTMFMODE = _("Please enter the dtmfmode for this device"); + $msgInvalidChannel = _("Please enter the channel for this device"); + $msgConfirmSecret = _("You have not entered a Secret for this device, although this is possible it is generally bad practice to not assign a Secret to a device. Are you sure you want to leave the Secret empty?"); + $msgInvalidSecret = _("Please enter a Secret for this device"); + $msgSecretSameAsExtension = _("You have set your secret and device/extension to the same value. This can be a serious security vulnerability resulting in a hacker compromising your system to make free phone calls. There are many known instances where this has already occurred"); + + // zap + $tmparr = array(); + $tmparr['channel'] = array('value' => '', 'level' => 0, 'jsvalidation' => 'isEmpty()', 'failvalidationmsg' => $msgInvalidChannel); + $tmparr['context'] = array('value' => 'from-internal', 'level' => 1); + $tmparr['immediate'] = array('value' => 'no', 'level' => 1); + $tmparr['signalling'] = array('value' => 'fxo_ks', 'level' => 1); + $tmparr['echocancel'] = array('value' => 'yes', 'level' => 1); + $tmparr['echocancelwhenbridged'] = array('value' => 'no', 'level' => 1); + $tmparr['echotraining'] = array('value' => '800', 'level' => 1); + $tmparr['busydetect'] = array('value' => 'no', 'level' => 1); + $tmparr['busycount'] = array('value' => '7', 'level' => 1); + $tmparr['callprogress'] = array('value' => 'no', 'level' => 1); + $tmparr['dial'] = array('value' => '', 'level' => 1); + $tmparr['accountcode'] = array('value' => '', 'level' => 1); + $tmparr['callgroup'] = array('value' => '', 'level' => 1); + $tmparr['pickupgroup'] = array('value' => '', 'level' => 1); + $tmparr['mailbox'] = array('value' => '', 'level' => 1); + $currentcomponent->addgeneralarrayitem('devtechs', 'zap', $tmparr); + unset($tmparr); + + // iax2 + $tmparr = array(); + $tmparr['secret'] = array('value' => '', 'level' => 0, 'jsvalidation' => '(' . $_REQUEST['extdisplay'] . ' == theForm.devinfo_secret.value && !confirm("' . $msgSecretSameAsExtension . '")) || isEmpty() && !confirm("'.$msgConfirmSecret.'")', 'failvalidationmsg' => $msgInvalidSecret); + $tmparr['notransfer'] = array('value' => 'yes', 'level' => 1); + $tmparr['context'] = array('value' => 'from-internal', 'level' => 1); + $tmparr['host'] = array('value' => 'dynamic', 'level' => 1); + $tmparr['type'] = array('value' => 'friend', 'level' => 1); + $tmparr['port'] = array('value' => '4569', 'level' => 1); + $tmparr['qualify'] = array('value' => 'yes', 'level' => 1); + $tmparr['disallow'] = array('value' => '', 'level' => 1); + $tmparr['allow'] = array('value' => '', 'level' => 1); + $tmparr['dial'] = array('value' => '', 'level' => 1); + $tmparr['accountcode'] = array('value' => '', 'level' => 1); + $tmparr['mailbox'] = array('value' => '', 'level' => 1); + $currentcomponent->addgeneralarrayitem('devtechs', 'iax2', $tmparr); + unset($tmparr); + + // sip + $tmparr = array(); + $tmparr['secret'] = array('value' => '', 'level' => 0, 'jsvalidation' => '(' . $_REQUEST['extdisplay'] . ' == theForm.devinfo_secret.value && !confirm("' . $msgSecretSameAsExtension . '")) || isEmpty() && !confirm("'.$msgConfirmSecret.'")', 'failvalidationmsg' => $msgInvalidSecret); + $tmparr['dtmfmode'] = array('value' => 'rfc2833', 'level' => 0, 'jsvalidation' => 'isEmpty()', 'failvalidationmsg' => $msgInvalidDTMFMODE ); + $tmparr['canreinvite'] = array('value' => 'no', 'level' => 1); + $tmparr['context'] = array('value' => 'from-internal', 'level' => 1); + $tmparr['host'] = array('value' => 'dynamic', 'level' => 1); + $tmparr['type'] = array('value' => 'friend', 'level' => 1); + $tmparr['nat'] = array('value' => 'yes', 'level' => 1); + $tmparr['port'] = array('value' => '5060', 'level' => 1); + $tmparr['qualify'] = array('value' => 'yes', 'level' => 1); + $tmparr['callgroup'] = array('value' => '', 'level' => 1); + $tmparr['pickupgroup'] = array('value' => '', 'level' => 1); + $tmparr['disallow'] = array('value' => '', 'level' => 1); + $tmparr['allow'] = array('value' => '', 'level' => 1); + $tmparr['dial'] = array('value' => '', 'level' => 1); + $tmparr['accountcode'] = array('value' => '', 'level' => 1); + $tmparr['mailbox'] = array('value' => '', 'level' => 1); + $currentcomponent->addgeneralarrayitem('devtechs', 'sip', $tmparr); + unset($tmparr); + + // custom + $tmparr = array(); + $tmparr['dial'] = array('value' => '', 'level' => 0); + $currentcomponent->addgeneralarrayitem('devtechs', 'custom', $tmparr); + unset($tmparr); + + // Devices list + $currentcomponent->addoptlistitem('devicelist', 'sip_generic', _("Generic SIP Device")); + $currentcomponent->addoptlistitem('devicelist', 'iax2_generic', _("Generic IAX2 Device")); + $currentcomponent->addoptlistitem('devicelist', 'zap_generic', _("Generic ZAP Device")); + $currentcomponent->addoptlistitem('devicelist', 'custom_custom', _("Other (Custom) Device")); + $currentcomponent->setoptlistopts('devicelist', 'sort', false); + + + // Option lists used by the gui + $currentcomponent->addoptlistitem('devicetypelist', 'fixed', _("Fixed")); + $currentcomponent->addoptlistitem('devicetypelist', 'adhoc', _("Adhoc")); + $currentcomponent->setoptlistopts('devicetypelist', 'sort', false); + + $currentcomponent->addoptlistitem('deviceuserlist', 'none', _("none")); + $currentcomponent->addoptlistitem('deviceuserlist', 'new', _("New User")); + $users = core_users_list(); + if (isset($users)) { + foreach ($users as $auser) { + $currentcomponent->addoptlistitem('deviceuserlist', $auser[0], $auser[0]); + } + } + $currentcomponent->setoptlistopts('deviceuserlist', 'sort', false); + + // Add the 'proces' functions + $currentcomponent->addguifunc('core_devices_configpageload'); + $currentcomponent->addprocessfunc('core_devices_configprocess'); + } +} + +function core_devices_configpageload() { + global $currentcomponent; + + // Init vars from $_REQUEST[] + $display = isset($_REQUEST['display'])?$_REQUEST['display']:null;; + $action = isset($_REQUEST['action'])?$_REQUEST['action']:null; + $extdisplay = isset($_REQUEST['extdisplay'])?$_REQUEST['extdisplay']:null; + $tech_hardware = isset($_REQUEST['tech_hardware'])?$_REQUEST['tech_hardware']:null; + + if ( $action == 'del' ) { // Deleted + + if ( $display != 'extensions' ) + $currentcomponent->addguielem('_top', new gui_subheading('del', $extdisplay.' '._("deleted"), false)); + + } elseif ( $extdisplay == '' && $tech_hardware == '' ) { // Adding + + if ($_SESSION["AMP_user"]->checkSection('999')) { + if ( $display != 'extensions') { + $currentcomponent->addguielem('_top', new gui_pageheading('title', _("Add Device")), 0); + } else { + $currentcomponent->addguielem('_top', new gui_pageheading('title', _("Add an Extension")), 0); + } + $currentcomponent->addguielem('_top', new gui_label('instructions', _("Please select your Device below then click Submit"))); + $currentcomponent->addguielem('Device', new gui_selectbox('tech_hardware', $currentcomponent->getoptlist('devicelist'), '', _("Device"), '', false)); + } else { + if ( $display != 'extensions') { + $currentcomponent->addguielem('_top', new gui_pageheading('title', _("Edit existing Device")), 0); + } else { + $currentcomponent->addguielem('_top', new gui_pageheading('title', _("Edit existing Extension")), 0); + } + } + + } else { + + $deviceInfo = array(); + if ( $extdisplay ) { // Editing + + $deviceInfo = core_devices_get($extdisplay); + + if ( $display != 'extensions' ) { + $currentcomponent->addguielem('_top', new gui_pageheading('title', _("Device").": $extdisplay", false), 0); + + $delURL = $_SERVER['PHP_SELF'].'?'.$_SERVER['QUERY_STRING'].'&action=del'; + $tlabel = sprintf(_("Delete Device %s"),$extdisplay); + $label = ' '.$tlabel.''; + $currentcomponent->addguielem('_top', new gui_link('del', $label, $delURL, true, false), 0); + + if ($deviceInfo['device_user'] != 'none') { + $editURL = $_SERVER['PHP_SELF'].'?type=setup&display=users&skip=0&extdisplay='.$deviceInfo['user']; + $tlabel = $deviceInfo['devicetype'] == 'adhoc' ? sprintf(_('Edit Default User: %s'),$deviceInfo['user']) : sprintf(_('Edit Fixed User: %s'),$deviceInfo['user']); + $label = ' '.$tlabel.''; + $currentcomponent->addguielem('_top', new gui_link('edit_user', $label, $editURL, true, false), 0); + } + } + } else { + + $tmparr = explode('_', $tech_hardware); + $deviceInfo['tech'] = $tmparr[0]; + $deviceInfo['hardware'] = $tmparr[1]; + unset($tmparr); + + if ( $display != 'extensions' ) { + $currentcomponent->addguielem('_top', new gui_pageheading('title', _("Add").' '.strtoupper($deviceInfo['tech']).' '._("Device")), 0); + } else { + $currentcomponent->addguielem('_top', new gui_pageheading('title', _("Add").' '.strtoupper($deviceInfo['tech']).' '._("Extension")), 0); + } + } + + // Ensure they exist before the extract + $devinfo_description = $devinfo_emergency_cid = null; + $devinfo_devicetype = $devinfo_user = $devinfo_hardware = null; + if ( is_array($deviceInfo) ) { + extract($deviceInfo, EXTR_PREFIX_ALL, 'devinfo'); + } + + // Setup vars for use in the gui later on + $fc_logon = featurecodes_getFeatureCode('core', 'userlogon'); + $fc_logoff = featurecodes_getFeatureCode('core', 'userlogoff'); + + $msgInvalidDevID = _("Please enter a device id."); + $msgInvalidDevDesc = _("Please enter a valid Description for this device"); + $msgInvalidEmergCID = _("Please enter a valid Emergency CID"); + $msgInvalidExtNum = _("Please enter a valid extension number."); + + // Actual gui + $currentcomponent->addguielem('_top', new gui_hidden('action', ($extdisplay ? 'edit' : 'add'))); + $currentcomponent->addguielem('_top', new gui_hidden('extdisplay', $extdisplay)); + + if ( $display != 'extensions' ) { + $section = _("Device Info"); + if ( $extdisplay ) { // Editing + $currentcomponent->addguielem($section, new gui_hidden('deviceid', $extdisplay)); + } else { // Adding + $currentcomponent->addguielem($section, new gui_textbox('deviceid', $extdisplay, _("Device ID"), _("Give your device a unique integer ID. The device will use this ID to authenticate to the system."), '!isInteger()', $msgInvalidDevID, false)); + } + $currentcomponent->addguielem($section, new gui_textbox('description', $devinfo_description, _("Description"), _("The caller id name for this device will be set to this description until it is logged into."), '!isAlphanumeric() || isWhitespace()', $msgInvalidDevDesc, false)); + $currentcomponent->addguielem($section, new gui_textbox('emergency_cid', $devinfo_emergency_cid, _("Emergency CID"), _("This caller id will always be set when dialing out an Outbound Route flagged as Emergency. The Emergency CID overrides all other caller id settings."), '!isCallerID()', $msgInvalidEmergCID)); + $currentcomponent->addguielem($section, new gui_selectbox('devicetype', $currentcomponent->getoptlist('devicetypelist'), $devinfo_devicetype, _("Device Type"), _("Devices can be fixed or adhoc. Fixed devices are always associated to the same extension/user. Adhoc devices can be logged into and logged out of by users.").' '.$fc_logon.' '._("logs into a device.").' '.$fc_logoff.' '._("logs out of a device."), false)); + $currentcomponent->addguielem($section, new gui_selectbox('deviceuser', $currentcomponent->getoptlist('deviceuserlist'), $devinfo_user, _("Default User"), _("Fixed devices will always mapped to this user. Adhoc devices will be mapped to this user by default.

If selecting 'New User', a new User Extension of the same Device ID will be set as the Default User."), false)); + } else { + $section = _("Extension Options"); + $currentcomponent->addguielem($section, new gui_textbox('emergency_cid', $devinfo_emergency_cid, _("Emergency CID"), _("This caller id will always be set when dialing out an Outbound Route flagged as Emergency. The Emergency CID overrides all other caller id settings."), '!isCallerID()', $msgInvalidEmergCID)); + } + $currentcomponent->addguielem($section, new gui_hidden('tech', $devinfo_tech)); + $currentcomponent->addguielem($section, new gui_hidden('hardware', $devinfo_hardware)); + + $section = _("Device Options"); + + $device_uses = sprintf(_("This device uses %s technology."),$devinfo_tech).(strtoupper($devinfo_tech) == 'ZAP' && ast_with_dahdi()?" ("._("Via DAHDI compatibility mode").")":""); + $currentcomponent->addguielem($section, new gui_label('techlabel', $device_uses),4); + $devopts = $currentcomponent->getgeneralarrayitem('devtechs', $devinfo_tech); + if (is_array($devopts)) { + foreach ($devopts as $devopt=>$devoptarr) { + $devopname = 'devinfo_'.$devopt; + $devoptcurrent = isset($$devopname) ? $$devopname : $devoptarr['value']; + $devoptjs = isset($devoptarr['jsvalidation']) ? $devoptarr['jsvalidation'] : ''; + $devoptfailmsg = isset($devoptarr['failvalidationmsg']) ? $devoptarr['failvalidationmsg'] : ''; + + if ( $devoptarr['level'] == 0 || ($extdisplay && $devoptarr['level'] == 1) ) { // editing to show advanced as well + $currentcomponent->addguielem($section, new gui_textbox($devopname, $devoptcurrent, $devopt, '', $devoptjs, $devoptfailmsg), 4); + } else { // add so only basic + $currentcomponent->addguielem($section, new gui_hidden($devopname, $devoptcurrent), 4); + } + } + } + } +} + +function core_devices_configprocess() { + if ( !class_exists('agi_asteriskmanager') ) + include 'common/php-asmanager.php'; + + //make sure we can connect to Asterisk Manager + if (!checkAstMan()) { + return false; + } + + //create vars from the request + extract($_REQUEST); + + $extension = isset($extension)?$extension:null; + $deviceid = isset($deviceid)?$deviceid:null; + $name = isset($name)?$name:null; + $action = isset($action)?$action:null; + + // fixed users only in extensions mode + if ( $display == 'extensions' ) { + $devicetype = 'fixed'; + $deviceid = $deviceuser = $extension; + $description = $name; + } + + //if submitting form, update database + switch ($action) { + case "add": + // really bad hack - but if core_users_add fails, want to stop core_devices_add + + if (!isset($GLOBALS['abort']) || $GLOBALS['abort'] !== true || !$_SESSION["AMP_user"]->checkSection('999')) { + if (core_devices_add($deviceid,$tech,$devinfo_dial,$devicetype,$deviceuser,$description,$emergency_cid)) { + needreload(); + if ($deviceuser != 'new') { + redirect_standard_continue(); + } + } + } else { + // This is a bit messy, because by this time, other modules may have added the device but this tries to block + // the user who does not have add permission from adding a new extension. + // + $GLOBALS['abort'] = true; + } + break; + case "del": + core_devices_del($extdisplay); + needreload(); + redirect_standard_continue(); + break; + case "edit": //just delete and re-add + // really bad hack - but if core_users_edit fails, want to stop core_devices_edit + if (!isset($GLOBALS['abort']) || $GLOBALS['abort'] !== true) { + core_devices_del($extdisplay,true); + core_devices_add($deviceid,$tech,$devinfo_dial,$devicetype,$deviceuser,$description,$emergency_cid,true); + needreload(); + redirect_standard_continue('extdisplay'); + } + break; + case "resetall": //form a url with this option to nuke the AMPUSER & DEVICE trees and start over. + core_users2astdb(); + core_devices2astdb(); + break; + } + return true; +} + +?> Index: /modules/branches/2.6/core/bin/fax-process.pl =================================================================== --- /modules/branches/2.6/core/bin/fax-process.pl (revision 6236) +++ /modules/branches/2.6/core/bin/fax-process.pl (revision 6236) @@ -0,0 +1,225 @@ +#!/usr/bin/perl -w + +# Small program to process a tiff file into a PDF and email it. +# +# Distributed under the terms of the GNU General Public License (GPL) Version 2 +# Copyright 2005 by Rob Thomas (xrobau@gmail.com) + +use MIME::Base64; +use Net::SMTP; + +# Default paramaters +my $to = "xrobau\@gmail.com"; +my $from = "fax\@"; +my $dest = undef; +my $subject = "Fax received"; +my $ct = "application/x-pdf"; +my $file = undef; +my $attachment = undef; + +# Care about the hostname. +my $hostname = `/bin/hostname`; +chomp ($hostname); +if ($hostname =~ /localhost/) { + $hostname = "set.your.hostname.com"; +} +$from .= $hostname; + +# Usage: +my $usage="Usage: --file filename [--attachment filename] [--to email_address] [--from email_address] [--type content/type] [--subject \"Subject Of Email\"] [--dest DID]"; + +# Parse command line.. +while (my $cmd = shift @ARGV) { + chomp $cmd; + # My kingdom for a 'switch' + if ($cmd eq "--to") { + my $tmp = shift @ARGV; + $to = $tmp if (defined $tmp); + } elsif ($cmd eq "--subject") { + my $tmp = shift @ARGV; + if ($tmp =~ /\^(\")|^(\')/) { + # It's a quoted string + my $delim = $+; # $+ is 'last match', which is ' or " + $tmp =~ s/\Q$delim\E//; # Strip out ' or " + $subject = $tmp; + while ($tmp = shift @ARGV) { + if ($tmp =~ /\Q$delim\E/) { + $tmp =~ s/\Q$delim\E//; + last; + } + $subject .= $tmp; + } + } else { + # It's a single word + $subject = $tmp; + } + # Convert %2x to proper characters, leave anything else alone. + $subject =~ s/\%20/ /g; + $subject =~ s/\%21/\!/g; + $subject =~ s/\%22/\"/g; + $subject =~ s/\%23/\#/g; + $subject =~ s/\%24/\$/g; + $subject =~ s/\%25/\%/g; + $subject =~ s/\%26/\&/g; + $subject =~ s/\%27/\'/g; + $subject =~ s/\%28/\(/g; + $subject =~ s/\%29/\)/g; + $subject =~ s/\%2a/\*/g; + $subject =~ s/\%2A/\*/g; + $subject =~ s/\%2b/\+/g; + $subject =~ s/\%2B/\+/g; + $subject =~ s/\%2c/\,/g; + $subject =~ s/\%2C/\,/g; + $subject =~ s/\%2d/\-/g; + $subject =~ s/\%2D/\-/g; + $subject =~ s/\%2e/\./g; + $subject =~ s/\%2E/\./g; + $subject =~ s/\%2f/\//g; + $subject =~ s/\%2F/\//g; + } elsif ($cmd eq "--type") { + my $tmp = shift @ARGV; + $ct = $tmp if (defined $tmp); + } elsif ($cmd eq "--from") { + my $tmp = shift @ARGV; + $from = $tmp if (defined $tmp); + } elsif ($cmd eq "--file") { + my $tmp = shift @ARGV; + $file = $tmp if (defined $tmp); + } elsif ($cmd eq "--attachment") { + my $tmp = shift @ARGV; + $attachment = $tmp if (defined $tmp); + } elsif ($cmd eq "--dest") { + my $tmp = shift @ARGV; + if ($tmp =~ /\^(\")|^(\')/) { + # It's a quoted string + my $delim = $+; # $+ is 'last match', which is ' or " + $tmp =~ s/\Q$delim\E//; # Strip out ' or " + $dest = $tmp; + while ($tmp = shift @ARGV) { + if ($tmp =~ /\Q$delim\E/) { + $tmp =~ s/\Q$delim\E//; + last; + } + $dest .= $tmp; + } + } else { + # It's a single word + $dest = $tmp; + } + } else { + die "$cmd not understood\n$usage\n"; + } + +} + +# OK. All our variables are set up. +# Lets make sure that we know about a file... +die $usage unless $file; +# and that the file exists... +open( FILE, $file ) or die "Error opening $file: $!"; +# Oh, did we possibly not specify an attachment name? +$attachment = $file unless ($attachment); + +my $encoded=""; +my $enc_gif=""; +my $buf=""; +my $convert_status=0; + +# First, lets find out if it's a TIFF file +read(FILE, $buf, 4); +if ($buf eq "MM\x00\x2a" || $buf eq "II\x2a\x00") { + # Tiff magic - We need to convert it to pdf first + # Need to do some error testing here - what happens if tiff2pdf + # doesn't exist? + open PDF, "tiff2pdf $file|"; + $buf = ""; + while (read(PDF, $buf, 60*57)) { + $encoded .= encode_base64($buf); + } + close PDF; + + open GIF, "convert -resize '50%' -monochrome -delay 300 ${file}[0,1] gif:- |"; + if (!eof(GIF)) { + $convert_status=1; + $buf = ""; + while (read(GIF, $buf, 60*57)) { + $enc_gif .= encode_base64($buf); + } + } + close GIF; +} else { + # It's a PDF already + # Go back to the start of the file, and start again + seek(FILE, 0, 0); + while (read(FILE, $buf, 60*57)) { + $encoded .= encode_base64($buf); + } +} +close FILE; + +# Now we have the file, we should ensure that there's no paths on the +# filename.. +$attachment =~ s/^.+\///; + +# And that's pretty much all the hard work done. Now we just create the +# headers for the MIME encapsulation: +my $boundary = '------FREEPBX_FAX_MAIL:'; +my $dtime = `date -R`; +chomp $dtime; +my @chrs = ('0' .. '9', 'A' .. 'Z', 'a' .. 'z'); +foreach (0..16) { $boundary .= $chrs[rand (scalar @chrs)]; } + +my $len = length $encoded; +my $len_gif = length $enc_gif; +# message body.. +my $msg ="Content-Class: urn:content-classes:message +Content-Transfer-Encoding: 7bit +MIME-Version: 1.0 +Content-Type: multipart/mixed; boundary=\"$boundary\" +From: $from +Date: $dtime +Reply-To: $from +X-Mailer: dofaxmail.pl +To: $to +Subject: $subject + +This is a multi-part message in MIME format. + +--$boundary +Content-Type: text/plain; charset=\"us-ascii\" +Content-Transfer-Encoding: quoted-printable + +A Fax has been received by the fax gateway and is attached to this message. + +The destination number for this fax is ".$dest." + + +"; +if ($convert_status eq 1) { +$msg=$msg."--$boundary +Content-Type: image/gif; name=\"thumb-".substr($attachment,0,-4).".gif\" +Content-Transfer-Encoding: base64 + +$enc_gif +"; +} + +$msg=$msg."--$boundary +Content-Type: $ct; name=\"$attachment\" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename=\"$attachment\" + +$encoded +--$boundary-- +"; + +#print "$msg"; +# Now we just send it. +my $smtp = Net::SMTP-> new("127.0.0.1", Debug => 0) or + die "Net::SMTP::new: $!"; +$smtp-> mail($from); +$smtp-> recipient($to); +$smtp-> data(); +$smtp-> datasend($msg); +$smtp-> dataend(); + Index: /modules/branches/2.6/core/etc/sip.conf =================================================================== --- /modules/branches/2.6/core/etc/sip.conf (revision 7041) +++ /modules/branches/2.6/core/etc/sip.conf (revision 7041) @@ -0,0 +1,51 @@ +;--------------------------------------------------------------------------------; +; Do NOT edit this file as it is auto-generated by FreePBX. All modifications to ; +; this file must be done via the web gui. There are alternative files to make ; +; custom modifications, details at: http://freepbx.org/configuration_files ; +;--------------------------------------------------------------------------------; +; + +[general] + +; These files will all be included in the [general] context +; +#include sip_general_additional.conf + +;sip_general_custom.conf is the proper file location for placing any sip general +;options that you might need set. For example: enable and force the sip jitterbuffer. +;If these settings are desired they should be set the sip_general_custom.conf file. +; +; jbenable=yes +; jbforce=yes +; +;It is also the proper place to add the lines needed for sip nat'ing when going +;through a firewall. For nat'ing you'd need to add the following lines: +; nat=yes , externip= , localhost= , and optionally fromdomain= . +; +#include sip_general_custom.conf + +;sip_nat.conf is here for legacy support reasons and for those that upgrade +;from previous versions. If you have this file with lines in it please make +;sure they are not duplicated in sip_general_custom.conf, if so remove them +;from sip_nat.conf as sip_general_custom.conf will have precedence. +#include sip_nat.conf + +;sip_registrations_custom.conf is for any customizations you might need to do to +;the automatically generated registrations that FreePBX makes. +; +#include sip_registrations_custom.conf +#include sip_registrations.conf + +; These files should all be expected to come after the [general] context +; +#include sip_custom.conf +#include sip_additional.conf + +;sip_custom_post.conf If you have extra parameters that are needed for a +;extension to work to for example, those go here. So you have extension +;1000 defined in your system you start by creating a line [1000](+) in this +;file. Then on the next line add the extra parameter that is needed. +;When the sip.conf is loaded it will append your additions to the end of +;that extension. +; +#include sip_custom_post.conf Index: /modules/branches/2.6/core/etc/features.conf =================================================================== --- /modules/branches/2.6/core/etc/features.conf (revision 6673) +++ /modules/branches/2.6/core/etc/features.conf (revision 6673) @@ -0,0 +1,18 @@ +;--------------------------------------------------------------------------------; +; Do NOT edit this file as it is auto-generated by FreePBX. All modifications to ; +; this file must be done via the web gui. There are alternative files to make ; +; custom modifications, details at: http://freepbx.org/configuration_files ; +;--------------------------------------------------------------------------------; +; + +[general] +#include features_general_additional.conf +#include features_general_custom.conf + +[applicationmap] +#include features_applicationmap_additional.conf +#include features_applicationmap_custom.conf + +[featuremap] +#include features_featuremap_additional.conf +#include features_featuremap_custom.conf Index: /modules/branches/2.6/core/etc/extensions.conf =================================================================== --- /modules/branches/2.6/core/etc/extensions.conf (revision 6999) +++ /modules/branches/2.6/core/etc/extensions.conf (revision 6999) @@ -0,0 +1,1080 @@ +;--------------------------------------------------------------------------------; +; Do NOT edit this file as it is auto-generated by FreePBX. All modifications to ; +; this file must be done via the web gui. There are alternative files to make ; +; custom modifications, details at: http://freepbx.org/configuration_files ; +;--------------------------------------------------------------------------------; +; + +; FreePBX +; Copyright (C) 2004 Coalescent Systems Inc (Canada) +; Copyright (C) 2006 Why Pay More 4 Less Pty Ltd (Australia) +; Copyright (C) 2007 Astrogen LLC (USA) +; Released under the GNU GPL Licence version 2. + +; dialparties.agi (http://www.sprackett.com/asterisk/) +; Asterisk::AGI (http://asterisk.gnuinter.net/) +; gsm (http://www.ibiblio.org/pub/Linux/utils/compress/!INDEX.short.html) +; loligo sounds (http://www.loligo.com/asterisk/sounds/) +; mpg123 (http://voip-info.org/wiki-Asterisk+config+musiconhold.conf) + +;************************** -WARNING- **************************************** +; * +; This include file is to be used with extreme caution. In almost all cases * +; any custom dialplan SHOULD be put in extensions_custom.conf which will * +; not hurt a FreePBX generated dialplan. In some very rare and custom * +; situations users may have a need to override what freepbx automatically * +; generates. If so anything in this file will do that. If you come up with a * +; situation where you need to modify the existing dialplan or macro, please * +; put it here and also notify the FreePBX development team so they can take it * +; into account in the future. * +; * +#include extensions_override_freepbx.conf +; * +;************************** -WARNING- **************************************** + +; include extension contexts generated from AMP +#include extensions_additional.conf + +; Customizations to this dialplan should be made in extensions_custom.conf +; See extensions_custom.conf.sample for an example. +; If you need to use [macro-dialout-trunk-predial-hook], [ext-did-custom], or +; [from-internal-custom] for example, place these in this file or they will get overwritten. +; +#include extensions_custom.conf + +[from-trunk] ; just an alias since VoIP shouldn't be called PSTN +include => from-pstn + +[from-pstn] +include => from-pstn-custom ; create this context in extensions_custom.conf to include customizations +include => ext-did +include => ext-did-post-custom +include => from-did-direct ; MODIFICATOIN (PL) for findmefollow if enabled, should be bofore ext-local +include => ext-did-catchall ; THIS MUST COME AFTER ext-did +exten => fax,1,Goto(ext-fax,in_fax,1) + +; MODIFICATION (PL) +; +; Required to assure that direct dids go to personal ring group before local extension. +; This could be auto-generated however I it is prefered to be put here and hard coded +; so that it can be modified if ext-local should take precedence in certain situations. +; will have to decide what to do later. +; +[from-did-direct] +include => ext-findmefollow +include => ext-local + + + +; ############################################################################ +; Macros [macro] +; ############################################################################ + +; Rings one or more extensions. Handles things like call forwarding and DND +; We don't call dial directly for anything internal anymore. +; ARGS: $TIMER, $OPTIONS, $EXT1, $EXT2, $EXT3, ... +; Use a Macro call such as the following: +; Macro(dial,$DIAL_TIMER,$DIAL_OPTIONS,$EXT1,$EXT2,$EXT3,...) +[macro-dial] +exten => s,1,GotoIf($["${MOHCLASS}" = ""]?dial) +exten => s,n,SetMusicOnHold(${MOHCLASS}) +exten => s,n(dial),AGI(dialparties.agi) +exten => s,n,NoOp(Returned from dialparties with no extensions to call and DIALSTATUS: ${DIALSTATUS}) + +exten => s,n+2(normdial),Dial(${ds}) ; dialparties will set the priority to 10 if $ds is not null +exten => s,n,Set(DIALSTATUS=${IF($["${DIALSTATUS_CW}"!="" ]?${DIALSTATUS_CW}:${DIALSTATUS})}) +exten => s,n,GosubIf($["${SCREEN}" != ""]?${DIALSTATUS},1) + +exten => s,20(huntdial),NoOp(Returned from dialparties with hunt groups to dial ) +exten => s,n,Set(HuntLoop=0) +exten => s,n(a22),GotoIf($[${HuntMembers} >= 1]?a30) ; if this is from rg-group, don't strip prefix +exten => s,n,NoOp(Returning there are no members left in the hunt group to ring) + +; dialparties.agi has setup the dialstring for each hunt member in a variable labeled HuntMember0, HuntMember1 etc for each iteration +; and The total number in HuntMembers. So for each iteration, we will update the CALLTRACE Data. +; +exten => s,n+2(a30),Set(HuntMember=HuntMember${HuntLoop}) +exten => s,n,GotoIf($[$["${CALLTRACE_HUNT}" != "" ] & $["${RingGroupMethod}" = "hunt" ]]?a32:a35) +exten => s,n(a32),Set(CT_EXTEN=${CUT(FILTERED_DIAL,,$[${HuntLoop} + 1])}) +exten => s,n,Set(DB(CALLTRACE/${CT_EXTEN})=${CALLTRACE_HUNT}) +exten => s,n,Goto(s,a42) + +;Set Call Trace for each hunt member we are going to call "Memory groups have multiple members to set CALL TRACE For hence the loop +; +exten => s,n(a35),GotoIf($[$["${CALLTRACE_HUNT}" != "" ] & $["${RingGroupMethod}" = "memoryhunt" ]]?a36:a50) +exten => s,n(a36),Set(CTLoop=0) +exten => s,n(a37),GotoIf($[${CTLoop} > ${HuntLoop}]?a42) ; if this is from rg-group, don't strip prefix +exten => s,n,Set(CT_EXTEN=${CUT(FILTERED_DIAL,,$[${CTLoop} + 1])}) +exten => s,n,Set(DB(CALLTRACE/${CT_EXTEN})=${CALLTRACE_HUNT}) +exten => s,n,Set(CTLoop=$[1 + ${CTLoop}]) +exten => s,n,Goto(s,a37) + +exten => s,n(a42),Dial(${${HuntMember}}${ds}) +exten => s,n,Set(HuntLoop=$[1 + ${HuntLoop}]) +exten => s,n,GotoIf($[$[$["foo${RingGroupMethod}" != "foofirstavailable"] & $["foo${RingGroupMethod}" != "foofirstnotonphone"]] | $["foo${DialStatus}" = "fooBUSY"]]?a46) +exten => s,n,Set(HuntMembers=0) +exten => s,n(a46),Set(HuntMembers=$[${HuntMembers} - 1]) +exten => s,n,Goto(s,a22) + +exten => s,n(a50),DBdel(CALLTRACE/${CT_EXTEN}) +exten => s,n,Goto(s,a42) + +; For call screening +exten => NOANSWER,1,Macro(vm,${SCREEN_EXTEN},BUSY,${IVR_RETVM}) +exten => NOANSWER,n,GotoIf($["${IVR_RETVM}" != "RETURN" | "${IVR_CONTEXT}" = ""]?bye) +exten => NOANSWER,n,Return +exten => NOANSWER,n(bye),Macro(hangupcall) +exten => TORTURE,1,Goto(app-blackhole,musiconhold,1) +exten => TORTURE,n,Macro(hangupcall) +exten => DONTCALL,1,Answer +exten => DONTCALL,n,Wait(1) +exten => DONTCALL,n,Zapateller() +exten => DONTCALL,n,Playback(ss-noservice) +exten => DONTCALL,n,Macro(hangupcall) + +; make sure hungup calls go here so that proper cleanup occurs from call confirmed calls and the like +; +exten => h,1,Macro(hangupcall) + +; Ring an extension, if the extension is busy or there is no answer send it +; to voicemail +; ARGS: $VMBOX, $EXT +[macro-exten-vm] +exten => s,1,Macro(user-callerid) + +exten => s,n,Set(RingGroupMethod=none) +exten => s,n,Set(VMBOX=${ARG1}) +exten => s,n,Set(EXTTOCALL=${ARG2}) +exten => s,n,Set(CFUEXT=${DB(CFU/${EXTTOCALL})}) +exten => s,n,Set(CFBEXT=${DB(CFB/${EXTTOCALL})}) +exten => s,n,Set(RT=${IF($[$["${VMBOX}"!="novm"] | $["foo${CFUEXT}"!="foo"]]?${RINGTIMER}:"")}) +exten => s,n,Macro(record-enable,${EXTTOCALL},IN) +exten => s,n,Macro(dial,${RT},${DIAL_OPTIONS},${EXTTOCALL}) +exten => s,n,GotoIf($[ $["${VMBOX}" != "novm"] & $["${SCREEN}" != ""] & $["${DIALSTATUS}" = "NOANSWER"] ]?exit,return) +exten => s,n,Set(SV_DIALSTATUS=${DIALSTATUS}) +exten => s,n,GosubIf($[$["${SV_DIALSTATUS}"="NOANSWER"] & $["${CFUEXT}"!=""] & $["${SCREEN}" = ""]]?docfu,1) ; check for CFU in use on no answer +exten => s,n,GosubIf($[$["${SV_DIALSTATUS}"="BUSY"] & $["${CFBEXT}"!=""]]?docfb,1) ; check for CFB in use on busy +exten => s,n,Set(DIALSTATUS=${SV_DIALSTATUS}) +exten => s,n,NoOp(Voicemail is '${VMBOX}') +exten => s,n,GotoIf($["${VMBOX}" = "novm"]?s-${DIALSTATUS},1) ; no voicemail in use for this extension +exten => s,n,NoOp(Sending to Voicemail box ${EXTTOCALL}) +exten => s,n,Macro(vm,${VMBOX},${DIALSTATUS},${IVR_RETVM}) + +; Try the Call Forward on No Answer / Unavailable number +exten => docfu,1,Set(RTCFU=${IF($["${VMBOX}"!="novm"]?${RINGTIMER}:"")}) +exten => docfu,n,Dial(Local/${CFUEXT}@from-internal/n,${RTCFU},${DIAL_OPTIONS}) +exten => docfu,n,Return + +; Try the Call Forward on Busy number +exten => docfb,1,Set(RTCFB=${IF($["${VMBOX}"!="novm"]?${RINGTIMER}:"")}) +exten => docfb,n,Dial(Local/${CFBEXT}@from-internal/n,${RTCFB},${DIAL_OPTIONS}) +exten => docfb,n,Return + +; Extensions with no Voicemail box reporting BUSY come here +exten => s-BUSY,1,NoOp(Extension is reporting BUSY and not passing to Voicemail) +exten => s-BUSY,n,GotoIf($["${IVR_RETVM}" = "RETURN" & "${IVR_CONTEXT}" != ""]?exit,1) +exten => s-BUSY,n,Playtones(busy) +exten => s-BUSY,n,Busy(20) + +; Anything but BUSY comes here +exten => _s-.,1,Noop(IVR_RETVM: ${IVR_RETVM} IVR_CONTEXT: ${IVR_CONTEXT}) +exten => _s-.,n,GotoIf($["${IVR_RETVM}" = "RETURN" & "${IVR_CONTEXT}" != ""]?exit,1) +exten => _s-.,n,Playtones(congestion) +exten => _s-.,n,Congestion(10) + +; Short burst of tones then return +exten => exit,1,Playback(beep&line-busy-transfer-menu&silence/1) +exten => exit,n(return),MacroExit() + +;------------------------------------------------------------------------ +; [macro-vm] +;------------------------------------------------------------------------ +; CONTEXT: macro-vm +; PURPOSE: call voicemail system and extend with personal ivr +; +; Under normal use, this macro will call the voicemail system with the extension and +; desired greeting mode of busy, unavailable or as specified with direct voicemail +; calls (usually unavailable) when entered from destinations. +; +; The voicemail system's two greetings have been 'hijacked' as follows to extend the +; system by giving the option of a private 'ivr' for each voicemail user. The following +; applies to both the busy and unavailable modes of voicemail and can be applied to one +; or both, and differently. +; +; Global Defaults: +; +; The following are default values, used in both busy and unavail modes if no specific +; values are specified. +; +; VMX_REPEAT +; The number of times to repeat the users message if no option is pressed. +; VMX_TIMEOUT +; The timeout to wait after playing message before repeating or giving up. +; VMX_LOOPS +; The number of times it should replay the message and check for an option when +; an invalid option is pressed. +; +; VMX_OPTS_DOVM +; Default voicemail option to use if vm is chosen as an option. No options will +; cause Allison's generic message, 's' will go straight to beep. +; VMX_OPTS_TIMEOUT +; Default voicemail option to use if it times out with no options. No options will +; cause Allison's generic message, 's' will go straight to beep. +; IF THE USER PRESSES # - it will look like a timeout as well since no option will +; be presented. If the user wishes to enable a mode where a caller can press # +; during their message and it goes straight to voicemail with only a 'beep' then +; this should be set to 's'. +; VMX_OPTS_LOOPS +; Default voicemail option to use if to many wrong options occur. No options will +; cause Allison's generic message, 's' will go straight to beep. +; +; VMX_CONTEXT +; Default context for user destinations if not supplied in the user's settings +; VMX_PRI +; Default priority for user destinations if not supplied in the user's settings +; +; VMX_TIMEDEST_CONTEXT +; Default context for timeout destination if not supplied in the user's settings +; VMX_TIMEDEST_EXT +; Default extension for timeout destination if not supplied in the user's settings +; VMX_TIMEDEST_PRI +; Default priority for timeout destination if not supplied in the user's settings +; +; VMX_LOOPDEST_CONTEXT +; Default context for loops destination if not supplied in the user's settings +; VMX_LOOPDEST_EXT +; Default extension for loops destination if not supplied in the user's settings +; VMX_LOOPDEST_PRI +; Default priority for loops destination if not supplied in the user's settings +; +; +; The AMPUSER database variable has been extended with a 'vmx' tree (vm-extension). A +; duplicate set is included for both unavail and busy. You could choose for to have an +; ivr when unavail is taken, but not with busy - or a different once with busy. +; The full list is below, each specific entry is futher described: +; +; state: Whether teh current mode is enabled or disabled. Anything but 'enabled' is +; treated as disabled. +; repeat: This is the number of times that the users message should be played after the +; timeout if the user has not entered anything. It is just a variable to the +; Read() function which will do the repeating. +; timeout: This is how long to wait after the message has been read for a response from +; the user. A caller can enter a digit any time during the playback. +; loops: This is the number of loops that the system will allow a caller to retry if +; they enter a bad menu choice, before going to the loop failover destination +; vmxopts: This is the vm options to send to the voicemail command used when a specific +; voicemail destination is chosen (inidcated by 'dovm' in the ext field). This is +; typically either set to 's' or left blank. When set to 's' there will be no +; message played when entering the voicemail, just a beep. When blank, you will +; have Allison's generic message played. It is not typical to play the greetings +; since they have been 'hijacked' for these IVR's and from a caller's perspecitive +; this system appears interconnected with the voicemail so instructions can be +; left there. +; timedest: The three variables: ext, context and pri are the goto destination if the caller +; enters no options and it timesout. None have to be set and a system default +; will be used. If just ext is set, then defaults will be used for context and +; pri, etc. +; loopdest: This is identical to timedest but used if the caller exceeds the maximum invalid +; menu choices. +; [0-9*]: The user can specify up to 11 ivr options, all as single digits from 0-9 or *. The +; # key can not be used since it is used as a terminator key for the Read command +; and will never be returned. A minimum of the ext must be specified for each valid +; option and as above, the context and priority can also be specified if the default +; is not to be used. +; Option '0' takes on a special meaning. Since a user is able to break out of the +; voicemail command once entering it with a 0, if specified, the 0 destination will +; be used. +; Option '*' can also be used to breakout. It is undecided at this point whether +; providing that option will be used as well. (probably should). +; +; +; /AMPUSER//vmx/[busy|unavail]/state: enabled|disabled +; /AMPUSER//vmx/[busy|unavail]/repeat: n (times to repeat message) +; /AMPUSER//vmx/[busy|unavail]/timeout: n (timeout to wait for digit) +; /AMPUSER//vmx/[busy|unavail]/loops: n (loop returies for invalid entries) +; /AMPUSER//vmx/[busy|unavail]/vmxopts/dovm: vmoptions (if ext is dovm) +; /AMPUSER//vmx/[busy|unavail]/vmxopts/timeout: vmoptions (if timeout) +; /AMPUSER//vmx/[busy|unavail]/vmxopts/loops: vmoptions (if loops) +; /AMPUSER//vmx/[busy|unavail]/timedest/ext: extension (if timeout) +; /AMPUSER//vmx/[busy|unavail]/timedest/context: context (if timeout) +; /AMPUSER//vmx/[busy|unavail]/timedest/pri: priority (if timeout) +; /AMPUSER//vmx/[busy|unavail]/loopdest/ext: extension (if too many failures) +; /AMPUSER//vmx/[busy|unavail]/loopdest/context: context (if too many failures) +; /AMPUSER//vmx/[busy|unavail]/loopdest/pri: priority (if too many failures) +; /AMPUSER//vmx/[busy|unavail]/[0-9*]/ext: extension (dovm for vm access) +; /AMPUSER//vmx/[busy|unavail]/[0-9*]/context: context +; /AMPUSER//vmx/[busy|unavail]/[0-9*]/pri: priority +;------------------------------------------------------------------------ +[macro-vm] +; ARG1 - extension +; ARG2 - DIRECTDIAL/BUSY +; ARG3 - RETURN makes macro return, otherwise hangup +exten => s,1,Macro(user-callerid,SKIPTTL) +exten => s,n,Set(VMGAIN=${IF($["foo${VM_GAIN}"!="foo"]?"g(${VM_GAIN})":"")}) +; +; If BLKVM_OVERRIDE is set, then someone told us to block calls from going to +; voicemail. This variable is reset by the answering channel so subsequent +; transfers will properly function. +; +exten => s,n,GotoIf($["foo${DB(${BLKVM_OVERRIDE})}" != "fooTRUE"]?vmx,1) +; +; we didn't branch so block this from voicemail +; +exten => s,n,Noop(CAME FROM: ${NODEST} - Blocking VM cause of key: ${DB(BLKVM_OVERRIDE)}) + + +; If vmx not enabled for the current mode,then jump to normal voicemail behavior +; also - if not message (no-msg) is requested, straight to voicemail +; +exten => vmx,1,GotoIf($["${ARG2}"="NOMESSAGE"]?s-${ARG2},1) +exten => vmx,n,Set(MODE=${IF($["${ARG2}"="BUSY"]?busy:unavail)}) +exten => vmx,n,GotoIf($["${ARG2}" != "DIRECTDIAL"]?notdirect) +exten => vmx,n,Set(MODE=${IF($["${REGEX("[b]" ${VM_DDTYPE})}" = "1"]?busy:${MODE})}) +exten => vmx,n(notdirect),Noop(Checking if ext ${ARG1} is enabled: ${DB(AMPUSER/${ARG1}/vmx/${MODE}/state)}) +exten => vmx,n,GotoIf($["${DB(AMPUSER/${ARG1}/vmx/${MODE}/state)}" != "enabled"]?s-${ARG2},1) + +; If the required voicemail file does not exist, then abort and go to normal voicemail behavior +; +; TODO: there have been errors using System() with jump to 101 where asterisk works fine at the begining and +; then starts to jump to 101 even on success. This new mode is being tried with the SYSTEM Status which +; returns SUCCESS when the command returned succcessfully with a 0 app return code. +; +exten => vmx,n,Macro(get-vmcontext,${ARG1}) +;exten => vmx,n,TrySystem(/bin/ls ${ASTSPOOLDIR}/voicemail/${VMCONTEXT}/${ARG1}/${MODE}.[wW][aA][vV]) +exten => vmx,n,AGI(checksound.agi,${ASTSPOOLDIR}/voicemail/${VMCONTEXT}/${ARG1}/temp) +exten => vmx,n,GotoIf($["${SYSTEMSTATUS}" = "SUCCESS"]?tmpgreet) +exten => vmx,n,AGI(checksound.agi,${ASTSPOOLDIR}/voicemail/${VMCONTEXT}/${ARG1}/${MODE}) +exten => vmx,n,GotoIf($["${SYSTEMSTATUS}" != "SUCCESS"]?nofile) + +; Get the repeat, timeout and loop times to use if they are overriden form the global settings +; +exten => vmx,n,Set(LOOPCOUNT=0) +exten => vmx,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/repeat)}" = "0"]?vmxtime) +exten => vmx,n,Set(VMX_REPEAT=${DB_RESULT}) +exten => vmx,n(vmxtime),GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/timeout)}" = "0"]?vmxloops) +exten => vmx,n,Set(VMX_TIMEOUT=${DB_RESULT}) +exten => vmx,n(vmxloops),GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/loops)}" = "0"]?vmxanswer) +exten => vmx,n,Set(VMX_LOOPS=${DB_RESULT}) +exten => vmx,n(vmxanswer),Answer() + +; Now play the users voicemail recording as the basis for their ivr, the Read command will repeat as needed and if it timesout +; then we go to the timeout. Otherwise handle invalid options by looping until the limit until a valid option is played. +; +exten => vmx,n(loopstart),Read(ACTION,${ASTSPOOLDIR}/voicemail/${VMCONTEXT}/${ARG1}/${MODE},1,skip,${VMX_REPEAT},${VMX_TIMEOUT}) +exten => vmx,n,GotoIf($["${EXISTS(${ACTION})}" = "1"]?checkopt) + +; If we are here we timed out, go to the required destination +; +exten => vmx,n(noopt),Noop(Timeout: going to timeout dest) +exten => vmx,n,Set(VMX_OPTS=${VMX_OPTS_TIMEOUT}) +exten => vmx,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/vmxopts/timeout)}" = "0"]?chktime) +exten => vmx,n,Set(VMX_OPTS=${DB_RESULT}) +exten => vmx,n(chktime),GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/timedest/ext)}" = "0"]?dotime) +exten => vmx,n,Set(VMX_TIMEDEST_EXT=${DB_RESULT}) +exten => vmx,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/timedest/context)}" = "0"]?timepri) +exten => vmx,n,Set(VMX_TIMEDEST_CONTEXT=${DB_RESULT}) +exten => vmx,n(timepri),GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/timedest/pri)}" = "0"]?dotime) +exten => vmx,n,Set(VMX_TIMEDEST_PRI=${DB_RESULT}) +exten => vmx,n(dotime),Goto(${VMX_TIMEDEST_CONTEXT},${VMX_TIMEDEST_EXT},${VMX_TIMEDEST_PRI}) + +; We got an option, check if the option is defined, or one of the system defaults +; +exten => vmx,n(checkopt),GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/${ACTION}/ext)}" = "1"]?doopt) +exten => vmx,n,GotoIf($["${ACTION}" = "0"]?o,1) +exten => vmx,n,GotoIf($["${ACTION}" = "*"]?adef,1) + +; Got invalid option loop until the max +; +exten => vmx,n,Set(LOOPCOUNT=$[${LOOPCOUNT} + 1]) +exten => vmx,n,GotoIf($[${LOOPCOUNT} > ${VMX_LOOPS}]?toomany) +exten => vmx,n,Playback(pm-invalid-option&please-try-again) +exten => vmx,n,Goto(loopstart) + +; tomany: to many invalid options, go to the specified destination +; +exten => vmx,n(toomany),Noop(Too Many invalid entries, got to invalid dest) +exten => vmx,n,Set(VMX_OPTS=${VMX_OPTS_LOOPS}) +exten => vmx,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/vmxopts/loops)}" = "0"]?chkloop) +exten => vmx,n,Set(VMX_OPTS=${DB_RESULT}) +exten => vmx,n(chkloop),GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/loopdest/ext)}" = "0"]?doloop) +exten => vmx,n,Set(VMX_LOOPDEST_EXT=${DB_RESULT}) +exten => vmx,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/loopdest/context)}" = "0"]?looppri) +exten => vmx,n,Set(VMX_LOOPDEST_CONTEXT=${DB_RESULT}) ;TODO make configurable per above +exten => vmx,n(looppri),GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/loopdest/pri)}" = "0"]?doloop) +exten => vmx,n,Set(VMX_LOOPDEST_PRI=${DB_RESULT}) ;TODO make configurable per above +exten => vmx,n(doloop),Goto(${VMX_LOOPDEST_CONTEXT},${VMX_LOOPDEST_EXT},${VMX_LOOPDEST_PRI}) + +; doopt: execute the valid option that was chosen +; +exten => vmx,n(doopt),Noop(Got a valid option: ${DB_RESULT}) +exten => vmx,n,Set(VMX_EXT=${DB_RESULT}) +; +; Special case, if this option was to go to voicemail, set options and go +; +exten => vmx,n,GotoIf($["${VMX_EXT}" != "dovm"]?getdest) +exten => vmx,n(vmxopts),Set(VMX_OPTS=${VMX_OPTS_DOVM}) +exten => vmx,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/vmxopts/dovm)}" = "0"]?vmxdovm) +exten => vmx,n(vmxopts),Set(VMX_OPTS=${DB_RESULT}) +exten => vmx,n(vmxdovm),goto(dovm,1) +; +; General case, setup the goto destination and go there (no error checking, its up to the GUI's to assure +; reasonable values +; +exten => vmx,n(getdest),GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/${ACTION}/context)}" = "0"]?vmxpri) +exten => vmx,n,Set(VMX_CONTEXT=${DB_RESULT}) +exten => vmx,n(vmxpri),GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/${ACTION}/pri)}" = "0"]?vmxgoto) +exten => vmx,n,Set(VMX_PRI=${DB_RESULT}) +exten => vmx,n(vmxgoto),Goto(${VMX_CONTEXT},${VMX_EXT},${VMX_PRI}) + +; If the required voicemail file is not present, then revert to normal voicemail +; behavior treating as if it was not set +; +exten => vmx,n(nofile),Noop(File for mode: ${MODE} does not exist, SYSTEMSTATUS: ${SYSTEMSTATUS}, going to normal voicemail) +exten => vmx,n,Goto(s-${ARG2},1) +exten => vmx,n(tmpgreet),Noop(Temporary Greeting Detected, going to normal voicemail) +exten => vmx,n,Goto(s-${ARG2},1) + +; Drop into voicemail either as a direct destination (in which case VMX_OPTS might be set to something) or +; if the user timed out or broke out of the loop then VMX_OPTS is always cleared such that an Allison +; message is played and the caller know's what is going on. +; +exten => dovm,1,Noop(VMX Timeout - go to voicemail) +exten => dovm,n,Voicemail(${ARG1}@${VMCONTEXT},${VMX_OPTS}${VMGAIN}) ; no flags, so allison plays please leave ... +exten => dovm,n,Goto(exit-${VMSTATUS},1) + +exten => s-BUSY,1,NoOp(BUSY voicemail) +exten => s-BUSY,n,Macro(get-vmcontext,${ARG1}) +exten => s-BUSY,n,Voicemail(${ARG1}@${VMCONTEXT},${VM_OPTS}b${VMGAIN}) ; Voicemail Busy message +exten => s-BUSY,n,Goto(exit-${VMSTATUS},1) + +exten => s-NOMESSAGE,1,NoOp(NOMESSAGE (beeb only) voicemail) +exten => s-NOMESSAGE,n,Macro(get-vmcontext,${ARG1}) +exten => s-NOMESSAGE,n,Voicemail(${ARG1}@${VMCONTEXT},s${VM_OPTS}${VMGAIN}) +exten => s-NOMESSAGE,n,Goto(exit-${VMSTATUS},1) + +exten => s-DIRECTDIAL,1,NoOp(DIRECTDIAL voicemail) +exten => s-DIRECTDIAL,n,Macro(get-vmcontext,${ARG1}) +exten => s-DIRECTDIAL,n,Voicemail(${ARG1}@${VMCONTEXT},${VM_OPTS}${VM_DDTYPE}${VMGAIN}) +exten => s-DIRECTDIAL,n,Goto(exit-${VMSTATUS},1) + +exten => _s-.,1,Macro(get-vmcontext,${ARG1}) +exten => _s-.,n,Voicemail(${ARG1}@${VMCONTEXT},${VM_OPTS}u${VMGAIN}) ; Voicemail Unavailable message +exten => _s-.,n,Goto(exit-${VMSTATUS},1) + +; If the user has a 0 option defined, use that for operator zero-out from within voicemail +; as well to keep it consistant with the menu structure +; +exten => o,1,Background(one-moment-please) ; 0 during vm message will hangup +exten => o,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/0/ext)}" = "0"]?doopdef) + +exten => o,n,Set(VMX_OPDEST_EXT=${DB_RESULT}) +exten => o,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/0/context)}" = "1"]?opcontext) +exten => o,n,Set(DB_RESULT=${VMX_CONTEXT}) +exten => o,n(opcontext),Set(VMX_OPDEST_CONTEXT=${DB_RESULT}) +exten => o,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/0/pri)}" = "1"]?oppri) +exten => o,n,Set(DB_RESULT=${VMX_PRI}) +exten => o,n(oppri),Set(VMX_OPDEST_PRI=${DB_RESULT}) + +exten => o,n,Goto(${VMX_OPDEST_CONTEXT},${VMX_OPDEST_EXT},${VMX_OPDEST_PRI}) +exten => o,n(doopdef),GotoIf($["x${OPERATOR_XTN}"="x"]?nooper:from-internal,${OPERATOR_XTN},1) +exten => o,n(nooper),GotoIf($["x${FROM_DID}"="x"]?nodid) +exten => o,n,Dial(Local/${FROM_DID}@from-pstn) +exten => o,n,Macro(hangup) +exten => o,n(nodid),Dial(Local/s@from-pstn) +exten => o,n,Macro(hangup) + +; If the user has a * option defined, use that for the * out from within voicemail +; as well to keep it consistant with the menu structure +; +exten => a,1,Macro(get-vmcontext,${ARG1}) +exten => a,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/*/ext)}" = "0"]?adef,1) + +exten => a,n,Set(VMX_ADEST_EXT=${DB_RESULT}) +exten => a,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/*/context)}" = "1"]?acontext) +exten => a,n,Set(DB_RESULT=${VMX_CONTEXT}) +exten => a,n(acontext),Set(VMX_ADEST_CONTEXT=${DB_RESULT}) +exten => a,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/*/pri)}" = "1"]?apri) +exten => a,n,Set(DB_RESULT=${VMX_PRI}) +exten => a,n(apri),Set(VMX_ADEST_PRI=${DB_RESULT}) +exten => a,n,Goto(${VMX_ADEST_CONTEXT},${VMX_ADEST_EXT},${VMX_ADEST_PRI}) + +exten => adef,1,VoiceMailMain(${ARG1}@${VMCONTEXT}) +exten => adef,n,GotoIf($["${ARG3}" = "RETURN"]?exit-RETURN,1) +exten => adef,n,Hangup + +exten => exit-FAILED,1,Playback(im-sorry&an-error-has-occured) +exten => exit-FAILED,n,GotoIf($["${ARG3}" = "RETURN"]?exit-RETURN,1) +exten => exit-FAILED,n,Hangup() + +exten => exit-SUCCESS,1,GotoIf($["${ARG3}" = "RETURN"]?exit-RETURN,1) +exten => exit-SUCCESS,n,Playback(goodbye) +exten => exit-SUCCESS,n,Hangup() + +exten => exit-USEREXIT,1,GotoIf($["${ARG3}" = "RETURN"]?exit-RETURN,1) +exten => exit-USEREXIT,n,Playback(goodbye) +exten => exit-USEREXIT,n,Hangup() + +exten => exit-RETURN,1,Noop(Returning From Voicemail because macro) + +exten => t,1,Hangup() +;------------------------------------------------------------------------ + +;------------------------------------------------------------------------ +; [macro-simple-dial] +;------------------------------------------------------------------------ +; This macro was derived from macro-exten-vm, which is what is normally used to +; ring an extension. It has been simplified and designed to never go to voicemail +; and always return regardless of the DIALSTATUS for any incomplete call. +; +; It's current primary purpose is to allow findmefollow ring an extension prior +; to trying the follow-me ringgroup that is provided. +; +; Ring an extension, if the extension is busy or there is no answer, return +; ARGS: $EXTENSION, $RINGTIME +;------------------------------------------------------------------------ +[macro-simple-dial] +exten => s,1,Set(EXTTOCALL=${ARG1}) +exten => s,n,Set(RT=${ARG2}) +exten => s,n,Set(CFUEXT=${DB(CFU/${EXTTOCALL})}) +exten => s,n,Set(CFBEXT=${DB(CFB/${EXTTOCALL})}) + +exten => s,n,Macro(dial,${RT},${DIAL_OPTIONS},${EXTTOCALL}) + +exten => s,n,Set(PR_DIALSTATUS=${DIALSTATUS}) + +; if we return, thus no answer, and they have a CFU setting, then we try that next +; +exten => s,n,GosubIf($[$["${PR_DIALSTATUS}"="NOANSWER"] & $["foo${CFUEXT}"!="foo"]]?docfu,1) ; check for CFU in use on no answer +exten => s,n,GosubIf($[$["${PR_DIALSTATUS}"="BUSY"] & $["foo${CFBEXT}"!="foo"]]?docfb,1) ; check for CFB in use on busy +exten => s,n,Set(DIALSTATUS=${PR_DIALSTATUS}) + +; Nothing yet, then go to the end (which will just return, but in case we decide to do something with certain +; return situations, this is left in. +; +exten => s,n,Goto(s-${DIALSTATUS},1) + +; Try the Call Forward on No Answer / Unavailable number. +; We want to try CFU if set, but we want the same ring timer as was set to our call (or do we want the +; system ringtimer? - probably not). Then if no answer there (assuming it doesn't drop into their vm or +; something we return, which will have the net effect of returning to the followme setup.) +; +; want to avoid going to other follow-me settings here. So check if the CFUEXT is a user and if it is +; then direct it straight to ext-local (to avoid getting intercepted by findmefollow) otherwise send it +; to from-internal since it may be an outside line. +; +exten => docfu,1,GotoIf( $[ "foo${DB(AMPUSER/${CFUEXT}/device)}" = "foo" ]?chlocal) +exten => docfu,n,Dial(Local/${CFUEXT}@ext-local,${RT},${DIAL_OPTIONS}) +exten => docfu,n,Return +exten => docfu,n(chlocal),Dial(Local/${CFUEXT}@from-internal/n,${RT},${DIAL_OPTIONS}) +exten => docfu,n,Return + +; Try the Call Forward on Busy number +exten => docfb,1,GotoIf( $[ "foo${DB(AMPUSER/${CFBEXT}/device)}" = "foo" ]?chlocal) +exten => docfb,n,Dial(Local/${CFBEXT}@ext-local,${RT},${DIAL_OPTIONS}) +exten => docfb,n,Return +exten => docfb,n(chlocal),Dial(Local/${CFBEXT}@from-internal/n,${RT},${DIAL_OPTIONS}) +exten => docfb,n,Return + +; In all cases of no connection, come here and simply return, since the calling dialplan will +; decide what to do next +exten => _s-.,1,NoOp(Extension is reporting ${EXTEN}) +;------------------------------------------------------------------------ + + +; get the voicemail context for the user in ARG1 +[macro-get-vmcontext] +exten => s,1,Set(VMCONTEXT=${DB(AMPUSER/${ARG1}/voicemail)}) +exten => s,2,GotoIf($["foo${VMCONTEXT}" = "foo"]?200:300) +exten => s,200,Set(VMCONTEXT=default) +exten => s,300,NoOp() + +; For some reason, if I don't run setCIDname, CALLERID(name) will be blank in my AGI +; ARGS: none +[macro-fixcid] +exten => s,1,Set(CALLERID(name)=${CALLERID(name)}) + +; Ring groups of phones +; ARGS: comma separated extension list +; 1 - Ring Group Strategy +; 2 - ringtimer +; 3 - prefix +; 4 - extension list +[macro-rg-group] +exten => s,1,Macro(user-callerid,SKIPTTL) ; already called from ringgroup +exten => s,2,GotoIf($["${CALLERID(name):0:${LEN(${RGPREFIX})}}" != "${RGPREFIX}"]?4:3) ; check for old prefix +exten => s,3,Set(CALLERID(name)=${CALLERID(name):${LEN(${RGPREFIX})}}) ; strip off old prefix +exten => s,4,Set(RGPREFIX=${ARG3}) ; set new prefix +exten => s,5,Set(CALLERID(name)=${RGPREFIX}${CALLERID(name)}) ; add prefix to callerid name +exten => s,6,Set(RecordMethod=Group) ; set new prefix +exten => s,7,Macro(record-enable,${MACRO_EXTEN},${RecordMethod}) +exten => s,8,Set(RingGroupMethod=${ARG1}) ; +exten => s,9,Macro(dial,${ARG2},${DIAL_OPTIONS},${ARG4}) +exten => s,10,Set(RingGroupMethod='') ; + + +; +; Outgoing channel(s) are busy ... inform the client +; but use noanswer features like ringgroups don't break by being answered +; just to play the message. +; +[macro-outisbusy] +exten => s,1,Playback(all-circuits-busy-now,noanswer) +exten => s,n,Playback(pls-try-call-later,noanswer) +exten => s,n,Macro(hangupcall) + +; What to do on hangup. +[macro-hangupcall] +exten => s,1,ResetCDR(w) +exten => s,n,NoCDR() + +; Cleanup any remaining RG flag +; +exten => s,n,GotoIf($[ "x${USE_CONFIRMATION}" = "x" | "x${RINGGROUP_INDEX}" = "x" | "${CHANNEL}" != "${UNIQCHAN}"]?skiprg) +exten => s,n,Noop(Cleaning Up Confirmation Flag: RG/${RINGGROUP_INDEX}/${CHANNEL}) +exten => s,n,DBDel(RG/${RINGGROUP_INDEX}/${CHANNEL}) + +; Cleanup any remaining BLKVM flag +; +exten => s,n(skiprg),GotoIf($[ "x${BLKVM_BASE}" = "x" | "BLKVM/${BLKVM_BASE}/${CHANNEL}" != "${BLKVM_OVERRIDE}" ]?skipblkvm) +exten => s,n,Noop(Cleaning Up Block VM Flag: ${BLKVM_OVERRIDE}) +exten => s,n,DBDel(${BLKVM_OVERRIDE}) + +; Cleanup any remaining FollowMe DND flags +; +exten => s,n(skipblkvm),GotoIf($[ "x${FMGRP}" = "x" | "x${FMUNIQUE}" = "x" | "${CHANNEL}" != "${FMUNIQUE}" ]?theend) +exten => s,n,DBDel(FM/DND/${FMGRP}/${CHANNEL}) + +exten => s,n(theend),Hangup + +[macro-faxreceive] +exten => s,1,Set(FAXFILE=${ASTSPOOLDIR}/fax/${UNIQUEID}.tif) +exten => s,2,Set(EMAILADDR=${FAX_RX_EMAIL}) +exten => s,3,rxfax(${FAXFILE}) +exten => s,103,Set(EMAILADDR=${FAX_RX_EMAIL}) +exten => s,104,Goto(3) + +; dialout and strip the prefix +[macro-dialout] +exten => s,1,Macro(user-callerid,SKIPTTL) +exten => s,2,GotoIf($["${ECID${CALLERID(number)}}" = ""]?5) ;check for CID override for exten +exten => s,3,Set(CALLERID(all)=${ECID${CALLERID(number)}}) +exten => s,4,Goto(7) +exten => s,5,GotoIf($["${OUTCID_${ARG1}}" = ""]?7) ;check for CID override for trunk +exten => s,6,Set(CALLERID(all)=${OUTCID_${ARG1}}) +exten => s,7,Set(length=${LEN(${DIAL_OUT_${ARG1}})}) +exten => s,8,Dial(${OUT_${ARG1}}/${ARG2:${length}}) +exten => s,9,Playtones(congestion) +exten => s,10,Congestion(5) +exten => s,109,Macro(outisbusy) + + +; dialout using default OUT trunk - no prefix +[macro-dialout-default] +exten => s,1,Macro(user-callerid,SKIPTTL) +exten => s,2,Macro(record-enable,${CALLERID(number)},OUT) +exten => s,3,Macro(outbound-callerid,${ARG1}) +exten => s,4,Dial(${OUT}/${ARG1}) +exten => s,5,Playtones(congestion) +exten => s,6,Congestion(5) +exten => s,105,Macro(outisbusy) + +[macro-dialout-trunk-predial-hook] +; this macro intentially left blank so it may be safely overwritten for any custom +; requirements that an installation may have. +; +; MACRO RETURN CODE: ${PREDIAL_HOOK_RET} +; if set to "BYPASS" then this trunk will be skipped +; +exten => s,1,MacroExit() + +; This macro is for dev purposes and just dumps channel/app variables. Useful when designing new contexts. +[macro-dumpvars] +exten => s,1,Noop(ACCOUNTCODE=${ACCOUNTCODE}) +exten => s,2,Noop(ANSWEREDTIME=${ANSWEREDTIME}) +exten => s,3,Noop(BLINDTRANSFER=${BLINDTRANSFER}) +exten => s,4,Noop(CALLERID=${CALLERID(all)}) +exten => s,5,Noop(CALLERID(name)=${CALLERID(name)}) +exten => s,6,Noop(CALLERID(number)=${CALLERID(number)}) +exten => s,7,Noop(CALLINGPRES=${CALLINGPRES}) +exten => s,8,Noop(CHANNEL=${CHANNEL}) +exten => s,9,Noop(CONTEXT=${CONTEXT}) +exten => s,10,Noop(DATETIME=${DATETIME}) +exten => s,11,Noop(DIALEDPEERNAME=${DIALEDPEERNAME}) +exten => s,12,Noop(DIALEDPEERNUMBER=${DIALEDPEERNUMBER}) +exten => s,13,Noop(DIALEDTIME=${DIALEDTIME}) +exten => s,14,Noop(DIALSTATUS=${DIALSTATUS}) +exten => s,15,Noop(DNID=${DNID}) +exten => s,16,Noop(EPOCH=${EPOCH}) +exten => s,17,Noop(EXTEN=${EXTEN}) +exten => s,18,Noop(HANGUPCAUSE=${HANGUPCAUSE}) +exten => s,19,Noop(INVALID_EXTEN=${INVALID_EXTEN}) +exten => s,20,Noop(LANGUAGE=${LANGUAGE}) +exten => s,21,Noop(MEETMESECS=${MEETMESECS}) +exten => s,22,Noop(PRIORITY=${PRIORITY}) +exten => s,23,Noop(RDNIS=${RDNIS}) +exten => s,24,Noop(SIPDOMAIN=${SIPDOMAIN}) +exten => s,25,Noop(SIP_CODEC=${SIP_CODEC}) +exten => s,26,Noop(SIPCALLID=${SIPCALLID}) +exten => s,27,Noop(SIPUSERAGENT=${SIPUSERAGENT}) +exten => s,29,Noop(TXTCIDNAME=${TXTCIDNAME}) +exten => s,30,Noop(UNIQUEID=${UNIQUEID}) +exten => s,31,Noop(TOUCH_MONITOR=${TOUCH_MONITOR}) +exten => s,32,Noop(MACRO_CONTEXT=${MACRO_CONTEXT}) +exten => s,33,Noop(MACRO_EXTEN=${MACRO_EXTEN}) +exten => s,34,Noop(MACRO_PRIORITY=${MACRO_PRIORITY}) + +[macro-user-logon] +; check device type +; +exten => s,1,Set(DEVICETYPE=${DB(DEVICE/${CALLERID(number)}/type)}) +exten => s,n,Answer() +exten => s,n,Wait(1) +exten => s,n,GotoIf($["${DEVICETYPE}" = "fixed"]?s-FIXED,1) +; get user's extension +; +exten => s,n,Set(AMPUSER=${ARG1}) +exten => s,n,GotoIf($["${AMPUSER}" != ""]?gotpass) +exten => s,n(playagain),Read(AMPUSER,please-enter-your-extension-then-press-pound,,,4) +; get user's password and authenticate +; +exten => s,n,GotoIf($["${AMPUSER}" = ""]?s-MAXATTEMPTS,1) +exten => s,n(gotpass),GotoIf($["${DB_EXISTS(AMPUSER/${AMPUSER}/password)}" = "0"]?s-NOUSER,1) +exten => s,n,Set(AMPUSERPASS=${DB_RESULT}) +exten => s,n,GotoIf($[${LEN(${AMPUSERPASS})} = 0]?s-NOPASSWORD,1) +; do not continue if the user has already logged onto this device +; +exten => s,n,Set(DEVICEUSER=${DB(DEVICE/${CALLERID(number)}/user)}) +exten => s,n,GotoIf($["${DEVICEUSER}" = "${AMPUSER}"]?s-ALREADYLOGGEDON,1) +exten => s,n,Authenticate(${AMPUSERPASS}) +exten => s,n,DeadAGI(user_login_out.agi,login,${CALLERID(number)},${AMPUSER}) +exten => s,n,Playback(vm-goodbye) + +exten => s-FIXED,1,NoOp(Device is FIXED and cannot be logged into) +exten => s-FIXED,n,Playback(ha/phone) +exten => s-FIXED,n,SayDigits(${CALLERID(number)}) +exten => s-FIXED,n,Playback(is-curntly-unavail&vm-goodbye) +exten => s-FIXED,n,Hangup ;TODO should play msg indicated device cannot be logged into + +exten => s-ALREADYLOGGEDON,1,NoOp(This device has already been logged into by this user) +exten => s-ALREADYLOGGEDON,n,Playback(vm-goodbye) +exten => s-ALREADYLOGGEDON,n,Hangup ;TODO should play msg indicated device is already logged into + +exten => s-NOPASSWORD,1,NoOp(This extension does not exist or no password is set) +exten => s-NOPASSWORD,n,Playback(pbx-invalid) +exten => s-NOPASSWORD,n,Goto(s,playagain) + +exten => s-MAXATTEMPTS,1,NoOp(Too many login attempts) +exten => s-MAXATTEMPTS,n,Playback(vm-goodbye) +exten => s-MAXATTEMPTS,n,Hangup + +exten => s-NOUSER,1,NoOp(Invalid extension ${AMPUSER} entered) +exten => s-NOUSER,n,Playback(pbx-invalid) +exten => s-NOUSER,n,Goto(s,playagain) + +[macro-user-logoff] +; check device type +; +exten => s,1,Set(DEVICETYPE=${DB(DEVICE/${CALLERID(number)}/type)}) +exten => s,n,GotoIf($["${DEVICETYPE}" = "fixed"]?s-FIXED,1) +exten => s,n,DeadAGI(user_login_out.agi,logout,${CALLERID(number)}) +exten => s,n(done),Playback(vm-goodbye) + +exten => s-FIXED,1,NoOp(Device is FIXED and cannot be logged out of) +exten => s-FIXED,n,Playback(an-error-has-occured&vm-goodbye) +exten => s-FIXED,n,Hangup ;TODO should play msg indicated device cannot be logged into + + + +; Privacy Manager Macro makes sure that any calls that don't pass the privacy manager are presented +; with congestion since there have been observed cases of the call continuing if not stopped with a +; congestion, and this provides a slightly more friendly 'sorry' message in case the user is +; legitamately trying to be cooperative. +; +; Note: the following options are configurable in privacy.conf: +; +; maxretries = 3 ; default value, number of retries before failing +; minlength = 10 ; default value, number of digits to be accepted as valid CID +; +[macro-privacy-mgr] +exten => s,1,Set(KEEPCID=${CALLERID(num)}) +exten => s,n,GotoIf($["foo${CALLERID(num):0:1}"="foo+"]?CIDTEST2:CIDTEST1) +exten => s,n(CIDTEST1),Set(TESTCID=${MATH(1+${CALLERID(num)})}) +exten => s,n,Goto(TESTRESULT) +exten => s,n(CIDTEST2),Set(TESTCID=${MATH(1+${CALLERID(num):1})}) +exten => s,n(TESTRESULT),GotoIf($["foo${TESTCID}"="foo"]?CLEARCID:PRIVMGR) +exten => s,n(CLEARCID),Set(CALLERID(num)=) +exten => s,n(PRIVMGR),PrivacyManager() +exten => s,n,GotoIf($["${PRIVACYMGRSTATUS}"="FAILED"]?fail) +exten => s,n,SetCallerPres(allowed_passed_screen); stop gap until app_privacy.c clears unavailble bit +exten => s,PRIVMGR+101(fail),Noop(STATUS: ${PRIVACYMGRSTATUS} CID: ${CALLERID(num)} ${CALLERID(name)} CALLPRES: ${CALLLINGPRES}) +exten => s,n,Playback(sorry-youre-having-problems) +exten => s,n,Playback(goodbye) +exten => s,n,Playtones(congestion) +exten => s,n,Congestion(5) + + + +; Text-To-Speech related macros +; These all follow common actions. First try to playback a file "tts/custom-md5" +; where "md5" is the md5() of whatever is going to be played. If that doesn't exist, +; try to playback using macro-tts-sayXXXXX (where XXXXX is text/digits/etc, same as +; the macro below). If that macro exits with MACRO_OFFSET=100, then it's done, +; therwise, fallback to the default asterisk method. +; +; say text is purely for text-to-speech, there is no fallback +[macro-saytext] +exten => s,1,Noop(Trying custom SayText playback for "${ARG1}") +exten => s,n,Playback(tts/custom-${MD5(${ARG1})}) +exten => s,n,GotoIf($["${PLAYBACKSTATUS}"="SUCCESS"]?done) +; call tts-saytext. This should set MACRO_OFFSET=101 if it was successful +exten => s,n(tts),Macro(tts-saytext,${ARG1},${ARG2},${ARG3}) +exten => s,n,Noop(No text-to-speech handler for SayText, cannot say "${ARG1}") +exten => s,n,Goto(done) +exten => s,tts+101,Noop(tts handled saytext) + +; say name is for saying names typically, but fallsback to using SayAlpha +; (saying the word letter-by-letter) +[macro-sayname] +exten => s,1,Noop(Trying custom SayName playback for "${ARG1}") +exten => s,n,Playback(tts/custom-${MD5(${ARG1})}) +exten => s,n,GotoIf($["${PLAYBACKSTATUS}"="SUCCESS"]?done) +; call tts-sayalpha. This should set MACRO_OFFSET=101 if it was successful +exten => s,n(tts),Macro(tts-sayalpha,${ARG1},${ARG2},${ARG3}) +exten => s,n,SayAlpha(${ARG1}) +exten => s,n,Goto(done) +exten => s,tts+101,Noop(tts handled sayname) + +; Say number is for saying numbers (eg "one thousand forty six") +[macro-saynumber] +exten => s,1,Noop(Trying custom SayNumber playback for "${ARG1}") +exten => s,n,Playback(tts/custom-${MD5(${ARG1})}) +exten => s,n,GotoIf($["${PLAYBACKSTATUS}"="SUCCESS"]?done) +; call tts-saynumber. This should set MACRO_OFFSET=101 if it was successful +exten => s,n(tts),Macro(tts-saynumber,${ARG1},${ARG2},${ARG3}) +exten => s,n,SayNumber(${ARG1}) +exten => s,n,Goto(done) +exten => s,tts+101,Noop(tts handled saynumber) + +; Say digits is for saying digits one-by-one (eg, "one zero four six") +[macro-saydigits] +exten => s,1,Noop(Trying custom SayDigits playback for "${ARG1}") +exten => s,n,Playback(tts/custom-${MD5(${ARG1})}) +exten => s,n,GotoIf($["${PLAYBACKSTATUS}"="SUCCESS"]?done) +; call tts-saydigits. This should set MACRO_OFFSET=101 if it was successful +exten => s,n(tts),Macro(tts-saydigits,${ARG1},${ARG2},${ARG3}) +exten => s,n,SayDigits(${ARG1}) +exten => s,n,Goto(done) + + +; +; ############################################################################ +; Inbound Contexts [from] +; ############################################################################ + +[from-sip-external] +;give external sip users congestion and hangup +; Yes. This is _really_ meant to be _. - I know asterisk whinges about it, but +; I do know what I'm doing. This is correct. +exten => _.,1,NoOp(Received incoming SIP connection from unknown peer to ${EXTEN}) +exten => _.,n,Set(DID=${IF($["${EXTEN:1:2}"=""]?s:${EXTEN})}) +exten => _.,n,Goto(s,1) +exten => s,1,GotoIf($["${ALLOW_SIP_ANON}"="yes"]?from-trunk,${DID},1) +exten => s,n,Set(TIMEOUT(absolute)=15) +exten => s,n,Answer +exten => s,n,Wait(2) +exten => s,n,Playback(ss-noservice) +exten => s,n,Playtones(congestion) +exten => s,n,Congestion(5) +exten => h,1,NoOp(Hangup) +exten => i,1,NoOp(Invalid) +exten => t,1,NoOp(Timeout) + +[from-internal-xfer] +; applications are now mostly all found in from-internal-additional in _custom.conf +include => parkedcalls +include => from-internal-custom +;allow phones to dial other extensions +include => ext-fax +;allow phones to access generated contexts +; +; MODIFIED (PL) +; +; Currently the include for findmefollow is being auto-generated before ext-local which is the desired behavior. +; However, I haven't been able to do anything that I know of to force this. We need to determine if it should +; be hardcoded into here to make sure it doesn't change with some configuration. For now I will leave it out +; until we can discuss this. +; +include => ext-local-confirm +include => findmefollow-ringallv2 +include => from-internal-additional +; This causes grief with '#' transfers, commenting out for the moment. +; include => bad-number +exten => s,1,Macro(hangupcall) +exten => h,1,Macro(hangupcall) + +[from-internal] +include => from-internal-xfer +include => bad-number + +;------------------------------------------------------------------------ +; [macro-setmusic] +;------------------------------------------------------------------------ +; CONTEXT: macro-setmusic +; PURPOSE: to turn off moh on routes where it is not desired +; +;------------------------------------------------------------------------ +[macro-setmusic] +exten => s,1,NoOp(Setting Outbound Route MoH To: ${ARG1}) +exten => s,2,SetMusicOnHold(${ARG1}) +;------------------------------------------------------------------------ + +; ########################################## +; ## Ring Groups with Confirmation macros ## +; ########################################## +; Used by followme and ringgroups + +;------------------------------------------------------------------------ +; [macro-dial-confirm] +;------------------------------------------------------------------------ +; This has now been incorporated into dialparties. It still only works with ringall +; and ringall-prim strategies. Have not investigated why it doesn't work with +; hunt and memory hunt. +; +;------------------------------------------------------------------------ +[macro-dial-confirm] +; This was written to make it easy to use macro-dial-confirm instead of macro-dial in generated dialplans. +; This takes the same paramaters, with an additional paramater of the ring group Number +; ARG1 is the timeout +; ARG2 is the DIAL_OPTIONS +; ARG3 is a list of xtns to call - 203-222-240-123123123#-211 +; ARG4 is the ring group number + +; This sets a unique value to indicate that the channel is ringing. This is used for warning slow +; users that the call has already been picked up. +; +exten => s,1,Set(DB(RG/${ARG4}/${CHANNEL})=RINGING) + +; We need to keep that channel variable, because it'll change when we do this dial, so set it to +; fallthrough to every sibling. +; +exten => s,n,Set(__UNIQCHAN=${CHANNEL}) + +; The calling ringgroup should have set RingGroupMethod appropriately. We need to set two +; additional parameters: +; +; USE_CONFIRMATION, RINGGROUP_INDEX +; +; Thse are passed to inform dialparties to place external calls through the [grps] context +; +exten => s,n,Set(USE_CONFIRMATION=TRUE) +exten => s,n,Set(RINGGROUP_INDEX=${ARG4}) +exten => s,n,Set(ARG4=) ; otherwise it gets passed to dialparties.agi which processes it (prob bug) + +exten => s,n,Macro(dial,${ARG1},${ARG2},${ARG3}) + +; delete the variable, if we are here, we are done trying to dial and it may have been left around +; +exten => s,n,DBDel(RG/${RINGGROUP_INDEX}/${CHANNEL}) +exten => s,n,Set(USE_CONFIRMATION=) +exten => s,n,Set(RINGGROUP_INDEX=) +;------------------------------------------------------------------------ + + +;------------------------------------------------------------------------ +; [ext-local-confirm] +;------------------------------------------------------------------------ +; If call confirm is being used in a ringgroup, then calls that do not require confirmation are sent +; to this extension instead of straight to the device. +; +; The sole purpose of sending them here is to make sure we run Macro(auto-confirm) if this +; extension answers the line. This takes care of clearing the database key that is used to inform +; other potential late comers that the extension has been answered by someone else. +; +; ALERT_INFO is deprecated in Asterisk 1.4 but still used throughout the FreePBX dialplan and +; usually set by dialparties.agi. This allows ineritance. Since no dialparties.agi here, set the +; header if it is set. +; +;------------------------------------------------------------------------ +[ext-local-confirm] +exten => _LC-.,1,Noop(IN ext-local-confirm with - RT: ${RT}, RG_IDX: ${RG_IDX}) +exten => _LC-.,n,GotoIf($["x${ALERT_INFO}"="x"]?godial) +exten => _LC-.,n,SIPAddHeader(Alert-Info: ${ALERT_INFO}) +exten => _LC-.,n(godial),dial(${DB(DEVICE/${EXTEN:3}/dial)},${RT},M(auto-confirm^${RG_IDX})${DIAL_OPTIONS}) + +;------------------------------------------------------------------------ +; [findmefollow-ringallv2] +;------------------------------------------------------------------------ +; This context, to be included in from-internal, implements the PreRing part of findmefollow +; as well as the GroupRing part. It also communicates between the two so that if DND is set +; on the primary extension, and mastermode is enabled, then the other extensions will not ring +; +;------------------------------------------------------------------------ +[findmefollow-ringallv2] +exten => _FMPR-.,1,Noop(In FMPR ${FMGRP} with ${EXTEN:5}) +exten => _FMPR-.,n,Set(RingGroupMethod=) +exten => _FMPR-.,n,Set(USE_CONFIRMATION=) +exten => _FMPR-.,n,Set(RINGGROUP_INDEX=) +exten => _FMPR-.,n,Macro(simple-dial,${EXTEN:5},${FMREALPRERING}) +exten => _FMPR-.,n,GotoIf($["${DIALSTATUS}" != "BUSY"]?nodnd) +exten => _FMPR-.,n,Set(DB(FM/DND/${FMGRP}/${FMUNIQUE})=DND) +exten => _FMPR-.,n(nodnd),Noop(Ending FMPR ${FMGRP} with ${EXTEN:5} and dialstatus ${DIALSTATUS}) +exten => _FMPR-.,n,Hangup() + +exten => _FMGL-.,1,Noop(In FMGL ${FMGRP} with ${EXTEN:5}) +exten => _FMGL-.,n,GotoIf($["${DB(FM/DND/${FMGRP}/${FMUNIQUE})}" = "DND"]?dodnd) +exten => _FMGL-.,n,Wait(1) +exten => _FMGL-.,n,GotoIf($["${DB(FM/DND/${FMGRP}/${FMUNIQUE})}" = "DND"]?dodnd) +exten => _FMGL-.,n,Wait(1) +exten => _FMGL-.,n,GotoIf($["${DB(FM/DND/${FMGRP}/${FMUNIQUE})}" = "DND"]?dodnd) +exten => _FMGL-.,n,Wait(${FMPRERING}) +exten => _FMGL-.,n,GotoIf($["${DB(FM/DND/${FMGRP}/${FMUNIQUE})}" = "DND"]?dodnd) +exten => _FMGL-.,n,DBDel(FM/DND/${FMGRP}/${FMUNIQUE}) +exten => _FMGL-.,n(dodial),Macro(dial,${FMGRPTIME},${DIAL_OPTIONS},${EXTEN:5}) +exten => _FMGL-.,n,Noop(Ending FMGL ${FMGRP} with ${EXTEN:5} and dialstatus ${DIALSTATUS}) +exten => _FMGL-.,n,Hangup() +exten => _FMGL-.,n+10(dodnd),DBDel(FM/DND/${FMGRP}/${FMUNIQUE}) +exten => _FMGL-.,n,GotoIf($["${FMPRIME}" = "FALSE"]?dodial) +exten => _FMGL-.,n,Noop(Got DND in FMGL ${FMGRP} with ${EXTEN:5} in ${RingGroupMethod} mode, aborting) +exten => _FMGL-.,n,Hangup() + +;------------------------------------------------------------------------ +; [block-cf] +;------------------------------------------------------------------------ +; This context is set as a target with FORWARD_CONTEXT when Call Forwarding is set to be +; ignored in a ringgoup or other features that may take advantage of this. Server side +; CF is done in dialparties.agi but if a client device forwards a call, it will be caught +; and blocked here. +;------------------------------------------------------------------------ +[block-cf] +exten => _X.,1,Noop(Blocking callforward to ${EXTEN} because CF is blocked) +exten => _X.,n,Hangup() + +;------------------------------------------------------------------------ + +; ############################################################################ +; Extension Contexts [ext] +; ############################################################################ + +[ext-fax] +exten => s,1,Answer +exten => s,2,Goto(in_fax,1) +exten => in_fax,1,StopPlayTones +exten => in_fax,2,GotoIf($["${FAX_RX}" = "system"]?3:analog_fax,1) +exten => in_fax,3,Macro(faxreceive) +exten => in_fax,4,Hangup +exten => analog_fax,1,GotoIf($["${FAX_RX}" = "disabled"]?4:2) ;if fax is disabled, just hang up +exten => analog_fax,2,Set(DIAL=${DB(DEVICE/${FAX_RX}/dial)}); +exten => analog_fax,3,Dial(${DIAL},20,d) +exten => analog_fax,4,Hangup +;exten => out_fax,1,wait(7) +exten => out_fax,1,txfax(${TXFAX_NAME},caller) +exten => out_fax,2,Hangup +exten => h,1,system(/var/lib/asterisk/bin/fax-process.pl --to ${EMAILADDR} --from ${FAX_RX_FROM} --dest "${FROM_DID}" --subject "Fax from ${URIENCODE(${CALLERID(number)})} ${URIENCODE(${CALLERID(name)})}" --attachment fax_${URIENCODE(${CALLERID(number)})}.pdf --type application/pdf --file ${FAXFILE}); +exten => h,2,Hangup() + +;this is where parked calls go if they time-out. Should probably re-ring +[default] +include => ext-local +exten => s,1,Playback(vm-goodbye) +exten => s,2,Macro(hangupcall) + Index: /modules/branches/2.6/core/etc/iax.conf =================================================================== --- /modules/branches/2.6/core/etc/iax.conf (revision 6674) +++ /modules/branches/2.6/core/etc/iax.conf (revision 6674) @@ -0,0 +1,30 @@ +;--------------------------------------------------------------------------------; +; Do NOT edit this file as it is auto-generated by FreePBX. All modifications to ; +; this file must be done via the web gui. There are alternative files to make ; +; custom modifications, details at: http://freepbx.org/configuration_files ; +;--------------------------------------------------------------------------------; +; + +[general] + +; These will all be included in the [general] context +#include iax_general_additional.conf +#include iax_general_custom.conf +#include iax_registrations_custom.conf +#include iax_registrations.conf + +; These should all be expected to come after the [general] context +; +;iax_custom.conf is the proper place to start creating new contexts that you +;might have a need for. Dundi IAX trunks is one example of when this file is needed. +; +#include iax_custom.conf +#include iax_additional.conf +; +;iax_custom_post.conf will allow you to modify FreePBX generated IAX setups so +;that you can add additional parameters to a auto-generated setup. +;if you have a auto-generated context of [foobar] and need to add a parameter +;to it then create this line [foobar](+) and place your additions on the next line +; +#include iax_custom_post.conf + Index: /modules/branches/2.6/core/page.general.php =================================================================== --- /modules/branches/2.6/core/page.general.php (revision 6973) +++ /modules/branches/2.6/core/page.general.php (revision 6973) @@ -0,0 +1,501 @@ +prepare('UPDATE globals SET value = ? WHERE variable = ?'); + //$compiled = $db->prepare('REPLACE INTO globals (value,variable) VALUES (?, ?)'); + $result = $db->executeMultiple($compiled,$globalfields); + if(DB::IsError($result)) { + echo $action.'
'; + die_freepbx($result->getMessage()); + } + + /* update online updates and email as appropriate + */ + $online_updates = isset($_REQUEST['online_updates'])? $_REQUEST['online_updates'] : 'yes'; + $update_email = isset($_REQUEST['update_email']) ? $_REQUEST['update_email'] : ''; + + if ($online_updates == 'yes') { + $cm->enable_updates(); + } else { + $cm->disable_updates(); + } + + // TODO: maybe check the email address a bit better server/client side + // + $cm->save_email($update_email); + + //indicate 'need reload' link in header.php + needreload(); +} + +$online_updates = $cm->updates_enabled() ? 'yes' : 'no'; +$update_email = $cm->get_email(); + +//get all rows relating to selected account +$sql = "SELECT * FROM globals"; +$globals = $db->getAll($sql); +if(DB::IsError($globals)) { +die_freepbx($globals->getMessage()); +} + +//create a set of variables that match the items in global[0] +foreach ($globals as $global) { + ${trim($global[0])} = $global[1]; +} + +?> + +
+ + + +
+ + + +
+ +
+
+
+
+
+
+
+ +
+ +
+
+
+
+
+
+
+ +
+ +
+ + + + + +
+ + + + +
+ + + + + +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+ + + + + + +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +

+
+
+ +
+ + + tabindex=""> +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +   
+ + +     
+ + +     
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ +
+ + + + +
+ + + +
+ + + tabindex=""> +
+ + + + + +
+ +
+ + + + +
+ Selecting 'disabled' will result in incoming calls being answered more quickly.")?> + + + +
+ + + +
+ + + +
+
+ + + +
+ : + + +
+ : + + +
+
+ + +
+ +

+

+
+
: +
+ +
+ +
+ + + + + + + + + +
+ + This will transmit your FreePBX and Asterisk version numbers along with a unique but random identifier. This is used to provide proper update information and to track version usage to focus development and maintenance efforts. No private information is transmitted."); ?> + + +
+ + + + +
+
+ " tabindex=""> +
+ +
+ Index: /modules/branches/2.6/announcement/i18n/sv_SE/LC_MESSAGES/announcement.po =================================================================== --- /modules/branches/2.6/announcement/i18n/sv_SE/LC_MESSAGES/announcement.po (revision 6938) +++ /modules/branches/2.6/announcement/i18n/sv_SE/LC_MESSAGES/announcement.po (revision 6938) @@ -0,0 +1,151 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: FreePBXannouncement\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2008-10-05 10:39+0200\n" +"PO-Revision-Date: 2008-10-10 20:20+0100\n" +"Last-Translator: Mikael Carlsson \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Poedit-Language: Swedish\n" +"X-Poedit-Country: SWEDEN\n" + +#: functions.inc.php:28 +#: functions.inc.php:48 +#, php-format +msgid "Announcement: %s" +msgstr "Meddelande: %s" + +#: install.php:98 +msgid "Checking if recordings need migration.." +msgstr "Kontrollerar om inspelningar behöver migreras.." + +#: install.php:104 +msgid "migrating" +msgstr "migrerar" + +#: install.php:105 +msgid "adding recording_id field.." +msgstr "lÀgger till fÀltet recording_id" + +#: install.php:109 +#: install.php:121 +#: install.php:137 +msgid "fatal error" +msgstr "allvarligt fel" + +#: install.php:112 +#: install.php:151 +msgid "ok" +msgstr "ok" + +#: install.php:117 +msgid "migrate to recording ids.." +msgstr "migrerar till recording ids.." + +#: install.php:141 +#, php-format +msgid "migrated %s entries" +msgstr "migrerade %s poster" + +#: install.php:145 +msgid "dropping recording field.." +msgstr "kastar fÀltet recording.." + +#: install.php:149 +msgid "no recording field???" +msgstr "inget fÀlt som heter recording???" + +#: install.php:155 +msgid "already migrated" +msgstr "redan migrerad" + +#: page.announcement.php:61 +#: page.announcement.php:93 +msgid "Add Announcement" +msgstr "LÀgg till meddelande" + +#: page.announcement.php:93 +msgid "Edit Announcement" +msgstr "Redigera meddelande" + +#: page.announcement.php:95 +msgid "Description" +msgstr "Beskrivning" + +#: page.announcement.php:95 +msgid "The name of this announcement" +msgstr "Kortfattat namn för detta meddelande" + +#: page.announcement.php:101 +msgid "Recording" +msgstr "Inspelning" + +#: page.announcement.php:101 +msgid "Message to be played.
To add additional recordings use the \"System Recordings\" MENU to the left" +msgstr "Meddelande att spela upp.
För att lÀgga till fler inspelade meddelande vÀljer du \"Systeminspelningar\" i menyn till vÀnster." + +#: page.announcement.php:118 +msgid "Repeat" +msgstr "Repetera" + +#: page.announcement.php:118 +msgid "Key to press that will allow for the message to be replayed. If you choose this option there will be a short delay inserted after the message. If a longer delay is needed it should be incoporated into the recording." +msgstr "Tangent att trycka för att repetera meddelandet. Om du vÀljer detta kommer en kort paus att lÀggas till efter meddelandet. Om en lÀngre paus behövs, spela in det i meddelandet." + +#: page.announcement.php:128 +msgid "Disable" +msgstr "Avaktivera" + +#: page.announcement.php:137 +msgid "Allow Skip" +msgstr "Tillåt hoppa över" + +#: page.announcement.php:137 +msgid "If the caller is allowed to press a key to skip the message." +msgstr "Om uppringaren ska tillåtas att trycka en tangent för att hoppa över meddelandet." + +#: page.announcement.php:141 +msgid "Return to IVR" +msgstr "à +tergå till den digitala receptionisten" + +#: page.announcement.php:141 +msgid "If this announcement came from an IVR and this box is checked, the destination below will be ignored and instead it will return to the calling IVR. Otherwise, the destination below will be taken. Don't check if not using in this mode.
The IVR return location will be to the last IVR in the call chain that was called so be careful to only check when needed. For example, if an IVR directs a call to another destination which eventually calls this annoucement and this box is checked, it will return to that IVR which may not be the expected behavior." +msgstr "Om detta meddelande kom från den digitala receptionisten och detta val aktiveras, kommer destinationen nedan att ignoreras och återgång kommer att ske till den anropande digitala receptionisten. Annars kommer destinationen nedan att anropas. Aktivera inte detta om du inte anvÀnder detta lÀge.
Returpunkten kommer att bli till den sist valda punkten i den Digitala receptionisten så var noga med att bara aktivera detta val nÀr det behövs. T.ex. om en Digital receptionist skickar samtalet till en destination som anropar detta meddelande och detta val Àr aktiverat kommer samtalet att återgå till den Digitala receptionisten och du har skapat en liten loop." + +#: page.announcement.php:145 +msgid "Don't Answer Channel" +msgstr "Svara inte denna kanal" + +#: page.announcement.php:145 +msgid "Check this to keep the channel from explicitly being answered. When checked, the message will be played and if the channel is not already answered it will be delivered as early media if the channel supports that. When not checked, the channel is answered followed by a 1 second delay. When using an annoucement from an IVR or other sources that have already answered the channel, that 1 second delay may not be desired." +msgstr "Aktivera denna för att hindra att kanalen uttryckligen svaras. NÀr detta Àr aktiverat kommer meddelandet att spelas upp och om kanalen inte redan har svarats kommer det att levereras som tidigt media om kanalen stöder det. NÀr valet inte Àr aktiverat kommer kanalen att svaras med en efterföljande paus på 1 sekund. NÀr du anvÀnder ett meddelande från en Digital receptionist (IVR) eller annan kÀlla som redan har svarat kanalen Àr kanske denna paus inte önskad." + +#: page.announcement.php:149 +msgid "Destination after playback" +msgstr "Destination efter uppspelning" + +#: page.announcement.php:157 +msgid "Submit Changes" +msgstr "Spara Àndringar" + +#: page.announcement.php:158 +msgid "Delete" +msgstr "Ta bort" + +#: page.announcement.php:183 +msgid "Invalid description specified" +msgstr "Ogiltig beskrivning" + +#: module.xml +msgid "Announcements" +msgstr "Meddelanden" + Index: /modules/branches/2.6/announcement/i18n/hu_HU/LC_MESSAGES/announcement.po =================================================================== --- /modules/branches/2.6/announcement/i18n/hu_HU/LC_MESSAGES/announcement.po (revision 6986) +++ /modules/branches/2.6/announcement/i18n/hu_HU/LC_MESSAGES/announcement.po (revision 6986) @@ -0,0 +1,180 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: 2.4\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2008-10-05 10:47+0200\n" +"PO-Revision-Date: 2008-02-06 20:49+0100\n" +"Last-Translator: Lónyai Gergely \n" +"Language-Team: Magyar \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Poedit-Language: Hungarian\n" +"X-Poedit-Country: HUNGARY\n" +"X-Poedit-SourceCharset: utf-8\n" + +#: functions.inc.php:28 functions.inc.php:48 functions.inc.php:213 +#, php-format +msgid "Announcement: %s" +msgstr "" + +#: install.php:98 +msgid "Checking if recordings need migration.." +msgstr "" + +#: install.php:104 +msgid "migrating" +msgstr "" + +#: install.php:105 +msgid "adding recording_id field.." +msgstr "" + +#: install.php:109 install.php:121 install.php:137 +msgid "fatal error" +msgstr "" + +#: install.php:112 install.php:151 +msgid "ok" +msgstr "" + +#: install.php:117 +msgid "migrate to recording ids.." +msgstr "" + +#: install.php:141 +#, php-format +msgid "migrated %s entries" +msgstr "" + +#: install.php:145 +msgid "dropping recording field.." +msgstr "" + +#: install.php:149 +msgid "no recording field???" +msgstr "" + +#: install.php:155 +msgid "already migrated" +msgstr "" + +#: page.announcement.php:61 page.announcement.php:93 +msgid "Add Announcement" +msgstr "Esemény hozzáadása" + +#: page.announcement.php:93 +msgid "Edit Announcement" +msgstr "Esemény szerkesztése" + +#: page.announcement.php:95 +msgid "Description" +msgstr "Meghatározás" + +#: page.announcement.php:95 +msgid "The name of this announcement" +msgstr "Esemény neve" + +#: page.announcement.php:101 +msgid "Recording" +msgstr "Rögzítés" + +#: page.announcement.php:101 +msgid "" +"Message to be played.
To add additional recordings use the \"System " +"Recordings\" MENU to the left" +msgstr "" +"Üzenet lejátszása.
Előzőleg a a rögzítéshez a \"Központoi rögzítés\" " +"menÃŒpontot használd a BAL menÃŒben." + +#: page.announcement.php:118 +msgid "Repeat" +msgstr "Ismétlés" + +#: page.announcement.php:118 +msgid "" +"Key to press that will allow for the message to be replayed. If you choose " +"this option there will be a short delay inserted after the message. If a " +"longer delay is needed it should be incoporated into the recording." +msgstr "" +"A gomb megnyomásával az ÃŒzenetet ismét lejátsza. Ha az opció engedélyezve " +"van, akkor egy kisebb szÃŒnet lesz az ÃŒzenet után illesztve. Ha hosszabb " +"szÃŒnetre lenne szÃŒkséged, akkor azt az ÃŒzenet rögzítésbe tervezd bele." + +#: page.announcement.php:128 +msgid "Disable" +msgstr "Tiltás" + +#: page.announcement.php:137 +msgid "Allow Skip" +msgstr "Elfogad kihagyást" + +#: page.announcement.php:137 +msgid "If the caller is allowed to press a key to skip the message." +msgstr "" +"Ha elfogadott, akkor a hívó egy gomb megnyomásával átugorhatja az ÃŒzenetet." + +#: page.announcement.php:141 +msgid "Return to IVR" +msgstr "Vissza az IVR-be." + +#: page.announcement.php:141 +msgid "" +"If this announcement came from an IVR and this box is checked, the " +"destination below will be ignored and instead it will return to the calling " +"IVR. Otherwise, the destination below will be taken. Don't check if not " +"using in this mode.
The IVR return location will be to the last IVR in " +"the call chain that was called so be careful to only check when needed. For " +"example, if an IVR directs a call to another destination which eventually " +"calls this annoucement and this box is checked, it will return to that IVR " +"which may not be the expected behavior." +msgstr "" +"Ha az esemény egy IVR-ből lett megcímezve, és ez a pipa meg van jelölve, " +"akkor a célpont figyelmen kívÃŒl lessz hagyva, és az ÃŒzenet lejátszása " +"után ismét az IVR lesz meghívva. Minden egyéb esetben a célpont lesz az " +"érvényes következő feladat. Ne használd, ha nem használnád.
Az IVR-" +"be visszatérés helye az utolsó kért IVR pont. Ha ide akarsz visszatérni, " +"csak akkor jelöld be. Ha egy másik IVR helyre szeretnél továbbmenni, " +"akkor a célpontok között jelöld meg azt az IVR pontot." + +#: page.announcement.php:145 +msgid "Don't Answer Channel" +msgstr "Nem megválaszolt csatorna." + +#: page.announcement.php:145 +msgid "" +"Check this to keep the channel from explicitly being answered. When checked, " +"the message will be played and if the channel is not already answered it " +"will be delivered as early media if the channel supports that. When not " +"checked, the channel is answered followed by a 1 second delay. When using an " +"annoucement from an IVR or other sources that have already answered the " +"channel, that 1 second delay may not be desired." +msgstr "" +"Használd ezt a pipát, ha a hívás ezidáig megválaszolatlan. Ha megjelölöd, " +"akkor az ÃŒzenet lejátszása után, ha a csatorna támogatja, és még nem lett " +"megválaszolva a hívás, akkor a hívásidő innentől lesz számolva. Ha nem " +"jelölöd meg, akkor a hívás egy 1 másodperces várakozással meg lesz " +"válaszolva. Amikor az eseményt egy IVR-ben, vagy más helyzetben használod, " +"akkor ez az 1 másodperces várakozás elmaradhat." + +#: page.announcement.php:149 +msgid "Destination after playback" +msgstr "Visszajátszás utáni cél" + +#: page.announcement.php:157 +msgid "Submit Changes" +msgstr "" + +#: page.announcement.php:158 +msgid "Delete" +msgstr "Törlés" + +#: page.announcement.php:183 +msgid "Invalid description specified" +msgstr "" + Index: /modules/branches/2.6/announcement/i18n/it_IT/LC_MESSAGES/announcement.po =================================================================== --- /modules/branches/2.6/announcement/i18n/it_IT/LC_MESSAGES/announcement.po (revision 6851) +++ /modules/branches/2.6/announcement/i18n/it_IT/LC_MESSAGES/announcement.po (revision 6851) @@ -0,0 +1,180 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: 1.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2008-09-15 21:54+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Francesco Romano\n" +"Language-Team: Italian \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=ISO-8859-1\n" +"Content-Transfer-Encoding: 8bit\n" + +#: install.php:98 +msgid "Checking if recordings need migration.." +msgstr "" + +#: install.php:104 +msgid "migrating" +msgstr "" + +#: install.php:105 +msgid "adding recording_id field.." +msgstr "" + +#: install.php:109 install.php:121 install.php:137 +msgid "fatal error" +msgstr "" + +#: install.php:112 install.php:151 +msgid "ok" +msgstr "" + +#: install.php:117 +msgid "migrate to recording ids.." +msgstr "" + +#: install.php:141 +#, php-format +msgid "migrated %s entries" +msgstr "" + +#: install.php:145 +msgid "dropping recording field.." +msgstr "" + +#: install.php:149 +msgid "no recording field???" +msgstr "" + +#: install.php:155 +msgid "already migrated" +msgstr "" + +#: page.announcement.php:61 page.announcement.php:93 +msgid "Add Announcement" +msgstr "Aggiungi Annuncio" + +#: page.announcement.php:93 +msgid "Edit Announcement" +msgstr "Modifica Annuncio" + +#: page.announcement.php:95 +msgid "Description" +msgstr "Descrizione" + +#: page.announcement.php:95 +msgid "The name of this announcement" +msgstr "Il nome dell'annuncio" + +#: page.announcement.php:101 +msgid "Recording" +msgstr "Registrazione" + +#: page.announcement.php:101 +msgid "" +"Message to be played.
To add additional recordings use the \"System " +"Recordings\" MENU to the left" +msgstr "" +"Messaggio da riprodurre.
Per aggiungere ulteriori registrazioni, " +"utilizzare \"Registrazioni di Sistema\" nel menu di sinistra." + +#: page.announcement.php:118 +msgid "Repeat" +msgstr "Ripeti" + +#: page.announcement.php:118 +msgid "" +"Key to press that will allow for the message to be replayed. If you choose " +"this option there will be a short delay inserted after the message. If a " +"longer delay is needed it should be incoporated into the recording." +msgstr "" +"Il tasto da premere per ripetere l'annuncio. Se si sceglie questa opzione ci " +"sarà un breve ritardo dopo il messaggio. Per allungare questo tempo, " +"includerlo nella registrazione." + +#: page.announcement.php:128 +msgid "Disable" +msgstr "" + +#: page.announcement.php:137 +msgid "Allow Skip" +msgstr "Permetti Salta" + +#: page.announcement.php:137 +msgid "If the caller is allowed to press a key to skip the message." +msgstr "" +"Se si vuole permettere al chiamante di saltare il messaggio premendo un " +"tasto." + +#: page.announcement.php:141 +msgid "Return to IVR" +msgstr "Ritorna all'IVR" + +#: page.announcement.php:141 +msgid "" +"If this announcement came from an IVR and this box is checked, the " +"destination below will be ignored and instead it will return to the calling " +"IVR. Otherwise, the destination below will be taken. Don't check if not " +"using in this mode.
The IVR return location will be to the last IVR in " +"the call chain that was called so be careful to only check when needed. For " +"example, if an IVR directs a call to another destination which eventually " +"calls this annoucement and this box is checked, it will return to that IVR " +"which may not be the expected behavior." +msgstr "" +"Se questo annuncio proviene da un IVR e questa opzione è selezionata, la " +"destinazione di sotto verrà ignorata e la chiamata ritornerà all'IVR. " +"Altrimenti, la destinazione di sotto verrà presa in considerazione. Non " +"selezionare se non si utilizzà questa modalità.
L'IVR di ritorno sarà " +"l'ultimo IVR richiamato nel percorso della chiamata quindi stare attenti a " +"impostare solo quando serve. Per esempio, se un IVR dirotta una chiamata " +"verso un'altra destinazione che richiama a sua volta questo annuncio e " +"l'impostazione è selezionata, la chiamata ritornerà all'IVR iniziale e " +"questo magari non è il comportamento che ci si aspetta." + +#: page.announcement.php:145 +msgid "Don't Answer Channel" +msgstr "Non Rispondere al Canale" + +#: page.announcement.php:145 +msgid "" +"Check this to keep the channel from explicitly being answered. When checked, " +"the message will be played and if the channel is not already answered it " +"will be delivered as early media if the channel supports that. When not " +"checked, the channel is answered followed by a 1 second delay. When using an " +"annoucement from an IVR or other sources that have already answered the " +"channel, that 1 second delay may not be desired." +msgstr "" +"Selezionare questa opzione per non rispondere esplicitamente alla chiamata. " +"Se impostato, il messaggio verrà riprodotto e se la chiamata non è già stata " +"risposta, verrà inviato come early media (il canale lo deve però " +"supportare). Se non impostato, il canale verrà risposto seguito da 1 secondo " +"di ritardo. Quando si utilizza un annuncio proveniente da un IVR o da altre " +"sorgenti che hanno risposto al canale, questo secondo di ritardo puo' essere " +"evitato." + +#: page.announcement.php:149 +msgid "Destination after playback" +msgstr "Destinazione dopo la riproduzione" + +#: page.announcement.php:157 +msgid "Submit Changes" +msgstr "Applica" + +#: page.announcement.php:158 +msgid "Delete" +msgstr "Elimina" + +#: page.announcement.php:183 +msgid "Invalid description specified" +msgstr "Descrizione specificata non valida" + +#: module.xml +msgid "Announcements" +msgstr "" Index: /modules/branches/2.6/announcement/i18n/announcement.pot =================================================================== --- /modules/branches/2.6/announcement/i18n/announcement.pot (revision 6938) +++ /modules/branches/2.6/announcement/i18n/announcement.pot (revision 6938) @@ -0,0 +1,158 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2008-10-05 10:47+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" + +#: functions.inc.php:28 functions.inc.php:48 functions.inc.php:213 +#, php-format +msgid "Announcement: %s" +msgstr "" + +#: install.php:98 +msgid "Checking if recordings need migration.." +msgstr "" + +#: install.php:104 +msgid "migrating" +msgstr "" + +#: install.php:105 +msgid "adding recording_id field.." +msgstr "" + +#: install.php:109 install.php:121 install.php:137 +msgid "fatal error" +msgstr "" + +#: install.php:112 install.php:151 +msgid "ok" +msgstr "" + +#: install.php:117 +msgid "migrate to recording ids.." +msgstr "" + +#: install.php:141 +#, php-format +msgid "migrated %s entries" +msgstr "" + +#: install.php:145 +msgid "dropping recording field.." +msgstr "" + +#: install.php:149 +msgid "no recording field???" +msgstr "" + +#: install.php:155 +msgid "already migrated" +msgstr "" + +#: page.announcement.php:61 page.announcement.php:93 +msgid "Add Announcement" +msgstr "" + +#: page.announcement.php:93 +msgid "Edit Announcement" +msgstr "" + +#: page.announcement.php:95 +msgid "Description" +msgstr "" + +#: page.announcement.php:95 +msgid "The name of this announcement" +msgstr "" + +#: page.announcement.php:101 +msgid "Recording" +msgstr "" + +#: page.announcement.php:101 +msgid "" +"Message to be played.
To add additional recordings use the \"System " +"Recordings\" MENU to the left" +msgstr "" + +#: page.announcement.php:118 +msgid "Repeat" +msgstr "" + +#: page.announcement.php:118 +msgid "" +"Key to press that will allow for the message to be replayed. If you choose " +"this option there will be a short delay inserted after the message. If a " +"longer delay is needed it should be incoporated into the recording." +msgstr "" + +#: page.announcement.php:128 +msgid "Disable" +msgstr "" + +#: page.announcement.php:137 +msgid "Allow Skip" +msgstr "" + +#: page.announcement.php:137 +msgid "If the caller is allowed to press a key to skip the message." +msgstr "" + +#: page.announcement.php:141 +msgid "Return to IVR" +msgstr "" + +#: page.announcement.php:141 +msgid "" +"If this announcement came from an IVR and this box is checked, the " +"destination below will be ignored and instead it will return to the calling " +"IVR. Otherwise, the destination below will be taken. Don't check if not " +"using in this mode.
The IVR return location will be to the last IVR in " +"the call chain that was called so be careful to only check when needed. For " +"example, if an IVR directs a call to another destination which eventually " +"calls this annoucement and this box is checked, it will return to that IVR " +"which may not be the expected behavior." +msgstr "" + +#: page.announcement.php:145 +msgid "Don't Answer Channel" +msgstr "" + +#: page.announcement.php:145 +msgid "" +"Check this to keep the channel from explicitly being answered. When checked, " +"the message will be played and if the channel is not already answered it " +"will be delivered as early media if the channel supports that. When not " +"checked, the channel is answered followed by a 1 second delay. When using an " +"annoucement from an IVR or other sources that have already answered the " +"channel, that 1 second delay may not be desired." +msgstr "" + +#: page.announcement.php:149 +msgid "Destination after playback" +msgstr "" + +#: page.announcement.php:157 +msgid "Submit Changes" +msgstr "" + +#: page.announcement.php:158 +msgid "Delete" +msgstr "" + +#: page.announcement.php:183 +msgid "Invalid description specified" +msgstr "" Index: /modules/branches/2.6/announcement/i18n/ru_RU/LC_MESSAGES/announcement.po =================================================================== --- /modules/branches/2.6/announcement/i18n/ru_RU/LC_MESSAGES/announcement.po (revision 6727) +++ /modules/branches/2.6/announcement/i18n/ru_RU/LC_MESSAGES/announcement.po (revision 6727) @@ -0,0 +1,183 @@ +# Russian freePBX ver. translation +# Copyright (c) 2006-2008 PostMet Corporation +# This file is distributed under the same license as the freePBX package. +# Alexander Kozyrev , Sergey Nikolayev , 2006-2008. +# +# žáßÞÛì×ÞÒÐâì iconv amp.new -f UTF-8 -t ISO-8859-5 -o amp.po +# fuzzy +msgid "" +msgstr "" +"Project-Id-Version: 1.3\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2008-09-15 21:54+0200\n" +"PO-Revision-Date: 2008-01-16 16:38+0100\n" +"Last-Translator: Alexander Kozyrev \n" +"Language-Team: Russian \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=iso-8859-5\n" +"Content-Transfer-Encoding: 8bit\n" + +#: install.php:98 +msgid "Checking if recordings need migration.." +msgstr "" + +#: install.php:104 +msgid "migrating" +msgstr "" + +#: install.php:105 +msgid "adding recording_id field.." +msgstr "" + +#: install.php:109 install.php:121 install.php:137 +msgid "fatal error" +msgstr "" + +#: install.php:112 install.php:151 +msgid "ok" +msgstr "" + +#: install.php:117 +msgid "migrate to recording ids.." +msgstr "" + +#: install.php:141 +#, php-format +msgid "migrated %s entries" +msgstr "" + +#: install.php:145 +msgid "dropping recording field.." +msgstr "" + +#: install.php:149 +msgid "no recording field???" +msgstr "" + +#: install.php:155 +msgid "already migrated" +msgstr "" + +#: page.announcement.php:61 page.announcement.php:93 +msgid "Add Announcement" +msgstr "ŽÞÑÐÒØâì ßàØÒÕâáâÒØÕ" + +#: page.announcement.php:93 +msgid "Edit Announcement" +msgstr "ž×ÜÕÝØâì ßàØÒÕâáâÒØÕ" + +#: page.announcement.php:95 +msgid "Description" +msgstr "ŸßØáÐÝØÕ" + +#: page.announcement.php:95 +msgid "The name of this announcement" +msgstr "žÜï ÔÛï íâÞÓÞ ßàØÒÕâáâÒØï" + +#: page.announcement.php:101 +msgid "Recording" +msgstr "·Ðߨáì" + +#: page.announcement.php:101 +msgid "" +"Message to be played.
To add additional recordings use the \"System " +"Recordings\" MENU to the left" +msgstr "" +"ÁÞÞÑéÕÝØÕ, ÚÞâÞàÞÕ ÑãÔÕâ ÒÞáßàÞØ×ÒÕÔÕÝÞ.
ŽÛï áÞ×ÔÐÝØï áÞÞÑéÕÝØï " +"ÒÞáßÞÛì×ãÙâÕáì àÐ×ÔÕÛÞÜ \"·Ðߨáì áÞÞÑéÕÝØÙ\" Ò ÜÕÝî áÛÕÒÐ." + +#: page.announcement.php:118 +msgid "Repeat" +msgstr "¿ÞÒâÞàØâì" + +#: page.announcement.php:118 +msgid "" +"Key to press that will allow for the message to be replayed. If you choose " +"this option there will be a short delay inserted after the message. If a " +"longer delay is needed it should be incoporated into the recording." +msgstr "" +"ºÐÚãî ÚÝÞßÚã ÝÐÖØÜÐâì ÔÛï ßÞÒâÞàÕÝØï ßàØÒÕâáâÒØï. µáÛØ ØáßÞÛì×ãÕâáï íâÐ " +"ÞßæØï, âÞ ÑãÔÕâ ÝÕÑÞÛìèÐï ×ÐÔÕàÖÚÐ ßÞáÛÕ áÞÞÑéÕÝØï. µáÛØ ÝãÖÝÐ ÑÞÛÕÕ " +"ÔÛØâÕÛìÝÐï ×ÐÔÕàÖÚÐ, Õñ ÝãÖÝÞ ÒÒÞÔØâì Ò ÚÞÝæÕ ×ÐߨáØ." + +#: page.announcement.php:128 +msgid "Disable" +msgstr "" + +#: page.announcement.php:137 +msgid "Allow Skip" +msgstr "ÀÐ×àÕèØâì ßàÞßãáâØâì" + +#: page.announcement.php:137 +msgid "If the caller is allowed to press a key to skip the message." +msgstr "" +"ÀÐ×àÕèØâì ßàÞßãáÚ ßàØÒÕâáâÒØï ßÞ ÝÐÖÐâØî ÚÛÐÒØèØ, çâÞÑë ÝÕ áÛãèÐâì ÕÓÞ " +"ÚÐÖÔëÙ àÐ×." + +#: page.announcement.php:141 +msgid "Return to IVR" +msgstr "²ÕàÝãâìáï Ò 'žÝâÕàÐÚâØÒÝÞÕ ÜÕÝî'" + +#: page.announcement.php:141 +msgid "" +"If this announcement came from an IVR and this box is checked, the " +"destination below will be ignored and instead it will return to the calling " +"IVR. Otherwise, the destination below will be taken. Don't check if not " +"using in this mode.
The IVR return location will be to the last IVR in " +"the call chain that was called so be careful to only check when needed. For " +"example, if an IVR directs a call to another destination which eventually " +"calls this annoucement and this box is checked, it will return to that IVR " +"which may not be the expected behavior." +msgstr "" +"µáÛØ ßàØÒÕâáâÒØÕ ØáßÞÛì×ãÕâáï ÚÐÚ èÐÓ Ò žÝâÕàÐÚâØÒÝÞÜ ÜÕÝî Ø ÞâÜÕçÕÝÞ " +"ØáßÞÛì×ÞÒÐÝØÕ ÒÞ×ÒàÐâÐ ÝÐ×ÐÔ ×ÔÕáì ßâØçÚÞÙ, âÞ ÝÐ×ÝÐçÕÝØÕ ÝØÖÕ ÑãÔÕâ " +"ßàÞØÓÝÞàØàÞÒÐÝÞ, Ø ×ÒÞÝÞÚ ÒÕàÝñâáï Ò žÝâÕàÐÚâØÒÝÞÕ ÜÕÝî ßÞáÛÕ " +"ÒÞáßàÞØ×ÒÕÔÕÝØï ßàØÒÕâáâÒØï. ² ÔàãÓÞÜ áÛãçÐÕ ×ÒÞÝÞÚ ßÕàÕåÞÔØâ ÝÐ áÛÕÔãîéØÙ " +"èÐÓ, ßÞ ÝÐ×ÝÐçÕÝØî, ãÚÐ×ÐÝÝÞÜã ÝØÖÕ. œÕ ÞâÜÕçÐÙâÕ íâã ÞßæØî, ÕáÛØ ÝÕ " +"ØáßÞÛì×ãÕâÕ íâÞâ àÕÖØÜ.
²Þ×ÒàÐâ Ò žÝâÕàÐÚâØÒÝÞÕ ÜÕÝî ßàÞØáåÞÔØâ ÝÐ âÞâ " +"èÐÓ, á ÚÞâÞàÞÓÞ ÑëÛÞ ØáßÞÛì×ÞÒÐÝÞ ÝÐßàÐÒÛÕÝØÕ ÝÐ íâÞ ßàØÒÕâáâÒØÕ, ßÞíâÞÜã " +"ØáßÞÛì×ãÙâÕ íâã ÞßæØî âÞÛìÚÞ âÞÓÔÐ, ÚÞÓÔÐ íâÞ ÞßàÐÒÔÐÝÝÞ. œÐßàØÜÕà, ÕáÛØ " +"žÝâÕàÐÚØÒÝÞÕ ÜÕÝî ÝÐßàÐÒÛïÕâ ×ÒÞÝÞÚ Ò ÔàãÓÞÕ ÝÐ×ÝÐçÕÝØÕ, ÓÔÕ ßÛÐÝØàãÕâáï " +"ÒÞáßàÞØ×ÒÕáâØ íâÞ ßàØÒÕâáâÒØÕ, Ø ÞâÜÕçÕÝÐ íâÐ ÞßæØï, âÞ ÒÞ×ÒàÐâ Ò " +"žÝâÕàÐÚâØÒÝÞÕ ÜÕÝî ÜÞÖÕâ ßàØÒÕáâØ Ú ÝÕßàÕÔáÚÐ×ãÕÜÞÜã ßÞÒÕÔÕÝØî." + +#: page.announcement.php:145 +msgid "Don't Answer Channel" +msgstr "œÕ ÞâÒÕçÐâì Ò ÚÐÝÐÛ" + +#: page.announcement.php:145 +msgid "" +"Check this to keep the channel from explicitly being answered. When checked, " +"the message will be played and if the channel is not already answered it " +"will be delivered as early media if the channel supports that. When not " +"checked, the channel is answered followed by a 1 second delay. When using an " +"annoucement from an IVR or other sources that have already answered the " +"channel, that 1 second delay may not be desired." +msgstr "" +"žáßÞÛì×ÞÒÐÝØÕ íâÞÙ ÞßæØØ ßàØ ïÒÝÞÜ ÞâÒÕâÕ. µáÛØ ÞâÜÕçÕÝÞ, ßàØÒÕâáâÒØÕ " +"ÒÞáßàÞØ×ÒÞÔØâáï, ÔÐÖÕ ÕáÛØ ÚÐÝÐÛ Õéñ ÝÕ ÞâÚàëÛáï. µáÛØ ÝÕ ÞâÜÕçÕÝÞ, âÞ ÚÐÝÐÛ " +"ÞâÒÕçÐÕâ á ×ÐÔÕàÖÚÞÙ ßàØÜÕàÝÞ Ò 1 áÕÚãÝÔã. µáÛØ ßàØÒÕâáâÒØÕ ØáßÞÛì×ãÕâáï ÚÐÚ " +"èÐÓ, ßÕàÕÝÐßàÐÒÛÕÝëÙ Ø× žÝâÕàÐÚâØÒÝÞÓÞ ÜÕÝî ØÛØ ÔàãÓÞÓÞ ØáâÞçÝØÚÐ, ÚÞâÞàëÙ " +"ãÖÕ ßàÞÓÞÒÞàØÛ çâÞ-âÞ Ò ÚÐÝÐÛ, âÞ íâÐ ×ÐÔÕàÖÚÐ Ò 1 áÕÚãÝÔã ÜÞÖÕâ Ñëâì " +"ÝÕÖÕÛÐâÕÛìÝÐ." + +#: page.announcement.php:149 +msgid "Destination after playback" +msgstr "œÐ×ÝÐçÕÝØÕ ßÞáÛÕ ÒÞáßàÞØ×ÒÕÔÕÝØï" + +#: page.announcement.php:157 +msgid "Submit Changes" +msgstr "¿àØÜÕÝØâì Ø×ÜÕÝÕÝØï" + +#: page.announcement.php:158 +msgid "Delete" +msgstr "ÃÔÐÛØâì" + +#: page.announcement.php:183 +msgid "Invalid description specified" +msgstr "ÃÚÐ×ÐÝÞ ÝÕÒÕàÝÞÕ ÞߨáÐÝØÕ" + +#: module.xml +msgid "Announcement" +msgstr "" + Index: /modules/branches/2.6/announcement/uninstall.php =================================================================== --- /modules/branches/2.6/announcement/uninstall.php (revision 3785) +++ /modules/branches/2.6/announcement/uninstall.php (revision 3785) @@ -0,0 +1,5 @@ + Index: /modules/branches/2.6/announcement/module.xml =================================================================== --- /modules/branches/2.6/announcement/module.xml (revision 7034) +++ /modules/branches/2.6/announcement/module.xml (revision 7034) @@ -0,0 +1,34 @@ + + announcement + Announcements + 2.5.1.7 + + *2.5.1.7* localization string enclosures, spelling + *2.5.1.6* spelling, localization fixes + *2.5.1.5* spelling fixes, Swedish + *2.5.1.4* #3196 typo in index + *2.5.1.3* #3195, localization fixes, Swedish + *2.5.1.2* #3138 Sqlite3 fixes, spellings + *2.5.1.1* #2987 sqlite3 install script changes + *2.5.1* #2063 Migrate recordings to recording ids + *2.5.0* #2845 tabindex + *2.4.0.3* #2872 mispelled Announcement + *2.4.0.2* #2604, #2843 mal-formed html tag, Russian translations + *2.4.0.1* added 2.4.0 dependency + *2.4.0* CHANGELOG TRUNCATED See SVN Repository + + setup + Inbound Call Control + + Plays back one of the system recordings (optionally allowing the user to skip it) and then goes to another destination. + + + 2.5.0alpha1 + recordings ge 3.3.8 + + + Announcements + + release/2.5/announcement-2.5.1.7.tgz + a01c255e80fedb1c17c29df5e35eff49 + Index: /modules/branches/2.6/announcement/functions.inc.php =================================================================== --- /modules/branches/2.6/announcement/functions.inc.php (revision 6938) +++ /modules/branches/2.6/announcement/functions.inc.php (revision 6938) @@ -0,0 +1,220 @@ + 'app-announcement-'.$row['announcement_id'].',s,1', 'description' => $row[1]); + } + return $extens; +} + +function announcement_getdest($exten) { + return array('app-announcement-'.$exten.',s,1'); +} + +function announcement_getdestinfo($dest) { + global $active_modules; + + if (substr(trim($dest),0,17) == 'app-announcement-') { + $exten = explode(',',$dest); + $exten = substr($exten[0],17); + + $thisexten = announcement_get($exten); + if (empty($thisexten)) { + return array(); + } else { + $type = isset($active_modules['announcement']['type'])?$active_modules['announcement']['type']:'setup'; + return array('description' => sprintf(_("Announcement: %s"),$thisexten['description']), + 'edit_url' => 'config.php?display=announcement&type='.$type.'&extdisplay='.urlencode($exten), + ); + } + } else { + return false; + } +} + +function announcement_recordings_usage($recording_id) { + global $active_modules; + + $results = sql("SELECT announcement_id, description FROM announcement WHERE recording_id = '$recording_id'","getAll",DB_FETCHMODE_ASSOC); + if (empty($results)) { + return array(); + } else { + $type = isset($active_modules['announcement']['type'])?$active_modules['announcement']['type']:'setup'; + foreach ($results as $result) { + $usage_arr[] = array( + 'url_query' => 'config.php?display=announcement&type='.$type.'&extdisplay='.urlencode($result['announcement_id']), + 'description' => sprintf(_("Announcement: %s"),$result['description']), + ); + } + return $usage_arr; + } +} + +function announcement_get_config($engine) { + global $ext; + switch ($engine) { + case 'asterisk': + foreach (announcement_list() as $row) { + $recording = recordings_get_file($row['recording_id']); + if (! $row['noanswer']) { + $ext->add('app-announcement-'.$row['announcement_id'], 's', '', new ext_gotoif('$["${CDR(disposition)}" = "ANSWERED"]','begin')); + $ext->add('app-announcement-'.$row['announcement_id'], 's', '', new ext_answer('')); + $ext->add('app-announcement-'.$row['announcement_id'], 's', '', new ext_wait('1')); + } + $ext->add('app-announcement-'.$row['announcement_id'], 's', 'begin', new ext_noop('Playing announcement '.$row['description'])); + if ($row['allow_skip'] || $row['repeat_msg']) { + // allow skip + if ($row['repeat_msg']) { + $ext->add('app-announcement-'.$row['announcement_id'], 's', '', new ext_responsetimeout(1)); + } + $ext->add('app-announcement-'.$row['announcement_id'], 's', 'play', new ext_background($recording.'|nm')); + if ($row['repeat_msg']) { + $ext->add('app-announcement-'.$row['announcement_id'], 's', '', new ext_waitexten('')); + } + + if ($row['allow_skip']) { + $ext->add('app-announcement-'.$row['announcement_id'], '_X', '', new ext_noop('User skipped announcement')); + if ($row['return_ivr']) { + $ext->add('app-announcement-'.$row['announcement_id'], '_X', '', new ext_gotoif('$["x${IVR_CONTEXT}" = "x"]', $row['post_dest'].':${IVR_CONTEXT},return,1')); + } else { + $ext->add('app-announcement-'.$row['announcement_id'], '_X', '', new ext_goto($row['post_dest'])); + } + } + if ($row['repeat_msg']) { + $ext->add('app-announcement-'.$row['announcement_id'], $row['repeat_msg'], '', new ext_goto('s,play')); + } + } else { + $ext->add('app-announcement-'.$row['announcement_id'], 's', '', new ext_playback($recording.',noanswer')); + } + + // if repeat_msg enabled then set exten to t to allow for the key to be pressed, otherwise play message and go + $exten = $row['repeat_msg'] ? 't':'s'; + if ($row['return_ivr']) { + $ext->add('app-announcement-'.$row['announcement_id'], $exten, '', new ext_gotoif('$["x${IVR_CONTEXT}" = "x"]', $row['post_dest'].':${IVR_CONTEXT},return,1')); + if ($row['allow_skip'] || $row['repeat_msg']) + $ext->add('app-announcement-'.$row['announcement_id'], 'i', '', new ext_gotoif('$["x${IVR_CONTEXT}" = "x"]', $row['post_dest'].':${IVR_CONTEXT},return,1')); + } else { + $ext->add('app-announcement-'.$row['announcement_id'], $exten, '', new ext_goto($row['post_dest'])); + if ($row['allow_skip'] || $row['repeat_msg']) + $ext->add('app-announcement-'.$row['announcement_id'], 'i', '', new ext_goto($row['post_dest'])); + } + + } + break; + } +} + +function announcement_list() { + global $db; + $sql = "SELECT announcement_id, description, recording_id, allow_skip, post_dest, return_ivr, noanswer, repeat_msg FROM announcement ORDER BY description "; + $results = $db->getAll($sql, DB_FETCHMODE_ASSOC); + if(DB::IsError($results)) { + die_freepbx($results->getMessage()."

Error selecting from announcement"); + } + + // Make array backward compatible. + $count = 0; + foreach($results as $item) { + $results[$count][0] = $item['announcement_id']; + $results[$count][1] = $item['description']; + $results[$count][2] = $item['recording_id']; + $results[$count][3] = $item['allow_skip']; + $results[$count][4] = $item['post_dest']; + $results[$count][5] = $item['return_ivr']; + $results[$count][6] = $item['noanswer']; + $results[$count][7] = $item['repeat_msg']; + $count++; + } + return $results; +} + +function announcement_get($announcement_id) { + global $db; + $sql = "SELECT announcement_id, description, recording_id, allow_skip, post_dest, return_ivr, noanswer, repeat_msg FROM announcement WHERE announcement_id = '".$db->escapeSimple($announcement_id)."'"; + $row = $db->getRow($sql,DB_FETCHMODE_ASSOC); + if(DB::IsError($row)) { + die_freepbx($row->getMessage()."

Error selecting row from announcement"); + } + // Added Associative query above but put positional indexes back to maintain backward compatibility + // + $i = 0; + foreach ($row as $item) { + $row[$i] = $item; + $i++; + } + return $row; +} + +function announcement_add($description, $recording_id, $allow_skip, $post_dest, $return_ivr, $noanswer, $repeat_msg) { + global $db; + $sql = "INSERT INTO announcement (description, recording_id, allow_skip, post_dest, return_ivr, noanswer, repeat_msg) VALUES (". + "'".$db->escapeSimple($description)."', ". + "'".$recording_id."', ". + "'".($allow_skip ? 1 : 0)."', ". + "'".$db->escapeSimple($post_dest)."', ". + "'".($return_ivr ? 1 : 0)."', ". + "'".($noanswer ? 1 : 0)."', ". + "'".$db->escapeSimple($repeat_msg)."')"; + $result = $db->query($sql); + if(DB::IsError($result)) { + die_freepbx($result->getMessage().$sql); + } +} + +function announcement_delete($announcement_id) { + global $db; + $sql = "DELETE FROM announcement WHERE announcement_id = ".$db->escapeSimple($announcement_id); + $result = $db->query($sql); + if(DB::IsError($result)) { + die_freepbx($result->getMessage().$sql); + } + +} + +function announcement_edit($announcement_id, $description, $recording_id, $allow_skip, $post_dest, $return_ivr, $noanswer, $repeat_msg) { + global $db; + $sql = "UPDATE announcement SET ". + "description = '".$db->escapeSimple($description)."', ". + "recording_id = '".$recording_id."', ". + "allow_skip = '".($allow_skip ? 1 : 0)."', ". + "post_dest = '".$db->escapeSimple($post_dest)."', ". + "return_ivr = '".($return_ivr ? 1 : 0)."', ". + "noanswer = '".($noanswer ? 1 : 0)."', ". + "repeat_msg = '".$db->escapeSimple($repeat_msg)."' ". + "WHERE announcement_id = ".$db->escapeSimple($announcement_id); + $result = $db->query($sql); + if(DB::IsError($result)) { + die_freepbx($result->getMessage().$sql); + } +} + +function announcement_check_destinations($dest=true) { + global $active_modules; + + $destlist = array(); + if (is_array($dest) && empty($dest)) { + return $destlist; + } + $sql = "SELECT announcement_id, post_dest, description FROM announcement "; + if ($dest !== true) { + $sql .= "WHERE post_dest in ('".implode("','",$dest)."')"; + } + $results = sql($sql,"getAll",DB_FETCHMODE_ASSOC); + + $type = isset($active_modules['announcement']['type'])?$active_modules['announcement']['type']:'setup'; + + foreach ($results as $result) { + $thisdest = $result['post_dest']; + $thisid = $result['announcement_id']; + $destlist[] = array( + 'dest' => $thisdest, + 'description' => sprintf(_("Announcement: %s"),$result['description']), + 'edit_url' => 'config.php?display=announcement&type='.$type.'&extdisplay='.urlencode($thisid), + ); + } + return $destlist; +} + +?> Index: /modules/branches/2.6/announcement/page.announcement.php =================================================================== --- /modules/branches/2.6/announcement/page.announcement.php (revision 6727) +++ /modules/branches/2.6/announcement/page.announcement.php (revision 6727) @@ -0,0 +1,199 @@ + +
+ +
+ +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

:
To add additional recordings use the \"System Recordings\" MENU to the left")?> + +
+ +
/>
The IVR return location will be to the last IVR in the call chain that was called so be careful to only check when needed. For example, if an IVR directs a call to another destination which eventually calls this annoucement and this box is checked, it will return to that IVR which may not be the expected behavior.")?> />
/>

:

" tabindex=""> + '; } ?> +
+ : +
+
+ + + Index: /modules/branches/2.6/announcement/install.php =================================================================== --- /modules/branches/2.6/announcement/install.php (revision 6686) +++ /modules/branches/2.6/announcement/install.php (revision 6686) @@ -0,0 +1,158 @@ +"; + } +} + +if (! function_exists("outn")) { + function outn($text) { + echo $text; + } +} + +global $db; +global $amp_conf; + +$autoincrement = (($amp_conf["AMPDBENGINE"] == "sqlite") || ($amp_conf["AMPDBENGINE"] == "sqlite3")) ? "AUTOINCREMENT":"AUTO_INCREMENT"; +$sql = "CREATE TABLE IF NOT EXISTS announcement ( + announcement_id integer NOT NULL PRIMARY KEY $autoincrement, + description VARCHAR( 50 ), + recording_id INTEGER, + allow_skip INT, + post_dest VARCHAR( 255 ), + return_ivr TINYINT(1) NOT NULL DEFAULT 0, + noanswer TINYINT(1) NOT NULL DEFAULT 0, + repeat_msg VARCHAR(2) NOT NULL DEFAULT '' +)"; +$check = $db->query($sql); +if(DB::IsError($check)) { + die_freepbx("Can not create annoucment table"); +} + +// Version 0.3 adds auto-return to IVR +$sql = "SELECT return_ivr FROM announcement"; +$check = $db->getRow($sql, DB_FETCHMODE_ASSOC); +if(DB::IsError($check)) { + // add new field + $sql = "ALTER TABLE announcement ADD return_ivr TINYINT(1) NOT NULL DEFAULT 0;"; + $result = $db->query($sql); + if(DB::IsError($result)) { die_freepbx($result->getDebugInfo()); } +} + +// Version 0.4 adds auto-return to IVR +$sql = "SELECT noanswer FROM announcement"; +$check = $db->getRow($sql, DB_FETCHMODE_ASSOC); +if(DB::IsError($check)) { + // add new field + $sql = "ALTER TABLE announcement ADD noanswer TINYINT(1) NOT NULL DEFAULT 0;"; + $result = $db->query($sql); + if(DB::IsError($result)) { die_freepbx($result->getDebugInfo()); } +} + +// Version 0.8 upgrade +$repeat = (($amp_conf["AMPDBENGINE"] == "sqlite") || ($amp_conf["AMPDBENGINE"] == "sqlite3")) ? "repeat":"`repeat`"; +$sql = "SELECT $repeat FROM announcement"; +$check = @$db->getRow($sql, DB_FETCHMODE_ASSOC); +if(! DB::IsError($check)) { + // Change field name because php5 was not happy with repeat + // + $sql = "ALTER TABLE announcement CHANGE $repeat repeat_msg VARCHAR( 2 ) NOT NULL DEFAULT '' ;"; + $result = $db->query($sql); + if(DB::IsError($result)) { + die_freepbx($result->getDebugInfo()); + } +} + +// Version 0.6 adds repeat_msg +$sql = "SELECT repeat_msg FROM announcement"; +$check = $db->getRow($sql, DB_FETCHMODE_ASSOC); +if(DB::IsError($check)) { + // add new field + $sql = "ALTER TABLE announcement ADD repeat_msg VARCHAR(2) NOT NULL DEFAULT '';"; + $result = $db->query($sql); + if(DB::IsError($result)) { die_freepbx($result->getDebugInfo()); } +} + +$results = array(); +$sql = "SELECT announcement_id, post_dest FROM announcement"; +$results = $db->getAll($sql, DB_FETCHMODE_ASSOC); +if (!DB::IsError($results)) { // error - table must not be there + foreach ($results as $result) { + $old_dest = $result['post_dest']; + $announcement_id = $result['announcement_id']; + + $new_dest = merge_ext_followme(trim($old_dest)); + if ($new_dest != $old_dest) { + $sql = "UPDATE announcement SET post_dest = '$new_dest' WHERE announcement_id = $announcement_id AND post_dest = '$old_dest'"; + $results = $db->query($sql); + if(DB::IsError($results)) { + die_freepbx($results->getMessage()); + } + } + } +} + +// Version 2.5 migrate to recording ids +// +outn(_("Checking if recordings need migration..")); +$sql = "SELECT recording_id FROM announcement"; +$check = $db->getRow($sql, DB_FETCHMODE_ASSOC); +if(DB::IsError($check)) { + // Add recording_id field + // + out(_("migrating")); + outn(_("adding recording_id field..")); + $sql = "ALTER TABLE announcement ADD recording_id INTEGER"; + $result = $db->query($sql); + if(DB::IsError($result)) { + out(_("fatal error")); + die_freepbx($result->getDebugInfo()); + } else { + out(_("ok")); + } + + // Get all the valudes and replace them with recording_id + // + outn(_("migrate to recording ids..")); + $sql = "SELECT `announcement_id`, `recording` FROM `announcement`"; + $results = $db->getAll($sql, DB_FETCHMODE_ASSOC); + if(DB::IsError($results)) { + out(_("fatal error")); + die_freepbx($results->getDebugInfo()); + } + $migrate_arr = array(); + $count = 0; + foreach ($results as $row) { + if (trim($row['recording']) != '') { + $rec_id = recordings_get_or_create_id($row['recording'], 'announcement'); + $migrate_arr[] = array($rec_id, $row['announcement_id']); + $count++; + } + } + if ($count) { + $compiled = $db->prepare('UPDATE `announcement` SET `recording_id` = ? WHERE `announcement_id` = ?'); + $result = $db->executeMultiple($compiled,$migrate_arr); + if(DB::IsError($result)) { + out(_("fatal error")); + die_freepbx($result->getDebugInfo()); + } + } + out(sprintf(_("migrated %s entries"),$count)); + + // Now remove the old recording field replaced by new id field + // + outn(_("dropping recording field..")); + $sql = "ALTER TABLE `announcement` DROP `recording`"; + $result = $db->query($sql); + if(DB::IsError($result)) { + out(_("no recording field???")); + } else { + out(_("ok")); + } + +} else { + out(_("already migrated")); +} + +?> Index: /modules/branches/2.6/conferences/i18n/sv_SE/LC_MESSAGES/conferences.po =================================================================== --- /modules/branches/2.6/conferences/i18n/sv_SE/LC_MESSAGES/conferences.po (revision 6939) +++ /modules/branches/2.6/conferences/i18n/sv_SE/LC_MESSAGES/conferences.po (revision 6939) @@ -0,0 +1,265 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: FreePBX conferences\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2008-10-05 10:59+0200\n" +"PO-Revision-Date: 2008-10-10 20:50+0100\n" +"Last-Translator: Mikael Carlsson \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Poedit-Language: Swedish\n" +"X-Poedit-Country: SWEDEN\n" + +#: functions.inc.php:56 +#, php-format +msgid "Conference Room %s : %s" +msgstr "Konferensrum %s : %s" + +#: functions.inc.php:75 +#, php-format +msgid "Conference: %s" +msgstr "Konferens: %s" + +#: functions.inc.php:194 +msgid "Conference: " +msgstr "Konferens:" + +#: install.php:35 +msgid "Checking if recordings need migration.." +msgstr "Kontrollerar om inspelningar behöver migreras.." + +#: install.php:41 +msgid "migrating" +msgstr "migrerar" + +#: install.php:42 +msgid "adding joinmsg_id field.." +msgstr "lÀgger till fÀltet joinmsg_id.." + +#: install.php:46 +#: install.php:58 +#: install.php:74 +msgid "fatal error" +msgstr "allvarligt fel" + +#: install.php:49 +#: install.php:88 +msgid "ok" +msgstr "ok" + +#: install.php:54 +msgid "migrate to recording ids.." +msgstr "migrerar till recording ids.." + +#: install.php:78 +#, php-format +msgid "migrated %s entries" +msgstr "migrerade %s poster" + +#: install.php:82 +msgid "dropping joinmsg field.." +msgstr "kastar fÀltet joinmsg.." + +#: install.php:86 +msgid "no joinmsg field???" +msgstr "inget fÀlt som heter joinmsg???" + +#: install.php:92 +msgid "already migrated" +msgstr "redan migrerad" + +#: page.conferences.php:24 +msgid "Warning! Extension" +msgstr "Varning! Anknytning" + +#: page.conferences.php:24 +msgid "is not allowed for your account." +msgstr "Àr inte tillåtet för ditt konto." + +#: page.conferences.php:64 +#: page.conferences.php:115 +#: page.conferences.php:126 +msgid "Add Conference" +msgstr "LÀgg till konferens" + +#: page.conferences.php:78 +msgid "Conference" +msgstr "Konferens" + +#: page.conferences.php:78 +msgid "deleted" +msgstr "borttagen" + +#: page.conferences.php:98 +msgid "Conference:" +msgstr "Konferens:" + +#: page.conferences.php:101 +#, php-format +msgid "Delete Conference %s" +msgstr "Ta bort konferens %s" + +#: page.conferences.php:118 +msgid "Conflicting Extensions" +msgstr "Anknytningarna Àr i konflikt" + +#: page.conferences.php:126 +msgid "Edit Conference" +msgstr "Redigera konferens" + +#: page.conferences.php:131 +msgid "Conference Number:" +msgstr "Konferensnummer:" + +#: page.conferences.php:131 +msgid "Use this number to dial into the conference." +msgstr "AnvÀnd detta nummer för att ringa till konferensen." + +#: page.conferences.php:136 +msgid "Conference Name:" +msgstr "Konferensnamn:" + +#: page.conferences.php:136 +msgid "Give this conference a brief name to help you identify it." +msgstr "Ge konferensen ett kortfattat namn." + +#: page.conferences.php:140 +msgid "User PIN:" +msgstr "AnvÀndarlösenord:" + +#: page.conferences.php:140 +msgid "You can require callers to enter a password before they can enter this conference.

This setting is optional.

If either PIN is entered, the user will be prompted to enter a PIN." +msgstr "Du kan krÀva att uppringare anger ett lösenord innan de når konferensen.

Denna instÀllning Àr valfri.

Om ett lösenord (endast siffror) skrivs in får uppringaren en fråga om att mata in ett lösenord." + +#: page.conferences.php:144 +msgid "Admin PIN:" +msgstr "Administratörslösenord:" + +#: page.conferences.php:144 +msgid "Enter a PIN number for the admin user.

This setting is optional unless the 'leader wait' option is in use, then this PIN will identify the leader." +msgstr "Skriv in ett lösenord (endast siffror) för administratören.
Denna instÀllning Àr valfri om inte 'InvÀnta ledare' Àr valt, då kommer detta lösenord att identifiera ledaren." + +#: page.conferences.php:150 +msgid "Conference Options" +msgstr "Konferensval" + +#: page.conferences.php:153 +#: page.conferences.php:170 +msgid "Join Message:" +msgstr "Anslutningsmeddelande:" + +#: page.conferences.php:153 +msgid "Message to be played to the caller before joining the conference.

To add additional recordings please use the \"System Recordings\" MENU to the left" +msgstr "Meddelande som ska spelas upp för uppringaren innan anslutning sker till konferensen.

För att lÀgga till fler inspelningar vÀljer du \"Systeminspelningar\" i menyn till vÀnster" + +#: page.conferences.php:158 +msgid "None" +msgstr "Inget" + +#: page.conferences.php:170 +msgid "Message to be played to the caller before joining the conference.

You must install and enable the \"Systems Recordings\" Module to edit this option" +msgstr "Meddelande som ska spelas upp för uppringaren innan anslutning sker till konferensen.

Du mÃ¥ste installera och aktivera modulen \"Systeminspelningar\" för att kunna redigera detta val" + +#: page.conferences.php:177 +msgid "Leader Wait:" +msgstr "VÀnta pÃ¥ ledaren:" + +#: page.conferences.php:177 +msgid "Wait until the conference leader (admin user) arrives before starting the conference" +msgstr "VÀnta till konferensledaren (administratören) ansluter innan konferensen startas" + +#: page.conferences.php:182 +#: page.conferences.php:194 +#: page.conferences.php:206 +#: page.conferences.php:218 +#: page.conferences.php:230 +#: page.conferences.php:242 +#: page.conferences.php:255 +msgid "No" +msgstr "Nej" + +#: page.conferences.php:183 +#: page.conferences.php:195 +#: page.conferences.php:207 +#: page.conferences.php:219 +#: page.conferences.php:231 +#: page.conferences.php:243 +#: page.conferences.php:256 +msgid "Yes" +msgstr "Ja" + +#: page.conferences.php:189 +msgid "Quiet Mode:" +msgstr "Tyst lÀge:" + +#: page.conferences.php:189 +msgid "Quiet mode (do not play enter/leave sounds)" +msgstr "Tyst lÀge (spela inte upp ljud för anslut/lÀmna)" + +#: page.conferences.php:201 +msgid "User Count:" +msgstr "RÀkna anvÀndare:" + +#: page.conferences.php:201 +msgid "Announce user(s) count on joining conference" +msgstr "BerÀtta antalet anvÀndare nÀr anslutning till konferensen sker" + +#: page.conferences.php:213 +msgid "User join/leave:" +msgstr "AnvÀndare ansluter/lÀmnar:" + +#: page.conferences.php:213 +msgid "Announce user join/leave" +msgstr "Annonsera nÀr anvÀndare ansluter/lÀmnar" + +#: page.conferences.php:225 +msgid "Music on Hold:" +msgstr "Pausmusik:" + +#: page.conferences.php:225 +msgid "Enable Music On Hold when the conference has a single caller" +msgstr "Aktivera pausmusik nÀr det endast Àr en anvÀndare i konferensen" + +#: page.conferences.php:237 +msgid "Allow Menu:" +msgstr "TillÃ¥t meny:" + +#: page.conferences.php:237 +msgid "Present Menu (user or admin) when '*' is received ('send' to menu)" +msgstr "Ge tillgÃ¥ng till en meny (anvÀndar eller administratörs) nÀr '*' trycks pÃ¥ telefonen" + +#: page.conferences.php:250 +msgid "Record Conference:" +msgstr "Spela in konferens:" + +#: page.conferences.php:250 +msgid "Record the conference call" +msgstr "VÀlj om konferensen ska spelas in" + +#: page.conferences.php:268 +msgid "Submit Changes" +msgstr "Spara Àndringar" + +#: page.conferences.php:282 +msgid "Please enter a valid Conference Number" +msgstr "Skriv in ett giltig konferensnummer" + +#: page.conferences.php:283 +msgid "Please enter a valid Conference Name" +msgstr "Skriv in ett giltigt konferensnamn" + +#: page.conferences.php:284 +msgid "You must set an admin PIN for the Conference Leader when selecting the leader wait option" +msgstr "Du mÃ¥ste sÀtta en administratörs-PIN för konferensledaren nÀr du vÀljer VÀnta pÃ¥ ledare" + +#: module.xml +msgid "Conferences" +msgstr "Konferenser" + Index: /modules/branches/2.6/conferences/i18n/he_IL/LC_MESSAGES/conferences.po =================================================================== --- /modules/branches/2.6/conferences/i18n/he_IL/LC_MESSAGES/conferences.po (revision 3441) +++ /modules/branches/2.6/conferences/i18n/he_IL/LC_MESSAGES/conferences.po (revision 3441) @@ -0,0 +1,171 @@ +# Hebrew version for Asterisk Conferences FreePBX Module. +# Copyright (C) 2006 +# This file is distributed under the same license as the PACKAGE package. +# Shimi , 2006. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: FreePBX 2.2.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2006-10-17 17:20+0300\n" +"PO-Revision-Date: 2006-10-17 17:30+0300\n" +"Last-Translator: Shimi \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: page.conferences.php:22 +msgid "Warning! Extension" +msgstr "אזה׹ה! שלוחה" + +#: page.conferences.php:22 +msgid "is not allowed for your account." +msgstr "אינה מוךשית עבוך החשבון שלך." + +#: page.conferences.php:53 page.conferences.php:84 page.conferences.php:91 +msgid "Add Conference" +msgstr "הוסף ועידה" + +#: page.conferences.php:67 +msgid "Conference" +msgstr "ועידה" + +#: page.conferences.php:67 +msgid "deleted" +msgstr "נמחקה" + +#: page.conferences.php:81 +msgid "Conference:" +msgstr "ועידה:" + +#: page.conferences.php:82 +msgid "Delete Conference" +msgstr "מחק ועידה" + +#: page.conferences.php:91 +msgid "Edit Conference" +msgstr "עךוך ועידה" + +#: page.conferences.php:96 +msgid "conference number:" +msgstr "מס׀ך ועידה:" + +#: page.conferences.php:96 +msgid "Use this number to dial into the conference." +msgstr "השתמש במס׀ך זה כדי לחייג לתוך הועידה" + +#: page.conferences.php:101 +msgid "conference name:" +msgstr "שם הועידה:" + +#: page.conferences.php:101 +msgid "Give this conference a brief name to help you identify it." +msgstr "תן לועידה זו שם ק׊ך שיעזוך לך לזהות אותה." + +#: page.conferences.php:105 +msgid "user PIN:" +msgstr "סיסמת משתמש:" + +#: page.conferences.php:105 +msgid "" +"You can require callers to enter a password before they can enter this " +"conference.

This setting is optional.

If either PIN is " +"entered, the user will be prompted to enter a PIN." +msgstr "אתה יכול לדךוש שמתקשךים ישט׹כו להכניס סיסמא ל׀ני שהם יכולים להיכנס לועידה זו.

הגד׹ה זו היא ךשות.

אם הוכנסה סיסמת משתמש כלשהיא, המשתמש יתבקש לחייגה בכניסה." + +#: page.conferences.php:109 +msgid "admin PIN:" +msgstr "סיסמת מנהל:" + +#: page.conferences.php:109 +msgid "" +"Enter a PIN number for the admin user.

This setting is optional " +"unless the 'leader wait' option is in use, then this PIN will identify the " +"leader." +msgstr "הכנס סיסמא עבוך המשתמש המנהל.

א׀שךות זו היא ךשות אלא אם כן הא׀שךות 'המתן למנהל' מסומנת, ובמק׹ה זה, סיסמא זו תזהה את המנהל." + +#: page.conferences.php:118 +msgid "Conference Options" +msgstr "א׀שךויות ועידה" + +#: page.conferences.php:121 page.conferences.php:139 +msgid "join message:" +msgstr "הודעת ה׊טך׀ות:" + +#: page.conferences.php:121 +msgid "" +"Message to be played to the caller before joining the conference.

To " +"add additional recordings please use the \"System Recordings\" MENU to the " +"left" +msgstr "הודעה שתושמע למתקשך ל׀ני הכניסה לועידה.

כדי להוסיף הודעות נוס׀ות, אנא השתמש בת׀ךיט \"הקלטות מעךכת\" שב׊ד שמאל." + +#: page.conferences.php:127 +msgid "None" +msgstr "אין" + +#: page.conferences.php:139 +msgid "" +"Message to be played to the caller before joining the conference.

You " +"must install and enable the \"Systems Recordings\" Module to edit this option" +msgstr "הודעה שתושמע למתקשך ל׀ני הכניסה לועידה.

אתה חייב להתקין ולה׀עיל את המודול \"הקלטות מעךכת\" כדי לעךוך א׀שךות זאת" + +#: page.conferences.php:149 +msgid "leader wait:" +msgstr "המתנה למנהל:" + +#: page.conferences.php:149 +msgid "" +"wait until the conference leader (admin user) arrives before starting the " +"conference" +msgstr "המתן עד שמנהל הועידה (משתמש עם סיסמא מיוחדת) יגיע ל׀ני שתחבך את כולם לועידה" + +#: page.conferences.php:154 page.conferences.php:166 page.conferences.php:178 +#: page.conferences.php:190 page.conferences.php:202 page.conferences.php:214 +msgid "No" +msgstr "לא" + +#: page.conferences.php:155 page.conferences.php:167 page.conferences.php:179 +#: page.conferences.php:191 page.conferences.php:203 page.conferences.php:215 +msgid "Yes" +msgstr "כן" + +#: page.conferences.php:161 +msgid "quiet mode:" +msgstr "משב שקט:" + +#: page.conferences.php:161 +msgid "quiet mode (do not play enter/leave sounds)" +msgstr "משב שקט (אל תשמיע שלילי כניסה/ישיאה)" + +#: page.conferences.php:173 +msgid "user count:" +msgstr "ס׀יךת משתמשים:" + +#: page.conferences.php:173 +msgid "announce user(s) count on joining conference" +msgstr "הכ׹ז על מס׀ך הנמשאים בועידה בזמן הכניסה לועידה" + +#: page.conferences.php:185 +msgid "user join/leave:" +msgstr "כניסת/י׊יאת משתמש:" + +#: page.conferences.php:185 +msgid "announce user join/leave" +msgstr "הכ׹ז על כניסה/ישיאה של משתמשים" + +#: page.conferences.php:197 +msgid "music on hold:" +msgstr "מוסיקה בהמתנה:" + +#: page.conferences.php:197 +msgid "enable music on hold when the conference has a single caller" +msgstr "ה׀על מוסיקה בהמתנה כאשך בועידה יש ךק מתקשך אחד" + +#: page.conferences.php:209 +msgid "allow menu:" +msgstr "א׀שך ת׀ךיט:" + +#: page.conferences.php:209 +msgid "present menu (user or admin) when '*' is received ('send' to menu)" +msgstr "השג ת׀ךיט (משתמש או מנהל) כאשך לוחשים על כוכבית ('שליחה' אל הת׀ךיט)" Index: /modules/branches/2.6/conferences/i18n/hu_HU/LC_MESSAGES/conferences.po =================================================================== --- /modules/branches/2.6/conferences/i18n/hu_HU/LC_MESSAGES/conferences.po (revision 6986) +++ /modules/branches/2.6/conferences/i18n/hu_HU/LC_MESSAGES/conferences.po (revision 6986) @@ -0,0 +1,273 @@ +msgid "" +msgstr "" +"Project-Id-Version: 2.4\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2008-10-05 10:59+0200\n" +"PO-Revision-Date: 2008-02-12 21:48+0100\n" +"Last-Translator: Lónyai Gergely \n" +"Language-Team: Magyar \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Poedit-Language: Hungarian\n" +"X-Poedit-Country: HUNGARY\n" +"X-Poedit-SourceCharset: utf-8\n" + +#: functions.inc.php:56 +#, php-format +msgid "Conference Room %s : %s" +msgstr "" + +#: functions.inc.php:75 +#, php-format +msgid "Conference: %s" +msgstr "" + +#: functions.inc.php:194 +msgid "Conference: " +msgstr "Konferencia:" + +#: install.php:35 +msgid "Checking if recordings need migration.." +msgstr "" + +#: install.php:41 +msgid "migrating" +msgstr "" + +#: install.php:42 +msgid "adding joinmsg_id field.." +msgstr "" + +#: install.php:46 install.php:58 install.php:74 +msgid "fatal error" +msgstr "" + +#: install.php:49 install.php:88 +msgid "ok" +msgstr "" + +#: install.php:54 +msgid "migrate to recording ids.." +msgstr "" + +#: install.php:78 +#, php-format +msgid "migrated %s entries" +msgstr "" + +#: install.php:82 +msgid "dropping joinmsg field.." +msgstr "" + +#: install.php:86 +msgid "no joinmsg field???" +msgstr "" + +#: install.php:92 +msgid "already migrated" +msgstr "" + +#: page.conferences.php:24 +msgid "Warning! Extension" +msgstr "Figyelem! Mellék" + +#: page.conferences.php:24 +msgid "is not allowed for your account." +msgstr "nem elfogadható a hozzáférés." + +#: page.conferences.php:64 page.conferences.php:115 page.conferences.php:126 +msgid "Add Conference" +msgstr "Konferencia hozzásadása" + +#: page.conferences.php:78 +msgid "Conference" +msgstr "Konferencia" + +#: page.conferences.php:78 +msgid "deleted" +msgstr "törölt" + +#: page.conferences.php:98 +msgid "Conference:" +msgstr "Konferencia:" + +#: page.conferences.php:101 +#, php-format +msgid "Delete Conference %s" +msgstr "Konferencia törlése %s" + +#: page.conferences.php:118 +msgid "Conflicting Extensions" +msgstr "Mellékek ÃŒtközése" + +#: page.conferences.php:126 +msgid "Edit Conference" +msgstr "Konferencia szerkesztése" + +#: page.conferences.php:131 +msgid "Conference Number:" +msgstr "Konferenciaszám:" + +#: page.conferences.php:131 +msgid "Use this number to dial into the conference." +msgstr "A szám, amit a conferencia eléréséhez tárcsázni kell." + +#: page.conferences.php:136 +msgid "Conference Name:" +msgstr "Konferencianév" + +#: page.conferences.php:136 +msgid "Give this conference a brief name to help you identify it." +msgstr "Adj meg a konferenciának egy jellemző nevet." + +#: page.conferences.php:140 +msgid "User PIN:" +msgstr "Felhasználó PIN:" + +#: page.conferences.php:140 +msgid "" +"You can require callers to enter a password before they can enter this " +"conference.

This setting is optional.

If either PIN is " +"entered, the user will be prompted to enter a PIN." +msgstr "" +"A konferenciát hívó személynek ezt a jelszót kell megadnia." +"

Opcionális beállítás

Ha megadsz egy PIN számot, akkor a " +"felhasználónak ugyanezt a PIN-t kell majd a belépéshez megadnia." + +#: page.conferences.php:144 +msgid "Admin PIN:" +msgstr "Admin PIN:" + +#: page.conferences.php:144 +msgid "" +"Enter a PIN number for the admin user.

This setting is optional " +"unless the 'leader wait' option is in use, then this PIN will identify the " +"leader." +msgstr "" +"Az admin felhasználó PIN száma.

Ezzel a beállítással a 'Vezetőre " +"várakozás' opcióban megadható PIN számot lehet beállítani. Aki az említett " +"időben megadja a PIN-t, az lesz a konferencia vezetője." + +#: page.conferences.php:150 +msgid "Conference Options" +msgstr "Konferencia opciók" + +#: page.conferences.php:153 page.conferences.php:170 +msgid "Join Message:" +msgstr "Csatlakozó ÃŒzenet:" + +#: page.conferences.php:153 +msgid "" +"Message to be played to the caller before joining the conference.

To " +"add additional recordings please use the \"System Recordings\" MENU to the " +"left" +msgstr "" +"Ez az Ìzenet lesz lejátszva a konferenciába csatlakozó hívóknak.

A " +"saját felvételeidet a \"Rendszerfelvételek\" bal oldali menÌpontban " +"rögzítheted." + +#: page.conferences.php:158 +msgid "None" +msgstr "Nincs" + +#: page.conferences.php:170 +msgid "" +"Message to be played to the caller before joining the conference.

You " +"must install and enable the \"Systems Recordings\" Module to edit this option" +msgstr "" +"Ez az Ìzenet lesz lejátszva a konferenciába csatlakozó hívóknak." +"

Használatához a \"Rendszerfelvételek\" modult telepítened, és " +"engedélyezed kell." + +#: page.conferences.php:177 +msgid "Leader Wait:" +msgstr "Vezetőre várakozás:" + +#: page.conferences.php:177 +msgid "" +"Wait until the conference leader (admin user) arrives before starting the " +"conference" +msgstr "Wárakozás a konferencia elindítása előtt a konferencia vezetőjére (admin)." + +#: page.conferences.php:182 page.conferences.php:194 page.conferences.php:206 +#: page.conferences.php:218 page.conferences.php:230 page.conferences.php:242 +#: page.conferences.php:255 +msgid "No" +msgstr "Nem" + +#: page.conferences.php:183 page.conferences.php:195 page.conferences.php:207 +#: page.conferences.php:219 page.conferences.php:231 page.conferences.php:243 +#: page.conferences.php:256 +msgid "Yes" +msgstr "Igen" + +#: page.conferences.php:189 +msgid "Quiet Mode:" +msgstr "Néma ÃŒzemmód:" + +#: page.conferences.php:189 +msgid "Quiet mode (do not play enter/leave sounds)" +msgstr "Csendes mód (nem játszik le zenét ki- és belépéskor)" + +#: page.conferences.php:201 +msgid "User Count:" +msgstr "Felhasználószámlálás:" + +#: page.conferences.php:201 +msgid "Announce user(s) count on joining conference" +msgstr "Esemény a felhasználók csatlakozásakor" + +#: page.conferences.php:213 +msgid "User join/leave:" +msgstr "Felhasználók fel/lecsatlakozása" + +#: page.conferences.php:213 +msgid "Announce user join/leave" +msgstr "Esemény felhasználó fel/lecsatlakozásakor" + +#: page.conferences.php:225 +msgid "Music on Hold:" +msgstr "Háttérzene:" + +#: page.conferences.php:225 +msgid "Enable Music On Hold when the conference has a single caller" +msgstr "Háttérzene engedélyezése, ha csak egy tagja van a konferenciának" + +#: page.conferences.php:237 +msgid "Allow Menu:" +msgstr "Elfogadva menÃŒ:" + +#: page.conferences.php:237 +msgid "Present Menu (user or admin) when '*' is received ('send' to menu)" +msgstr "menÃŒ megmutatása (felhasználónak vagy adminnak) amikor '*' érkezik" + +#: page.conferences.php:250 +msgid "Record Conference:" +msgstr "Konferencia rögzítése:" + +#: page.conferences.php:250 +msgid "Record the conference call" +msgstr "Rögzíti a teljes konferenciabeszélgetést" + +#: page.conferences.php:268 +msgid "Submit Changes" +msgstr "" + +#: page.conferences.php:282 +msgid "Please enter a valid Conference Number" +msgstr "" + +#: page.conferences.php:283 +msgid "Please enter a valid Conference Name" +msgstr "" + +#: page.conferences.php:284 +msgid "" +"You must set an admin PIN for the Conference Leader when selecting the " +"leader wait option" +msgstr "" + + + + Index: /modules/branches/2.6/conferences/i18n/it_IT/LC_MESSAGES/conferences.po =================================================================== --- /modules/branches/2.6/conferences/i18n/it_IT/LC_MESSAGES/conferences.po (revision 5363) +++ /modules/branches/2.6/conferences/i18n/it_IT/LC_MESSAGES/conferences.po (revision 5363) @@ -0,0 +1,175 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: 1.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2007-01-25 22:30+0100\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Francesco Romano\n" +"Language-Team: Italian\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=ISO-8859-1\n" +"Content-Transfer-Encoding: 8bit\n" + +#: page.conferences.php:22 +msgid "Warning! Extension" +msgstr "Attenzione!" + +#: page.conferences.php:22 +msgid "is not allowed for your account." +msgstr "Non hai i permessi." + +#: page.conferences.php:56 page.conferences.php:87 page.conferences.php:94 +msgid "Add Conference" +msgstr "Aggiungi Conferenza" + +#: page.conferences.php:70 +msgid "Conference" +msgstr "Conferenza" + +#: page.conferences.php:70 +msgid "deleted" +msgstr "eliminata" + +#: page.conferences.php:84 +msgid "Conference:" +msgstr "Conferenza:" + +#: page.conferences.php:85 +msgid "Delete Conference" +msgstr "Elimina Conferenza" + +#: page.conferences.php:94 +msgid "Edit Conference" +msgstr "Modifica Conferenza" + +#: page.conferences.php:99 +msgid "conference number:" +msgstr "Conferenza numero:" + +#: page.conferences.php:99 +msgid "Use this number to dial into the conference." +msgstr "Utilizzare questo numero per entrare nella conferenza." + +#: page.conferences.php:104 +msgid "conference name:" +msgstr "Conferenza nome:" + +#: page.conferences.php:104 +msgid "Give this conference a brief name to help you identify it." +msgstr "Dare alla conferenza un nome breve per una facile identificazione." + +#: page.conferences.php:108 +msgid "user PIN:" +msgstr "PIN utente:" + +#: page.conferences.php:108 +msgid "" +"You can require callers to enter a password before they can enter this " +"conference.

This setting is optional.

If either PIN is " +"entered, the user will be prompted to enter a PIN." +msgstr "Si può richiedere ai chiamanti di digitare una password prima di entrare in conferenza.

Questa impostazione è opzionale.

Se nessun PIN è stato inserito il sistema richiederà di digitarlo." + +#: page.conferences.php:112 +msgid "admin PIN:" +msgstr "PIN amministratore:" + +#: page.conferences.php:112 +msgid "" +"Enter a PIN number for the admin user.

This setting is optional " +"unless the 'leader wait' option is in use, then this PIN will identify the " +"leader." +msgstr "Inserire il numero PIN per l'utente amministratore.

Questa impostazione è opzionale fino a quando non si seleziona 'Attendere amministratore' che lo indentificherà tramite questo PIN." + +#: page.conferences.php:121 +msgid "Conference Options" +msgstr "Opzioni Conferenza" + +#: page.conferences.php:124 page.conferences.php:142 +msgid "join message:" +msgstr "Messaggio di ingresso:" + +#: page.conferences.php:124 +msgid "" +"Message to be played to the caller before joining the conference.

To " +"add additional recordings please use the \"System Recordings\" MENU to the " +"left" +msgstr "Selezionare il messaggio da riprodurre ai chiamanti prima di entrate in conferenza.

Bisogna installare e attivare il modulo \"Registrazioni di Sistema\" prima di modificare questa opzione." + +#: page.conferences.php:130 +msgid "None" +msgstr "Nessuno" + +#: page.conferences.php:142 +msgid "" +"Message to be played to the caller before joining the conference.

You " +"must install and enable the \"Systems Recordings\" Module to edit this option" +msgstr "Selezionare il messaggio da riprodurre ai chiamanti prima di entrate in conferenza.

Bisogna installare e attivare il modulo \"Registrazioni di Sistema\" prima di modificare questa opzione." + +#: page.conferences.php:152 +msgid "leader wait:" +msgstr "Attendere l'amministratore:" + +#: page.conferences.php:152 +msgid "" +"wait until the conference leader (admin user) arrives before starting the " +"conference" +msgstr "Attende l'arrivo dell'amministratore prima di iniziare la conferenza" + +#: page.conferences.php:157 page.conferences.php:169 page.conferences.php:181 +#: page.conferences.php:193 page.conferences.php:205 page.conferences.php:217 +msgid "No" +msgstr "No" + +#: page.conferences.php:158 page.conferences.php:170 page.conferences.php:182 +#: page.conferences.php:194 page.conferences.php:206 page.conferences.php:218 +msgid "Yes" +msgstr "Si" + +#: page.conferences.php:164 +msgid "quiet mode:" +msgstr "Modalità silenziosa:" + +#: page.conferences.php:164 +msgid "quiet mode (do not play enter/leave sounds)" +msgstr "Attiva la modalità silenziosa, non riproduce i suoni quando si entra o esce dalla conferenza" + +#: page.conferences.php:176 +msgid "user count:" +msgstr "Conteggio utente:" + +#: page.conferences.php:176 +msgid "announce user(s) count on joining conference" +msgstr "Annuncia il conteggio degli utenti quando entrano in conferenza" + +#: page.conferences.php:188 +msgid "user join/leave:" +msgstr "Ingresso/uscita utenti:" + +#: page.conferences.php:188 +msgid "announce user join/leave" +msgstr "Annucia l'ingresso/uscita degli utenti" + +#: page.conferences.php:200 +msgid "music on hold:" +msgstr "Musica di Attesa" + +#: page.conferences.php:200 +msgid "enable music on hold when the conference has a single caller" +msgstr "Attiva la Musica di Attesa quando c'è solo un utente nella conferenza" + +#: page.conferences.php:212 +msgid "allow menu:" +msgstr "Permetti menu:" + +#: page.conferences.php:212 +msgid "present menu (user or admin) when '*' is received ('send' to menu)" +msgstr "Presenta il menu (utente o amministratore) quando si preme '*' ('invia' al menu)" + +msgid "Submit Changes" +msgstr "Applica" Index: /modules/branches/2.6/conferences/i18n/conferences.pot =================================================================== --- /modules/branches/2.6/conferences/i18n/conferences.pot (revision 6939) +++ /modules/branches/2.6/conferences/i18n/conferences.pot (revision 6939) @@ -0,0 +1,260 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2008-10-05 10:59+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" + +#: functions.inc.php:56 +#, php-format +msgid "Conference Room %s : %s" +msgstr "" + +#: functions.inc.php:75 +#, php-format +msgid "Conference: %s" +msgstr "" + +#: functions.inc.php:194 +msgid "Conference: " +msgstr "" + +#: install.php:35 +msgid "Checking if recordings need migration.." +msgstr "" + +#: install.php:41 +msgid "migrating" +msgstr "" + +#: install.php:42 +msgid "adding joinmsg_id field.." +msgstr "" + +#: install.php:46 install.php:58 install.php:74 +msgid "fatal error" +msgstr "" + +#: install.php:49 install.php:88 +msgid "ok" +msgstr "" + +#: install.php:54 +msgid "migrate to recording ids.." +msgstr "" + +#: install.php:78 +#, php-format +msgid "migrated %s entries" +msgstr "" + +#: install.php:82 +msgid "dropping joinmsg field.." +msgstr "" + +#: install.php:86 +msgid "no joinmsg field???" +msgstr "" + +#: install.php:92 +msgid "already migrated" +msgstr "" + +#: page.conferences.php:24 +msgid "Warning! Extension" +msgstr "" + +#: page.conferences.php:24 +msgid "is not allowed for your account." +msgstr "" + +#: page.conferences.php:64 page.conferences.php:115 page.conferences.php:126 +msgid "Add Conference" +msgstr "" + +#: page.conferences.php:78 +msgid "Conference" +msgstr "" + +#: page.conferences.php:78 +msgid "deleted" +msgstr "" + +#: page.conferences.php:98 +msgid "Conference:" +msgstr "" + +#: page.conferences.php:101 +#, php-format +msgid "Delete Conference %s" +msgstr "" + +#: page.conferences.php:118 +msgid "Conflicting Extensions" +msgstr "" + +#: page.conferences.php:126 +msgid "Edit Conference" +msgstr "" + +#: page.conferences.php:131 +msgid "Conference Number:" +msgstr "" + +#: page.conferences.php:131 +msgid "Use this number to dial into the conference." +msgstr "" + +#: page.conferences.php:136 +msgid "Conference Name:" +msgstr "" + +#: page.conferences.php:136 +msgid "Give this conference a brief name to help you identify it." +msgstr "" + +#: page.conferences.php:140 +msgid "User PIN:" +msgstr "" + +#: page.conferences.php:140 +msgid "" +"You can require callers to enter a password before they can enter this " +"conference.

This setting is optional.

If either PIN is " +"entered, the user will be prompted to enter a PIN." +msgstr "" + +#: page.conferences.php:144 +msgid "Admin PIN:" +msgstr "" + +#: page.conferences.php:144 +msgid "" +"Enter a PIN number for the admin user.

This setting is optional " +"unless the 'leader wait' option is in use, then this PIN will identify the " +"leader." +msgstr "" + +#: page.conferences.php:150 +msgid "Conference Options" +msgstr "" + +#: page.conferences.php:153 page.conferences.php:170 +msgid "Join Message:" +msgstr "" + +#: page.conferences.php:153 +msgid "" +"Message to be played to the caller before joining the conference.

To " +"add additional recordings please use the \"System Recordings\" MENU to the " +"left" +msgstr "" + +#: page.conferences.php:158 +msgid "None" +msgstr "" + +#: page.conferences.php:170 +msgid "" +"Message to be played to the caller before joining the conference.

You " +"must install and enable the \"Systems Recordings\" Module to edit this option" +msgstr "" + +#: page.conferences.php:177 +msgid "Leader Wait:" +msgstr "" + +#: page.conferences.php:177 +msgid "" +"Wait until the conference leader (admin user) arrives before starting the " +"conference" +msgstr "" + +#: page.conferences.php:182 page.conferences.php:194 page.conferences.php:206 +#: page.conferences.php:218 page.conferences.php:230 page.conferences.php:242 +#: page.conferences.php:255 +msgid "No" +msgstr "" + +#: page.conferences.php:183 page.conferences.php:195 page.conferences.php:207 +#: page.conferences.php:219 page.conferences.php:231 page.conferences.php:243 +#: page.conferences.php:256 +msgid "Yes" +msgstr "" + +#: page.conferences.php:189 +msgid "Quiet Mode:" +msgstr "" + +#: page.conferences.php:189 +msgid "Quiet mode (do not play enter/leave sounds)" +msgstr "" + +#: page.conferences.php:201 +msgid "User Count:" +msgstr "" + +#: page.conferences.php:201 +msgid "Announce user(s) count on joining conference" +msgstr "" + +#: page.conferences.php:213 +msgid "User join/leave:" +msgstr "" + +#: page.conferences.php:213 +msgid "Announce user join/leave" +msgstr "" + +#: page.conferences.php:225 +msgid "Music on Hold:" +msgstr "" + +#: page.conferences.php:225 +msgid "Enable Music On Hold when the conference has a single caller" +msgstr "" + +#: page.conferences.php:237 +msgid "Allow Menu:" +msgstr "" + +#: page.conferences.php:237 +msgid "Present Menu (user or admin) when '*' is received ('send' to menu)" +msgstr "" + +#: page.conferences.php:250 +msgid "Record Conference:" +msgstr "" + +#: page.conferences.php:250 +msgid "Record the conference call" +msgstr "" + +#: page.conferences.php:268 +msgid "Submit Changes" +msgstr "" + +#: page.conferences.php:282 +msgid "Please enter a valid Conference Number" +msgstr "" + +#: page.conferences.php:283 +msgid "Please enter a valid Conference Name" +msgstr "" + +#: page.conferences.php:284 +msgid "" +"You must set an admin PIN for the Conference Leader when selecting the " +"leader wait option" +msgstr "" Index: /modules/branches/2.6/conferences/i18n/ru_RU/LC_MESSAGES/conferences.po =================================================================== --- /modules/branches/2.6/conferences/i18n/ru_RU/LC_MESSAGES/conferences.po (revision 7044) +++ /modules/branches/2.6/conferences/i18n/ru_RU/LC_MESSAGES/conferences.po (revision 7044) @@ -0,0 +1,195 @@ +# Russian freePBX ver. translation +# Copyright (c) 2006-2008 PostMet Corporation +# This file is distributed under the same license as the freePBX package. +# Alexander Kozyrev , Sergey Nikolayev , 2006-2008. +# +# žáßÞÛì×ÞÒÐâì iconv amp.new -f UTF-8 -t ISO-8859-5 -o amp.po +# fuzzy +msgid "" +msgstr "" +"Project-Id-Version: 1.3\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2007-04-19 21:45+0100\n" +"PO-Revision-Date: 2008-01-16 16:38+0100\n" +"Last-Translator: Alexander Kozyrev \n" +"Language-Team: Russian \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=iso-8859-5\n" +"Content-Transfer-Encoding: 8bit\n" + +#: page.conferences.php:22 +msgid "Warning! Extension" +msgstr "²ÝØÜÐÝØÕ! ²ÝãâàÕÝÝØÙ ÝÞÜÕà" + +#: page.conferences.php:22 +msgid "is not allowed for your account." +msgstr "ÝÕ àÐ×àÕèñÝ Ú ØáßÞÛì×ÞÒÐÝØî Ò Ò íâÞÜ ÐÚÚÐãÝâÕ." + +#: page.conferences.php:56 page.conferences.php:87 page.conferences.php:94 +msgid "Add Conference" +msgstr "ŽÞÑÐÒØâì ÚÞÝäÕàÕÝæØî" + +#: page.conferences.php:70 +msgid "Conference" +msgstr "ºÞÝäÕàÕÝæØï" + +#: page.conferences.php:70 +msgid "deleted" +msgstr "ãÔÐÛÕÝÞ" + +#: page.conferences.php:84 +msgid "Conference:" +msgstr "ºÞÝäÕàÕÝæØï:" + +#: page.conferences.php:85 +msgid "Delete Conference" +msgstr "ÃÔÐÛØâì ÚÞÝäÕàÕÝæØî" + +#: page.conferences.php:94 +msgid "Edit Conference" +msgstr "ž×ÜÕÝØâì ÚÞÝäÕàÕÝæØî" + +#: page.conferences.php:99 +msgid "Conference Number:" +msgstr "œÞÜÕà ÚÞÝäÕàÕÝæØØ:" + +#: page.conferences.php:99 +msgid "Use this number to dial into the conference." +msgstr "ÇâÞÑë ßÞ×ÒÞÝØâì Ò ÚÞÝäÕàÕÝæØî ØáßÞÛì×ãÙâÕ íâÞâ ÝÞÜÕà." + +#: page.conferences.php:104 +msgid "Conference Name:" +msgstr "œÐ×ÒÐÝØÕ ÚÞÝäÕàÕÝæØØ:" + +#: page.conferences.php:104 +msgid "Give this conference a brief name to help you identify it." +msgstr "¿àØáÒÞÙâÕ ÚÞÝäÕàÕÝæØØ ÚÞàÞâÚÞÕ ØÜï ÔÛï ØÔÕÝâØäØÚÐæØØ." + +#: page.conferences.php:108 +msgid "User PIN:" +msgstr "PIN ßÞÛì×ÞÒÐâÕÛï:" + +#: page.conferences.php:108 +msgid "" +"You can require callers to enter a password before they can enter this " +"conference.

This setting is optional.

If either PIN is " +"entered, the user will be prompted to enter a PIN." +msgstr "" +"ŒÞÖÝÞ âàÕÑÞÒÐâì ÒÒÕáâØ ßÐàÞÛì ÔÛï ÒåÞÔï ßÞÛì×ÞÒÐâÕÛÕÙ Ò ÚÞÝäÕàÕÝæØî.

" +"ÍâÞ ÝÕÞÑï×ÐâÕÛìÝëÙ ßÐàÐÜÕâà.

µáÛØ ãÚÐ×ÐÝ PIN Ò íâÞÜ ßÞÛÕ, ßÞÛì×ÞÒÐâÕÛî " +"ÑãÔÕâ ßàÕÔÛÞÖÕÝÞ ÝÐÑàÐâì ÕÓÞ." + +#: page.conferences.php:112 +msgid "Admin PIN:" +msgstr "PIN ÐÔÜØÝØáâàÐâÞàÐ:" + +#: page.conferences.php:112 +msgid "" +"Enter a PIN number for the admin user.

This setting is optional " +"unless the 'leader wait' option is in use, then this PIN will identify the " +"leader." +msgstr "" +"ÃÚÐÖØâÕ PIN ÔÛï ÐÔÜØÝØáâàÐâÞàÐ.

ÍâÞ ÝÕÞÑï×ÐâÕÛìÝëÙ ßÐàÐÜÕâà, ÕáÛØ ØáßÞÛì×ãÕâáï " +"ÞßæØï 'ÛØÔÕà ÖÔñâ', âÞ íâÞâ PIN ØÔÕÝâØäØæØàãÕâ ÛØÔÕàÐ." + +#: page.conferences.php:121 +msgid "Conference Options" +msgstr "ŸßæØØ ÚÞÝäÕàÕÝæØØ" + +#: page.conferences.php:124 page.conferences.php:142 +msgid "Join Message:" +msgstr "ÁÞÞÑéÕÝØÕ Þ ßÞÔáÞÕÔØÝÕÝØØ?" + +#: page.conferences.php:124 +msgid "" +"Message to be played to the caller before joining the conference.

To " +"add additional recordings please use the \"System Recordings\" MENU to the " +"left" +msgstr "" +"¿àØ ßÞÔáÞÕÔØÝÕÝØØ Ú ÚÞÝäÕàÕÝæØØ ßÞÛì×ÞÒÐâÕÛî ÑãÔÕâ ÒÞáßàÞØ×ÒÕÔÕÝÞ íâÞ áÞÞÑéÕÝØÕ." +"

ÇâÞÑë áÞ×ÔÐâì áÞÞÑéÕÝØÕ ÒÞáßÞì×ãÙâÕáì áÕÚæØÕÙ ·Ðߨáì áÞÞÑéÕÝØÙ Ò ÜÕÝî áÛÕÒÐ." + +#: page.conferences.php:130 +msgid "None" +msgstr "œÕâ" + +#: page.conferences.php:142 +msgid "" +"Message to be played to the caller before joining the conference.

You " +"must install and enable the \"Systems Recordings\" Module to edit this option" +msgstr "" +"¿àØ ßÞÔáÞÕÔØÝÕÝØØ Ú ÚÞÝäÕàÕÝæØØ ßÞÛì×ÞÒÐâÕÛî ÑãÔÕâ ÒÞáßàÞØ×ÒÕÔÕÝÞ áÞÞÑéÕÝØÕ." +"

œÕÞÑåÞÔØÜÞ ØÝáâÐÛÛØàÞÒÐâì Ø ÐÚâØÒØàÞÒÐâì ÜÞÔãÛì '·Ðߨáì áÞÞÑéÕÝØÙ' ÔÛï Ø×ÜÕÝÕÝØï " +"íâÞÙ ÞßæØØ." + +#: page.conferences.php:152 +msgid "Leader Wait:" +msgstr "¶ÔÐâì ÞàÓÐÝØ×ÐâÞàÐ?" + +#: page.conferences.php:175 +msgid "" +"Wait until the conference leader (admin user) arrives before starting the " +"conference" +msgstr "" +"¶ÔÐâì ÞàÓÐÝØ×ÐâÞàÐ ÚÞÝäÕàÕÝæØØ (ßÞÛì×ÞÒÐâÕÛì ÐÔÜØÝØáâàÐâÞà) ßÞÚÐ ÞÝ ÝÕ ßÞÔáÞÕÔØÝØâáï, çâÞÑë " +"ÝÐçÐâì ÚÞÝäÕàÕÝæØî." + +#: page.conferences.php:157 page.conferences.php:169 page.conferences.php:181 +#: page.conferences.php:193 page.conferences.php:205 page.conferences.php:217 +msgid "No" +msgstr "œÕâ" + +#: page.conferences.php:158 page.conferences.php:170 page.conferences.php:182 +#: page.conferences.php:194 page.conferences.php:206 page.conferences.php:218 +msgid "Yes" +msgstr "ŽÐ" + +#: page.conferences.php:164 +msgid "Quiet Mode:" +msgstr "ÂØåØÙ àÕÖØÜ?" + +#: page.conferences.php:164 +msgid "Quiet mode (do not play enter/leave sounds)" +msgstr "" +"ÂØåØÙ àÕÖØÜ (ÝÕ ÒÞáßàÞØ×ÒÞÔïâáï áÞÞÑéÕÝØï Þ âÞÜ ÚâÞ ÒÞèñÛ ØÛØ ÒëèÕÛ Ø× ÚÞÝäÕàÕÝæØØ)" + +#: page.conferences.php:176 +msgid "User Count:" +msgstr "ºÞÛØçÕáâÒÞ ãçÐáâÝØÚÞÒ?" + +#: page.conferences.php:176 +msgid "Announce user(s) count on joining conference" +msgstr "°ÝÞÝáØàÞÒÐâì ÚÞÛØçÕáâÒÞ ãçÐáâÝØÚÞÒ ÚÞÝäÕàÕÝæØØ ßàØ ßÞÔáÞÕÔØÝÕÝØØ?" + +#: page.conferences.php:188 +msgid "User join/leave:" +msgstr "ÃçÐáâÝØÚ ßÞÔáÞÕÔØÝØÛáï/ÞâÚÛîçØÛáï?" + +#: page.conferences.php:188 +msgid "Announce user join/leave" +msgstr "°ÝÞÝáØàÞÒÐâì ßÞÔáÞÕÔØÝÕÝØÕ/ÞâÚÛîçÕÝØÕ ãçÐáâÝØÚÞÒ?" + +#: page.conferences.php:200 +msgid "Music on Hold:" +msgstr "Œã×ëÚÐ Ò ÞÖØÔÐÝØØ?" + +#: page.conferences.php:200 +msgid "Enable Music On Hold when the conference has a single caller" +msgstr "žáßÞÛì×ÞÒÐâì Üã×ëÚã Ò ÞÖØÔÐÝØØ, ÕáÛØ Ò ÚÞÝäÕàÕÝæØØ ßÞÚÐ ÞÔØÝ ãçÐáâÝØÚ?" + +#: page.conferences.php:212 +msgid "Allow Menu:" +msgstr "ÀÐ×àÕèØâì ÜÕÝî?" + +#: page.conferences.php:212 +msgid "Present Menu (user or admin) when '*' is received ('send' to menu)" +msgstr "¿àÕÔÞáâÐÒØâì ÔÞáâãß Ò ÜÕÝî (ãçÐáâÝØÚã ØÛØ ÐÔÜØÝØáâàÐâÞàã) ßàØ ÝÐÖÐâØØ '*'?" + +msgid "Record Conference:" +msgstr "·ÐߨáëÒÐâì ÚÞÝäÕàÕÝæØî?" + +msgid "Record the conference call" +msgstr "·ÐߨáëÒÐâì áÞÔÕàÖÐÝØÕ ÚÞÝäÕàÕÝæØØ?" + +msgid "Submit Changes" +msgstr "¿àØÜÕÝØâì Ø×ÜÕÝÕÝØï" Index: /modules/branches/2.6/conferences/install.sql =================================================================== --- /modules/branches/2.6/conferences/install.sql (revision 1081) +++ /modules/branches/2.6/conferences/install.sql (revision 1081) @@ -0,0 +1,4 @@ + +CREATE TABLE IF NOT EXISTS `meetme` ( `exten` VARCHAR( 50 ) NOT NULL , `options` VARCHAR( 15 ) , `userpin` VARCHAR( 50 ) , `adminpin` VARCHAR( 50 ) , `description` VARCHAR( 50 ) , `joinmsg` VARCHAR( 255 ) ); + + Index: /modules/branches/2.6/conferences/module.xml =================================================================== --- /modules/branches/2.6/conferences/module.xml (revision 7018) +++ /modules/branches/2.6/conferences/module.xml (revision 7018) @@ -0,0 +1,38 @@ + + conferences + Conferences + 2.5.1.5 + setup + Internal Options & Configuration + Allow creation of conference rooms (meet-me) where multiple people can talk together. + + *2.5.1.5* localization strings enclosed + *2.5.1.4* #3237 + *2.5.1.3* #3192 set dir for recordings, localization cleanup and Swedish + *2.5.1.2* #3135 variable initialization + *2.5.1.1* #3087 add hook to module code + *2.5.1* #2064 Migrate recordings to recording ids + *2.5.0* #2845, added blf hints, added delete and add icons + *2.4.0.2* #2604, #2843 fix mal-formed html tags, Russian Translation + *2.4.0.1* added depends on 2.4.0 + *2.4.0* #2158 add recording option, add support for Extension and Destination Registries, it translations + *1.2.2* don't ask for name confirmation when recording names on Asterisk 1.3 (new option I replaces i) + *1.2.1.3* move Macro(user-callerid) to be called with each conf to accomodate future language settings + *1.2.1.2* add call to Macro(user-callerid) to get proper CID in Meetme Conference + *1.2.1.1* bump for rc1 + *1.2.1* changed syntax error in meetme_additional.conf form '|' to ',' separator + *1.2* Fixed raising asterisk error on empty dialstatus #1708 + *1.1.2* Add he_IL translation + *1.1.1* Updated for 2.2.0RC1 + *1.1* First release for FreePBX 2.2 - Fixed compatibility issue with new UI + + + 2.5.0alpha1 + recordings ge 3.3.8 + + + Conferences + + release/2.5/conferences-2.5.1.5.tgz + b8ae0551f3bd4655023e5ae9d3596e17 + Index: /modules/branches/2.6/conferences/functions.inc.php =================================================================== --- /modules/branches/2.6/conferences/functions.inc.php (revision 6939) +++ /modules/branches/2.6/conferences/functions.inc.php (revision 6939) @@ -0,0 +1,232 @@ +_meetmes[$room] = $pin; + } + // return the output that goes in the file + function generateConf() { + $output = ""; + if (isset($this->_meetmes) && is_array($this->_meetmes)) { + foreach (array_keys($this->_meetmes) as $meetme) { + $output .= 'conf => '.$meetme.",".$this->_meetmes[$meetme]."\n"; + } + } + return $output; + } +} + +// returns a associative arrays with keys 'destination' and 'description' +function conferences_destinations() { + //get the list of meetmes + $results = conferences_list(); + + // return an associative array with destination and description + if (isset($results)) { + foreach($results as $result){ + $extens[] = array('destination' => 'ext-meetme,'.$result['0'].',1', 'description' => $result['1']." <".$result['0'].">"); + } + return $extens; + } else { + return null; + } +} + +function conferences_getdest($exten) { + return array('ext-meetme,'.$exten.',1'); +} + +function conferences_getdestinfo($dest) { + global $active_modules; + + if (substr(trim($dest),0,11) == 'ext-meetme,') { + $exten = explode(',',$dest); + $exten = $exten[1]; + $thisexten = conferences_get($exten); + if (empty($thisexten)) { + return array(); + } else { + //$type = isset($active_modules['announcement']['type'])?$active_modules['announcement']['type']:'setup'; + return array('description' => sprintf(_("Conference Room %s : %s"),$exten,$thisexten['description']), + 'edit_url' => 'config.php?display=conferences&extdisplay='.urlencode($exten), + ); + } + } else { + return false; + } +} + +function conferences_recordings_usage($recording_id) { + global $active_modules; + + $results = sql("SELECT `exten`, `description` FROM `meetme` WHERE `joinmsg_id` = '$recording_id'","getAll",DB_FETCHMODE_ASSOC); + if (empty($results)) { + return array(); + } else { + foreach ($results as $result) { + $usage_arr[] = array( + 'url_query' => 'config.php?display=conferences&extdisplay='.urlencode($result['exten']), + 'description' => sprintf(_("Conference: %s"),$result['description']), + ); + } + return $usage_arr; + } +} + +/* Generates dialplan for conferences + We call this with retrieve_conf +*/ +function conferences_get_config($engine) { + global $ext; // is this the best way to pass this? + global $conferences_conf; + global $version; + global $amp_conf; + switch($engine) { + case "asterisk": + $ext->addInclude('from-internal-additional','ext-meetme'); + $contextname = 'ext-meetme'; + if(is_array($conflist = conferences_list())) { + + // Start the conference + $ext->add($contextname, 'STARTMEETME', '', new ext_meetme('${MEETME_ROOMNUM}','${MEETME_OPTS}','${PIN}')); + $ext->add($contextname, 'STARTMEETME', '', new ext_hangup('')); + + // hangup for whole context + $ext->add($contextname, 'h', '', new ext_hangup('')); + + foreach($conflist as $item) { + $room = conferences_get(ltrim($item['0'])); + + $roomnum = ltrim($item['0']); + $roomoptions = $room['options']; + if (version_compare($version, "1.4",">=")) { + $roomoptions = str_replace('i','I',$roomoptions); + } + $roomuserpin = $room['userpin']; + $roomadminpin = $room['adminpin']; + + if (isset($room['joinmsg_id']) && $room['joinmsg_id'] != '') { + $roomjoinmsg = recordings_get_file($room['joinmsg_id']); + } else { + $roomjoinmsg = ''; + } + + // Add optional hint + if ($amp_conf['USEDEVSTATE']) { + $ext->addHint($contextname, $roomnum, "MeetMe:".$roomnum); + } + // entry point + $ext->add($contextname, $roomnum, '', new ext_macro('user-callerid')); + $ext->add($contextname, $roomnum, '', new ext_setvar('MEETME_ROOMNUM',$roomnum)); + if (strstr($room['options'],'r') !== false) { + $ext->add($contextname, $roomnum, '', new ext_setvar('MEETME_RECORDINGFILE','${ASTSPOOLDIR}/monitor/meetme-conf-rec-${MEETME_ROOMNUM}-${UNIQUEID}')); + } + $ext->add($contextname, $roomnum, '', new ext_gotoif('$["${DIALSTATUS}" = "ANSWER"]',($roomuserpin == '' && $roomadminpin == '' ? 'USER' : 'READPIN'))); + $ext->add($contextname, $roomnum, '', new ext_answer('')); + $ext->add($contextname, $roomnum, '', new ext_wait(1)); + + // Deal with PINs -- if exist + if ($roomuserpin != '' || $roomadminpin != '') { + $ext->add($contextname, $roomnum, '', new ext_setvar('PINCOUNT','0')); + $ext->add($contextname, $roomnum, 'READPIN', new ext_read('PIN','enter-conf-pin-number')); + + // userpin -- must do always, otherwise if there is just an adminpin + // there would be no way to get to the conference ! + $ext->add($contextname, $roomnum, '', new ext_gotoif('$[x${PIN} = x'.$roomuserpin.']','USER')); + + // admin pin -- exists + if ($roomadminpin != '') { + $ext->add($contextname, $roomnum, '', new ext_gotoif('$[x${PIN} = x'.$roomadminpin.']','ADMIN')); + } + + // pin invalid + $ext->add($contextname, $roomnum, '', new ext_setvar('PINCOUNT','$[${PINCOUNT}+1]')); + $ext->add($contextname, $roomnum, '', new ext_gotoif('$[${PINCOUNT}>3]', "h")); + $ext->add($contextname, $roomnum, '', new ext_playback('conf-invalidpin')); + $ext->add($contextname, $roomnum, '', new ext_goto('READPIN')); + + // admin mode -- only valid if there is an admin pin + if ($roomadminpin != '') { + $ext->add($contextname, $roomnum, 'ADMIN', new ext_setvar('MEETME_OPTS','aA'.$roomoptions)); + if ($roomjoinmsg != '') { // play joining message if one defined + $ext->add($contextname, $roomnum, '', new ext_playback($roomjoinmsg)); + } + $ext->add($contextname, $roomnum, '', new ext_goto('STARTMEETME,1')); + } + } + + // user mode + $ext->add($contextname, $roomnum, 'USER', new ext_setvar('MEETME_OPTS',$roomoptions)); + if ($roomjoinmsg != '') { // play joining message if one defined + $ext->add($contextname, $roomnum, '', new ext_playback($roomjoinmsg)); + } + $ext->add($contextname, $roomnum, '', new ext_goto('STARTMEETME,1')); + + // add meetme config + $conferences_conf->addMeetme($room['exten'],$room['userpin']); + } + } + + break; + } +} + +function conferences_check_extensions($exten=true) { + $extenlist = array(); + if (is_array($exten) && empty($exten)) { + return $extenlist; + } + $sql = "SELECT exten, description FROM meetme "; + if (is_array($exten)) { + $sql .= "WHERE exten in ('".implode("','",$exten)."')"; + } + $sql .= " ORDER BY exten"; + $results = sql($sql,"getAll",DB_FETCHMODE_ASSOC); + + foreach ($results as $result) { + $thisexten = $result['exten']; + $extenlist[$thisexten]['description'] = _("Conference: ").$result['description']; + $extenlist[$thisexten]['status'] = 'INUSE'; + $extenlist[$thisexten]['edit_url'] = 'config.php?display=conferences&extdisplay='.urlencode($thisexten); + } + return $extenlist; +} + +//get the existing meetme extensions +function conferences_list() { + $results = sql("SELECT exten,description FROM meetme ORDER BY exten","getAll",DB_FETCHMODE_ASSOC); + foreach($results as $result){ + // check to see if we are in-range for the current AMP User. + if (isset($result['exten']) && checkRange($result['exten'])){ + // return this item's dialplan destination, and the description + $extens[] = array($result['exten'],$result['description']); + } + } + if (isset($extens)) { + return $extens; + } else { + return null; + } +} + +function conferences_get($account){ + //get all the variables for the meetme + $results = sql("SELECT exten,options,userpin,adminpin,description,joinmsg_id FROM meetme WHERE exten = '$account'","getRow",DB_FETCHMODE_ASSOC); + return $results; +} + +function conferences_del($account){ + $results = sql("DELETE FROM meetme WHERE exten = \"$account\"","query"); +} + +function conferences_add($account,$name,$userpin,$adminpin,$options,$joinmsg_id=null){ + global $active_modules; + $results = sql("INSERT INTO meetme (exten,description,userpin,adminpin,options,joinmsg_id) values (\"$account\",\"$name\",\"$userpin\",\"$adminpin\",\"$options\",\"$joinmsg_id\")"); +} +?> Index: /modules/branches/2.6/conferences/uninstall.sql =================================================================== --- /modules/branches/2.6/conferences/uninstall.sql (revision 842) +++ /modules/branches/2.6/conferences/uninstall.sql (revision 842) @@ -0,0 +1,2 @@ + +DROP TABLE IF EXISTS meetme; Index: /modules/branches/2.6/conferences/page.conferences.php =================================================================== --- /modules/branches/2.6/conferences/page.conferences.php (revision 6853) +++ /modules/branches/2.6/conferences/page.conferences.php (revision 6853) @@ -0,0 +1,320 @@ +javascript:alert('"._("Warning! Extension")." $account "._("is not allowed for your account.")."');"; +} else { + + //if submitting form, update database + switch ($action) { + case "add": + + $conflict_url = array(); + $usage_arr = framework_check_extension_usage($account); + if (!empty($usage_arr)) { + $conflict_url = framework_display_extension_usage_alert($usage_arr); + } elseif (conferences_add($account,$_REQUEST['name'],$_REQUEST['userpin'],$_REQUEST['adminpin'],$_REQUEST['options'],$_REQUEST['joinmsg_id']) !== false) { + needreload(); + redirect_standard(); + } + break; + case "delete": + conferences_del($extdisplay); + needreload(); + redirect_standard(); + break; + case "edit": //just delete and re-add + conferences_del($account); + conferences_add($account,$_REQUEST['name'],$_REQUEST['userpin'],$_REQUEST['adminpin'],$_REQUEST['options'],$_REQUEST['joinmsg_id']); + needreload(); + redirect_standard('extdisplay'); + break; + } +} + +//get meetme rooms +//this function needs to be available to other modules (those that use goto destinations) +//therefore we put it in globalfunctions.php +$meetmes = conferences_list(); +?> + +
+ + +
+ + +
+

'._("Conference").' '.$extdisplay.' '._("deleted").'!









'; +} else { + if ($extdisplay){ + //get details for this meetme + $thisMeetme = conferences_get($extdisplay); + $options = $thisMeetme['options']; + $userpin = $thisMeetme['userpin']; + $adminpin = $thisMeetme['adminpin']; + $description = $thisMeetme['description']; + $joinmsg_id = $thisMeetme['joinmsg_id']; + } else { + $options = ""; + $userpin = ""; + $adminpin = ""; + $description = ""; + $joinmsg_id = ""; + } + +?> + +

+ '.$tlabel.''; +?> +
+ + : + + + +

+"._("Conflicting Extensions").""; + echo implode('
',$conflict_url); + } +?> +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +


This setting is optional.

If either PIN is entered, the user will be prompted to enter a PIN.")?>

This setting is optional unless the 'leader wait' option is in use, then this PIN will identify the leader.")?>



To add additional recordings please use the \"System Recordings\" MENU to the left")?>
+ +

You must install and enable the \"Systems Recordings\" Module to edit this option")?>
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+hookHtml; +?> +
" tabindex="">
+ +
+ Index: /modules/branches/2.6/conferences/install.php =================================================================== --- /modules/branches/2.6/conferences/install.php (revision 6720) +++ /modules/branches/2.6/conferences/install.php (revision 6720) @@ -0,0 +1,94 @@ +"; + } +} + +if (! function_exists("outn")) { + function outn($text) { + echo $text; + } +} + +global $db; +global $amp_conf; + +$sql = " +CREATE TABLE IF NOT EXISTS `meetme` +( + `exten` VARCHAR( 50 ) NOT NULL , + `options` VARCHAR( 15 ) , + `userpin` VARCHAR( 50 ) , + `adminpin` VARCHAR( 50 ) , + `description` VARCHAR( 50 ) , + `joinmsg_id` INTEGER +) +"; +$check = $db->query($sql); +if(DB::IsError($check)) { + die_freepbx("Can not create meetme table"); +} + +// Version 2.5 migrate to recording ids +// +outn(_("Checking if recordings need migration..")); +$sql = "SELECT joinmsg_id FROM meetme"; +$check = $db->getRow($sql, DB_FETCHMODE_ASSOC); +if(DB::IsError($check)) { + // Add recording_id field + // + out(_("migrating")); + outn(_("adding joinmsg_id field..")); + $sql = "ALTER TABLE meetme ADD joinmsg_id INTEGER"; + $result = $db->query($sql); + if(DB::IsError($result)) { + out(_("fatal error")); + die_freepbx($result->getDebugInfo()); + } else { + out(_("ok")); + } + + // Get all the valudes and replace them with joinmsg_id + // + outn(_("migrate to recording ids..")); + $sql = "SELECT `exten`, `joinmsg` FROM `meetme`"; + $results = $db->getAll($sql, DB_FETCHMODE_ASSOC); + if(DB::IsError($results)) { + out(_("fatal error")); + die_freepbx($results->getDebugInfo()); + } + $migrate_arr = array(); + $count = 0; + foreach ($results as $row) { + if (trim($row['joinmsg']) != '') { + $rec_id = recordings_get_or_create_id($row['joinmsg'], 'conference'); + $migrate_arr[] = array($rec_id, $row['exten']); + $count++; + } + } + if ($count) { + $compiled = $db->prepare('UPDATE `meetme` SET `joinmsg_id` = ? WHERE `exten` = ?'); + $result = $db->executeMultiple($compiled,$migrate_arr); + if(DB::IsError($result)) { + out(_("fatal error")); + die_freepbx($result->getDebugInfo()); + } + } + out(sprintf(_("migrated %s entries"),$count)); + + // Now remove the old recording field replaced by new id field + // + outn(_("dropping joinmsg field..")); + $sql = "ALTER TABLE `meetme` DROP `joinmsg`"; + $result = $db->query($sql); + if(DB::IsError($result)) { + out(_("no joinmsg field???")); + } else { + out(_("ok")); + } + +} else { + out(_("already migrated")); +} +?> Index: /modules/branches/2.6/customappsreg/i18n/sv_SE/LC_MESSAGES/customappsreg.po =================================================================== --- /modules/branches/2.6/customappsreg/i18n/sv_SE/LC_MESSAGES/customappsreg.po (revision 6943) +++ /modules/branches/2.6/customappsreg/i18n/sv_SE/LC_MESSAGES/customappsreg.po (revision 6943) @@ -0,0 +1,171 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: FreePBX customappsreg\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2008-10-05 22:57+0200\n" +"PO-Revision-Date: 2008-10-11 16:54+0100\n" +"Last-Translator: Mikael Carlsson \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Poedit-Language: Swedish\n" +"X-Poedit-Country: SWEDEN\n" + +#: functions.inc.php:29 +#, php-format +msgid "Custom Destination: %s" +msgstr "Anpassad destination: %s" + +#: functions.inc.php:52 +msgid "Custom Extension: " +msgstr "Anpassad anknytning:" + +#: functions.inc.php:103 +#: page.customdests.php:190 +msgid "Invalid Destination, must not be blank, must be formatted as: context,exten,pri" +msgstr "Ogiltig destination, den kan inte vara tom och måste vara formaterad som: context,exten,pri" + +#: functions.inc.php:107 +#: functions.inc.php:140 +#: page.customdests.php:191 +#: page.customextens.php:140 +msgid "Invalid description specified, must not be blank" +msgstr "Ogiltig beskrivning, den kan inte vara tom" + +#: functions.inc.php:112 +msgid "DUPLICATE Destination: This destination is already in use" +msgstr "DUBLETT av destination: Denna destination finns redan" + +#: functions.inc.php:123 +#: functions.inc.php:186 +msgid "DUPLICATE Destination: This destination is in use or potentially used by another module" +msgstr "DUBLETT av destination: Denna destination finns redan eller anvÀnds av annan modul" + +#: functions.inc.php:136 +#: page.customextens.php:139 +msgid "Invalid Extension, must not be blank" +msgstr "Ogiltig anknytning, den kan inte vara tom" + +#: functions.inc.php:151 +msgid "DUPLICATE Extension: This extension already in use" +msgstr "DUBLETT av anknytning: Denna anknytning anvÀnds redan" + +#: page.customdests.php:54 +#: page.customdests.php:80 +#: page.customdests.php:92 +msgid "Add Custom Destination" +msgstr "LÀgg till anpassad destination" + +#: page.customdests.php:78 +#: page.customextens.php:92 +msgid "Edit: " +msgstr "Redigera:" + +#: page.customdests.php:83 +msgid "Custom Destinations allows you to register your custom destinations that point to custom dialplans and will also 'publish' these destinations as available destinations to other modules. This is an advanced feature and should only be used by knowledgeable users. If you are getting warnings or errors in the notification panel about CUSTOM destinations that are correct, you should include them here. The 'Unknown Destinations' chooser will allow you to choose and insert any such destinations that the registry is not aware of into the Custom Destination field." +msgstr "Anpassade destinationer ger dig möjlighet att registrera dina anpassningar i nummerplanen och 'publicerar' dessa som tillgÀngliga destinationer för andra moduler. Detta Àr en avancerad funktion och bör bara anvÀndas av personer med insikt i Asterisk nummerplan. Om du får varningar eller felmeddelande i \"Meddelanden från FreePBX\" om ANPASSADE destinationer, bör du inkludera dom hÀr." + +#: page.customdests.php:92 +msgid "Edit Custom Destination" +msgstr "Redigera anpassad anknytning" + +#: page.customdests.php:94 +msgid "Custom Destination" +msgstr "Anpassad destination" + +#: page.customdests.php:97 +msgid "This is the Custom Destination to be published. It should be formatted exactly as you would put it in a goto statement, with context, exten, priority all included. An example might look like:
mycustom-app,s,1" +msgstr "Detta Àr en Anpassad destination som ska publiceras. Formatet ska vara exakt som du anvÀnder i en goto sats, med context, exten, priority. Ett exempel kan se ut som detta:
min-anpassade-app,s,1" + +#: page.customdests.php:99 +msgid "READONLY WARNING: Because this destination is being used by other module objects it can not be edited. You must remove those dependencies in order to edit this destination, or create a new destination to use" +msgstr "VARNING SKRIVSKYDDAD: Denna destination anvÀnds av andra moduler och kan inte redigeras. Du mÃ¥ste ta bort ta bort dessa beroenden för att kunna redigera denna destination, eller skapa en ny destination." + +#: page.customdests.php:121 +msgid "Destination Quick Pick" +msgstr "Snabbval för destination" + +#: page.customdests.php:123 +msgid "Choose un-identified destinations on your system to add to the Custom Destination Registry. This will insert the chosen entry into the Custom Destination box above." +msgstr "VÀlj en oidentifierad destination i ditt system för att lÀgga till den i registret för Anpassad destinationer. Detta kommer att lÀgga till vÀrdet i rutan Anpassad destination ovan." + +#: page.customdests.php:129 +msgid "(pick destination)" +msgstr "(vÀlj destination)" + +#: page.customdests.php:144 +#: page.customextens.php:118 +msgid "Description" +msgstr "Beskrivning" + +#: page.customdests.php:144 +msgid "Brief Description that will be published to modules when showing destinations. Example: My Weather App" +msgstr "Kortfattad beskrivning som kommer att visas nÀr du vÀljer destination i moduler. Exempel: Min Anpassade VÀg" + +#: page.customdests.php:148 +#: page.customextens.php:122 +msgid "Notes" +msgstr "Notering" + +#: page.customdests.php:148 +msgid "More detailed notes about this destination to help document it. This field is not used elsewhere." +msgstr "Mer detaljerad beskrivning om denna destination, för dokumentation. Detta fÀlt anvÀnds bara hÀr." + +#: page.customdests.php:153 +#: page.customextens.php:127 +msgid "Submit Changes" +msgstr "Spara Àndringar" + +#: page.customdests.php:154 +#: page.customextens.php:128 +msgid "Delete" +msgstr "Ta bort" + +#: page.customextens.php:70 +#: page.customextens.php:94 +#: page.customextens.php:111 +msgid "Add Custom Extension" +msgstr "LÀgg till anpassad anknytning" + +#: page.customextens.php:97 +msgid "Custom Extensions provides you with a facility to register any custom extensions or feature codes that you have created in a custom file and FreePBX doesn't otherwise know about them. This allows the Extension Registry to be aware of your own extensions so that it can detect conflicts or report back information about your custom extensions to other modules that may make use of the information. You should not put extensions that you create in the Misc Apps Module as those are not custom." +msgstr "Anpassade anknytningar ger dig en möjlighet att registrera anpassade anknytningar eller funktionskoder som du har skapat i en anpassad fil som FreePBX inte kÀnner till. Detta ger en möjlighet för Anknytningsregistret att kÀnna till dina anknytningar sÃ¥ att konflikter kan detekteras eller rapporteras tillbaka till andra moduler som eventuellt anvÀnder informationen. Du ska inte lÀgga till anknytningar hÀr som du skapar i Övriga Applikationer dÃ¥ dom inte Àr att rÀkna som anpassade" + +#: page.customextens.php:101 +msgid "Conflicting Extensions" +msgstr "Konfliktande anknytningar" + +#: page.customextens.php:111 +msgid "Edit Custom Extension" +msgstr "Redigera anpassad anknytning" + +#: page.customextens.php:113 +msgid "Custom Extension" +msgstr "Anpassad anknytning" + +#: page.customextens.php:113 +msgid "This is the Extension or Feature Code you are using in your dialplan that you want the FreePBX Extension Registry to be aware of." +msgstr "Detta Àr den anpassade anknytning eller funktionskod som du anvÀnder i din nummerplan som FreePBX kommer att kÀnna till." + +#: page.customextens.php:118 +msgid "Brief description that will be published in the Extension Registry about this extension" +msgstr "Kortfattad beskrivning som kommer att visas för övriga anknytningar" + +#: page.customextens.php:122 +msgid "More detailed notes about this extension to help document it. This field is not used elsewhere." +msgstr "Mer detaljerad beskrivning om denna anknytning för att underlÀtta dokumentation. Detta anvÀnds bara hÀr." + +#: module.xml +msgid "Custom Destinations" +msgstr "Anpassade destinationer" + +#: module.xml +msgid "Custom Extensions" +msgstr "Anpassade anknytningar" + Index: /modules/branches/2.6/customappsreg/i18n/ru_RU/LC_MESSAGES/customappsreg.po =================================================================== --- /modules/branches/2.6/customappsreg/i18n/ru_RU/LC_MESSAGES/customappsreg.po (revision 6975) +++ /modules/branches/2.6/customappsreg/i18n/ru_RU/LC_MESSAGES/customappsreg.po (revision 6975) @@ -0,0 +1,195 @@ +# Russian freePBX ver. translation +# Copyright (c) 2006-2008 PostMet Corporation +# This file is distributed under the same license as the freePBX package. +# Alexander Kozyrev , Sergey Nikolayev , 2006-2008. +# +# žáßÞÛì×ÞÒÐâì iconv amp.new -f UTF-8 -t ISO-8859-5 -o amp.po +# fuzzy +msgid "" +msgstr "" +"Project-Id-Version: 1.3\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2007-04-19 21:45+0100\n" +"PO-Revision-Date: 2008-01-16 16:38+0100\n" +"Last-Translator: Alexander Kozyrev \n" +"Language-Team: Russian \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=iso-8859-5\n" +"Content-Transfer-Encoding: 8bit\n" + +#: functions.inc.php:52 +msgid "Custom Extension: " +msgstr "ŸáÞÑëÙ ÝÞÜÕà:" + +#: functions.inc.php:103 page.customdests.php:190 +msgid "" +"Invalid Destination, must not be blank, must be formatted as: context,exten," +"pri" +msgstr "œÕÒÕàÝÞÕ ÝÐ×ÝÐçÕÝØÕ, ÝÕ ÔÞÛÖÝÞ Ñëâì ßãáâëÜ, Ø ÔÞÛÖÝÞ Ñëâì Ò äÞàÜÐâÕ: ÚÞÝâÕÚáâ, íÚáâÕÝÑ ßàØÞàØâÕâ." + +#: functions.inc.php:107 functions.inc.php:140 page.customdests.php:191 +#: page.customextens.php:140 +msgid "Invalid description specified, must not be blank" +msgstr "œÕÒÕàÝÞÕ ÞߨáÐÝØÕ. œÕ ÔÞÛÖÝÞ Ñëâì ßãáâëÜ." + +#: functions.inc.php:112 +msgid "DUPLICATE Destination: This destination is already in use" +msgstr "ŽÃ±»žº°Â Ò ÝÐ×ÝÐçÕÝØØ: íâÞ ÝÐ×ÝÐçÕÝØÕ ãÖÕ ØáßÞÛì×ãÕâáï" + +#: functions.inc.php:123 functions.inc.php:186 +msgid "" +"DUPLICATE Destination: This destination is in use or potentially used by " +"another module" +msgstr "ŽÃ±»žº°Â Ò ÝÐ×ÝÐçÕÝØØ: íâÞ ÝÐ×ÝÐçÕÝØÕ ãÖÕ ØáßÞÛì×ãÕâáï ØÛØ ßÞâÕÝæØÐÛìÝÞ ÜÞÖÕâ Ñëâì ØáßÞÛì×ÞÒÐÝÞ Ò ÔàãÓÞÜ ÜÞÔãÛÕ" + +#: functions.inc.php:136 page.customextens.php:139 +msgid "Invalid Extension, must not be blank" +msgstr "œÕÒÕàÝëÙ ÒÝãâàÕÝÝØÙ ÝÞÜÕà, ÝÕ ÜÞÖÕâ Ñëâì ßãáâëÜ" + +#: functions.inc.php:151 +msgid "DUPLICATE Extension: This extension already in use" +msgstr "ŽÃ±»žº°Â ÒÝãâàÕÝÝÕÓÞ ÝÞÜÕàÐ: íâÞâ ÝÞÜÕà ãÖÕ ØáßÞÛì×ãÕâáï" + +#: page.customdests.php:76 page.customextens.php:92 +msgid "Edit: " +msgstr "ÀÕÔÐÚâØàÞÒÐâì:" + +#: page.customdests.php:78 page.customdests.php:90 +msgid "Add Custom Destination" +msgstr "ŽÞÑÐÒØâì áßÕæØÐÛìÝÞÕ ÝÐ×ÝÐçÕÝØÕ" + +#: page.customdests.php:81 +msgid "" +"Custom Destinations allows you to register your custom destinations that " +"point to custom dialplans and will also 'publish' these destinations as " +"available destinations to other modules. This is an advanced feature and " +"should only be used by knowledgeable users. If you are getting warnings or " +"errors in the notification panel about CUSTOM destinations that are correct, " +"you should include them here. The 'Unknown Destinations' chooser will allow " +"you to choose and insert any such destinations that the registry is not " +"aware of into the Custom Destination field." + +msgstr "" +"ÁßÕæØÐÛìÝÞÕ ÝÐ×ÝÐçÕÝØÕ ÔÐñâ ÒÞ×ÜÞÖÝÞáâì àÕÓØáâàØàÞÒÐâì áßÕæØÐÛìÝëÕ áæÕÝÐàØØ, ÚÞâÞàëÕ " +"ÒáâàÐØÒÐîâáï Ò ÒÐè ÔØÐÛ ßÛÐÝ Ø áâÐÝÞÒïâáï ÔÞáâãßÝëÜØ ÔÛï ßÕàÕÝÐßàÐÒÛÕÝØï ÝÐ ÝØå " +"Ø× ÔàãÓØå ÜÞÔãÛÕÙ. ÍâÞ âÐÚÐï ÞçÕÝì ßàÞÔÒØÝãâÐï ÞßæØï, Ø ÜÞÖÕâ ØáßÞÛì×ÞÒÐâìáï âÞÛìÚÞ " +"ÞßëâÝëÜØ ßÞÛì×ÞÒÐâÕÛïÜØ, ÚÞâÞàëÕ ßÞÝØÜÐîâ çâÞ ÞÝØ åÞâïâ áÔÕÛÐâì. µáÛØ ÒØÔÝë " +"ßàÕÔãßàÕÖÔÕÝØï ØÛØ áÞÞÑéÕÝØï Ò ßÐÝÕÛØ áÞáâÞïÝØï áØáâÕÜë ßÞ ßÞÒÞÔã CUSTOM " +"ÝÐßàÐÒÛÕÝØÙ, âÞ Òáñ Ò ßÞàïÔÚÕ, Òë ÔÞÛÖÝë ØÜØ ßàÞáâÞ ßÞÛì×ÞÒÐâìáï. ²ëÑÞà âÕàÜØÝÐæØØ " +"×ÒÞÝÚÐ Ò áæÕÝÐàØïå ÒåÞÔïéÕÙ ÜÐàèàãâØ×ÐæØØ ÑãÔÕâ ÒëÓÛïÔÕâì ÚÐÚ 'Custom Applications' " +"ÓÔÕ áÞ×ÔÐÝÝëÙ ÚÞÝâÕÚáâ ÜÞÖÝÞ ÒëÑàÐâì Ò 'ÃáâÐÝÞÒØâì ÝÐßàÐÒÛÕÝØÕ'" + +#: page.customdests.php:90 +msgid "Edit Custom Destination" +msgstr "ÀÕÔÐÚâØàÞÒÐâì áßÕæØÐÛìÝÞÕ ÝÐ×ÝÐçÕÝØÕ" + +#: page.customdests.php:92 +msgid "Custom Destination" +msgstr "ÁßÕæÝÐ×ÝÐçÕÝØÕ" + +#: page.customdests.php:92 +msgid "" +"This is the Custom Destination to be published. It should be formatted " +"exactly as you would put it in a goto statement, with context, exten, " +"priority all included. An example might look like:
mycustom-app,s,1" +msgstr "" +"ÍâÞ ÞÑêïÒÛÕÝØÕ ØáßÞÛì×ÞÒÐÝØï ÁßÕæØÐÛìÝÞÓÞ ÝÐ×ÝÐçÕÝØï. ¿àØ áÞ×ÔÐÝØØ ÝÕÞÑåÞÔØÜÞ ãÚÐ×ëÒÐâì " +"ÚÞÝâÕÚáâ, ÒÝãâàÕÝÝØÙ ÝÞÜÕà Ø ßàØÞàØâÕâ. œÐßàØÜÕà:
mycustom-app,s,1" + +#: page.customdests.php:98 +msgid "Destination Quick Pick" +msgstr "œÐ×ÝÐçÕÝØÕ ±ëâàëÙ ¿ÕàÕåÒÐâ" + +#: page.customdests.php:100 +msgid "" +"Choose un-identified destinations on your system to add to the Custom " +"Destinaion Registry. This will insert the chosen entry into the Custom " +"Destination box above." +msgstr "" +"²ëÑÕàØâÕ ÝÕØÔÕÝâØäØæØàÞÒÐÝÝëÕ ÝÐ×ÝÐçÕÝØï ÒÐèÕÙ áØáâÕÜë çâÞÑë ÔÞÑÐÒØâì Ò àÕÓØáâà " +"ÁßÕæÝÐ×ÝÐçÕÝØÙ. ¿àØ íâÞÜ ÒáÕ ãÚÐ×ÐÝëÕ ×ÐßØáØ ßÞïÒïâáï Ò ÞÚÝÕ ÁßÕæÝÐ×ÝÐçÕÝØï" + +#: page.customdests.php:106 +msgid "(pick destination)" +msgstr "(ÒëÑàÐâì ÝÐ×ÝÐçÕÝØÕ)" + +#: page.customdests.php:118 page.customextens.php:118 +msgid "Description" +msgstr "ŸßØáÐÝØÕ" + +#: page.customdests.php:118 +msgid "" +"Brief Description that will be published to modules when showing " +"destinations. Example: My Weather App" +msgstr "" +"ºÞàÞâÚÞÕ ÞߨáÐÝØÕ, ÚÞâÞàÞÕ ßÞïÒØâáï ßàØ ÒëÑÞàÕ íâÞÓÞ ÝÐ×ÝÐçÕÝØï. œÐßàØÜÕà: " +"ÁÛãÖÑÐ ŒÕÖÓÐÛÐÚâØçÕáÚØå ŽÞáâÐÒÞÚ" + +#: page.customdests.php:122 page.customextens.php:122 +msgid "Notes" +msgstr "¿àØÜÕçÐÝØï" + +#: page.customdests.php:122 +msgid "" +"More detailed notes about this destination to help document it. This field " +"is not used elsewhere." +msgstr "" +"±ÞÛÕÕ ÔÕâÐÛìÝëÕ ×ÐÜÕçÐÝØï, ÚÞâÞàëÕ ßÞÜÞÓãâ ÔÞÚãÜÕÝâØàÞÒÐâì íâØ ÝÐ×ÝÐçÕÝØï, ÚÞÓÔÐ " +"Øå ÜÝÞÓÞ. ÍâÞ ßÞÛÕ ÑÞÛìèÕ ÝØÓÔÕ ÝÕ ØáßÞÛì×ãÕâáï." + +#: page.customdests.php:128 page.customextens.php:128 +msgid "Delete" +msgstr "ÃÔÐÛØâì" + +#: page.customextens.php:94 page.customextens.php:111 +msgid "Add Custom Extension" +msgstr "ŽÞÑÐÒØâì ŸáÞÑëÙ ÝÞÜÕà" + +#: page.customdests.php:97 +msgid "This is the Custom Destination to be published. It should be formatted exactly as you would putit in a goto statement, with context, exten, priority all included. An example might look like:
mycustom-app,s,1" +msgstr "±ãÔÕâ áÞ×ÔÐÝÞ ÞáÞÑÞÕ ÝÐ×ÝÐçÕÝØÕ. ŸÝÞ ÔÞÛÖÝÞ ØÜÕâì äÞàÜÐâ ßÕàÕÝÐßàÐÒÛÕÝØï GoTo á ÞÑï×ÐâÕÛìÝëÜ ãÚÐ×ÐÝØÕÜ ÚÞÝâÕÚáâÐ, íÚáâÝÕÝèÝ, ßàØÞàØâÕâÐ. œÐßàØÜÕà:
mycustom-app,s,1" + +#: page.customextens.php:97 +msgid "Custom Extensions provides you with a facility to register any custom extensions or feature codes that you have created in a custom file and FreePBX doesn't otherwise know about them. This allows the Extension Registry to be aware of your own extensions so that it can detect conflicts or report back information about your custom extensions to other modules that may make use of the information. You should not put extensions that you create in the Misc Apps Module as those are not custom." +msgstr "" +"ŸáÞÑëÕ ÝÞÜÕàÐ ßÞÜÞÓÐîâ àÕÓØáâàØàÞÒÐâì ÚÐÚØÕ-ÛØÑÞ áßÕæØÐÛìÝëÕ ÝÞÜÕàÐ ÔÞÝÐÑÞàÐ, " +"ÚÞâÞàëÕ áÞ×ÔÐîâáï Ò custom äÐÙÛÐå, Ð FreePBX ÝÕ ØÜÕÕâ ßÞÝïâØï Þ ÝØå. ÍâÞ ÔÐñâ " +"ÒÞ×ÜÞÖÝÞáâì áÞÔÕàÖÐâì àÕÓØáâà ÒÝãâàÕÝÝØå ÝÞÜÕàÞÒ âÐÚØÜ ÞÑàÐ×ÞÜ, çâÞÑë ßàÕÔÞâÒàÐéÐâì " +"ÚÞÝäÛØÚâë á ÞÔØÝÐÚÞÒëÜØ ÝÞÜÕàÐÜØ (ØÛØ ÚÞÔÐÜØ ÔÞÝÐÑÞàÐ) Ø áÞÞÑéÐâì Þ ÝØå Ò ÔàãÓØÕ " +"ÜÞÔãÛØ, ÚÞâÞàëÕ ÜÞÓãâ ØáßÞÛì×ÞÒÐâì íâã ØÝäÞàÜÐæØî. ²ë ÝÕ ÔÞÛÖÝë áÞ×ÔÐÒÐâì íâØ " +"ÞáÞÑëÕ ÝÞÜÕàÐ Ò ÜÞÔãÛÕ Misc Apps âÐÚ ÚÐÚ ÞÝØ ÑãÔãâ ÔàãÓØÜØ." + +#: page.customextens.php:101 +msgid "Conflicting Extensions" +msgstr "ºÞÝäÛØÚâãîéØÕ ÝÞÜÕàÐ" + +#: page.customextens.php:111 +msgid "Edit Custom Extension" +msgstr "ÀÕÔÐÚâØàÞÒÐâì ŸáÞÑëÙ ÝÞÜÕà" + +#: page.customextens.php:113 +msgid "Custom Extension" +msgstr "ŸáÞÑëÙ œÞÜÕà" + +#: page.customextens.php:113 +msgid "" +"This is the Extension or Feature Code you are using in your dialplan that " +"you want the FreePBX Extension Registry to be aware of." +msgstr "" +"ÍâÞ ŸáÞÑëÙ ÝÞÜÕà ØÛØ ÚÞÔ ÔÞÝÐÑÞàÐ, ÚÞâÞàëÙ ÑãÔÕâ ØáßÞÛì×ÞÒÐâìáï Ò ÒÐèÕÜ ÔØÐÛ ßÛÐÝÕ, " +"ÔÛï ãçÕâÐ ÕÓÞ Ò ÞÑéÕÜ ÀÕÓØáâàÕ ÝÞÜÕàÞÒ FreePBX." + +#: page.customextens.php:118 +msgid "" +"Brief description that will be published in the Extension Registry about " +"this extension" +msgstr "" +"ºÞàÞâÚÞÕ ÞߨáÐÝØÕ íâÞÓÞ ÝÞÜÕàÐ, ÚÞâÞàÞÕ ÑãÔÕâ ØáßÞÛì×ÞÒÐâìáï Ò ÀÕÓØáâàÕ ÝÞÜÕàÞÒ." + +#: page.customextens.php:122 +msgid "" +"More detailed notes about this extension to help document it. This field is " +"not used elsewhere." +msgstr "" +"±ÞÛÕÕ ÔÕâÐÛìÝëÕ ßàØÜÕçÐÝØï ÞÑ íâÞÜ ÝÞÜÕàÕ, ÚÞâÞàÞÕ ßÞÜÞÖÕâ ÔÞÚãÜÕÝâØàÞÒÐâì ×ÐߨáØ, ÚÞÓÔÐ " +"Øå ÜÝÞÓÞ. ÍâÞ ßÞÛÕ ÑÞÛìèÕ ÝØÓÔÕ ÝÕ ØáßÞÛì×ãÕâáï." Index: /modules/branches/2.6/customappsreg/i18n/customappsreg.pot =================================================================== --- /modules/branches/2.6/customappsreg/i18n/customappsreg.pot (revision 6943) +++ /modules/branches/2.6/customappsreg/i18n/customappsreg.pot (revision 6943) @@ -0,0 +1,193 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2008-10-05 22:57+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" + +#: functions.inc.php:29 +#, php-format +msgid "Custom Destination: %s" +msgstr "" + +#: functions.inc.php:52 +msgid "Custom Extension: " +msgstr "" + +#: functions.inc.php:103 page.customdests.php:190 +msgid "" +"Invalid Destination, must not be blank, must be formatted as: context,exten," +"pri" +msgstr "" + +#: functions.inc.php:107 functions.inc.php:140 page.customdests.php:191 +#: page.customextens.php:140 +msgid "Invalid description specified, must not be blank" +msgstr "" + +#: functions.inc.php:112 +msgid "DUPLICATE Destination: This destination is already in use" +msgstr "" + +#: functions.inc.php:123 functions.inc.php:186 +msgid "" +"DUPLICATE Destination: This destination is in use or potentially used by " +"another module" +msgstr "" + +#: functions.inc.php:136 page.customextens.php:139 +msgid "Invalid Extension, must not be blank" +msgstr "" + +#: functions.inc.php:151 +msgid "DUPLICATE Extension: This extension already in use" +msgstr "" + +#: page.customdests.php:54 page.customdests.php:80 page.customdests.php:92 +msgid "Add Custom Destination" +msgstr "" + +#: page.customdests.php:78 page.customextens.php:92 +msgid "Edit: " +msgstr "" + +#: page.customdests.php:83 +msgid "" +"Custom Destinations allows you to register your custom destinations that " +"point to custom dialplans and will also 'publish' these destinations as " +"available destinations to other modules. This is an advanced feature and " +"should only be used by knowledgeable users. If you are getting warnings or " +"errors in the notification panel about CUSTOM destinations that are correct, " +"you should include them here. The 'Unknown Destinations' chooser will allow " +"you to choose and insert any such destinations that the registry is not " +"aware of into the Custom Destination field." +msgstr "" + +#: page.customdests.php:92 +msgid "Edit Custom Destination" +msgstr "" + +#: page.customdests.php:94 +msgid "Custom Destination" +msgstr "" + +#: page.customdests.php:97 +msgid "" +"This is the Custom Destination to be published. It should be formatted " +"exactly as you would put it in a goto statement, with context, exten, " +"priority all included. An example might look like:
mycustom-app,s,1" +msgstr "" + +#: page.customdests.php:99 +msgid "" +"READONLY WARNING: Because this destination is being used by other module " +"objects it can not be edited. You must remove those dependencies in order to " +"edit this destination, or create a new destination to use" +msgstr "" + +#: page.customdests.php:121 +msgid "Destination Quick Pick" +msgstr "" + +#: page.customdests.php:123 +msgid "" +"Choose un-identified destinations on your system to add to the Custom " +"Destination Registry. This will insert the chosen entry into the Custom " +"Destination box above." +msgstr "" + +#: page.customdests.php:129 +msgid "(pick destination)" +msgstr "" + +#: page.customdests.php:144 page.customextens.php:118 +msgid "Description" +msgstr "" + +#: page.customdests.php:144 +msgid "" +"Brief Description that will be published to modules when showing " +"destinations. Example: My Weather App" +msgstr "" + +#: page.customdests.php:148 page.customextens.php:122 +msgid "Notes" +msgstr "" + +#: page.customdests.php:148 +msgid "" +"More detailed notes about this destination to help document it. This field " +"is not used elsewhere." +msgstr "" + +#: page.customdests.php:153 page.customextens.php:127 +msgid "Submit Changes" +msgstr "" + +#: page.customdests.php:154 page.customextens.php:128 +msgid "Delete" +msgstr "" + +#: page.customextens.php:70 page.customextens.php:94 page.customextens.php:111 +msgid "Add Custom Extension" +msgstr "" + +#: page.customextens.php:97 +msgid "" +"Custom Extensions provides you with a facility to register any custom " +"extensions or feature codes that you have created in a custom file and " +"FreePBX doesn't otherwise know about them. This allows the Extension " +"Registry to be aware of your own extensions so that it can detect conflicts " +"or report back information about your custom extensions to other modules " +"that may make use of the information. You should not put extensions that you " +"create in the Misc Apps Module as those are not custom." +msgstr "" + +#: page.customextens.php:101 +msgid "Conflicting Extensions" +msgstr "" + +#: page.customextens.php:111 +msgid "Edit Custom Extension" +msgstr "" + +#: page.customextens.php:113 +msgid "Custom Extension" +msgstr "" + +#: page.customextens.php:113 +msgid "" +"This is the Extension or Feature Code you are using in your dialplan that " +"you want the FreePBX Extension Registry to be aware of." +msgstr "" + +#: page.customextens.php:118 +msgid "" +"Brief description that will be published in the Extension Registry about " +"this extension" +msgstr "" + +#: page.customextens.php:122 +msgid "" +"More detailed notes about this extension to help document it. This field is " +"not used elsewhere." +msgstr "" + +#: module.xml +msgid "Custom Destinations" +msgstr "" + +#: module.xml +msgid "Custom Extensions" +msgstr "" Index: /modules/branches/2.6/customappsreg/uninstall.php =================================================================== --- /modules/branches/2.6/customappsreg/uninstall.php (revision 5324) +++ /modules/branches/2.6/customappsreg/uninstall.php (revision 5324) @@ -0,0 +1,13 @@ +\n"; + +echo "dropping table custom_extensions.."; +sql("DROP TABLE IF EXISTS `custom_extensions`"); +echo "done
\n"; + +?> Index: /modules/branches/2.6/customappsreg/page.customextens.php =================================================================== --- /modules/branches/2.6/customappsreg/page.customextens.php (revision 6721) +++ /modules/branches/2.6/customappsreg/page.customextens.php (revision 6721) @@ -0,0 +1,155 @@ + +
+ +
    +'._('Add Custom Extension').''; + +foreach (customappsreg_customextens_list() as $row) { + $descr = $row['description'] != '' ? $row['description'] : '('.$row['custom_exten'].')'; + echo '
  • '.$descr.'
  • '; +} + +?> +
+ +
+ +"._("Edit: ")."$disp_description".""; +} else { + echo "

"._("Add Custom Extension")."

"; +} + +$helptext = _("Custom Extensions provides you with a facility to register any custom extensions or feature codes that you have created in a custom file and FreePBX doesn't otherwise know about them. This allows the Extension Registry to be aware of your own extensions so that it can detect conflicts or report back information about your custom extensions to other modules that may make use of the information. You should not put extensions that you create in the Misc Apps Module as those are not custom."); +echo $helptext; + +if (!empty($conflict_url)) { + echo "
"._("Conflicting Extensions")."
"; + echo implode('
',$conflict_url); +} +?> + +
+ + + + + + + + + + + + + + + + + + + + + + +

:
:
:

" tabindex=""> + '; } ?> +
+
+ + Index: /modules/branches/2.6/customappsreg/module.xml =================================================================== --- /modules/branches/2.6/customappsreg/module.xml (revision 7016) +++ /modules/branches/2.6/customappsreg/module.xml (revision 7016) @@ -0,0 +1,32 @@ + + customappsreg + Custom Applications + 2.5.0.4 + tool + System Administration + + Registry to add custom extensions and destinations that may be created and used so that the Extensions and Destinations Registry can include these. + + + Custom Extensions + Custom Destinations + + + *2.5.0.4* #3263, localization fixes + *2.5.0.3* localizations fixes + *2.5.0.2* localization, Swedish + *2.5.0.1* #3003 spelling + *2.5.0* #2845 tabindex + *2.4.0.5* #2843 Russian Translation + *2.4.0.4* #2700 block editing of destination field when once other modules are using it + *2.4.0.3* added depends on 2.4.0 + *2.4.0.2* #2558 can't edit/del custom extension + *2.4.0.1* Fix typo in install script, non-existent primary key + *2.4.0* First release of module + + + 2.4.0 + + release/2.5/customappsreg-2.5.0.4.tgz + c4791603420dd2a21bf8f3226c01b4fc + Index: /modules/branches/2.6/customappsreg/functions.inc.php =================================================================== --- /modules/branches/2.6/customappsreg/functions.inc.php (revision 7000) +++ /modules/branches/2.6/customappsreg/functions.inc.php (revision 7000) @@ -0,0 +1,232 @@ + $row['custom_dest'], 'description' => $row['description'], 'category' => _("Custom Destinations")); + } + return $extens; +} + +/** the 'exten' is the same as the destination for this module + */ +function customappsreg_customdests_getdest($exten) { + return array($exten); +} + +/** If this is ours, we return it, otherwise we return false + * We use just use customappsreg and not the display because it + * is a per-module routine + */ +function customappsreg_getdestinfo($dest) { + global $active_modules; + + $thisexten = customappsreg_customdests_get($dest); + if (empty($thisexten)) { + return false; + } else { + $type = isset($active_modules['customappsreg']['type'])?$active_modules['customappsreg']['type']:'tool'; + return array('description' => sprintf(_("Custom Destination: %s"),$thisexten['description']), + 'edit_url' => 'config.php?display=customdests&type='.$type.'&extdisplay='.urlencode($dest), + ); + } +} + +function customappsreg_check_extensions($exten=true) { + global $active_modules; + + $extenlist = array(); + if (is_array($exten) && empty($exten)) { + return $extenlist; + } + $sql = "SELECT custom_exten, description FROM custom_extensions "; + if (is_array($exten)) { + $sql .= "WHERE custom_exten in ('".implode("','",$exten)."')"; + } + $results = sql($sql,"getAll",DB_FETCHMODE_ASSOC); + + $type = isset($active_modules['customappsreg']['type'])?$active_modules['customappsreg']['type']:'tool'; + + foreach ($results as $result) { + $thisexten = $result['custom_exten']; + $extenlist[$thisexten]['description'] = _("Custom Extension: ").$result['description']; + $extenlist[$thisexten]['status'] = 'INUSE'; + $extenlist[$thisexten]['edit_url'] = 'config.php?display=customextens&extdisplay='.urlencode($thisexten); + } + return $extenlist; +} + +function customappsreg_customdests_list() { + global $db; + $sql = "SELECT custom_dest, description, notes FROM custom_destinations ORDER BY description"; + $results = $db->getAll($sql, DB_FETCHMODE_ASSOC); + if(DB::IsError($results)) { + die_freepbx($results->getMessage()."

Error selecting from custom_destinations"); + } + return $results; +} + +function customappsreg_customextens_list() { + global $db; + $sql = "SELECT custom_exten, description, notes FROM custom_extensions ORDER BY custom_exten"; + $results = $db->getAll($sql, DB_FETCHMODE_ASSOC); + if(DB::IsError($results)) { + die_freepbx($results->getMessage()."

Error selecting from custom_extensions"); + } + return $results; +} + +function customappsreg_customdests_get($custom_dest) { + global $db; + $sql = "SELECT custom_dest, description, notes FROM custom_destinations WHERE custom_dest = ".q($custom_dest); + $row = $db->getRow($sql, DB_FETCHMODE_ASSOC); + if(DB::IsError($row)) { + die_freepbx($row->getMessage()."

Error selecting row from custom_destinations"); + } + return $row; +} + +function customappsreg_customextens_get($custom_exten) { + global $db; + $sql = "SELECT custom_exten, description, notes FROM custom_extensions WHERE custom_exten = ".q($custom_exten); + $row = $db->getRow($sql, DB_FETCHMODE_ASSOC); + if(DB::IsError($row)) { + die_freepbx($row->getMessage()."

Error selecting row from custom_extensions"); + } + return $row; +} + +function customappsreg_customdests_add($custom_dest, $description, $notes) { + global $db; + + if (!ereg("[^,]+,[^,]+,[^,]+",$custom_dest)) { + echo ""; + return false; + } + if (trim($description) == '') { + echo ""; + return false; + } + $usage_list = framework_identify_destinations($custom_dest, $module_hash=false); + if (!empty($usage_list[$custom_dest])) { + echo ""; + return false; + } + + $custom_dest = q($custom_dest); + $description = q($description); + $notes = q($notes); + $sql = "INSERT INTO custom_destinations (custom_dest, description, notes) VALUES ($custom_dest, $description, $notes)"; + $results = $db->query($sql); + if (DB::IsError($results)) { + if ($results->getCode() == DB_ERROR_ALREADY_EXISTS) { + echo ""; + return false; + } else { + die_freepbx($results->getMessage()."

".$sql); + } + } + return true; +} + +function customappsreg_customextens_add($custom_exten, $description, $notes) { + global $db; + + if ($custom_exten == '') { + echo ""; + return false; + } + if (trim($description) == '') { + echo ""; + return false; + } + + $custom_exten = q($custom_exten); + $description = q($description); + $notes = q($notes); + $sql = "INSERT INTO custom_extensions (custom_exten, description, notes) VALUES ($custom_exten, $description, $notes)"; + $results = $db->query($sql); + if (DB::IsError($results)) { + if ($results->getCode() == DB_ERROR_ALREADY_EXISTS) { + echo ""; + return false; + } else { + die_freepbx($results->getMessage()."

".$sql); + } + } + return true; +} + +function customappsreg_customdests_delete($custom_dest) { + global $db; + + $sql = "DELETE FROM custom_destinations WHERE custom_dest = ".q($custom_dest); + $result = $db->query($sql); + if(DB::IsError($result)) { + die_freepbx($result->getMessage().$sql); + } +} + +function customappsreg_customextens_delete($custom_exten) { + global $db; + + $sql = "DELETE FROM custom_extensions WHERE custom_exten = ".q($custom_exten); + $result = $db->query($sql); + if(DB::IsError($result)) { + die_freepbx($result->getMessage().$sql); + } +} + +function customappsreg_customdests_edit($old_custom_dest, $custom_dest, $description, $notes) { + global $db; + + if ($old_custom_dest != $custom_dest) { + $usage_list = framework_identify_destinations($custom_dest, $module_hash=false); + if (!empty($usage_list[$custom_dest])) { + echo ""; + return false; + } + } + + $sql = "UPDATE custom_destinations SET ". + "custom_dest = ".q($custom_dest).", ". + "description = ".q($description).", ". + "notes = ".q($notes)." ". + "WHERE custom_dest = ".q($old_custom_dest); + $result = $db->query($sql); + if(DB::IsError($result)) { + die_freepbx($result->getMessage().$sql); + } +} + +function customappsreg_customextens_edit($old_custom_exten, $custom_exten, $description, $notes) { + global $db; + + $sql = "UPDATE custom_extensions SET ". + "custom_exten = ".q($custom_exten).", ". + "description = ".q($description).", ". + "notes = ".q($notes)." ". + "WHERE custom_exten = ".q($old_custom_exten); + $result = $db->query($sql); + if(DB::IsError($result)) { + die_freepbx($result->getMessage().$sql); + } +} + +function customappsreg_customdests_getunknown() { + + $results = array(); + + $my_probs = framework_list_problem_destinations($my_hash, false); + + if (!empty($my_probs)) { + foreach ($my_probs as $problem) { + if ($problem['status'] == 'CUSTOM') { + $results[] = $problem['dest']; + } + } + } + return array_unique($results); +} + +?> Index: /modules/branches/2.6/customappsreg/install.php =================================================================== --- /modules/branches/2.6/customappsreg/install.php (revision 5469) +++ /modules/branches/2.6/customappsreg/install.php (revision 5469) @@ -0,0 +1,33 @@ +query($sql); +if(DB::IsError($check)) { + die_freepbx("Can not create custom_destinations table\n"); +} + + +$sql = " + CREATE TABLE IF NOT EXISTS `custom_extensions` + ( + `custom_exten` varchar(80) NOT NULL default '', + `description` varchar(40) NOT NULL default '', + `notes` varchar(255) NOT NULL default '', + PRIMARY KEY (`custom_exten`) + )"; + +$check = $db->query($sql); +if(DB::IsError($check)) { + die_freepbx("Can not create custom_extensions table\n"); +} + +?> Index: /modules/branches/2.6/customappsreg/page.customdests.php =================================================================== --- /modules/branches/2.6/customappsreg/page.customdests.php (revision 6722) +++ /modules/branches/2.6/customappsreg/page.customdests.php (revision 6722) @@ -0,0 +1,209 @@ + +
+ +
    +'._('Add Custom Destination').''; + +foreach (customappsreg_customdests_list() as $row) { + $descr = $row['description'] != '' ? $row['description'] : '('.$row['custom_dest'].')'; + echo '
  • '.$descr.'
  • '; +} + +?> +
+ +
+ +"._("Edit: ")."$disp_description".""; +} else { + echo "

"._("Add Custom Destination")."

"; +} + +$helptext = _("Custom Destinations allows you to register your custom destinations that point to custom dialplans and will also 'publish' these destinations as available destinations to other modules. This is an advanced feature and should only be used by knowledgeable users. If you are getting warnings or errors in the notification panel about CUSTOM destinations that are correct, you should include them here. The 'Unknown Destinations' chooser will allow you to choose and insert any such destinations that the registry is not aware of into the Custom Destination field."); +echo $helptext; +?> + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

: + + mycustom-app,s,1"); + if (!empty($usage_list)) { + echo "
"._("READONLY WARNING: Because this destination is being used by other module objects it can not be edited. You must remove those dependencies in order to edit this destination, or create a new destination to use"); + } + ?> +
+ + + + + + + +
:
:

" tabindex=""> + '; } ?> +
+ : +
+
+ + Index: /modules/branches/2.6/framework/module.xml =================================================================== --- /modules/branches/2.6/framework/module.xml (revision 7069) +++ /modules/branches/2.6/framework/module.xml (revision 7069) @@ -0,0 +1,35 @@ + + framework + FreePBX Framework + 2.5.1.0 + no + no + + *2.5.1.0* #3271, #3309, localization fixes + *2.5.0.1* #2792, #3223, #3225, #3235, #3234, #3242, #3246, #3247, #3248, #3221 + *2.5.0.0* #3176, #3191, #3204, #3209 - fixes SECURITY VULNERABILITY in CDR Reporting + *2.5.0rc3.0* #3145, #3151, #3154, #3155, #3156, #3164, #3166, #3165, #3077, #3170 (DAHDI Support) + *2.5.0rc2.4* #3131, #3137 several changes to better cache module data and boost performance of page loads + *2.5.0rc2.3* #2750, #3128, #3124, #3134, #3131 + *2.5.0rc2.2* #3107, #3093, #3090, #3113, $3117 + *2.5.0rc2.1* #3104 fix some urlencoding/decoding re: #3102 changes + *2.5.0rc2.0* #3067, #3086, #3082, #3102 + *2.5.0rc1.1* published wrong, including rc1.0 additions + *2.5.0rc1.0* #2913, #3052 delay_answer schema and CSS fix + *2.5.0beta1.2* #3014, #3030, #2992, #3026, #3027 + *2.5.0beta1.1* #2635, #2792 CDR Reporting pie chart errors, and fix bug introduced by #2963 + *2.5.0beta1.0* #2854, #2978, #2980, #2981, #2982, #2963, #2985 + *2.5.0alpha1.2* #2957 fix fatal failure in retrieve_conf from change to splice + *2.5.0alpha1.1* #2941, #2924, #1539, #2950, #2944, #2945, #2699, #2686, #2946, #2606, #2772, #2565, #1679 + *2.5.0alpha1.0* #1628, #1715, #1843, #2497, #2604, #2606, #2609, #2686, #2701, #2703, #2739, #2766, #2777, #2782, #2784, #2793, #2798, #2799, #2809, #2818, #2829, #2843, #2845, #2855, #2862, #2881, #2890, #2891, #2897, #2903, #2910, #2911, #2921, #2924 + *2.4.0.1* #2843, #2701, #2818, #2784, #2604, #2766, #2798, #2809, #2799, #2685, #2676 + *2.4.0.0* CHANGELOG TRUNCATED See SVN Repository + + + This module provides a facility to install bug fixes to the framework code that is not otherwise housed in a module + + setup + Basic + release/2.5/framework-2.5.1.0.tgz + 564d4b1e76d6f4704f0a2e7d470e1881 + Index: /modules/branches/2.6/framework/install.php =================================================================== --- /modules/branches/2.6/framework/install.php (revision 6493) +++ /modules/branches/2.6/framework/install.php (revision 6493) @@ -0,0 +1,107 @@ +'cp -rf' from src: '$src' to dst: '$dst'...details follow
"; + foreach ($errors as $error) { + echo "$error
"; + } +} + +if (! function_exists('out')) { + function out($text) { + echo $text."
"; + } +} + +if (! function_exists('outn')) { + function outn($text) { + echo $text; + } +} + +if (! function_exists('error')) { + function error($text) { + echo "[ERROR] ".$text."
"; + } +} + +if (! function_exists('fatal')) { + function fatal($text) { + echo "[FATAL] ".$text."
"; + exit(1); + } +} + +if (! function_exists('debug')) { + function debug($text) { + global $debug; + + if ($debug) echo "[DEBUG-preDB] ".$text."
"; + } +} + +include dirname(__FILE__)."/libfreepbx.install.php"; + +global $amp_conf; +global $asterisk_conf; + +$debug = false; +$dryrun = false; + +/** verison_compare that works with freePBX version numbers + * included here because there are some older versions of functions.inc.php that do not have + * it included as it was added during 2.3.0beta1 + */ +if (!function_exists('version_compare_freepbx')) { + function version_compare_freepbx($version1, $version2, $op = null) { + $version1 = str_replace("rc","RC", strtolower($version1)); + $version2 = str_replace("rc","RC", strtolower($version2)); + if (!is_null($op)) { + return version_compare($version1, $version2, $op); + } else { + return version_compare($version1, $version2); + } + } +} + +/* + * Framework install script + */ + + $htdocs_source = dirname(__FILE__)."/htdocs/*"; + $bin_source = dirname(__FILE__)."/bin/*"; + $agibin_source = dirname(__FILE__)."/agi-bin/*"; + + // These are required by libfreepbx.install.php library for upgrade routines + // + define("UPGRADE_DIR", dirname(__FILE__)."/upgrades/"); + define("MODULE_DIR", $amp_conf['AMPWEBROOT'].'/modules/'); + + $htdocs_dest = $amp_conf['AMPWEBROOT']; + $bin_dest = isset($amp_conf['AMPBIN']) ? $amp_conf['AMPBIN'] : '/var/lib/asterisk/bin'; + $agibin_dest = isset($asterisk_conf['astagidir']) ? $asterisk_conf['astagidir']:'/var/lib/asterisk/agi-bin'; + + exec("cp -rf $htdocs_source $htdocs_dest 2>&1",$out,$ret); + if ($ret != 0) { + framework_print_errors($htdocs_source, $htdocs_dest, $out); + } + + exec("cp -rf $bin_source $bin_dest 2>&1",$out,$ret); + if ($ret != 0) { + framework_print_errors($bin_source, $bin_dest, $out); + } + + exec("cp -rf $agibin_source $agibin_dest 2>&1",$out,$ret); + if ($ret != 0) { + framework_print_errors($agibin_source, $agibin_dest, $out); + } + + if (function_exists('upgrade_all')) { + upgrade_all(getversion()); + } else { + echo ("[ERROR] Function: 'upgrade_all' not present, libfreepbx.inc.php must not be isntall
"); + } + +?> Index: /modules/branches/2.6/frameworksvn.pl =================================================================== --- /modules/branches/2.6/frameworksvn.pl (revision 6493) +++ /modules/branches/2.6/frameworksvn.pl (revision 6493) @@ -0,0 +1,33 @@ +#!/usr/bin/perl + +# This script (sculpted from publish.pl) will check the last tarball (which must be there) +# based on the framework xml version number and then run svn log against all updates since +# framework was last published. +# +$rver = "2.5"; +$framework = "framework"; + +$moddir = 'framework'; + +my $reldir = "release/"; + + open FH, "$moddir/module.xml"; + $newxml = ""; + $vers = "unset"; + while () { + if ($vers == 'unset' && /(.+)<\/version>/) { $vers = $1; } + $newxml .= $_; + } + close FH; + + die "Don't know version of $moddir" if ($vers eq "unset"); + # Automatically check in any files that were modified but weren't checked into SVN + + # Now we know the version. Get the svnversion.txt from the last update. + $filename = "../../$reldir"."$rver/$framework-$vers.tgz"; + print "CHECKING VERSION: ..... "; + #print "CHECKING VERSION WITH: tar -zxOf $filename $moddir/svnversion.txt: ... "; + system("tar -zxOf ".$filename." ".$moddir."/svnversion.txt"); + print "Geting svn log since that version for $rver : .... \n\n"; + $svnver = system("svn log http://svn.freepbx.org/freepbx/branches/$rver -r `tar -zxOf ".$filename." ".$moddir."/svnversion.txt | sed -e s/SVN\\\ VERSION://`:HEAD"); + Index: /modules/branches/2.6/callwaiting/i18n/callwaiting.pot =================================================================== --- /modules/branches/2.6/callwaiting/i18n/callwaiting.pot (revision 6837) +++ /modules/branches/2.6/callwaiting/i18n/callwaiting.pot (revision 6837) @@ -0,0 +1,29 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2008-09-17 11:11+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" + +#: install.php:4 +msgid "Call Waiting - Activate" +msgstr "" + +#: install.php:12 +msgid "Call Waiting - Deactivate" +msgstr "" + +#: module.xml +msgid "Call Waiting" +msgstr "" Index: /modules/branches/2.6/callwaiting/i18n/sv_SE/LC_MESSAGES/callwaiting.po =================================================================== --- /modules/branches/2.6/callwaiting/i18n/sv_SE/LC_MESSAGES/callwaiting.po (revision 6665) +++ /modules/branches/2.6/callwaiting/i18n/sv_SE/LC_MESSAGES/callwaiting.po (revision 6665) @@ -0,0 +1,31 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: FreePBX callwaitning\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2008-09-09 12:15+0200\n" +"PO-Revision-Date: 2008-09-09 12:43+0100\n" +"Last-Translator: Mikael Carlsson \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Poedit-Language: Swedish\n" +"X-Poedit-Country: SWEDEN\n" + +#: install.php:4 +msgid "Call Waiting - Activate" +msgstr "Aktivera Samtal vÀntar" + +#: install.php:12 +msgid "Call Waiting - Deactivate" +msgstr "Avaktivera Samtal vÀntar" + +#: module.xml:3 +msgid "Call Waiting" +msgstr "Samtal vÀntar" + Index: /modules/branches/2.6/callwaiting/uninstall.php =================================================================== --- /modules/branches/2.6/callwaiting/uninstall.php (revision 2816) +++ /modules/branches/2.6/callwaiting/uninstall.php (revision 2816) @@ -0,0 +1,15 @@ +database_deltree('CW'); +} else { + fatal("Cannot connect to Asterisk Manager with ".$amp_conf["AMPMGRUSER"]."/".$amp_conf["AMPMGRPASS"]); +} + +?> Index: /modules/branches/2.6/callwaiting/module.xml =================================================================== --- /modules/branches/2.6/callwaiting/module.xml (revision 7037) +++ /modules/branches/2.6/callwaiting/module.xml (revision 7037) @@ -0,0 +1,19 @@ + + callwaiting + Call Waiting + 2.5.0 + + *2.5.0* localization string enclosures + *2.4.0* bumped for 2.4 + *1.1.2.2* changed categories + *1.1.2.1* bump for rc1 + *1.1.2* changed ${CALLERID(number)} to ${AMPUSER} to accomodate CID number masquerading + *1.1.1* Fixed typo Provdes to Provides* + *1.1* First release for 2.2 + + setup + Internal Options & Configuration + Provides an option to turn on/off call waiting + release/2.5/callwaiting-2.5.0.tgz + 88a20f5f1ae6300e024e1a03192e855d + Index: /modules/branches/2.6/callwaiting/functions.inc.php =================================================================== --- /modules/branches/2.6/callwaiting/functions.inc.php (revision 4041) +++ /modules/branches/2.6/callwaiting/functions.inc.php (revision 4041) @@ -0,0 +1,61 @@ +getCodeActive(); + unset($fcc); + + if ($fc != '') + $fname($fc); + } else { + $ext->add('from-internal-additional', 'debug', '', new ext_noop($modulename.": No func $fname")); + var_dump($item); + } + } + } + break; + } +} + +function callwaiting_cwon($c) { + global $ext; + + $id = "app-callwaiting-cwon"; // The context to be included + + $ext->addInclude('from-internal-additional', $id); // Add the include from from-internal + + $ext->add($id, $c, '', new ext_answer('')); // $cmd,1,Answer + $ext->add($id, $c, '', new ext_wait('1')); // $cmd,n,Wait(1) + $ext->add($id, $c, '', new ext_macro('user-callerid')); // $cmd,n,Macro(user-callerid) + $ext->add($id, $c, '', new ext_setvar('DB(CW/${AMPUSER})', 'ENABLED')); + $ext->add($id, $c, '', new ext_playback('call-waiting&activated')); // $cmd,n,Playback(...) + $ext->add($id, $c, '', new ext_macro('hangupcall')); // $cmd,n,Macro(user-callerid) +} + + +function callwaiting_cwoff($c) { + global $ext; + + $id = "app-callwaiting-cwoff"; // The context to be included + + $ext->addInclude('from-internal-additional', $id); // Add the include from from-internal + + $ext->add($id, $c, '', new ext_answer('')); // $cmd,1,Answer + $ext->add($id, $c, '', new ext_wait('1')); // $cmd,n,Wait(1) + $ext->add($id, $c, '', new ext_macro('user-callerid')); // $cmd,n,Macro(user-callerid) + $ext->add($id, $c, '', new ext_dbdel('CW/${AMPUSER}')); + $ext->add($id, $c, '', new ext_playback('call-waiting&de-activated')); // $cmd,n,Playback(...) + $ext->add($id, $c, '', new ext_macro('hangupcall')); // $cmd,n,Macro(user-callerid) +} +?> Index: /modules/branches/2.6/callwaiting/install.php =================================================================== --- /modules/branches/2.6/callwaiting/install.php (revision 6888) +++ /modules/branches/2.6/callwaiting/install.php (revision 6888) @@ -0,0 +1,22 @@ +setDescription('Call Waiting - Activate'); +$fcc->setDefault('*70'); +$fcc->update(); +unset($fcc); + +// Register FeatureCode - Deactivate +$fcc = new featurecode('callwaiting', 'cwoff'); +$fcc->setDescription('Call Waiting - Deactivate'); +$fcc->setDefault('*71'); +$fcc->update(); +unset($fcc); +?> Index: /modules/branches/2.6/ringgroups/i18n/sv_SE/LC_MESSAGES/ringgroups.po =================================================================== --- /modules/branches/2.6/ringgroups/i18n/sv_SE/LC_MESSAGES/ringgroups.po (revision 6951) +++ /modules/branches/2.6/ringgroups/i18n/sv_SE/LC_MESSAGES/ringgroups.po (revision 6951) @@ -0,0 +1,403 @@ +# Swedish translation. +# Copyright (C) 2008 +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Poedit-Language: Swedish\n" +"X-Poedit-Country: SWEDEN\n" + +#: functions.inc.php:35 +#, php-format +msgid "Ring Group %s: " +msgstr "Ringgrupp %s: " + +#: functions.inc.php:55 +#: functions.inc.php:248 +#, php-format +msgid "Ring Group: %s" +msgstr "Ringgrupp: %s" + +#: functions.inc.php:199 +msgid "This ringgroup" +msgstr "Denna ringgrupp" + +#: functions.inc.php:199 +msgid "is already in use" +msgstr "anvÀnds redan" + +#: functions.inc.php:249 +msgid "INUSE" +msgstr "ANVÄNDS" + +#: functions.inc.php:275 +#, php-format +msgid "Ringroup: %s (%s)" +msgstr "Ringgrupp: %s (%s)" + +#: install.php:164 +msgid "Checking if recordings need migration.." +msgstr "Kontrollerar om inspelningar behöver migreras.." + +#: install.php:170 +msgid "migrating" +msgstr "migrerar" + +#: install.php:171 +msgid "adding annmsg_id field.." +msgstr "lÀgger till fÀltet annmsg_id.." + +#: install.php:175 +#: install.php:184 +#: install.php:193 +#: install.php:205 +#: install.php:221 +#: install.php:231 +#: install.php:247 +#: install.php:257 +#: install.php:273 +msgid "fatal error" +msgstr "kritiskt fel" + +#: install.php:178 +#: install.php:187 +#: install.php:196 +#: install.php:287 +#: install.php:295 +#: install.php:303 +msgid "ok" +msgstr "ok" + +#: install.php:180 +msgid "adding remotealert_id field.." +msgstr "lÀgger till fÀltet remotealert_id.." + +#: install.php:189 +msgid "adding toolate_id field.." +msgstr "lÀgger till fÀltet toolate_id.." + +#: install.php:201 +msgid "migrate annmsg to ids.." +msgstr "migrerar annmsg till ids.." + +#: install.php:225 +#: install.php:251 +#: install.php:277 +#, php-format +msgid "migrated %s entries" +msgstr "migrerat %s poster" + +#: install.php:227 +msgid "migrate remotealert to ids.." +msgstr "migrerar remotealert till ids.." + +#: install.php:253 +msgid "migrate toolate to ids.." +msgstr "migrerar toolate till ids.." + +#: install.php:281 +msgid "dropping annmsg field.." +msgstr "kastar fÀltet annmsg.." + +#: install.php:285 +msgid "no annmsg field???" +msgstr "inget annmsg fÀlt???" + +#: install.php:289 +msgid "dropping remotealert field.." +msgstr "kastar fÀltet remotealet.." + +#: install.php:293 +msgid "no remotealert field???" +msgstr "inget remotealert fÀlt???" + +#: install.php:297 +msgid "dropping toolate field.." +msgstr "kastar toolate fÀltet" + +#: install.php:301 +msgid "no toolate field???" +msgstr "inget toolate fÀt???" + +#: install.php:307 +msgid "already migrated" +msgstr "redan migrerad" + +#: page.ringgroups.php:69 +msgid "Warning! Extension" +msgstr "Varning! Anknytning" + +#: page.ringgroups.php:69 +msgid "is not allowed for your account" +msgstr "Àr inte tillÃ¥tet för ditt konto" + +#: page.ringgroups.php:105 +#: page.ringgroups.php:182 +#: page.ringgroups.php:189 +msgid "Add Ring Group" +msgstr "LÀgg till ringgrupp" + +#: page.ringgroups.php:121 +#: page.ringgroups.php:152 +msgid "Ring Group" +msgstr "Ringgrupp" + +#: page.ringgroups.php:121 +msgid "deleted" +msgstr "borttagen" + +#: page.ringgroups.php:149 +msgid "Delete Group" +msgstr "Ta bort grupp" + +#: page.ringgroups.php:178 +msgid "Conflicting Extensions" +msgstr "Konfliktande anknytning" + +#: page.ringgroups.php:189 +msgid "Edit Ring Group" +msgstr "Redigera ringgrupp" + +#: page.ringgroups.php:197 +msgid "Ring-Group Number" +msgstr "Ringgruppsnummer" + +#: page.ringgroups.php:197 +msgid "The number users will dial to ring extensions in this ring group" +msgstr "Detta nummer kommer anvÀndarna att ringa för att komma till denna ringgrupp" + +#: page.ringgroups.php:203 +msgid "Group Description" +msgstr "Beskrivning för gruppen" + +#: page.ringgroups.php:203 +msgid "Provide a descriptive title for this Ring Group." +msgstr "Skriv in en kortfattat beskrivning för denna grupp" + +#: page.ringgroups.php:208 +msgid "Ring Strategy:" +msgstr "Ringstrategi" + +#: page.ringgroups.php:210 +msgid "ringall" +msgstr "ringalla" + +#: page.ringgroups.php:210 +msgid "Ring all available channels until one answers (default)" +msgstr "Ring pÃ¥ alla anknytningar tills nÃ¥gon svarar (standard)" + +#: page.ringgroups.php:211 +msgid "hunt" +msgstr "runda" + +#: page.ringgroups.php:211 +msgid "Take turns ringing each available extension" +msgstr "Ring runt pÃ¥ respektive anknytning" + +#: page.ringgroups.php:212 +msgid "memoryhunt" +msgstr "minnesrunda" + +#: page.ringgroups.php:212 +msgid "Ring first extension in the list, then ring the 1st and 2nd extension, then ring 1st 2nd and 3rd extension in the list.... etc." +msgstr "Ring första anknytningen i listan, ring sedan ettan och tvÃ¥an, ring sedan första, andra och tredje i listan..... etc" + +#: page.ringgroups.php:213 +msgid "*-prim" +msgstr "*-första" + +#: page.ringgroups.php:213 +msgid "These modes act as described above. However, if the primary extension (first in list) is occupied, the other extensions will not be rung. If the primary is FreePBX DND, it won't be rung. If the primary is FreePBX CF unconditional, then all will be rung" +msgstr "Dessa strategier fungerar som ovanstÃ¥ende. Men, om första anknytningen (den första i listan) Àr upptagen, kommer de andra anknytningarna i listan inta att ringas. Om den första anknytningen Àr FreePBX Stör Ej (DND), kommer den inte att ringas. Om den första anknytningen Àr FreePBX Vidarebefordra Samtal (CF) kommer alla anknytningar att ringas" + +#: page.ringgroups.php:214 +msgid "firstavailable" +msgstr "först-tillgÀnglig" + +#: page.ringgroups.php:214 +msgid "ring only the first available channel" +msgstr "ring bara den första tillgÀngliga kanalen" + +#: page.ringgroups.php:215 +msgid "firstnotonphone" +msgstr "första-inte-upptagen" + +#: page.ringgroups.php:215 +msgid "ring only the first channel which is not offhook - ignore CW" +msgstr "ring endast den första kanalen som inte Àr upptagen - strunta i Samtal VÀntar (CF)" + +#: page.ringgroups.php:233 +msgid "Ring Time (max 60 sec)" +msgstr "Ringtid (max 60 sek)" + +#: page.ringgroups.php:235 +msgid "Time in seconds that the phones will ring. For all hunt style ring strategies, this is the time for each iteration of phone(s) that are rung" +msgstr "Tid i sekunder som telefonen kommer att ringa. För alla rund-rings-strategier, detta Àr tiden för varje runda av telefoner som rings" + +#: page.ringgroups.php:243 +msgid "Extension List" +msgstr "Anknytningslista" + +#: page.ringgroups.php:243 +msgid "List extensions to ring, one per line, or use the Extension Quick Pick below to insert them here.

You can include an extension on a remote system, or an external number by suffixing a number with a '#'. ex: 2448089# would dial 2448089 on the appropriate trunk (see Outbound Routing)

Extensions (without a '#' will not ring a user's Follow-Me. To dial Follow-Me, Queues and other numbers that are not extensions, put a '#' at the end." +msgstr "Lista med anknytningar att ringa, en per rad, eller vÀlj i snabbvalslistan nedan för att inkludera dom hÀr.

Du kan inkludera ett externt nummer genom att skriva ett '#' efter telefonnumret, t.ex. 040123456#, då kommer nummer 040123456 att ringas upp via lÀmplig trunk (se Utgående vÀg)

Anknytningar utan '#' kommer inte att ringa Följ-Mig. För att ringa Följ-Mig, Köer och andra nummer som inte Àr anknytningar,lÀgg till ett '#' i slutet." + +#: page.ringgroups.php:255 +msgid "Extension Quick Pick" +msgstr "Snabbvalslista för anknytningar" + +#: page.ringgroups.php:257 +msgid "Choose an extension to append to the end of the extension list above." +msgstr "VÀlj en anknytning för att lÀgga till den i slutet på anknytningsl