Code

Added schema updated - homeServer for conferences
[gosa.git] / plugins / gofon / phoneaccount / class_phoneAccount.inc
index 3c2f020b46bd2adf75f3783dfe6df2f6117dccce..56347c7032c1533f3b9b7ec08f93b2cda2585ab3 100644 (file)
@@ -8,24 +8,29 @@ class phoneAccount extends plugin
   var $has_mailAccount= FALSE;
 
   /* Attributes */
-  var $telephoneNumber        = "";
-  var $goFonHardware          = "";
-  var $goFonForwarding        = "";
-  var $goFonFormat            = "";
+  var $telephoneNumber        = array();
+  var $goFonHardware          = "automatic";
+  var $goFonFormat            = "wav";
   var $goFonPIN               = "";
+  var $goFonVoicemailPIN      = "";
   var $goFonDeliveryMode      = "";
   var $phoneNumbers           = array();
-  var $forwarders             = array();
   var $mail                   = "";
   var $hardware_list          = array();
   var $used_hardware          = array();
   var $goFonMacro             = "";
-  var $macro                  = 0;              // Selected Macor
+  var $macro                  = 0;              // Selected Macroi
+  var $lastmacro              = "";
   var $macros                 = array();        // List of macros for smarty select box
   var $macroarray             = array();        // All needed macro informations
   var $macrostillavailable    = false;
   var $generate_error         = "";
-  var $a_old_telenums           = array();
+  var $a_old_telenums         = array();
+  var $goFonPINVoice          = "";
+  var $goFonHomeServer        = "0";            // Contains the dn of the server that manage this account 
+  var $init_HomeServer        = "0";            // Contains the dn of the server that manage this account 
+  var $goFonHomeServers       = array();        // Contains all available server configurations 
+    
 
   /* CLI vars */
   var $cli_summary            = "Manage users phone account";
@@ -33,23 +38,18 @@ class phoneAccount extends plugin
   var $cli_parameters         = array("eins" => "Eins ist toll", "zwei" => "Zwei ist noch besser");
 
   /* attribute list for save action */
-  var $attributes             = array("goFonDeliveryMode", "goFonForwarding", "goFonFormat",
-      "goFonHardware", "goFonPIN", "telephoneNumber", "goFonMacro","macro");
-  var $objectclasses= array("goFonAccount");
+  var $CopyPasteVars          = array("phoneNumbers","macroarray","macrostillavailable"/*"phoneNumbers" -Reset- */,
+                                      "hardware_list","used_hardware");
 
-  function phoneAccount ($config, $dn= NULL)
-  {
-    plugin::plugin ($config, $dn);
+  var $attributes             = array("goFonDeliveryMode", "goFonFormat","uid","cn","goFonHomeServer",
+      "goFonHardware","goFonPIN","goFonVoicemailPIN","telephoneNumber", "goFonMacro","macro");
+  var $objectclasses= array("goFonAccount");
 
-    /* Set phone hardware */
-    if (!isset($this->attrs['goFonHardware'])){
-      $this->goFonHardware= "automatic";
-    }
+  var $uid;
 
-    /* Preset voice format */
-    if (!isset($this->attrs['goFonFormat'])){
-      $this->goFonFormat= "wav";
-    }
+  function phoneAccount ($config, $dn= NULL, $parent= NULL)
+  {
+    plugin::plugin ($config, $dn, $parent);
 
     /* Assemble phone numbers */
     if (isset($this->attrs['telephoneNumber'])){
@@ -59,16 +59,6 @@ class phoneAccount extends plugin
       }
     }
 
-    /* Assemble forwarders */
-    if (isset($this->attrs['goFonForwarding'])){
-      for ($i= 0; $i<$this->attrs['goFonForwarding']['count']; $i++){
-        list($num, $v1, $v2) =split(';', $this->attrs['goFonForwarding'][$i]);
-        $this->forwarders[$num]= "$v1;$v2";
-      }
-    } else {
-      $this->forwarders= array("");
-    }
-
     /* Set up has_mailAccount */
     if (isset($this->attrs['objectClass'])){
       if (in_array("gosaMailAccount", $this->attrs['objectClass'])){
@@ -76,7 +66,66 @@ class phoneAccount extends plugin
       }
     }
 
-    /* Load hardware list */
+
+    /* Check server configurations 
+     * Load all server configuration in $this->goFonHomeServers if available
+     *  and first server as default if necessary.
+     * Check if connection is successfull for the selected server $this->goFonHomeServer
+     */
+    $a_SETUP= array();
+    if(array_key_exists('config',$_SESSION) &&
+       array_key_exists('SERVERS',$_SESSION['config']->data) &&
+       array_key_exists('FON',$_SESSION['config']->data['SERVERS']) &&
+       is_callable("mysql_connect")
+       ) {
+
+      /* Set available server */
+      $this->goFonHomeServers = $_SESSION['config']->data['SERVERS']['FON'];
+
+      /* Servers defined? Watch here... */
+      if (count($this->goFonHomeServers)){
+
+        /* Set default server */
+        if(empty($this->goFonHomeServer) || $this->goFonHomeServer == "0"){
+          $this->goFonHomeServer= $this->goFonHomeServers[0]['DN'];
+        }
+
+        /* Remember inital home server, to be able to remove old entries */
+        $this->init_HomeServer = $this->goFonHomeServer;
+
+        /* Get config */
+        if(!isset($this->goFonHomeServers[$this->goFonHomeServer])){
+          print_red(sprintf(_("The specified goFonHomeServer '%s' is not available in GOsa server configuration. Saving this account will create a new entry on the server '%s'. Use cancel if you do not want to create a new entry ignoring old accounts."),$this->goFonHomeServer, $this->goFonHomeServers[0]['DN']));
+
+          $this->goFonHomeServer = $this->goFonHomeServers[0]['DN'];
+          $this->init_HomeServer = $this->goFonHomeServers[0]['DN'];
+        }    
+        $cur_cfg = $this->goFonHomeServers[$this->goFonHomeServer];
+
+        $r_con =  @mysql_pconnect($cur_cfg['SERVER'],$cur_cfg['LOGIN'],$cur_cfg['PASSWORD']);
+        if(!$r_con){
+          print_red( sprintf(_("The MySQL Server '%s' isn't reachable as user '%s', check GOsa log for mysql error."),
+                $cur_cfg['SERVER'],$cur_cfg['LOGIN']));
+          gosa_log(mysql_error());
+        }
+        $db  =  @mysql_select_db($cur_cfg['DB'],$r_con);
+        if(!$db){
+          print_red(sprintf(_("Can't select database %s on %s."),$cur_cfg['DB'],$cur_cfg['SERVER']));
+          gosa_log(mysql_error());
+        }
+
+        $first = false; 
+        foreach($this->phoneNumbers as $key => $val){
+          if(!$first){
+            $first = $key;
+          }
+        }
+      }
+    }
+
+    /* Get available phone hardware  
+     * Search for all available phone hardware  
+     */
     $ldap= $this->config->get_ldap_link();
     $ldap->cd($this->config->current['BASE']);
     $ldap->search("(objectClass=goFonHardware)", array('cn', 'description'));
@@ -88,65 +137,65 @@ class phoneAccount extends plugin
         $description= "";
       }
       $this->hardware_list[$cn]= "$cn$description";
-
     }
 
-    /* Prepare templating */
-    $smarty= get_smarty();
-
 
-    /* Perform search, to get Macro Parameters,Name,Dn,Displayname etc*/
-    $ldap->search("(objectClass=goFonMacro)", array("*"));
+    /* Get available Macros  
+     * Search for all Marcos that are visible and create 
+     *  an array with name and parameters 
+     */
+    $ldap->search("(&(objectClass=goFonMacro)(goFonMacroVisible=1))", array("*"));
 
     /* Add none for no macro*/
     $this->macros['none']=_("no macro");    
     $this->macro ="none";
 
