Changeset 9977

Show
Ignore:
Timestamp:
06/28/10 13:20:44 (2 years ago)
Author:
p_lindheimer
Message:

fixes #4382 enapsulate symlinking/copying into a class with error reporting at end

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • freepbx/branches/2.8/amp_conf/bin/retrieve_conf

    r9608 r9977  
    11#!/usr/bin/php -q 
    2  
    32<?php 
     3 
     4class connectdirs { 
     5 
     6  var $nt; 
     7  var $symlink_dirs; 
     8  var $cp_dirs; 
     9 
     10  var $cp_errors = ''; 
     11  var $symlink_error_modules = ''; 
     12     
     13  function &create(&$db) { 
     14    static $obj; 
     15    if (!isset($obj)) { 
     16      $obj = new connectdirs(); 
     17    } 
     18    return $obj; 
     19  } 
     20 
     21  function connectdirs() { 
     22    global $amp_conf; 
     23    global $db; 
     24    $this->symlink_dirs['sounds'] = $amp_conf['ASTVARLIBDIR'].'/sounds'; 
     25    $this->symlink_dirs['bin']    = $amp_conf['AMPBIN']; 
     26    $this->symlink_dirs['etc']    = $amp_conf['ASTETCDIR']; 
     27    $this->symlink_dirs['images'] = $amp_conf['AMPWEBROOT']."/admin/images";  
     28 
     29    $this->cp_dirs['agi-bin'] = $amp_conf['ASTAGIDIR']; 
     30    $this->nt = notifications::create($db); 
     31  } 
     32 
     33  function symlink_subdirs($moduledir) { 
     34    foreach ($this->symlink_dirs as $subdir => $targetdir) { 
     35      $dir = addslash($moduledir).$subdir; 
     36      if (is_dir($dir)) { 
     37        $d = opendir($dir); 
     38        while ($file = readdir($d)) { 
     39          if ($file[0] != '.') { 
     40            $src = addslash($dir).$file; 
     41            $dest = addslash($targetdir).$file; 
     42            if (file_exists_wrapper($dest)) { 
     43              if (!is_link($dest)) { 
     44                freepbx_log('retrieve-conf', 'error', $dest.' already exists, and is not a symlink!'); 
     45                $this->symlink_error_modules .= "<br />&nbsp;&nbsp;&nbsp;".$dest; 
     46              } else if (readlink($dest) != $src) { 
     47                // TODO : is this the proper handling? should we just overwrite..? 
     48                freepbx_log('retrieve-conf', 'error', $dest.' already exists, and is linked to something else!'); 
     49                $this->symlink_error_modules .= "<br />&nbsp;&nbsp;&nbsp;".$dest; 
     50              } else { 
     51                freepbx_log('retrieve-conf', 'devel-debug', $dest.' already points to '.$src.' - OK'); 
     52              } 
     53            } else { 
     54//            // symlink, unlike copy, doesn't overwrite - have to delete first 
     55//            if (is_link($dest) || file_exists($dest)) { 
     56//              unlink($dest); 
     57//            } 
     58              if (symlink($src, $dest)) { 
     59                freepbx_log('retrieve-conf', 'devel-debug', 'Symlinked '.$src.' to '.$dest); 
     60              } else { 
     61                freepbx_log('retreive-conf', 'devel-debug', 'Cannot symlink '.$src.' to '.$dest.'. Check Permissions?'); 
     62              } 
     63            } 
     64          } 
     65        } 
     66        closedir($d); 
     67      } 
     68    } 
     69  } 
     70 
     71  function symlink_check_errors() { 
     72    if ($this->symlink_error_modules) { 
     73      $this->nt->add_error('retrieve_conf', 'SYMLINK', _("Symlink from modules failed"), sprintf(_("retrieve_conf failed to sym link: %s<br \>This can result in FATAL failures to your PBX. If the target file exists, the symlink will not occur and you should rename the target file to allow the automatic sym link to occur and remove this error, unless this is an intentional customization."),$this->symlink_error_modules)); 
     74    } else { 
     75      $this->nt->delete('retrieve_conf', 'SYMLINK'); 
     76    } 
     77  } 
     78 
     79  function cp_subdirs($moduledir) { 
     80    foreach ($this->cp_dirs as $subdir => $targetdir) { 
     81      $dir = addslash($moduledir).$subdir; 
     82      if(is_dir($dir)){ 
     83        foreach(listdir($dir) as $idx => $file){ 
     84          $sourcefile = $file; 
     85          $filesubdir=str_replace($dir.'/', '', $file); 
     86          $targetfile = addslash($targetdir).$filesubdir; 
     87   
     88          if (file_exists_wrapper($targetfile)) { 
     89            if (is_link($targetfile)) { 
     90              if ($this->err_unlink($targetfile)) { 
     91                freepbx_log('retrieve-conf', 'devel-debug', "$targetfile was symbolic link, unlink successful"); 
     92              } else { 
     93                freepbx_log('retrieve-conf', 'error', "$targetfile is a symblolic link, failed to unlink!"); 
     94                break; 
     95              } 
     96            } 
     97          } 
     98          // OK, now either the file is a regular file or isn't there, so proceed 
     99          // 
     100          if ($this->err_copy($sourcefile,$targetfile)) { 
     101            freepbx_log('retrieve-conf', 'devel-debug', "$targetfile successfully copied"); 
     102            // copy was successful, make sure it has execute permissions 
     103            chmod($targetfile,0754); 
     104          } else { 
     105            freepbx_log('retrieve-conf', 'error', "$targetfile failed to copy from module directory"); 
     106          } 
     107        } 
     108      } 
     109    } 
     110  } 
     111  function cp_check_errors() { 
     112    if ($this->cp_errors) { 
     113      $this->nt->add_error('retrieve_conf', 'CPAGIBIN', _("Failed to copy from module agi-bin"), sprintf(_("Retrieve conf failed to copy file(s) from a module's agi-bin dir: %s"),$cp_errors)); 
     114    } else { 
     115      $this->nt->delete('retrieve_conf', 'CPAGIBIN'); 
     116    } 
     117  } 
     118  function add_cp_error($string) { 
     119    $this->cp_errors .= $string; 
     120  } 
     121 
     122  // wrap copy with error handler 
     123  // 
     124  function err_copy($source, $dest) { 
     125    $ret = false; 
     126    set_error_handler("report_errors"); 
     127    //if were copying a directory, just mkdir the directory 
     128    if(is_dir($source)){ 
     129      $ret=mkdir($dest,0754); 
     130    }elseif(copy($source, $dest)) { 
     131      $ret = chmod($dest,0754); 
     132    } 
     133    restore_error_handler(); 
     134    return $ret; 
     135  } 
     136 
     137  // wrap unlink with error handler 
     138  // 
     139  function err_unlink($dest) { 
     140    set_error_handler("report_errors"); 
     141    $ret = unlink($dest); 
     142    restore_error_handler(); 
     143    return $ret; 
     144  } 
     145} 
     146 
     147// I don't think this can be part of the class since it is called by an 
     148// error function as a callback (otherwise, can move it into above). 
     149// 
     150function report_errors($errno, $errstr, $errfile, $errline) { 
     151  global $cp_errors; 
     152  switch($db_engine) { 
     153    case "sqlite3":  
     154      $escaped_string = sqlite_real_escape($errstr); 
     155      break; 
     156    case "mysql": 
     157      $escaped_string = mysql_real_escape_string($errstr); 
     158      break; 
     159    case "pgsql": 
     160      $escaped_string = pgsql_escape_string($errstr); 
     161      break; 
     162  } 
     163  freepbx_log('retrieve-conf', 'error', "php reported: '$escaped_string' after copy or unlink attempt!"); 
     164  $cp_errors .= $errstr."\n"; 
     165  $conn_dirs = connectdirs::create(); 
     166  $conn_dirs->add_cp_error($errstr."\n"); 
     167} 
    4168 
    5169// Emulate gettext extension functions if gettext is not available 
     
    268432// 
    269433$nt = notifications::create($db); 
     434$con_dirs = connectdirs::create(); 
    270435 
    271436/* 
     
    333498      // 
    334499      if ($key != 'framework') { 
    335        symlink_subdirs( $amp_conf['AMPWEBROOT'].'/admin/modules/'.$key ); 
    336        cp_subdirs( $amp_conf['AMPWEBROOT'].'/admin/modules/'.$key ); 
     500        $con_dirs->symlink_subdirs( $amp_conf['AMPWEBROOT'].'/admin/modules/'.$key ); 
     501        $con_dirs->cp_subdirs( $amp_conf['AMPWEBROOT'].'/admin/modules/'.$key ); 
    337502      } 
    338503    } 
     
    341506// Now also make sure to symlink the CDR images which is not a proper module 
    342507// 
    343 symlink_subdirs( $amp_conf['AMPWEBROOT'].'/admin/cdr/'); 
     508$con_dirs->symlink_subdirs( $amp_conf['AMPWEBROOT'].'/admin/cdr/'); 
     509 
     510// Now that we have done all the symlinks and copies, we check and report if there were any errors 
     511// 
     512$con_dirs->symlink_check_errors(); 
     513$con_dirs->cp_check_errors(); 
     514 
    344515 
    345516// create an object of the extensions class 
     
    533704} 
    534705 
    535 function symlink_subdirs($moduledir) { 
    536   global $symlink_dirs; 
    537   $symlink_errors = false; 
    538  
    539   $nt = notifications::create($db); 
    540  
    541   $error_modules = ''; 
    542   foreach ($symlink_dirs as $subdir => $targetdir) { 
    543     $dir = addslash($moduledir).$subdir; 
    544     if (is_dir($dir)) { 
    545       $d = opendir($dir); 
    546       while ($file = readdir($d)) { 
    547         if ($file[0] != '.') { 
    548           $src = addslash($dir).$file; 
    549           $dest = addslash($targetdir).$file; 
    550           if (file_exists_wrapper($dest)) { 
    551             if (!is_link($dest)) { 
    552               freepbx_log('retrieve-conf', 'error', $dest.' already exists, and is not a symlink!'); 
    553               $error_modules .= "<br />&nbsp;&nbsp;&nbsp;".$dest; 
    554               $symlink_errors = true; 
    555             } else if (readlink($dest) != $src) { 
    556               // TODO : is this the proper handling? should we just overwrite..? 
    557               freepbx_log('retrieve-conf', 'error', $dest.' already exists, and is linked to something else!'); 
    558               $error_modules .= "<br />&nbsp;&nbsp;&nbsp;".$dest; 
    559               $symlink_errors = true; 
    560             } else { 
    561               freepbx_log('retrieve-conf', 'devel-debug', $dest.' already points to '.$src.' - OK'); 
    562             } 
    563           } else { 
    564 //            // symlink, unlike copy, doesn't overwrite - have to delete first 
    565 //            if (is_link($dest) || file_exists($dest)) { 
    566 //              unlink($dest); 
    567 //            } 
    568             if (symlink($src, $dest)) { 
    569               freepbx_log('retrieve-conf', 'devel-debug', 'Symlinked '.$src.' to '.$dest); 
    570             } else { 
    571               freepbx_log('retreive-conf', 'devel-debug', 'Cannot symlink '.$src.' to '.$dest.'. Check Permissions?'); 
    572             } 
    573           } 
    574         } 
    575       } 
    576       closedir($d); 
    577     } 
    578   } 
    579   if ($error_modules) { 
    580     $nt->add_error('retrieve_conf', 'SYMLINK', _("Symlink from modules failed"), sprintf(_("retrieve_conf failed to sym link: %s<br \>This can result in FATAL failures to your PBX. If the target file exists, the symlink will not occur and you should rename the target file to allow the automatic sym link to occur and remove this error, unless this is an intentional customization."),$error_modules)); 
    581   } else { 
    582     $nt->delete('retrieve_conf', 'SYMLINK'); 
    583   } 
    584 } 
    585  
    586 // wrap copy with error handler 
    587 // 
    588 function err_copy($source, $dest) { 
    589   $ret = false; 
    590   set_error_handler("report_errors"); 
    591   //if were copying a directory, just mkdir the directory 
    592   if(is_dir($source)){ 
    593     $ret=mkdir($dest,0754); 
    594   }elseif(copy($source, $dest)) { 
    595     $ret = chmod($dest,0754); 
    596   } 
    597   restore_error_handler(); 
    598   return $ret; 
    599 } 
    600  
    601 // wrap unlink with error handler 
    602 // 
    603 function err_unlink($dest) { 
    604   set_error_handler("report_errors"); 
    605   $ret = unlink($dest); 
    606   restore_error_handler(); 
    607   return $ret; 
    608 } 
    609  
    610  
    611706//based on: http://snippets.dzone.com/posts/show/155 
    612707function listdir($directory, $recursive=true) { 
     
    630725  } 
    631726  return array_reverse($array_items);//reverse so that we get directories BEFORE the files that are in them 
    632 } 
    633  
    634 function cp_subdirs($moduledir) { 
    635   global $cp_errors; 
    636   global $cp_dirs; 
    637  
    638   $cp_errors = ""; 
    639   foreach ($cp_dirs as $subdir => $targetdir) { 
    640     $dir = addslash($moduledir).$subdir; 
    641     if(is_dir($dir)){ 
    642       foreach(listdir($dir) as $idx => $file){ 
    643         $sourcefile = $file; 
    644         $filesubdir=str_replace($dir.'/', '', $file); 
    645         $targetfile = addslash($targetdir).$filesubdir; 
    646    
    647         if (file_exists_wrapper($targetfile)) { 
    648           if (is_link($targetfile)) { 
    649             if (err_unlink($targetfile)) { 
    650               freepbx_log('retrieve-conf', 'devel-debug', "$targetfile was symbolic link, unlink successful"); 
    651             } else { 
    652               freepbx_log('retrieve-conf', 'error', "$targetfile is a symblolic link, failed to unlink!"); 
    653               break; 
    654             } 
    655           } 
    656         } 
    657         // OK, now either the file is a regular file or isn't there, so proceed 
    658         // 
    659         if (err_copy($sourcefile,$targetfile)) { 
    660           freepbx_log('retrieve-conf', 'devel-debug', "$targetfile successfully copied"); 
    661           // copy was successful, make sure it has execute permissions 
    662           chmod($targetfile,0754); 
    663         } else { 
    664           freepbx_log('retrieve-conf', 'error', "$targetfile failed to copy from module directory"); 
    665         } 
    666       } 
    667     } 
    668   } 
    669   $nt = notifications::create($db); 
    670   if ($cp_errors) { 
    671     $nt->add_error('retrieve_conf', 'CPAGIBIN', _("Failed to copy from module agi-bin"), sprintf(_("Retrieve conf failed to copy file(s) from a module's agi-bin dir: %s"),$cp_errors)); 
    672   } else { 
    673     $nt->delete('retrieve_conf', 'CPAGIBIN'); 
    674   } 
    675 } 
    676  
    677 function report_errors($errno, $errstr, $errfile, $errline) { 
    678   global $cp_errors; 
    679   switch($db_engine) { 
    680     case "sqlite3":  
    681       $escaped_string = sqlite_real_escape($errstr); 
    682       break; 
    683     case "mysql": 
    684       $escaped_string = mysql_real_escape_string($errstr); 
    685       break; 
    686     case "pgsql": 
    687       $escaped_string = pgsql_escape_string($errstr); 
    688       break; 
    689   } 
    690   freepbx_log('retrieve-conf', 'error', "php reported: '$escaped_string' after copy or unlink attempt!"); 
    691   $cp_errors .= $errstr."\n"; 
    692727} 
    693728