protected function execute(InputInterface $input, OutputInterface $output, $quiet = false)
 {
     if (posix_geteuid() != 0) {
         $output->writeln("<error>" . _("You need to be root to run this command") . "</error>");
         exit(1);
     }
     $this->quiet = $quiet;
     if (!$this->quiet) {
         $output->writeln(_("Setting Permissions") . "...");
     }
     $freepbx_conf = \freepbx_conf::create();
     $conf = $freepbx_conf->get_conf_settings();
     foreach ($conf as $key => $val) {
         ${$key} = $val['value'];
     }
     /*
      * These are files Framework is responsible for This list can be
      * reduced by moving responsibility to other modules as a hook
      * where appropriate.
      *
      * Types:
      * 		file:		Set permissions/ownership on a single item
      * 		dir: 		Set permissions/ownership on a single directory
      * 		rdir: 		Set permissions/ownership on a single directory then recursively on
      * 					files within less the execute bit. If the dir is 755, child files will be 644,
      * 					child directories will be set the same as the parent.
      * 		execdir:	Same as rdir but the execute bit is not stripped.
      */
     $sessdir = session_save_path();
     $sessdir = !empty($session) ? $session : '/var/lib/php/session';
     $args = array();
     if ($input) {
         $args = $input->getArgument('args');
         $this->moduleName = !empty($this->moduleName) ? $this->moduleName : strtolower($args[0]);
     }
     // Always update hooks before running a Chown
     \FreePBX::Hooks()->updateBMOHooks();
     if (!empty($this->moduleName) && $this->moduleName != 'framework') {
         $mod = $this->moduleName;
         $this->modfiles[$mod][] = array('type' => 'rdir', 'path' => $AMPWEBROOT . '/admin/modules/' . $mod, 'perms' => 0755);
         $hooks = $this->fwcChownFiles();
         $current = isset($hooks[ucfirst($mod)]) ? $hooks[ucfirst($mod)] : false;
         if (is_array($current)) {
             $this->modfiles[$mod] = array_merge_recursive($this->modfiles[$mod], $current);
         }
     } else {
         $webuser = \FreePBX::Freepbx_conf()->get('AMPASTERISKWEBUSER');
         $web = posix_getpwnam($webuser);
         if (!$web) {
             throw new \Exception(sprintf(_("I tried to find out about %s, but the system doesn't think that user exists"), $webuser));
         }
         $home = trim($web['dir']);
         if (is_dir($home)) {
             $this->modfiles['framework'][] = array('type' => 'rdir', 'path' => $home, 'perms' => 0755);
             // SSH folder needs non-world-readable permissions (otherwise ssh complains, and refuses to work)
             $this->modfiles['framework'][] = array('type' => 'rdir', 'path' => "{$home}/.ssh", 'perms' => 0700);
         }
         $this->modfiles['framework'][] = array('type' => 'rdir', 'path' => $sessdir, 'perms' => 0744);
         $this->modfiles['framework'][] = array('type' => 'file', 'path' => '/etc/amportal.conf', 'perms' => 0640);
         $this->modfiles['framework'][] = array('type' => 'file', 'path' => '/etc/freepbx.conf', 'perms' => 0640);
         $this->modfiles['framework'][] = array('type' => 'dir', 'path' => $ASTRUNDIR, 'perms' => 0755);
         $this->modfiles['framework'][] = array('type' => 'rdir', 'path' => \FreePBX::GPG()->getGpgLocation(), 'perms' => 0755);
         //we may wish to declare these manually or through some automated fashion
         $this->modfiles['framework'][] = array('type' => 'rdir', 'path' => $ASTETCDIR, 'perms' => 0750);
         $this->modfiles['framework'][] = array('type' => 'file', 'path' => $ASTVARLIBDIR . '/.ssh/id_rsa', 'perms' => 0600);
         $this->modfiles['framework'][] = array('type' => 'rdir', 'path' => $ASTLOGDIR, 'perms' => 0755);
         $this->modfiles['framework'][] = array('type' => 'rdir', 'path' => $ASTSPOOLDIR, 'perms' => 0755);
         //I have added these below individually,
         $this->modfiles['framework'][] = array('type' => 'file', 'path' => $FPBXDBUGFILE, 'perms' => 0644);
         $this->modfiles['framework'][] = array('type' => 'file', 'path' => $FPBX_LOG_FILE, 'perms' => 0644);
         //We may wish to declare files individually rather than touching everything
         $this->modfiles['framework'][] = array('type' => 'rdir', 'path' => $ASTVARLIBDIR . '/' . $MOHDIR, 'perms' => 0755);
         $this->modfiles['framework'][] = array('type' => 'rdir', 'path' => $ASTVARLIBDIR . '/sounds', 'perms' => 0755);
         $this->modfiles['framework'][] = array('type' => 'file', 'path' => '/etc/obdc.ini', 'perms' => 0644);
         //we were doing a recursive on this which I think is not needed.
         //Changed to just be the directory
         //^ Needs to be the whole shebang, doesnt work otherwise
         $this->modfiles['framework'][] = array('type' => 'rdir', 'path' => $AMPWEBROOT, 'perms' => 0755);
         //Anything in bin and agi-bin should be exec'd
         //Should be after everything except but before hooks
         //So that we dont get overwritten by ampwebroot
         $this->modfiles['framework'][] = array('type' => 'execdir', 'path' => $AMPBIN, 'perms' => 0755);
         $this->modfiles['framework'][] = array('type' => 'execdir', 'path' => $ASTAGIDIR, 'perms' => 0755);
         //Merge static files and hook files, then act on them as a single unit
         $fwcCF = $this->fwcChownFiles();
         if (!empty($this->modfiles) && !empty($fwcCF)) {
             $this->modfiles = array_merge_recursive($this->modfiles, $fwcCF);
         }
     }
     $ampowner = $AMPASTERISKWEBUSER;
     /* Address concerns carried over from amportal in FREEPBX-8268. If the apache user is different
      * than the Asterisk user we provide permissions that allow both.
      */
     $ampgroup = $AMPASTERISKWEBUSER != $AMPASTERISKUSER ? $AMPASTERISKGROUP : $AMPASTERISKWEBGROUP;
     foreach ($this->modfiles as $moduleName => $modfilelist) {
         foreach ($modfilelist as $file) {
             if (!isset($file['path']) || !isset($file['perms']) || !file_exists($file['path'])) {
                 continue;
             }
             //Handle custom ownership (optional)
             $owner = isset($file['owner']) ? $file['owner'] : $ampowner;
             $group = isset($file['group']) ? $file['group'] : $ampgroup;
             //Set warning for bad permissions and move on
             $this->padPermissions($file['path'], $file['perms']);
             $file['type'] = isset($file['type']) ? $file['type'] : 'file';
             switch ($file['type']) {
                 case 'file':
                 case 'dir':
                     $path = \ForceUTF8\Encoding::toLatin1($file['path']);
                     $owner = \ForceUTF8\Encoding::toLatin1($owner);
                     $group = \ForceUTF8\Encoding::toLatin1($group);
                     $json = @json_encode(array($path, $owner, $group, $file['perms']));
                     $err = $this->jsonError();
                     if (empty($err)) {
                         $this->actions->enqueue($json);
                     } else {
                         $this->errors[] = sprintf(_('An error occurred while adding file %s because %s'), $f, $err);
                     }
                     break;
                 case 'rdir':
                     $fileperms = $this->stripExecute($file['perms']);
                     $files = $this->recursiveDirList($file['path']);
                     $path = \ForceUTF8\Encoding::toLatin1($file['path']);
                     $owner = \ForceUTF8\Encoding::toLatin1($owner);
                     $group = \ForceUTF8\Encoding::toLatin1($group);
                     $json = @json_encode(array($path, $owner, $group, $file['perms']));
                     $err = $this->jsonError();
                     if (empty($err)) {
                         $this->actions->enqueue($json);
                     } else {
                         $this->errors[] = sprintf(_('An error occurred while adding file %s because %s'), $f, $err);
                     }
                     foreach ($files as $f) {
                         if (is_dir($f)) {
                             $path = \ForceUTF8\Encoding::toLatin1($f);
                             $owner = \ForceUTF8\Encoding::toLatin1($owner);
                             $group = \ForceUTF8\Encoding::toLatin1($group);
                             $json = @json_encode(array($path, $owner, $group, $file['perms']));
                             $err = $this->jsonError();
                             if (empty($err)) {
                                 $this->actions->enqueue($json);
                             } else {
                                 $this->errors[] = sprintf(_('An error occurred while adding file %s because %s'), $f, $err);
                             }
                         } else {
                             $path = \ForceUTF8\Encoding::toLatin1($f);
                             $owner = \ForceUTF8\Encoding::toLatin1($owner);
                             $group = \ForceUTF8\Encoding::toLatin1($group);
                             $json = @json_encode(array($path, $owner, $group, $fileperms));
                             $err = $this->jsonError();
                             if (empty($err)) {
                                 $this->actions->enqueue($json);
                             } else {
                                 $this->errors[] = sprintf(_('An error occurred while adding file %s because %s'), $f, $err);
                             }
                         }
                     }
                     break;
                 case 'execdir':
                     $files = $this->recursiveDirList($file['path']);
                     $path = \ForceUTF8\Encoding::toLatin1($file['path']);
                     $owner = \ForceUTF8\Encoding::toLatin1($owner);
                     $group = \ForceUTF8\Encoding::toLatin1($group);
                     $json = @json_encode(array($path, $owner, $group, $file['perms']));
                     $err = $this->jsonError();
                     if (empty($err)) {
                         $this->actions->enqueue($json);
                     } else {
                         $this->errors[] = sprintf(_('An error occurred while adding file %s because %s'), $f, $err);
                     }
                     foreach ($files as $f) {
                         $path = \ForceUTF8\Encoding::toLatin1($f);
                         $owner = \ForceUTF8\Encoding::toLatin1($owner);
                         $group = \ForceUTF8\Encoding::toLatin1($group);
                         $json = @json_encode(array($path, $owner, $group, $file['perms']));
                         $err = $this->jsonError();
                         if (empty($err)) {
                             $this->actions->enqueue($json);
                         } else {
                             $this->errors[] = sprintf(_('An error occurred while adding file %s because %s'), $f, $err);
                         }
                     }
                     break;
             }
         }
     }
     $actioncount = count($this->actions);
     if (!$this->quiet) {
         $progress = new ProgressBar($output, $actioncount);
         $progress->setRedrawFrequency(100);
         $progress->start();
     }
     foreach ($this->actions as $action) {
         $action = json_decode($action, true);
         //Ignore call files, Asterisk may process/delete them before we get to them.
         if (pathinfo($action[0], PATHINFO_EXTENSION) == 'call') {
             continue;
         }
         $this->singleChown($action[0], $action[1], $action[2]);
         $this->singlePerms($action[0], $action[3]);
         if (!$this->quiet) {
             $progress->advance();
         }
     }
     if (!$this->quiet) {
         $progress->finish();
         $output->writeln("");
         $output->writeln("Finished setting permissions");
         foreach ($this->errors as $error) {
             $output->writeln("<error>" . $error . "</error>");
         }
         foreach ($this->infos as $error) {
             $output->writeln("<info>" . $error . "</info>");
         }
     }
 }
 protected function execute(InputInterface $input, OutputInterface $output, $quiet = false)
 {
     $this->output = $output;
     if (posix_geteuid() != 0) {
         $output->writeln("<error>" . _("You need to be root to run this command") . "</error>");
         exit(1);
     }
     $this->quiet = $quiet;
     $etcdir = \FreePBX::Config()->get('ASTETCDIR');
     if (!$this->quiet) {
         if (!file_exists($etcdir . '/freepbx_chown.conf')) {
             $output->writeln("<info>" . sprintf(_("Taking too long? Customize the chown command, See %s"), "http://wiki.freepbx.org/display/FOP/FreePBX+Chown+Conf") . "</info>");
         }
         $output->writeln(_("Setting Permissions") . "...");
     }
     $freepbx_conf = \freepbx_conf::create();
     $conf = $freepbx_conf->get_conf_settings();
     foreach ($conf as $key => $val) {
         ${$key} = $val['value'];
     }
     /*
      * These are files Framework is responsible for This list can be
      * reduced by moving responsibility to other modules as a hook
      * where appropriate.
      *
      * Types:
      * 		file:		Set permissions/ownership on a single item
      * 		dir: 		Set permissions/ownership on a single directory
      * 		rdir: 		Set permissions/ownership on a single directory then recursively on
      * 					files within less the execute bit. If the dir is 755, child files will be 644,
      * 					child directories will be set the same as the parent.
      * 		execdir:	Same as rdir but the execute bit is not stripped.
      */
     $sessdir = session_save_path();
     $sessdir = !empty($sessdir) ? $sessdir : '/var/lib/php/session';
     $args = array();
     if ($input) {
         $args = $input->getArgument('args');
         $mname = isset($args[0]) ? $args[0] : '';
         $this->moduleName = !empty($this->moduleName) ? $this->moduleName : strtolower($mname);
     }
     // Always update hooks before running a Chown
     \FreePBX::Hooks()->updateBMOHooks();
     if (!empty($this->moduleName) && $this->moduleName != 'framework') {
         $mod = $this->moduleName;
         $this->modfiles[$mod][] = array('type' => 'rdir', 'path' => $AMPWEBROOT . '/admin/modules/' . $mod, 'perms' => 0755);
         $hooks = $this->fwcChownFiles();
         $current = isset($hooks[ucfirst($mod)]) ? $hooks[ucfirst($mod)] : false;
         if (is_array($current)) {
             $this->modfiles[$mod] = array_merge_recursive($this->modfiles[$mod], $current);
         }
     } else {
         $webuser = \FreePBX::Freepbx_conf()->get('AMPASTERISKWEBUSER');
         $web = posix_getpwnam($webuser);
         if (!$web) {
             throw new \Exception(sprintf(_("I tried to find out about %s, but the system doesn't think that user exists"), $webuser));
         }
         $home = trim($web['dir']);
         if (is_dir($home)) {
             $this->modfiles['framework'][] = array('type' => 'rdir', 'path' => $home, 'perms' => 0755);
             // SSH folder needs non-world-readable permissions (otherwise ssh complains, and refuses to work)
             $this->modfiles['framework'][] = array('type' => 'rdir', 'path' => "{$home}/.ssh", 'perms' => 0700);
         }
         $this->modfiles['framework'][] = array('type' => 'rdir', 'path' => $sessdir, 'perms' => 0744, 'always' => true);
         $this->modfiles['framework'][] = array('type' => 'file', 'path' => '/etc/amportal.conf', 'perms' => 0640, 'always' => true);
         $this->modfiles['framework'][] = array('type' => 'file', 'path' => '/etc/freepbx.conf', 'perms' => 0640, 'always' => true);
         $this->modfiles['framework'][] = array('type' => 'dir', 'path' => $ASTRUNDIR, 'perms' => 0755, 'always' => true);
         $this->modfiles['framework'][] = array('type' => 'rdir', 'path' => \FreePBX::GPG()->getGpgLocation(), 'perms' => 0755, 'always' => true);
         //we may wish to declare these manually or through some automated fashion
         $this->modfiles['framework'][] = array('type' => 'rdir', 'path' => $ASTETCDIR, 'perms' => 0750, 'always' => true);
         $this->modfiles['framework'][] = array('type' => 'file', 'path' => $ASTVARLIBDIR . '/.ssh/id_rsa', 'perms' => 0600);
         $this->modfiles['framework'][] = array('type' => 'rdir', 'path' => $ASTLOGDIR, 'perms' => 0755, 'always' => true);
         $this->modfiles['framework'][] = array('type' => 'rdir', 'path' => $ASTSPOOLDIR, 'perms' => 0755);
         //I have added these below individually,
         $this->modfiles['framework'][] = array('type' => 'file', 'path' => $FPBXDBUGFILE, 'perms' => 0644);
         $this->modfiles['framework'][] = array('type' => 'file', 'path' => $FPBX_LOG_FILE, 'perms' => 0644);
         //We may wish to declare files individually rather than touching everything
         $this->modfiles['framework'][] = array('type' => 'rdir', 'path' => $ASTVARLIBDIR . '/' . $MOHDIR, 'perms' => 0755);
         $this->modfiles['framework'][] = array('type' => 'rdir', 'path' => $ASTVARLIBDIR . '/sounds', 'perms' => 0755);
         $this->modfiles['framework'][] = array('type' => 'file', 'path' => '/etc/obdc.ini', 'perms' => 0644);
         //we were doing a recursive on this which I think is not needed.
         //Changed to just be the directory
         //^ Needs to be the whole shebang, doesnt work otherwise
         $this->modfiles['framework'][] = array('type' => 'rdir', 'path' => $AMPWEBROOT, 'perms' => 0755);
         //Anything in bin and agi-bin should be exec'd
         //Should be after everything except but before hooks
         //So that we dont get overwritten by ampwebroot
         $this->modfiles['framework'][] = array('type' => 'execdir', 'path' => $AMPBIN, 'perms' => 0755, 'always' => true);
         $this->modfiles['framework'][] = array('type' => 'execdir', 'path' => $ASTAGIDIR, 'perms' => 0755, 'always' => true);
         $this->modfiles['framework'][] = array('type' => 'execdir', 'path' => $ASTVARLIBDIR . "/bin", 'perms' => 0755, 'always' => true);
         //Merge static files and hook files, then act on them as a single unit
         $fwcCF = $this->fwcChownFiles();
         if (!empty($this->modfiles) && !empty($fwcCF)) {
             foreach ($fwcCF as $key => $value) {
                 $this->modfiles[$key] = $value;
             }
             //$this->modfiles = array_merge_recursive($this->modfiles,$fwcCF);
         }
     }
     //Let's move the custom array to the end so it happens last
     //FREEPBX-12515
     //Store in a temporary variable. If Null we make it an empty array
     $holdarray = $this->modfiles['byconfig'];
     //Unset it from the array
     unset($this->modfiles['byconfig']);
     //Add it back to the array
     $this->modfiles['byconfig'] = $holdarray;
     $ampowner = $AMPASTERISKWEBUSER;
     /* Address concerns carried over from amportal in FREEPBX-8268. If the apache user is different
      * than the Asterisk user we provide permissions that allow both.
      */
     $ampgroup = $AMPASTERISKWEBUSER != $AMPASTERISKUSER ? $AMPASTERISKGROUP : $AMPASTERISKWEBGROUP;
     $fcount = 0;
     if (!$this->quiet) {
         $output->write("\t" . _("Collecting Files..."));
     }
     $exclusive = $input->hasOption('file') ? $input->getOption('file') : null;
     $process = array();
     foreach ($this->modfiles as $moduleName => $modfilelist) {
         if (!is_array($modfilelist)) {
             continue;
         }
         foreach ($modfilelist as $file) {
             switch ($file['type']) {
                 case 'file':
                 case 'dir':
                     if (empty($exclusive) || $exclusive == $file['path']) {
                         $file['files'] = array($file['path']);
                         $fcount++;
                     } else {
                         continue 2;
                     }
                     break;
                 case 'execdir':
                 case 'rdir':
                     $files = $this->recursiveDirList($file['path']);
                     $children = false;
                     if (empty($exclusive) || $exclusive == $file['path']) {
                         $file['files'] = array($file['path']);
                         $fcount++;
                         $children = true;
                     }
                     foreach ($files as $f) {
                         if (empty($exclusive) || $children || $exclusive == $f) {
                             $file['files'][] = $f;
                             $fcount++;
                         } else {
                             continue;
                         }
                     }
                     if (empty($file['files'])) {
                         continue 2;
                     }
                     break;
             }
             $process[$file['type']][] = $file;
         }
     }
     $verbose = $this->output->getVerbosity() >= OutputInterface::VERBOSITY_VERBOSE;
     if (!$this->quiet) {
         $output->writeln(_("Done"));
         if (!$verbose) {
             $progress = new ProgressBar($output, $fcount);
             $progress->setRedrawFrequency(100);
             $progress->start();
         }
     }
     foreach ($process as $type => $modfilelist) {
         foreach ($modfilelist as $file) {
             if (!isset($file['path']) || !isset($file['perms']) || !file_exists($file['path'])) {
                 if (!$this->quiet && !$verbose) {
                     $progress->advance();
                 }
                 continue;
             }
             //Handle custom ownership (optional)
             $owner = isset($file['owner']) ? $file['owner'] : $ampowner;
             $group = isset($file['group']) ? $file['group'] : $ampgroup;
             $owner = \ForceUTF8\Encoding::toLatin1($owner);
             $group = \ForceUTF8\Encoding::toLatin1($group);
             foreach ($file['files'] as $path) {
                 if ($this->checkBlacklist($path)) {
                     $this->infos[] = sprintf(_('%s skipped by configuration'), $path);
                     continue;
                 }
                 switch ($file['type']) {
                     case 'file':
                     case 'dir':
                         $this->setPermissions(array($path, $owner, $group, $file['perms']));
                         break;
                     case 'rdir':
                         if (is_dir($path)) {
                             $this->setPermissions(array($path, $owner, $group, $file['perms']));
                         } else {
                             $fileperms = $this->stripExecute($file['perms']);
                             $this->setPermissions(array($path, $owner, $group, $fileperms));
                         }
                         break;
                     case 'execdir':
                         $this->setPermissions(array($path, $owner, $group, $file['perms']));
                         break;
                 }
                 if (!$this->quiet && !$verbose) {
                     $progress->advance();
                 }
             }
         }
     }
     if (!$this->quiet && !$verbose) {
         $progress->finish();
     }
     if (!$this->quiet) {
         $output->writeln("");
         $output->writeln("Finished setting permissions");
         $errors = array_unique($this->errors);
         foreach ($errors as $error) {
             $output->writeln("<error>" . $error . "</error>");
         }
         $infos = array_unique($this->infos);
         foreach ($infos as $error) {
             $output->writeln("<info>" . $error . "</info>");
         }
     }
 }