Changeset 9978

Show
Ignore:
Timestamp:
06/28/10 14:27:49 (3 years ago)
Author:
p_lindheimer
Message:

Merged revisions 9977 via svnmerge from
http://www.freepbx.org/v2/svn/freepbx/branches/2.8

........

r9977 | p_lindheimer | 2010-06-28 11:20:44 -0700 (Mon, 28 Jun 2010) | 1 line


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

........

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • freepbx/branches/2.7

    • Property svnmerge-integrated changed from /freepbx/branches/2.6:1-8598,8646-8647,8828 /freepbx/branches/2.8:1-9715,9728,9961 to /freepbx/branches/2.6:1-8598,8646-8647,8828 /freepbx/branches/2.8:1-9715,9728,9961,9977
  • freepbx/branches/2.7/amp_conf/bin/retrieve_conf

    r8701 r9978  
    11#!/usr/bin/php -q 
    2  
    32<?php 
    43 
     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} 
     168 
     169// Emulate gettext extension functions if gettext is not available 
    5170if (! function_exists("_")) { 
    6171  function _($str) { 
     
    274439// 
    275440$nt = notifications::create($db); 
     441$con_dirs = connectdirs::create(); 
    276442 
    277443/* 
     
    339505      // 
    340506      if ($key != 'framework') { 
    341        symlink_subdirs( $amp_conf['AMPWEBROOT'].'/admin/modules/'.$key ); 
    342        cp_subdirs( $amp_conf['AMPWEBROOT'].'/admin/modules/'.$key ); 
     507        $con_dirs->symlink_subdirs( $amp_conf['AMPWEBROOT'].'/admin/modules/'.$key ); 
     508        $con_dirs->cp_subdirs( $amp_conf['AMPWEBROOT'].'/admin/modules/'.$key ); 
    343509      } 
    344510    } 
     
    347513// Now also make sure to symlink the CDR images which is not a proper module 
    348514// 
    349 symlink_subdirs( $amp_conf['AMPWEBROOT'].'/admin/cdr/'); 
     515$con_dirs->symlink_subdirs( $amp_conf['AMPWEBROOT'].'/admin/cdr/'); 
     516 
     517// Now that we have done all the symlinks and copies, we check and report if there were any errors 
     518// 
     519$con_dirs->symlink_check_errors(); 
     520$con_dirs->cp_check_errors(); 
     521 
    350522 
    351523// create an object of the extensions class 
     
    535707} 
    536708 
    537 function symlink_subdirs($moduledir) { 
    538   global $symlink_dirs; 
    539   $symlink_errors = false; 
    540  
    541   $nt = notifications::create($db); 
    542  
    543   $error_modules = ''; 
    544   foreach ($symlink_dirs as $subdir => $targetdir) { 
    545     $dir = addslash($moduledir).$subdir; 
    546     if (is_dir($dir)) { 
    547       $d = opendir($dir); 
    548       while ($file = readdir($d)) { 
    549         if ($file[0] != '.') { 
    550           $src = addslash($dir).$file; 
    551           $dest = addslash($targetdir).$file; 
    552           if (file_exists_wrapper($dest)) { 
    553             if (!is_link($dest)) { 
    554               freepbx_log('retrieve-conf', 'error', $dest.' already exists, and is not a symlink!'); 
    555               $error_modules .= "<br />&nbsp;&nbsp;&nbsp;".$dest; 
    556               $symlink_errors = true; 
    557             } else if (readlink($dest) != $src) { 
    558               // TODO : is this the proper handling? should we just overwrite..? 
    559               freepbx_log('retrieve-conf', 'error', $dest.' already exists, and is linked to something else!'); 
    560               $error_modules .= "<br />&nbsp;&nbsp;&nbsp;".$dest; 
    561               $symlink_errors = true; 
    562             } else { 
    563               freepbx_log('retrieve-conf', 'devel-debug', $dest.' already points to '.$src.' - OK'); 
     709//based on: http://snippets.dzone.com/posts/show/155 
     710function listdir($directory, $recursive=true) { 
     711  $array_items = array(); 
     712    if ($handle = opendir($directory)) { 
     713      while (false !== ($file = readdir($handle))) { 
     714        if ($file != "." && $file != "..") { 
     715          if (is_dir($directory. "/" . $file)) { 
     716            if($recursive) { 
     717              $array_items = array_merge($array_items, listdir($directory. "/" . $file, $recursive)); 
    564718            } 
    565           } else { 
    566 //            // symlink, unlike copy, doesn't overwrite - have to delete first 
    567 //            if (is_link($dest) || file_exists($dest)) { 
    568 //              unlink($dest); 
    569 //            } 
    570             if (symlink($src, $dest)) { 
    571               freepbx_log('retrieve-conf', 'devel-debug', 'Symlinked '.$src.' to '.$dest); 
    572             } else { 
    573               freepbx_log('retreive-conf', 'devel-debug', 'Cannot symlink '.$src.' to '.$dest.'. Check Permissions?'); 
    574             } 
    575           } 
     719          $file = $directory . "/" . $file; 
     720          $array_items[] = preg_replace("/\/\//si", "/", $file); 
     721        }else{ 
     722          $file = $directory . "/" . $file; 
     723          $array_items[] = preg_replace("/\/\//si", "/", $file); 
    576724        } 
    577725      } 
    578       closedir($d); 
    579     } 
    580   } 
    581   if ($error_modules) { 
    582     $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)); 
    583   } else { 
    584     $nt->delete('retrieve_conf', 'SYMLINK'); 
    585   } 
    586 
    587  
    588 // wrap copy with error handler 
    589 // 
    590 function err_copy($source, $dest) { 
    591   $ret = false; 
    592   set_error_handler("report_errors"); 
    593   if (copy($source, $dest)) { 
    594     $ret = chmod($dest,0754); 
    595   } 
    596   restore_error_handler(); 
    597   return $ret; 
    598 
    599  
    600 // wrap unlink with error handler 
    601 // 
    602 function err_unlink($dest) { 
    603   set_error_handler("report_errors"); 
    604   $ret = unlink($dest); 
    605   restore_error_handler(); 
    606   return $ret; 
    607 
    608  
    609 function cp_subdirs($moduledir) { 
    610   global $cp_errors; 
    611   global $cp_dirs; 
    612  
    613   $cp_errors = ""; 
    614   foreach ($cp_dirs as $subdir => $targetdir) { 
    615     $dir = addslash($moduledir).$subdir; 
    616     if (is_dir($dir)) { 
    617       $d = opendir($dir); 
    618       while ($file = readdir($d)) { 
    619         if ($file[0] != '.') { 
    620           $sourcefile = addslash($dir).$file; 
    621           $targetfile = addslash($targetdir).$file; 
    622  
    623           if (file_exists_wrapper($targetfile)) { 
    624             if (is_link($targetfile)) { 
    625               if (err_unlink($targetfile)) { 
    626                 freepbx_log('retrieve-conf', 'devel-debug', "$targetfile was symbolic link, unlink successful"); 
    627               } else { 
    628                 freepbx_log('retrieve-conf', 'error', "$targetfile is a symblolic link, failed to unlink!"); 
    629                 break; 
    630               } 
    631             } 
    632           } 
    633           // OK, now either the file is a regular file or isn't there, so proceed 
    634           // 
    635           if (err_copy($sourcefile,$targetfile)) { 
    636             freepbx_log('retrieve-conf', 'devel-debug', "$targetfile successfully copied"); 
    637             // copy was successful, make sure it has execute permissions 
    638             chmod($targetfile,0754); 
    639           } else { 
    640             freepbx_log('retrieve-conf', 'error', "$targetfile failed to copy from module directory"); 
    641           } 
    642         } 
    643       } 
    644       closedir($d); 
    645     } 
    646   } 
    647   $nt = notifications::create($db); 
    648   if ($cp_errors) { 
    649     $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)); 
    650   } else { 
    651     $nt->delete('retrieve_conf', 'CPAGIBIN'); 
    652   } 
    653 
    654  
    655 function report_errors($errno, $errstr, $errfile, $errline) { 
    656   global $cp_errors; 
    657   switch($db_engine) { 
    658     case "sqlite3":  
    659       $escaped_string = sqlite_real_escape($errstr); 
    660       break; 
    661     case "mysql": 
    662       $escaped_string = mysql_real_escape_string($errstr); 
    663       break; 
    664     case "pgsql": 
    665       $escaped_string = pgsql_escape_string($errstr); 
    666       break; 
    667   } 
    668   freepbx_log('retrieve-conf', 'error', "php reported: '$escaped_string' after copy or unlink attempt!"); 
    669   $cp_errors .= $errstr."\n"; 
     726    } 
     727    closedir($handle); 
     728  } 
     729  return array_reverse($array_items);//reverse so that we get directories BEFORE the files that are in them 
    670730} 
    671731