-
     /* Fetch all Macros*/
     while ($attrs= $ldap->fetch()){
 
-      /* Only visisble */
-      if((isset($attrs['goFonMacroVisible'][0]))&&($attrs['goFonMacroVisible'][0] ==1)){
-
-        /* unset Count, we don't need that here */
-        unset($attrs['displayName']['count']);
-
-        /* fill Selectfield variable with Macros */
-        if(isset($attrs['displayName'][0])){
-          $this->macros[$attrs['dn']] = $attrs['displayName'][0]." (".$attrs['cn'][0].")";
-        }else{
-          $this->macros[$attrs['dn']] = _("undefined");
-        }
+      /* unset Count, we don't need that here */
+      unset($attrs['displayName']['count']);
 
-        /* Parse macro data, unset count for parameterarrays  */
+      /* Parse macro data, unset count for parameterarrays  */
+      if (isset($attrs['goFonMacroParameter']['count'])){
         unset($attrs['goFonMacroParameter']['count']);
+      }
 
-        /* Go through available parameters and parse all attributes, like parametername, type, default ...*/
-        if((isset($attrs['goFonMacroParameter']))&&(is_array($attrs['goFonMacroParameter']))){
-
-          foreach($attrs['goFonMacroParameter'] as $pkey=>$pval){
-
-            /* Split Data in readable values, by delimiter !  */
-            $data = split("!",$attrs['goFonMacroParameter'][$pkey]);
+      /* fill Selectfield variable with Macros */
+      if(isset($attrs['displayName'][0])){
+        $this->macros[$attrs['dn']] = $attrs['displayName'][0]." (".$attrs['cn'][0].")";
+      }else{
+        $this->macros[$attrs['dn']] = _("undefined");
+      }
 
-            /* Set all attrs */
-            $id = $data[0];
-            $this->macroarray[$attrs['dn']][$id]['var']    ="var".$id;
+      /* Go through available parameters and parse all attributes, like parametername, type, default ...*/
+      if((isset($attrs['goFonMacroParameter']))&&(is_array($attrs['goFonMacroParameter']))){
+
+        foreach($attrs['goFonMacroParameter'] as $pkey=>$pval){
+          /* Split Data in readable values, by delimiter !  */
+          $data = split("!",$attrs['goFonMacroParameter'][$pkey]);
+
+          /* Set all attrs */
+          $id = $data[0];
+          $this->macroarray[$attrs['dn']][$id]['var']    ="var".$id;
+          $this->macroarray[$attrs['dn']][$id]['choosen']=$data[3]; 
+          $this->macroarray[$attrs['dn']][$id]['id']     =$id;
+          $this->macroarray[$attrs['dn']][$id]['name']   =$data[1];
+          $this->macroarray[$attrs['dn']][$id]['type']   =$data[2];
+          $this->macroarray[$attrs['dn']][$id]['default']=$data[3];
+          if($data[2] == "bool"){
             $this->macroarray[$attrs['dn']][$id]['choosen']=$data[3];
-            $this->macroarray[$attrs['dn']][$id]['id']     = $id;
-            $this->macroarray[$attrs['dn']][$id]['name']   =$data[1];
-            $this->macroarray[$attrs['dn']][$id]['type']   =$data[2];
-            $this->macroarray[$attrs['dn']][$id]['default']=$data[3];
-          }//foreach
-        }//is_array
-      }//visible = 1
+          }
+        }//foreach
+      }//is_array
     }//while
 
-    /* Go through already saved values, for a parameter */
-    $tmp = split("!",$this->goFonMacro);
 
-    /* it is possible that nothing has been saved yet */
+    /* Parse used Macro  
+     * If we have a macro selected, parse it and set values 
+     *  in $this->macroarray[$this->macro]. 
+     */
+    $tmp = split("!",$this->goFonMacro);
     if(is_array($tmp)){
 
       /* First value is the macroname */
@@ -156,7 +205,7 @@ class phoneAccount extends plugin
       unset($tmp[0]);
 
       /* Check if makro has been removed */
-      if(!isset($this->macroarray[$this->macro])){
+      if(!isset($this->macros[$this->macro])){
         $this->macrostillavailable = false;
       }else{
         $this->macrostillavailable = true;
@@ -170,14 +219,17 @@ class phoneAccount extends plugin
 
         /* Only insert if the parameter still exists */
         if(isset($this->macroarray[$this->macro][$varar[0]])){
-
           /* Assign value */
           $this->macroarray[$this->macro][$varar[0]]['choosen']=$varar[1];
         }
       }
     }
 
-    /* Eventually colorize phones */
+
+    /* Colorize phones 
+     * Used phones will be colored in grey, 
+     *  so we must detect which phones are currently in use.
+     */
     $ldap->cd($this->config->current['BASE']);
     foreach ($this->hardware_list as $cn => $desc){
       $ldap->search("(goFonHardware=$cn)", array('cn'));
@@ -188,197 +240,479 @@ class phoneAccount extends plugin
         }
       }
     }
-
     $this->hardware_list["automatic"]= _("automatic");
     ksort($this->hardware_list);
     $this->a_old_telenums = $this->phoneNumbers;
+
+    if($this->is_account){
+      $this->is_modified = true;
+    }
+
+
+    /* Get voicemail PIN from MySQL DB 
+     * Because every user can change his PIN directly from the phone
+     *  without any update to the ldap
+     * This means, the PIN in the DB is up to date
+     */
+    // Connect to DB server
+    if((is_callable("mysql_pconnect"))&&(isset($cur_cfg))&&(isset($cur_cfg['SERVER']))&&(isset($cur_cfg['LOGIN']))&&(isset($cur_cfg['PASSWORD']))){
+      $r_con =  @mysql_pconnect($cur_cfg['SERVER'],$cur_cfg['LOGIN'],$cur_cfg['PASSWORD']);
+      if($r_con){
+        $r_db  =  @mysql_select_db($cur_cfg['DB'],$r_con);
+        $vp = mysql_fetch_row(mysql_query("SELECT ".$cur_cfg['VOICE_TABLE'].".password FROM  ".$cur_cfg['VOICE_TABLE'].", ".$cur_cfg['SIP_TABLE']."  WHERE customer_id = sip_users.mailbox AND name='".$this->uid."'"));
+
+        if((isset($vp[0]))&&(!empty($vp[0]))){
+          $this->goFonPINVoice = $vp[0];
+        }
+      }
+    }
+    $this->lastmacro=$this->macro;
+
+    if(is_callable("mysql_close")&&(isset($r_con))&&($r_con)){
+      @mysql_close($r_con) ;
+    }
   }
 
 
