/**
  * Find the available service with highest priority
  *
  * @param	string		Service type
  * @param	string		Service sub type
  * @param	mixed		Service keys that should be excluded in the search for a service. Array or comma list.
  * @return	mixed		Service info array if a service was found, FLASE otherwise
  * @author	Rene Fritz <*****@*****.**>
  */
 public static function findService($serviceType, $serviceSubType = '', $excludeServiceKeys = array())
 {
     global $T3_SERVICES, $TYPO3_CONF_VARS;
     $serviceKey = FALSE;
     $serviceInfo = FALSE;
     $priority = 0;
     $quality = 0;
     if (!is_array($excludeServiceKeys)) {
         $excludeServiceKeys = t3lib_div::trimExplode(',', $excludeServiceKeys, 1);
     }
     if (is_array($T3_SERVICES[$serviceType])) {
         foreach ($T3_SERVICES[$serviceType] as $key => $info) {
             if (in_array($key, $excludeServiceKeys)) {
                 continue;
             }
             // select a subtype randomly
             // usefull to start a service by service key without knowing his subtypes - for testing purposes
             if ($serviceSubType == '*') {
                 $serviceSubType = key($info['serviceSubTypes']);
             }
             // this matches empty subtype too
             if ($info['available'] && ($info['subtype'] == $serviceSubType || $info['serviceSubTypes'][$serviceSubType]) && $info['priority'] >= $priority) {
                 // has a lower quality than the already found, therefore we skip this service
                 if ($info['priority'] == $priority && $info['quality'] < $quality) {
                     continue;
                 }
                 // service depends on external programs - check if they exists
                 if (trim($info['exec'])) {
                     $executables = t3lib_div::trimExplode(',', $info['exec'], 1);
                     foreach ($executables as $executable) {
                         if (!t3lib_exec::checkCommand($executable)) {
                             self::deactivateService($serviceType, $key);
                             $info['available'] = FALSE;
                             break;
                         }
                     }
                 }
                 // still available after exec check?
                 if ($info['available']) {
                     $serviceKey = $key;
                     $priority = $info['priority'];
                     $quality = $info['quality'];
                 }
             }
         }
     }
     if ($serviceKey) {
         $serviceInfo = $T3_SERVICES[$serviceType][$serviceKey];
     }
     return $serviceInfo;
 }
 /**
  * check the availability of external programs
  *
  * @param	string		comma list of programs 'perl,python,pdftotext'
  * @return	boolean		return FALSE if one program was not found
  */
 function checkExec($progList)
 {
     $ret = TRUE;
     $progList = t3lib_div::trimExplode(',', $progList, 1);
     foreach ($progList as $prog) {
         if (!t3lib_exec::checkCommand($prog)) {
             // program not found
             $this->errorPush('External program not found: ' . $prog, T3_ERR_SV_PROG_NOT_FOUND);
             $ret = FALSE;
         }
     }
     return $ret;
 }