+  /* This function generates the Database entries. 
+   * The Parameter 'save' could be true or false.
+   *  false - means only testing no database transactions.
+   *  true  - write database entries.
+   *
+   * 'sip_users','voice_mail' and 'extensions' table entries will be created.
+   * 
+   * If the phone hardware is 'automatic' the table entries will only be removed
+   *  and not added. 
+   */
+  function generate_mysql_entension_entries($save = false)
+  {
+    /* Check if there is at least one server available 
+     * If not, return and tell the user that saving failed 
+     */
+    if(!count($this->goFonHomeServers)){
+      if($save){
+        print_red(_("There is currently no asterisk server defined. Possibly you are missing a server that handles the asterisk management (goFonServer). Your settings can't be saved to asterisk database."));
+      }
+      return(true);
+    }
 
+    /* Check if Mysql extension is available */
+    if(!is_callable("mysql_pconnect")){
+      if($save)
+      print_red(_("Can't save any changes to asterisk database, there is no mysql extension available."));
+      return(true);
+    }
+    /********************** 
+     * Attribute Initialisation
+     **********************/
 
-  // Generate MySQL Syntax
-  function generate_mysql_entension_entries($save = false){
+    $old_connection = false;
 
     // Get Configuration for Mysql database Server
-    $a_SETUP = $_SESSION['config']->data['SERVERS']['FON'];
-    $s_parameter  ="";
+    $s_parameter    = "";                                           // Contains paramter for selected Macro 
+    $r_con          = false;                                        // DB connection
+    $r_db           = false;                                        // Selected DB
+    $r_res          = false;                                        // Result resource
+    $a_ldap_attrs   = array();                                      //  
 
-    // Connect to DB server
-    $r_con =  @mysql_connect($a_SETUP['SERVER'],$a_SETUP['LOGIN'],$a_SETUP['PASSWORD']);
+    $s_ip           = NULL;                   // Contains ip for Sip entry
+    $s_host         = NULL;                   // Contains host for Sip entry
+    $s_qualify      = "yes";                  // Qualify entry
+    $s_pin          = NULL;                   // Entry for secret
+    $s_type         = NULL;                   // Entry for phone type (friend , peer ..)
 
-    // Check if we are  connected correctly
-    if(!$r_con){
-      $this->generate_error = sprintf(_("The MySQL Server '%s' isn't reachable as user '%s', check GOsa log for mysql error."),
-          $a_SETUP['SERVER'],$a_SETUP['LOGIN']);
-      gosa_log(mysql_error());
-      return false;
+    $sip_data_array = array();                // Contains complete sip entry, to generate SQL syntax
+    $i_old_key      = false;                  // Contains index for first old phonenumber, to delete old entries corectly
+    $i_new_key      = false;                  // Contains index for first new phonenumber, to generate new  entries corectly
+
+    $s_sip_values   = "";     // Contains string with all values for given attributes in SQL syntax
+    $s_sip_keys     = "";     // Contains all needed attributes to generate sip entry in DB
+
+    $s_sip_key      = "";     // Key for SIP entry index      
+    $s_sip_val      = "";     // Value for SIP entry index      
+
+    $b_first_deleted= false;  // Only delete first entry, 
+    $s_telenums     = "";     // for each value variable
+
+    $i_is_accounted = false;  // Ensure that extension entry, for name to number is only once in table
+
+    restore_error_handler();
+
+    /* Prepare some basic attributes */
+    foreach($this->a_old_telenums as $tele){
+      $oldnums[]= preg_replace("/[^0-9]/","",$tele);
+    }
+    foreach($this->phoneNumbers as $tele){
+      $newnums[]= preg_replace("/[^0-9]/","",$tele);
     }
 
-    // Select database for Extensions
-    $db  =  @mysql_select_db($a_SETUP['DB'],$r_con);
+    /* If deletion starts from userslist, cn uid are not set */
+    if((isset($this->parent->by_object['user']->uid))&&(!empty($this->parent->by_object['user']->uid))){
+      $this->uid = $this->parent->by_object['user']->uid;
+    }
+    if((isset($this->parent->by_object['user']->cn))&&(!empty($this->parent->by_object['user']->cn))){
+      $this->cn  = $this->parent->by_object['user']->cn;
+    }
+    /* Create voicemail entry 
+     */
+    if((!isset($this->cn))||(empty($this->cn))){
+      $CNname= $this->uid;
+    }else{
+      $CNname= $this->cn;
+    }
 
-    // Test if we have the database selected correctly
-    if(!$db){
-      $this->generate_error = sprintf(_("Can't select database %s on %s."),$a_SETUP['DB'],$a_SETUP['SERVER']);
-      gosa_log(mysql_error());
-      return false;
+    if((isset($this->parent))&&(isset($this->parent->by_object['mailAccount']))&&($this->parent->by_object['mailAccount']->is_account==true)){
+      $s_mail = $this->parent->by_object['mailAccount']->mail;
+    }else{
+      $s_mail = "";
+    }
+    /* Get phonehardware to setup sip entry  */
+    $ldap         = $this->config->get_ldap_link();
+    $r_res        = $ldap->search("(&(objectClass=goFonHardware)(cn=".$this->goFonHardware."))", array('*'));
+    $a_ldap_attrs = $ldap->fetch();
+
+    /* Check selected phone hardware, is a default IP set? */
+    if(((isset($a_ldap_attrs['goFonDefaultIP'][0]))&&($a_ldap_attrs['goFonDefaultIP'][0] != "dynamic"))){
+      $s_ip       = $a_ldap_attrs['goFonDefaultIP'][0];
+      $s_host     = $s_ip;
+    }else{
+      $s_ip       = NULL;
+      $s_host     = "dynamic";
     }
 
-    // Save data 
-    if($save == true){
+    // Attribute GoFonQualify set ?
+    if(isset($a_ldap_attrs['goFonQualify'])){
+      $s_qualify = $a_ldap_attrs['goFonQualify'][0];
+    }
 
-      // Get phonehardware to setup sip entry
-      $ldap= $this->config->get_ldap_link();
-      $res = $ldap->search("(&(objectClass=goFonHardware)(cn=".$this->goFonHardware."))", array('*'));
-      $attrs = $ldap->fetch();
+    // Attribute GoFonPIN set ?
+    if(isset($this->goFonPIN)){
+      $s_pin      = $this->goFonPIN;
+    }
 
-      // Attribute GoFonDefaultIP set ?
-      if(((isset($attrs['goFonDefaultIP'][0]))&&($attrs['goFonDefaultIP'][0] != "dynamic"))){
-        $ip = $attrs['goFonDefaultIP'][0];
-        $host = $ip;
-      }else{
-        $ip = NULL;
-        $host = "dynamic";
-      }
+    // Attribute GoFonType set ?
+    if(isset($a_ldap_attrs['goFonType'])){
+      $s_type = $a_ldap_attrs['goFonType'][0];
+    }
 
-      // Attribute GoFonQualify set ?
-      if(!isset($attrs['goFonQualify'])){
-        $qualify = NULL;
-      }else{
-        $qualify = $attrs['goFonQualify'][0];
-      }
+    if(isset($a_ldap_attrs['goFonDmtfMode'][0])){
+      $sip_data_array['dtmfmode']     = $a_ldap_attrs['goFonDmtfMode'][0];
+    }else{
+      $sip_data_array['dtmfmode']     ="rfc2833";
+    }
 
-      // Attribute GoFonPIN set ?
-      if(!isset($this->goFonPIN)){
-        $pin = NULL;
-      }else{
-        $pin = $this->goFonPIN;
-      }
+    /* Check if phone number is used */
+    if($this->is_number_used()){
+      $this->generate_error = $this->is_number_used(); 
+      return false;
+    }
 
-      // Attribute GoFonType set ?
-      if(!isset($attrs['goFonType'])){
-        $type = NULL;
-      }else{
-        $type = $attrs['goFonType'][0];
+
+
+    /********************** 
+     * Check Server Connection Information
+     **********************/
+    /* Create Mysql handle for the current goFonHomeServer, if possible  
+     * Get configuration to old asterisk home server 
+     */ 
+    $a_New = $this->goFonHomeServers[$this->goFonHomeServer];  // DB Configuration
+    $new_connection =  @mysql_pconnect($a_New['SERVER'],$a_New['LOGIN'],$a_New['PASSWORD']);
+    if(!$new_connection){
+      $this->generate_error = sprintf(
+          _("The MySQL Server '%s' isn't reachable as user '%s'. Abort saving entries to keep the database consistent, check GOsa log for mysql error."),
+          $a_New['SERVER'],$a_New['LOGIN']);
+      gosa_log(@mysql_error($new_connection));
+      return false;
+    }
+    $new_database  =  @mysql_select_db($a_New['DB'],$new_connection);
+    if(!$new_database){
+      $this->generate_error = sprintf(
+          _("Can't select database %s on %s. Abort saving entries to keep the database consistent, check GOsa log for mysql error."),
+          $a_New['DB'],$a_New['SERVER']);
+      gosa_log( @mysql_error($new_connection));
+      return false;
+    }
+
+    /* If the home server has changed, we must remove entries from old 
+     *  server and add new entries in new server.  
+     */
+    if($this->init_HomeServer != $this->goFonHomeServer){
+    
+      /* Get configuration to old asterisk home server */ 
+      $a_Remove = $this->goFonHomeServers[$this->init_HomeServer];  // DB Configuration
+      /* Create connection to the database that contains the old entry. 
+       */
+      $old_connection =  @mysql_pconnect($a_Remove['SERVER'],$a_Remove['LOGIN'],$a_Remove['PASSWORD']);
+      if(!$old_connection){
+        $this->generate_error = sprintf(
+            _("The old MySQL home server '%s' isn't reachable as user '%s'. Abort saving entries to keep the database consistent, check GOsa log for mysql error."),
+            $a_Remove['SERVER'],$a_Remove['LOGIN']);
+        gosa_log(@mysql_error($old_connection));
+        return false;
+      }
+      $old_database  =  @mysql_select_db($a_Remove['DB'],$old_connection);
+      if(!$old_database){
+        $this->generate_error = sprintf(
+            _("Can't select database %s on %s. Abort saving entries to keep the database consistent, check GOsa log for mysql error."),
+            $a_Remove['DB'],$a_Remove['SERVER']);
+        gosa_log(@mysql_error($old_connection));
+        return false;
       }
+    }
 
-      // generate SIP entry
-      $sip_data_array['id']           = "";
-      $sip_data_array['name']         = $this->uid;
-      $sip_data_array['accountcode']  = NULL;          
-      $sip_data_array['amaflags']     = NULL;
-      $sip_data_array['callgroup']    = NULL;
-      $sip_data_array['callerid']     = "";
-      $sip_data_array['canreinvite']  = "yes";
+    /* Save means that we must save changes, not only test  */
+    if($save == true){
     
-      // Must be default and the name of an entry that already exists
-      $sip_data_array['context']      = "default";
-      $sip_data_array['defaultip']    = NULL;
-      
-      if(isset($attrs['goFonDmtfMode'][0])){
-        $sip_data_array['dtmfmode']     = $attrs['goFonDmtfMode'][0];
-      }else{
-        $sip_data_array['dtmfmode']     ="rfc2833";
-      }
-      $sip_data_array['fromuser']     = NULL;
-      $sip_data_array['fromdomain']   = NULL;
-      $sip_data_array['host']         = $host;
-      $sip_data_array['insecure']     = NULL;
-      $sip_data_array['language']     = NULL;
-      $sip_data_array['mailbox']      = "asterisk";
-      $sip_data_array['md5secret']    = NULL;
-      $sip_data_array['nat']          = "no";
-      $sip_data_array['permit']       = NULL;
-      $sip_data_array['deny']         = NULL;
-      $sip_data_array['mask']         = NULL;
-      $sip_data_array['pickupgroup']  = NULL;
-      $sip_data_array['port']         = NULL;
-      $sip_data_array['qualify']      = $qualify;
-      $sip_data_array['restrictcid']  = "n";
-      $sip_data_array['rtptimeout']   = NULL;
-      $sip_data_array['rtpholdtimeout']=NULL;
-      $sip_data_array['secret']       = $pin;
-      $sip_data_array['type']         = $type ;
-      $sip_data_array['username']     = $this->uid;
-      $sip_data_array['disallow']     = NULL;
-      $sip_data_array['allow']        = NULL;
-      $sip_data_array['musiconhold']  = NULL;
-      $sip_data_array['regseconds']   = NULL;
-      $sip_data_array['ipaddr']       = $ip;
-      $sip_data_array['regexten']     = NULL;
-      $sip_data_array['cancallforward']=NULL;
+      /********************** 
+       * Remove entries from old home server 
+       **********************/
+
+      /* Check if there is an old entry 
+       * If there is en old entry, get callerid and remove voicemail and extensions too 
+       */
+      if($old_connection){
+        $query  = "SELECT id,name,callerid FROM ".$a_Remove['SIP_TABLE']." WHERE name='".$this->uid."';";
+        $rid    = mysql_query($query,$old_connection);
+
+        /* Old entry found, remove it */
+        $query_a = array();
+        if(mysql_affected_rows($old_connection)){
+          $result = mysql_fetch_assoc($rid);
+          $query_a[]= "DELETE FROM ".$a_Remove['SIP_TABLE']." WHERE name='".$this->uid."';";
+          $query_a[]= "DELETE FROM ".$a_Remove['VOICE_TABLE']." WHERE customer_id='".$result['callerid']."';";
+          $query_a[]= "DELETE FROM ".$a_Remove['EXT_TABLE']." WHERE exten='".$this->uid."';";
+          foreach($oldnums as $s_telenums) {
+            $query_a[]= "DELETE FROM ".$a_Remove['EXT_TABLE']." WHERE exten='".$s_telenums."';";
+          }
 
-      // Get selected Macro Parameter and create parameter entry 
-      if(isset($this->macroarray[$this->macro])){
-        foreach($this->macroarray[$this->macro] as $key => $val ){
-          $s_parameter .= $val['choosen']."|";
+          foreach($query_a as $qry){
+            if(!mysql_query($qry,$old_connection)){
+              echo $qry;
+              echo mysql_error($old_connection);
+            } 
+          }
         }
-        $s_parameter = preg_replace("/\|$/","",$s_parameter);
       }
 
-      // $SQL contains all queries
-      $SQL = array();
-      $SQL[] = "DELETE FROM ".$a_SETUP['EXT_TABLE']." WHERE exten='".$this->uid."';\n";
-      $SQL[] = "DELETE FROM ".$a_SETUP['SIP_TABLE']." WHERE name='".$this->uid."';\n";
+      /********************** 
+       * Update / Insert sip_users entry  
+       **********************/
+
+      /* Set the first given phone number as callerid */
+      reset($newnums);        
+      $i_new_key = key($newnums);
+      $sip_data_array['callerid']  =$newnums[$i_new_key];
+      $sip_data_array['mailbox']   =$newnums[$i_new_key];
+
+      /* Check if there is already an entry in sip_users for this uid */
+      $SQL_query_array = array();
+      $rid = mysql_query("SELECT * FROM ".$a_New['SIP_TABLE']." WHERE name='".$this->uid."';\n",$new_connection);
+      if(mysql_affected_rows($new_connection)){
+
+        /********************** 
+         * Update sip_users entry 
+         **********************/
+        $result                     = mysql_fetch_assoc($rid);
+        $sip_data_array['host']         = $s_host;
+        $sip_data_array['qualify']      = $s_qualify;
+        $sip_data_array['secret']       = $this->goFonPIN;
+        $sip_data_array['type']         = $s_type ;
+        $sip_data_array['username']     = $this->uid;
+        $sip_data_array['ipaddr']       = $s_ip;
+
+        /* Remove not changed attributes, to avoid updating table with same values */
+        foreach($sip_data_array as $name => $value){
+          if($result[$name] == $value){
+            unset($sip_data_array[$name]);
+          }
+        }
+        /* Only update entry if there is something to uopdate */
+        if(count($sip_data_array)){
+          $query = "UPDATE ".$a_New['SIP_TABLE']." SET ";
+          foreach($sip_data_array as $key => $val){
+            $query.= "".$key."='".$val."',"; 
+          } 
+          $query = preg_replace("/,$/","",$query);
+          $query.= " WHERE name='".$this->uid."';";
+          $SQL_query_array[] = $query;
+        }
+      } else {
+        /********************** 
+         * Insert sip_users entry 
+         **********************/
+        //generate SIP entry
+        $sip_data_array['id']           = "";
+        $sip_data_array['name']         = $this->uid;
+        $sip_data_array['accountcode']  = NULL;          
+        $sip_data_array['amaflags']     = NULL;
+        $sip_data_array['callgroup']    = NULL;
+        $sip_data_array['canreinvite']  = "no";
+        $sip_data_array['context']      = "default";
+        $sip_data_array['defaultip']    = NULL;
+        $sip_data_array['fromuser']     = NULL;
+        $sip_data_array['fromdomain']   = NULL;
+        $sip_data_array['host']         = $s_host;
+        $sip_data_array['insecure']     = NULL;
+        $sip_data_array['language']     = NULL;
+        $sip_data_array['mailbox']      = $newnums[$i_new_key];
+        $sip_data_array['md5secret']    = NULL;
+        $sip_data_array['nat']          = "no";
+        $sip_data_array['permit']       = NULL;
+        $sip_data_array['deny']         = NULL;
+        $sip_data_array['mask']         = NULL;
+        $sip_data_array['pickupgroup']  = NULL;
+        $sip_data_array['port']         = NULL;
+        $sip_data_array['qualify']      = $s_qualify;
+        $sip_data_array['restrictcid']  = "n";
+        $sip_data_array['rtptimeout']   = NULL;
+        $sip_data_array['rtpholdtimeout']=NULL;
+        $sip_data_array['secret']       = $this->goFonPIN;
+        $sip_data_array['type']         = $s_type ;
+        $sip_data_array['username']     = $this->uid;
+        $sip_data_array['disallow']     = NULL;
+        $sip_data_array['allow']        = NULL;
+        $sip_data_array['musiconhold']  = NULL;
+        $sip_data_array['regseconds']   = NULL;
+        $sip_data_array['ipaddr']       = $s_ip;
+        $sip_data_array['regexten']     = NULL;
+        $sip_data_array['cancallforward']=NULL;
+
+        /* There is currently no entry for this user in the sip_users table. 
+         * We should create one i
+         */
+        foreach($sip_data_array as $s_sip_key=>$s_sip_val){
+          if($s_sip_val == NULL) continue;
+          $s_sip_values.="'".$s_sip_val."',";
+          $s_sip_keys  .="`".$s_sip_key."`,";
+        }
+        $s_sip_values =  preg_replace("/,$/","",$s_sip_values);
+        $s_sip_keys   =  preg_replace("/,$/","",$s_sip_keys);
 
-      // Create new SIP entry ...
-      $sip_entry = $sip_data_array;
-    
-      reset($this->phoneNumbers);
-  
-      $key = key($this->phoneNumbers);
-      $sip_entry['callerid']  =$this->phoneNumbers[$key];
-     
-      if(isset($this->parent->by_object['mailAccount']->mail)){
-        $mail = $this->parent->by_object['mailAccount']->mail;
-      }else{
-        $mail = "";
+        /* Add sip entries to mysql queries */
+        $SQL_query_array[] ="INSERT INTO ".$a_New['SIP_TABLE']." (".$s_sip_keys.") VALUES (".$s_sip_values.");";
       }
 
 
-      $SQL[]= "DELETE FROM ".$a_SETUP['VOICE_TABLE']." WHERE customer_id='".$this->phoneNumbers[$key]."';"; 
-      $SQL[]= "INSERT INTO ".$a_SETUP['VOICE_TABLE']." 
-                  (`customer_id`,`context`,`mailbox`,`password`,`fullname`,`email`,`pager`) 
-               VALUES 
-                  ('".$this->phoneNumbers[$key]."','default','".$this->phoneNumbers[$key]."','".$this->goFonPIN."','".$this->sn."','".$mail."','');";
+      /********************** 
+       * Update / Insert Voice mail entry  
+       **********************/
 
-      // Generate Strings with keys and values 
-      $values = "";
-      $keys   = "";
-      foreach($sip_entry as $key=>$val){
-        if($val == NULL) continue;
-        $values.="'".$val."',";
-        $keys  .="`".$key."`,";
-      }
-      // Remove last ,
-      $values =  preg_replace("/,$/","",$values);
-      $keys   =  preg_replace("/,$/","",$keys);
+      $customer_id = $newnums[$i_new_key];
 
-      // Append SIP Entry 
-      $SQL[] ="INSERT INTO ".$a_SETUP['SIP_TABLE']." (".$keys.") VALUES (".$values.");";
+      $voice_data_array = array(
+          "customer_id" => $customer_id,
+          "mailbox"     => $customer_id,
+          "password"    => $this->goFonVoicemailPIN,
+          "fullname"    => $CNname,
+          "email"       => $s_mail);
 
-      // Delete old entries
-      foreach($this->a_old_telenums as $s_telenums){
-        $SQL[] = "DELETE FROM ".$a_SETUP['EXT_TABLE']." WHERE exten='".$s_telenums."';\n";
+      /* Check if there is already an entry in sip_users for this uid */
+      $rid = mysql_query("SELECT * FROM ".$a_New['VOICE_TABLE']." WHERE customer_id='".$customer_id."';\n",$new_connection);
+      if(mysql_affected_rows($new_connection)){
+
+        /********************** 
+         * Update Voice mail entry  
+         **********************/
+        $result = mysql_fetch_assoc($rid)  ;
+
+        foreach($voice_data_array as $name => $value){
+          if($result[$name] == $value){
+            unset($voice_data_array[$name]);
+          }
+        }
+
+        /* Only update entry if there is something to uopdate */
+        if(count($voice_data_array)){
+          $query = "UPDATE ".$a_New['VOICE_TABLE']." SET ";
+          foreach($voice_data_array as $key => $val){
+            $query.= "".$key."='".$val."',"; 
+          } 
+          $query = preg_replace("/,$/","",$query);
+          $query.= " WHERE customer_id='".$customer_id."';";
+          $SQL_query_array[] = $query;
+        }
+      }else{
+
+        /********************** 
+         * Insert Voice mail entry  
+         **********************/
+        $voice_data_array['context'] = "default";
+        $voice_data_array['pager']   = "";
+  
+        /* There is currently no voice mail entry for this user. 
+         * We should create one 
+         */
+        $s_voi_values = $s_voi_keys = "";
+        foreach($voice_data_array as $s_voi_key=>$s_voi_val){
+          if($s_voi_val == NULL) continue;
+          $s_voi_values.="'".$s_voi_val."',";
+          $s_voi_keys  .="`".$s_voi_key."`,";
+        }
+        $s_voi_values =  preg_replace("/,$/","",$s_voi_values);
+        $s_voi_keys   =  preg_replace("/,$/","",$s_voi_keys);
+
+        /* Add sip entries to mysql queries */
+        $SQL_query_array[] ="INSERT INTO ".$a_New['VOICE_TABLE']." (".$s_voi_keys.") VALUES (".$s_voi_values.");";
       }
 
-      $i_is_accounted=false;
+     
+      /********************** 
+       * Remove/Insert extension entries
+       **********************/
+      
+      /* Remove old entries */
+      $query = array();
+      $query[]= "DELETE FROM ".$a_New['EXT_TABLE']." WHERE exten=\"".$this->uid."\";";
+      foreach($newnums as $s_telenums){
+        $query[]= "DELETE FROM ".$a_New['EXT_TABLE']." WHERE exten=\"".$s_telenums."\";";
+      }
+      foreach($query as $qry){
+        if(!mysql_query($qry,$new_connection)){
+          echo mysql_error($new_connection);
+        } 
+      }
+      /********************** 
+       * Insert extension entries
+       **********************/
+      // Get selected Macro Parameter and create parameter entry 
+      if(isset($this->macroarray[$this->macro])){
+        foreach($this->macroarray[$this->macro] as $key => $val ){
+          $s_parameter .= $val['choosen']."|";
+        }
+        $s_parameter = preg_replace("/\|$/","",$s_parameter);
+      }
+     
+      $i = 0; 
+      $EXT = array();
+      $EXT[$i]['context'] = 'GOsa';
+      $EXT[$i]['exten']   = $this->uid;
+      $EXT[$i]['priority']= 1;
+      $EXT[$i]['app']     = "Goto";
+      $EXT[$i]['appdata'] = $newnums[$i_new_key]."|1";
+      $i ++;
 
       // Entension entries  Hint / Dial / Goto
-      foreach($this->phoneNumbers as $s_telenums){
-        // Entry  to call by name
-        $s_entry_name['context']  = 'GOsa';
-        $s_entry_name['exten']    = $this->uid;
-        $s_entry_name['priority'] = 1;
-        $s_entry_name['app']      = 'Goto';
-        $s_entry_name['appdata']  = $s_telenums."|1";
-        
-        // hint
-        $s_entry_hint['context']  = 'GOsa';
-        $s_entry_hint['exten']    = $s_telenums;
-        $s_entry_hint['app']      = 'hint';
-        $s_entry_hint['appdata']  = 'SIP/'.$this->uid;
+      foreach($newnums as $s_telenums){
+
+        /* Hint Entry */
+        $EXT[$i]['context'] = 'GOsa';
+        $EXT[$i]['exten']   = $s_telenums;
+        $EXT[$i]['priority']= "Hint";
+        $EXT[$i]['app']     = 'SIP/'.$this->uid;
+        $i ++;  
+        /* SetCID */
+        //$EXT[$i]['context'] = 'GOsa';
+        //$EXT[$i]['exten']   = $s_telenums;
+        //$EXT[$i]['priority']= 1;
+        //$EXT[$i]['app']     = "SetCIDName";
+        //$EXT[$i]['appdata'] = $CNname;
+        //$i ++;  
 
         // If no macro is selected use Dial
         if($this->macro!="none"){ 
@@ -388,70 +722,101 @@ class phoneAccount extends plugin
           $s_par = $macroname."|".$s_parameter; 
         }else{
           $s_app = "Dial";
-          $s_par = 'SIP/'.$this->uid;
+          $s_par = 'SIP/'.$this->uid."|20|r";
         }
 
-        // Entry  to call by number
-        $s_entry_phone['context']  = 'GOsa';
-        $s_entry_phone['exten']    = $s_telenums;
-        $s_entry_phone['priority'] = 1;
-        $s_entry_phone['app']      = $s_app;
-        $s_entry_phone['appdata']  = $s_par;
-
-        // append name entry only once
-        if(!$i_is_accounted){ 
-          $i_is_accounted = true;
-          $entries[]=array("hint"=>$s_entry_hint,"phone"=>$s_entry_phone,"name"=>$s_entry_name); 
-        }else{
-          $entries[]=array("hint"=>$s_entry_hint,"phone"=>$s_entry_phone);
-        }
+        $EXT[$i]['context'] = 'GOsa';
+        $EXT[$i]['exten']   = $s_telenums;
+        $EXT[$i]['priority']= 1;
+        $EXT[$i]['app']     = $s_app;
+        $EXT[$i]['appdata'] = $s_par;
+        $i ++;
       }
 
       // Append all these Entries 
-      foreach($entries as $num => $val){
-        foreach($val as $entr){
-          $SQL_syn = "INSERT INTO ".$a_SETUP['EXT_TABLE']." (";
-          foreach($entr as $key2 => $val2){
-            $SQL_syn.= "`".$key2."`,";
-          }
-          $SQL_syn = preg_replace("/,$/","",$SQL_syn);
-          $SQL_syn .= ") VALUES ("; 
-          foreach($entr as $key2 => $val2){
-            $SQL_syn .= "'".$val2."',";
-          }
-          $SQL_syn = preg_replace("/,$/","",$SQL_syn);
-          $SQL_syn .=");\n";
-          $SQL[] =$SQL_syn;
-          $SQL_syn ="";
+      foreach($EXT as $entr){
+        $SQL_syn = "INSERT INTO ".$a_New['EXT_TABLE']." (";
+        foreach($entr as $key2 => $val2){
+          $SQL_syn.= "`".$key2."`,";
         }
+        $SQL_syn = preg_replace("/,$/","",$SQL_syn);
+        $SQL_syn .= ") VALUES ("; 
+        foreach($entr as $key2 => $val2){
+          $SQL_syn .= "'".$val2."',";
+        }
+        $SQL_syn = preg_replace("/,$/","",$SQL_syn);
+        $SQL_syn .=");\n";
+
+        $SQL_query_array[] =$SQL_syn;
+        $SQL_syn ="";
       }
 
       // Perform queries ...
-      foreach($SQL as $query){
-        if(!mysql_query($query,$r_con)){
-          print_red(_("Error while performing query ".mysql_error()));
-          return false;
+      if($this->goFonHardware != "automatic"){
+        foreach($SQL_query_array as $query){
+          if(!@mysql_query($query,$new_connection)){
+            print_red(_("Error while performing query:")." ".mysql_error());
+            return false;
+          }
         }
       }
     }
-  return true;
+    @mysql_close($new_connection);
+    return true;
   }
 
 
+  function execute()
+  {
+    /* Call parent execute */
+    plugin::execute();
 
+    $display = "";
 
+    if(empty($this->macro)&&(!empty($this->goFonMacro))){
 
+      /* Go through already saved values, for a parameter */
+      $tmp = split("!",$this->goFonMacro);
 
+      /* it is possible that nothing has been saved yet */
+      if(is_array($tmp)){
 
+        /* First value is the macroname */
+        $this->macro = $tmp[0];
 
+        /* Macroname saved, delete that index */
+        unset($tmp[0]);
 
+        /* Check if macro has been removed */
+        if(!isset($this->macroarray[$this->macro])){
+          $this->macrostillavailable = false;
+        }else{
+          $this->macrostillavailable = true;
+        }
 
+        /* for each parametervalues ( parameterID#value like 25#twentyfive) */
+        foreach($tmp as $var){
 
+          /* Split this, so we have $varar[0] = parameterID $varar[1] = SelectedValue */
+          $varar = split("#",$var);
 
+          /* Only insert if the parameter still exists */
+          if(isset($this->macroarray[$this->macro][$varar[0]])){
+            /* Assign value */
+            $this->macroarray[$this->macro][$varar[0]]['choosen']=$varar[1];
+          }
+        }
+      }
+    }
+    
+    /* Do we represent a valid account? */
+    if (!$this->is_account && $this->parent == NULL){
+      $display= "<img alt=\"\" src=\"images/stop.png\" align=\"middle\">&nbsp;<b>".
+        _("This account has no phone extensions.")."</b>";
+      $display.= back_to_main();
+      return ($display);
+    }
 
-
-  function execute()
-  {
     /* Do we need to flip is_account state? */
     if (isset($_POST['modify_state'])){
       $this->is_account= !$this->is_account;
@@ -462,25 +827,61 @@ class phoneAccount extends plugin
       $this->macro ="none";
     }
 
-    /* tell user that the pluging selected is no longer available*/
-    if((!$this->macrostillavailable)&&($this->macro!="none")){
-      print_red(_("The macro you selected in the past, is no longer available for you, please choose another one."));
-    }
-
     /* Prepare templating */
     $smarty= get_smarty();
 
+    /* tell user that the selected plugin is no longer available */
+    if((!$this->macrostillavailable)&&($this->macro!="none")){
+      print_red(_("The macro you selected, is no longer available for you, please choose another one."));
+    }
+
     /* Assing macroselectbox values  */
     $smarty->assign("macros",$this->macros);   
     $smarty->assign("macro", $this->macro);   
 
-    /* Create parameter table, skip if no parameters given */
+    /* check if there is a FON server created */
+    if(!count($this->goFonHomeServer)){
+      print_red(_("There is currently no asterisk server defined. Possibly you are missing a server that handles the asterisk management (goFonServer). Your settings can't be saved to asterisk database."));
+    }
+
+    /* Create html parameter table for selected macro parameters 
+     *  skip if no parameters given 
+     */
     if(!isset($this->macroarray[$this->macro])){
       $macrotab="";
     }else{
 
       $macrotab ="<table summary=\""._("Parameter")."\">";
       /* for every single parameter-> display textfile,combo, or true false switch*/
+
+      foreach($this->phoneNumbers as $phonenum){
+        $tmp[] = $phonenum;
+      }
+    
+      if($this->macro != $this->lastmacro){
+        /* Go through all params */
+        foreach($this->macroarray[$this->macro] as $key => $paras){
+
+          $string = $paras['default'];
+
+          $string=preg_replace("/%uid/i",$this->uid,$string);
+
+          if(isset($this->cn)){
+            $string=preg_replace("/%cn/i",$this->cn,$string);
+          }
+
+          for($i = 0 ; $i < 10; $i++){
+            if(isset($tmp[$i])){
+              $string = preg_replace("/%telephoneNumber_".($i+1)."/i",$tmp[$i],$string);
+            }
+          }
+          if(isset($tmp[0])){
+            $string = preg_replace("/%telephoneNumber/i",$tmp[0],$string);
+          }
+          $this->macroarray[$this->macro][$key]['choosen']=$string;
+        }
+      }
+
       foreach($this->macroarray[$this->macro] as $paras){
 
         /* get al vars */
@@ -496,7 +897,7 @@ class phoneAccount extends plugin
         switch ($type){
 
           case "combo":
-            $str= "<select name='".$var."' ".chkacl($this->acl, "goFonMacro")."  ".chkacl($this->acl, "goFonMacro").">";
+            $str= "<select name='".$var."' ".chkacl($this->acl, "goFonMacro")." >";
           foreach(split(":",$default) as $choice){
             if($choosen==$choice){
               $str.= "\n<option value='".$choice."' selected>".$choice."&nbsp;</option>";
@@ -505,7 +906,7 @@ class phoneAccount extends plugin
             }
           }
           $str.="</select>";
-          $macrotab.= "<td>$name</td><td>$str";
+          $macrotab.= "<td>".base64_decode($name)."</td><td>$str";
           break;
 
           case "bool":
@@ -514,24 +915,25 @@ class phoneAccount extends plugin
             }else{
               $str="\n<input type='checkbox' name='".$var."' value='1' checked  ".chkacl($this->acl, "goFonMacro").">";
             }
-          $macrotab.= "<td colspan='2'>$str&nbsp;$name";
+          $macrotab.= "<td colspan='2'>$str&nbsp;".base64_decode($name)."";
           break;
 
           case "string":
-            $str="<input name='".$var."' value='".$choosen."' ".chkacl($this->acl, "goFonMacro").">";
-          $macrotab.= "<td>$name</td><td>$str";
+            $str="<input name='".$var."' value='".$choosen."' ".chkacl($this->acl, "goFonMacro")." style='width:340px;'>";
+          $macrotab.= "<td>".base64_decode($name)."</td><td>$str";
           break;
 
         }
-        $macrotab.= "</td</tr>";
+        $macrotab.= "</td></tr>";
 
       }
-      $macrotab.="</table>";
+      $macrotab.="</table><input name='post_success' type='hidden' value='1'>";
     }//is_array()
 
     /* Give smarty the table */
     $smarty->assign("macrotab",$macrotab);
 
+
     /* Do we represent a valid account? */
     if (!$this->is_account && $this->parent == NULL){
       $display= "<img alt=\"\" src=\"images/stop.png\" align=\"middle\">&nbsp;<b>".
@@ -548,8 +950,13 @@ class phoneAccount extends plugin
         $display= $this->show_header(_("Remove phone account"),
             _("This account has phone features enabled. You can disable them by clicking below."));
       } else {
-        $display= $this->show_header(_("Create phone account"),
-            _("This account has phone features disabled. You can enable them by clicking below."));
+        if(empty($this->uid)){
+          $display= $this->show_header(_("Create phone account"),
+              _("This account has phone features disabled. You can't enable them while no uid is set."),TRUE,TRUE);
+        }else{
+          $display= $this->show_header(_("Create phone account"),
+              _("This account has phone features disabled. You can enable them by clicking below."));
+        }
         return ($display);
       }
     }
@@ -573,28 +980,29 @@ class phoneAccount extends plugin
       }
     }
 
-    /* Check for forwarding action */
-    foreach ($this->forwarders as $nr => $fw){
-
-      /* Buttons pressed? */
-      if (isset($_POST["add_fw$nr"])){
-        $this->forwarders= $this->insert_after("", $nr, $this->forwarders);
-      }
-      if (isset($_POST["remove_fw$nr"])){
-        unset($this->forwarders[$nr]);
+    /* Transfer ACL's */
+    foreach($this->attributes as $val){
+      $smarty->assign($val."ACL", chkacl($this->acl,$val));
+      if(isset($this->$val)){
+        $smarty->assign($val,$this->$val);
+      }else{
+        $smarty->assign($val,"");
       }
     }
 
-    /* Transfer ACL's */
-    foreach($this->attributes as $val){
-      $smarty->assign($val."ACL", chkacl($this->acl, "$val"));
-      $smarty->assign($val,$this->$val);
+    /* Create home server array */
+    $tmp = array();
+    foreach($this->goFonHomeServers as $dn => $attrs){
+      if(!is_numeric($dn)){
+        $tmp[$dn] = $attrs['SERVER'];
+      }
     }
+    $smarty->assign("goFonHomeServers",$tmp);
 
     /* Fill arrays */
     $smarty->assign ("goFonHardware", $this->goFonHardware);
     if (!count($this->phoneNumbers)){
-      $smarty->assign ("phoneNumbers", array(""));
+      $smarty->assign ("phoneNumbers", array());
     } else {
       $smarty->assign ("phoneNumbers", $this->phoneNumbers);
     }
@@ -616,29 +1024,8 @@ class phoneAccount extends plugin
     $hl.= "</select>\n";
     $smarty->assign ("hardware_list", $hl);
 
-    /* Generate forwarder view */
-    $forwarder_list="";
-    $acl= chkacl($this->acl, "goFonForwaring");
-    foreach ($this->forwarders as $nr => $fw){
-      if ($fw == ""){
-        $number= ""; $timeout= "";
-      } else {
-        list($number, $timeout)= split(";", $fw);
-      }
-      $forwarder_list.= "<tr><td>";
-      $forwarder_list.= "<input name=\"fwn$nr\" size=25 align=\"middle\" maxlength=60 value=\"$number\" $acl>";
-      $forwarder_list.= "</td><td>";
-      $forwarder_list.= "<input name=\"fwt$nr\" size=5 align=\"middle\" maxlength=5 value=\"$timeout\" $acl>";
-      $forwarder_list.= "</td><td>";
-      $forwarder_list.= "<input type=\"submit\" value=\""._("Add")."\" name=\"add_fw$nr\" $acl>";
-      if (count($this->forwarders) > 1){
-        $forwarder_list.= "<input type=\"submit\" value=\""._("Remove")."\" name=\"remove_fw$nr\" $acl>";
-      }
-      $forwarder_list.= "</td></tr>";
-    }
-    $smarty->assign("forwarder_list", $forwarder_list);
-
     /* Show main page */
+    $this->lastmacro = $this->macro;
     $display.= $smarty->fetch(get_template_path('generic.tpl', TRUE, dirname(__FILE__)));
     return($display);
   }
@@ -662,86 +1049,80 @@ class phoneAccount extends plugin
         $this->goFonDeliveryMode= $tmp;
       }
 
-      /* Save forwarding numbers and timeouts */
-      if (chkacl ($this->acl, "goFonForwarder") == ""){
-        foreach ($this->forwarders as $nr => $fw){
-          $tmp= $_POST["fwn$nr"].";".$_POST["fwt$nr"];
-          if ($this->forwarders[$nr] != $tmp){
-            $this->is_modified= TRUE;
-          }
-          $this->forwarders[$nr]= $tmp;
-        }
-      }
-
       /* Every macro in the select box are available */
       if((isset($_POST['macro']))){
         $this->macrostillavailable=true;
       }
 
+      if(is_array($this->phoneNumbers)){
+        foreach($this->phoneNumbers as $telenumms) {
+          $nummsinorder[]=$telenumms; 
+        }
+      }else{
+        $nummsinorder=array("");
+      }
+
       /* get all Postvars */
       if(isset($this->macroarray[$this->macro])){ 
         foreach($this->macroarray[$this->macro] as $key => $paras){
           if(isset($_POST[$paras['var']])){
-            $this->macroarray[$this->macro][$key]['choosen'] = $_POST[$paras['var']]; 
+            $this->macroarray[$this->macro][$key]['choosen'] = $_POST[$paras['var']];
           }
 
           /* Checkboxes are special, they are not Posted if they are not selected, so the won't be changed with the above code 
              We need this code below to read and save checkboxes correct
            */
-          if($this->macroarray[$this->macro][$key]['type']=="bool"){
-            if(isset($_POST[$this->macroarray[$this->macro][$key]['var']])) {
-              $this->macroarray[$this->macro][$key]['choosen']=$_POST[$paras['var']];
-            }else{
-              $this->macroarray[$this->macro][$key]['choosen']=false;
+
+          if(isset($_POST['post_success'])){
+            if($this->macroarray[$this->macro][$key]['type']=="bool"){
+              if(isset($_POST[$this->macroarray[$this->macro][$key]['var']])) {
+                $this->macroarray[$this->macro][$key]['choosen']=$_POST[$paras['var']];
+              }else{
+                $this->macroarray[$this->macro][$key]['choosen']=false;
+              }
             }
           }
         }
       }
     }
-
-
   }
 
   function check()
   {
-    /* Reset message array */
-    $message= array();
+    /* Call common method to give check the hook */
+    $message= plugin::check();
 
-    if(!$this->generate_mysql_entension_entries()){
-      $message[] = $this->generate_error;
+    if(!count($this->goFonHomeServers)){
+      $message[] = _("There must be at least one server with an asterisk database to create a phone account.");
     }
 
-    /* We need at least one phone number */
-    if (count($this->phoneNumbers) == 0){
-      $message[]= sprintf(_("You need to specify at least one phone number!"));
+    if(empty($this->goFonHomeServer)){
+      $message[] = _("Please select a valid goFonHomeServer.");
     }
 
-    if(($this->goFonPIN)==""){
-      $this->goFonPIN = array();
+    if((strlen($this->goFonVoicemailPIN)==0)||(strlen($this->goFonVoicemailPIN)>4)){
+      $message[]=(_("Voicemail PIN must be between 1-4 characters."));
     }else{
-      if(strcmp ((int)($this->goFonPIN),($this->goFonPIN))){
-        $message[] = sprintf(_("The given PIN is not valid, only numbers are allowed for this type."));
-      }elseif(strlen($this->goFonPIN) < 4){
-        $message[] = sprintf(_("The given PIN is too short"));
+      if(preg_match("/[^0-9]/",$this->goFonVoicemailPIN)){
+        $message[]=(_("The specified Voicemail PIN contains invalid characters, only numeric values are allowed here."));
       }
+    }
 
+    if((strlen($this->goFonPIN)<=0)){
+      $message[]=(_("Phone PIN must be at least one character long."));
+    }else{
+      if(preg_match("/[^0-9a-z]/i",$this->goFonPIN)){
+        $message[]=(_("The specified phone PIN contains invalid characters, only aphanumeric values are allowed here."));
+      }
     }
-    /* Check timestamps and phonenumbers */
-    foreach ($this->forwarders as $fw){
 
-      /* Skip empty values */
-      if ($fw == ";"){
-        continue;
-      }                
+    if(!$this->generate_mysql_entension_entries()){
+      $message[] = $this->generate_error;
+    }
 
-      /* Check */
-      list($number, $timeout)= split(";", $fw);
-      if (!is_phone_nr($number)){
-        $message[]= sprintf(_("The number '%s' is no valid phone number!"), $number);
-      }
-      if (!is_id($timeout)){
-        $message[]= sprintf(_("The timeout '%s' contains invalid characters!"), $timeout);
-      }
+    /* We need at least one phone number */
+    if (count($this->phoneNumbers) == 0){
+      $message[]= sprintf(_("You need to specify at least one phone number!"));
     }
 
     /* check for ! in any parameter setting*/
@@ -761,14 +1142,20 @@ class phoneAccount extends plugin
   {
     plugin::save();
 
+    /* Force saving macro again 
+     * This ensures that 
+     *  - the macro is available on the destiantion server.
+     *  - the macro saved is up to date on the destination server.
+     */
+    if(!empty($this->macro) && $this->macro != "none")  {
+      $macro_tab = new macrotabs($this->config,$this->config->data['TABS']['MACROTABS'], $this->macro);
+      $macro_tab -> save();
+    }
+
     /* Save arrays */
-    $this->attrs['telephoneNumber']= array();
+    $tmp_numbers = array();
     foreach ($this->phoneNumbers as $number){
-      $this->attrs['telephoneNumber'][]= $number;
-    }
-    $this->attrs['goFonForwarding']= array();
-    foreach ($this->forwarders as $index => $number){
-      $this->attrs['goFonForwarding'][]= "$index;$number";
+      $tmp_numbers[] = $number;
     }
 
     /* Save settings, or remove goFonMacro attribute*/
@@ -784,52 +1171,43 @@ class phoneAccount extends plugin
     }
     unset($this->attrs['macro'])  ;
 
+    $this->attrs['goFonForwarding']=array();
+
+    $str = $this->generate_mysql_entension_entries(true);
+    if(empty($str)){
+      print_red($str);
+    }
+
     if($this->attrs['goFonMacro']==""){
       $this->attrs['goFonMacro']=array();
     }
+
+    unset($this->attrs['cn']);
+
     /* Write back to ldap */
     $ldap= $this->config->get_ldap_link();
     $ldap->cd($this->dn);
-    $ldap->modify($this->attrs);
-    show_ldap_error($ldap->get_error());
-
-    $this->generate_mysql_entension_entries(true);
+    $this->cleanup();
+    
+    /* Force saving numbers, else it will be overwriten by user account. */
+    $this->attrs['telephoneNumber'] =$tmp_numbers;
+    $ldap->modify ($this->attrs); 
 
+    show_ldap_error($ldap->get_error(), _("Saving phone account failed"));
 
     /* Optionally execute a command after we're done */
+
     if ($this->initially_was_account == $this->is_account){
       if ($this->is_modified){
-        $this->handle_post_events("modify");
+        $this->handle_post_events("modify",array("uid" => $this->uid));
       }
     } else {
-      $this->handle_post_events("add");
+      $this->handle_post_events("add",array("uid" => $this->uid));
     }
 
   }
 
 
-  function insert_after($entry, $nr, $list)
-  {
-    /* Is the entry free? No? Make it free... */
-    if (isset($list[$nr])) {
-      $dest= array();
-      $newidx= 0;
-
-      foreach ($list as $idx => $contents){
-        $dest[$newidx++]= $contents;
-        if ($idx == $nr){
-          $dest[$newidx++]= $entry;
-        }
-      }
-    } else {
-      $dest= $list;
-      $dest[$nr]= $entry;
-    }
-
-    return ($dest);
-  }
-
-
   function adapt_from_template($dn)
   {
     plugin::adapt_from_template($dn);
@@ -841,50 +1219,59 @@ class phoneAccount extends plugin
         $this->phoneNumbers[$number]= $number;
       }
     }
-
-    /* Assemble forwarders */
-    if (isset($this->attrs['goFonForwarding'])){
-      for ($i= 0; $i<$this->attrs['goFonForwarding']['count']; $i++){
-        list($num, $v1, $v2) =split(';', $this->attrs['goFonForwarding'][$i]);
-        $this->forwarders[$num]= "$v1;$v2";
-      }
-    } else {
-      $this->forwarders= array("");
-    }
   }
 
 
   function remove_from_parent()
   {
-    // Get Configuration for Mysql database Server
-    $a_SETUP = $_SESSION['config']->data['SERVERS']['FON'];
-    $s_parameter  ="";
-
-    // Connect to DB server
-    $r_con =  @mysql_connect($a_SETUP['SERVER'],$a_SETUP['LOGIN'],$a_SETUP['PASSWORD']);
+    if(!$this->initially_was_account) return;
 
-    // Check if we are  connected correctly
-    if(!$r_con){
-      $this->generate_error = sprintf(_("The MySQL Server '%s' isn't reachable as user '%s', check GOsa log for mysql error."),
-          $a_SETUP['SERVER'],$a_SETUP['LOGIN']);
-      gosa_log(mysql_error());
-      return false;
+    foreach($this->attributes as $key=>$val){
+      if(in_array($val,array("uid","cn"))){
+        unset($this->attributes[$key]);
+        unset($this->$val);
+      }
     }
+    if(count($this->goFonHomeServers) && !empty($this->init_HomeServer) && is_callable("mysql_pconnect")){
 
-    // Select database for Extensions
-    $db  =  @mysql_select_db($a_SETUP['DB'],$r_con);
+      // Get Configuration for initial Mysql database Server
+      $a_SETUP = $this->goFonHomeServers[$this->init_HomeServer];
+      $s_parameter  ="";
 
-    // Test if we have the database selected correctly
-    if(!$db){
-      $this->generate_error = sprintf(_("Can't select database %s on %s."),$a_SETUP['DB'],$a_SETUP['SERVER']);
-      gosa_log(mysql_error());
-      return false;
-    }
+      // Connect to DB server
+      $r_con =  @mysql_pconnect($a_SETUP['SERVER'],$a_SETUP['LOGIN'],$a_SETUP['PASSWORD']);
 
-    $SQL="";
+      // Check if we are  connected correctly
+      if(!$r_con){
+        print_red(sprintf(_("The MySQL Server '%s' isn't reachable as user '%s', check GOsa log for mysql error."),
+                    $a_SETUP['SERVER'],$a_SETUP['LOGIN']));
+        gosa_log(@mysql_error());
+        return false;
+      }
 
-    $first_num = false;
-    // Delete old entries
+      // Select database for Extensions
+      $db  =  @mysql_select_db($a_SETUP['DB'],$r_con);
+
+      // Test if we have the database selected correctly
+      if(!$db){
+        print_red(sprintf(_("Can't select database %s on %s."),$a_SETUP['DB'],$a_SETUP['SERVER']));
+        gosa_log(@mysql_error());
+        return false;
+      }
+
+      $SQL="";
+
+      /* If deletion starts from userslist, cn uid are not set */
+      if((isset($this->parent->by_object['user']->uid))&&(!empty($this->parent->by_object['user']->uid))){
+        $this->uid = $this->parent->by_object['user']->uid;
+      }
+
+      if((isset($this->parent->by_object['user']->cn))&&(!empty($this->parent->by_object['user']->cn))){
+        $this->cn  = $this->parent->by_object['user']->cn;
+      }
+
+      $first_num = false;
+      // Delete old entries
       foreach($this->a_old_telenums as $s_telenums){
         if(!$first_num){
           $first_num = $s_telenums;
@@ -896,15 +1283,16 @@ class phoneAccount extends plugin
       $SQL[] = "DELETE FROM ".$a_SETUP['EXT_TABLE']." WHERE exten='".$this->uid."';\n";
       $SQL[] = "DELETE FROM ".$a_SETUP['SIP_TABLE']." WHERE name='".$this->uid."';\n";
 
-
       foreach($SQL as $query){
-        if(!mysql_query($query,$r_con)){
+        if(!@mysql_query($query,$r_con)){
           print_red(_("Stop".mysql_error()));
           return false;
         }
       }
-
-
+    }else{
+      print_red(_("Can't remove phone account, the mysql extension is not present in php configuration."));
+      return false;
+    }
 
     /* unset macro attr, it will cause an error */
     $tmp = array_flip($this->attributes);
@@ -920,21 +1308,108 @@ class phoneAccount extends plugin
 
     /* Just keep one phone number */
     if (count($this->telephoneNumber) && $this->telephoneNumber != ""){
-      $this->attrs['telephoneNumber']= $this->telephoneNumber[0];
+      $this->attrs['telephoneNumber']= $this->telephoneNumber;
     } else {
       $this->attrs['telephoneNumber']= array();
     }
 
+
     $ldap= $this->config->get_ldap_link();
+    $ldap->cd($this->config->current['BASE']);
+    $ldap->search("(objectClass=goFonQueue)", array("member"));
+    while($attr = $ldap->fetch()){
+      if(in_array($this->dn,$attr['member'])){
+        $new =new ogrouptabs($this->config, $this->config->data['TABS']['OGROUPTABS'],$attr['dn']);
+        unset($new->by_object['ogroup']->memberList[$this->dn]);
+        unset($new->by_object['ogroup']->member[$this->dn]);
+        $new->save();
+        print_red(sprintf(_("Removed user '%s' from phone queue '%s'."),$this->uid,$new->by_object['ogroup']->attrs['cn']));
+      }
+    }
     $ldap->cd($this->dn);
-    $ldap->modify($this->attrs);
-    show_ldap_error($ldap->get_error());
+    $this->cleanup();
+    $ldap->modify ($this->attrs); 
+
+    show_ldap_error($ldap->get_error(), _("Removing phone account failed"));
 
     /* Optionally execute a command after we're done */
-    $this->handle_post_events('remove');
+    @mysql_close($r_con);
+    $this->handle_post_events('remove',array("uid"=> $this->uid));
   }
 
 
+
+  /* This function checks if the given phonenumbers are available or already in use*/
+  function is_number_used()
+  {
+    $ldap= $this->config->get_ldap_link();
+    $ldap->cd($this->config->current['BASE']);
+    $ldap->search("(|(objectClass=goFonAccount)(objectClass=goFonQueue)(objectClass=goFonConference))", array("telephoneNumber","cn","uid"));
+    while($attrs = $ldap->fetch()) {
+      unset($attrs['telephoneNumber']['count']);
+      foreach($attrs['telephoneNumber'] as $tele){
+        if(!isset($attrs['cn'][0])) $attrs['cn'][0]=$attrs['dn'];
+        if(!isset($attrs['uid'][0])) $attrs['uid'][0]=$attrs['dn'];
+        $numbers[$tele]=$attrs;
+      }
+    }
+
+    foreach($this->phoneNumbers as $num){
+      if(!isset($this->cn)) $this->cn = "";
+
+      if((isset($numbers[$num]))&&(($numbers[$num]['uid'][0]!=$this->uid))){
+        if(isset($numbers[$num]['uid'][0])){
+          return sprintf(_("The specified telephonenumber '%s' is already assigned to '%s'."),$num,$numbers[$num]['uid'][0]);
+        }else{
+          return sprintf(_("The specified telephonenumber '%s' is already assigned to '%s'."),$num,$numbers[$num]['cn'][0]);
+        }
+      }
+    }
+  }
+
+
+  /* Create phoneAccount part of copy & paste dialog */
+  function getCopyDialog()
+  { 
+    if(!$this->is_account) return("");
+    $smarty = get_smarty();
+    if (!count($this->phoneNumbers)){
+      $smarty->assign ("phoneNumbers", array(""));
+    } else {
+      $smarty->assign ("phoneNumbers", $this->phoneNumbers);
+    }
+
+    $smarty->assign("goFonVoicemailPIN",$this->goFonVoicemailPIN);
+    $smarty->assign("goFonPIN",$this->goFonPIN);
+
+    $display= $smarty->fetch(get_template_path('paste_generic.tpl', TRUE, dirname(__FILE__)));
+    $ret =array();
+    $ret['string'] = $display;
+    $ret['status'] = "";
+    return($ret);
+  }
+
+  /* Save posts from copy & paste dialog dialog  */
+  function saveCopyDialog()
+  {
+    if(!$this->is_account) return;
+    $this->execute();
+    if(isset($_POST['goFonVoicemailPIN'])) {
+      $this->goFonVoicemailPIN = $_POST['goFonVoicemailPIN'];
+    }
+    if(isset($_POST['goFonPIN'])){
+      $this->goFonPIN = $_POST['goFonPIN'];
+    }
+  }
+
+
+  function allow_remove()
+  {
+    /* Check if previously selected server is still available */
+    if($this->initially_was_account && !isset($this->goFonHomeServers[$this->goFonHomeServer])){
+      return sprintf(_("The previously selected asterisk home server (%s) is no longer available. Remove aborted."),preg_replace("/,/",", ",$this->goFonHomeServer));
+    }
+  }
 }
 
 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler: