gempir

fb_tools

Dec 16th, 2022 (edited)
53
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 263.30 KB | None | 0 0
  1. #!/usr/bin/php
  2. <?php # (charset=iso-8859-1 / tabs=8 / lines=cr+lf / lang=de)
  3. /*  This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
  4.     the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
  5.     This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
  6.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  7.     You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */
  8. if($ver = "fb_tools 0.33 (c) GPL 10.12.2022 by Michael Engelke <https://mengelke.de/.dg>") {
  9.  if(!(isset($cfg) and is_array($cfg)))  // Testen ob $cfg existiert und ein array ist
  10.   $cfg = array();           // Config-Variable anlegen
  11.  foreach(array(             // Vorkonfiguration einzeln durchgehen
  12.     'sock'  => 'auto',      // Socket: http, https, ssl, tls
  13.     'host'  => 'fritz.box',     // Fritz!Box-Addresse
  14.     'pass'  => 'password',      // Fritz!Box Kennwort
  15.     'uipw'  => false,       // Fritz!Box Anmeldekennwort (Nur mit AuthBasic-Fernwartung)
  16.     'user'  => false,       // Fritz!Box Username (Optional)
  17.     'totp'  => false,       // Zweite-Faktor-Authentifizierung
  18.     'port'  => 80,          // Fritz!Box HTTP-Port (Normalerweise immer 80)
  19.     'fiwa'  => 100,         // Fritz!Box Firmware (Nur Intern)
  20.     'upnp'  => 49000,       // Fritz!Box UPnP-Port (Normalerweise immer 49000)
  21.     'jsdp'  => 512,         // Maximale Verschachtelung beim parsen von JSON-Daten
  22.     'sbuf'  => 4096,        // TCP/IP Socket-Buffergr��e oder file-Buffer
  23.     'tout'  => 30,          // TCP/IP Socket-Timeout
  24.     'pcre'  => 64*1024*1024,    // pcre.backtrack_limit (RegEx)
  25.     'meli'  => 128*1024*1024,   // Memory Limit
  26.     'upda'  => 60*60*24*100,    // Auto-Update-Check Periode (Kein Update-Check: 0)
  27.     'wrap'  => 'auto',      // Manueller Wortumbruch (Kein Umbruch: 0)
  28.     'char'  => 'auto',      // Zeichenkodierung der Console (auto/ansi/oem/utf8)
  29.     'dbfn'  => 'debug#.txt',    // Template f�r Debug-Dateien
  30.     'time'  => 'Europe/Berlin', // Zeitzone festlegen
  31.     'slct'  => 'de_DE',     // Locales Datumsformat nach Land festlegen
  32.     'drag'  => 'info hash *',   // Drag'n'Drop-Modus
  33.     'fesc'  => '|<>?*+"/\\:',   // Illegale Dateizeichen
  34.     'frep'  => '_',         // Ersetzungszeichen f�r Illegale Dateizeichen
  35.     'fbtg'  => 'fbtp_*.php',    // Plugin Glob-Pattern
  36.     'fbtm'  => 'fbtp_([\w-]+)\.php',// Plugin Preg_Match-Pattern
  37.     'fbtp'  => 'plugins',       // Plugin-Pfad
  38.     'libs'  => 'libs',      // PHP-Bibliotheken
  39.     'argn'  => 'https?:|\w:|[\da-f]{2}:',// Args-Filter
  40.     'help'  => false,       // Hilfe ausgeben
  41.     'dbug'  => false,       // Debuginfos ausgeben
  42.     'oput'  => false,       // Ausgaben speichern
  43.     'zlib'  => array('mode' => -1), // ZLib-Funktionen (mode: packlevel)
  44.     'error' => array(),     // Fehler Pool Defininieren
  45.     'proxy' => false,       // HTTP-Proxy ohne Authentifizierung (proxy.tld:port)
  46.     'touch' => ".touch",        // Workaround, wenn fb_Tools nicht schreiben kann/darf
  47.     'usrcfg'=> 'fb_config.php', // Name der Benutzerkonfiguration
  48.     'gz'    => 9,           // ZIP Deflate Pack Level
  49.  ) as $key => $var)
  50.   if(!isset($cfg[$key]))        // Existiert die Variable schon
  51.    $cfg[$key] = $var;           // Wenn nicht - dann anlegen
  52. }
  53. if(!function_exists('array_combine')) {         // http://php.net/array_combine
  54.  function array_combine($key,$value,$array=array()) {
  55.   if(count($key = array_values($key)) == count($value = array_values($value)))
  56.    foreach($value as $k => $v)
  57.     $array[$key[$k]] = $v;
  58.   return $array ? $array : false;
  59.  }
  60. }
  61. if(!function_exists('gzdecode')) {          // http://php.net/gzdecode (Workaround)
  62.  function gzdecode($data,$len=0,$out=false) {
  63.   global $cfg;
  64.   $out = '';
  65.   if(preg_match('/^\x1f\x8b\x08([\x00-\x1f])[\x00-\xff]{4}\x02[\x00-\xff]([\x00-\xff]+)([\x00-\xff]{4})([\x00-\xff]{4})$/s',$data,$gz)) {
  66.    $flag = ord($gz[1]);                     // Flags lesen
  67.    $tmp = $gz[2];
  68.    while($flag >>= 1)                       // Extra-Header �berspringen
  69.     $tmp = substr($gz[2],strpos($gzip[2],"\0")+1);
  70.    $tmp = gzinflate($tmp);                  // Deflate-Daten entpacken
  71.    if(strlen($tmp) == hexdec(bin2hex(strrev($gz[4]))) and hash('crc32b',$tmp,1) == strrev($gz[3]))  // Alles Pr�fen (L�nge & CRC32)
  72.     if($len)
  73.      $out = substr($data,0,$len);
  74.   }
  75.   if(!$out and $tmp = tempnam(null,'gz') and $fp = fopen($tmp,'w')) {   // Gepackte Daten speichern
  76.    fwrite($fp,$data);
  77.    fclose($fp);
  78.    if($fp = $cfg['zlib']['open']($tmp,'rb')) {          // Daten entpackt lesen
  79.     while(!$cfg['zlib']['eof']($fp))
  80.      $out .= $cfg['zlib']['read']($fp,$cfg['sbuf']);
  81.     $cfg['zlib']['close']($fp);
  82.     if($len)
  83.      $out = substr($out,0,$len);
  84.    }
  85.    @unlink($tmp);                       // �berreste l�schen
  86.   }
  87.   return $out;
  88.  }
  89. }
  90. if(!function_exists('hash')) {              // http://php.net/hash (Workaround f�r crc32b, md5, sha1 und optional sha256)
  91.  function hash($algo,$data,$raw=false) {
  92.   return ($algo == 'sha256' and function_exists('mhash') and $a = mhash(MHASH_SHA256,$data)) ? ($raw ? $a : bin2hex($a))
  93.     : ((preg_match('/^(md5|sha\d+)$/',$algo) and function_exists($algo) and $a = $algo($data) or $algo == 'crc32b' and $a = sprintf('%08x',crc32($data))) ? ($raw ? pack("H*",$a) : $a) : false);
  94.  }
  95. }
  96. if(!function_exists('strftime')) {          // http://php.net/strftime
  97.  function strfime($data,$time=false,$last=0) {
  98.   if(!$time)
  99.    $time = time();
  100.   if(preg_match_all('/(.)(.)/',"AlBFGoHHIhMiPaSsVWYYZTaDbMddejhMkGlgmmpAsUuNwwyyzO",$m))
  101.    $c = array_combine($m[1],$m[2]) + array('D' => 'm/d/y', 'x' => 'm/d/y', 'F' => 'Y-m-d',
  102.     'R' => 'H:i', 'T' => 'H:i:s', 'X' => 'H:i:s', 'r' => 'h:i:s A', 'c' => 'D M j H:i:s Y');
  103.   while(preg_match('/%(-?)(\w|%)/',substr($data,$last),$m,PREG_OFFSET_CAPTURE)) {
  104.    $new = isset($c[$a = $m[2][0]]) ? date($c[$a],$time) : (($a == 'j') ? substr("00".(date('z',$time) + 1),-3)
  105.     : (($a == 'C') ? floor(date('Y',$time) / 100) : (($a == 'g') ? substr(date('o',$time),-2) : (($a == 'U')
  106.     ? substr("0".floor((date('z',$time) + date('w',strtotime(date('Y',$time)."-01-01"))) / 7),-2) : (($a == 'W')
  107.     ? substr("0".floor((date('z',$time) + date('N',strtotime(date('Y',$time)."-01-01")) - 1) / 7),-2)
  108.     : preg_replace('/^%\w$/','',strtr($m[0][0],array("%n" => "\n", "%t" => "\t", "%-n" => "\n", "%-t" => "\t", "%%" => "%"))))))));
  109.    $data = substr_replace($data,$m[1][0] ? preg_replace('/^([+-])[0\s]?(\d*)$/','$1$2',$new) : $new,$last + $m[0][1],strlen($m[0][0]));
  110.    $last += strlen($m[0][0]) + $m[0][1];
  111.   }
  112.   return $data;
  113.  }
  114. }
  115. function utf8($str,$mode=0) {               // UTF-8 Tool mode: Bit0 -> 0:decode 1:encode
  116.  if(is_array($str) and preg_array('/[deuhx]|u[0-3]/',$str,5)) {
  117.   if(isset($str['u0'])) {                               // Entwertete Zeichen in UTF8 umwandeln
  118.    if(($a = $str['u0']) != "" or isset($str['u3']) and ($a = $str['u3']) != "" or isset($str['x']) and ($a = $str['x']) != "")  // hex -> Int
  119.     $a = hexdec($a);
  120.    elseif(isset($str['u1']) and isset($str['u2']) and $a = $str['u1'] and $b = $str['u2'])  // hex 20 Bit -> Int
  121.     $a = (hexdec($a) & 1023) * 1024 + (hexdec($b) & 1023) + 65536;
  122.    elseif(isset($str['h']) and $a = ifset($str['h']))                       // Dec -> Int
  123.     $a = intval($a);
  124.    else                                             // Fehler
  125.     $a = false;
  126.   }
  127.   else
  128.    $a = $str[0];
  129.   if(isset($str['e']) or is_int($a)) {  // Ansi -> UTF8
  130. //   if(function_exists('utf8_encode') and !is_int($a)) return utf8_encode($a);
  131.    if(($a = is_int($a) ? $a : ord($a)) < 128)
  132.     return chr($a);
  133.    $b = "";
  134.    $c = 6;
  135.    while($a >= 1 << $c and --$c) {
  136.     $b = chr($a & 63 | 128).$b;
  137.     $a >>= 6;
  138.    }
  139.    return chr((1 << 7 - $c) -1 << ++$c | $a).$b;
  140.   }
  141.   elseif(isset($str['d'])) {        // UTF8 -> Ansi
  142. //   if(function_exists('utf8_decode')) return utf8_decode($a);
  143.    for($b = ord($a[0]) % (1 << 7 - strlen($a)), $c = 1; $c < strlen($a); $c++)
  144.     $b = $b * 64 + (ord($a[$c]) & 63);
  145.    return ($b < 256) ? chr($b) : "\\u".(($b < 65536) ? str_pad(dechex($b),4,0,STR_PAD_LEFT)
  146.     : str_pad(dechex(($b - 65536) >> 10 | 55296),4,0,STR_PAD_LEFT)."\\u".str_pad(dechex(($b - 65536) & 1023 | 56320),4,0,STR_PAD_LEFT));
  147.   }
  148.   return $a;
  149.  }
  150.  elseif(is_array($str)) {       // Array -> utf8[mode]
  151.   foreach($str as $key => $var)
  152.    if(is_string($var) or is_array($var))
  153.     $str[$key] = call_user_func(__FUNCTION__,$var,$mode);
  154.  }
  155.  else {
  156.   $p = "[\x80-\xbf]";
  157.   $p = "[\xc0-\xdf]$p|[\xe0-\xef]$p{2}|[\xf0-\xf7]$p{3}|[\xf8-\xfb]$p{4}|[\xfc-\xfd]$p{5}|\xfe$p{6}";
  158.   $p = "/".(($mode & 1) ? "(?P<u>$p)|(?P<e>[\x80-\xff])".(($mode & 2)
  159.     ? '|\\\\(?:u\{(?P<u0>[\da-f]+)\}|(?:u(?P<u1>d[89ab][\da-f]{2})\\\\u(?P<u2>d[cdef][\da-f]{2}))|u(?P<u3>[\da-f]{4}))|(?:&\#(?:(?P<h>\d+)|x(?P<x>[\da-f]+));)'
  160.     : '') : "(?P<d>$p)")."/";
  161.   if((float)phpversion() > 5.2)
  162.    return preg_replace_callback($p,__FUNCTION__,$str);
  163.   elseif(preg_match_all($p,$str,$match,PREG_OFFSET_CAPTURE)) {  // Workaround PHP 4.3 - 5.2
  164.    for($a=count($match[0])-1; $a >= 0; $a--) {
  165.     $var = array($match[0][$a][0]);
  166.     $var[(isset($match['e']) and $match['e'][$a][1] > -1) ? 'e' : ((isset($match['d']) and $match['d'][$a][1] > -1) ? 'd' : 'u')] = $var[0];
  167.     $str = substr_replace($str,utf8($var),$match[0][$a][1],strlen($match[0][$a][0]));
  168.    }
  169.   }
  170.  }
  171.  return $str;
  172. }
  173. function file_contents($file,$data=false,$mode=false) { // (Gepackte) Datei lesen/schreiben|mode: Bit1 -> Lock, Bit3 -> Append
  174.  global $cfg;
  175.  if(is_string($data)) {                     // Datei schreiben
  176.   if($file == ':')                      // Bei nur ":" nichts schreiben
  177.    return true;
  178.   if(strpos($file,'%') !== false)               // strftime aufl�sen
  179.    $file = @strftime($file);
  180.   if(is_bool($mode) and !$mode)
  181.    if(preg_match('/\.t?gz$/i',$file) and $fp = $cfg['zlib']['open']($file,'w'.$cfg['zlib']['mode'])) {// Write GZip
  182.     dbug("Schreibe GZip-File: $file",9);
  183.     $data = $cfg['zlib']['write']($fp,$data);
  184.     $cfg['zlib']['close']($fp);
  185.     return $data;
  186.    }
  187.    elseif(preg_match('/\.t?bz(ip)?2?$/i',$file) and ifset($cfg['bzip']) and $fp = bzopen($file,'w')) {  // Write BZip2
  188.     dbug("Schreibe BZip2-File: $file",9);
  189.     $data = bzwrite($fp,$data);
  190.     bzclose($fp);
  191.     return $data;
  192.    }
  193.    elseif(preg_match('/\.zip$/i',$file) and !preg_match('/^PK\x03\x04/',$data))
  194.     $data = data2zip(array(preg_replace('/.*?([^\/]*)\.zip$/','$1',$file) => $data));
  195.   if(function_exists('file_put_contents'))
  196.    return file_put_contents($file,$data,$mode);         // Ungepackt schreiben
  197.   else {                            // file_put_contents ($mode ist nicht vollst�ndig implemmentiert)
  198.    if($fp = fopen($file,($mode & 1<<3) ? 'a' : 'w')) {      // FILE_APPEND -> 8
  199.     if(is_array($data))
  200.      $data = implode('',$data);
  201.     if($mode & 1<<1) {  // LOCK_EX -> 2
  202.      if(flock($fp,2)) { // flock LOCK_EX
  203.       fputs($fp,$data);
  204.       flock($fp,3); // flock LOCK_UN
  205.      }
  206.      else {
  207.       fclose($fp);
  208.       return null;
  209.      }
  210.     }
  211.     else
  212.      fputs($fp,$data);
  213.     fclose($fp);
  214.     $fp = strlen($data);
  215.    }
  216.    return $fp;
  217.   }
  218.  }
  219.  elseif(!$data and !$mode and !preg_match('/\.t?gz$/i',$file))  // Datei vollst�ndig lesen (data:0)
  220.   return file_get_contents($file);
  221.  elseif(is_int($data) and (float)phpversion() >= 5.1) {     // Datei ab Offset lesen (data:offset, mode:length) & PHP 5.1+
  222.   $data = array($file,false,null,filesize($file) + (($data < 0) ? max($data,-filesize($file)) : min($data,filesize($file))));
  223.   if($mode)
  224.    $data[] = $mode;
  225.   return call_user_func_array('file_get_contents',$data);
  226.  }
  227.  elseif(is_int($data) and $fp = fopen($file,'r')) {     // Datei ab Offset lesen (data:offset, mode:length)
  228.   dbug("Lese File: $file ($data/$mode)",9);
  229.   fseek($fp,$data,($data < 0) ? SEEK_END : SEEK_SET);
  230.   $data = "";
  231.   if($mode)
  232.    $data = fread($fp,$mode);
  233.   else
  234.    while(!feof($fp))
  235.     $data .= fread($fp,$cfg['sbuf']);
  236.   fclose($fp);
  237.   return $data;
  238.  }
  239.  elseif(preg_match('/\.t?bz(ip)?2?$/i',$file) and ifset($cfg['bzip']) and $fp = bzopen($file,'r')) {    // BZip2 lesen
  240.   dbug("Lese BZip2-File: $file",9);
  241.   $data = "";
  242.   while(($var = bzread($fp,$cfg['sbuf'])) !== false)
  243.    $data .= $var;
  244.   bzclose($fp);
  245.   return $data;
  246.  }
  247.  elseif($fp = $cfg['zlib']['open']($file,'r')) {        // (gz)Datei entpackt lesen
  248.   dbug("Lese gzFile: $file",9);
  249.   $data = "";
  250.   while(!$cfg['zlib']['eof']($fp))
  251.    $data .= $cfg['zlib']['read']($fp,$cfg['sbuf']);
  252.   $cfg['zlib']['close']($fp);
  253.   return $data;
  254.  }
  255.  return false;
  256. }
  257. function file_stream($file,$data=false) {       // Datei-Stream Zeilenweise Lesen/Schreiben - Optional mit GZip/BZip2
  258.  global $cfg,$fsData;
  259.  $out = $fs = false;
  260.  if(!(isset($fsData) and is_array($fsData)))                // Globale Variabel vorhanden?
  261.   $fsData = array('bs' => $cfg['sbuf'], 'pt' => 0, 'fs' => array());    // Globale Variable anlegen
  262.  if(is_string($file)) {                         // OPEN (file)
  263.   $fs = array('file' => $file, 'seek' => 0, 'data' => '', 'mode' => (is_int($data)) ? $data : ($data ? 1 : 0));     // Init
  264.   $rw = ($fs['mode'] & 1) ? 'w' : 'r';
  265.   $mode = $fs['mode'] & 6;
  266.   dbug("file_stream: open ",9,6);
  267.   if(($mode == 2 or preg_match('/\.t?gz$/i',$file)) and $fp = $cfg['zlib']['open']($file,$rw.$cfg['zlib']['mode'])) {   // GZip
  268.    dbug("GZip-File",9,12);
  269.    $fs['mode'] |= 2;
  270.    $fs['fp'] = $fp;
  271.   }
  272.   elseif($mode == 4 or preg_match('/\.t?bz(ip)?2?$/i',$file) and ifset($cfg['bzip']) and $fp = bzopen($file,$rw)) { // BZip2
  273.    dbug("BZip2-File",9,12);
  274.    $fs['mode'] |= 4;
  275.    $fs['fp'] = $fp;
  276.   }
  277.   elseif($fp = fopen($file,$rw)) {                                          // Normal
  278.    dbug("File",9,12);
  279.    $fs['fp'] = $fp;
  280.   }
  281.   else {
  282.    dbug("Fail",9,12);
  283.    $file = $fs = false;
  284.   }
  285.   if($fs)                       // Neuen FileStream ablegen
  286.    $fsData['fs'][$file = ++$fsData['pt']] = $fs;
  287.   $out = $file;
  288.  }
  289.  elseif($file and is_int($file) and isset($fsData['fs'][$file]) and $fs = $fsData['fs'][$file]) {   // Daten lesen / schreiben
  290.   $mode = $fs['mode'] & 6;              // GZip/BZip2/Std
  291.  
  292.   if(!($fs['mode'] & 1)) {              // LESEN
  293.    if(is_int($data)) {                  // Byteweise
  294.     if($mode == 2)                  // GZip
  295.      $out = $cfg['zlib']['read']($fs['fp'],$data);
  296.     elseif($mode == 4) {                // BZip
  297.      if(($len = strlen($fs['data'])) < $data)
  298.       $fs['data'] .= bzread($fs['fp'],$data-$len);
  299.      $out = substr($fs['data'],0,$data+1);
  300.      $fs['data'] = substr($fs['data'],strlen($out));
  301.     }
  302.     elseif(!$mode)                  // Normal
  303.      $out = fread($fs['fp'],$data);
  304.    }
  305.    elseif($mode == 2)                   // GZip (Zeilenweise)
  306.     $out = $cfg['zlib']['gets']($fs['fp'],$fsData['bs']);
  307.    elseif($mode == 4) {                 // BZip (Zeilenweise)
  308.     if(($len = strlen($fs['data'])) < $fsData['bs']) {
  309.      $var = bzread($fs['fp'],$fsData['bs'] - $len);
  310.      $fs['data'] .= $var;
  311.      $fs['seek'] += strlen($var);
  312.     }
  313.     if(($pos = strpos($fs['data'],"\n")) === false)
  314.      $pos = strlen($fs['data']);
  315.     $out = substr($fs['data'],0,$pos+1);
  316.     $fs['data'] = substr($fs['data'],strlen($out));
  317.    }
  318.    elseif(!$mode)                   // Normal (Zeilenweise)
  319.     $out = fgets($fs['fp'],$fsData['bs']);
  320.    $fs['seek'] += strlen($out);
  321.   }
  322.   elseif(($fs['mode'] & 1) and $data) {         // SCHREIBEN (Byteweise)
  323.    if($mode == 2)                   // GZip
  324.     $out = $cfg['zlib']['write']($fs['fp'],$data);
  325.    elseif($mode == 4)                   // BZip
  326.     $out = bzwrite($fs['fp'],$data);
  327.    elseif(!$mode)                   // Normal
  328.     $out = fwrite($fs['fp'],$data);
  329.    $fs['seek'] += $out;
  330.   }
  331.   if(!$out or $fs['mode'] & 1 and !$data) {     // CLOSE
  332.    if($mode == 2)                   // GZip
  333.     $cfg['zlib']['close']($fs['fp']);
  334.    elseif($mode == 4)                   // BZip
  335.     bzclose($fs['fp']);
  336.    elseif(!$mode)                   // Normal
  337.     fclose($fs['fp']);
  338.    unset($fsData['fs'][$file]);             // Pointer l�schen
  339.    $file = $fs = false;                 // Variabeln l�schen
  340.   }
  341.  }
  342.  if($file and $fs)
  343.   $fsData['fs'][$file] = $fs;
  344.  return $out;
  345. }
  346. function listDir($pat,$dirs='',$mode=0,$list=array()) { // Liest ein Verzeichnis aus (Pattern, Verzeichnis(e), Modus)   // Bit0 > Pattern, Bit1 > PathPat
  347.  if(!($mode & 1<<0)) {      // Simple-Pattern           // Bit2 > basename, Bit3 > noFile, Bit4 > noDir, Bit5 > Recusiv, Bit6 > Sort
  348.   if(!$dirs) {          // Kein Verzeichnis angegeben
  349.    if(file_exists($pat))    // Pattern existiert
  350.     if(is_file($pat)) {     // Pattern ist ein File
  351.      $dirs = dirname($pat);
  352.      $pat = basename($pat);
  353.     }
  354.     else {          // Pattern ist ein Verzeichnis
  355.      $dirs = $pat;
  356.      $pat = '*';
  357.     }
  358.    elseif($var = ifset($pat,'/^(.*?)([^\\\\\/]*[*?][^\\\\\/]*)$/')) {   // Pattern besteht aus Verzeichnis und Pattern (glob)
  359.     $dirs = $var[1];
  360.     $pat = $var[2];
  361.    }
  362.    if(!$dirs)
  363.     $dirs = '.';
  364.   }
  365.   if($pat and !function_exists('fnmatch')) {        // Workaround wenn fnmatch() nicht verf�gbar ist
  366.    $pat = "/^".strtr(preg_quote($pat,'/'),array('\*' => '.*', '\?' => '.', '\[' => '[', '\]' => ']'))."$/i";
  367.    $mode |= 1<<0;
  368.   }
  369.  }
  370.  foreach(array_unique((array)$dirs) as $dir) {      // Alle Verzeichnisse durchgehen
  371.   if(file_exists($dir) and $dp = opendir($dir)) {
  372.    $dir = preg_replace('/[\\\\\/]$/','',$dir);      // Letzten Slash entfernen
  373.    while(($file = readdir($dp)) !== false)
  374.     if(!preg_match('/^\.\.?$/',$file)) {        // Kein Current oder Parent
  375.      $fn = (($mode & 1<<1) ? "$dir/" : '').$file;   // Bit 1 -> Filename f�r Pattern
  376.      if(!$pat or $mode & 1<<0 and preg_match($pat,$fn) or !($mode & 1<<0) and fnmatch($pat,$fn,FNM_CASEFOLD)    // Bit 0 -> Patterncheck
  377.     and (!($mode & (1<<3 | 1<<4)) or $mode & 1<<3 and !is_file("$dir/$file") or $mode & 1<<4 and !is_dir("$dir/$file"))) {  // Bit3 -> file / Bit4 -> dir
  378.       $fn = ($mode & 1<<2) ? $file : (($dir != '.') ? "$dir/" : "").$file.((is_dir("$dir/$file")) ? '/' : '');
  379.       if($mode & 1<<2)
  380.        $list[realpath("$dir/$file")] = $fn;
  381.       else
  382.        array_push($list,$fn);
  383.       if($mode & 1<<5 and is_dir("$dir/$file") and $array = call_user_func(__FUNCTION__,$pat,"$dir/$file",$mode))   // Bit 5 -> Rekursiv
  384.        if($mode & 1<<2)                         // Bit 2 -> Basename
  385.         $list[($mode & 1<<2) ? realpath($file) : $file] = $array;   // Assoc
  386.        else
  387.         $list = array_merge($list,$array);              // List
  388.      }
  389.     }
  390.    closedir($dp);
  391.   }
  392.  }
  393.  if(!$mode & 1<<2)
  394.   $list = array_unique($list);
  395.  if($mode & 1<<6)                           // Bit 6 -> Sortieren
  396.   natcasesort($list);
  397.  return $list ? $list : false;
  398. }
  399. function ifset(&$x,$y=false) {              // Variabeln pr�fen und Optional vergleichen (var,test)
  400.  return (isset($x) and ($x or $x != '')) ? ($y ? ((is_string($y) and preg_match('!^(([^\w\s]).*\2[imsuxADU]{0,8})((\d)|(a))?($)!Us',$y,$w) and is_string($x)
  401.     and ($w[5] and preg_match_all($w[1],$x,$z) or preg_match($w[1],$x,$z))) ? (($z and $w[4] != "") ? $z[(int)$w[4]] : $z) : (is_array($x)
  402.     ? ((is_string($y) and $w) ? preg_grep($y,$x) : (is_int($y) ? count($x) == $y : (is_bool($y) ? $x : array_search($y,$x))))
  403.     : (((is_callable($y) and $z = call_user_func($y,$x)) ? (is_bool($z) ? $x : $z) : ((!is_bool($x) or is_bool($y)) and $x == $y)))))
  404.     : (is_string($x) ? (is_string($y) ? $x : strlen($x)) : ((is_numeric($x) or is_bool($x)) ? $x : (is_array($x) ? count($x) : !$y)))) : false;
  405. }
  406. function preg_array($x,$y,$z=0) {           // Durchsucht einen Array mit Regul�ren Ausdruck (preg,array,mode)
  407.  $w = ($z & 1<<1) ? array() : false;    // Return All/First             // Bit 0: Search 0:value / 1:key    1
  408.  foreach($y as $k => $v)                                // Bit 1: Result 0:first / 1:all    2
  409.   if(($z & (1<<4)) and is_array($v) and $u = call_user_func(__FUNCTION__,$x,$v,$z)) // Bit 2: Result 0:value / 1:key    4
  410.    if($z & 1<<1)            // Result All                   // Bit 3: Search 0:found / 1:not found  8
  411.     $w[$k] = $u;                                    // Bit 4: 0:iterativ     / 1:rekusiv    16
  412.    else                 // Result First
  413.     return ($z & 1<<2) ? $k : $u;   // Return Key/Value
  414.   elseif(($z & 1<<3) xor preg_match($x,($z & 1<<0) ? $k : (is_array($v) ? "" : $v)))    // (not)Found & Key/Value
  415.    if($z & 1<<1)            // Result All
  416.     $w[$k] = $v;
  417.    else                 // Result First
  418.     return ($z & 1<<2) ? $k : $v;   // Return Key/Value
  419.  return $w;
  420. }
  421. function unBase($data,$base=false,$bits=false) {    // unBase2-128 (data-string, base-chars[Default: AVM-Base32], input-bits)
  422.  for($base = $base ? $base : 'ABCDEFGHIJKLMNOPQRSTUVWXYZ123456', $bits = $bits ? $bits : intval(log(strlen($base),2)), $a=$b=$c=0, $out=""; $a < strlen($data); )
  423.   if(($e = strpos($base,$data[$a++])) !== false)
  424.    for($c = ($c << $bits) + $e, $b += $bits; $b >= 8; $c %= 1 << $b)
  425.     $out .= chr($c >> ($b -= 8));
  426.  return $out;
  427. }
  428. function getArg($name=false,$preg=false,$arg=null) {    // N�chsten Parameter holen (argname, /preg_match/, argname-only & return@false)
  429.  global $cfg,$pset; // args,argc,argn,arg,$opts
  430.  $tst = $arg;                                   // Parameter retten f�r TEST-Modus
  431.  if(is_string($name) and $name[0] == '-') {                 // Optionen abfragen
  432.   $def = 'opts';
  433.   $name = substr($name,1);
  434.  }
  435.  else                                       // Argumente abfragen
  436.   $def = 'args';
  437.  if($name) {                                    // Benanntes Argument (name)
  438.   if(is_bool($name))                                // Ungepr�fte Parameter vorhanden? (name -> true)
  439.    $arg = preg_array("/^(".str_replace('\|','|',preg_quote(implode('|',array_keys($cfg['argk'])),'/')).")$/",$cfg['arg'],11);
  440.   elseif(isset($cfg[$def][$name]) and is_array($var = $cfg[$def][$name])) { // Benanntes Argument ist ein Array
  441.    if(is_string($preg) and strlen($preg) == 1)                  // Array als CSV zur�ckgeben? (preg -> .)
  442.     $arg = implode($preg,str_replace($preg,$preg.$preg,$var));
  443.    elseif(!is_array($preg) and $var = current($cfg[$def][$name]) and ifset($var,$preg)) // Aktuelles Argument aus Array zur�ckgeben (preg)
  444.     $arg = $preg ? $var : current($cfg[$def][$name]);
  445.    elseif(is_array($preg))                          // Nur Argumente zur�ckgeben, die auf [preg] passen oder alle
  446.     $arg = (isset($preg[0]) and $preg[0]) ? preg_array($preg[0],$cfg[$def][$name],(isset($preg[1])) ? $preg[1] : 2) : $cfg[$def][$name];
  447.   }
  448.   elseif(isset($cfg[$def][$name]))                      // Benannter Parameter
  449.    $arg = $preg ? ifset($cfg[$def][$name],$preg) : $cfg[$def][$name];
  450.  }
  451.  elseif(is_null($arg) and is_array($preg) and $cfg['argc'])         // Alle restlichen Nummerischen Parameter zur�ckgeben
  452.   for($arg=array(); $name = array_shift($cfg['argc']);)
  453.    $arg[] = $cfg['arg'][$name];
  454.  if($def == 'opts')                             // Optionen sofort zur�ckgeben
  455.   return (is_null($arg)) ? false : ((is_array($preg)) ? (array)$arg : $arg);    // Vorgabe oder false zur�ckgeben
  456.  elseif($tst === true)                              // Parameter nur Testweise zur�ckgeben
  457.   return ($arg === true) ? (($var = ifset($cfg['arg'][$name = reset($cfg['argc'])],$preg)) ? ($preg ? $var : $cfg['arg'][$name]) : false) : $arg;
  458.  elseif(is_null($arg) or $arg == $tst and $cfg['argc']) {           // Nummerierter/Unbenannter Parameter
  459.   foreach($cfg['argc'] as $val => $name)                    // Auf Inhaltpr�fen
  460.    if(($var = ifset($cfg['arg'][$name],$preg)) != "")
  461.     break;
  462.   if(ifset($var) != "") {                           // Wurde ein Nummerierter/Unbenannter Parameter gefunden?
  463.    if(!$cfg['argn'])                                // �bergabe/Abfrage vom alten Parameter-System erm�glichen
  464.     $pset++;
  465.    unset($cfg['argc'][$val]);                           // Parameter l�schen
  466.    $arg = $preg ? $var : $cfg['arg'][$name];
  467.   }
  468.  }
  469.  return (is_null($arg) or !$arg and (is_array($arg) or is_string($arg) and is_bool($arg))) ? false : $cfg['argk'][$name] = ((is_array($preg)) ? (array)$arg : $arg);    // Vorgabe oder false zur�ckgeben
  470. }
  471. function out($str,$mode=0,$lf=PHP_EOL) {        // Textconvertierung vor der ausgabe (mode: 0 -> echo / 1 -> noautolf / 2 -> debug)
  472.  global $cfg;
  473.  $cp = ifset($cfg['char']) ? (array)$cfg['char'] : array('c' => 1);
  474.  if(ifset($cp['n']))                        // Char:none
  475.   return "";                            // Keine Ausgabe
  476.  if(is_array($str))
  477.   $str = print_r($str,true);
  478.  if(is_string($str) and $str != "") {
  479.   if(!($mode & 1<<1) and preg_match('/\S$/D',$str))     // AutoLF
  480.    $str .= $lf;
  481.   if($mode & 1<<2)                      // Unn�tige Whitespaces im Debug-Modus l�schen
  482.    $str = preg_replace('/(?<=\n\n|\r\n\r\n)\s+$/','',$str);
  483.   if($cfg['oput'] and !($mode & 1<<2))              // Ausgabe speichern
  484.    file_contents($cfg['oput'],textTable($str,-1),8);
  485.   if(ifset($cp['d']) and preg_match_all('/(.)(.)/',base64_decode(
  486.     "thSnFceA/IHpguKD5ITgheWG54fqiOuJ6Irvi+6M7I3EjsWPyZDmkcaS9JP2lPKV+5b5l/+Y1pncmqOc4aDtofOi+qPxpNGlqqa6p7+orKq9q7ysoa2rrruv3+G15rHx9/aw+Lf6sv2g/"
  487.     .((substr($cp['d'],-3) == 437) ? "6KbpZ0=" : "/ib2J3Xnq6pwbXCtsC3qbiivaW+48bDx6TP8NDQ0crSy9PI1M3WztfP2KbdzN7T4NTi0uP15NXl/ufe6Nrp2+rZ6/3s3e2v7rTvrfC+87b0p/W496j5ufuz/A==")),$m))
  488.    $str = strtr(utf8($str),array_combine($m[1],$m[2]));     // DOS
  489.   elseif(ifset($cp['m']) and preg_match_all('/(.)(.)/',"ǀ��������Ďɐ����֙ܚמ��������������¶����������������������������������",$m))
  490.    $str = strtr(utf8($str),array_combine($m[1],$m[2]));     // cp852
  491.   elseif(ifset($cp['u']))
  492.    $str = utf8($str,3);                     // UTF8
  493.   elseif(ifset($cp['h']) and preg_match_all('/(.)([\da-z#]+)/','&amp<lt>gt"quot\'#39�auml�ouml�uuml�szlig�Auml�Ouml�Uuml',$m))
  494.    $str = strtr($str,array_combine($m[1],preg_replace('/.+/','&$0;',$m[2])));   // HTML
  495.   elseif((ifset($cp['c']) or ifset($cp['l']) or ifset($cp['r']) or !ifset($cp['a']))
  496.     and preg_match_all('/([^ -~]+)([ -~]+)/','�!�GBP�|�\\S�"�(c)�<<�-�(R)��\'�^�+-�2�3�\'�u�I�\''
  497.     .'�.�1�>>�1/4�1/2�3/4�?�AE�Ae�Oe�Ue��ae�oe�ue�ss�����A�C����E����I�D�N�����O���UݥY�p�����a�c����e����i�n�������o���u�P��y�x�:',$m)) {
  498.    $a = array();                        // 7 Bit ASCII
  499.    foreach($m[1] as $key => $var)
  500.     for($b=0; $b < strlen($var); $b++)
  501.      $a[$var[$b]] = $m[2][$key];
  502.    $str = strtr(utf8($str),$a);
  503.   }
  504.   else                              // Ansi
  505.    $str = utf8($str);
  506.   $str = textTable($str,-1);                    // Tabelle im String
  507.   if($var = ifset($cp['l'],"") and preg_match_all('/([a-z\d])(.)/i','1I2Z3E4A5S6G7T8B9g0Oa4A4b8B8e3E3g6G6l1L1o0O0q9Q9s5S5t7T7z2Z2'.(is_numeric($var) ? '' : 'c<C(h#H#i!I!x+X+'),$m))
  508.    $str = strtr($str,array_combine($m[1],$m[2]));
  509.   elseif(ifset($cp['r']))
  510.    $str = str_rot13($str);
  511.   if($col = (int)$cfg['wrap'] and --$col) {         // My WordWrap
  512. #   $str = wordwrap($str,$cfg['wrap']-1,$lf,true);
  513.    $esc = array();                      // Mutibytes Entwerten
  514.    $pos = 0;
  515.    $p = "[\x80-\xbf]";
  516.    while(preg_match("/\x7f|[\xc0-\xdf]$p|[\xe0-\xef]$p{2}|[\xf0-\xf7]$p{3}|[\xf8-\xfb]$p{4}|[\xfc-\xfd]$p{5}|\xfe$p{6}
  517.     |\\\\(u\{[\da-f]+\}|ud[89ab][\da-f]{2}\\\\ud[cdef][\da-f]{2}|u[\da-f]{4})|(&\#(\d+|x[\da-f]+);)/x",substr($str,$pos),$m,PREG_OFFSET_CAPTURE)) {
  518.     $str = substr_replace($str,"\x7f",$pos + $m[0][1], strlen($m[0][0]));
  519.     $esc[] = $m[0][0];
  520.     $pos += $m[0][1] + 1;
  521.    }
  522.    $inp = str_replace("\x0b"," ",$str);             // WordWrap vorbereiten
  523.    $len = strlen($inp);
  524.    $str = "";
  525.    $pos = 0;
  526.    while(preg_match('/^([ \t]*)(.*?(?:\r?\n|$))/',substr($inp,$pos),$m) and $pos < $len) {
  527.     if(($col-($spc = strlen($m[1]))) < 16) {
  528.      $spc = 0;
  529.      $m[1] = "";
  530.     }
  531.     $str .= preg_replace(array("/^/","/\x0b/"),array($m[1],"$lf$m[1]"),wordwrap($m[2],$col-$spc,"\x0b",true));
  532.     $pos += strlen($m[0]);
  533.    }
  534.    $m = 0;                          // Entwertete Zeichen wieder zur�ckholen
  535.    while(($m = strpos($str,"\x7f",$m)) !== false) {
  536.     $str = substr_replace($str,$esc[0],$m,1);
  537.     $m += strlen(array_shift($esc));
  538.    }
  539.   }
  540.  }
  541.  elseif(is_array($str))                     // Leeres Array
  542.   $str = "";
  543.  return ($mode & 1<<0) ? $str : print $str;
  544. }
  545. function dbug($str,$level=0,$mode=4) {          // Debug-Daten ausgeben/speichern (mode: 4 -> Debug) # dbug(compact(explode(',','array,key,var')));
  546.  global $cfg;
  547.  if(floor($cfg['dbug']/(1<<$level))%2) {        // Nur Entsprechenden Debug-Level ausgaben
  548.   if(is_string($mode))                  // Entweder Mode-Angabe oder Dateiname
  549.    if(preg_match('/^(\d+),(.+)$/',$mode,$var)) {
  550.     $mode = $var[1];
  551.     $file = $var[2];
  552.    }
  553.    else {
  554.     $file = $mode;
  555.     $mode = 4;
  556.    }
  557.   else
  558.    $file = false;
  559.   $time = ($cfg['dbug'] & 1<<2 and !($mode & 1<<3)) ? number_format(array_sum(explode(' ',microtime()))-$cfg['time'],3,',','.').' ' : '';
  560.   if($cfg['dbug'] & 1<<1 and $cfg['dbfn'] and $file)    // Debug: Array in separate Datei sichern
  561.    if(strpos($file,'#') and is_array($str))
  562.     foreach($str as $key => $var)           // Debug: Array in mehrere separaten Dateien sichern
  563.      file_contents($cfg['dbcd'].str_replace('#',"-".str_replace('#',$key,$file),$cfg['dbfn']),$time.((is_array($var)) ? print_r($var,true) : $var),8);
  564.    else
  565.     file_contents($cfg['dbcd'].str_replace('#',"-$file",$cfg['dbfn']),$time.((is_array($str)) ? print_r($str,true) : $str),8);  // Alles in EINE Datei Sichern
  566.   else {
  567.    if(is_string($str)) {
  568.     if(preg_match('/^\$(\w+)$/',$str,$var) and isset($GLOBALS[$var[1]]))    // GLOBALS Variable ausgeben
  569.      $str = "$str => ".(is_array($GLOBALS[$var[1]]) ? print_r($GLOBALS[$var[1]],true) : $GLOBALS[$var[1]]);
  570.     elseif(!($mode & 1<<1) and preg_match('/\S$/D',$str))// AutoLF
  571.      $str .= "\n";
  572.    }
  573.    elseif(is_array($str))
  574.     $str = print_r($str,true);
  575.    if($cfg['dbug'] & 1<<1 and $cfg['dbfn']) {       // Debug: Ausgabe/Speichern
  576.     file_contents($cfg['dbcd'].str_replace('#','',$cfg['dbfn']),$time.$str,8);
  577.     if(!$level)                     // Nur Level 0 Ausgeben
  578.      out($time.$str,($mode | 4) & 7);
  579.    }
  580.    else
  581.     out($time.$str,($mode | 4) & 7);
  582.   }
  583.  }
  584. }
  585. function errmsg($msg=0,$name='main') {          // Fehlermeldung(en) Sichern
  586.  global $cfg;
  587.  if(!ifset($cfg['errmute']))    // Fehleraufzeichnung pausieren?
  588.   if($msg) {            // Fehlermeldung speichern
  589.    dbug("Fehler: $msg",9);
  590.    $cfg['error'][$name][] = trim($msg);
  591.   }
  592.   else {            // Letzte Fehlermeldung abrufen
  593.    dbug("Suche Fehler von Funktion: $name",9);
  594.    if($name == "*" and $var = array_keys($cfg['error']))
  595.     $name = end($var);      // Letzte Fehlermeldung finden
  596.    while(isset($cfg['error'][$name]) and is_array($cfg['error'][$name]))// Fehlermeldung vorhanden?
  597.     if($val = end($cfg['error'][$name]) and preg_match('/^\w+$/',$val)) // M�glicher Rekusive Fehlermeldung?
  598.      $name = $val;                          // N�chste Fehlermeldung suchen
  599.     else {
  600.      if($name != 'main')
  601.       $cfg['error']['main'][] = $val;
  602.      return (substr($val,0,2) != '1:') ? preg_replace('/^\d+:/','',$val) : false;// Nur Fehlermeldung ohne Error-Code ausgeben
  603.     }
  604.   }
  605.  return ($msg and $name == 'main') ? preg_replace('/^\d+:/','',$msg) : false;   // Ohne Funktionsname: Fehler ausgeben oder fehlschlag
  606. }
  607. function phperr($no,$str,$file,$line) {         // PHP-Fehler Debuggen
  608.  foreach(preg_split("/\s+/","ERROR WARNING PARSE NOTICE CORE_ERROR CORE_WARNING COMPILE_ERROR COMPILE_WARNING
  609.     USER_ERROR USER_WARNING USER_NOTICE STRICT RECOVERABLE_ERROR DEPRECATED USER_DEPRECATED UNKNOWN") as $b => $c)
  610.   if($no == 1 << $b)
  611.    break;
  612.  $a = "$str on line $line";
  613.  $b = &$GLOBALS["cfg"]["error"][$c][$file];
  614. //  $b["backtrace"][] = debug_backtrace();
  615.  if(!isset($a,$b) or array_search($a,$b) === false)
  616.   $b[] = $a;
  617.  return false;
  618. }
  619. function makedir($dir,$mode=1) {            // Erstellt ein Verzeichnis und wechselt dorthin
  620.  if(!$dir or ifset($dir,$GLOBALS['cfg']['ptar']))   // Self-Dir und Archive nicht bearbeiten
  621.   return true;
  622.  $dir = preg_replace('/[\\\\\/]+$/','',$dir);       // Abschlussshlash entfernen
  623.  if(strpos($dir,'%') !== false)             // strftime aufl�sen (Problematische Zeichen werden umgewandelt)
  624.   $dir = @strftime($dir);
  625.  if(preg_match('/^(\w:)?(.*)$/',$dir,$var))     // Windows Verzeichnis Pr�fen
  626.   $dir = $var[1].preg_replace('/[<:*|?">]+/','-',$var[2]);
  627.  if(!file_exists($dir)) {               // Neues Verzeichniss erstellen
  628.   if($mode)                     // Debug-Meldung unterdr�cken
  629.    dbug("Erstelle Ordner $dir");
  630.   $dirs = preg_split('/[\\\\\/]/',$dir);        // Verzeichniskette erstellen
  631.   $val = '';
  632.   foreach($dirs as $var) {
  633.    $val .= $var;
  634.    if($val and !file_exists($val))
  635.     mkdir($val);
  636.    $val .= '/';
  637.   }
  638.  }
  639.  if($mode and is_dir($dir)) {               // Aktuelles-Dir setzen
  640.   dbug("Wechsle zu Ordner $dir");
  641.   chdir($dir);
  642.  }
  643.  return is_dir($dir) ? $dir : false;
  644. }
  645. function mytouch($mode=false) {             // Ermitteln ob fb_Tools wieder nach Updates suchen soll
  646.  global $cfg,$script;
  647.  $rt = false;
  648.  if(is_string($mode)) {                 // Pr�fen, ob eine Datei geschrieben werden kann
  649.   $file = $mode;
  650.   if(file_exists($file)) {              // Test mit einer Datei, die schon da ist
  651.    $new = preg_replace('/(?=\.\w+$)|$/','_test',$file);
  652.    if(rename($file,$new)) {
  653.     if(file_contents($file,$file) and unlink($file))
  654.      $rt = true;
  655.     rename($new,$file);
  656.    }
  657.   }
  658.   elseif(file_contents($file,$file) and unlink($file))  // Einfacher Schreibtest
  659.    $rt = true;
  660.  }
  661.  else {
  662.   $dbg = ($cfg['upda'] < 0) ? 0 : 9;            // Debug-Modus festlegen
  663.   $time = time();                   // Aktuelle Uhrzeit
  664.   $name = "/$cfg[touch]-$cfg[cu]";          // Touch-Dateinamen aus der Konfig holen
  665.   $temp = (function_exists('sys_get_temp_dir')) ? sys_get_temp_dir() : (($var = getenv('TEMP')) ? $var : "/tmp");
  666.   $array = array_unique(array_merge(array_reverse(array_slice($cfg['fbta'],2)),array_reverse(array_slice($cfg['fbtl'],2)),array_slice($cfg['fbta'],1,1),
  667.     array_slice($cfg['fbtl'],1,1),array($script,"$cfg[dir]/$cfg[usrcfg]","$cfg[home]/$cfg[usrcfg]",$cfg['dir'],$cfg['home'],".",$temp)));
  668.   # dbug($array,$dbg);
  669.   if($mode) {                       // Datum setzen
  670.    foreach($array as $file)             // Verschiedene Speicherorte probieren
  671.     if(file_exists($file = realpath($file)) and (is_file($file) and @touch($file,$time) or is_dir($file) and @file_contents($file .= $name,"$time") and file_exists($file)) and filemtime($file) == $time) {
  672.      dbug("Touch-Datei: '$file' erfolgreich auf '".date('r',$time)."' gesetzt",$dbg);
  673.      return true;
  674.     }
  675.   }
  676.   elseif($cfg['upda'] > 0) {                // Datum abfragen
  677.    $max = filemtime($script);               // Das Script selber
  678.    array_push($array,$cfg['dir'],$cfg['home']);     // Touch-Datei
  679.    if($cfg['usrcfg'])                   // Globale/Lokale Konfig-Datei
  680.     array_unshift($array,"$cfg[dir]/$cfg[usrcfg]","$cfg[home]/$cfg[usrcfg]",$cfg['usrcfg'],"$cfg[dir]/.$cfg[usrcfg]","$cfg[home]/.$cfg[usrcfg]",".$cfg[usrcfg]");
  681.    if(ifset($cfg['loadcfg']))               // Geladene Konfig-Datei
  682.     array_merge((array)explode(',',$cfg['loadcfg']),$array);
  683.    array_push($array,"$temp");
  684.    $dir = array();                  // Pfade auf echte Pfade reduzieren
  685.    foreach($array as $file)
  686.     if($var = realpath($file))
  687.      $dir[$var] = 1;
  688.    $array = array_keys($dir);
  689.    foreach($array as $var)
  690.     if($var and file_exists($var) and (is_dir($var) and $files = glob(realpath($var)."/$cfg[touch]-*") or is_file($var) and $files = array($var)))
  691.      foreach($files as $file) {
  692.       $max = max($max,filemtime($file));        // Das neuste Datum sichern
  693.       dbug("Touch-Datei gefunden: $file",$dbg);
  694.      }
  695.    dbug("Letztes Touch-Datum: ".date('r',$max),$dbg);
  696.    $rt =  $time - $max > $cfg['upda'];          // Vergleichen
  697.   }
  698.  }
  699.  return $rt;                        // ALLES ist fehlgeschlagen
  700. }
  701. function otpauth($key,$rep=1,$time=0,$digit=6,$sec=30) {// OTP-Token Generieren f�r Zweite-Faktor-Authentifizierung
  702.  dbug("OATH-TOTP-Secret: $key",9,2);
  703.  $otp = array();
  704.  if(function_exists('hash_hmac') or cfgdecrypt(0,'hashtool')) {
  705.   $time = floor(($time ? $time : time()) / $sec);                   // Zeit auf $sec Sekunden runden
  706.   while($rep--) {
  707.    $hash = hash_hmac('sha1',str_pad(pack('N*',$time),8,"\0",STR_PAD_LEFT),unBase(strtoupper($key),'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'),true); // Hash aus Zeit und Secret berechnen
  708.    $hash = unpack('N',substr($hash,ord(substr($hash,-1)) & 15, 4));         // Hash auf 32 Bits reduzieren
  709.    $otp[$time++*$sec] = str_pad(($hash[1] & (1 << 31) - 1) % 1e6,$digit,0,STR_PAD_LEFT);// fertigen Code ausgeben
  710.   }
  711.  }
  712.  else
  713.   return errmsg("hash_hmac steht nicht zur verf�gung",__FUNCTION__);
  714.  dbug(" -> Token: ".implode(", ",$otp),9);
  715.  return (count($otp) == 1) ? reset($otp) : $otp;
  716. }
  717. function xml2array($xml,$attr="_attribute") {       // Konvertiert eine XML-Datei in ein Array
  718.  if(preg_match_all('/<([\w:.-]+)([^\/>]*)(?:\/>|>\s*((?:[^<]|<(?!\/?\1>)|(?R))*)\s*<\/\1>)/x',$xml,$val)) {
  719.   $xml = array();
  720.   foreach($val[1] as $key => $var) {
  721.    $sub = call_user_func(__FUNCTION__,$val[3][$key],$attr);// Untertag einlesen
  722.    if($val[2][$key] and preg_match_all('/([\w:.-]+)="((?:[^"]+|\\\\")*)"/',$val[2][$key],$m))
  723.     foreach($m[1] as $k => $v) {            // Attribute einlesen
  724.      if(is_string($sub))
  725.       $sub = $sub ? array($sub) : array();
  726.      if($attr)
  727.       $sub[$attr][$v] = $m[2][$k];
  728.      else
  729.       $sub[$v] = $m[2][$k];
  730.     }
  731.    if(isset($xml[$var])) {              // Tag schon vorhanden
  732.     if(!isset($xml[$var][0]) or !is_array($xml[$var]))  // Noch nicht Nummeriert?
  733.      $xml[$var] = array($xml[$var]);            // Eintr�ge in Nummer 0 verschieben
  734.     elseif(isset($xml[$var][0]) and !is_array($xml[$var][0]) and isset($xml[$var][$attr])) {
  735.      $xml[$var][0] = array($xml[$var][0],$attr => $xml[$var][$attr]);
  736.      unset($xml[$var][$attr]);
  737.     }
  738.     $xml[$var][] = $sub;                // Tag hinten dran h�ngen
  739.    }
  740.    else
  741.     $xml[$var] = $sub;                  // Tag normal speichern
  742.   }
  743.  }
  744.  return $xml;
  745. }
  746. function tar2array($file,$preg=false) {         // Liest ein Tar-Archiv vom File als Array ein
  747.  global $cfg;
  748.  if(file_exists($file) and preg_match($cfg['ptar'],$file,$var) and $func = ($cfg['bzip'] and ifset($var[3])) ? array('bzopen','bzread','bzclose')
  749.     : array($cfg['zlib']['open'],$cfg['zlib']['read'],$cfg['zlib']['close']) and $fp = call_user_func($func[0],$file,'r')) {
  750.   dbug("Entpacke Tar-Archiv aus Datei",9);
  751.   $tar = array();
  752.   while($meta = call_user_func($func[1],$fp,512) and preg_match('/^[^\0]+/',substr($meta,0,100),$name)) {
  753.    $data = substr_replace($meta,"        ",148,8);
  754.    for($crc=$a=0; $a < 512; $crc += ord($data[$a++]));
  755.    if($crc != octdec(substr($meta,148,6)))
  756.     return errmsg("16:Defektes Tar-Archiv",__FUNCTION__);
  757.    if($size = octdec(substr($meta,124,11)))
  758.     for($data = "", $a = $size + 512 - $size % 512; $a and ($var = call_user_func($func[1],$fp,$a)) !== false; $a -= strlen($var))
  759.      $data .= $var;
  760.    if(!$meta[156] and (!$preg or preg_match($preg,$name[0])))
  761.     $tar[$name[0]] = substr($data,0,$size);
  762.   }
  763.   call_user_func($func[2],$fp);
  764.   dbug($tar,9,'8,tar2array-#');
  765.   return $tar;
  766.  }
  767.  return errmsg("8:TAR-Archiv nicht gefunden oder l��t sich nicht �ffnen",__FUNCTION__);
  768. }
  769. function datatar2array($tar,$preg=false) {      // Parst aus einer Variable ein Tar-Archiv mit Meta-Daten als Array
  770.  dbug("Entpacke Tar-Archiv aus Variable",9);
  771.  if(preg_match_all('/(\D+)(\d+)/',"name100mode8UID8GID8SIZE12MTIME12CHKSUM8TYPEFLAG1linkname100magic6VERSION2uname32gname32devmajor8devminor8prefix155",$array))
  772.   $array = array_combine($array[1],$array[2]);
  773.  $out = array();
  774.  $pos = 0;
  775.  while($pos < strlen($tar) and $tar[$pos] != "\0") {
  776.   $meta = array();
  777.   $data = substr_replace(substr($tar,$pos,512),"        ",148,8);// Buffer ohne Checksumme vorbereiten
  778.   for($crc=$a=0; $a < 512; $crc += ord($data[$a++]));       // Checksumme berechnen
  779.   if($crc != octdec(substr($tar,$pos + 148,6)))
  780.    return errmsg("16:Defektes Tar-Archiv",__FUNCTION__);
  781.   $a = $pos;
  782.   foreach($array as $key => $var) {
  783.    if($data = preg_replace('/\0+$/','',substr($tar,$a,$var)))
  784.     $meta[strtolower($key)] = (strtoupper($key) == $key and preg_match('/^[0-7]+$/',$data)) ? octdec($data) : $data;
  785.    $a += $var;
  786.   }
  787.   $meta['data'] = substr($tar,$pos + 512,$meta['size']);
  788.   if($size = $meta['size'])
  789.    $pos += $size + 512 - $size % 512;
  790.   $pos += 512;
  791.   if(!ifset($meta['typeflag']) and (!$preg or preg_match($preg,$meta['name'])))
  792.    $out[$meta['name']] = $meta;
  793.  }
  794.  return $out;
  795. }
  796. function data2tar($name,$data='',$time=0) {     // Erstellt ein Tar-Header
  797.  $data = str_pad($name,100,chr(0))."0100777".chr(0).str_repeat(str_repeat("0",7).chr(0),2).str_pad(decoct(strlen($data)),11,"0",STR_PAD_LEFT).chr(0)
  798.     .str_pad(decoct($time),11,"0",STR_PAD_LEFT).chr(0)."        0".str_repeat(chr(0),100)."ustar".chr(0)."00".str_repeat(chr(0),247)
  799.     .$data.str_repeat(chr(0),(512 - strlen($data) % 512) % 512);
  800.  for($a=$b=0; $a<512; $a++)
  801.   $b += ord($data[$a]);
  802.  return substr_replace($data,str_pad(decoct($b),6,"0",STR_PAD_LEFT).chr(0)." ",148,8);
  803. }
  804. function zip2array($data,$pass=array(),$zip=array(),$x=0) {// Liest ein ZIP-Archiv auf einer Variable als Array ein
  805.  global $cfg;
  806.  if(is_int($pass)) {                // Unterfunktionen f�r zip2array
  807.   if($pass >=0) {               // le2int (str,pos,len,raw)
  808.    $data = strrev(substr($data,intval($pass),$zip ? intval($zip) : 2));
  809.    $zip = $x ? $data : hexdec(bin2hex($data));
  810.   }
  811.   elseif($pass >= -2) {             // zipcrypto (str,-[12],array(zipcrc))
  812.    $nhash = "";
  813.    for($a = 0; $a < strlen($data); $a++) {
  814.     if($pass == -2)
  815.      $nhash .= chr(ord($data[$a]) ^ call_user_func(__FUNCTION__,$b = $zip[2] | 2,-5,$b ^ 1) >> 8 & 255);
  816.     $zip[0] = call_user_func(__FUNCTION__,call_user_func(__FUNCTION__,$nhash ? $nhash[$a] : $data[$a],-3,$zip[0]),-4,0);
  817.     $zip[1] = call_user_func(__FUNCTION__,call_user_func(__FUNCTION__,$zip[1] + ($zip[0] & 255),-5,0x8088405) + 1,-4,0);
  818.     $zip[2] = call_user_func(__FUNCTION__,call_user_func(__FUNCTION__,chr(call_user_func(__FUNCTION__,$zip[1],-4,24)),-3,$zip[2]),-4,0);
  819.    }
  820.    if($pass == -2)
  821.    $zip = $nhash;
  822.   }
  823.   elseif($pass == -3) {             // crc32 (str,-3,crc)
  824.    if(!isset($cfg['czip']))
  825.     for($a=0; $a < 256; $cfg['czip'][$a++] = $c)
  826.      for($b=0,$c=$a; $b < 8; $b++)
  827.       $c = ($c>>1) & 0x7FFFFFFF ^ ($c & 1) * 0xEDB88320;
  828.    for($zip = intval($zip), $a=0; $a < strlen($data); $a++)
  829.     $zip = $cfg['czip'][($zip ^ ord($data[$a])) & 255] ^ ( $zip >> 8 ) & 0xFFFFFF;
  830.    # $zip = substr("0000000".dechex($zip < 0 ? ~$zip : 0xFFFFFFFF + ~ --$zip),-8);
  831.  }
  832.   elseif($pass == -4) {             // urShift (a,-4,b)
  833.    if($zip >= 32 or $zip < -32)
  834.     $zip %= 32;
  835.    elseif($zip < 0)
  836.     $zip += 32;
  837.    $zip = !$zip ? ($data>>1 & 0x7fffffff) * 2 + ($data>>$zip & 1) : (($data < 0) ? ($data >> 1 & 0x7fffffff | 0x40000000) >> $zip - 1 : $data >> $zip);
  838.   }
  839.   elseif($pass == -5)               // imul (a,-5,b)
  840.    $zip = call_user_func(__FUNCTION__,($data >> 16 & 65535) * ($c = $zip & 65535) + ($data &= 65535) * ($zip >> 16 & 65535) << 16,-4,0) + $data * $c;
  841.  }
  842.  else {                     // data2zip
  843.   if(!$pass and ifset($cfg['zp']))
  844.    $pass = $cfg['zp'];
  845.   if($pass and (!($aes = cfgdecrypt(0,'aes')) or !preg_array('/^(openssl|mcrypt)$/i',$aes,1) or !(function_exists('hash_pbkdf2') or cfgdecrypt(0,'hashtool'))
  846.     or !(function_exists('hash_algos') or !cfgdecrypt(0,'mhash') or !cfgdecrypt(0,'sha256'))))              // Ist Verschl�sslung m�glich?
  847.    return errmsg("Keine AES-CTR Funktion gefunden",__FUNCTION__);
  848.   for($pos = $d = 0; $pos < strlen($data)
  849.     and preg_match('/^PK(?:(\x03\x04)|(\x01\x02)|\x05(?:(\x05)|(\x06))|\x06(?:(\x06)|(\x07)|(\x08))|(\x07\x08))()/',substr($data,$pos),$c); $pos += $d) {
  850.    if($c[1] and call_user_func(__FUNCTION__,$data,$pos + 4,1) < 52) {                               // \x03\x04 (Local file header) Bis Version 5.1
  851.     $g = (call_user_func(__FUNCTION__,$data,$pos + 6) & 8 and preg_match('/PK\x07\x08.{12}PK[\x01-\x09]{2}/s',substr($data,$pos),$h)) ? $h : 0; // Stream-ZIP Ersatz-Header suchen
  852.     $i = substr($data,$pos + 30,$d = $h = call_user_func(__FUNCTION__,$data,$pos + 26));                    // Dateiname
  853.     $j = strtotime((1980 + (($e = call_user_func(__FUNCTION__,$data,$pos + 10,4))>>25))."-".($e>>21 & 15)."-".($e>>16 & 31)." ".($e>>11 & 31).":".($e>>5 & 63).":".(($e & 31) * 2));    // Datum
  854.     $e = substr($data,$pos + 30 + ($d += call_user_func(__FUNCTION__,$data,$pos + 28)),($f = $g ? call_user_func(__FUNCTION__,$g[0],8,4) : call_user_func(__FUNCTION__,$data,$pos + 18,4)));    // Gepackte Daten holen (f = l�nge)
  855.     $d += 30 + $f;                                                      // Offset um Header mit Daten zu �berspringen
  856.     if(!(call_user_func(__FUNCTION__,$data,$pos + 6) & ~2062)   and (!$e or ($e = (($f = call_user_func(__FUNCTION__,$data,$pos + 8)) == 8) ? gzinflate($e)// Flags abfragen
  857.     : (($f == 12 and $cfg['bzip']) ? bzdecompress($e) : (!$f ? $e : ""))))                          // UnZip
  858.     and strlen($e) == ($g ? call_user_func(__FUNCTION__,$g[0],12,4) : call_user_func(__FUNCTION__,$data,$pos + 22,4))   // Stimmt die L�nge?
  859.     and (hash('crc32b',$e,1) == ($g ? call_user_func(__FUNCTION__,$g[0],4,4,1) : call_user_func(__FUNCTION__,$data,$pos + 14,4,1)))) { // Entpackte Daten korrekt?
  860.      if(substr($i,-1) != "/")
  861.       $zip[$i] = $x ? $e : array('data' => $e, 'mtime' => $j);                              // Entpackte Daten & Datum sichern
  862.      $i = 0;
  863.     }
  864.     else if(!$g and !(($g = call_user_func(__FUNCTION__,$data,$pos + 6)) & ~2055) and $g % 2 and call_user_func(__FUNCTION__,$data,$pos + 8) == 99 and substr($data,$g = $pos + 30 + $h,2) == "\x01\x99"        // AES-ZIP
  865.     and (($f = call_user_func(__FUNCTION__,$data,$g + 4)) == 2 and !call_user_func(__FUNCTION__,$data,$pos + 14,4) or $f == 1) and $f = call_user_func(__FUNCTION__,$data,$g + 8,1) and $f = ++$f * 64) {       // f: AES-Bits / g: offset extra-header
  866.      if(!$pass)
  867.       return errmsg("Archiv ben�tigt ein Kennwort (-zp:'password')",__FUNCTION__);
  868.      foreach($pass as $pw)                                              // Password-manager befragen
  869.       if(substr(($c = hash_pbkdf2("sha1",$pw,substr($e,0,$f >> 4),1e3,$f / 4 + 16,1)),$f / 4,2) == substr($e,$f >> 4,2))// Kennwort-Hash erstellen und testen
  870.        break;
  871.       else
  872.        $pw = false;
  873.      if($c and $pw and substr($c,$f / 4,2) == substr($e,$f >> 4,2) and substr(hash_hmac("sha1",$h = substr($e,$f / 16 + 2, strlen($e) - ($f / 16 + 2) - 10),substr($c,$f / 8, $f / 8),1),0,10) == substr($e,-10)) {
  874.       for($e = ""; strlen($e) < strlen($h); ) {
  875.        $b = array(substr($h,strlen($e),16),substr($c,0,$f/8),str_pad(pack('V',(strlen($e) >> 4) + 1),16,chr(0)));
  876.        if(isset($aes['openssl']))
  877.         $e .= openssl_decrypt($b[0],"aes-$f-ctr",$b[1],OPENSSL_RAW_DATA,$b[2]);
  878.        elseif(isset($aes['mcrypt']))                                        // Extension: MCrypt
  879.         $e .= mcrypt_decrypt(MCRYPT_RIJNDAEL_128,$b[1],$b[0],'ctr',$b[2]);
  880.        else
  881.         break;
  882.       }
  883.       if(($e = (($c = call_user_func(__FUNCTION__,$data,$g + 9)) == 8) ? gzinflate($e) : (($c == 12 and $cfg['bzip']) ? bzdecompress($e) : (!$c ? $e : "")) or $e === "")// UnZip
  884.     and strlen($e) == call_user_func(__FUNCTION__,$data,$pos + 22,4) and (($c = call_user_func(__FUNCTION__,$data,$g + 4)) == 1 and call_user_func(__FUNCTION__,$data,$pos + 14,4,1) == hash('crc32b',$e,1) or $c == 2)) {  // L�nge & Optional CRC32 �berpr�fen
  885.        if(substr($i,-1) != "/")                                         // Nur Dateien eintragen
  886.         $zip[$i] = $x ? $e : array('data' => $e, 'mtime' => $j, 'pass' => $pw, 'bits' => $f);           // Entpackte Daten & Datum sichern
  887.        $i = 0;
  888.       }
  889.       else
  890.        return errmsg("Entschl�sselung ist fehlgeschlagen",__FUNCTION__);
  891.      }
  892.      else
  893.       return errmsg("Das Kennwort ist falsch",__FUNCTION__);
  894.     }
  895.     else if(($g = call_user_func(__FUNCTION__,$data,$pos + 6)) % 2 and !($g & ~2063) and call_user_func(__FUNCTION__,$data,$pos + 14,4)) { // Crypto-ZIP
  896.      if(!$pass)
  897.       return errmsg("Archiv ben�tigt ein Kennwort (-zp:'password')",__FUNCTION__);
  898.      foreach($pass as $pw) {// Password-manager befragen
  899.       $f = call_user_func(__FUNCTION__,$pw,-1,array(0x12345678,0x23456789,0x34567890));
  900.       if(substr($data,$pos + ($g & 8 ? 11 : 17),1) == substr($f = call_user_func(__FUNCTION__,$e,-2,$f),11,1))  // Kennwort-Hash erstellen und testen
  901.        break;
  902.       else
  903.        return errmsg("Das Kennwort ist falsch",__FUNCTION__);
  904.      }
  905.      if($f and (!($e = substr($f,12)) or ($e = ($f = call_user_func(__FUNCTION__,$data,$pos + 8)) == 8 ? gzinflate($e) : (($f == 12) ? bzdecompress($e) : (!$f ? $e : "")))// UnZip
  906.     and strlen($e) == call_user_func(__FUNCTION__,$data,$pos + 22,4) and hash('crc32b',$e,1) == call_user_func(__FUNCTION__,$data,$pos + 14,4,1))) { // L�nge & CRC32 �berpr�fen
  907.        if(substr($i,-1) != "/")                                         // Nur Dateien eintragen
  908.         $zip[$i] = $x ? $e : array('data' => $e, 'mtime' => $j, 'pass' => $pw, 'bits' => $f);           // Entpackte Daten & Datum sichern
  909.        $i = 0;
  910.       }
  911.     }
  912.     if($i)
  913.      $data .= 0;                                                // Fehler erkennen (Sourcel�nge ver�ndern)
  914.    }
  915.    else                                                     // Alle Header werden �bersprungen (Ignoriert)
  916.     $d = $c[2] ? 46 + call_user_func(__FUNCTION__,$data,$pos + 28) + call_user_func(__FUNCTION__,$data,$pos + 30) + call_user_func(__FUNCTION__,$data,$pos + 32)// \x01\x02 (Central directory file header)
  917.           : ($c[3] ? call_user_func(__FUNCTION__,$data,$pos + 4) + 6                    // \x05\x05 (Digital signature)
  918.               : ($c[4] ? call_user_func(__FUNCTION__,$data,$pos + 20) + 22              // \x05\x06 (End of central directory record)
  919.                   : ($c[5] ? call_user_func(__FUNCTION__,$data,$pos + 4,8) + 12         // \x06\x06 (Zip64 end of central directory record)
  920.                       : ($c[6] ? 20                             // \x06\x07 (Zip64 end of central directory locator)
  921.                           : ($c[7] ? call_user_func(__FUNCTION__,$data,$pos + 4,4) + 8  // \x06\x08 (Archive extra data record)
  922.                               : ($c[8] ? 16 : 1))))));                  // \x07\x08 (Stream-Header: crc32, df-len, if-len)
  923.   }
  924. #  dbug($zip,9,'8,zip2array-#');
  925.  if($pos != strlen($data))
  926.    $zip = errmsg("Archiv ist besch�digt oder wird nicht unterst�tzt",__FUNCTION__);
  927.  }
  928.  return $zip;
  929. }
  930. function data2zip($files,$pass=false,$time=false) { // Erstellt aus ein Array ein ZIP-Archiv
  931.  global $cfg;
  932.  if(!is_array($files))
  933.   return errmsg("Unbekannte Parameter",__FUNCTION__);
  934.  if(!$pass and ifset($cfg['zp']))   // Password von Optionen �bernehmen
  935.   $pass = $cfg['zp'] ? reset($cfg['zp']) : false;
  936.  if($pass)              // Pr�fen ob Verschl�sselung �berhaupt m�glich ist
  937.   if(!$aes = cfgdecrypt(0,'aes') or !preg_array('/^(openssl|mcrypt)$/i',$aes,1) or !(function_exists('hash_pbkdf2') or cfgdecrypt(0,'hashtool'))
  938.     or !(function_exists('hash_algos') or !cfgdecrypt(0,'mhash') or !cfgdecrypt(0,'sha256')) or !$cfg['zb'])    // Ist Verschl�sslung m�glich?
  939.    return errmsg("Keine m�glichkeit gefunden die AES-CTR Funktion auszuf�hren",__FUNCTION__);
  940.  $zip = $dir = "";          // Leeres Zip-Archiv
  941.  foreach($files as $file => $meta) {    // Array durchgehen
  942.   if(!is_array($meta))
  943.    $meta = array('data' => $meta);
  944.   $time = isset($meta['time']) ? $meta['time'] : ($time ? $time : time());
  945.   $m = "";
  946.   $i = strlen($meta['data']) ? ($cfg['bz'] ? bzcompress($meta['data'],$cfg['bz']) : ($cfg['gz'] ? gzdeflate($meta['data'],$cfg['gz']) : "")) : "";  // Deflate Data
  947.   if(!$i or strlen($i) > strlen($meta['data']))             // Store Data?
  948.    $i = $meta['data'];
  949.   if($pass) {                               // Verschl�sselung AES-AE2 (128/192/256)
  950.    $jk = function_exists("openssl_random_pseudo_bytes") ? openssl_random_pseudo_bytes($cfg['zb']/8) : sha1(mt_rand().time());   // key
  951.    $js = substr(hash_hmac('sha256',$file.time().serialize($meta).$pass,$jk,1),0,$cfg['zb']/16);
  952.    $jh = hash_pbkdf2("sha1",$pass,$js,1e3,$cfg['zb']/4+16,1);       // (48,64,80)
  953.    for($k = $m; strlen($k) < strlen($i);) {
  954.     $b = array( substr($i,strlen($k),16),               // Data
  955.         substr($jh,0,$cfg['zb'] / 8),               // Key
  956.         str_pad(pack('V',(strlen($k) >> 4) + 1),16,"\0"));  // Counter
  957.     if(isset($aes['openssl']))
  958.      $k .= openssl_encrypt($b[0],"aes-$cfg[zb]-ctr",$b[1],OPENSSL_RAW_DATA,$b[2]);
  959.     elseif(isset($aes['mcrypt']) and $x = mcrypt_module_open(MCRYPT_RIJNDAEL_128,'','ctr','')) { // Extension: MCrypt
  960.      mcrypt_generic_init($x, $b[1], $b[2]);             // https://github.com/beyonderyue/aes-ctr-php
  961.      $k .= mcrypt_generic($x, $b[0]);
  962.      mcrypt_generic_deinit($x);
  963.      mcrypt_module_close($x);
  964.     }
  965.     else
  966.      break;
  967.    }
  968.    $m = "\1\x99\7\0\2\0AE".chr($cfg['zb']/64-1).chr((strlen($k) == strlen($meta['data'])) ? 0 : ($cfg['bz'] ? 12 : 8))."\0";    // Extra-Data Header
  969.    $i = $js.substr($jh,$cfg['zb'] / 4,2).$k.substr(hash_hmac("sha1",$k,substr($jh,$cfg['zb'] / 8,$cfg['zb'] / 8),1),0,10);// Salt + Chk + Cipher + Hash
  970.   }
  971.   $k = (($k = utf8($file)) != $file) ? $k : $file;
  972.   $j = ($m ? "\x33" : (($i != $meta['data']) ? chr($cfg['bz'] ? 46 : 20) : "\n"))."\0"
  973.     .pack("v",(($k != $file) ? 2048 : 0) | ($m ? 1 : 0)).($m ? "c" : chr(($i != $meta['data']) ? ($cfg['bz'] ? 12 : 8) : 0))."\0"
  974.     .pack('v*',intval(date('G',$time)) * (1<<11) + intval(date('i',$time)) * (1<<5) + (intval(date('s',$time)) >>1),// Time
  975.     (intval(date('Y',$time)) - 1980) * (1<<9) + intval(date('n',$time)) * (1<<5) + intval(date('j',$time)))     // Date
  976.     .strrev(!$m ? hash("crc32b",$meta['data'],1) : pack("V",0))                         // CRC32
  977.     .pack('V*',strlen($i),strlen($meta['data'])).pack('v*',strlen($k),strlen($m));
  978.   $dir .= "PK\1\2\0\0$j".str_repeat("\0",10).pack('V',strlen($zip)).$k.$m;  // Central directory file header
  979.   $zip .= "PK\3\4$j$k$m$i";                         // Local file header
  980.  }
  981.  return $zip.$dir."PK\5\6\0\0\0\0".str_repeat(pack('v',count($files)),2).pack('V*',strlen($dir),strlen($zip))."\0\0";
  982. }
  983. function json2array($str,$o=array(),$s=array(),$c=0) {  // JSON-Parser mit UTF8-Decoder
  984.  global $cfg;
  985.  if(is_array($str)) // Decode UTF8
  986.   $o = $str[1] ? chr(strpos("01234567btnvfr",$str[1])) : utf8(array($str[4] ? (hexdec($str[4]) & 1023) * 1024 + (hexdec($str[5]) & 1023) + 65536 : hexdec("$str[2]$str[3]$str[6]")));
  987.  elseif(function_exists("json_decode") and !$o and $v = json_decode($str,true,$cfg['jsdp']))    // PHP-Funktion nutzen
  988.   $o = $v;
  989.  else           // Parse JSON
  990.   while(preg_match('/^\s*(?:(?:(["\']?)(?![-.\d])([^!-,\/;-@\[-^\]`\{|\}\s]*)(?<!\\\\)\1\s*:)?\s*(?:([\{\[])|(true|false|null)|([+-]?\d+(?:e[+-]?\d{1,2})?(\.\d+(?:e[+-]?\d{1,2})?)?)|(["\'])(.*?)(?<!\\\\)\7|(\/.+?(?<!\\\\)\/\w*))|([\]\}])|(?!$)\s*(?:\/\/.*|\#.*|(?s:\/\*.*?\*\/))?)\s*(,?)/ix',substr($str,$c),$m) and $m[0] != '') {
  991.    $c += strlen($m[0]);
  992.    $v = array(($m[2] != "") ? $m[2] : false);
  993.    if($m[3]) {
  994.     if(count($s) > $cfg['jsdp'])
  995.      return errmsg("16:Arrays oder Objekte zu tief verschachtelt ($cfg[jsdp])",__FUNCTION__);
  996.     $s[] = $k = array($o,$s ? $v[0]: null,$m[3]);
  997.     $o = array();
  998.     $v = false;
  999.    }
  1000.    elseif($m[10]) {
  1001.     if(!($k = is_array($s) ? end($s) : false) or $k[2] != '[' and $m[10] == ']' or $k[2] != '{' and $m[10] == '}')
  1002.      return errmsg("16:Array oder Objekt falsch geschlossen",__FUNCTION__);
  1003.     if($k[1])
  1004.      $k[0][$k[1]] = $o;
  1005.     elseif(is_null($k[1]))
  1006.      $k[0] += $o;
  1007.     else
  1008.      $k[0][] = $o;
  1009.     $o = $k[0];
  1010.     array_pop($s);
  1011.     $v = false;
  1012.    }
  1013.    elseif($x = strtolower($m[4]))
  1014.     $v[] = ($x == 'null') ? null : $x == 'true';
  1015.    elseif($m[5] != '')
  1016.     $v[] = $m[6] ? floatval($m[5].$m[6]) : intval($m[5]);
  1017.    elseif($m[7])
  1018.     $v[] = preg_replace_callback('/\\\\(?:([0-7btnvfr])|(x[\da-f]{2})|u\{([\da-f]+)\}|(?:u(d[89ab][\da-f]{2})\\\\u(d[cdef][\da-f]{2})|u([\da-f]{4})))(\b|\B)/i',__FUNCTION__,preg_replace("/\\\\($m[7])/",'$1',$m[8]));
  1019.    elseif($m[9])
  1020.     $v[] = $m[9];
  1021.    else
  1022.     $v = false;
  1023.    if($v)
  1024.     if($v[0])
  1025.      $o[$v[0]] = $v[1];
  1026.     elseif($k[2] == '[')
  1027.      $o[] = $v[1];
  1028.   }
  1029.  return $o;
  1030. }
  1031. function textTable($table,$cols=0,$col="|",$row="\n",$tab=" ",$sp=" ") { // Text als Text-Tabelle konvertieren
  1032.  if($cols == -1)        // Creole-Aufruf
  1033.   return preg_replace_callback('/\{\{\{(?:tt|77)((?:,[^,\}]*)*)\}(.*?)\}\}/s',__FUNCTION__,$table);
  1034.  elseif(is_array($table)) { // Creole-Funktion
  1035.   if($var = ifset($table[1],'/,([^,]*)/a')) {
  1036.    array_unshift($var[1],$table[2]);
  1037.    $opts = $var[1];
  1038.    if(ifset($opts[4],'/;/'))
  1039.     $opts[4] = explode(';',$opts[4]);
  1040.    if(ifset($opts[5],'/;/'))
  1041.     $opts[5] = explode(';',$opts[5]);
  1042.   }
  1043.   else
  1044.    $opts = array($table[2]);
  1045.   return call_user_func_array(__FUNCTION__,$opts);
  1046.  }
  1047.  elseif(!$cols and $cols = $GLOBALS['cfg']['wrap'])
  1048.   $cols -= 2;
  1049.  $esc = array();
  1050.  $pos = 0;
  1051.  $p = "[\x80-\xbf]";
  1052.  while(preg_match("/\x7f|[\xc0-\xdf]$p|[\xe0-\xef]$p{2}|[\xf0-\xf7]$p{3}|[\xf8-\xfb]$p{4}|[\xfc-\xfd]$p{5}|\xfe$p{6}
  1053.     |\\\\(u\{[\da-f]+\}|ud[89ab][\da-f]{2}\\\\ud[cdef][\da-f]{2}|u[\da-f]{4})|(&\#(\d+|x[\da-f]+);)/x",substr($table,$pos),$m,PREG_OFFSET_CAPTURE)) {
  1054.   $table = substr_replace($table,"\x7f",$pos + $m[0][1], strlen($m[0][0]));
  1055.   $esc[] = $m[0][0];
  1056.   $pos += $m[0][1] + 1;
  1057.  }
  1058.  $lines = explode($row,trim($table));
  1059.  $lens = $max = $min = $ali = $table = array();
  1060.  $col = array('/(?<!\\\\)'.preg_quote($col,'/').'/','/\\\\(?='.preg_quote($col,'/').')/');
  1061.  foreach($lines as $kl => $line) {
  1062.   $table[$kl] = preg_replace($col[1],'',preg_split($col[0],$line));
  1063.   foreach($table[$kl] as $kr => $rift)
  1064.    if(preg_match('/^(\s*)(.*?)(\s*)$/',$rift,$var)) {
  1065.     $table[$kl][$kr] = $var[2];
  1066.     $ali[$kl][$kr] = ($var[1] and $var[3]) ? STR_PAD_BOTH : (($var[1] and !$var[3]) ? STR_PAD_LEFT : STR_PAD_RIGHT);
  1067.     $max[$kr] = max((isset($max[$kr])) ? $max[$kr] : 0, strlen($var[2]));
  1068.    }
  1069.  }
  1070.  if($cols and array_sum($max) + count($max) -1 > $cols) {
  1071.   $cols = max($cols,count($max) * 2);
  1072.   foreach($table as $kl => $line)
  1073.    foreach($line as $kr => $rift)
  1074.     $min[$kr] = max((isset($min[$kr])) ? $min[$kr] : 0,max($lens[$kl][$kr] = array_map('strlen',explode((is_array($sp)) ? $sp[$kr] : $sp,$table[$kl][$kr]))));
  1075.   while(($cols and array_sum($max) + count($max) -1 > $cols) and array_sum($max) > array_sum($min)) {
  1076.    $mlen = array();
  1077.    foreach($lens as $kl => $line) {
  1078.     $var = count($line) -1;
  1079.     $key = array();
  1080.     foreach($line as $kr => $rift) {
  1081.      $var += array_sum($rift) + count($rift) -1;
  1082.      if(!$key or $key[1] < count($rift))
  1083.       $key = array($kr,count($rift));
  1084.     }
  1085.     if(!$mlen or $mlen[1] <= $var and $mlen[3] < $key)
  1086.      $mlen = array_merge(array($kl,$var),$key);
  1087.    }
  1088.    if($mlen)
  1089.     array_pop($lens[$mlen[0]][$mlen[2]]);
  1090.    else
  1091.     break;
  1092.    $max = $min;
  1093.    foreach($lens as $kl => $line)
  1094.     foreach($line as $kr => $rift)
  1095.      $max[$kr] = max((isset($max[$kr])) ? $max[$kr] : 0, array_sum($rift) + count($rift) -1);
  1096.   }
  1097.   while(array_sum($max) + count($max) -1 > $cols)
  1098.    $max[array_search(max($max),$max)]--;
  1099.  }
  1100.  $out = array();
  1101.  foreach($table as $tk => $line) {
  1102.   $wrap = 0;
  1103.   foreach($line as $key => $var) {
  1104.    $line[$key] = explode($row,wordwrap($var,$max[$key],$row,true));
  1105.    $wrap = max($wrap,count($line[$key]));
  1106.   }
  1107.   for($a=0; $a < $wrap; $a++) {
  1108.    $buf = "";
  1109.    foreach($line as $key => $var)
  1110.     $buf .= str_pad((isset($line[$key][$a])) ? $line[$key][$a] : "",$max[$key],(is_array($sp)) ? $sp[$key] : $sp,$ali[$tk][$key]).((is_array($tab)) ? $tab[$key] : $tab);
  1111.    $out[] = rtrim($buf);
  1112.   }
  1113.  }
  1114.  $table = implode($row,$out);
  1115.  $m = 0;
  1116.  while(($m = strpos($table,"\x7f",$m)) !== false) {
  1117.   $table = substr_replace($table,$esc[0],$m,1);
  1118.   $m += strlen(array_shift($esc));
  1119.  }
  1120.  return $table;
  1121. }
  1122. function request($method,$page='/',$body=0,$head=0,$host=0,$port=0,$sock=0,$user=0,$pass=0) { // HTTP-Request durchf�hren
  1123.  global $cfg;
  1124.  if(!$method) {                             // Unterfunktion: HTTP Auth zusammenstellen ($page,$arg,$auth)
  1125.   if(is_string($head) and preg_match('/^(\w+)\s+(.*)$/',$head,$m)) {    // Erste Anmeldung
  1126.    $head = array();
  1127.    $m[1] = strtolower($m[1]);
  1128.    if($m[1] == 'basic') {
  1129.     $head['username'] = $body['user'];
  1130.     $head['password'] = $body['pass'];
  1131.     $head[$m[1]] = "Basic ".base64_encode(implode(":",$head));      // Absolut unknackbar ;-)
  1132.     $cfg['auth'] = $head;
  1133.    }
  1134.    elseif($m[1] == 'digest' and preg_match_all('/(\w+)\s*=\s*(\\\\?["\']?)(.*?)\2(,\s*|\s*$)/',$m[2],$m)) {// HTTP Auth Digest
  1135.     dbug($m,4);
  1136.     $head = array_merge(array(
  1137.     'username' => $body['user'],
  1138.     'nc' => 0,
  1139.     'cnonce' => substr(hash('md5',time().rand()),16),
  1140.     ),array_combine($m[1],$m[3]));
  1141.    }
  1142.    if(isset($head['username']))
  1143.     dbug("HTTP Auth ".((isset($head['basic'])) ? "Basic" : "Digest")." f�r $head[username]",5);
  1144.   }
  1145.   if(is_array($head))
  1146.    if(isset($head['basic']))                        // HTTP Auth Basic
  1147.     $method = $head['basic'];
  1148.    elseif(isset($head['username'])) {                   // HTTP Auth Digest
  1149.     $head['nc'] = str_pad(intval($head['nc']) + 1,8,0,STR_PAD_LEFT);    // Z�hler erh�hen
  1150.     $head['uri'] = $page;                       // Aktuelle Seite
  1151.     $hash = (ifset($head['algorithm'])) ? strtolower(str_replace('-','',$head['algorithm'])) : 'md5';// Hash Methode festlegen
  1152.     if($head['response'] = hash($hash,hash($hash,"$head[username]:$head[realm]:$body[pass]")
  1153.     .":$head[nonce]:$head[nc]:$head[cnonce]:$head[qop]:".hash($hash,strtoupper(preg_replace('/-.*/','',$body['method'])).":$page"))) {
  1154.      $cfg['auth'] = $head;  // Werte sichern
  1155.      foreach($head as $key => $var)
  1156.       $head[$key] = "$key=\"$var\"";
  1157.      $method = "Digest ".implode(', ',$head);       // Anmeldedaten zusammenstellen
  1158.     }
  1159.    }
  1160.   return $method;
  1161.  }
  1162.  elseif(is_array($method))              // Parameter aus Array holen
  1163.   extract($method);
  1164.  elseif(is_string($method) and $val = ifset($method,    // Parameter aus String holen (GET-array)
  1165.     '/^(https?):(?:\[([^\[\s\]]+)\])?\/\/(?:([^@:\s]+):)?(?:([^@\s]+)@)?
  1166.     ((?:(?!-)[a-z\d-]+(?<!-)\.)+(?!-)[a-z\d-]+(?<!-)|0*(?:\d{1,2}|1\d{2}|2[0-4]\d|25[0-5])(?:\.0*(?:\d{1,2}|1\d{2}|2[0-4]\d|25[0-5])){3}
  1167.     |\[:?(?:[\da-f]{0,4}:){0,7}[\da-f]{0,4}\])(?::(\d{1,5}))?(\/[^\#?\s]*)?(?:\?([^\s]*))?(?:\#(.+?))?(\#?$)/ix')) {
  1168.   $arg = array();
  1169.   foreach(explode(',','sock,mode,user,pass,host,port,page,body,uipw') as $key => $var)
  1170.    if($var and ifset($val[$key+1]))
  1171.     $$var = $arg[$var] = ($var == 'host') ? preg_replace('/^\[|\]$/','',$val[$key+1]) : $val[$key+1];
  1172.   $method = (ifset($mode)) ? $mode : 'GET';
  1173.   if(!$port)                        // Port festlegen
  1174.    $port = $arg['port'] = ($sock == 'http') ? 80 : 443;
  1175.   if($val[10])
  1176.    return $arg;
  1177.  }
  1178.  foreach(explode(',','sock,host,port,user,pass') as $var)// Host, Port, user & pass setzen
  1179.   if(!$$var)
  1180.    $$var = $cfg[$var];
  1181.  if(!$head)                     // Head Initialisieren
  1182.   $head = $cfg['head'];
  1183.  if($mode = preg_match('/^(\w+)(?:-(.+))?/',$method,$var)) {
  1184.   $method = strtoupper($var[1]);
  1185.   $mode = (isset($var[2])) ? $var[2] : (($var[1] == strtolower($var[1])) ? 'array' : false);// Result-Modus festlegen
  1186.  }
  1187.  $arg = array_flip(explode(',','method,mode,sock,host,port,page,head,body,user,pass'));// Parameter sichern
  1188.  foreach($arg as $key => $var)
  1189.   $arg[$key] = $$key;
  1190.  $http = $sock;
  1191.  if($sock = ($sock == 'auto' and ($port == 80 or $port == 8080 or $port == 49000) or $sock == 'http') ? '' : ((ifset($sock,'/^(ssl|tls)$/')) ? "$sock://" : 'ssl://'))
  1192.   if(!$cfg['ssl'])
  1193.    if($var = cfgdecrypt(0,'openssl')) {
  1194.     $cfg['ssl'] = $var;
  1195.     dbug("OpenSSL nachgeladen: $var",9);
  1196.    }
  1197.    else
  1198.     return errmsg("8:OpenSSL nicht verf�gbar",__FUNCTION__);
  1199.  if($var = ifset($cfg['proxy'],'/^([\w.-]+):(\d+)$/')) {// Primitive Proxy-Umleitung
  1200.   if(!isset($cfg['http']))
  1201.    dbug("Benutze Proxy: $var[0]",9);
  1202.   $page = "http".($sock ? "s" : "")."://$host:$port$page";
  1203.   $head['host'] = $host; // .($sock ? ":$port" : "");
  1204.   $host = $var[1];
  1205.   $port = $var[2];
  1206.  }
  1207.  dbug("$sock$host:$port",5);
  1208.  if(!isset($cfg['fail']["$host:$port"]) and function_exists('stream_socket_client')
  1209.     and $fp = @stream_socket_client(($sock ? $sock : "tcp://")."$host:$port",$errnr,$errstr,$cfg['tout'],
  1210.     STREAM_CLIENT_CONNECT,stream_context_create((ifset($http,'/auto|https/i'))
  1211.     ? array('ssl' => array('verify_peer' => false, 'verify_peer_name' => false)) : array()))
  1212.     or $fp = @fsockopen($sock.$host,$port,$errnr,$errstr,$cfg['tout'])) {// Verbindung aufbauen
  1213.   if($cfg['tout'])
  1214.    stream_set_timeout($fp,$cfg['tout']);        // Timeout setzen
  1215. //  stream_set_blocking($fp,0);
  1216.   if($method == 'POST') {               // POST-Request vorbereiten
  1217.    if(is_array($body)) {                // Multipart-Post vorbereiten
  1218.     $row = "---".hash('md5',rand().time());
  1219.     foreach($body as $key => $var) {
  1220.      $val = array('','');
  1221.      if(is_array($var))                 // Unter-Header im Header
  1222.       foreach($var as $k => $v)
  1223.        if($k == '')                 // Content
  1224.         $var = $v;
  1225.        elseif($k == 'filename')             // Weitere Angaben im Header
  1226.         $val[0] .= "; $k=\"$v\"";
  1227.        else                     // Sub-Header
  1228.         $val[1] = "$k: $v\r\n";
  1229.      $body[$key] = "$row\r\nContent-Disposition: form-data; name=\"$key\"$val[0]\r\n$val[1]\r\n$var\r\n";
  1230.     }
  1231.     $body = implode('',$body)."$row--\r\n";
  1232.     $var = "multipart/form-data; boundary=$row";
  1233.    }
  1234.    else
  1235.     $var = 'application/x-www-form-urlencoded';     // Standard Post
  1236.    if(!isset($head['content-type']))
  1237.     $head['content-type'] = $var;
  1238.    if(!isset($head['content-length']))
  1239.     $head['content-length'] = strlen($body);
  1240.    $body = "\r\n$body";
  1241.   }
  1242.   elseif($method == 'GET' and $body) {          // GET-Request vorbereiten
  1243.    if(is_array($body)) {
  1244.     $val = array();
  1245.     foreach($body as $key => $var)
  1246.      $val[] = urlencode($key)."=".urlencode($var);
  1247.     $body = implode('&',$val);
  1248.    }
  1249.    $page .= "?$body";
  1250.    $body = "\r\n";
  1251.   }
  1252.   elseif($method == 'PUT' and $body) {          // PUT-Request vorbereiten
  1253.    if(!isset($head['content-type']) and preg_match('/^\{.*\}$/s',$body))
  1254.     $head['content-type'] = 'application/json';
  1255.    if(!isset($head['content-length']))
  1256.     $head['content-length'] = strlen($body);
  1257.   }
  1258.   else
  1259.    $body = "\r\n";
  1260.   if(!isset($head['host']))             // Host zum Header hinzuf�gen
  1261.    $head['host'] = $host;
  1262.   if($cfg['auth'] and $auth = call_user_func(__FUNCTION__,0,$page,$arg,$cfg['auth']))// HTTP Auth in folge
  1263.    $head['Authorization'] = $auth;
  1264.   if(!isset($head['connection']))           // Connection zum Header hinzuf�gen
  1265.    $head['connection'] = "close";
  1266.   foreach($head as $key => $var) {          // Header vorbereiten
  1267.    $k = $key;
  1268.    if($cfg['php'][3] > 5.3)
  1269.     $k = ucwords($key,'-');
  1270.    elseif(preg_match_all('/(?<=^|-)[a-z]/',$k,$m,PREG_OFFSET_CAPTURE))  // ucwords f�r PHP 5.3 und �lter
  1271.     for($a=count($m[0])-1; $a >= 0; $a--)
  1272.      $k = substr_replace($key,strtoupper($m[0][$a][0]),$m[0][$a][1],strlen($m[0][$a][0]));
  1273.    $head[$key] = "$k: $var";
  1274.   }
  1275.   $sp = preg_match('/^(?:save|down(?:load)?):(.*?(\.gz)?)$/i',$mode,$file);
  1276.   $head = "HTTP/1.1\r\n".implode("\r\n",$head)."\r\n";  // Header Finalisieren
  1277.   dbug("$method $page".(($cfg['dbug'] & 1<<7) ? " $head$body\n\n" : ''),5,__FUNCTION__);// Debug Request
  1278.   fwrite($fp,"$method $page $head$body");       // Request Absenden
  1279.   if($mode == 'putonly')                // Nur Upload durchf�hren
  1280.    return fclose($fp);
  1281.   $head = array();
  1282.   $header = "";
  1283.   while($a = trim($b = fgets($fp,$cfg['sbuf']))) {  // Alle Header herunterladen
  1284.    $header .= $b;
  1285.    if(preg_match('/^([\w-]+):\s*(.*)$/',$a,$b))
  1286.     $head[ucwords($b[1])] = $b[2];
  1287.    elseif(preg_match('!^HTTP/[\d.]+\s*(\d+)\s*(.+?)\s*$!im',$a,$b)) {// HTTP_Code abfangen
  1288.     $head[] = $a;
  1289.     $head['HTTP_Code'] = $b[1]; // Error-Code
  1290.     $head['HTTP_Info'] = $b[2]; // Error-Name
  1291.    }
  1292.   }
  1293.   if(!isset($head['HTTP_Code'])) {          // Request fehlgeschlagen und als Timeout Kennzeichnen
  1294.    $head['HTTP_Code'] = 504;
  1295.    $head['HTTP_Info'] = "Timeout";
  1296.   }
  1297.   $cfg['http'] = $head;                 // Header Global sichern
  1298.   if($method == 'HEAD' or $mode == 'header') {      // Nur Header herunterladen
  1299.    fclose($fp);
  1300.    return $head;
  1301.   }
  1302.   if($head['HTTP_Code'] >= 400) {           // Blacklist erkennen
  1303.    fclose($fp);
  1304.    if($head['HTTP_Code'] == 401 and !isset($arg['head']['Authorization']) and isset($head['WWW-Authenticate'])
  1305.     and $auth = call_user_func(__FUNCTION__,0,$page,$arg,$head['WWW-Authenticate'])) {// HTTP Auth
  1306.     $arg['head']['Authorization'] = $auth;
  1307.     return call_user_func(__FUNCTION__,$arg);
  1308.    }
  1309.    return errmsg("16:HTTP-Fehler: $head[HTTP_Code] $head[HTTP_Info] $page",__FUNCTION__);
  1310.   }
  1311.   $size = (ifset($head['Content-Length'])) ? $head['Content-Length'] : 0;
  1312.   $rp = "";
  1313.   if($sp) {                     // Download -> Datei
  1314.    $gz = ifset($file[2]);               // GZip komprimieren?
  1315.    if(!feof($fp)) {                 // Nur weitermachen wenn noch Daten kommen
  1316.     $file[1] = preg_replace('/(?<=[\\\\\/])$|^\.?$/',preg_replace($cfg['fesc'],$cfg['frep'],(ifset($file[1],'/^[.\\\\\/]*$/')
  1317.     and $var = ifset($head['Content-Disposition'],'/^(?:attachment;\s*)?filename=(["\']?)(.*?)\1$/mi'))
  1318.     ? $var[2] : basename(urldecode($page))),$file[1]);
  1319.     dbug("Downloade '".basename($file[1])."'".($size ? " ".number_format($size,0,'.',',')." Bytes" : ""));
  1320.     $a = $b = 0;                    // Antwort vorbereiten
  1321.     if($sp = $gz ? $cfg['zlib']['open']($file[1],'w'.$cfg['zlib']['mode']) : fopen($file[1],'w')) {
  1322.      if(ifset($head['Transfer-Encoding'],'chunked'))    // Chunked decodieren
  1323.       while(!feof($fp) and $var = fgets($fp,$cfg['sbuf'])) {                // Chunk-L�nge holen
  1324.        $len = (preg_match('/^([\da-f]+)\s*$/i',$var,$m)) ? hexdec($m[1]) : 0;       // Chunk-L�nge ermitteln
  1325.        while(!feof($fp) and $buf = ($len > $cfg['sbuf']) ? $cfg['sbuf'] : $len) {   // Buffer-L�nge nicht �berschreiten
  1326.         $len -= $buf;                   // Restl�nge bestimmen
  1327.         $var = "";                  // Buffer setzen
  1328.         while(strlen($var) < $buf)          // Soll-Daten WIRKLICH gelesen?
  1329.          $var .= fread($fp,$buf-strlen($var));      // Daten in Buffer lesen
  1330.         if($gz)                     // Buffer schreiben
  1331.          $cfg['zlib']['write']($sp,$var);
  1332.         else
  1333.          fwrite($sp,$var);
  1334.         $a += strlen($var);             // Fortschritts-Anzeige berechnen
  1335.         $c = $size ? floor($a / max($a,$size) * max($cfg['wrap']-1,10)) - $b : 1;
  1336.         dbug(str_repeat(".",$c),0,10);          // Download-Anzeige
  1337.         $b += $c;
  1338.        }
  1339.        fgets($fp,$cfg['sbuf']);             // Pad-Daten �berspringen
  1340.       }
  1341.      else                       // Normaler Download
  1342.       while(!feof($fp) and $var = fread($fp,$cfg['sbuf'])) {
  1343.        if($gz)
  1344.         $cfg['zlib']['write']($sp,$var);
  1345.        else
  1346.         fwrite($sp,$var);
  1347.        $a += strlen($var);
  1348.        $c = $size ? floor($a / max($a,$size) * max($cfg['wrap']-1,10)) - $b : 1;
  1349.        dbug(str_repeat(".",$c),0,10);           // Download-Anzeige
  1350.        $b += $c;
  1351.      }
  1352.      if($gz)
  1353.       $cfg['zlib']['close']($sp);
  1354.      else
  1355.       fclose($sp);
  1356.      dbug("\n",0,8);                    // Download-Anzeige abschlie�en
  1357.      if(!$a) {                      // Wurde wirklich was heruntergeladen?
  1358.       unlink($file[1]);
  1359.       return errmsg("8:Download Fehlgeschlagen: Keine Daten erhalten",__FUNCTION__);
  1360.      }
  1361.      else
  1362.       touch($file[1],(isset($head['Last-Modified'])) ? strtotime($head['Last-Modified']) : time());
  1363.     }
  1364.     else
  1365.      return errmsg("32:$file[1] kann nicht zum Schreiben ge�ffnet werden",__FUNCTION__);
  1366.    }
  1367.    else
  1368.     return errmsg("8:Download abgebrochen: Keine Daten erhalten",__FUNCTION__);
  1369.   }
  1370.   else {                        // Daten nur lesen
  1371.    if(preg_match('/^seek:([-+]?)(\d+)(?:-(\d+))?$/i',$mode,$var)) {// Nur einen Teil lesen (Seek:-+<offset>-<size>)
  1372.     fseek($fp,intval($var[2]),(ifset($var[1])) ? SEEK_CUR : SEEK_SET);
  1373.     if(ifset($var[3]))
  1374.      $size = intval($var[3]);
  1375.    }
  1376.    while(!feof($fp) and $var = fread($fp,$cfg['sbuf'])) {
  1377.     $rp .= $var;
  1378.     dbug(".",6,10);                 // Download-Anzeige
  1379.    }
  1380.    $meta = stream_get_meta_data($fp);
  1381.    if($meta['timed_out'] )
  1382.     $err = "Timeout: Keine Reaktion nach $cfg[tout] Sekunden";
  1383.    elseif(!$meta['eof'])                    // Sollte nie auftreten und macht bei ssl probleme
  1384.     while($meta = stream_get_meta_data($fp) and !$meta['eof'])  // Solange was runterladen bis es NICHTS mehr gibt
  1385.      while(!feof($fp) and $var = fread($fp,$cfg['sbuf'])) {
  1386.       $rp .= $var;
  1387.       dbug(".",6,10);                   // Download-Anzeige
  1388.      }
  1389.    if(ifset($head['Transfer-Encoding'],'chunked'))  // Chunked decodieren
  1390.     for($vas=$rp, $rp=''; $vas; $vas=trim($vas)) {
  1391.      $rp .= substr($vas,$pos = strpos($vas,"\r\n") +2,$len = intval($vas,16));
  1392.      $vas = substr($vas,$pos + $len);
  1393.     }
  1394.   }
  1395.   if(ifset($err))
  1396.    dbug($meta,7,'Stream-Metadata');
  1397.   fclose($fp);
  1398.   dbug("\n",6,8);                   // Download-Anzeige abschlie�en
  1399.   dbug((($cfg['dbug'] & 1<<7) ? "$header$rp" : preg_replace('/\n.*$/s','',"$header\n$rp"))."\n\n",6,__FUNCTION__);// Debug Response
  1400.   $cfg['body'] = $rp;                   // Download-Content in Globale Variable sichern
  1401.   if($mode == 'array') {                // Ausgabe mit HTTP-Header
  1402.    $fp = $head;
  1403.    $fp[1] = $rp;
  1404.   }
  1405.   elseif(substr($mode,0,4) == 'save')
  1406.    $fp = $head;
  1407.   else                          // Nur Netto-Daten zur�ckgeben
  1408.    $fp = $rp;
  1409.  }
  1410.  else {
  1411.   $err = "$host:$port - Fehler $errnr: $errstr";
  1412.   if(!isset($cfg['fail']["$host:$port"]))
  1413.    $cfg['fail']["$host:$port"] = "$errnr: $errstr";
  1414.  }
  1415.  if(ifset($err))
  1416.   errmsg("16:$err",__FUNCTION__);
  1417.  return $fp;
  1418. }
  1419. function login($pass=0,$user=0,$uipw=0,$sid=0) {    // In der Fritz!Box einloggen
  1420.  global $cfg;
  1421.  if(is_array($pass)) {                  // Login-Response berechnen
  1422.   dbug($pass[0],6);
  1423.   $preg = "(2(\\$\\d+\\$[\\da-f]+){2}|[\\da-f]+)";  // Ausdruck um Challenge zu erhalten
  1424.   if(preg_match("!<Challenge>$preg</Challenge>!i",$pass[0],$var)
  1425.     or preg_match("/(?:security:status\/challenge.*?|\"?challenge\"?:)\"?$preg\"?,?\s*(\"|$)/mi",$pass[0],$var)) {
  1426.    dbug("Kodiere Kennwort aus Challenge: $var[1] - OS ".(($var[1][1] == '$') ? '7.24' : '4.74'),9);
  1427.    $hash = (function_exists('hash_pbkdf2') and substr($var[1],0,2) == '2$' and $var = explode('$',$var[1]))
  1428.     ? "response=$var[4]$".hash_pbkdf2('sha256',hash_pbkdf2('sha256',utf8($pass[1],1),pack("H*",$var[2]),$var[1],32,true),pack("H*",$var[4]),$var[3],64,false)   // Ab OS7.24
  1429.     : "response=$var[1]-".hash('md5',preg_replace('!.!',"\$0\0","$var[1]-$pass[1]")); // Ab OS4.74
  1430.    if($pass[2] and $cfg['fiwa'] == 100)
  1431.     $cfg['fiwa'] = (substr($pass[2],-4) == '.lua') ? (isset($var[4]) ? '724' : '530') : '474';
  1432.    dbug($hash,9);
  1433.    return $hash;
  1434.   }
  1435.   else
  1436.    return errmsg("12:Keine Challenge erhalten (".((substr($pass[2],-4) == '.lua') ? 'lua' : 'xml').")",__FUNCTION__);
  1437.  }
  1438.  elseif(is_bool($pass) and !$pass and !$sid) {      // Firmware-Version ermitteln
  1439.   if($cfg['fiwa'] == 100) {
  1440.    dbug("Ermittle Boxinfos");
  1441.    if($data = request('GET','/jason_boxinfo.xml') and preg_match_all('/<([jeq]:(\w+))>([^<>]+)<\/\1>/m',$data,$array)) { // BoxInfos holen
  1442.     dbug($array,4);
  1443.     $cfg['boxinfo'] = array_combine($array[2],$array[3]);
  1444.     $cfg['boxinfo']['Time'] = strtotime($cfg['http']['Date']);
  1445.     if(preg_match('/^\d+\.0*(\d+?)\.(\d+)(-\d+)?$/',$cfg['boxinfo']['Version'],$var)) // Firmware-Version sichern
  1446.      $cfg['fiwa'] = $var[1].$var[2];
  1447.    }
  1448.   }
  1449.   return (($fw = $cfg['fiwa']) != 100 and ($user and $fw < $user or $uipw and $fw > $uipw)) ? false : $fw; // Optional: min:$user & max:$uipw
  1450.  }
  1451.  else {                         // Normaler Aufruf
  1452.   $login = array("/login_sid.lua","/cgi-bin/webcm?getpage=../html/login_sid.xml","/login.lua","/twofactor.lua");
  1453.   $page = explode('?',$login[1]);
  1454.   $preg = '/<SID>(\w+)<\/SID>/i';
  1455.   if($sid) {                        // SID-Session best�tigen lassen
  1456.    if($rp = request('GET',"$login[0]?sid=$sid") and preg_match($preg,$rp,$var) and $var[1] == $sid) {
  1457.     if($cfg['fiwa'] == 100)
  1458.      $cfg['fiwa'] = 530;
  1459.    }
  1460.    elseif($rp = request('GET',"$login[1]&sid=$sid") and preg_match($preg,$rp,$var) and $var[1] == $sid) {
  1461.     if($cfg['fiwa'] == 100)
  1462.      $cfg['fiwa'] = 474;
  1463.    }
  1464.    else
  1465.     $sid = false;                   // SID ist ung�ltig
  1466.    return $sid;                     // SID zur�ckgeben
  1467.   }
  1468.   else
  1469.    $sid = $rp = $err = false;
  1470.   call_user_func(__FUNCTION__,false);           // Firmware ermitteln
  1471.   if(isset($cfg['fail']["$cfg[host]:$cfg[port]"]))
  1472.    return errmsg("8:Host '$cfg[host]:$cfg[port]' antwortet nicht",__FUNCTION__);
  1473.   foreach(array('user','pass','uipw') as $var)      // User & Pass setzen
  1474.    if(($var != 'uipw' or $cfg['fiwa'] < 500) and !$$var)
  1475.     $$var = $GLOBALS['cfg'][$var];
  1476.   if($cfg['fiwa'] < 500 and $uipw) {            // Passwordanmeldung mit Fernwartung
  1477.    $pass = $uipw;
  1478.    $user = false;
  1479.   }
  1480.   if($cfg['fiwa'] > 723 and !$user) {           // Anmeldung ab Fritz!OS 7.24+ ohne Benutzernamen
  1481.    dbug("Suche Benutzernamen");
  1482.    if($rp = request('GET',$login[0]) and (preg_match_all('!<User[^>]*>(fritz\d+)</User>!i',$rp,$var) and count($var[1]) == 1
  1483.     or preg_match_all('!<User[^>]*>([\w\s,.-]+)</User>!i',$rp,$var) and count($var[1]) == 1)) {
  1484.     dbug("Nutze: ".$var[1][0]);
  1485.     $user = $cfg['user'] = $var[1][0];
  1486.    }
  1487.    else
  1488.     return errmsg("12:Keinen Benutzernamen angegeben",__FUNCTION__);
  1489.   }
  1490.   $bug = ($user ? " $user@" : " ")."$cfg[host] - Methode";
  1491.   if(!$sid and ($cfg['fiwa'] == 100 or $cfg['fiwa'] > 529)) { // Login lua ab 05.29 und 7.24
  1492.    dbug("Login$bug SID.lua (5.30)");
  1493.    if($rp = request('GET',$login[0].(($cfg['fiwa'] >= 724 and (function_exists('hash_pbkdf2') or cfgdecrypt(0,'hashtool'))
  1494.     and (function_exists('hash_algos') or cfgdecrypt(0,'mhash') or cfgdecrypt(0,'sha256'))) ? "?version=2" : ""))
  1495.     and ($auth = call_user_func(__FUNCTION__,array($rp,$pass,$login[0]))) and $rp = request('POST',$login[0],($user ? "$auth&username=$user" : $auth)) and preg_match($preg,$rp,$var)) {
  1496.     if($auth = ifset($rp,'/<Name>(\w+)<\/Name>\s*<Access>(\w+)<\/Access>/ia')) {
  1497.      $cfg['auth'] = array_combine($auth[1],$auth[2]);
  1498.      dbug("Benutzerrechte: ".implode(", ",$auth[1]),9);
  1499.     }
  1500.     if($cfg['fiwa'] == 100)
  1501.      $cfg['fiwa'] = 530;
  1502.     if(hexdec($var[1]) != 0)
  1503.      $sid = $var[1];
  1504.     else
  1505.      $err = ", SID.lua ist ung�ltig";
  1506.    }
  1507.    elseif(!$rp and !$err)
  1508.     $err = ", keine Antwort";
  1509.   }
  1510.   if(!$sid and ($cfg['fiwa'] == 100 or $cfg['fiwa'] > 473)) { // Login cgi ab 04.74 (Zwischen 4.74 bis 5.29)
  1511.    dbug("Login$bug SID.xml (4.74)");
  1512.    if(($rp = request('GET',$login[1]) and $auth = call_user_func(__FUNCTION__,array($rp,$pass,$page[0])) or $rp = request('GET',$login[2]) and $auth = call_user_func(__FUNCTION__,array($rp,$pass,$page[0])))
  1513.     and $rp = request('POST',$page[0],"$page[1]&login:command/$auth") and preg_match($preg,$rp,$var)) {
  1514.     if($cfg['fiwa'] == 100)
  1515.      $cfg['fiwa'] = 474;
  1516.     if(hexdec($var[1]) != 0)
  1517.      $sid = $var[1];
  1518.     elseif(!$err)
  1519.      $err = ", SID.xml ist ung�ltig";
  1520.    }
  1521.   }
  1522.   if(!$sid and ($cfg['fiwa'] == 100 or $cfg['fiwa'] < 490)) { // Login classic bis 4.89 (z.B. FRITZ!Repeater N/G)
  1523.    dbug("Login$bug PlainText");
  1524.    if($var = request('POST',$page[0],"login:command/password=$pass") and !preg_match('/Anmeldung|logincheck\.lua/',$var))
  1525.     $sid = true;
  1526.    elseif(!$var and !$err)
  1527.     $err = ", keine Antwort";
  1528.   }
  1529.   elseif($sid and $var = xml2array($rp) and ifset($var['SessionInfo']))
  1530.    $cfg['sessioninfo'] = $var['SessionInfo'];
  1531.   if($cfg['fiwa'] > 668 and $sid and $tfa = (($uipw and is_bool($uipw) or !$uipw) and $cfg['totp'] and (is_string($cfg['totp']) or !$cfg['uipw'])) ? $cfg['totp']
  1532.     : ((($uipw and is_bool($uipw) or is_bool($cfg['totp']) and $cfg['totp']) and $cfg['uipw']) ? $cfg['uipw'] : $uipw)) {   // Zwei-Faktor-Authentisierung
  1533.    $done = $cfg['2fa'] = false; # Besten Dank an Alexander Palm: (https://www.alexander-palm.de/2022/10/29/fritzbox-tools-mein-retter/)
  1534.   if(is_string($tfa)) {
  1535.     if(strlen(preg_replace('/\W/','',$tfa)) != 32 and file_exists($tfa)) { // Pr�fen ob Token/Key ein Datei ist
  1536.      dbug("Lade $tfa nach");
  1537.      $tfa = file_contents($tfa);            // Token/Key von Datei laden
  1538.     }
  1539.     if(!ifset($tfa,'/^\d{6}$/')) {          // Pr�fen ob es kein Token ist
  1540.      $tfa = otpauth($tfa);              // Token aus Key erstellen
  1541.      dbug("Generiere 2fa-Token: $tfa");
  1542.     }
  1543.     else
  1544.      dbug("Token: $tfa");
  1545.    }
  1546.    dbug("Starte Zwei-Faktor-Authentisierung");
  1547.    if($rp = request('POST',$login[3],"xhr=1&sid=$sid&tfa_start=&no_sidrenew=") and $m = ifset($rp,'/"state":"([^"]*?\\b(button|googleauth|dtmf;\d+)\\b[^"]*?)"/')) {
  1548.     $d = 0;
  1549.     $info = "Bitte an der Fritz!Box in den n�chsten $cfg[tout] Sekunden mit einer Taste best�tigen"
  1550.     .(($var = ifset($m[1],'/\bdtmf;(\d+)\b/')) ? " oder w�hlen Sie *1$var[1] mit dem Telefon" : "")."!";
  1551.     if($cfg['fiwa'] > 689 and ifset($m[1],'/\\bgoogleauth\\b/') and ifset($tfa,'/^\d{6}$/')) { // Google Authenticator (Funktioniert ohne https:// erst ab Fritz!OS 7.20)
  1552.      sleep(1);
  1553.      request('POST',$login[3],"xhr=1&sid=$sid&tfa_googleauth=$tfa&no_sidrenew=");
  1554.      $d++;
  1555.     }
  1556.     else
  1557.      out($info);
  1558.     for($a=$b=0; $a < $cfg['tout']; $a++) {     // Warten
  1559.      if($d and $a == 1)                 // Fallback, falls der Token vom Google Authenticator falsch ist
  1560.       out($info);
  1561.      sleep(1);
  1562.      if($rp = request('POST',$login[3],"xhr=1&sid=$sid&tfa_active=&no_sidrenew=") and $done = ifset($rp,'/"done":true/'))   // Pr�fen ob ok
  1563.       break;
  1564.      else {                     // Warte-Anzeige
  1565.       $c = $cfg['tout'] ? floor($a / max($a,$cfg['tout']) * max($cfg['wrap']-1,10)) - $b : 1;
  1566.       out(str_repeat(".",$c),2);
  1567.       $b += $c;
  1568.      }
  1569.     }
  1570.     if($b)                      // Warte-Anzeige abschlie�en
  1571.      out("\n",2);
  1572.    }
  1573.    elseif($done = ifset($rp,'/"state":""/'))
  1574.     dbug("Zwei-Faktor-Authentisierung ist nicht erforderlich!");
  1575.    else
  1576.     dbug("Zwei-Faktor-Authentisierung konnte nicht initiiert werden!");
  1577.    if($done or isset($cfg['opts']['f']) and $cfg['opts']['f']) // 2FA war erfolgreich oder wurde mit -f erzwungen
  1578.     $cfg['2fa'] = $done;
  1579.    else {                       // Fehlschlag
  1580.     logout($sid);
  1581.     return errmsg("Zwei-Faktor-Authentisierung fehlgeschlagen",__FUNCTION__);
  1582.    }
  1583.   }
  1584.   return ($cfg['sid'] = $sid) ? $sid : errmsg(($var = ":Anmeldung fehlgeschlagen$err" and !ifset($pass,'/^[ -~]+$/')) ?
  1585.     "5$var\nHinweis: Das Login-Kennwort enth�lt Sonderzeichen, die bei unterschiedlicher Zeichenkodierung Probleme bereiten k�nnen" : "4$var",__FUNCTION__);
  1586.  }
  1587. }
  1588. function logout($sid=0) {               // Aus der Fritz!Box ausloggen
  1589.  if(!$sid)
  1590.   $sid = $GLOBALS['cfg']['sid'];
  1591.  dbug("Logout ".$GLOBALS['cfg']['host']);
  1592.  if(is_string($sid) and $sid)               // Ausloggen
  1593.   request('GET',(($GLOBALS['cfg']['fiwa'] < 529) ? "/cgi-bin/webcm" : "/login_sid.lua"),"security:command/logout=1&logout=1&sid=$sid");
  1594. }
  1595. function supportcode($str = false) {            // Supportcode aufschl�sseln
  1596.  dbug("Entschl�ssele Supportcode");
  1597.  return ($str or $str = request('GET','/cgi-bin/system_status')) ? ((preg_match('!
  1598.     ^\s*(?:(?:<[^>]+>\s*)*(?:.*\n)?|System Status[^-]*-*[\s\r\n]*)?
  1599.     (([^<>]+?)-
  1600.     ([AB]|Kabel|Cable|Ohne)-
  1601.     ([01]\d|2[0-3])([0-2]\d|3[01])(0\d|1[01])-
  1602.     (\d\d)(\d\d)([0-2]\d|3[01])-
  1603.     ([0-7X]{6})-
  1604.     ([0-7X]{6})-
  1605.     (1[49]|21|78|8[35])(67|79)(\d\d)
  1606.     (?:-(\d{2,3})(\d\d)(\d\d)-(\d+))?
  1607.     (?:-((?=[^-]*[a-z])\w+))?
  1608.     (?:-([a-z]+))?
  1609.     |([^<>]+?)\W(\w+)\W(\d\d)(\d\d)(\d\d)\W(\d\d)(\d\d)(\d\d)(?:\W(\d{6})\W(\d{6}))?
  1610.     (?:\W(\d\d)(\d\d)(\d\d))?
  1611.     (?:\W(\d{2,3})(\d\d)(\d\d)\W(\d+))?
  1612.     (?:\W(\w+))?
  1613.     (?:\W(\w+))?)
  1614.     !ix',$str,$a))
  1615.   ? dbug($a,4).$a[1].((ifset($a[21]) and array_splice($a,2,19)) ? " (Ung�ltig)".dbug($a,4) : "")."\n\n".textTable("Modell|$a[2]"
  1616.     .(ifset($a[15]) ? "\nFirmware|$a[15].$a[16].$a[17]\nVersion|$a[18]" : "")
  1617.     .(ifset($a[20]) ? "\nSprache|$a[20]" : "")
  1618.     .(ifset($a[19]) ? "\nMarke|$a[19]" : "")
  1619.     ."\nAnnex|$a[3]"
  1620.     ."\n|\nLaufzeit|".preg_replace(array('/\b0*(\d+)(\D+)/','/(\b1\D+?)\D(?=,|$)/','/\b0+\D+/','/^\s+|,\s*$/','/^\s*$/'),array(' $1 $2','$1','','',0),"$a[7]Jahre,$a[6]Monate,$a[5]Tage,$a[4]Stunden,")
  1621.     ."\nNeustarts|".($a[8] * 32 + $a[9])
  1622.     .(($a[10] and $a[10] != "XXXXXX") ? "\n|\nCRC32 (Bootloader)|".strtoupper(str_pad(dechex((intval($a[10],8) >> 2) ^ 65535).str_pad(substr(dechex(intval($a[11],8) ^ 65535),-4),4,0,STR_PAD_LEFT),8,0,STR_PAD_LEFT))
  1623.         . " (".str_pad(decbin(intval(substr($a[10],-1).$a[11][0],8) >> 1 & 15),4,0,STR_PAD_LEFT).")" : "")
  1624.     .($a[12] ? "\n|\ndebug.cfg|".(($a[12] % 64 == 14) ? "Nicht v" : "V")."erf�gbar"
  1625.     ."\nFirmware-Attribut|".(($a[12] < 64) ? "Ge�ndert" : "Unver�ndert")
  1626.     ."\n|\nOEM|".(($a[13] == 67) ? "Custom" : "Original")
  1627.     ."\nRunClock|$a[14]" : "")."\n")
  1628.   : errmsg(($var = ifset($str,'/<title>(.*?)<\/title>/i')) ? "16:Fehler: $var[1]" : "16:Unbekannt: $str",__FUNCTION__)) : errmsg('request',__FUNCTION__);
  1629. }
  1630. function boxinfo($data=false,$mode=false) {     // jason_boxinfo.xml / juis_boxinfo.xml auslesen und auswerten
  1631.  global $cfg;
  1632.  if(!$data and login(false) and ifset($cfg['http'])) {  // Boxinfo aus der Fritz!Box auslesen
  1633.   $body = array('jason_boxinfo.xml' => $cfg['http'] + array(1 => $cfg['body']));
  1634.   $data = $cfg['body'];
  1635.   $date = isset($cfg['http']['Date']) ? $cfg['http']['Date'] : 0;
  1636.   if($var = request('GET','/juis_boxinfo.xml')) {
  1637.    $body['juis_boxinfo.xml'] = $cfg['http'] + array(1 => $var);
  1638.    $data .= $var;
  1639.   }
  1640.  }
  1641.  dbug($cfg['http'],6);
  1642.  dbug($data,6);
  1643.  if(preg_match_all('/<([ejqs]:(\w+))>([^<>]+)<\/\1>/m',$data,$array)) {
  1644.   dbug($array,4);
  1645.   $jason = array(
  1646.     'Name'      => 'Modell',
  1647.     'HW'        => 'Hardware-Version',
  1648.     'Version'   => 'Firmware-Version',
  1649.     'Revision'  => 'Firmware-Revision',
  1650.     'OEM'       => 'Marke',
  1651.     'Annex'     => 'Annex (Festnetz)',
  1652.     'Lab'       => 'Labor',
  1653.     'Country'   => 'Land-Vorwahl',
  1654.     'Major'     => 'Hauptversion',
  1655.     'Minor'     => 'Nebenversion',
  1656.     'Patch'     => 'Unterversion',
  1657.     'Buildnumber'   => 'Firmware-Revision',
  1658.     'Firmware_attrib' => 'Firmware-Attribut',
  1659.     'Serial'    => array('MAC-Adresse (LAN)',array('/\w\w(?!$)/','$0:')),
  1660.     'Buildtype' => array('Firmware-Typ',array(
  1661.         array(1007 => "PLUS Beta", 1006 => "TEST Beta", 1004 => "Phone", 1001 => 'Frisch aus der Entwicklung', 1000 => 'Inhouse', 1 => 'Normal'))),
  1662.     'UpdateConfig'  => array('Aktualisierung',array(
  1663.         array("-/-","Benachrichtigen","Benachrichtigen & Sicherheitsaktualisierungen","Automatische Aktualisierungen"))),
  1664.     'Lang'      => array('Sprache',array(
  1665.         array('de' => "Deutsch", 'en' => "English", 'es' => "Espa�ol", 'fr' => "Fran�ais", 'it' => "Italiano", 'pl' => "Polski"))),
  1666.     'Flag'      => array('Flags',array(
  1667.         array(  'crashreport' => "Absturzbericht",
  1668.             'avm_acs' => "TR-069 (AVM)",
  1669.             'prov_acs' => "TR-069 (Provider)",
  1670.             'myfritz_letsencrypt' => "HTTPS mit LetsEncrypt",
  1671.             'botnet_detection' => "Viren Erkennung",
  1672.             'mesh_master_no_trusted' => "Einsame Mesh-Zentrale",
  1673.             'mesh_repeater_no_trusted' => "Einsamer Mesh-Teilnehmer",
  1674.             'mesh_master' => "Mesh mit Teilnehmern",
  1675.             'mesh_repeater' => "Mesh-Teilnehmer",
  1676.             'nomini' => "Kein FRITZ!Mini",
  1677.             '2nd_factor_disabled' => 'Kein zweiter Faktor',
  1678.             'remote_login_service' => 'Fernwartung',
  1679.             'medium_dsl' => 'DSL-Internet',
  1680.             'medium_lan' => 'LAN-Internet'))),
  1681.   );
  1682.   $boxinfo = array();
  1683.   foreach($array[2] as $key => $var)
  1684.    $boxinfo[$var][] = html_entity_decode($array[3][$key]);
  1685.   $array = array();
  1686.   foreach($boxinfo as $key => $var) {
  1687.    $var = array_unique($var);
  1688.    if(isset($jason[$key]))
  1689.     if(is_array($jason[$key])) {
  1690.      if(ifset($jason[$key][1]))
  1691.       $var = (count($jason[$key][1]) == 2) ? preg_replace($jason[$key][1][0],$jason[$key][1][1],$var)
  1692.     : str_replace(array_keys($jason[$key][1][0]),array_values($jason[$key][1][0]),$var);
  1693.      $title = $jason[$key][0];
  1694.     }
  1695.     else
  1696.      $title = $jason[$key];
  1697.    else
  1698.     $title = $key;
  1699.    $array[$title] = "$title|".implode(", ",$var);
  1700.   }
  1701.   if($cfg['fiwa'] > 723) {                  // Erweitere Daten aus login_sid.lua auslesen
  1702.    if($rp = request('GET','/login_sid.lua') and preg_match_all('!<(User)([^>]*)>([ \w,.-]+)</\1>!i',$rp,$user)) {   // XML-Login
  1703.     $body['login_sid.xml'] = $cfg['http'] + array(1 => $rp);
  1704.     if($var = ifset($rp,'/<(BlockTime)>(\d+)<\/\1>/i') and $var[2])// Ist immer 0?
  1705.     $array['blocktime'] = "Sperrzeit|$var[2] Sekunden";
  1706.     if(count($user[3]) > 1 and ($last = preg_array('/./',$user[2],4)) !== false)
  1707.      $array['lastuser'] = "Letzter Benutzer|".$user[3][$last];
  1708.     $array['admin'] = "Benutzer (Admin)|".implode(", ",$user[3]);
  1709.    }
  1710.    else
  1711.     $user = false;
  1712.    if($rp = request('GET','/nas/api/login.lua') and $js = json2array($rp) and $flag = ifset($js['session'],true)) { // NAS-Login
  1713.     $body['login_nas.json'] = $cfg['http'] + array(1 => $rp);
  1714.     $flag = $js['session'];
  1715.     if($a = ifset($js['session']['activeUsers'],true) and (!$user or array_diff($user[3],$a) or array_diff($a,$user[3])))// NAS-User
  1716.      $array['nas'] = "Benutzer (NAS)|".implode(", ",$a);
  1717.    }
  1718.    if($rp = request('GET','/myfritz/api/login.lua') and $js = json2array($rp) and $b = ifset($js['session'],true)) {    // MyFritz-Login
  1719.     $body['login_myfritz.json'] = $cfg['http'] + array(1 => $rp);
  1720.     $flag += $b;
  1721.     if($b = ifset($js['session']['activeUsers'],true) and (!ifset($user) or array_diff($user[3],$b) or array_diff($b,$user[3]))
  1722.     and (!ifset($a) or array_diff($a,$b) or array_diff($b,$a)))                         // MyFritz-User
  1723.      $array['myfritz'] = "Benutzer (MyFritz)|".implode(", ",$b);
  1724.    }
  1725.    if(isset($array['admin']) and !isset($array['myfritz']) and !isset($array['nas']))
  1726.     $array['admin'] = preg_replace('/^(\w+)[^|]*/','$1',$array['admin']);
  1727.    $flags = "";
  1728.    if(ifset($flag['fromInternet']))
  1729.     $flags .= ", Internet-Zugang";
  1730.    if(ifset($flag['noUserList']))
  1731.     $flags .= ", Keine Benutzerliste";
  1732.    if(isset($flag['firstStartWizardDone']) and !$flag['firstStartWizardDone'])
  1733.     $flags .= ", Assistent beim Start";
  1734.    if(isset($flag['nasActive']))
  1735.     $flags .= ", NAS ist a".($flag['nasActive'] ? "n" : "us");
  1736.    if($key = ifset($flag['viewMode'],""))
  1737.     $flags .= ", ".(($key == "loginOnlyWithPwd") ? "Login nur mit Kennwort" : "Benutzer-Login" );
  1738.    if($key = ifset($flag['migratedUser'],""))
  1739.     $array['migrated'] = "Migrierter Benutzer|$key";
  1740.    if($flags)
  1741.     $array['Flags'] = ifset($array['Flags']) ? $array['Flags'].$flags : substr($flags,2);
  1742.   }
  1743.   if($date)
  1744.    $array['Boxtime'] = 'Aktuelle Uhrzeit|'.date('d.m.Y H:i:s',strtotime($date));
  1745.   $data = textTable(implode("\n",$array));
  1746.   dbug($body,6);
  1747.   if($mode) {                       // RAW-Daten mit zur�ckgeben
  1748.    array_unshift($body,$data);
  1749.    $data = $body;
  1750.   }
  1751.   return $data;
  1752.  }
  1753.  else
  1754.   return '';
  1755. }
  1756. function upnprequest($page,$ns,$rq,$exp=false) {    // UPnP Request durchf�hren
  1757.  global $cfg;
  1758.  dbug("Setzte UPnP request ab: $page - $rq",9);
  1759.  if($rp = request(array(
  1760.     'method' => 'POST-array',
  1761.     'page' => $page,
  1762.     'body' => utf8("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
  1763.     ."<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n"
  1764.     ."<s:Body><u:$rq xmlns:u=$ns /></s:Body>\n</s:Envelope>",1),
  1765.     'head' => array_merge($GLOBALS['cfg']['head'],array('content-type' => 'text/xml; charset="utf-8"', 'soapaction' =>  "\"$ns#$rq\"")),
  1766.     'port' => $GLOBALS['cfg']['upnp']))) {
  1767.   if($cfg['fiwa'] != 100 and $var = ifset($rp['SERVER'],'/0*([1-9])\.(\d{2})\s*$/'))    // Firmware-Version auslesen
  1768.    $cfg['fiwa'] = intval($var[1].$var[2]);
  1769.   if($exp and is_string($exp))              // Nur einen Wert extrahieren
  1770.    return (preg_match("!<$exp>(.*?)</$exp>!",$rp[1],$var)) ? $var[1] : errmsg('16:Kein Erwartetes Ergebnis erhalten',__FUNCTION__);
  1771.   elseif(is_array($exp) and preg_match_all('!<(\w+)>(.+?)</\1>!',$rp[1],$array)) {  // Alle Werte in ein Array packen
  1772.    dbug($array,4,__FUNCTION__);
  1773.    foreach($array[1] as $key => $var)           // Ergebnisse zusammenstellen
  1774.     $exp[$var] = $array[2][$key];
  1775.    return $exp;
  1776.   }
  1777.   else                          // Response RAW zur�ckgeben
  1778.    return $rp;
  1779.  }
  1780.  else                           // Fehler aufgetreten
  1781.   return errmsg('request',__FUNCTION__);
  1782. }
  1783. function getupnppath($urn) {                // Helper f�r UPnP-Requests
  1784.  dbug("Ermittle UPnP Pfad: $urn",9);
  1785.  if($rp = request(array('method' => 'GET', 'page' => '/igddesc.xml', 'port' => $GLOBALS['cfg']['upnp']))
  1786.     and preg_match("!<(service)>.*?<(serviceType)>(urn:[^<>]*".$urn."[^<>]*)</\\2>.*?<(controlURL)>(/[^<>]+)</\\4>.*?</\\1>!s",$rp,$var)) {
  1787.   dbug($var,4);
  1788.   $rp = array($var[3],$var[5]);
  1789.  }
  1790.  else
  1791.   $rp = errmsg('request',__FUNCTION__);
  1792.  return $rp;
  1793. }
  1794. function getexternalip() {              // Externe IPv4-Adresse �ber UPnP ermitteln
  1795.  global $cfg;
  1796.  dbug("Ermittle IP-Adresse �ber UPnP f�r $cfg[fiwa]");
  1797.  $ip = array();
  1798.  if($val = getupnppath('WANIPConnection')) {
  1799.   if($var = upnprequest($val[1],$val[0],'GetExternalIPAddress','NewExternalIPAddress'))
  1800.     $ip['IPv4'] = $var;
  1801.   if($cfg['http']['HTTP_Code'] == 200 and ($cfg['fiwa'] >= 550 or $cfg['fiwa'] == 100)) {   // IPv6 und DNS bei neueren Boxen
  1802.    $k = "X_AVM_DE_Get";
  1803.    if($var = upnprequest($val[1],$val[0],$k.'ExternalIPv6Address','NewExternalIPv6Address'))
  1804.     $ip['IPv6'] = $var;
  1805.    if($var = upnprequest($val[1],$val[0],$k.'IPv6Prefix',array()) and ifset($var['NewIPv6Prefix']))
  1806.     $ip['IPv6-Prefix'] = "$var[NewIPv6Prefix]/$var[NewPrefixLength]";
  1807.    if($var = upnprequest($val[1],$val[0],$k.'DNSServer',array()) and $var = preg_array('/New(IPv4)?DNSServer/',$var,3))
  1808.     $ip['DNSv4'] = implode(", ",$var);
  1809.    if($var = upnprequest($val[1],$val[0],$k.'IPv6DNSServer',array()) and $var = preg_array('/NewIPv6DNSServer/',$var,3))
  1810.     $ip['DNSv6'] = implode(", ",$var);
  1811.   }
  1812.   if($ip)
  1813.    return $ip;
  1814.  }
  1815.  return errmsg('request',__FUNCTION__);
  1816. }
  1817. function forcetermination() {               // Internetverbindungen �ber UPnP neu aufbauen
  1818.  dbug("WAN Neueinwahl �ber UPnP");
  1819.  return ($val = getupnppath('WANIPConnection') and $var = upnprequest($val[1],$val[0],'ForceTermination'))
  1820.   ? $var : errmsg('request',__FUNCTION__);
  1821. }
  1822. function saverpdata($file,$data,$name) {        // HTTP-Downloads in Datei speichern
  1823.  global $cfg;
  1824.  if(!$file or is_bool($file)) {                     // File ist leer
  1825.   $dir = "./";
  1826.   $file = "";
  1827.  }
  1828.  elseif($file == ':')                           // Es soll nichts geschrieben werden
  1829.   return true;
  1830.  elseif(file_exists($file) and is_dir($file)) {             // file ist ein Verzechnis
  1831.   $dir = str_replace('\\','/',realpath($file))."/";
  1832.   $file = false;
  1833.  }
  1834.  elseif($dir = dirname($file)."/" and file_exists($dir) and is_dir($dir))// file enth�lt ein Verzeichnis
  1835.   $file = basename($file);
  1836.  else {                                 // file ist nur eine Datei...
  1837.   $dir = "./";
  1838.   if(!file_exists($file))                       // ...dass nicht existiert
  1839.    $file = basename($file);
  1840.  }
  1841.  if(!is_array($data))
  1842.   $data = $cfg['http'] + array(1 => $data);
  1843.  $cfg['file'] = $file = preg_replace($cfg['fesc'],$cfg['frep'],(!$file and isset($data['Content-Disposition']) and preg_match('/filename="(.*)"/',$data['Content-Disposition'],$var)) ? $var[1] : ($file ? $file : $name));
  1844.  dbug("Speichere Daten in $dir$file",9);
  1845.  return file_contents($dir.$file,$data[1]);
  1846. }
  1847. function supportdata($file=false,$tm=false,$sid=0) {    // Supportdaten anfordern
  1848.  dbug("Hole Supportdaten");
  1849.  if(!$sid)
  1850.   $sid = $GLOBALS['cfg']['sid'];
  1851.  $array = array();
  1852.  if(!is_bool($sid))
  1853.   $array['sid'] = $sid;
  1854.  $mode = 'SupportData';
  1855.  if($tm !== false) {
  1856.   if($GLOBALS['cfg']['fiwa'] < 680 and $GLOBALS['cfg']['fiwa'] >= 650) {    // Telemetrie ab OS6.5 aktivieren
  1857.    dbug("Telemetrie wird ".($tm ? '' : 'de') ."aktiviert");
  1858.    request('POST','/data.lua',"xhr=1&sid=$sid&lang=de&no_sidrenew=".($tm ? '&supportdata_enhanced=on' : '')."&support_plus=&oldpage=/support.lua");
  1859.   }
  1860.   elseif($GLOBALS['cfg']['fiwa'] >= 680 and !$tm) {
  1861.    dbug("Aktiviere Telemetrie");
  1862.    $mode .= 'Enhanced';
  1863.   }
  1864.  }
  1865.  $array[$mode] = '';
  1866.  $data = $file ? (bool)request("POST-save:$file",'/cgi-bin/firmwarecfg',$array) : request("POST-array",'/cgi-bin/firmwarecfg',$array);
  1867.  return $data ? $data : errmsg('request',__FUNCTION__);
  1868. }
  1869. function supportdataextrakt($data,$mode=0,$file='') {   // Supportdaten extrahieren
  1870.  global $cfg;
  1871.  $info = array();
  1872.  if(is_array($mode) and $mode[0] == 'sec') {
  1873.   $preg = '/^#{5} +BEGIN +SECTION +(\S+) *([^\r\n]+\s*)?(.*?)^#{5} +END +SECTION +\1\s+/sim';
  1874.   if(preg_match_all($preg,$data,$array)) {
  1875.    dbug($array,4,'SupportDataExtrakt-#');
  1876.    foreach($array[1] as $key => $var)
  1877.     if(trim($array[3][$key]))
  1878.      $info = array_merge($info,(($val = trim(preg_replace($preg,'',$array[3][$key]))) ? array($var => $array[2][$key].$val) : array()),call_user_func(__FUNCTION__,$array[3][$key],array('sec')));
  1879.   }
  1880.  }
  1881.  else {
  1882.   dbug("Zerlege Supportdaten");
  1883.   $mstr = $mlen = array(0,0);
  1884.   $val = $list = array();
  1885.   if(substr($data,0,5) == '#####')
  1886.    $array = call_user_func(__FUNCTION__,$data,array('sec'));
  1887.   elseif(preg_match('/^Support Data\n-+\n/',$data)
  1888.     and preg_match_all('/([()\/\w@:. -]+)\n-+\n([\s\S]+?)(?=End Of Support Data\s*$|\n\n[()\/\w@:. -]+\n-+\n|$)/i',$data,$array))
  1889.    $array = array_combine($array[1],$array[2]);
  1890.   if($array) {
  1891.    if(ifset($file,'/\.zip$/i')) {
  1892.     if($zip = data2zip($array))
  1893.      file_contents($file,$zip);
  1894.    }
  1895.    else {                       // Tar-Archiv
  1896.     if($mode and $file)                 // Tar-Archiv Initialisieren
  1897.      $fp = ($mode == 2) ? $cfg['zlib']['open']($file,'w'.$cfg['zlib']['mode']) : call_user_func(($cfg['bzip'] and $mode == 3) ? 'bzopen' : 'fopen',$file,'w');
  1898.     foreach($array as $key => $var) {           // Maximale L�ngen ermitteln
  1899.      $key = preg_replace($cfg['fesc'],$cfg['frep'],$key);
  1900.      $list[] = array($key,number_format(strlen($var),0,",","."));
  1901.      if($mode == 3 and $fp)
  1902.       bzwrite($fp,data2tar("$key.txt",$var,$date));
  1903.      elseif($mode == 2 and $fp)
  1904.       $cfg['zlib']['write']($fp,data2tar("$key.txt",$var,$date));
  1905.      elseif($mode == 1 and $fp)
  1906.       fwrite($fp,data2tar("$key.txt",$var,$date));
  1907.      elseif($file)
  1908.       file_contents("$key.txt",$var);
  1909.     }
  1910.     if($mode and $fp) {                 // Tar-Archiv abschlie�en
  1911.      $data = str_repeat("\0",512);
  1912.      if($mode == 3) {
  1913.       bzwrite($fp,$data);
  1914.       bzclose($fp);
  1915.      }
  1916.      elseif($mode == 2) {
  1917.       $cfg['zlib']['write']($fp,$data);
  1918.       $cfg['zlib']['close']($fp);
  1919.      }
  1920.      else {
  1921.       fwrite($fp,$data);
  1922.       fclose($fp);
  1923.      }
  1924.     }
  1925.    }
  1926.    for($a=0; $a < ceil(count($list)/2); $a++)
  1927.     foreach(array($a,$a+ceil(count($list)/2)) as $b)
  1928.      if(isset($list[$b]))
  1929.       $val[$a] = ((isset($val[$a])) ? $val[$a]."||" : "").$list[$b][0]."| ".$list[$b][1]." Bytes";
  1930.     $info = textTable(implode("\n",$val));
  1931.   }
  1932.   else
  1933.    dbug("Das zerlegen der Supportdaten ist fehlgeschlagen");
  1934.  }
  1935.  return $info;
  1936. }
  1937. function dial($dial,$fon=false,$sid=0) {        // Wahlhilfe
  1938.  global $cfg;
  1939.  if(!$sid)
  1940.   $sid = $cfg['sid'];
  1941.  $sid = (!is_bool($sid)) ? "&sid=$sid" : '';
  1942.  $dial = preg_replace('/[^\d*#]+/','',$dial);
  1943.  $rdial = urlencode($dial);
  1944.  $fon = ($var = ifset($fon,'/^((?P<i>[1-4]|5[0-8]|6[0-5])|(?P<s>fon[1-4]?|isdn[0-8]?|dect[0-6]?))($)/i'))
  1945.     ? (($var['i']) ? intval($var['i']) : (($var = ifset($var['s'],'/(\D+)(\d?)/')) ? ((ifset($var[1],'/fon/i')) ? (($var[2]) ? intval($var[2]) : 1)
  1946.     : ((ifset($var[0],'/isdn|dect0?$/i')) ? 50 : 59) + intval($var[2])) : 0)) : false;
  1947.  if($cfg['fiwa'] >= 530) {
  1948.   if($fon) {
  1949.    dbug("Dial: �ndere Anruf-Telefon auf $fon");
  1950.    request('POST',"/fon_num/dial_fonbook.lua","clicktodial=on&port=$fon&btn_apply=$sid");
  1951.   }
  1952.   dbug("Dial: ".($dial ? "W�hle $dial" : "Auflegen"));
  1953.   request((($cfg['fiwa'] >= 708) ? 'POST' : 'GET'),"/fon_num/fonbook_list.lua",($dial ? "dial=$rdial" : "hangup=&orig_port=$fon").$sid);
  1954.  }
  1955.  else { // Classic
  1956.   request('POST',"/cgi-bin/webcm","telcfg:settings/UseClickToDial=1"
  1957.     .($dial ? "&telcfg:command/Dial=$rdial" : "&telcfg:command/Hangup=")
  1958.     .($fon ? "&telcfg:settings/DialPort=$fon" : "").$sid);
  1959.   dbug("Dial: ".($dial ? "W�hle $dial".($fon ? " f�r Telefon $fon" : "") : "Auflegen"));
  1960.  }
  1961.  return $dial ? $dial : "-";
  1962. }
  1963. function cfgexport($mode,$pass=false,$sid=0) {      // Konfiguration Exportieren (NUR Exportieren)
  1964.  dbug("Exportiere Konfig");
  1965.  $body = array('ImportExportPassword' => $pass, 'ConfigExport' => false);
  1966.  $path = '/cgi-bin/firmwarecfg';
  1967.  if(!$sid) {
  1968.   $sid = $GLOBALS['cfg']['sid'];
  1969.   if(!is_bool($sid))
  1970.    $body = array_merge(array('sid' => $sid),$body);
  1971.  }
  1972.  return $mode   ? (($mode === 'array')  ? request('POST-array',$path,$body)
  1973.                     : request('POST-save:'.(($mode === true) ? './' : $mode),$path,$body))
  1974.         : request('POST',$path,$body);
  1975. }
  1976. function cfgcalcsum($data) {                // Checksumme f�r die Konfiguration berechnen
  1977.  if(preg_match_all('/^(\w+)=(\S+)\s*$|^(\*{4}) (?:CRYPTED)?(CFG|BIN|B64)FILE:(\S+)\s*(.*?)\3 END OF FILE \3\s*$/sm',$data,$array)) {
  1978.   dbug("Berechne Konfig-Checksumme",9);
  1979.   dbug($array,4,'CfgCalcSum-#');
  1980.   foreach($array[4] as $key => $var)
  1981.    $array[0][$key] = ($array[1][$key]) ? $array[1][$key].$array[2][$key]."\0" : $array[5][$key]."\0".(($var == 'BIN')
  1982.     ? pack('H*',preg_replace('/[^\da-f]+/i','',$array[6][$key])) : (($var == 'B64') ? base64_decode($array[6][$key])
  1983.     : preg_replace('/\r|\\\\(?=\\\\)/','',substr($array[6][$key],0,-1))));
  1984.   dbug($array[0],4,'8,CfgCalcSumArray-#');
  1985.   dbug(join('',$array[0]),4,'8,CfgCalcSumData');
  1986.  }
  1987.  return ($array and preg_match('/(?<=^\*{4} END OF EXPORT )[A-Z\d]{8}(?= \*{4}\s*$)/m',$data,$key,PREG_OFFSET_CAPTURE))
  1988.     ? array($key[0][0],$var = strtoupper(hash('crc32b',join('',$array[0]))),substr_replace($data,$var,$key[0][1],8)) : errmsg('16:Keine Konfig-Datei',__FUNCTION__);
  1989. }
  1990. function cfgimport($file,$pass='',$mode=false,$sid=0) { // Konfiguration importieren (Wird vermutlich bald �berarbeitet)
  1991.  global $cfg;
  1992.  if($file and ( is_file($file) and preg_match($cfg['ptar'],$file,$var) and ($data = cfgmake($var[4] ? zip2array(file_contents($file)) : tar2array($file)))
  1993.         or is_file($file) and ($data = file_contents($file))
  1994.         or is_dir($file) and ($data = cfgmake($file))
  1995.     ) or !$file and $data = $mode and substr($mode,0,4) == '****') {
  1996.   if($mode and $var = cfgcalcsum($data))
  1997.    $data = $var[2];
  1998.   dbug("Upload Konfig-File an ".$cfg['host']);
  1999.   $body = array('ImportExportPassword' => $pass,
  2000.     'ConfigImportFile' => array('filename' => $file, 'Content-Type' => 'application/octet-stream', '' => $data),
  2001.     'apply' => false);
  2002.   if(!$sid) {
  2003.    $sid = $cfg['sid'];
  2004.    if(!is_bool($sid))
  2005.     $body = array_merge(array('sid' => $sid),$body);
  2006.   }
  2007.   if($cfg['fiwa'] >= 724)
  2008.    $res = request('POST','/data.lua',"xhr=1&recovery&$sid=$sid&ImportExportPassword=".urlencode($pass)."&uiPass=".urlencode($pass)
  2009.     ."&cfgtakeover=all&restore=&lang=de&page=sysImp");
  2010.   return request('POST','/cgi-bin/firmwarecfg',$body);
  2011.  }
  2012.  else
  2013.   return errmsg('8:Import-Datei/Ordner nicht gefunden',__FUNCTION__);
  2014. }
  2015. function cfginfo($data,$mode=0,$file='',$text=false) {  // Konfiguration in Einzeldateien sichern (mode: 0->show, 1->Dir, 2->Tar, 3->tgz, 4->tbz)
  2016.  global $cfg;
  2017.  if(preg_match_all('/^(?:
  2018.     \*{4}\s(.*?)\sCONFIGURATION\sEXPORT|(\w+=\S+))\s*$          # 1 Fritzbox-Modell, 2 Variablen
  2019.     |^\*{4}\s(?:CRYPTED)?(CFG|BIN|B64)FILE:(\S+)\s*?\r?\n(.*?)\r?\n # 3 Typ, 4 File, 5 Data
  2020.     ^\*{4}\sEND\sOF\sFILE\s\*{4}\s*?$/msx',$data,$array) and $array[1][0] and $crc = cfgcalcsum($data)) {
  2021.   $list = $val = $vars = array();
  2022.   $mstr = $mlen = array(0,0);
  2023.   dbug($array,4,'CfgInfo-#');
  2024.   if($mode == 4 and !$cfg['bzip']) {
  2025.    $mode -= 2;
  2026.    $file = preg_replace('/(\.tar)?\.t?bz(ip)?2?|/i','.tar',$file);
  2027.   }
  2028.   elseif($mode == 5)
  2029.    $zip = array();
  2030.   $fp = ($mode < 5 and $mode >= 2 and $file) ? (($mode == 3) ? $cfg['zlib']['open']($file,'w'.$cfg['zlib']['mode']) : call_user_func(($mode == 4) ? 'bzopen' : 'fopen',$file,'w')) : false; // tar/tgz initialisieren
  2031.   foreach($array[3] as $key => $var)        // Config-Dateien aufteilen
  2032.    if($var) {
  2033.     if($array[3][$key] == 'CFG') {
  2034.      $bin = preg_replace('/\r|\\\\(?=\\\\)/','',$array[5][$key]);
  2035.      if(!isset($vars['Date']) and preg_match('/^\s\*\s([\s:\w]+)$/m',$bin,$var))
  2036.       $vars['Date'] = strtotime($var[1]);
  2037.     }
  2038.     else
  2039.      $bin = ($array[3][$key] == 'B64') ? base64_decode($array[5][$key]) : pack('H*',preg_replace('/[^\da-f]+/i',"",$array[5][$key]));
  2040.     $list[] = array($array[3][$key],$array[4][$key],number_format(strlen($bin),0,",","."));
  2041.     if($mode == 5)
  2042.      $zip[$array[4][$key]] = array('data' => $bin, 'date' => $vars['Date']);
  2043.     elseif($fp and $mode == 4)
  2044.      bzwrite($fp,data2tar($array[4][$key],$bin,$vars['Date']));
  2045.     elseif($fp and $mode == 3)
  2046.      $cfg['zlib']['write']($fp,data2tar($array[4][$key],$bin,$vars['Date']));
  2047.     elseif($fp and $mode >= 2)
  2048.      fwrite($fp,data2tar($array[4][$key],$bin,$vars['Date']));
  2049.     elseif($mode >= 1)
  2050.      file_contents($array[4][$key],$bin);
  2051.     unset($array[2][$key]);
  2052.    }
  2053.    elseif($var = ifset($array[2][$key],'/^(\w+)=(.*)$/'))
  2054.     $vars[$var[1]] = $var[2];
  2055.    else
  2056.     unset($array[2][$key]);
  2057.   $name = "index.txt";              // Konfig-Schablone sichern
  2058.   $data = preg_replace('/^(\*{4}\s(?:CRYPTED)?(?:CFG|BIN|B64)FILE:\S+\s*?\r?\n).*?\r?\n(^\*{4}\sEND\sOF\sFILE\s\*{4}\s*?)$/msx','$1$2',$data);
  2059.   $list[] = array("TXT",$name,number_format(strlen($data),0,",","."));
  2060.   if($mode == 5)
  2061.    $zip[$name] = array('data' => $data, 'date' => $vars['Date']);
  2062.   elseif($fp and $mode == 4)
  2063.    bzwrite($fp,data2tar($name,$data,$vars['Date']));
  2064.   elseif($fp and $mode == 3)
  2065.    $cfg['zlib']['write']($fp,data2tar($name,$data,$vars['Date']));
  2066.   elseif($fp and $mode >= 2)
  2067.    fwrite($fp,data2tar($name,$data,$vars['Date']));
  2068.   elseif($mode >= 1)
  2069.    file_contents($name,$data);
  2070.   if($text) {                   // Zugangsdaten sichern
  2071.    $name = "zugangsdaten.txt";
  2072.    $list[] = array("TXT",$name,number_format(strlen($text),0,",","."));
  2073.   if($mode == 5)
  2074.    $zip[$name] = array('data' => $text, 'date' => $vars['Date']);
  2075.    if($fp and $mode == 4)
  2076.     bzwrite($fp,data2tar($name,$text,$vars['Date']));
  2077.    elseif($fp and $mode == 3)
  2078.     $cfg['zlib']['write']($fp,data2tar($name,$text,$vars['Date']));
  2079.    elseif($fp and $mode >= 2)
  2080.     fwrite($fp,data2tar($name,$text,$vars['Date']));
  2081.    elseif($mode >= 1)
  2082.     file_contents($name,$text);
  2083.   }
  2084.   if($mode == 5 and $zip = data2zip($zip))
  2085.     file_contents($file,$zip);
  2086.   elseif($fp) {                 // tar/tgz finalisieren
  2087.    $data = str_repeat("\0",512);
  2088.    if($mode == 4) {
  2089.     bzwrite($fp,$data);
  2090.     bzclose($fp);
  2091.    }
  2092.    elseif($mode == 3) {
  2093.     $cfg['zlib']['write']($fp,$data);
  2094.     $cfg['zlib']['close']($fp);
  2095.    }
  2096.    elseif($mode == 2) {
  2097.     fwrite($fp,$data);
  2098.     fclose($fp);
  2099.    }
  2100.   }
  2101.   for($a=0; $a < ceil(count($list)/2); $a++)
  2102.    foreach(array($a,$a+ceil(count($list)/2)) as $b)
  2103.     if(isset($list[$b]))
  2104.      $val[$a] = ((isset($val[$a])) ? $val[$a]."||" : "").$list[$b][0].":|".$list[$b][1]."| ".$list[$b][2]." Bytes";
  2105.   $list = "\nModell:   {$array[1][0]}\n";
  2106.   if(ifset($vars['Date']))
  2107.    $list .= "Datum:    ".date('d.m.Y H:i:s',$vars['Date'])."\n";
  2108.   if(ifset($vars['FirmwareVersion']))
  2109.    $list .= "Firmware: $vars[FirmwareVersion]\n";
  2110.   return $list."Checksum: $crc[0]".((!$mode and $text) ? "" : " (".(($crc[0] == $crc[1]) ? "OK" : "Inkorrekt! - Korrekt: $crc[1]").")")."\n\n"
  2111.     .textTable(implode("\n",$val))."\n".((!$mode and $text) ? $text : '');
  2112.  }
  2113.  else
  2114.   return errmsg('16:Keine Konfig-Datei',__FUNCTION__);
  2115. }
  2116. function cfgmake($dir,$mode='',$file=false) {       // Konfiguration wieder zusammensetzen
  2117.  if(is_array($dir) and isset($dir[0]) and !$mode and !$file) {  // Helper f�r Preg_Replace CfgMake
  2118.   if(is_array($GLOBALS['val']) and isset($GLOBALS['val'][$dir[3]]))
  2119.    $mode = $GLOBALS['val'][$dir[3]];
  2120.   elseif(file_exists("$GLOBALS[val]/$dir[3]"))
  2121.    $mode = file_contents("$GLOBALS[val]/$dir[3]");
  2122.   return $dir[1].(($dir[2] == 'CFG') ? str_replace("\\","\\\\",$mode)
  2123.     : wordwrap(($dir[2] == 'BIN') ? strtoupper(implode('',unpack('H*',$mode))) : base64_encode($mode),80,$dir[4],1)).$dir[4].$dir[5];
  2124.  }
  2125.  elseif($dir and (is_array($dir) and $data = preg_array('/^(index|pattern)\.txt$/',$dir,1) or ($var = glob("$dir/{index,pattern}.txt",GLOB_BRACE))
  2126.     and ($data = file_contents($var[0]))) and preg_match('/^\*{4}\s+\w+.*CONFIGURATION EXPORT/',$data,$array)) {
  2127.   dbug("Setze Konfig-Daten zusammen");
  2128.   $GLOBALS['val'] = $dir;
  2129.   $data = preg_replace_callback('/(^\*{4}\s(?:CRYPTED)?(CFG|BIN|B64)FILE:(\S+)\s*?(\r?\n))(^\*{4}\sEND\sOF\sFILE\s\*{4}\s*?$)/m',__FUNCTION__,$data);
  2130.   if(preg_match('/^\*{4}\s(.*?)\sCONFIGURATION\sEXPORT.*?FirmwareVersion=(\S+)/s',$data,$array) and $crc = cfgcalcsum($data)) {
  2131.    $val = "Modell:   $array[1]\nFirmware: $array[2]\nChecksum: $crc[0] ";
  2132.    $val .= (($crc[0] == $crc[1]) ? "(OK)" : "Inkorrekt! - Korrekt: $crc[1]")."\n";
  2133.    $data = $mode ? $crc[2] : $data;
  2134.    if($file)
  2135.     file_contents($file,$data);
  2136.    return $file ? $val : $data;
  2137.   }
  2138.  }
  2139.  return errmsg("8:Keine Konfig-Daten - Konfig-Schablone nicht gefunden",__FUNCTION__);
  2140. }
  2141. function cfgdecrypt($data=false,$pass=false) {      // Konfig-Datei entschl�sseln
  2142.  global $cfg;
  2143.  if(is_array($pass) and substr($copy = $data,0,4) == '$$$$') {  // Fritz Decrypt
  2144.   $a = substr($d = unBase($data),0,16);             // AES iv
  2145.   $b = substr($d,16).str_pad("\0",16 - strlen($d) % 16);    // AES data.pad
  2146.   foreach($cfg['aes'] as $aes => $var) {            // Alle AES-Bibliotheken durchprobieren
  2147.    for($c=count($pass)-1; $c >= 0; $c--) {          // Alle Kennw�rter durchprobieren
  2148.     if($pass[$c] == 1)                      // Letzter Schl�ssel im Bund
  2149.      $data = false;
  2150.     elseif($aes == 'openssl')                   // Extension: OpenSSL
  2151.      $data = openssl_decrypt($b, "AES-256-CBC", $pass[$c], OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $a);
  2152.     elseif($aes == 'mcrypt')                    // Extension: MCrypt
  2153.      $data = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $pass[$c], $b, MCRYPT_MODE_CBC, $a);
  2154.     elseif($aes == 'aes5')                  // Script: Aes.php
  2155.      $data = eval('$d = new PhpAes\Aes($pass[$c], "CBC", $a); return $d->decrypt($b);');
  2156.     elseif($aes == 'aes4') {                    // Script: AES_4.class.php
  2157.      $d = new Aes($pass[$c], "CBC", $a);
  2158.      $data = $d->decrypt($b);
  2159.     }
  2160.     if(substr(hash('md5',substr($data,4,strlen($data) - 20),true),0,4) == substr($data,0,4)) {          // Checksum
  2161.      $data = substr($data,8,hexdec(bin2hex(substr($data,4,4))));                        // Extract
  2162.      return (end($pass) == 1) ? preg_replace(array('/\0?$/','/[\\"]/'),array('','\\\\$0'),$data) : $data;
  2163.     }
  2164.    }
  2165.   }
  2166.   dbug("Fail: $copy",4);
  2167.   return false;
  2168.  }
  2169.  elseif(preg_match('/^\*{4} .*? CONFIGURATION EXPORT$/mi',$data) and $pass) {   // Konfig einlesen und zur entschl�sselung vorbereiten
  2170.   dbug($data,4,'12,CfgDeCrypt-Crypted');
  2171.   if(preg_match('/^\s*(?:([A-Z](?:0[1-9]|[1-4]\d|5[0-3])[1-7]\.?\d{3}\.?\d{2}(?:\.?\d{3}){2})\W)?((?:[\dA-F]{2}([:-]|(?=\s*$))){6})\s*$/i',$pass,$var)) // Alternative zur Konfiguationen ohne Kennwort
  2172.    $pass = ((ifset($var[1])) ? str_replace('.','',$var[1]) : str_repeat('0',16))."\n".strtoupper(str_replace('-',':',$var[2]))."\n";    // Seriennummer und MacA-Adresse als Kennwort
  2173.   $pass = array(str_pad(hash('md5',$pass,true),32,"\0"));
  2174.   if(preg_match_all('/(Password\d*=)(\${4}\w+)/i',$data,$match,PREG_OFFSET_CAPTURE))
  2175.    for($a=count($match[0])-1; $a >= 0; $a--)
  2176.     if($key = call_user_func(__FUNCTION__,$match[2][$a][0],$pass) and strlen($key) == 32 and substr($key,0,16) == substr($key,16)) {    // Schl�ssel extraieren
  2177.      $pass[] = str_pad(substr($key,16),32,"\0");                                    // Schl�ssel merken
  2178.      $data = substr_replace($data,strtoupper(bin2hex(substr($key,16))),$match[2][$a][1],strlen($match[2][$a][0]));  // Schl�ssel in Plaintext
  2179.     }
  2180.   if(count($pass) > 1 and preg_match_all('/(\${4}\w+)(?="|$)|^(\*{4}\sB(64|IN)FILE:.*\s*)([\dA-F\s]*?(?:24\s*){4}(?:[46][1-9A-F]|[57][0-9A]|3\d|\s*)+[\dA-F\s]*|[\w+\/\s]*?(?:JCQkJ|QkJC|kJCQk)[\w+\/\s=]+)(?=\s+\*{4})|^(\*{4}\sCRYPTEDB(64|IN)FILE:.*\s*)([\dA-F\s]+)(?=\s+\*{4})/im',$data,$match,PREG_OFFSET_CAPTURE)) {
  2181.    $pass[] = 1;                         // Schl�sselring anschlie�en
  2182.    for($a=count($match[0])-1; $a >= 0; $a--) {
  2183.     if($match[1][$a][0])
  2184.      $data = substr_replace($data,call_user_func(__FUNCTION__,$match[1][$a][0],$pass),$match[1][$a][1],strlen($match[1][$a][0]));
  2185.     else {
  2186.      if($match[5][$a]) {
  2187.       $match[2][$a] = $match[5][$a];
  2188.       $match[3][$a] = $match[6][$a];
  2189.       $match[4][$a] = $match[7][$a];
  2190.      }
  2191.      $b = $match[2][$a][0];
  2192.      $c = ($match[3][$a][0] == 64) ? base64_decode($match[4][$a][0]) : pack("H*", preg_replace('/\W+/','',$match[4][$a][0]));
  2193.      if(isset($match[5][$a][0]) and $match[5][$a][0] == $b) {   // CryptedBin
  2194.       foreach($cfg['aes'] as $aes => $var) {
  2195.        $d = $c.str_repeat("\0",16 - strlen($c) % 16);
  2196.        if($aes == 'openssl')
  2197.         $d = openssl_decrypt($d, "AES-256-ECB", $pass[0], OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING);
  2198.        elseif($aes == 'mycrypt')
  2199.         $d = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $pass[0], $d, MCRYPT_MODE_ECB, substr($d,0,16));
  2200.        elseif($aes == 'aes5')
  2201.         $d = eval('$d = new PhpAes\Aes($pass[0], "ECB"); return $d->decrypt($d);');
  2202.        elseif($aes == 'aes4') {
  2203.         $f = new Aes($pass[0], "ECB");
  2204.         $d = $f->decrypt($d);
  2205.        }
  2206.        $f = -1;                         // Workaround f�r strrpos
  2207.        while($e = strpos($d,"AVM\0",$f + 1))
  2208.         $f = $e;
  2209.        if($aes and $f > 0) {                    // $f = strrpos($d,"AVM\0")
  2210.         $c = substr($d,4,hexdec(bin2hex(substr($d,$f + 12,4))));
  2211.         $b = str_replace('CRYPTED','',$b);
  2212.         break;
  2213.        }
  2214.       }
  2215.      }
  2216.      elseif(preg_match_all('/\${4}\w+(?="|$)/',$c,$var,PREG_OFFSET_CAPTURE))
  2217.       for($d=count($var[0])-1; $d >= 0; $d--)
  2218.        $c = substr_replace($c,call_user_func(__FUNCTION__,$var[0][$d][0],$pass),$var[0][$d][1],strlen($var[0][$d][0]));
  2219.       $data = substr_replace($data,$b.preg_replace('/.{80}/',"\$0\n",($match[3][$a][0] == 64) ? base64_encode($c) : strtoupper(bin2hex($c))),$match[0][$a][1],strlen($match[0][$a][0]));
  2220.     }
  2221.    }
  2222.    return $data;
  2223.   }
  2224.   else
  2225.    return errmsg('4:Falsches Konfig-Kennwort',__FUNCTION__);
  2226.  }
  2227.  elseif(!$data) {                       // AES init
  2228.   if(!ifset($cfg['php'][5])) {
  2229.    ob_start();
  2230.    phpinfo();
  2231.    if(preg_match('/^Configuration File.*?=>\s*(.*)$/m',ob_get_contents(),$array))
  2232.     $cfg['php'][5] = $array[1];
  2233.    ob_end_clean();
  2234.   }
  2235.   $ext = array();
  2236.   foreach(array(
  2237.     'openssl' =>    array('ext' => 1, 'min' => 5.4,         'func'  => 'openssl_decrypt',   'preg' => '/\b(php_)?openssl\.(so|dll)/i'),
  2238.     'mcrypt' => array('ext' => 1,               'func'  => 'mcrypt_decrypt',    'preg' => '/\b(php_)?mcrypt\.(so|dll)/i'),
  2239.     'mhash' =>  array('ext' => 1,       'max' => 5.1,   'func'  => 'mhash',     'preg' => '/\b(php_)?mhash\.(so|dll)/i'),
  2240.     'zlib' =>   array('ext' => 1,               'func'  => 'gzread',        'preg' => '/\b(php_)?zlib\.(so|dll)/i'),
  2241.     'bzip2' =>  array('ext' => 1,               'func'  => 'bzread',        'preg' => '/\b(php_)?bz2\.(so|dll)/i'),
  2242.     'mysqli' => array('ext' => 1, 'min' => 5.0,         'obj'   => 'mysqli',        'preg' => '/\b(php_)?mysqli\.(so|dll)/i'),
  2243.     'sqlite3' =>    array('ext' => 1, 'min' => 5.3,         'obj'   => 'SQLite3',       'preg' => '/\b(php_)?sqlite3\.(so|dll)/i'),
  2244.     'aes5' =>   array('php' => 1, 'min' => 5.3, 'max' => 8.11,  'obj'   => 'PhpAes\Aes',    'preg' => '/\baes\.php/i'),
  2245.     'aes4' =>   array('php' => 1,       'max' => 7.1,   'obj'   => 'Aes',       'preg' => '/\baes_?4.*?\.php/i'),
  2246.     'sha256' => array('php' => 1,       'max' => 5.2,   'func'  => 'sha256',        'preg' => '/\bsha.?256\.php/i'),
  2247.     'sha512' => array('php' => 1,       'max' => 5.2,   'func'  => 'sha512',        'preg' => '/\bsha.?512\.php/i'),
  2248.     'hashtool' =>   array('php' => 1,       'max' => 5.6,   'func'  => 'hash_pbkdf2',   'preg' => '/\bhashtool\.php/i')) as $key => $var)
  2249.    if(!isset($ext[$key]) and (!$pass or $pass == 'aes' or strstr($pass,$key))
  2250.     and ($pass and $pass != 'aes' and strstr($pass,$key) or (!isset($var['min']) or $cfg['php'][3] >= $var['min']) and (!isset($var['max']) or $cfg['php'][3] < $var['max']))
  2251.     and ((isset($var['ext']) and ((isset($var['func']) and $val = function_exists($var['func']) or isset($var['obj']) and $val = class_exists($var['obj']))
  2252.     or @ini_get('enable_dl') and (defined('PHP_BINARY') and $val = listDir($var['preg'],dirname(PHP_BINARY),1)
  2253.     or $cfg['php'][5] and $val = listDir($var['preg'],dirname($cfg['php'][5]),1) or $val = listDir($var['preg'],realpath(@ini_get('extension_dir')),1))))
  2254.     or (isset($var['php']) and ((isset($var['func']) and $val = function_exists($var['func']) or isset($var['obj']) and $val = class_exists($var['obj']))
  2255.     or $val = listDir($var['preg'],$cfg['fbtl'],1)))) and (is_bool($val) or $val = ifset($val,$var['preg']))) {
  2256.     if(is_array($val)) {
  2257.      $val = array_values($val);
  2258.      if(isset($var['ext'])) {
  2259.       if(realpath(@ini_get('extension_dir')) != dirname($val[0]))
  2260.        @ini_set('extension_dir',dirname($val[0]));
  2261.       @dl(basename($val[0]));
  2262.      }
  2263.      if(isset($var['php']))
  2264.       include_once $val[0];
  2265.     }
  2266.     if(isset($var['func']) and function_exists($var['func']) or isset($var['obj']) and class_exists($var['obj'])) { // Erweiterung einrichten
  2267.      $ext[$key] = (is_array($val)) ? ((count($val) > 1) ? $val : $val[0]) : $val;
  2268.      dbug($key." nachgeladen",9);
  2269.     }
  2270.    }
  2271.   if($pass == 'openssl' and $ext['openssl'] = (defined('OPENSSL_VERSION_TEXT')) ? OPENSSL_VERSION_TEXT : ((defined('OPENSSL_NO_PADDING')) ? "OpenSSL 0.9x" : false)) {
  2272.    if(substr($cfg['head']['User-Agent'],-1) == ' ')
  2273.     $cfg['head']['User-Agent'] .= $ext['openssl'];
  2274.    $cfg['osn'] = ($var = ifset($ext['openssl'],'/[\d.]+/')) ? (float)$var[0] : false;
  2275.   }
  2276.   if(isset($cfg['aes']))
  2277.    $cfg['aes'] = array_merge($cfg['aes'],$ext);
  2278.   foreach($ext as $key => $var)
  2279.    if(!isset($cfg['mods'][$key]))
  2280.     $cfg['mods'][$key] = $var;
  2281.   return ($pass == 'aes') ? preg_array('/aes\d+|openssl|mcrypt/',$ext,3) : ((count($ext) == 1 and isset($ext[$pass])) ? $ext[$pass] : $ext);
  2282.  }
  2283.  else
  2284.   return $pass ? errmsg('16:Keine Konfig-Datei',__FUNCTION__) : false;
  2285. }
  2286. function konfig2array($data) {              // FRITZ!Box-Konfig -> Array
  2287.  $config = array();
  2288.  if($data[0] == '*')
  2289.   dbug("Konvertiere Fritz!Konfig...");
  2290.  if($data[0] == '*' and preg_match_all('/^(?:\*{4}\s(.*?)\sCONFIGURATION\sEXPORT|(\w+)=(\S+))\s*$
  2291.     |^\*{4}\s(?:CRYPTED)?(CFG|BIN|B64)FILE:(\S+)\s*?\r?\n(.*?)\r?\n^\*{4}\sEND\sOF\sFILE\s\*{4}\s*?($)/msx',$data,$array)) {
  2292.   dbug($array,4,'Konfig2Array-#');          // Debugdaten Speichern
  2293.   foreach($array[4] as $key => $var)
  2294.    if($array[1][$key])                  // Routername
  2295.     $config['Name'] = $array[1][$key];
  2296.    elseif($array[2][$key])              // Variablen
  2297.     $config[$array[2][$key]] = $array[3][$key];
  2298.    elseif(ifset($array[4][$key],'B64'))         // Base64 Data
  2299.     $config[$array[5][$key]] = base64_decode($array[6][$key]);
  2300.    elseif(ifset($array[4][$key],'BIN'))         // Bin Data
  2301.     $config[$array[5][$key]] = pack('H*',preg_replace('/[^\da-f]+/i','',$array[6][$key]));
  2302.    elseif(ifset($array[4][$key],'CFG') and preg_match_all('/^(\w+)\s(\{\s*$.*?^\})\s*$/smx',
  2303.     str_replace(array("\r","\\\\"),array("","\\"),$array[6][$key]),$match)) // CfgData
  2304.     foreach($match[1] as $k => $v)
  2305.      $config/*[$array[5][$key]]*/[$v] = call_user_func(__FUNCTION__,$match[2][$k]);
  2306.   dbug($config,4,'Konfig2Array');           // Debugdaten Speichern
  2307.  }
  2308.  elseif($data[0] == '{' and preg_match_all('/\{\s*?$.*?^\}/msx',$data,$array)) {
  2309.   dbug($array,4,'Konfig2Array-Multi-#');        // Debugdaten Speichern
  2310.   if(count($array[0]) > 1)              // Ein oder Multi-Array
  2311.    foreach($array[0] as $var)               // Weitere Matches auf selber Ebene
  2312.     $config[] = call_user_func(__FUNCTION__,$var);
  2313.   elseif(preg_match_all('/^\s{8}(?:(\w+)\s(?:=\s(?:([^\s"]+)|(".*?(?<!\\\\)"(?:,\s*)?));|(\{\s*$.*?^\s{8}\}))\s*($))$/msx',$data,$match)) {
  2314.    dbug($match,4,'Konfig2Array-Sub-#');         // Debugdaten Speichern
  2315.    foreach($match[1] as $key => $var)           // Array durch arbeiten
  2316.     if($match[2][$key])                 // Einfache Werte
  2317.      $config[$var] = ($match[2][$key] == 'yes') ? true  : (($match[2][$key] == 'no') ? false : ((ifset($match[2][$key],'/^\d+(\.\d+)?$/')) ? (int)($match[2][$key]) : $match[2][$key]));
  2318.     elseif($match[3][$key] and preg_match_all('/"(.*?)(?<!\\\\)"/',$match[3][$key],$val))   // String(s)
  2319.      $config[$var] = str_replace('\"','"',(count($val[1]) > 1) ? $val[1] : $val[1][0]);
  2320.     elseif($match[4][$key])             // Verschachteltes Array
  2321.      $config[$var] = call_user_func(__FUNCTION__,preg_replace('/^\s{8}/m','',$match[4][$key]));
  2322.   }
  2323.  }
  2324.  else
  2325.   return errmsg('16:Keine Konfig-Datei',__FUNCTION__);
  2326.  return $config;
  2327. }
  2328. function showaccessdata($data) {            // Die Kronjuwelen aus Konfig-Daten heraussuchen
  2329.  if(is_array($data))
  2330.   return chr(intval($data[1],8));
  2331.  $text = '';
  2332.  $config = array();
  2333.  if($konfig = konfig2array($data)) {            // Konfig als Array umwandeln
  2334.   dbug("Stelle Zugangsdaten zusammen...");
  2335.   $access = array(
  2336.    'Mobile-Stick'       => array(&$konfig['ar7cfg']['serialcfg'],'=number,provider,username,passwd'),
  2337.    'DSL'            => array(&$konfig['ar7cfg']['targets'],'-name,>local>username,>local>passwd'),
  2338.    'IPv6'           => array(&$konfig['ipv6']['sixxs'],'=ticserver,username,passwd,tunnelid'),
  2339.    'DynamicDNS'         => array(&$konfig['ddns']['accounts'],'=domain,username,passwd'),
  2340.    'MyFRITZ!'           => array(&$konfig['jasonii'],'=user_email,user_password,box_id,box_id_passphrase,dyn_dns_name'),
  2341.    'FRITZ!Box-Oberfl�che' => array(&$konfig['webui'],'=username,password'),
  2342.    'Fernwartung'        => array(&$konfig['websrv']['users'],'=username,passwd'),
  2343.    'GUI-Unterordner'        => array(&$konfig['websrv.subfolder']['=name,passwd']),
  2344.    'TR-064'         => array(&$konfig['TR_064'],'=username,password'),
  2345.    'TR-069-Fernkonfiguration'   => array(&$konfig['tr069cfg']['igd']['managementserver'],'=url,username,password,ConnectionRequestUsername,ConnectionRequestPassword'),
  2346.    'Diagnose/Wartung'       => array(&$konfig['tr069cfg']['lab'],'=CRUsername,CRPassword','+username,password,domain_name,update_url'),
  2347.    'Netzwerkumgebung'       => array(&$konfig['landevices']['landevices'],'-ip,name,neighbour_name,remotelogin_username,remotelogin_password'),
  2348.    'Telekom-Mediencenter'   => array(&$konfig['t_media'],'=refreshtoken,accesstoken'),
  2349.    'Google-Play-Music'      => array(&$konfig['gpm'],'=emailaddress,password,partition,servername'),
  2350.    'Onlinespeicher'     => array(&$konfig['webdavclient'],'=host_url,username,password'),
  2351.    'WLAN'           => array(&$konfig['wlancfg'],'/^(((guest|sta)_)?(ssid(_(scnd|thrd))?|pskvalue)|(sta_)?key_value\d|wps_pin|wds_(key|ssid))$/i'),
  2352.    'Push-Dienst'        => array(&$konfig['emailnotify'],'=From,To,SMTPServer,accountname,passwd','+To,arg0'),
  2353.    'DECT-eMail'         => array(&$konfig['configd'],'!<\?xml.*?<list>.*?<email>.*?<pool>(.*?)</pool>!s','!((name)|user_name|(?:smtp_)?server|user|pass|uipin|port)="([^"]+)"!s'),
  2354.    'FRITZ!Box-Benutzer'     => array(&$konfig['boxusers']['users'],'-name,email,passwd,password,googleauth_sharedsecret,googleauth_devicename'),
  2355.    'Apps'           => array(&$konfig['apps']['apps'],'-displayname,username,password,id,appavmaddress'),
  2356.    'Apps2'          => array(&$konfig['apps'],'=box_senderid,enc_secret,box_auth_id,box_auth_pwd'),
  2357.    'InternetTelefonie'      => array(&$konfig['voipcfg'],'_name,username,authname,passwd,registrar,stunserver,stunserverport,gui_readonly'),
  2358.    'IP-Telefon'         => array(&$konfig['voipcfg']['extensions'],'-extension_number,username,authname,passwd,clientid'),
  2359.    'Online-Telefonbuch'     => array(&$konfig['voipcfg']['onlinetel'],'-pbname,url,serviceid,username,passwd,refreshtoken,accesstoken'),
  2360.    'FRITZ!NAS Share'        => array(&$konfig['usbhost.filelinks'],'-id,path'),
  2361.    'Virtual-Privat-Network' => array(&$konfig['vpncfg']['connections'],'-name,>localid<fqdn,>remoteid<fqdn,>localid<user_fqdn,>remoteid<user_fqdn,key,>xauth>username,>xauth>passwd'),
  2362.    'WireGuard-Interface'    => array(&$konfig['vpncfg']['global'],'/^wg_(private_key|public_key|listen_port)$/i'),
  2363.    'WireGuard-Peer:'        => array(&$konfig['vpncfg']['connections'],'-name,wg_public_key,wg_preshared_key'),
  2364.    'Tickets'            => array(&$konfig['usercfg']['valid_tickets'],'-#ticket'),
  2365.   );
  2366.   foreach($access as $key => $var)      // Accessliste durcharbeiten
  2367.    if(ifset($var[0])) {
  2368.     if($var[1][0] == '/') {         // Regul�re Ausdr�cke verwenden (Schl�sselname)
  2369.      foreach($var[0] as $k => $v)
  2370.       if(preg_match($var[1],$k) and $var[0][$k])// Schl�ssel Suchen und Pr�fen
  2371.        $config[$key][$k] = $var[0][$k];
  2372.     }
  2373.     elseif($var[1][0] == '!' and preg_match($var[1],$var[0],$val) and preg_match_all($var[2],$val[1],$val)) {   // Regul�re Ausdr�cke verwenden (Inhalt)
  2374.      foreach($val[3] as $k => $v)
  2375.       if(ifset($val[2][$k]))
  2376.        $name = $v;
  2377.       else
  2378.        $config[$key][$name][$val[1][$k]] = $v;
  2379.     }
  2380.     elseif($var[1][0] == '=') {         // Normal abfragen
  2381.      $keys = explode(',',substr($var[1],1));
  2382.      foreach($keys as $k)
  2383.       if(ifset($var[0][$k]))            // Schl�ssel Testen
  2384.        $config[$key][$k] = $var[0][$k];
  2385.     }
  2386.     if(preg_match('/^([-+_])(.+)$/',$var[(isset($var[2])) ? 2 : 1],$keys)) {    // Eine Schl�ssel-Ebene �berspringen
  2387.      if($keys[1] == '-' and count(array_filter(array_keys($var[0]),'is_string')) > 0)
  2388.       $var[0] = array($var[0]);
  2389.      $keys[3] = explode(',',$keys[2]);
  2390.      foreach($var[0] as $k => $v)
  2391.       if((preg_match('/\d+\s*$/',$k,$val) or $keys[1] == '+') and is_array($v)) {   // Neue Ebene gefunden
  2392.        $name = $val ? false : $k;
  2393.        foreach($keys[3] as $val)
  2394.         if($val[0] == '>' and preg_match('/(\w+)([<>])(\w+)/',$val,$va1) and ifset($var[0][$k][$va1[1]][$va1[3]]))  // Mit Regul�re Ausdr�cke noch eine Ebene �berspringen
  2395.          if($name === false)
  2396.           $name = (string)$var[0][$k][$va1[1]][$va1[3]];
  2397.          else
  2398.           $config[$key][$name][(($va1[2] == '<') ? $va1[1] : $va1[3])] = $var[0][$k][$va1[1]][$va1[3]]; // Den Vorigen Schl�ssel verwenden?
  2399.         elseif($val[0] == '#' and ifset($var[0][$k][$kk = substr($val,1)])) {   // Ketten-Werte
  2400.          if(!isset($config[$key][$kk]))                     // Objekt schon vorhanden
  2401.           $config[$key][$kk] = array();                     // Leere Kette anlegen
  2402.          $config[$key][$kk][] = $v[$kk];                    // Kettenglied dranh�ngen
  2403.         }
  2404.         elseif(ifset($var[0][$k][$val]))        // Auf der neuen Ebene Pr�fen
  2405.          if($name === false)
  2406.           $name = (string)$var[0][$k][$val];
  2407.          else
  2408.           $config[$key][$name][$val] = $var[0][$k][$val];
  2409.       }
  2410.     }
  2411.    }
  2412.   dbug($config,4,'ShowAccessData');         // Alle Fundst�cke ungefiltert sichern
  2413.   foreach($config as $key => $var)          // Filter: Doppelte Kategorien zusammenfassen
  2414.    if($val = ifset($key,'/^([\w-]+)\d+$/') and isset($config[$val[1]])) {
  2415.     $config[$val[1]] = array_merge($config[$val[1]],$var);
  2416.     unset($config[$key]);
  2417.    }
  2418.   if(ifset($config['InternetTelefonie']))       // Filter: StunServerPort 3478 filtern
  2419.    foreach($config['InternetTelefonie'] as $key => $var)
  2420.     if(ifset($var['stunserverport'],3478))
  2421.      unset($config['InternetTelefonie'][$key]['stunserverport']);
  2422.   if(ifset($config['IPv6']) and ifset($config['IPv6']['ticserver']) and count($config['IPv6']) == 1)    // Filter: IPv6 tivserver
  2423.    unset($config['IPv6']);
  2424.   if(ifset($config['TR-069-Fernkonfiguration']) and ifset($config['TR-069-Fernkonfiguration']['url']) and count($config['TR-069-Fernkonfiguration']) == 1)  // Filter: TR069 url
  2425.    unset($config['TR-069-Fernkonfiguration']);
  2426.   if(ifset($config['Mobile-Stick']) and ifset($config['Mobile-Stick']['username'],'ppp') and ifset($config['Mobile-Stick']['passwd'],'ppp'))    // Filter: Surf-Stick ppp
  2427.    unset($config['Mobile-Stick']);
  2428.   if(ifset($config['Onlinespeicher']) and !ifset($config['Onlinespeicher']['password']))        // Filter: Onlinespeicher
  2429.    unset($config['Onlinespeicher']);
  2430.   if(ifset($config['DECT-eMail']))                                  // Filter: DECT-eMail
  2431.    foreach($config['DECT-eMail'] as $key => $var) {
  2432.     if(ifset($var['server']) and ifset($var['port'])) { // Server & Port zusammenf�hren
  2433.      $config['DECT-eMail'][$key]['server'] .= ":$var[port]";
  2434.      unset($config['DECT-eMail'][$key]['port']);
  2435.     }
  2436.     if(ifset($var['user'],$key))            // Doppelte Namen
  2437.      unset($config['DECT-eMail'][$key]['user']);
  2438.     if(ifset($var['user_name'],$key))
  2439.      unset($config['DECT-eMail'][$key]['user_name']);
  2440.    }
  2441.   if(ifset($config['Netzwerkumgebung']))                                // Filter: Netzwerkumgebung
  2442.    foreach($config['Netzwerkumgebung'] as $key => $var) // Hosts ohne Kennwort
  2443.     if(!ifset($var['remotelogin_password']))
  2444.      unset($config['Netzwerkumgebung'][$key]);
  2445.   if(ifset($config['TR-064']) and !ifset($config['TR-064']['password']))                // Filter: TR-064
  2446.    unset($config['TR-064']);
  2447.   if(is_null($config['TR-069-Fernkonfiguration']))                          // Filter: TR-069
  2448.    unset($config['TR-069-Fernkonfiguration']);
  2449.   elseif(is_null($config['TR-069-Fernkonfiguration']['url']))                       // Filter: TR-069
  2450.    unset($config['TR-069-Fernkonfiguration']['url']);
  2451.   if(isset($config['WLAN']))                                        // Filter: WLAN
  2452.    foreach(array('','WDS_','STA_') as $key)
  2453.     if(isset($config['WLAN'][$key."ssid"])) {       // Doppelte SSID
  2454.      if(isset($config['WLAN'][$key."ssid_thrd"]) and ($config['WLAN'][$key."ssid"] == $config['WLAN'][$key."ssid_thrd"]
  2455.     or isset($config['WLAN'][$key."ssid_scnd"]) and $config['WLAN'][$key."ssid_thrd"] == $config['WLAN'][$key."ssid_scnd"]))
  2456.       unset($config['WLAN'][$key."ssid_thrd"]);
  2457.      if(isset($config['WLAN'][$key."ssid_scnd"]) and $config['WLAN'][$key."ssid"] == $config['WLAN'][$key."ssid_scnd"])
  2458.       unset($config['WLAN'][$key."ssid_scnd"]);
  2459.      if($key)
  2460.       foreach(array('ssid','key','pskvalue') as $var)   // Doppelte Kennw�rter
  2461.        if(isset($config['WLAN'][$var]) and isset($config['WLAN'][$key.$var]) and $config['WLAN'][$var] == $config['WLAN'][$key.$var]
  2462.     or isset($config['WLAN']['pskvalue']) and isset($config['WLAN'][$key.$var]) and $config['WLAN']['pskvalue'] == $config['WLAN'][$key.$var])
  2463.         unset($config['WLAN'][$key.$var]);
  2464.     }
  2465.   $a = array('/^\${4}\w+/','(Verschl�sselt)');                                // Verschl�sselte Eintr�ge umschreiben
  2466.   foreach($config as $key => $var)
  2467.    if($var) {
  2468.     if($val = preg_array($a[0],$var,3)) {   // Array-Schl�ssel umbennenen
  2469.      foreach($val as $k => $v) {
  2470.       $config[$key][] = $v;
  2471.       unset($config[$key][$k]);
  2472.      }
  2473.      $var = $config[$key];
  2474.     }
  2475.     foreach($var as $k => $v)
  2476.      if(is_array($v)) {             // Unterwert umschreiben
  2477.       foreach($v as $kk => $vv)
  2478.        if(ifset($vv,$a[0]))
  2479.         $config[$key][$k][$kk] = $a[1];
  2480.      }
  2481.      elseif(ifset($v,$a[0]))            // Hauptwert umschreiben
  2482.       $config[$key][$k] = $a[1];
  2483.    }
  2484.   foreach($config as $name => $keys)                                    // Array in Text Umwandeln
  2485.    if($keys) {
  2486.     foreach($keys as $key => $data) {
  2487.      if(is_array($data) and array_values($data) !== $data)                      // Assoc-Array
  2488.       foreach($data as $k => $v)
  2489.        $data[$k] = "$k=$v";
  2490.      $keys[$key] = "|$key|->|".str_replace('|','\|',implode(', ',(array)$data));
  2491.     }
  2492.     $text .= "\n$name\n".textTable(implode("\n",$keys))."\n";
  2493.    }
  2494.  }
  2495.  else
  2496.   dbug("showaccessdata fehlgeschlagen");
  2497.  return preg_replace_callback('/\\\\([0-7]{3})/',__FUNCTION__,$text);                   // Zum Schluss noch Oktale-Ansi-Zeichen decodieren
  2498. }
  2499. function getevent($filter='aus',$sid=0) {       // Ereignisse abrufen
  2500.  global $cfg;
  2501.  $filters = array('aus','system','internet','telefon','wlan','usb');
  2502.  $jfilter = array('all','sys','net','fon','wlan','usb');
  2503.  $filter = (($var = ifset($filters,$filter)) !== false) ? $var : 0;
  2504.  dbug("Hole Ereignisse (Filter: {$filters[$filter]})");
  2505.  if(!$sid)
  2506.   $sid = $cfg['sid'];
  2507.  $sid = (!is_bool($sid)) ? "&sid=$sid" : '';
  2508.  if($cfg['fiwa'] < 500)
  2509.   $data = request('POST-array','/cgi-bin/webcm',"getpage=../html/de/system/ppSyslog.html&logger:settings/filter=$filter$sid");
  2510.  elseif($cfg['fiwa'] < 669)
  2511.   $data = request('GET-array',"/system/syslog.lua?tab={$filters[$filter]}&event_filter=$filter&stylemode=print$sid");
  2512.  $array = array(); // Date,Time,Text,Code,View,Help
  2513.  if(ifset($data) and preg_match('!\["[\w:/]+log_separate"\]\s*=\s*\{((\s*\[\d+\]\s*=\s*\{(\s*\[\d+\]\s*=\s*".*?",?)+\s*\},?)+)\s*\}!',$data[1],$code)
  2514.     and preg_match_all('!\s*\[(\d+)\]\s*=\s*\{((\s*\[\d+\]\s*=\s*".*?",?)+)\s*\}!',$code[1],$lines)) {
  2515.   foreach($lines[2] as $key => $line)
  2516.    if(preg_match_all('/"(.*?)(?<!\\\\)"/',$line,$cols))
  2517.     $array[] = $cols[1];
  2518.  }
  2519.  elseif(ifset($data) and preg_match_all(($cfg['fiwa'] < 500) ? '!<p class="log">(\S*)\s*(\S*)\s*(.*?)</p>!'
  2520.     : '!<tr><td[^>]*>(?:<div>)?(.*?)(?:</div>)?</td><td[^>]*>(.*?)</td><td[^>]*><a[^>]*?href="(.*?(\d+)\.html?)"[^>]*?>(.*?)</a></td></tr>!',$data[1],$lines)) {
  2521.   if(count($lines) < 5)
  2522.    foreach($lines[3] as $key => $line)
  2523.     $array[] = array(0 => $lines[1][$key], 1 => $lines[2][$key], 2 => $line);
  2524.   else
  2525.    foreach($lines[5] as $key => $line)
  2526.     $array[] = array(0 => $lines[1][$key], 1 => $lines[2][$key], 2 => $line, 3 => $lines[4][$key], 5 => $lines[3][$key]);
  2527.  }
  2528.  elseif($cfg['fiwa'] >= 669 and $data = request('POST-array','/data.lua',"xhr=1$sid&lang=de&page=log&xhrId=log&filter=".(($cfg['fiwa'] < 739) ? $filter : $jfilter[$filter])."&no_sidrenew=") and $js = json2array($data[1]) and $log = ifset($js['data']['log'],true)) {
  2529.   $group = array_flip($jfilter);
  2530.   foreach($log as $key => $var) {
  2531.    $var = preg_replace('/sid=[\da-f]+&|[?&]sid=[\da-f]+$|\\\\(?=\/)/','',$var);
  2532.    $array[] = ($cfg['fiwa'] >= 739)
  2533.     ? array($var['date'],$var['time'],$var['msg'],$var['id'],$group[$var['group']],$var['helplink'])
  2534.     : $var;
  2535.   }
  2536.  }
  2537.  else {
  2538.   if(ifset($data))
  2539.    dbug($data,4,'GetEvent-data');
  2540.   return errmsg("8:Keine Ereignisse bekommen".(($var = errmsg(0,'request')) ? " ($var)" : ""),__FUNCTION__);
  2541.  }
  2542.  $event = array();
  2543.  $a = count($array);
  2544.  $b = 1;
  2545.  while($a)
  2546.   $event[strtotime("20".implode('-',array_reverse(explode('.',$array[--$a][0])))." ".$array[$a][1]).".".$b++] = $array[$a];
  2547.  dbug($event,4,'GetEvent_array');
  2548.  return $event;
  2549. }
  2550. function getcall($mode='call',$sid=0) {         // Anrufliste auslesen (mode: array,call,data)
  2551.  global $cfg;
  2552.  if(!$sid)
  2553.   $sid = $cfg['sid'];
  2554.  if($cfg['fiwa'] > 530 and $data = request('get','/fon_num/foncalls_list.lua',"sid=$sid&apply=&csv=")   // Download der Anrufliste
  2555.     or $data = request('get','/cgi-bin/webcm',"getpage=../html/de/FRITZ!Box_Anrufliste.csv&sid=$sid")) {
  2556.   $sep = (preg_match('/^sep=(.+)/',$data[1],$var)) ? $var[1] : ';';
  2557.   $psep = preg_quote($sep,'/');
  2558.   if(preg_match_all("/^".($preg = "([0-4]$psep((0[1-9]|[12]\d|3[10])\.(0[1-9]|1[0-2])\.(?:20)?(\d\d)\s+([\d:]+)|[\w .:\/+-]+)($psep(.*?)){4,5})\s*$/")."m",$data[1],$array)) {
  2559.    dbug($array,4);
  2560.    if($mode == 'data')
  2561.     return $data[1];
  2562.    foreach($array as $key => $var)  // Komplette Matchliste umdrehen
  2563.     $array[$key] = array_reverse($var);
  2564.    $call = array();
  2565.    foreach($array[1] as $key => $var)
  2566.     if($time = strtotime(($array[3][$key]) ? "20{$array[5][$key]}-{$array[4][$key]}-{$array[3][$key]} {$array[6][$key]}" : $array[2][$key]))
  2567.      $call["$time.$key"] = preg_split("/(?<!\\\\)$psep/",$var);
  2568.    if($mode == 'call')
  2569.     return $call;
  2570.    return array('sep' => $sep, 'csv' => preg_replace('/\d[\s\S]*$/','',$data[1]), 'call' => $call, 'data' => $data[1]);
  2571.   }
  2572.   else
  2573.    return errmsg("8:Keine Anrufliste bekommen",__FUNCTION__);
  2574.  }
  2575.  else
  2576.   return errmsg("8:Anforderung der Anrufliste fehlgeschlagen".(($var = errmsg(0,'request')) ? " ($var)" : ""),__FUNCTION__);
  2577. }
  2578. function gettraffic($sid=0) {               // Traffic-Z�hler als array auslesen
  2579.  global $cfg;
  2580.  if(!$sid)
  2581.   $sid = $cfg['sid'];
  2582.  $out = array();
  2583.  dbug("Hole Traffic-Daten ",0,2);
  2584.  if($cfg['fiwa'] < 550  // Fritz!OS 4 - 5.49
  2585.     and $rp = request('GET','/cgi-bin/webcm',"getpage=../html/de/menus/menu2.html&var:lang=de&var:pagename=inetstat&var:menu=home&var:tabInetstat=1&sid=$sid")
  2586.     and preg_match_all('/(?:^\s*(?:var\s)?(?:time|v?(?:in|out)[hl]|ap2ap)\s*=\s*[^;]*;\s*)+SetRow\(.*?\);|^\s*(?:var\s)?(?:max|rec|sent)(?:low|high)\s*=\s*\d*;/sm',$rp,$array)) {
  2587.   dbug("f�r OS 4 - 5.49");
  2588.   dbug($array,4);
  2589.   foreach($array[0] as $line)
  2590.    if(preg_match('/(time)\s=*\s*(\d*).*?SetRow\("(\w+)"/s',$line,$var)) {
  2591.     $key = $var[3];
  2592.     $out[$key][$var[1]] = intval($var[2]);
  2593.     if(preg_match('!<span\s*id="span'.$key.'\w+">.*?</span></td>\s*<td\s*class="c23">(\d*)</td>!',$rp,$var))
  2594.      $out[$key]['connect'] = intval($var[1]);
  2595.     if(preg_match_all('/(in|out)([hl])\s*=\s*(\d*);/',$line,$m))
  2596.      foreach($m[3] as $k => $v) {
  2597.       if(!isset($out[$key][$m[1][$k]]))
  2598.        $out[$key][$m[1][$k]] = 0;
  2599.       $out[$key][$m[1][$k]] += ($m[2][$k] == 'h') ? pow(2,32) * intval($v) : intval($v);
  2600.      }
  2601.     $out[$key]['sum'] = $out[$key]['in'] + $out[$key]['out'];
  2602.    }
  2603.    elseif(preg_match('/(\w+?)(low|high)\s*=\s*(\d*);/',$line,$m)) { // Online-Z�hler (Traffic)
  2604.     if(!isset($out['Counter'][$m[1]]))
  2605.      $out['Counter'][$m[1]] = 0;
  2606.     $out['Counter'][$m[1]] += ($m[2] == 'high') ? pow(2,32) * intval($m[3]) : intval($m[3]);
  2607.    }
  2608.   if(preg_match_all('!^\s*(?:var\s)?(cur|max)\s*=\s*Math.ceil\((\d+)/60\);!m',$rp,$m)) {
  2609.    dbug($m,4);
  2610.    $array = array('max' => 'maxtime', 'cur' => 'time');
  2611.    foreach($m[1] as $key => $var)
  2612.     if($m[2][$key])
  2613.      $out['Counter'][$array[$var]] = floor(intval($m[2][$key]) / 60);
  2614.   }
  2615.   $out['Counter']['sum'] = $out['Counter']['rec'] + $out['Counter']['sent'];
  2616.  }
  2617.  elseif($cfg['fiwa'] >= 550 and $cfg['fiwa'] < 650 and $rp = request('GET','/internet/inetstat_counter.lua',"sid=$sid") and preg_match_all('!\["inetstat:status/(\w+)/(\w+)"\]\s*=\s*"(\d*)",!',$rp,$m)) {  // OS 5.50 - 6.49
  2618.   dbug("f�r OS 5.50 - 6.49");
  2619.   dbug($m,4);
  2620.   $array = array('BytesReceived' => 'in', 'BytesSent' => 'out', 'OutgoingCalls' => 'connect', 'PhyConnTimeOutgoing' => 'time');
  2621.   foreach($m[3] as $key => $var)
  2622.    if(preg_match('/^(.*?)((High)|Low)$/',$m[2][$key],$x)) {
  2623.     if(!isset($out[$m[1][$key]][$array[$x[1]]]))
  2624.      $out[$m[1][$key]][$array[$x[1]]] = 0;
  2625.     $out[$m[1][$key]][$array[$x[1]]] += (isset($x[3])) ? pow(2,32) * $var : $var;
  2626.    }
  2627.    else
  2628.     $out[$m[1][$key]][$array[$m[2][$key]]] = $var;
  2629.   foreach($out as $key => $var)
  2630.    $out[$key]['sum'] = $out[$key]['in'] + $out[$key]['out'];
  2631.   dbug("Hole Budget-Z�hler");
  2632.   if($rp = request('GET','/internet/inetstat_budget.lua',"sid=$sid") and preg_match_all('!\["(?:inetstat:status/ThisMonth|connection\d:settings/Budget)/(\w+?)(Low|High)?"\]\s*=\s*"(\d*)",!',$rp,$m)) {
  2633.    dbug($m,4);
  2634.    $array = array('ConnectionTime' => 'maxtime', 'Volume' => 'max', 'BytesReceived' => 'rec', 'BytesSent' => 'sent', 'PhyConnTimeOutgoing' => 'time');
  2635.    foreach($m[3] as $key => $var)
  2636.     if(preg_match('/^((High)|Low)$/',$m[2][$key],$x)) {
  2637.      if(!isset($out['Counter'][$array[$m[1][$key]]]))
  2638.       $out['Counter'][$array[$m[1][$key]]] = 0;
  2639.      $out['Counter'][$array[$m[1][$key]]] += (isset($x[3])) ? pow(2,32) * $var : $var;
  2640.     }
  2641.     elseif(isset($array[$m[1][$key]]))
  2642.      $out['Counter'][$array[$m[1][$key]]] = $var;
  2643.    $out['Counter']['sum'] = $out['Counter']['rec'] + $out['Counter']['sent'];
  2644.   }
  2645.  }
  2646.  elseif($cfg['fiwa'] >= 650 and $cfg['fiwa'] < 724 and $rp = request('POST','/data.lua',"xhr=1&sid=$sid&lang=de&no_sidrenew=&page=netCnt") and preg_match_all('!<tr><td[^>]*>[^<>\n]+</td>\s*(?:<td[^>]*>[\d:]+</td>\s*){5}</tr>!x',$rp,$m)) {  // OS 6.50 - 7.23
  2647.   dbug("f�r OS 6.50+");
  2648.   dbug($m,4);
  2649.   $cols = array('label','time','sum','out','in','connect');
  2650.   $rows = array('Today','Yesterday','ThisWeek','ThisMonth','LastMonth');
  2651.   foreach($m[0] as $key => $var)
  2652.    if(preg_match_all('!<td[^>]*>([^<>]+)</td>!',$var,$line))
  2653.     foreach($line[1] as $k => $v)
  2654.      if($k)
  2655.       $out[$rows[$key]][$cols[$k]] = ($k < 5 and $k > 1) ? $v * 1024 * 1024 : (($k == 1 and $x = explode(':',$v)) ? intval($x[0]) * 60 + intval($x[1]) : $v);
  2656.   if(preg_match('!<tr>\s*<td[^>]*>[^<>]*</td>\s*<td[^>]*><div[^>]*>(?:<span[^>]*>\s*</span>)+\s*</div>\s*</td>\s*<td>(?:(\d+)\D+(\d+)\sMB|(\d+)\D+(\d+)\D+(\d+)\D+)</td>\s*</tr>!',$rp,$m)) {
  2657.    dbug($m,4);
  2658.    if($m[2]) {
  2659.     $out['Counter']['sum'] = intval($m[1]) * 1024 * 1024;
  2660.     $out['Counter']['max'] = intval($m[2]) * 1024 * 1024;
  2661.    }
  2662.    else {
  2663.     $out['Counter']['time'] = intval($m[3]) * 60 + intval($m[4]);
  2664.     $out['Counter']['maxtime'] = intval($m[5]) * 60;
  2665.    }
  2666.   }
  2667.  }
  2668.  elseif($cfg['fiwa'] >= 724 and $rp = request('POST','/data.lua',"xhr=1&sid=$sid&lang=de&no_sidrenew=&page=netCnt") and preg_match_all('!<tr[^>]*><td[^>]*>[^<>\n]+</td>\s*(?:<td[^>]*>[\d:\s]+</td>\s*)+</tr>!x',$rp,$m) and preg_match_all('/"(\w+)":\{((?:"\w+":"\d+",?)+)\}/sx',$rp,$n)) {  // OS 7.24+
  2669.   dbug("f�r OS 7.24+");
  2670.   foreach($m[0] as $var)
  2671.    if(preg_match('!<tr id="ui(\w+)">(?:<td[^>]*>(?:(\d+):)?([\w\s]+)</td>\s*){2}(?:<td[^>]*>([\s\d]+)</td>\s*){4}!',$var,$v)) {
  2672.     $out[$v[1]]['time'] = $v[2] * 60 + $v[3];
  2673.     $out[$v[1]]['connect'] = $v[4];
  2674.     $out[$v[1]]['in'] = $out[$v[1]]['out'] = $out[$v[1]]['sum'] = 0;
  2675.    }
  2676.   $cols = array('Sent' => 'out', 'Received' => 'in');
  2677.   foreach($n[2] as $key => $var)
  2678.    if(preg_match_all('/"Bytes(Sent|Received)(High|Low)":"(\d+)"/',$var,$x))
  2679.     foreach($x[1] as $k => $v) {
  2680.      $k = $x[3][$k] * (($x[2][$k] == 'Low') ? 1 : pow(2,32));
  2681.      $out[$n[1][$key]][$cols[$v]] += $k;
  2682.      $out[$n[1][$key]]['sum'] += $k;
  2683.     }
  2684.   if(preg_match('!<tr>\s*<td[^>]*>\w+</td>\s*<td>\s*<div\s*class="meter">\s*<span\sclass="bar\sused\w*"[^>]*></span>\s*<span[^>]*></span>\s*</div>\s*</td>\s*<td>(?:(\d+)\D+(\d+)\sMB|(?:(\d+)\s\w+\s)?(?:(\d+)\s\w+)?\D+(\d+)\s\w+)</td>\s*</tr>!sx',$rp,$v))
  2685.    if($v[1].$v[2]) {
  2686.     $out['Counter']['sum'] = intval($v[1]) * 1024 * 1024;
  2687.     $out['Counter']['max'] = intval($v[2]) * 1024 * 1024;
  2688.    }
  2689.    else {
  2690.     $out['Counter']['time'] = intval($v[3]) * 60 + intval($v[4]);
  2691.     $out['Counter']['maxtime'] = intval($v[5]) * 60;
  2692.    }
  2693.  }
  2694.  else {
  2695.   dbug("- fehlgeschlagen");
  2696.   $out = errmsg("8:Traffic konnte nicht ermittelt werden",__FUNCTION__);
  2697.  }
  2698.  if($out) {
  2699.   $out['Time'] = ($cfg['http']['Date']) ? strtotime($cfg['http']['Date']) : 0;
  2700.   dbug($out,9);
  2701.  }
  2702.  return $out;
  2703. }
  2704. function smarthome($cmd=0,$ain=0,$set=array(),$sid=0) { // SmartHome Ger�teliste, Infos, Schalten (cmd:string/array, ain, set:array, sid)
  2705.  global $cfg;
  2706.  if($cmd == 'temp')                     // temp: Temperatur entschl�sseln
  2707.   $out = ($ain == 0 or $ain == 253) ? "aus" : (($ain == 1 or $ain == 254) ? "an" : (($ain == 2) ? 'um' : ($ain/2)."�C"));
  2708.  elseif($cmd == 'functionbit') {                // functionbit: functionbitmask Entschl�sseln
  2709.   $name = explode(',',"HANFUN Ger�t,Bit1,Lampe,Bit3,Alarm-Sensor,Taster,Heizk�rperregler,Energie Messger�t,Temperatursensor,Schaltsteckdose,"
  2710.     ."AVM DECT Repeater,Mikrofon,Gruppe,HANFUN Unit,Bit14,Schaltbar,Dimmbar,Farblampe");
  2711.   foreach($name as $key => $var) {
  2712.    if($ain % 2)
  2713.     $set[$key] = $var;
  2714.    $ain >>= 1;
  2715.   }
  2716.   return $set;
  2717.  }
  2718.  elseif($cmd == 'template') {
  2719.   foreach($set as $var)
  2720.    if(isset($var['template']))
  2721.     foreach($var['template'] as $val)
  2722.      if($ain == $val['identifier'] or $ain == $val['id'] or strtolower($ain) == strtolower($val['name']))
  2723.       return $val;
  2724.   return false;
  2725.  }
  2726.  elseif($ain === true and is_array($cmd) and !$set) {       // Type STRING aus Array weitgehend in INT/FLOAT umwandeln
  2727.   foreach($cmd as $key => $var)
  2728.    $set[(preg_match('/^\d+$/',$key)) ? intval($key) : $key] = (is_array($var)) ? call_user_func(__FUNCTION__,$var,true)
  2729.     : ((is_string($var) and preg_match('/^(?:(\d{1,7})|((?!0\.0$)\d{1,7}\.\d+))($)/',$var,$val))
  2730.     ? (($val[1] != '') ? intval($var) : (($val[2] != '') ? floatval($var) : $var)) : $var);
  2731.   return $set;
  2732.  }
  2733.  else {
  2734.   dbug(compact(explode(',','cmd,ain,set,sid')),9);
  2735.  
  2736.   if(!$sid)
  2737.    $sid = $cfg['sid'];
  2738.   dbug("Hole SmartHome Ger�teliste");
  2739.   $out = false;
  2740.   $link = '/webservices/homeautoswitch.lua';
  2741.   $parm = "sid=$sid&switchcmd=";
  2742.   $device = array();
  2743.   $hfu = array();
  2744.   if($ain and $set === true and preg_match('/on|off|trip/',$cmd)) { // Force-Modus
  2745.    $do = array('Aktor wurde ausgeschaltet','Aktor wurde eingeschaltet','on' => 'setswitchon', 'off' => 'setswitchoff', 'trip' => 'setswitchtoggle');
  2746.    if($out = request('GET',$link,$parm.$do[$cmd]."&ain=$ain")) {
  2747.     if(ifset($out,'/^\d+$/') and isset($do[(int)$out]))
  2748.      $out = $do[(int)$out];
  2749.    }
  2750.    else
  2751.     $out = "Aktor '$ain' nicht gefunden";
  2752.   }
  2753.   elseif($xml = request('GET',$link,$parm."getdevicelistinfos") and preg_match_all('!<(device|group)\s([^>]+)>(.*?)</\1>!s',preg_replace('/[\r\n]+/','',$xml),$list)) {
  2754.    if($cmd == 'xml')                        // xml: Gebe ROH-Daten zur�ck
  2755.     return $xml;
  2756.    dbug($xml,9);
  2757.    dbug($list,4);
  2758.    foreach($list[2] as $k => $v) {              // Devices und Gruppen durchgehen
  2759.     $device[$k] = xml2array($list[3][$k],false);        // Device Infos einlesen
  2760.     if(preg_match_all('/([\w-]+)="([^"]+)"/',$v,$m))        // Device Attribute einlesen
  2761.      foreach($m[1] as $key => $var)
  2762.       $device[$k][$var] = $m[2][$key];
  2763.     if(ifset($device[$k]['functionbitmask']))           // Device Bitmaske entschl�sseln
  2764.      $device[$k]['functionbitname'] = call_user_func(__FUNCTION__,'functionbit',$device[$k]['functionbitmask']);
  2765.     if(isset($device[$k]['etsiunitinfo']) and $var = $device[$k]['etsiunitinfo']) { // HAN-FUN Unit/Ger�t
  2766.      $units = array(        266 => 'DIMMER_SWITCH',     278 => 'DIMMABLE_COLOR_BULB',
  2767.     281 => 'BLIND',     273 => 'SIMPLE_BUTTON',     519 => 'GLAS_BREAK_DETECTOR',
  2768.     640 => 'SIREN',     518 => 'FLOOD_DETECTOR',    257 => 'SIMPLE_ON_OFF_SWITCH',
  2769.     282 => 'LAMELLAR',  265 => 'DIMMABLE_LIGHT',    256 => 'SIMPLE_ON_OFF_SWITCHABLE',
  2770.     262 => 'AC_OUTLET', 512 => 'SIMPLE_DETECTOR',   513 => 'DOOR_OPEN_CLOSE_DETECTOR',
  2771.     277 => 'COLOR_BULB',    515 => 'MOTION_DETECTOR',   514 => 'WINDOW_OPEN_CLOSE_DETECTOR',
  2772.     264 => 'SIMPLE_LIGHT',  520 => 'VIBRATION_DETECTOR',    263 => 'AC_OUTLET_SIMPLE_POWER_METERING');
  2773.      $types = array(        277 => 'KEEP_ALIVE',        256 => 'ALERT',     512 => 'ON_OFF',
  2774.     513 => 'LEVEL_CTRL',    514 => 'COLOR_CTRL',        516 => 'OPEN_CLOSE',    517 => 'OPEN_CLOSE_CONFIG',
  2775.     772 => 'SIMPLE_BUTTON', 1024 => 'SUOTA-Update');
  2776.      $hfu[$device[$k]['id']] = $var['etsideviceid'];
  2777.      if(ifset($var['unittype']) and isset($units[$var['unittype']]))
  2778.       $device[$k]['etsiunitinfo']['unittypename'] = $units[$var['unittype']];
  2779.      if(ifset($var['interfaces']))
  2780.       $device[$k]['etsiunitinfo']['interfacename'] = preg_array('/^('.str_replace(',','|',$var['interfaces']).')$/',$types,3);
  2781.     }
  2782.     if(isset($device[$k]['functionbitname'][2])) {      // Einstellbare Vorgabe-Farben ermitteln
  2783.      if($xml = request('GET',$link,$parm."getcolordefaults") and preg_match_all('/<hs\b[^>]*>.*?<\/hs>/s',$xml,$array)) // Farbwerte extrahieren
  2784.       foreach($array[0] as $var)
  2785.        if(is_array($val = xml2array($var,-1)) and $device[$k]['defaults']['hue'][$val['hs']['color'][0][-1]['hue']] = $val['hs']['name'][0])
  2786.         foreach($val['hs']['color'] as $v)
  2787.          $device[$k]['defaults']['color'][$val['hs']['name'][0]][$v[-1]['sat_index']] = array('hue' => $v[-1]['hue'], 'sat' => $v[-1]['sat'], 'val' => $v[-1]['val']);
  2788.      if(preg_match_all('/<temp\b[^\d>]*(\d+)[^>]*\/>/s',$xml,$array))   // Farbtemperatur extrahieren
  2789.       $device[$k]['defaults']['temperature'] = $array[1];
  2790.     }
  2791.    }
  2792.    if($xml = request('GET',$link,$parm."gettemplatelistinfos") and preg_match_all('!<(template)\s([^>]+)>(.*?)</\1>!s',preg_replace('/[\r\n]+/','',$xml),$list))
  2793.     foreach($list[2] as $key => $var)               // Templates durchgehen
  2794.      if(preg_match_all('/(\w+)="([^"]*)"/',$var,$array)) {
  2795.       $array = array_combine($array[1],$array[2]);
  2796.       $array['name'] = preg_match('/<name>(.*?)<\/name>/',$list[3][$key],$m) ? $m[1] : false;
  2797.       $array['device'] = preg_match('/<device identifier="([^"]*)"\s*\/>/',$list[3][$key],$m) ? $m[1] : false;
  2798.       if(isset($array['functionbitmask']))
  2799.        $array['functionbitname'] = call_user_func(__FUNCTION__,'functionbit',$array['functionbitmask']);
  2800.       foreach($device as $key => $var)
  2801.        if($var['identifier'] == $array['device']) {
  2802.         $device[$key]['template'][] = $array+array('key' => $key); // Eintragen
  2803.         break;
  2804.        }
  2805.      }
  2806.    $idx = array();                      // ID-Index anlegen
  2807.    foreach($device as $key => $var)
  2808.     $idx[$var['id']] = $key;
  2809.    foreach($hfu as $key => $var) {              // Doppelte HAN-FUN Units/Ger�te zusammenlegen
  2810.     if((float)$device[$idx[$key]]['fwversion'] == 0)
  2811.      $device[$idx[$key]]['fwversion'] = $device[$idx[$var]]['fwversion'];
  2812.     $device[$idx[$key]]['link'] = $device[$idx[$var]];      // Kopie sichern
  2813.     unset($device[$idx[$var]]);                 // Device l�schen
  2814.     unset($hfu[$key]);                      // Link zum Device l�schen
  2815.    }
  2816.    dbug($device,9);
  2817.    $device = call_user_func(__FUNCTION__,$device,true);
  2818.    if(!$ain and $cmd == 'array')
  2819.     return $device;
  2820.    if($ain) {                           // Einzelnen Aktor Schalten oder auslesen
  2821.     foreach($device as $v)
  2822.      if($ain == $v['id'] or preg_replace('/\W/','',strtoupper($ain)) == preg_replace('/\W/','',$v['identifier']) or strtolower($ain) == strtolower($v['name'])) {
  2823.       dbug("Aktor/Gruppe '$ain' gefunden",9);
  2824.       $ain = $v;
  2825.       break;
  2826.      }
  2827.     if($cmd == 'array')
  2828.      return $ain;
  2829.     if(is_array($ain))
  2830.      if($cmd == 'info') {
  2831.       $out = "Hauptdaten|Name:|$ain[name]
  2832. |AIN:|$ain[identifier]
  2833. |ID:|$ain[id]
  2834. |Hersteller:|$ain[manufacturer]".((ifset($ain['productname'])) ? "\n|Modell:|$ain[productname]" : "")."
  2835. |Funktionen:|".implode(", ",$ain['functionbitname'])."
  2836. |Verbindung:|".(($ain['present']) ? "Online" : "Offline")
  2837. .((ifset($ain['fwversion']) and (float)$ain['fwversion']) ? "\n|Firmware:|$ain[fwversion]" : "")
  2838. .((isset($ain['txbusy'])) ? "\n|Besch�ftigt:|".(($ain['txbusy']) ? "Ja" : "Nein") : "")
  2839. .((ifset($ain['simpleonoff'])) ? "\n|Schaltzustand:|A".(($ain['simpleonoff']['state']) ? "n" : "us") : "")
  2840. .((ifset($ain['battery'])) ? "\n|Batterie:|$ain[battery]%".(($ain['batterylow']) ? " (Schwach)" : "") : "")."\n";
  2841.       if(ifset($ain['template'])) {
  2842.        $array = array();
  2843.        foreach($ain['template'] as $var)
  2844.         $array[] = $var['name'];
  2845.        $out .= "|Template:|".implode(", ",$array)."\n";
  2846.       }
  2847.       if(ifset($ain['groupinfo'])) {
  2848.        $array = explode(',',$ain['groupinfo']['members']);
  2849.        foreach($array as $key => $var) {
  2850.         $val = $device[$idx[intval($var)]];
  2851.         $array[$key] = (ifset($val['name'])) ? $val['name'] : $val['identifier'];
  2852.        }
  2853.        $out .= "Gruppe|Mitglieder:|".implode(", ",$array)."\n";
  2854.        if(ifset($ain['groupinfo']['masterdeviceid'])) {
  2855.         $var = $device[$idx[$ain['groupinfo']['masterdeviceid']]];
  2856.         $out .= "|Master:|".(($var['name']) ? $var['name'] : $var['identifier'])."\n";
  2857.        }
  2858.       }
  2859.       if(ifset($ain['switch']) and $x = $ain['switch'] or ifset($ain['hkr']) and $x = $ain['hkr'])
  2860.        $out .= "Schloss|Taster:|".(($x['devicelock']) ? "Gesperrt" : "Frei")."
  2861. |Fernsteuerung:|".(($x['lock']) ? "Gesperrt" : "Frei")."\n";
  2862.       if(ifset($ain['powermeter']) and $x = $ain['powermeter'])
  2863.        $out .= "Energie Messger�t|Spannung:|".number_format(intval($x['voltage'])/1e3,2,",",".")." Volt
  2864. |Leistung:|".number_format(intval($x['power'])/1e3,3,",",".")." Watt
  2865. |Stromz�hler:|".number_format(intval($x['energy'])/1e3,3,",",".")." KiloWattStunden\n";
  2866.       if(ifset($ain['switch']) and $x = $ain['switch'])
  2867.        $out .= "Schaltsteckdose|Schaltzustand:|".(($x['state']) ? "An" : "Aus")."
  2868. |Modus:|".ucfirst($x['mode'])."\n";
  2869.       if(ifset($ain['temperature']) and $x = $ain['temperature'])
  2870.        $out .= "Temperatur|Sensor:|".(intval($x['celsius'])/10)."�C".(($x['offset']) ? "\n|Offset:|".preg_replace('/^(?=\d)/','+',$x['offset']/10) : "")."\n";
  2871.       if(ifset($ain['hkr']) and $x = $ain['hkr'])
  2872.        $out .= "Heizregler|Aktuell:|".call_user_func(__FUNCTION__,'temp',$x['tist'])."
  2873. |Eingestellt:|".call_user_func(__FUNCTION__,'temp',$x['tsoll'])."
  2874. |Spar:|".call_user_func(__FUNCTION__,'temp',$x['absenk'])."
  2875. |Komfort:|".call_user_func(__FUNCTION__,'temp',$x['komfort'])."
  2876. |N�chste �nderung:|".date('d.m.Y H:i:s',$x['nextchange']['endperiod'])." Uhr auf ".call_user_func(__FUNCTION__,'temp',$x['nextchange']['tchange'])."
  2877. |Fenster:|".(($x['windowopenactiv']) ? "Offen" : "Geschlossen")."
  2878. |Sommerpause:|".(($x['summeractive']) ? "Aktiviert" : "Aus")."
  2879. |Urlaub:|".(($x['holidayactive']) ? "Aktiv" : "Aus")."
  2880. |Letzter Fehler:|".(($y = explode("\n","Kein Fehler
  2881. Keine Adaptierung m�glich
  2882. Ventilhub zu kurz oder Batterieleistung zu schwach
  2883. Keine Ventilbewegung m�glich
  2884. Die Installation wird gerade vorbereitet
  2885. Der Heizk�rperregler ist im Installationsmodus und kann auf das Heizungsventil montiert werden
  2886. Der Heizk�rperregler passt sich nun an den Hub des Heizungsventils an")) ? ((ifset($y[$x['errorcode']])) ? $y[$x['errorcode']] : "Unbekannt ($x[errorcode])") : "")."\n";
  2887.       if(isset($ain['functionbitname'][2])) {           // Lampe
  2888.        $out .= "Lampe";
  2889.        if(ifset($ain['levelcontrol']) and $x = $ain['levelcontrol'])
  2890.         $out .= "|Helligkeit:|".($v = (isset($x['levelpercentage']) ? $x['levelpercentage'] : (isset($x['level']) ? floor($x['level']/2.55) : 'Unbekannt')))."%\n";
  2891.        if(ifset($ain['colorcontrol']) and $x = $ain['colorcontrol']) {
  2892.         if(isset($x['hue']) and $h = $x['hue'] and isset($ain['defaults']['hue'])) {
  2893.          if(isset($ain['defaults']['hue'][$h]))
  2894.           $hue = $ain['defaults']['hue'][$h];
  2895.          else {
  2896.           $var = array_values($ain['defaults']['hue']);
  2897.           $hue = $var[round($h/30)%12];
  2898.          }
  2899.          $out .= "|Farbwinkel:|{$h}� ($hue)\n";
  2900.         }
  2901.         $var = array('Warm','Neutral','Kalt');
  2902.         if(isset($x['saturation']))
  2903.          $out .= "|Farbs�ttigung:|".floor($s = intval($x['saturation']) / 2.55)."%\n";
  2904.         if(isset($x['temperature']) and $y = $x['temperature'])
  2905.          $out .= "|Farbtemperatur:|$y K (".(($z = preg_array('/'.preg_quote($y,'/').'/',$ain['defaults']['temperature'],4)) ? $var[floor($z / 3)]." ".($z % 3 + 1)
  2906.         : (($y >= 2700 and $y <= 3400) ? "Warm" : (($y >= 3800 and $y <= 4700) ? "Neutral" : (($y >= 5300 and $y <= 6500) ? "Kalt" : "Unbekannt")))).")\n";
  2907.         if(isset($ain['defaults']['hue']))
  2908.          $out .= "|Vorgabefarben:|".implode(', ',array_merge($var,$ain['defaults']['hue']))."\n";
  2909.         if(isset($ain['defaults']['temperature']))
  2910.          $out .= "|Temperaturwerte|".implode(", ",$ain['defaults']['temperature'])." (Kelvin)\n";
  2911.        }
  2912.        if(isset($h) and isset($s) and isset($v)) {      // HSV in RGB umrechnen
  2913.         for($c = array(0,0,0), $i = 0; $i < 4; $i++)
  2914.          if(abs(intval($h) - $i * 120) < 120)
  2915.           $c[$i % 3] = 1 - ((max(60,abs(intval($h) - $i * 120)) - 60) / 60);
  2916.         for($h = max($c), $i = 0; $i < 3; $i++)
  2917.          $c[$i] = round(($c[$i] + ($h - $c[$i]) * (1 - $s / 100)) * 255 * ($v / 100));
  2918.         $out .= sprintf("|RGB-Farbwert:|#%02X%02X%02X\n",$c[0],$c[1],$c[2]);
  2919.        }
  2920.       }
  2921.       if(ifset($ain['button'])) {               // Taster
  2922.        $array = (ifset($ain['button'][0])) ? $ain['button'] : array($ain['button']);
  2923.        foreach($array as $k => $v)
  2924.         $out .= "Schalter #".($k + 1)."|Name:|$v[name]
  2925. |AIN:|$v[identifier]
  2926. |ID:|$v[id]".((ifset($v['lastpressedtimestamp'])) ? "\n|Zuletzt bet�tigt:|".date('d.m.Y H:i:s',$v['lastpressedtimestamp'])." Uhr" : "")."\n";
  2927.       }
  2928.       if(ifset($ain['etsiunitinfo']) and $x = $ain['etsiunitinfo']) // HAN-FUN Unit/Ger�t
  2929.        $out .= "HAN-FUN Unit|Type:|$x[unittypename]\n|Interfaces:|".implode(", ",$x['interfacename'])."\n";
  2930.       if($cfg['dbug'])                      // Debug-Modus
  2931.        foreach($ain as $key => $var)
  2932.         if(is_null($ain[$key]))
  2933.          unset($ain[$key]);
  2934.       dbug($ain,9);
  2935.      }
  2936.      elseif($ain['present']) {
  2937.       $do = array('on' => 'setswitchon', 'off' => 'setswitchoff', 'trip' => 'setswitchtoggle');
  2938.       $d0 = array_flip(array('off','on','trip'));
  2939.       $aid = str_replace(' ','',$ain['identifier']);
  2940.       if(ifset($ain['txbusy']))                 // Besch�ftigt
  2941.        $out = "$ain[name] ist noch mit der letzten Aktion besch�ftigt!";
  2942.       elseif(ifset($ain['simpleonoff']) and ifset($cmd,'/test/')) {// Universal Schnelltest f�r on / off
  2943.        $out = "$ain[name] ist A".(($ain['simpleonoff']['state']) ? "N" : "US")." geschaltet!";
  2944.        if($ain['simpleonoff']['state'])
  2945.         errmsg("1:$out",__FUNCTION__);
  2946.       }
  2947.       elseif(ifset($ain['simpleonoff']) and ifset($cmd,'/on|off/'))// Universal an / aus
  2948.        $out = request('GET',$link,$parm."setsimpleonoff&onoff=".$d0[$cmd]."&ain=$aid");
  2949.       elseif(ifset($ain['functionbitname'][9])) {       // Schaltsteckdosen
  2950.        if(ifset($cmd,'/test/')) {               // test
  2951.         $out = "$ain[name] ist A".(($ain['switch']['state']) ? "N" : "US")." geschaltet!";
  2952.         if($ain['switch']['state'])
  2953.          errmsg("1:$out",__FUNCTION__);
  2954.        }
  2955.        elseif(ifset($ain['switch']['lock']))
  2956.         $out = errmsg("8:Aktor ist f�r die Fernwartung gesperrt!",__FUNCTION__);
  2957.        elseif(ifset($cmd,'/on|off|trip/'))          // on / off / trip
  2958.         $out = request('GET',$link,$parm.$do[$cmd]."&ain=$aid");
  2959.       }
  2960.       elseif(ifset($ain['functionbitname'][6])) {       // Heizk�rperregler
  2961.        if($cmd == 'test') {
  2962.         $out = "$ain[name] ist ".preg_replace('/^(?=\d)/','auf ',call_user_func(__FUNCTION__,'temp',$ain['hkr']['tsoll']))." gestellt";
  2963.         if(!$ain['hkr']['tsoll'] and $ain['hkr']['tsoll'] != 253)
  2964.          errmsg("1:$out",__FUNCTION__);
  2965.        }
  2966.        elseif(ifset($ain['hkr']['lock']))
  2967.         $out = errmsg("8:Aktor ist f�r die Fernwartung gesperrt!",__FUNCTION__);
  2968.        elseif(ifset($cmd,'/on|off|trip|set/')) {
  2969.         $var = (isset($set['hkr'])) ? $set['hkr'] : false;
  2970.         $do = array('on' => 254, 'off' => 253, 'trip' => ($ain['hkr']['tsoll'] == 253) ? 254 : 253, 'set' => ($var == 'spar')
  2971.     ? $ain['hkr']['absenk'] : (($var == 'komfort') ? $ain['hkr']['komfort'] : (($var == 'an' or $var == 'on') ? 254
  2972.     : ((!$var or $var == 'aus' or $var == 'off') ? 253 : floor(floatval($var)*2)))));
  2973.         $out = request('GET',$link,$parm."sethkrtsoll&param=".$do[$cmd]."&ain=".urlencode($ain['identifier']));
  2974.        }
  2975.       }
  2976.       elseif(ifset($ain['functionbitname'][2]) and $cmd == 'set') { // Lampe
  2977.        $hue = $sat = $val = $kel = $col = $a = 0;
  2978.        $delay = "&duration=".((ifset($set['delay'])) ? $set['delay'] : 0);
  2979.        if($hsv = ifset($set['hsv'],'/\d+/a'))               // HSV-Angaben
  2980.         foreach($xxx = array_combine(array('hue','sat','val'),array_pad($hsv[0],3,0)) as $key => $var)
  2981.          $$key = round($var * (($a++) ? 2.55 : 1));
  2982.        if($var = ifset($set['color'],'/^(?:(warm)|(neutral)|(cold|kalt)|([\w\s]*?))([1-3]?)($)/ui') or $var = ifset($set['color'],'/(^)()()([\w\s�������]+)([1-3]?)($)/'))
  2983.         if($var[1] or $var[2] or $var[3])
  2984.          $kel = $ain['defaults']['temperature'][(($var[1]) ? 0 : (($var[2]) ? 3 : (($var[3]) ? 6 : 0))) + ($var[5] ? $var[5]-1 : 0)];
  2985.         elseif($var[4])
  2986.          extract($ain['defaults']['color'][$col = preg_array('/^'.preg_quote(utf8($var[4],1),'/').'/i',array_combine(array_keys($ain['defaults']['color']),preg_replace('/\s+/','',array_keys($ain['defaults']['color']))),4)][$var[5] ? $var[5] : 1]);
  2987.        if(ifset($set['dimm']))
  2988.         $val = round($set['dimm'] * 2.55);
  2989.        if(ifset($set['kelvin']))
  2990.         $kel = (int)$set['kelvin'];
  2991.        if(($hue and $sat or $hsv)) {
  2992.         dbug("Setzte Farbe {$hue}� und S�ttigung $sat/255 auf $ain[name]");
  2993.         if(request('GET',$link,$parm."setcolor&hue=$hue&saturation=$sat$delay&ain=$aid"))
  2994.          $out = "$ain[name] wurde auf ".($col ? "die Farbe $col" : "den Farbwinkel {$hue}�")." mit ".round($sat/2.55)."% Farbs�ttigung eingestellt";
  2995.        }
  2996.        elseif($kel) {
  2997.         dbug("Setzte $kel Kelvin auf $ain[name]");
  2998.         $out = (trim(request('GET',$link,$parm."setcolortemperature&temperature=$kel$delay&ain=$aid")) == $kel) ? "$ain[name] wurde auf $kel Kelvin gestellt" : "";
  2999.        }
  3000.        if($val) {
  3001.         while($var = call_user_func(__FUNCTION__,'array',$aid) and ifset($var['txbusy'])) { // Warten bis die Lampe fertig ist
  3002.          dbug("Warte...");
  3003.          sleep(1);
  3004.         }
  3005.         dbug("Setze Helligkeit $val auf $ain[name]");
  3006.         if(request('GET',$link,$parm."setlevel&level=$val$delay&ain=$aid"))         // Helligkeit setzen
  3007.          $out = ($out ? "$out und" : "$ain[name] wurde")." auf ".round($val/2.55)."% Helligkeit gesetzt";
  3008.        }
  3009.       }
  3010.       elseif(ifset($cmd,'/open|close|stop/i') and isset($ain['etsiunitinfo']['interfacename'][281]))    // Rolll�den
  3011.        $out = (request('GET',$link,$parm."setblind&target=".strtolower($cmd)."&ain=$aid")) ? "$ain[name] wurde geschaltet" : "";
  3012.       if(!$out)
  3013.        $out = errmsg("64:Aktor unterst�tzt diese Funktion nicht!",__FUNCTION__);
  3014.       elseif(ifset($out,'/^\d+$/'))
  3015.        $out = "$ain[name] wurde ".preg_replace('/^(?=\d)/','auf ',call_user_func(__FUNCTION__,'temp',$out))." geschaltet!";
  3016.      }
  3017.      else
  3018.       $out = errmsg("8:Aktor ist nicht verbunden bzw. OFFLINE!",__FUNCTION__);
  3019.     elseif($cmd == 'set' and $tmp = call_user_func(__FUNCTION__,'template',$ain,$device)) { // Template setzen
  3020.      dbug("Setze Template: '$tmp[name]' von: '".$device[$tmp['key']]['name']."'");
  3021.      request('GET',$link,$parm."applytemplate&ain=$tmp[identifier]");
  3022.     }
  3023.     elseif(ifset($cmd,'/on|off|trip/')) {
  3024.      $do = array('on' => 'setswitchon', 'off' => 'setswitchoff', 'trip' => 'setswitchtoggle');
  3025.      $out = request('GET',$link,$parm.$do[$cmd]."&ain=".urlencode($ain));
  3026.     }
  3027.     else
  3028.      $out = errmsg("8:Aktor '$ain' nicht gefunden!",__FUNCTION__);
  3029.    }
  3030.    elseif($cmd == 'json')
  3031.     $out = (function_exists('json_encode')) ? json_encode(utf8($device,1))."\n" : errmsg("64:JSON_Encode von PHP {$cfg['php'][0]} ist fehlgeschlagen",__FUNCTION__);
  3032.    else {                           // Device-Liste zur�ckgeben
  3033.     $list = array();
  3034.     $spar = array(0,0);
  3035.     foreach($device as $k => $v) {
  3036.      $array = array('ID' => 'id', 'AIN' => 'identifier', 'Name' => 'name', 'Modell' => 'productname', 'OS' => 'fwversion');
  3037.      foreach($array as $key => $var)
  3038.       $list[$k][$key] = (ifset($v[$var])) ? $v[$var] : false;
  3039.      if(!$list[$k]['Modell'] and ifset($v['groupinfo'])) {
  3040.       $var = count(explode(',',$v['groupinfo']['members']));
  3041.       $list[$k]['Modell'] = "Gruppe ($var Mitglied".(($var == 1) ? "" : "er").")";
  3042.      }
  3043.      $list[$k]['Batterie'] = (isset($v['battery'])) ? ($spar[0] = "$v[battery]%") : "-";
  3044.      $val = "-";
  3045.      if(ifset($v['temperature'])) {             // Temperatur
  3046.       $x = $v['temperature'];
  3047.       if(isset($x['celsius']))
  3048.        $val = (intval($x['celsius'])/10)."�C";
  3049.       if(isset($x['offset']) and $x['offset'])
  3050.        $val .= " (".preg_replace('/^(?=\d)/','+',$x['offset']/10).")";
  3051.       $spar[1] = $val;
  3052.      }
  3053.      elseif(ifset($v['hkr']) and ifset($v['hkr']['tist']))  // Alternative M�glichkeit �ber HKR
  3054.       $val = call_user_func(__FUNCTION__,'temp',$v['hkr']['tist']);
  3055.      $list[$k]['Temperatur'] = $val;
  3056.      $val = "offline";                      // Status
  3057.      if($v['present']) {
  3058.       if(isset($v['switch']['state'])) {            // Schaltsteckdose
  3059.        if(($val = ($v['switch']['state']) ? "an" : "aus") == 'on' and isset($v['powermeter']['power']))
  3060.         $val .= " (".($v['powermeter']['power']/1e3)."W)";
  3061.       }
  3062.       elseif(isset($v['hkr']['tsoll']))             // Heizk�rperregler
  3063.        $val = call_user_func(__FUNCTION__,'temp',$v['hkr']['tsoll']);
  3064.       elseif(isset($v['simpleonoff']['state']))         // Schaltlampe
  3065.        $val = ($v['simpleonoff']['state']) ? "an" : "aus";
  3066.       else
  3067.        $val = "online";                     // Unbekannt
  3068.      }
  3069.      $list[$k]['Status'] = $val;
  3070.      if(isset($device[$k]['template'])) {           // Templates
  3071.       $array = array();
  3072.       foreach($device[$k]['template'] as $key => $var) {
  3073.        $array['ID'] = $var['id'];
  3074.        $array['AIN'] = $var['identifier'];
  3075.        $array['Name'] = $var['name'];
  3076.        $array['Modell'] = 'Template';
  3077.        $list["$k.$key"] = $array;
  3078.       }
  3079.      }
  3080.     }
  3081.     if(!array_sum($spar))                   // Unn�tze Spalten einsparen
  3082.      foreach($list as $key => $var) {
  3083.       if(!$spar[0])
  3084.        unset($list[$key]['Batterie']);
  3085.       if(!$spar[1])
  3086.        unset($list[$key]['Temperatur']);
  3087.      }
  3088.     if($cmd == 'csv') {                     // CSV-Ausgabe
  3089.      $s = (ifset($set['csv'])) ? $set['csv'] : ";";
  3090.      $out = implode($s,array_keys(reset($list)))."\n";
  3091.      foreach($list as $var)
  3092.       $out .= implode($s,preg_replace('/'.preg_quote($s,'/').'/','\\$0',$var))."\n";
  3093.     }
  3094.     elseif($cmd == 'list') {                    // Text-Ausgabe
  3095.      $out = implode('|',array_keys(reset($list)))."\n";
  3096.      foreach($list as $var)
  3097.       $out .= implode('|',preg_replace('/'.preg_quote('|','/').'/','\\$0',$var))."\n";
  3098.     }
  3099.     else                            // RAW-Ausgabe
  3100.      $out = $list;
  3101.    }
  3102.   }
  3103.   else
  3104.    $out = errmsg("8:Keine Aktoren gefunden!",__FUNCTION__);
  3105.  }
  3106.  return $out;
  3107. }
  3108. function init($ver,$x=0,$y=0) {             // Fritz!Box Tools Initialisieren
  3109.  global $cfg,$script,$self,$Self;
  3110.  if((float)phpversion() > 4.3 and $ver = ifset($ver,'/^(\w+) ([\d.]+) \(c\) (?:GNU )?GPL (\d\d)\.(\d\d)\.(\d{4}) by ([\w ]+?) <(\w+:\/\/[\w.-]+)(.*?)>$/')) {
  3111.   define($ver[1],1);                    // Feste Kennung f�r Plugins etc.
  3112.   $ver[] = intval($ver[5].$ver[4].$ver[3]);     // fb_tools Datum (9)
  3113.   $ver[] = floatval($ver[2]);               // fb_tools Version (10)
  3114.   $var = $_SERVER['argv'][0];
  3115.   $script = (ifset($var)) ? (($var = realpath($var)) ? $var : realpath($var.".bat")) : $_SERVER['PHP_SELF'];
  3116.   $self = basename($var);               // Exec-Script (Wie von der Konsole aufgerufen)
  3117.   $Self = basename($script);                // Script_Name
  3118.   $cfg['dir'] = preg_replace(array('/\\\\/','/\/$/'),array('/',''),dirname($script));
  3119.   $cfg['ver'] = $ver;                   // FB_Tools Versionsstring
  3120.   $cfg['ext'] = strtolower(preg_replace('/\W+/','',pathinfo($script,PATHINFO_EXTENSION))); // Extension f�r Unix/Win32 unterscheidung
  3121.   $cfg['php'] = array(phpversion(),php_uname(),php_sapi_name(),(float)phpversion(),(defined('PHP_INT_SIZE')) ? PHP_INT_SIZE * 8 : 32);
  3122.   $cfg['ssl'] = (defined('OPENSSL_VERSION_TEXT')) ? OPENSSL_VERSION_TEXT : false;
  3123.   $cfg['osn'] =  ($var = ifset($cfg['ssl'],'/[\d.]+/')) ? (float)$var[0] : false;
  3124.   $cfg['ptar'] = '/\.(?:(tar)|(t(?:ar\.)?gz)|(t(?:ar\.)?bz(?:ip)?2?)|(zip))($)/i';  // Tar-Ausdruck (1: .tar | 2: t?GZip | 3: tBZip2 | 4: ZIP)
  3125.   $cfg['dbcd'] = realpath('.').'/';         // Current_Dir f�r Debug-Daten
  3126.   $cfg['desc'] = '/['.preg_quote(preg_replace('!/.*$!','',$cfg['fesc']),'/').']+/';
  3127.   $cfg['fesc'] = '/['.preg_quote($cfg['fesc'],'/').']+/';
  3128.   $cfg['head'] = array('User-Agent' => "$Self $ver[2] {$cfg['php'][1]} PHP {$cfg['php'][0]}/{$cfg['php'][2]} ({$cfg['php'][4]} Bit) $cfg[ssl]"); // Fake UserAgent
  3129.   $cfg['fail'] = array();
  3130.   $cfg['uplink'] = array(
  3131.     'host' => preg_replace('/^.*?(?=[\w.-]+$)/','',$ver[7]).":443,80",
  3132.     'path' => "/Projekte/FritzBox-Tools;",
  3133.     'fbts' => $ver[1],
  3134.     'fbtp' => "fbt_plugins");
  3135.   if(($cfg['os'] = strtolower(PHP_OS)) == 'winnt')  // Sonderarten von Windows erkennen
  3136.    $cfg['os'] .= (count(preg_array('/^(HOME|SYSTEM(DRIVE|ROOT)|APPDATA|WINDIR)$/',$_SERVER,3)) == 5) ? '-busybox'
  3137.     : ((count(preg_array('/^(SystemDrive|SYSTEMROOT|APPDATA|windir|WINE(LOADER|SERVER)?)$/',$_SERVER,3)) == 7) ? '-wine' : '');
  3138.   $cfg['cu'] = ($var = getenv('USER') or $var = getenv('USERNAME')) ? $var
  3139.     : ((is_callable('posix_geteuid') and is_callable('posix_getpwuid') and $var = posix_getpwuid(posix_geteuid())) ? $var['name']
  3140.     : (($var = getenv('windir') and file_exists("$var/system32/whoami.exe") or file_exists("/bin/whoami") or file_exists("/usr/bin/whoami"))
  3141.     ? basename(@exec('whoami')) : (($var = get_current_user()) ? $var : "UNKNOWN")));
  3142.   $cfg['home'] = ($var = getenv('HOME') or $var = getenv('APPDATA') or $var = getenv('USERPROFILE')) ? $var : ".";
  3143.   foreach(array('l' => $cfg['libs'], 'a' => $cfg['fbtp']) as $key => $var)  // Verzeichnisliste f�r Libs/Plugins vorab berechnen in $cfg[fbtl/fbta]
  3144.    $cfg["fbt$key"] = array(".","$cfg[dir]",$var,strtoupper($var),ucwords($var),"$cfg[dir]/$var","$cfg[dir]/".strtoupper($var),"$cfg[dir]/".ucwords($var));
  3145.   if(ifset($_SERVER['argc']) and !preg_match('/cli/',$cfg['php'][2]) and function_exists('header_remove')) {    // HTTP-Header l�schen wenn PHP-CGI eingesetzt wird
  3146.    header('Content-type:');
  3147.    header_remove('Content-type');
  3148.    header_remove('X-Powered-By');
  3149.   }
  3150.   if(ifset($cfg['cron']))               // Verschiedene Funktionen einfach f�r Cron-Dienste abschalten
  3151.    $cfg['wrap'] = $cfg['char'] = $cfg['uplink'] = 0;
  3152.   if(function_exists('php_ini_loaded_file') and $var = php_ini_loaded_file())   // PHP.ini Location speichern
  3153.    $cfg['php'][] = $var;
  3154.   if(@ini_get('pcre.backtrack_limit') < $cfg['pcre'])   // F�r Gro�e RegEx-Ergebnisse
  3155.    @ini_set('pcre.backtrack_limit',$cfg['pcre']);
  3156.   if(@ini_get('memory_limit') < $cfg['meli'])       // Speicher-Buffer
  3157.    @ini_set('memory_limit',$cfg['meli']);
  3158.   if($cfg['time'])                  // Zeitzone festlegen
  3159.    @ini_set('date.timezone',$cfg['time']);
  3160.   if($cfg['slct'])                  // Zeitformat festlegen
  3161.    @setlocale(LC_TIME,$cfg['slct']);
  3162.   $gz = (function_exists("gzopen") or function_exists("gzopen64")) ? true : false;  // ZLib Funktionen initialisieren
  3163.   foreach(explode(',','open,close,eof,file,gets,puts,read,write,seek,tell,encode,decode,deflate,inflate') as $key)
  3164.    $cfg['zlib'][$key] = $gz ? ((function_exists("gz$key")) ? "gz$key" : ((function_exists("gz{$key}64")) ? "gz{$key}64" : 'init'))
  3165.     : ((function_exists($key)) ? $key : ((function_exists("f$key")) ? "f$key" : 'init'));
  3166.   if(!file_exists($var = realpath($cfg['usrcfg']))) {
  3167.    $file = basename($cfg['usrcfg']);
  3168.    foreach(array(".",$cfg['home'],$cfg['dir']) as $dir)         // Benutzerkonfig suchen
  3169.     if(file_exists($var = realpath($dir)."/$file") or file_exists($var = realpath($dir)."/.$file")) // Benutzerkonfig gefunden
  3170.      break;
  3171.   }
  3172.   if(file_exists($var)) {
  3173.    dbug("Lade Benutzer-Konfig: $var");                  // Debug-Meldung (dbug muss im Haupt-Quelltext aktiviert werden)
  3174.    include_once $cfg['loadcfg'] = $var;                 // Benutzer-Konfig ausf�hren
  3175.   }
  3176.   foreach(array('preset','plugin') as $var)
  3177.    if(!isset($cfg[$var]) or !is_array($cfg[$var]))          // Sicherstellen dass preset/plugin ein Array ist
  3178.     $cfg[$var] = array();
  3179.   $cfg['a1st'] = (date('nj') == 41 and $x = $cfg['zlib']['inflate'](base64_decode(  /* Test-Funktion */"
  3180.     XZBBT8JAEIXv/IrxtpsICdFTNTRFIwejaZDogXBYu9N2adnW2SkiIf3ZnnpwC3LQ45s3+d68GczRIcfKuc+K9GF4eEHeM9iGQCsHkd1gqbFAa73PoJoU3pAK
  3181.     h8Y6xrJsbIYW9g11SSHGcrAwSYE8Q4ukuCIPnCJhkltkyLqSTYZw2nGQdj7EIDwaq5GcSXIkzxNXl9eyPYgwvqV6Mhf9gTKMxe+NMpRHj7PJQhxJMpyJc6B3
  3182.     22VKhvej92q3guWm0hj8LVlrP6+9Cu4xVU3JcLZW7Wn/fwvOepJKVPDQoy+m1Q6eorthpAmdw1X7Wjew7lRa+79R7gVtFSlY5+qD0E+/ezUewXOC2y+4Gcof"))) ? explode("~",$x) : false;
  3183.   $cfg['time'] = (ifset($_SERVER['REQUEST_TIME_FLOAT'])) ? $_SERVER['REQUEST_TIME_FLOAT'] : array_sum(explode(' ',microtime()));    // Startzeit sichern
  3184.   foreach(explode(',','aes,arg,opt,argc,argk,args,opts,auth,mods') as $var) // Leeres Array setzen
  3185.    $cfg[$var] = array();
  3186.   if(!isset($cfg['bzip'])) {                        // BZip2 Funktionen initialisieren
  3187.    $cfg['bzip'] = (function_exists("bzopen") or function_exists("bzopen64")) ? true : cfgdecrypt(0,'bzip2');
  3188.    $cfg['bz'] = 0;
  3189.   }
  3190.   return true;
  3191.  }
  3192.  return false;
  3193. }
  3194.  
  3195. # Eigentlicher Programmstart
  3196. if(ifset($argc) and ifset($argv) and init($ver)) {  ## CLI-Modus ##
  3197.  $pmax = $argc;     // Anzahl der Parameter
  3198.  $pset = 1;     // Argumentenz�hler
  3199.  $opts = "";        // Kontext-Optionen
  3200.  
  3201. # Drag'n'Drop Modus
  3202.  if(ifset($cfg['drag']) and $pset+1 == $pmax and file_exists($argv[$pset]) and is_file($argv[$pset])) {
  3203.   if(is_array($cfg['drag'])) {  // Ist es ein Array mit Dateitypen als Schl�ssel?
  3204.    if(!preg_match('/\.([^.]+)(\.(gz|bz2?))?$/',$argv[$pset],$m) or !($drag = ifset($cfg['drag'][strtolower($m[1])],"")))
  3205.     $drag = isset($cfg['drag']['*']) ? $cfg['drag']['*'] : 'info hash *';
  3206.   }
  3207.   else              // Fallback zu String
  3208.    $drag = $cfg['drag'];
  3209.   dbug("Nutze Drag-Parameter: ".str_replace('*'," {$argv[$pset]} ",$drag)); // Debug-Meldung (Kann nicht mit -d angezeigt werden)
  3210.   $drag = explode('*',$drag);
  3211.   array_splice($argv,$pmax,0,explode(' ',trim($drag[1])));
  3212.   array_splice($argv,$pset,0,explode(' ',trim($drag[0])));
  3213.   $pmax = $argc = count($argv);
  3214.  }
  3215.  
  3216. # Ersten Fritz!Box Parameter ermitteln und auswerten
  3217.  if($pset < $pmax and @preg_match('/^(?!-) (?:(?P<us>https?):\/\/)? (?:(["\']?)(?P<un>.+)\2:)? (?:(["\']?)(?P<pw>.+)\4@)? (?P<fb>[\w.-]+\.[\w.-]+|(?<=@)[\w.-]+|\[[a-f\d:]+\]|'
  3218.     .strtr(preg_quote(implode("\t",array_keys($cfg['preset'])),'/'),"\t",'|')
  3219.     .'|[\w-]+::(["\']?)(?P<cf>.+)\7) (?::(?P<pt>\d{1,5}))? (?:\#(["\']?)(?P<ui>.+)\9)? ($)/ix',$argv[$pset],$m)) {  // Fritz!Box Anmeldedaten holen
  3220.   dbug("Presets: ".implode(', ',array_keys($cfg['preset'])),9);
  3221.   if(ifset($m['cf']) and file_exists($m['cf'])) { // Kurzschreibweise: [name]::'[/path/fb_config.php]'
  3222.    dbug("Lade Konfig-Datei: $m[cf]");
  3223.    include_once $m['cf'];
  3224.    $m['fb'] = preg_replace('/:.*$/','',$m['fb']);
  3225.   }
  3226.   $cfg['host'] = $m['fb'];  // fb:Host
  3227.   if(isset($cfg['preset'][$m['fb']])) { // Voreingestellte Fritz!Boxen Erkennen und Eintragen
  3228.    dbug("�bernehme Preset: $m[fb]");
  3229.    if(is_string($cfg['preset'][$m['fb']]) and $key = request($cfg['preset'][$m['fb']].'#'))
  3230.     $cfg['preset'][$m['fb']] = $key;
  3231.    if(is_array($cfg['preset'][$m['fb']]))
  3232.     foreach($cfg['preset'][$m['fb']] as $key => $var)
  3233.      $cfg[$key] = $var;
  3234.   }
  3235.   if($m['us']) {        // us: Protokoll
  3236.    $cfg['sock'] = $m['us'];
  3237.    if($m['us'] == 'https')
  3238.     $cfg['port'] = 443;
  3239.   }
  3240.   if($m['un'])          // un:Username
  3241.    $cfg['user'] = $m['un'];
  3242.   if($m['pw'])          // pw:Password
  3243.    $cfg['pass'] = $m['pw'];
  3244.   if($m['pt'])          // pt:Port
  3245.    $cfg['port'] = $m['pt'];
  3246.   if($m['ui'])          // ui:Password2
  3247.    $cfg['uipw'] = $m['ui'];
  3248.   $pset++;
  3249.  }
  3250.  unset($cfg['preset']);                 // Preset-Daten werden nicht mehr ben�tigt!
  3251.  
  3252. # Benannte / Nummerische Argumente und Optionen setzen
  3253.  if($pset < $pmax) {
  3254.   for($key=$pset; $key < $pmax; $key++)
  3255.    if(preg_match("/^(?!$cfg[argn])(-?)(\w+)(?:(?:\[(.)\])?[:=]([\"']?)(.*?)\\4)?($)/i",$argv[$key],$var) and ($var[1] != "" or $var[5] != "")) {    // Benanntes Argument
  3256.     if($var[3] and preg_match_all('/(?:[^'.preg_quote($var[3],'/').'\\\\]+|\\\\'.preg_quote($var[3],'/').'?)+/',$var[5],$array))    // Ketten-Argumente (test[,]=foo,bar)
  3257.      $var[5] = $array[0];
  3258.     if($var[1]) {               // Optionen
  3259.      $val = 'opts';
  3260.      if($var[5] == '')
  3261.       $var[5] = true;
  3262.     }
  3263.     else                    // Argumente
  3264.      $val = 'args';
  3265.     if(isset($cfg[$val][$var[2]]))      // Existiert schon?
  3266.      if(is_array($cfg[$val][$var[2]]))      // Ein Array?
  3267.       if(is_array($var[5]))
  3268.        $cfg[$val][$var[2]] = array_merge($cfg[$val][$var[2]],$var[5]);
  3269.       else
  3270.        $cfg[$val][$var[2]][] = $var[5];     // Array erweitern
  3271.      else
  3272.       $cfg[$val][$var[2]] = (is_array($var[5])) ? array_merge(array($cfg[$val][$var[2]]),$var[5]) : array($cfg[$val][$var[2]],$var[5]); // In Array umwandeln
  3273.     else
  3274.      $cfg[$val][$var[2]] = $var[5];     // Normal speichern
  3275.    }
  3276.    elseif(isset($argv[$key][0]) and $argv[$key][0] != '-')// Nummeriertes Argument
  3277.     $cfg['arg'][$key] = $argv[$key];
  3278.   $cfg['argc'] = array_keys($cfg['arg']);
  3279.   if($cfg['args'])
  3280.    $cfg['arg'] += $cfg['args'];         // Alle Argumente zusammenf�hren
  3281.   else
  3282.    $cfg['argn'] = false;            // Alten Parametermodus aktivieren
  3283.   foreach($cfg['opts'] as $key => $var) {#=>    // Optionen auswerten und setzen
  3284.    $var = (is_array($var)) ? $var[0] : $var;    // Bei mehreren Argumenten, nur das erste benutzen - entspreche getArg("-$key")
  3285.    if($key == 'h')  // help
  3286.     $cfg['help'] = $var;
  3287.    elseif($key == 'd') {// Debug
  3288.     $cfg['dbug'] = ($val = ifset($var,'/^(\d+)(?:.(.+))?($)/')) ? intval($val[1]) : true;
  3289.     if($val and $val[2] and (file_exists($val[2]) and is_dir($val[2]) or !file_exists($val[2]) and $val[2] = makedir($val[2],0)))
  3290.      $cfg['dbcd'] = realpath($val[2]).'/';  // CD Setzen
  3291.    }
  3292.    elseif($key == 'w')  // Wrap
  3293.     $cfg['wrap'] = (ifset($var,'/^[1-9]\d+$/')) ? intval($var) : 80;
  3294.    elseif($key == 'c')  // Char
  3295.     $cfg['char'] = strtolower($var);
  3296.    elseif($key == 't')  // Timeout
  3297.     $cfg['tout'] = (ifset($var,'/^\d+$/')) ? intval($var) : 0;
  3298.    elseif($key == 'b')  // Buffer
  3299.     $cfg['sbuf'] = (ifset($var,'/^[1-9]\d{2,}$/') ) ? intval($var) : 4096;
  3300.    elseif($key == 'p')  // Protokoll
  3301.     $cfg['sock'] = ($v = ifset($var,'/^(auto|https?|ssl|tls)$/i') ) ? strtolower($v[0]) : 'auto';
  3302.    elseif($key == 's') {// SID
  3303.     if($val = ifset($var,'/^[\da-f]{16}$/i0'))          // SID direkt �bernehmen
  3304.      $cfg['sid'] = $val;
  3305.     elseif(file_exists($var) and preg_match('/^\s*([\da-fA-F]{16}|(a:\d+:)?(\{.*\}))\s*($)/s',file_contents($var),$val)) {
  3306.      if($val[3])
  3307.       $cfg = array_replace($cfg,$val[2] ? unserialize($val[1]) : json2array($val[3]));  // S�mtliche Variabeln aus der Datei in $cfg �bernehmen/�berschreiben
  3308.      else
  3309.       $cfg['sid'] = $val[1];                    // NUR die SID �bernehmen
  3310.     }
  3311.     else
  3312.      errmsg("2:Ung�ltige SID �bergeben");
  3313.     if(ifset($cfg['sid']) and $sid = login(0,0,0,$cfg['sid'])) {// Sid best�tigen lassen
  3314.      $cfg['bsid'] = $cfg['sid'] = $sid;             // Festlegen, dass die Funktionen die Firmware-Abfragen und das Logout �berspringen sollen
  3315.      dbug("Recycle Login-SID: $sid von $cfg[host]");
  3316.     }
  3317.     else
  3318.      errmsg("20:SID ist ung�ltig");
  3319.    }
  3320.    elseif($key == 'gz') {                   // GZip Crunchlevel
  3321.     $cfg['zlib']['mode'] = ($v = ifset($var,'/^-?(\d)[fhR]?$/')) ? $v[0] : -1;
  3322.     $cfg['gz'] = $v ? $v[1] : 0;
  3323.    }
  3324.    elseif($key == 'zb')                     // ZIP-AES Bits
  3325.     $cfg['zb'] = intval(ifset($var,'/^(128|192|256)$/0')) or $cfg['zb'] = 256;
  3326.    elseif($key == 'zp') {                   // ZIP Kennwort
  3327.     if(!is_array($var = $cfg['opts'][$key]))            // Sicherstellen dass die ZIP-Kennw�rter ein Array sind
  3328.      $var = array($var);
  3329.     $cfg['zp'] = $var;
  3330.     if(!ifset($cfg['zb']))                  // Gleich noch die Bits pr�fen oder festlegen
  3331.      $cfg['zb'] = 256;
  3332.    }
  3333.    elseif($key == 'bz')                     // BZip2 Crunchlevel
  3334.     $cfg['bz'] = ifset($var,'/^\d$/0');
  3335.    elseif($key == 'pe' and $var)                // PHP-Extension nachladen
  3336.     @dl($var);
  3337.    elseif($key == 'fw' and $v = ifset($var,'/^(\d+\.0)?([1-9])\.?(\d{2})(-\d+)?$/'))    // Fritz!Box Firmware-Version
  3338.     $cfg['fiwa'] = (int)($v[2].$v[3]);
  3339.    elseif($key == 'ua' and $v = ifset($var,'/^[[:print:]]+$/')) // UserAgent setzen
  3340.     $cfg['head']['User-Agent'] = $v[0];
  3341.    elseif($key == 'px' and ifset($var,'/^[\w.-]+:\d+$/'))   // Proxy & Port
  3342.     $cfg['proxy'] = $var;
  3343.    elseif($key == 'pp' and is_dir($var))            // Plugin-Path setzen
  3344.     $cfg['fbta'] = array(realpath($var));
  3345.    elseif($key == 'nu')                     // Kein Update-Check
  3346.     $cfg['upda'] = is_bool($var) ? -1 : intval($var);
  3347.    elseif($key == 'cc' and file_exists($var)) {         // Include BenutzerKonfig
  3348.     $cfg['loadcfg'] = (ifset($cfg['loadcfg'])) ? "$cfg[loadcfg]|$var" : $var;
  3349.     include_once $var;
  3350.    }
  3351.    elseif($key == 'cm') {                   // Cron-Modus: Einige Funktionen deaktivieren
  3352.     $cfg['cron'] = true;
  3353.     $cfg['wrap'] = $cfg['char'] = $cfg['upda'] = $cfg['uplink'] = 0;// Alles Ausschalten
  3354.    }
  3355.    elseif($key == 'ps' and isset($cfg['preset'][$var])) {
  3356.     dbug("�bernehme Preset: $var");
  3357.     if(is_string($cfg['preset'][$var]) and $key = request($cfg['preset'][$var].'#'))
  3358.      $cfg['preset'][$var] = $key;
  3359.     if(is_array($cfg['preset'][$var]))
  3360.      foreach($cfg['preset'][$var] as $k => $v)
  3361.       $cfg[$k] = $v;
  3362.    }
  3363.    else
  3364.     foreach(array('o' => 'oput', 'un' => 'user', 'pw' => 'pass', 'ui' => 'uipw', 'fb' => 'host', 'pt' => 'port', 'tf' => 'totp') as $k => $v)   // Optionen mit Zwangsparameter
  3365.      if($key == $k and $var)
  3366.       $cfg[$v] = $var;
  3367.   }
  3368.  }
  3369.  if($cfg['dbug'] & 1<<8)        // PHP-Fehler Protokollieren
  3370.   set_error_handler('phperr');
  3371.  else
  3372.   error_reporting(0);           // Fehler-Meldungen deaktivieren
  3373.  
  3374. # Consolen Breite automatisch ermitteln
  3375.  if(ifset($cfg['wrap'],'auto')) {
  3376.   if(ifset($cfg['os'],'/darwin|linux/'))    // Linux/Mac
  3377.    $cfg['wrap'] = (($var = (int)getenv('COLUMNS'))
  3378.     or file_exists('/bin/stty') and $var = (int)preg_replace('/^\d+\D*/','',@exec('stty size'))
  3379.     or file_exists('/bin/tput') and $var = (int)@exec('tput cols')
  3380.     or file_exists('/bin/busybox')  and @exec('busybox | grep ttysize') and $var = (int)preg_replace('/\D.*$/s','',@exec('busybox ttysize'))) ? $var : 0;
  3381.   elseif((ifset($cfg['os'],'/^winnt(?!-wine)/') or file_exists(getenv('windir')."/system32/mode.com")) and (@exec('mode con',$var) or true) // Windows
  3382.     and is_array($var) and preg_match_all('/(?:(zeilen|lines)|(spalten|columns)|(code\s?page)):\s*(\S+)/',strtolower(implode('',$var)),$val))
  3383.    foreach($val[4] as $key => $var) {
  3384.     if(ifset($val[2][$key]))            // Breite sichern
  3385.      $cfg['wrap'] = $var;
  3386.     if(ifset($val[3][$key]))            // Codepage merken
  3387.      $char = "cp".(($var == 65001 and ifset(($cfg['php'][1]),'/Windows NT[\s\w_-]*(6\.[01])/i')) ? 850 : $var);
  3388.    }
  3389.   if($cfg['wrap'] == 'auto')            // Auto fehlgeschlagen -> Wrap deaktiviert
  3390.    $cfg['wrap'] = 0;
  3391.  }
  3392.  
  3393. # Char ermitteln und festlegen
  3394.  if(ifset($cfg['char'],'auto')) {
  3395.   if(!ifset($cfg['cron']) and preg_match('/(13)[73]((\1)37)/',date('dnHi'),$var))
  3396.    $cfg['char'] = $var[2];
  3397.   elseif(ifset($char))
  3398.    $cfg['char'] = $char;
  3399.   elseif($var = ifset($_SERVER['LANG'],'/(UTF-?8)|((?:iso-)?8859-1)/i') and ($var[1] and !isset($cfg['utf8'])) or ifset($var[2]))   // Linux/Ubuntu
  3400.    $cfg['char'] = ($var[1]) ? 'utf-8' : 'iso-8859-1';
  3401.   elseif(getenv('HOME') and getenv('USER') and getenv('TERM') and getenv('SHELL')   // Unix/Linux/Mac
  3402.     and file_exists('/usr/bin/locale') and preg_match('/(utf-?8)|(ansi|iso-?8859-?1|ascii)/i',@exec('locale charmap'),$var))
  3403.    $cfg['char'] = (ifset($var[1]) and !isset($cfg['utf8'])) ? 'utf8' : ((ifset($var[2])) ? strtolower(str_replace('-','_',$var[2])) : 'utf7');
  3404.   elseif(getenv('SystemDrive') and getenv('SystemRoot') and getenv('APPDATA'))      // Windows
  3405.    $cfg['char'] = 'oem';
  3406.   else
  3407.    $cfg['char'] = '7bit';
  3408.  }
  3409.  $cfg['char'] = ($var = '(?:c(?:odepage|p))?'
  3410.     and $val = ifset($cfg['char'],"/^(?:(?P<d>$var(437|85[08])|dos|oem)|(?P<a>$var(1252|851|28591)|iso.?8859.?1|ansi)|(?P<m>$var(?:1250|852|28952)|iso.?8859.?2)"
  3411.     ."|(?P<c>{$var}65000|7bit|asc(ii)?|utf-?7)|(?P<u>{$var}65001|utf-?8)|(?P<h>x?html?)|(?P<l>[1l][E3�]{2}[t\+7])|(?P<r>rot13)|(?P<n>auto|none))$/i"))
  3412.     ? $val : array(0 => "char ($cfg[char])", 'c' => 1);
  3413.  dbug(array('char' => $cfg['char']),4);
  3414.  
  3415. # Auto-Update (Check)
  3416.  if(ifset($cfg['uplink']) and is_array($cfg['uplink']) and isset($cfg['uplink']['host'])) {     // Links zum Updatecheck vorhanden?
  3417.   if(!isset($cfg['uplink']['port']) and preg_match_all('/[:,](\d+)/',$cfg['uplink']['host'],$array)) {  // Einen Speziellen Port benutzen?
  3418.    $cfg['uplink']['port'] = $array[1];
  3419.    $cfg['uplink']['host'] = preg_replace('/:.*$/','',$cfg['uplink']['host']);
  3420.   }
  3421.   else
  3422.    $cfg['uplink']['port'] = array(80);
  3423.   if($cfg['upda'] and ifset($cfg['uplink'],5)) {
  3424.    $file = "$cfg[dir]/.touch-$cfg[cu]"; // Alternative Datei zum beschreiben
  3425.    if($cfg['upda'] < 0)         // Update-Pr�fung verhindern und Touch-Datei aktualisieren
  3426.     mytouch(1);
  3427.    elseif(mytouch())            // Pr�fung auf Touchdatei
  3428.     if(mytouch(1)) {            // Touch-Datei aktualisieren
  3429.      dbug("Pr�fe auf Updates...");
  3430.      foreach($cfg['uplink']['port'] as $var)
  3431.       if($fbnet = request('GET-array',$cfg['uplink']['path'].$cfg['uplink']['fbts'].".md5",0,0,$cfg['uplink']['host'],$var)) {
  3432.        if($var = ifset($fbnet['Location'],'/^(https?:)(\/\/.+)$/'))
  3433.         $fbnet = request("$var[1][array]$var[2]");
  3434.        break;
  3435.       }
  3436.      if($fbnet and ifset($fbnet['Content-MD5'],hash('md5',$fbnet[1])) and preg_match("/^#\s*(\w+)\s([\d\s.:]+)\((\w+)\s([\d.]+)\)/",$fbnet[1],$var)) {
  3437.       if(floatval($var[4]) > $cfg['ver'][10]) {
  3438.        out(errmsg("1:Ein Update ist verf�gbar ($var[3] $var[4]) - Bitte nutzen Sie die Update-Funktion!\n\nBeispiel:\n$self info update\n\n"));
  3439.        if($var[1] == 'Emergency_Update' or $var[1] == 'Emergency_Exit' and errmsg("254:$var[1]"))
  3440.         $cfg['args'] = array('mode' => 'info', 'func' => 'update');
  3441.       }
  3442.       if(ifset($fbnet['X-Cookie']))
  3443.        dbug($fbnet['X-Cookie']);
  3444.      }
  3445.      else
  3446.       dbug(errmsg("1:Fehlerhafte Update-Liste erhalten!")); // Eigentlich ein Fehler
  3447.     }
  3448.     else
  3449.      errmsg("32:Keine Schreibberechtigung!\nBitte �ndern Sie das oder deaktivieren Sie die Auto-Update Funktion in der fb_config.php oder nutzen Sie die Option -nu!");
  3450.   }
  3451.  }
  3452.  
  3453. # Bei Fehlern jetzt abbrechen
  3454.  if($var = errmsg())
  3455.   out($var);
  3456. # Parameter auswerten
  3457.  elseif($val = getArg('mode','/^
  3458.     ((?P<bi>BoxInfo|bi) |(?P<pi>PlugIns?|pi)    |(?P<gip>G(et)?IP)      |(?P<lio>Log(in(-?test)?|out)|l(o|it?))
  3459.     |(?P<rc>ReConnect|rc)   |(?P<sd>SupportDaten|sd)|(?P<ss>(System)?S(tatu)?s) |(?P<k>K(onfig)?)   |(?P<i>I(nfo)?|UpGrade|ug)
  3460.     |(?P<e>E(reignisse)?)   |(?P<led>led)       |(?P<al>AnrufListe?|al)     |(?P<sh>SmartHome?|sh)  |(?P<wh>Dial|d|WahlHilfe|wh)
  3461.     |(?P<kf>KF|Komfort) |(?P<t>T(raffic)?)'.($cfg['a1st'] ? $cfg['a1st'][1] : "").'|(?P<pit>[\w-]+))($)/ix')) {
  3462.   dbug(array('mode' => $val, 'opts' => $cfg['opts'], 'argk' => $cfg['argk'], 'arg' => $cfg['arg'], 'argc' => $cfg['argc'], 'args' => $cfg['args']),3);
  3463.   if(!$val['pi'] and !$val['pit'])          // Plugin Voreinstellungen l�schen, wenn KEINE Plugins geladen werden
  3464.    unset($cfg['plugin']);
  3465.   if($val['i']) {                   // Info (Intern)
  3466.    if($cfg['help']) {
  3467.     $var = (ifset($cfg['uplink'])) ? array("\nUpDate <opt:Check>|-|FB_Tools �ber das Internet aktualisieren","\n$self info update") : array ("","");
  3468.     out("$self [mode:Info|i] <func|Datei> <Parameter>\n
  3469. Funktionen (func):\n{{{tt}
  3470. AES|-|Verf�gbarkeit der AES-Entschl�sselung ausgeben
  3471. Arg <arg> <preg>|-|Geparste Argumente ausgeben
  3472. Cat [file]|-|Dateiinhalt mit Terminal-Charset ausgeben
  3473. CSV [file]|-|CSV-Datei als Tabelle ausgeben
  3474. Dir <dir>|-|Verzeichnis auflisten
  3475. Echo <str>|-|Parameter ausgeben
  3476. ExTension|-|Verf�gbarkeit der PHP-Erweiterungen anzeigen
  3477. eXtrakt [file] <dir>|-|Dateien aus Archiv auflisten oder entpacken
  3478. Globals|-|Alle PHP-Variabeln ausgeben
  3479. Hash <file\|str>|-|Hashes von einer Datei oder einem String erstellen
  3480. JSON [file]|-|JSON-Datei geparst ausgeben
  3481. OpenSsl|-|Verf�gbarkeit der OpenSSL-Bibliotek ausgeben
  3482. OTPauth <secret\|file>|-|TOTP Token-Generator (Google Authenticator)
  3483. PanGramm|-|Kodierungstest mit Umlauten und ASCII-Art
  3484. PHP|-|PHPInfo() ausgeben
  3485. PhpIni <find:Suchname>|-|Werte aus der PHP.ini ausgeben
  3486. StrfTime <str> <time>|-|Alle Zeit-Angaben von strftime ausgeben$var[0]
  3487. WebGet [url] <file\|:>|-|Datei herunterladen und HTTP-Header ausgeben}}".((ifset($cfg['help'],'/[ab]/i')) ? "\n
  3488. Beispiele:
  3489. $self info
  3490. $self info cat fb_config.php
  3491. $self info csv Anrufliste.csv -cs:';'
  3492. $self info dir
  3493. $self info echo \"Hello World!\"
  3494. $self info fb_config.php$var[1]
  3495. $self info hash file:'$script'
  3496. $self info json ./assets/meta.json
  3497. $self info otp secret:'ABCD EFGH IJKL MNOP QRST UVWX YZ23 4567'
  3498. $self info wg http://http.mengelke.de : -ua:Wget/1.10
  3499. $self info strftime '%d.%m.%y %H:%M:%S' @1234567890
  3500. $self i pg -c:ansi
  3501. $self i x -zp:password FRITZBox-assets.zip ./dir/" : ""));
  3502.     if(!$cfg['help'] or $cfg['help'] === true)
  3503.      $cfg['help'] = -1;
  3504.     if(ifset($cfg['uplink']))
  3505.      $opts .= "CSV:|-cs:|[Char]|CSV-Separator festlegen (;)
  3506. Extrakt:|-pa:|[TAR\|ZIP]|Archiv-Type festlegen
  3507. |-zp:|[Password]|ZIP-Kennwort festlegen
  3508. OTPauth:|-ft:|[strftime]|Eigenes Datumsformat
  3509. |-rp:|[count]|Anzahl der Token, die ausgegeben werden sollen
  3510. |-tf:|[Secret]|Secret f�r TOTP-Token
  3511. |-ts:|[time]|Zeit f�r die TOTP-Token
  3512. Update:|-f||Fehler Ignorieren
  3513. |-rd:|[dir]|RAW-Daten speichern
  3514. ";
  3515.    }
  3516.    elseif($arg = getArg('func','/^(?:   (?P<php>PHP)        |(?P<pi>pi|phpini)  |(?P<g>G(?:LOBALS)?)    |(?P<pg>P(?:anGramm|g))
  3517.     |(?P<c>c|Cat)   |(?P<e>e|Echo)  |(?P<wg>wg|W(eb)?Get)   |(?P<st>st|StrfTime)    |(?P<h>h(ash(er)?)?)    |(?P<os>os|OpenSSL)
  3518.     |(?P<d>d|Dir)   |(?P<a>a|Arg)   |(?P<t>t|Test)      |(?P<et>et|ExTension)   |(?P<ud>U(?:pdate|d))   |(?P<otp>otp(auth)?)
  3519.     |(?P<aes>aes)   |(?P<cs>csv)    |(?P<js>json)       |(?P<x>x|eXtra[ck]t)    )($)/ix') or ifset($val['i'],'/upgrade|ug/'))
  3520.     if($arg['pg'] and $var = "Welch fieser Katzentyp qu�lt da s��e V�gel blo� zum Jux?")  // Pangramm mit Kitty
  3521.      out(($vas = $cfg['zlib']['inflate'](base64_decode("VMqxCcQwEETR3OAefjYS7MjJZQJXIrxbiLnaD4X34sefd8GWEWE7Is/j23TDXZ3tihpWCcADpufci4sOjQXwxsfQ6Y4cYy4alKzzEA/AQ4FsSy0vW1DWys5v3pklJZUA")))
  3522.     ? wordwrap("$var\n",min((($cfg['wrap']) ? (int)$cfg['wrap'] : 80),42)).$vas : $var);
  3523.     elseif($arg['c'] and $file = getArg('file','file_exists'))  // Cat
  3524.      out(preg_replace('/^\xef\xbb\xbf/','',file_contents($file)));
  3525.     elseif($arg['js'] and $file = getArg('file','file_exists')) // JSON
  3526.      out(json2array(file_contents($file)));
  3527.     elseif($arg['os'])                  // OpenSSL
  3528.      out(($var = cfgdecrypt(0,'openssl')) ? $var : errmsg("8:Nicht vorhanden - Kein SSL/HTTPS m�glich!"));
  3529.     elseif($arg['aes'])                 // AES
  3530.      out(($var = cfgdecrypt(0,'aes')) ? ($val = count($var))." Bibliothek".(($val > 1) ? "en" : "")." zur Entschl�sselung vorhanden" : errmsg("8:Nicht vorhanden - Keine Entschl�sselung m�glich!"));
  3531.     elseif($arg['d'])                   // Dir
  3532.      out(implode("\n",(array)listDir(getArg('dir'),false,(int)getArg('opt'))));
  3533.     elseif($arg['t'])                   // Test{}
  3534.      out(($str = getArg('str')) ? ifset($str,is_callable($var = getArg('test')) ? "" : $var) : ";-)");
  3535.     elseif($arg['a']) {                 // Args
  3536.      $array = array('system' => $argv, 'arguments' => $cfg['arg'], 'available keys' => $cfg['argc'], 'labeled' => $cfg['args'], 'options' => $cfg['opts']);
  3537.      if($cfg['dbug'])
  3538.       $array['consign'] = $cfg['argk'];
  3539.      $var = getArg('arg','/^(?:(arg[cksv]?|'.implode('|',array_keys($array)).')|\w+)($)/i');
  3540.      out(($var and isset($cfg['arg'][$var[0]])) ? getArg($var[0],is_callable($preg = getArg('preg')) ? "" : $preg) : (($var and isset($cfg[$var[1]])) ? $cfg[$var[1]] : (($var and isset($array[$var[1]])) ? $array[$var[1]] : $array)));
  3541.     }
  3542.     elseif($arg['php']) {               // PHPInfo()
  3543.      cfgdecrypt();
  3544.      ob_start();
  3545.      phpinfo();
  3546.      $data = ob_get_contents();
  3547.      ob_end_clean();
  3548.      out(($cfg['php'][2] == 'cli') ? $data : preg_replace(array('/<style[^>]*>.*?<\/style>|<[^>]+>/s','/&#0?39;/','/&nbsp;/','/&amp;/'),array('',"'",' ','&'),$data));
  3549.     }
  3550.     elseif($arg['pi'] and $array = ini_get_all()) { // PHP.ini
  3551.      $preg = ($var = getArg('find')) ? "/".preg_quote($var,'/')."/i" : false;
  3552.      $ini = array();
  3553.      foreach($array as $key => $var) {
  3554.       $main = (preg_match('/^(\w+)\./',$key,$val)) ? $val[1] : "PHP";
  3555.       $key = preg_replace('/^\w+\./','',$key);
  3556.       if(!$preg or ifset($main,$preg) or ifset($key,$preg))
  3557.        foreach(array('global_value','local_value','access') as $val) {
  3558.         $vas = ($val == 'access') ?(($var[$val]&4) ? 's' : '-').(($var[$val]&2) ? 'p' : '-').(($var[$val]&1) ? 'u' : '-') : $var[$val];
  3559.         $ini[$main][$key][] = $vas;
  3560.        }
  3561.      }
  3562.      foreach($ini as $key => $var) {
  3563.       foreach($var as $k => $v)
  3564.        $var[$k] = trim("$k|$v[2]|".(($v[0] != $v[1]) ? (($v[0]) ? "$v[0] \| $v[1]" : $v[1]) : $v[0]));
  3565.       $ini[$key] = strtoupper("||\n[$key]\n").implode("\n",$var);
  3566.      }
  3567.      cfgdecrypt(0,'php');
  3568.      out($cfg['php'][5]."\n{{{tt}".implode("\n",$ini)."}}");
  3569.     }
  3570.     elseif($arg['g']) {                 // PHP-GLOBALS
  3571.      cfgdecrypt();
  3572.      $_ENV = getenv();
  3573.      $_CLASS = get_declared_classes();
  3574.      $_CONSTANT = get_defined_constants();
  3575.      $_EXTENSION = get_loaded_extensions();
  3576.      $_FUNCTION = get_defined_functions();
  3577.      $_PHPINI = ini_get_all();
  3578.      out($GLOBALS);
  3579.     }
  3580.     elseif($arg['et']) {                // PHP-Extension
  3581.      cfgdecrypt();
  3582.      ob_start();                    // PHPInfo() aufrufen
  3583.      phpinfo();
  3584.      $data = ob_get_contents();
  3585.      ob_end_clean();
  3586.      dbug($data);
  3587.      $array = array();
  3588.      foreach($cfg['mods'] as $key => $var) {
  3589.       $var = (is_array($var)) ? realpath($var[0]) : ((is_string($var)) ? realpath($var) : 'Intern oder bereits geladen');
  3590.       if($key == 'openssl')
  3591.        $array[$key] = OPENSSL_VERSION_TEXT;
  3592.       elseif($key == 'mysqli')
  3593.        $array[$key] = preg_replace(array('/(?<=\d)(?=(\d\d)+$)/','/\b0+(?=0\b)/'),array('.',''),mysqli_get_client_version());
  3594.       elseif(ifset($key,'/(aes\d*|sha(256|512)|hashtool)/'))
  3595.        $array[$key] = preg_match('/\/\/\s*\b[\w-]+ ([\d\.]+)/',file_contents($var),$val) ? $val[1] : '-/-';
  3596.       elseif(preg_match("/^$key$\s*(?:.*?)^$/msi",$data,$val) and preg_match("/^(?:$key(?:\s*api)?|compiled|)?\s*version.*?(\d[\w.]+)/mi",$val[0],$m))
  3597.        $array[$key] = $m[1];
  3598.       elseif(preg_match("/^$key version.*?(\d[\w ,.-]+)/mi",$data,$m))
  3599.        $array[$key] = $m[1];
  3600.       elseif(preg_match("/^".substr($key,0,-1)." library .*?(\d[\w ,.-]+)/mi",$data,$m))
  3601.        $array[$key] = $m[1];
  3602.       else
  3603.        $array[$key] = "Unbekannt";
  3604.       $array[$key] = "$key||".$array[$key]."||$var";
  3605.      }
  3606.      out($array ? "{{{tt}".implode("\n",$array)."}}" : errmsg("8:Keine Erweiterungen gefunden!"));
  3607.     }
  3608.     elseif($arg['e']) {                 // Echo
  3609.      $var = getArg('str',array()) or $var = getArg(0,array());
  3610.      if($cfg['dbug']) {
  3611.       ob_start();
  3612.       var_dump($var);
  3613.       $data = ob_get_contents();
  3614.       ob_end_clean();
  3615.       dbug($data);
  3616.      }
  3617.      else
  3618.       out(trim(implode(' ',$var)));
  3619.     }
  3620.     elseif($arg['st']) {                // strftime
  3621.      $arg = getArg('str');
  3622.      $time = ($var = getArg('time') and $var = strtotime($var)) ? $var : time();
  3623.      if($arg) {
  3624.       out($var = @strftime(trim($arg),$time));
  3625.       $var = strtotime($var);
  3626.       dbug(($var != $time) ? "$arg -> ".(($var === false) ? "false" : "Zeitunterschied: ".($time - $var)." sec") : "Format kann mit strtotime() erkannt werden");
  3627.      }
  3628.      else {
  3629.       $out = $array = array();
  3630.       for($a=65; $a <= 90; $a++)            // Alle Buchstaben
  3631.        for($b=0; $b < 2; $b++)              // Gross und kleinschreibung
  3632.         for($c=0; $c < 2; $c++) {           // Positiv und Negativ
  3633.          $key = ($c ? '-' : "").chr($a + $b * 32);  // Code-Zeichen berechnen
  3634.          $var = @strftime("%$key",$time);       // Code-Datum erstellen
  3635.          $val = str_replace(array("\n","\t"),array('\n','\t'),str_pad("%$key",4," ")."= $var"); // Code-Spalte erstellen
  3636.          if($var and !ifset($var,"/^%?".preg_quote($key,'/')."$/") and !ifset($key,"/^-?".preg_quote($var,'/')."$/") and (!$c or preg_replace('/^%-?(\w)\s*/','%$1  ',$val) != $array[substr($key,1)]))
  3637.           $array[$key] = str_replace('|','\|',$val);
  3638.         }
  3639. //  ksort($array);
  3640.       $array = array_values($array);
  3641.       $b = count($array);
  3642.       for($a=0; $a < ($c = ceil($b/2)); $a++)
  3643.        $out[] = $array[$a]."|".(isset($array[$a+$c]) ? $array[$a+$c] : "");
  3644.       out("{{{tt}".implode("\n",$out)."}}\n\nWeitere Hinweise finden Sie auf strftime.org");
  3645.      }
  3646.     }
  3647.     elseif($arg['cs'] and $file = getArg('file') and $data = preg_replace('/^\xef\xbb\xbf/','',file_contents($file))) { // CSV
  3648.      if(preg_match('/^.*?\bsep=(.)/i',$data,$var)) {
  3649.       $cs = $var[1];
  3650.       $data = preg_replace('/^.*\r?\n/','',$data);
  3651.      }
  3652.      else
  3653.       $cs = ";";
  3654.      if($var = getArg("-cs"))
  3655.       $cs = $var;
  3656.      print textTable(out($data,1),0,$cs);
  3657.     }
  3658.     elseif($arg['x'] and $file = getArg('file') and ($var = ifset($file,$cfg['ptar'])
  3659.     or $var = getArg('-pa','/'.strstr($cfg['ptar'],'(')))) { // Archive Extract
  3660.      $ft = getArg('-ft',0,'%d.%m.%Y %X');
  3661.      if($files = $var[4] ? zip2array(file_contents($file,0)) : datatar2array(file_contents($file))) {
  3662.       if($dir = getArg('dir')) {
  3663.        if(!file_exists($dir))
  3664.         makedir($dir,1);
  3665.        foreach($files as $key => $var) {
  3666.         out("$key ... ",2);
  3667.         if(!file_exists(dirname($key)))
  3668.          makedir(dirname($key),0);
  3669.         if(file_contents($key,$var['data']) or !$var['data']) {
  3670.          touch("$key",$var['mtime']);
  3671.          out("ok");
  3672.         }
  3673.         else
  3674.          out("fail");
  3675.        }
  3676.       }
  3677.       else {
  3678.     $typ = explode(',',"Daten,Gepackt,Programm,Document,Bild,Bin�r,Ascii,Ansi,Leer,UTF-8,UTF-8 BOM");
  3679.        $out = "Datei | Bytes|Typ |Datum\n";
  3680.        $sum = 0;
  3681.        foreach($files as $key => $var) {
  3682.         $sum += strlen($var['data']);
  3683.         $out .= "$key | ".number_format(strlen($var['data']),0,0,'.')."|"
  3684.     .$typ[preg_match('/^(PK\x03\x04|7z\xbc\xaf\'\x1c|\xfd7zXZ|\x1f\x8b\x08|BZh\d|Rar!)|^(MZ[\x00-\xff]\x00|\x7fELF|\xd0\xcf\x11\xe0\xa1\xb1\x1a\xe1\x00)'
  3685.     .'|^(%PDF|\x7b\\\\rtf1)|^(GIF8|\x89PNG|MM\x00|BM\xb6|\xff\xd8\xff\xe0)|(\x00)|^((?=[ -~\s]+$)...)|^(\xef\xbb\xbf)?((?=[\s -\xff]+$)...)|(^$)|(.)/s',$var['data'],$m)
  3686.     ? ($m[1] ? 1 : ($m[2] ? 2 : ($m[3] ? 3 : ($m[4] ? 4 : ($m[5] ? 5 : ($m[6] ? 6
  3687.     : (($m[8] and utf8($var['data']) != $var['data']) ? ($m[7] ? 10 : 9) : ($m[8] ? 7 : (($var['data'] == "") ? 8 : 0))))))))) : 0]." |".($var['mtime'] ? @strftime($ft,$var['mtime']) : " - ")."\n";
  3688.        }
  3689.        print textTable(out($out,1),0,"|","\n","|"," ").out("\n\nDateien gesamt: ".number_format(count($files),0,0,'.')." - Gesamtgr��e: ".number_format($sum)." Bytes",1);
  3690.       }
  3691.      }
  3692.      else
  3693.       out(errmsg(0,'*'));
  3694.     }
  3695.     elseif($arg['wg'] and $var = getArg('url','/^(?:(https?):\/\/)?([.\w-]+)(?::(\d+))?(.*)$/i')) { // WGet
  3696.      $opt = array(
  3697.     'host' => $var[2],
  3698.     'sock' => ($var[1]) ? $var[1] : 'auto',
  3699.     'page' => ($var[4]) ? $var[4] : '/',
  3700.     'method' => ($file = getArg('file')) ? (($file == ':') ? 'GET' : 'GET-save:'.$file) : 'GET-save:./');
  3701.      $opt['port'] = ($var[3]) ? $var[3] : ((strlen($opt['sock']) == 5) ? 443 : 80);
  3702.      out(($val = request($opt)) ? $val : (($cfg['http']) ? $cfg['http'] : errmsg("8:Aufruf fehlgeschlagen")));
  3703.     }
  3704.     elseif($arg['h'] and ($file = getArg('file','file_exists') or $str = getArg('str') or $file = $script)) { // Hashes berechnen
  3705.      $a = $b = 0;
  3706.      $hash = array();
  3707.      if(!ifset($str))
  3708.       $size = filesize($file);
  3709.      if(!function_exists('hash_algos')) // SHA-256 nachinstallieren
  3710.       cfgdecrypt(0,'mhash sha256 sha512');
  3711.      $algo = array('crc32b','md5','sha1','sha256','sha512');
  3712.      if(!isset($str) and function_exists('hash_init') and $fp = fopen($file,'r')) { // Hash direkt beim Laden erstellen
  3713.       foreach($algo as $var)        // Init Hashes
  3714.        $hash[$var] = hash_init($var);
  3715.       while(!feof($fp)) {       // Read Data
  3716.        $data = fread($fp,$cfg['sbuf']);
  3717.        foreach($hash as $var)       // Calc Hashes
  3718.         hash_update($var,$data);
  3719.        $a += strlen($data);     // Fortschritts-Anzeige berechnen
  3720.        $c = floor($a / max($a,$size) * max($cfg['wrap']-1,10)) - $b;
  3721.        dbug(str_repeat(".",$c),0,10);   // Download-Anzeige
  3722.        $b += $c;
  3723.       }
  3724.       dbug("\n",0,8);           // Download-Anzeige abschlie�en
  3725.       foreach($hash as $key => $var)    // Finalize Hashes
  3726.        $hash[$key] = hash_final($var);
  3727.       fclose($fp);
  3728.      }
  3729.      else
  3730.       foreach($algo as $var)        // Daten laden und dann ein Hash davon berechnen
  3731.        $hash[$var] = hash($var,ifset($str) ? $str : file_contents($file,0));
  3732.      $out = ($str ? "String:|$str" : "File:|$file\nSize:|".number_format($size,0,0,'.')." Bytes")."\n\n";
  3733.      foreach($hash as $key => $var) // Hashes ausgeben
  3734.       if($var = preg_replace('/(?<=\w)(?=(\w{8})+$)/i',' ',$var))
  3735.        $out .= preg_replace('/\D$/','',strtoupper($key)).":|$var\n";
  3736.      out("{{{tt}$out}}");
  3737.     }
  3738.     elseif($arg['otp'] and (function_exists('hash_hmac') or cfgdecrypt(0,'hashtool'))   // OTPAuth
  3739.     and ($data = getArg('secret',$preg = '/(?i:\b[A-Z2-7]{4}(\W?[A-Z2-7]{4}){7}\b)|^[A-Z2-7]{16,32}$/i0')   // secret-Parameter �berpr�fen
  3740.     or $file = getArg('file','file_exists') and $var = file_contents($file) and preg_match($preg,$var,$data)
  3741.     or $data = ifset($cfg['totp'],$preg) or $data = ifset($cfg['uipw'],$preg))) {   // file-Parameter �berpr�fen
  3742.      $ft = getArg('-ft',0,'%d.%m.%Y %X : ');                        // Option f�r eigenes Datum-Format
  3743.      $rp = getArg('-rp','/^\d+$/0',1);                          // Option f�r Multi-Token ausgabe
  3744.      $ts = getArg('-ts','/^[\w\s.:\/+-]+$/');                       // Option f�r die Uhrzeit
  3745.      $time = ($ts and $var = strtotime($ts)) ? $var : time();               // Aus der Uhrzeit ein Timestamp machen
  3746.      dbug("Nutze OATH-TOTP-Secret: ".preg_replace('/[^A-Z2-7]+/','',strtoupper($data)));
  3747.      if($otp = otpauth($data,$rp,$time)) {
  3748.       if(is_array($otp)) {
  3749.        foreach($otp as $key => $var)
  3750.         $otp[$key] = @strftime($ft,$key).$var;
  3751.        $otp = implode("\n",$otp);
  3752.       }
  3753.       out($otp);
  3754.      }
  3755.      else
  3756.       out(errmsg(0,'otpauth'));
  3757.     }
  3758.     elseif(ifset($cfg['uplink'],5) and ($arg['ud'] or ifset($val['i'],'/upgrade|ug/i'))) {  // FB_Tools Update
  3759.      if($cfg['sock'] == 'auto' and !$cfg['ssl'])            // SSL Laden
  3760.       $cfg['ssl'] = cfgdecrypt(0,'openssl');
  3761.      foreach($cfg['uplink']['port'] as $port)
  3762.       if($fbnet = request('GET-array',$cfg['uplink']['path'].$cfg['uplink']['fbts'].".md5",0,0,$cfg['uplink']['host'],$port)) {
  3763.        if($var = ifset($fbnet['Location'],'/^(https?:)(\/\/.+)$/'))
  3764.         $fbnet = request("$var[1][array]$var[2]");
  3765.        break;
  3766.       }
  3767.      if($fbnet and $rd = getArg('-rd','is_dir'))            // RAW-Daten Speichern?
  3768.       file_contents(realpath($rd)."/".$cfg['uplink']['fbts'].".md5",$fbnet[1]);
  3769.      if($fbnet and ifset($fbnet['Content-MD5'],hash('md5',$fbnet[1]))) {// Update-Check
  3770.       if(preg_match("/((\d\d)\.(\d\d)\.(\d{4}))\s[\d:]+\s*\((\w+)\s([\d.]+)\)(?:.*?(\w+)\s\*\w+\.$cfg[ext](?=\s))?/s",$fbnet[1],$up)) {
  3771.        $usrid = (ifset($fbnet['X-Usrid'])) ? preg_replace('/^0+/','',bin2hex(base64_decode($fbnet['X-Usrid']))) : false;
  3772.        if(intval($up[4].$up[3].$up[2]) > $cfg['ver'][9] and floatval($up[6]) > $cfg['ver'][10] or getArg('-f')) {
  3773.         out("Ein Update ist verf�gbar: $up[5] $up[6] vom $up[1]");
  3774.         if(!getArg('opt','/^(C(?:heck)?)$/il') or getArg('-f')) {
  3775.          out("Installiere Update ... ");
  3776.          $manuell = "!\nBitte installieren Sie es von http://{$cfg['uplink']['host']}/.dg manuell!";
  3777.          if(ifset($up[7]) and $up[8] = @request('GET',$cfg['uplink']['path'].$cfg['uplink']['fbts'].".$cfg[ext].gz?$usrid",0,0,$cfg['uplink']['host'],80)) {
  3778.           if($rd)
  3779.            file_contents(realpath($rd)."/".$cfg['uplink']['fbts'].".$cfg[ext].gz",$up[8]);
  3780.           $rename = preg_replace('/(?=(\.\w+)?$)/',"_{$cfg['ver'][2]}.bak",$script,1);  // Neuer Name f�r alte Version
  3781.           if($var = $cfg['zlib']['decode']($up[8]) and hash('md5',$var) == $up[7] and @rename($script,$rename)) {   // Update ab PHP5
  3782.            file_contents($script,$var);
  3783.            @chmod($script,intval(fileperms($rename),8));
  3784.            out("abgeschlossen!");
  3785.           }
  3786.           else
  3787.            out(errmsg("16:fehlgeschlagen$manuell"));
  3788.          }
  3789.          else
  3790.           out(errmsg("16:Automatisches Update ist nicht verf�gbar$manuell"));
  3791.         }
  3792.        }
  3793.        else {
  3794.         out("Kein neues Update verf�gbar!");
  3795.         if(ifset($up[6],$cfg['ver'][10]) and $up[7] != hash('md5',file_contents($script)))  // MD5-Check
  3796.          out(errmsg("1:Hinweis: $Self wurde ver�ndert"));
  3797.        }
  3798.        mytouch(1);                          // Aktuelles Datum setzen
  3799.       }
  3800.       else                              // fb_tools.md5 nicht verf�gbar
  3801.        out(errmsg("16:Update-Server sagt NEIN! - Keine g�ltigen Updates verf�gbar"));
  3802.       if(ifset($fbnet['X-Cookie']))                 // Coolen Spruch ausgeben
  3803.        out("\n".$fbnet['X-Cookie']);
  3804.      }
  3805.      else                               // Kein Netzwerk/Internet verf�gbar
  3806.       out(errmsg("16:Computer sagt NEIN! - Entweder ist MEngelke offline oder kein Netzwerk/Internet ist verf�gbar"));
  3807.     }
  3808.     else
  3809.      out(errmsg("2:Unerwartete Parameter �bergeben!"));
  3810.    else {                       // FB_Tools-Version und PHP Kurzinfos ausgeben
  3811.     $var = array("PHP {$cfg['php'][0]}/{$cfg['php'][2]} ({$cfg['php'][4]} Bit)",$cfg['php'][1]);
  3812.     out($cfg['ver'][0]."\n\n".implode(($cfg['wrap'] and strlen($var[0].$var[1])+3 < $cfg['wrap']) ? " - " : "\n",$var)
  3813.     .(ifset($cfg['cron']) ? "" : "\nTerminal: Breite: $cfg[wrap], Zeichensatz: {$cfg['char'][0]}, OS: ".strtoupper($cfg['os']).", Benutzer: $cfg[cu]")
  3814.     .(ifset($cfg['loadcfg']) ? "\n\n{{{tt}Konfig-Datei:|".str_replace('|',', ',$cfg['loadcfg'])."|}}" : "")
  3815.     .(ifset($dev) ? "\nDeveloper-Location: ".((preg_match('/^\w{3,}:/',$dev)) ? $dev : realpath($dev))
  3816.     .((isset($http_response_header) and $val = preg_array('/^X-Cookie/',$http_response_header)) ? "\n".ifset($val,'/: (.*)/1') : "") : ""));
  3817.    }
  3818.   }
  3819.   elseif($val['al']) {                  // Anrufliste
  3820.    if(ifset($cfg['help'])) {                        // Hilfe Ausgeben
  3821.     out("$self <fritz.box> [mode:AnrufListe|al] <file:Datei/Ordner> <from:zeit> <to:zeit>".((ifset($cfg['help'],'/[ab]/i')) ? "\n
  3822. Beispiele:
  3823. $self fritz.box mode:anrufliste file:calllist-%y%m%d.csv -cs:\"\\t\"
  3824. $self fritz.box al
  3825. $self fritz.box al from:2018-01-01 \"to:2018-12-31 23:59\"
  3826. $self fritz.box mode:anrufliste file:call_%G-%m-%d.csv -ch -lf" : "")."\n");
  3827.   if(!$cfg['help'] or $cfg['help'] === true)
  3828.    $cfg['help'] = -1;
  3829.   $opts .= "AnrufListe:|-ch||Schreibt in der Datei ein CSV-Header
  3830. |-cs:|[Char]|CSV-Separator festlegen (;)
  3831. |-ft:|[Strftime]|Eigenes Datumsformat
  3832. |-lf||Schreibt die Daten als Logfile";
  3833.    }
  3834.    elseif($sid = (ifset($cfg['bsid'])) ? $cfg['bsid'] : login()) {
  3835.     if($cfg['bsid'] or $cfg['fiwa'] < 530 or isset($cfg['auth']['BoxAdmin'])) {
  3836.      dbug("Download der Anrufliste anfordern");
  3837.      $pfile = getArg('file');
  3838.      $from = ($var = getArg('from') and $val = strtotime($var) and $val != -1) ? $val : false;
  3839.      $to = ($var = getArg('to') and $val = strtotime($var) and $val != -1) ? $val : false;
  3840.      $file = ($pfile and strpos($pfile,'%') !== false) ? @strftime($pfile) : ((!$pfile or ifset($pfile,'/^[:*]$/')) ? false : $pfile);
  3841.      $ftime = getArg('-ft');                        // Benutzerdefiniertes Datum-Format
  3842.      if($data = getcall('all')) {                   // Anrufliste holen
  3843.       dbug($data,4);
  3844.       $count = 0;
  3845.       $sep = strtr((!$file) ? '|' : getArg('-cs',0,$data['sep']),array('\t' => "\t"));  // Seperator f�r CSV-Dateien
  3846.       $psep = preg_quote($sep,'/');
  3847.       $csv = (!$file or getArg('-ch')) ? preg_replace("/".preg_quote($data['sep'],'/')."/",$sep,$data['csv']) : ""; // CSV-Header
  3848.       $call = array();                          // Zeitbereich ausw�hlen
  3849.       foreach($data['call'] as $time => $var)
  3850.        if((!$from or $time >= $from) and (!$to or $time <= $to)) {
  3851.         if($ftime)
  3852.          $var[1] = @strftime($ftime,$time);
  3853.         $var[0] = str_replace($sep,"\\$sep",strtr($var[0],array('fail','in','ring','drop','out')));
  3854.         $call[$time] = implode($sep,$var);
  3855.        }
  3856.       dbug(count($call).((count($call) != count($data['call'])) ? "/".count($data['call']) : "")." Anruf(e) wurden ausgelesen");
  3857.       if(!$file)                                // Anrufliste auf den Bildschirm ausgeben
  3858.        out("{{{tt}".utf8(preg_replace('/^.*sep=.*\r?\n/','',$csv).implode("\n",$call))."}}");
  3859.       else {                                // CSV-Datei speichern
  3860.        $preg = "/((?:[0-4]|fail|in|ring|drop|out)$psep((0[1-9]|[12]\d|3[10])\.(0[1-9]|1[0-2])\.(?:20)?(\d\d)\s+([\d:]+)|[\w .:\/+-]+)($psep(.*?)){4,5})\s*$/";
  3861.        if(getArg('-lf')) {                      // Logmodus
  3862.         dbug("Anrufliste im Logfile-Modus speichern");
  3863.         $last = -1;
  3864.         foreach($call as $key => $var) {
  3865.          if($file != ($val = (strpos($pfile,'%') !== false) ? @strftime($pfile,intval($key)) : $pfile))
  3866.           $file = $val;
  3867.          $date = 0;
  3868.          if(file_exists($file)) {
  3869.           if($data = file_contents($file,-256) and preg_match($preg,$data,$m))
  3870.            $date = strtotime(($m[3]) ? "20$m[5]-$m[4]-$m[3] $m[6]" : $m[2]);
  3871.          }
  3872.          elseif($csv)
  3873.           file_contents($file,$csv);                    // CSV-Header anlegen
  3874.          if(intval($key) > $date or intval($key) == $last) {        // or intval($key) == $date and $var != $val[1]
  3875.           file_contents($file,"$var\r\n",8);                // Anruf speichern
  3876.           $last = intval($key);
  3877.           $count++;
  3878.          }
  3879.         }
  3880.        }
  3881.        else {                               // Anrufliste normal in Datei speichern
  3882.         if(file_exists($file)) {
  3883.          $date = 0;
  3884.          if($data = file_contents($file,-256) and preg_match($preg,$data,$m))
  3885.           $date = strtotime(($m[3]) ? "20$m[5]-$m[4]-$m[3] $m[6]" : $m[2]);
  3886.          foreach($call as $key => $var)
  3887.           if(intval($key) <= $date)
  3888.            unset($call[$key]);
  3889.          if($call)
  3890.           file_contents($file,implode("\r\n",$call)."\r\n",8);      // Anruf speichern
  3891.         }
  3892.         else
  3893.          file_contents($file,$csv.implode("\r\n",$call)."\r\n");        // Anruf speichern
  3894.         $count = count($call);
  3895.        }
  3896.       }
  3897.       if($count)
  3898.        out("Es wurde".(($count == 1) ? " 1 neuer Eintrag" : "n $count neue Eintr�ge")." gespeichert");
  3899.      }
  3900.      else
  3901.       out(errmsg("8:Keine Anrufliste erhalten!"));
  3902.     }
  3903.     else
  3904.      out(errmsg("8:Benutzer hat nicht das Recht f�r die Administration"));
  3905.     if(!ifset($cfg['bsid']))                        // Abmelden
  3906.      logout($sid);
  3907.    }
  3908.    else
  3909.     out(errmsg(0,'login'));                     // Login fehlgeschlagen
  3910.   }
  3911.   elseif($val['bi']) {                  // Jason/Juis Boxinfo
  3912.    if(ifset($cfg['help'])) {
  3913.     out("$self <fritz.box> [mode:BoxInfo|bi] <file:jason_boxinfo.xml>".((ifset($cfg['help'],'/[ab]/i')) ? "\n
  3914. Beispiele:
  3915. $self fritz.box mode:boxinfo file:/media/stick/jason_boxinfo.xml
  3916. $self fritz.box bi
  3917. $self fritz.box boxinfo -rd:debug
  3918. $self boxinfo" : ""));
  3919.     if(!$cfg['help'] or $cfg['help'] === true)
  3920.      $cfg['help'] = -1;
  3921.     $opts .= "Boxinfo:|-rd:|<path>|Schreibt die RAW-Daten";
  3922.    }
  3923.    elseif($data = boxinfo(($arg = getArg('file','file_exists')) ? file_contents($arg) : false,$path = getArg('-rd'))) {
  3924.     if(is_array($data)) {               // RAW-Daten Speichern
  3925.      if(!is_bool($path))
  3926.       if(!file_exists($path))
  3927.        makedir($path);
  3928.       elseif(is_dir($path))
  3929.        chdir($path);
  3930.      foreach($data as $key => $var)
  3931.       if(!is_int($key))
  3932.        file_contents("$key",$var[1]);
  3933.      $data = $data[0];
  3934.     }
  3935.     out("Boxinfos:\n".$data);
  3936.    }
  3937.    elseif($data === '')
  3938.     out(errmsg("8:Keine BoxInfos erhalten"));
  3939.    else
  3940.     out(errmsg(0,'request'));
  3941.   }
  3942.   elseif($val['gip']) {                 // Get Extern IP
  3943.    if(ifset($cfg['help']))
  3944.     out("$self <fritz.box> [mode:GetIP|gip] <filter>".((ifset($cfg['help'],'/[ab]/i')) ? "\n
  3945. Beispiele:
  3946. $self fritz.box mode:getip filter:ipv4
  3947. $self fritz.box gip
  3948. $self getip
  3949. $self gip dns" : ""));
  3950.    elseif($array = getexternalip()) {
  3951.     if($var = getArg('filter','/[-\w]+/'))
  3952.      $array = preg_array("/$var[0]/i",$array,3);
  3953.     foreach($array as $key => $var)
  3954.      $array[$key] = "$key:|$var";
  3955.     if($array)
  3956.      out("{{{tt}".implode("\n",$array)."}}");
  3957.     else
  3958.      out(errmsg("8:Keine Daten erhalten"));
  3959.    }
  3960.    elseif($var = errmsg(0,'getexternalip'))
  3961.     out($var);
  3962.    else
  3963.     out(errmsg("8:UPnP Deaktiviert oder keine IP-Adressen erhalten"));
  3964.   }
  3965.   elseif($val['e']) {                   // Ereignisse
  3966.    if(ifset($cfg['help'])) {
  3967.     out("$self <fritz.box> [mode:Ereignisse|e] <file> <filter> <from:zeit> <to:zeit>\n
  3968. Folgende Filter sind M�glich: alle, telefon, internet, usb, wlan, system".((ifset($cfg['help'],'/[ab]/i')) ? "\n
  3969. Beispiele:
  3970. $self fritz.box mode:Ereignisse file:event-internet.csv filter:internet -cs:;
  3971. $self fritz.box Ereignisse event.csv
  3972. $self fritz.box e -pw:secret
  3973. $self fritz.box e logs-%y%m%d.log alle -lf" : ""));
  3974.     if(!$cfg['help'] or $cfg['help'] === true)
  3975.      $cfg['help'] = -1;
  3976.     $opts .= "Ereignisse:|-ch||Schreibt in der Datei ein CSV-Header
  3977. |-cs:|[Char]|CSV-Separator festlegen ( )
  3978. |-ft:|[Strftime]|Eigenes Datumsformat
  3979. |-lf||Schreibt die Daten als Logfile";
  3980.    }
  3981.    elseif($sid = (ifset($cfg['bsid'])) ? $cfg['bsid'] : login()) {  // Einloggen
  3982.     if($cfg['bsid'] or $cfg['fiwa'] < 530 or isset($cfg['auth']['BoxAdmin'])) {
  3983.      $pfile = getArg('file');
  3984.      $file = (strpos($pfile,'%') !== false) ? @strftime($pfile) : ((ifset($file,'/^[:*]$/')) ? false : $pfile);
  3985.      $filter = preg_array('/^'.getArg('filter','/^(?=a(lle)?|t(elefon)?|i(nternet)?|u(sb)?|w(lan)?|s(ystem)?)\w/i0',0,'a').'/i',explode(',','alle,telefon,internet,usb,wlan,system'));
  3986.      $from = ($var = getArg('from') and $val = strtotime($var) and $val != -1) ? $val : false;
  3987.      $to = ($var = getArg('to') and $val = strtotime($var) and $val != -1) ? $val : false;
  3988.      $sep = strtr(getArg('-cs',0,' '),array('\t' => "\t"));     // Seperator f�r CSV-Dateien
  3989.      $psep = preg_quote($sep,'/');
  3990.      $count = 0;
  3991.      $preg = array("/(0[1-9]|[12]\d|3[10])\.(0[1-9]|1[0-2])\.(?:20)?(\d\d)$psep([\d:]+)$psep(.*?)\s*$/","/(?<=^|\\n)([\w .:+\/-]+)$psep(.*?)\s*$/");
  3992.      $ftime = getArg('-ft');                        // Benutzerdefiniertes Datum-Format
  3993.      if($array = getevent($filter)) {                   // Ereignisse holen
  3994.       $event = array();                         // Zeitbereich ausw�hlen
  3995.       foreach($array as $key => $var)
  3996.        if($time = intval($key) and (!$from or $time >= $from) and (!$to or $time <= $to))
  3997.         $event[$key] = utf8($var);
  3998.       dbug(count($event).((count($event) != count($array)) ? "/".count($array) : "")." Event(s) wurden ausgelesen");
  3999.       if($file and getArg('-lf')) {                 // Logmodus
  4000.        dbug("Ereignisse im Logfile-Modus speichern");
  4001.        $last = -1;
  4002.        foreach($event as $key => $var) {
  4003.         if($file != ($val = (strpos($pfile,'%') !== false) ? @strftime($pfile,intval($key)) : ((ifset($file,'/^[:*]$/')) ? false : $pfile)))
  4004.          $file = $val;
  4005.         $date = (file_exists($file)) ? (($data = file_contents($file,-1024) and preg_match($preg[0],$data,$m)) ? strtotime("20$m[3]-$m[2]-$m[1] $m[4]") : 0) : 0;
  4006.         if(intval($key) > $date or intval($key) == $last) {
  4007.          $last = intval($key);
  4008.          file_contents($file,($ftime ? @strftime($ftime,$last) : "$var[0]$sep$var[1]")."$sep$var[2]\n",8);  // Ereignisse speichern
  4009.          $count++;
  4010.         }
  4011.        }
  4012.       }
  4013.       elseif($file) {                           // Ereignisse normal in Datei speichern
  4014.        dbug("Ereignisse normal speichern");
  4015.        $date = 0;
  4016.        if(file_exists($file)) {
  4017.         $data = file_contents($file,-1024);
  4018.         if(preg_match($preg[0],$data,$m))
  4019.          $date = strtotime("20$m[3]-$m[2]-$m[1] $m[4]");
  4020.         elseif(preg_match($preg[1],$data,$m))
  4021.          $date = strtotime($m[1]);
  4022.        }
  4023.        $log = array();
  4024.        foreach($event as $key => $var)
  4025.         if(intval($key) > $date)
  4026.          $log[] = ($ftime ? @strftime($ftime,intval($key)) : "$var[0]$sep$var[1]")."$sep$var[2]";
  4027.        if($count = count($log))
  4028.         file_contents($file,implode("\n",$log)."\n",8);         // Ereignisse speichern
  4029.       }
  4030.       elseif($event) {                          // Ereignisse auf den Bildschirm ausgeben
  4031.        $val = "";
  4032.        foreach($event as $key => $var)
  4033.         $val .= ($ftime ? @strftime($ftime,intval($key)) : "$var[0] $var[1]")."|$var[2]\n";
  4034.        out("{{{tt}$val}}");
  4035.       }
  4036.       if($count)
  4037.        out("Es wurde".(($count == 1) ? " 1 neuer Eintrag" : "n $count neue Eintr�ge")." gespeichert");
  4038.      }
  4039.      else
  4040.       out(errmsg(0,'getevent'));
  4041.     }
  4042.     else
  4043.      out(errmsg("8:Benutzer hat nicht das Recht f�r die Administration"));
  4044.     if(!ifset($cfg['bsid']))                    // Ausloggen
  4045.      logout($sid);
  4046.    }
  4047.    else
  4048.     out(errmsg(0,'login'));
  4049.   }
  4050.   elseif($val['k']) {                   // Konfig
  4051.    if(ifset($cfg['help']) or !getArg(true))
  4052.     out("$self <fritz.box> [mode:Konfig|k] [func:Funktion] <Datei|Ordner> <Kennwort>\n
  4053. Funktionen (func):\n{{{tt}
  4054. ExPort|<of:file> <pass>|-|Konfig exportieren(1)
  4055. ExPort-DeCrypt|<of:file> <pass>|-|Konfig entschl�sseln und exportieren(1,3)
  4056. ExTrakt|<of:dir> <pass>|-|Konfig entpackt anzeigen/exportieren(1)
  4057. ExTrakt-DeCrypt|<of:dir> <pass>|-|Konfig entpackt entschl./anz./exp.(1,3)
  4058. File|[if:file] <of:dir>|-|Konfig aus Datei entpacken und anzeigen(2)
  4059. File|[if:dir] [of:file]|-|Konfig-Ordner in Datei zusammenpacken(2)
  4060. File-CalcSum|[if:file/dir] [of:file]|-|Konfig-Datei/Ordner f�r Import Vorbereiten(2)
  4061. File-JSON|[if:file] [of:file]|-|Konfig-Daten in JSON konvertieren(2)
  4062. File-DeCrypt|[if:file] [pass:list/file]||<of:file> - Konfig-Daten entschl�sseln(2,3,4)
  4063. ImPort|[if:file/dir] <pass>|-|Konfig importieren(1)
  4064. ImPort-CalcSum|[if:file/dir] <pass>|-|Ver�nderte Konfig importieren(1)}}\n
  4065. (1) Anmeldung mit Logindaten und 2FA erforderlich / (2) Ohne Fritz!Box nutzbar
  4066. (3) Eins von (php_openssl, php_mcrypt, aes.php, aes_4.class.php) erforderlich
  4067. (4) Mehrere Angaben m�glich (pass:foo pass:bar pass:test oder pass[/]:foo/bar/test)
  4068. [ ] Pflicht | < > Optional | ( ) Auswahl\n
  4069. Ab OS 6.69 ist beim Login eine Zwei-Faktor-Authentisierung erforderlich, falls aktiviert".((ifset($cfg['help'],'/[ab]/i')) ? "\n
  4070. Beispiele:
  4071. $self fritz.box konfig export
  4072. $self fritz.box konfig extrakt
  4073. $self konfig file fritzbox.export.gz
  4074. $self konfig file-decrypt fb.export geheim fbdc.export -d
  4075. $self fritz.box konfig extract archiv.tar.gz
  4076. $self k fcs Export-Ordner fritzbox.export
  4077. $self fritz.box konfig import \"fb 7170.export\"
  4078. $self fritz.box konfig import archiv.tar.gz
  4079. $self fritz.box k ipcs \"FRITZ.Box Fon WLAN 6360 85.04.86_01.01.00_0100.export\"
  4080. $self k fdc if:fb7390_nopass.export pass:admin123 pass:11:23:58:13:21:34 pass:passwd.txt
  4081. $self k fdc if:fb7530_nopass.export of:fb7530_decrypt.export pass:K175.678.30.000.196-98:9B:CB:30:01:96" : ""));
  4082.    elseif($mode = getArg('func','/^(                    # 1:Alle
  4083.     |i(p|mport)(cs|-calcsum)?                   # 2:Import 3:CalcSum
  4084.     |e(p|xport)(?:(dc|-de(?:crypt|code))?)              # 4:Export 5:DeCrypt
  4085.     |(et|(?:extra[ck]t))?(?:(dc|-de(?:crypt|code))?)        # 6:Extrakt 7:DeCrypt
  4086.     |(f(?:ile)?)(?:(cs|-calcsum)?|(dc|-de(?:crypt|code))?|(-?json)?)# 8:File 9:CalcSum 10:DeCrypt 11:JSON
  4087.         )$/ix')) {
  4088.     dbug($mode,3);                  // Debug Parameter
  4089.     $mode = array_pad($mode,12,null);
  4090.     $file = getArg('if');
  4091.     if($pw = getArg('pass',array()))            // Multipass ;-)
  4092.      $pass = reset($pw);
  4093.     $save = getArg('of');
  4094.     if(($mode[5] or $mode[7] or $mode[10]) and !cfgdecrypt(0,'aes')) {
  4095.      out(errmsg("64:Die Entschl�sselung wird von ihren System nicht unterst�tzt!\nBitte Installieren Sie die AES-Scripte aus dem Archiv: fb_Tools.7z\n\n"));
  4096.      $mode[5] = $mode[7] = $mode[10] = false;
  4097.     }
  4098.     if(($mode[2] or $mode[4] or $mode[6])) {        // Login Optionen
  4099.      if($sid = (ifset($cfg['bsid'])) ? $cfg['bsid'] : login(0,0,true)) {
  4100.       if($cfg['bsid'] or $cfg['fiwa'] < 530 or isset($cfg['auth']['BoxAdmin'])) {
  4101.          $file = getArg('of',false,$file);      // Arg[of]
  4102.          if(!ifset($pass))
  4103.           $pass = false;
  4104.          if(($mode[5] or $mode[7]) and !$pass)      // Im DeCode-Modus kein leeres Kennwort zulassen
  4105.           $pass = (ifset($cfg['pass'],'/^[ -~]+$/')) ? $cfg['pass'] : 'geheim';
  4106.          if($mode[4]) {                 // Export
  4107.           if(is_dir($file)) {               // Im Ordner schreiben
  4108.            makedir($file);              // Verzeichnis erstellen
  4109.            $file = false;
  4110.           }
  4111.           if($mode[5] and $pass and $data = cfgexport('array',$pass) and $data[1]) {    // Exportieren mit Entschl�sselten Benutzerdaten
  4112.            dbug("Entschl�ssele Konfig-Daten");
  4113.            if($data[1] and $data[1] = cfgdecrypt($data[1],$pass)) {
  4114.             out(showaccessdata($data[1]));
  4115.             saverpdata($file,$data,'file.export');
  4116.            }
  4117.            else
  4118.             out(errmsg(0,'cfgdecrypt') || errmsg(0,'cfgexdport') || errmsg(0,'request'));
  4119.           }
  4120.           elseif(!ifset($data))                 // Export direkt File
  4121.            out(cfgexport($file ? $file : true,$pass) ? "Konfiguation wurde erfolgreich exportiert" : errmsg(0,'request'));
  4122.           else
  4123.            out(($var = errmsg(0,'request')) ? $var : errmsg("8:Keine Konfig erhalten - M�glichlichweise ist noch die Sicherheits-Best�tigungsfunktion aktiviert?"));
  4124.          }
  4125.          elseif($mode[6]) {                 // Extrakt
  4126.           if($data = cfgexport('array',$pass) and $data[1]) {   // Konfigdaten holen
  4127.            $mod = $file ? (preg_match($cfg['ptar'],$file,$var) ? ($var[4] ? 5 : (($cfg['bzip'] and $var[3]) ? 4 : ($var[2] ? 3 : 2))) : 1) : 0;
  4128.            if($mod == 1)
  4129.             makedir($file);                 // Verzeichnis erstellen
  4130.            dbug("Entschl�ssele Konfig-Daten");
  4131.            if($mode[7] and $pass and $data[2] = cfgdecrypt($data[1],$pass,$sid))    // Konfig Entschl�sseln
  4132.             out(cfginfo($data[2],$mod,$file,showaccessdata($data[2])));
  4133.            else
  4134.             out(cfginfo($data[1],$mod,$file));
  4135.           }
  4136.           else
  4137.            out(($var = errmsg(0,'request')) ? $var : errmsg("8:Keine Konfig erhalten - M�glichlichweise ist noch die Sicherheits-Best�tigungsfunktion aktiviert?"));
  4138.          }
  4139.          elseif($mode[2] and $file and file_exists($file))  // Import-Konfig
  4140.           out((cfgimport($file,$pass,$mode[3])) ? "Konfig wurde hochgeladen und wird nun bearbeitet" : errmsg(0,'cfgimport'));
  4141.          else
  4142.           out(errmsg("8:$file kann nicht ge�ffnet werden!"));
  4143.       }
  4144.       else
  4145.        out(errmsg("8:Benutzer hat nicht das Recht f�r die Administration"));
  4146.       if(!ifset($cfg['bsid']))
  4147.        logout($sid);
  4148.      }
  4149.      else
  4150.       out(errmsg(0,'login'));
  4151.     }
  4152.     elseif($file = getArg('if',false,$file) and $mode[8] and !$mode[10] and !$mode[11] and is_file($file) and $data = file_contents($file) and preg_match('/^\*{4}\s+\w+.*CONFIGURATION EXPORT/',$data)) {  // Converter-Modus File -> Dir
  4153.      $mod = ($save = getArg('of',false,$pass)) ? ((preg_match($cfg['ptar'],$save,$var)) ? (($cfg['bzip'] and ifset($var[3])) ? 4 : ((ifset($var[2])) ? 3 : 2)) : 1) : 0;
  4154.      if($mod == 1 and (!file_exists($save) or !is_dir($save)) and $var = cfgcalcsum($data))
  4155.       out((file_contents($save,$var[2])) ? (($var[0] == $var[1]) ? "Konfig-Checksumme ist korrekt!" : errmsg("1:Konfig-Checksumme wurde von $var[0] auf $var[1] korrigiert!")) : errmsg("32:Konfig-Datei konnte nicht gespeichert werden!"));
  4156.      else
  4157.       out(($data = cfginfo($data,$mod,$save)) ? $data : errmsg("16:Defekte Konfig Export-Datei angegeben"));
  4158.     }
  4159.     elseif($mode[8] and !$mode[10] and !$mode[11] and (preg_match($cfg['ptar'],$file,$val) and is_file($file) or is_dir($file))) {  // Converter-Modus Dir/Tar -> File
  4160.      $array = array();
  4161.      if($val)
  4162.       $array = ($val[4] and $data = file_contents($file)) ? zip2array($data,array(),array(),true) : tar2array($file);   // Archiv als Array einlesen
  4163.      out($array ? (($data = cfgmake($array,$mode[9],$save)) ? ($save ? $data : cfginfo($data)) : errmsg("10:Kein Konfig Export-Archiv/Verzeichnis angegeben")) : errmsg(0,'tar2array'));
  4164.     }
  4165.     elseif($mode[8] and $mode[10] and !$mode[11] and $pass and is_file($file) and $data = (preg_match($cfg['ptar'],$file,$var)) ? cfgmake($var[4] ? zip2array(file_contents($file),array(),array(),1) : tar2array($file)) : file_contents($file)) { // Kennw�rter Entschl�sseln
  4166.      if(preg_match('/^\*{4} .*? CONFIGURATION EXPORT/',$data)) {
  4167.       foreach($pw as $pass) {
  4168.        if($fp = (file_exists($pass)) ? $cfg['zlib']['open']($pass,'r') : false) {// Passwordliste einlesen
  4169.         $cfg['errmute'] = true;                         // Fehlermeldungen pausieren
  4170.         dbug("Lese Password-Liste: $pass");
  4171.        }
  4172.        while($pwd = $fp ? $cfg['zlib']['gets']($fp,$cfg['sbuf']) : $pass)   // Password-Argument oder Passwordliste durchgehen
  4173.         if($pass = false or $pwd = preg_replace('/[\r\n]+$/','',$pwd)) {    // Password von cr/lf bereinigen
  4174.          dbug(".",0,10);
  4175.          if(isset($cfg['error']['cfgdecrypt']))                 // Alte Fehlermeldung entfernen
  4176.           unset($cfg['error']['cfgdecrypt']);
  4177.          if($dcdata = cfgdecrypt($data,$pwd)) {                 // Konfig mit Kennwort entschl�sseln
  4178.           dbug("\nKonfig-Kennwort gefunden: $pwd",0,8);
  4179.           if($save) {
  4180.            if(preg_match('/^(.*?)[\\\\\/]$/',$save,$var)) {         // Verzeichnis erstellen
  4181.             makedir($save);
  4182.             $mod = 1;
  4183.             $save = $var[1];
  4184.            }
  4185.            elseif(preg_match($cfg['ptar'],$save,$var))
  4186.             $mod = (($cfg['bzip'] and ifset($var[3])) ? 4 : ((ifset($var[2])) ? 3 : 2));
  4187.            else {
  4188.             file_contents($save,$dcdata);                   // Entschl�sselte Konfig sichern
  4189.             $mod = 0;
  4190.            }
  4191.           }
  4192.           else
  4193.            $mod = 0;
  4194.           out(cfginfo($dcdata,$mod,$save,showaccessdata($dcdata)));     // Daten als Text Pr�sentieren
  4195.           break;
  4196.          }
  4197.         }
  4198.        dbug("",0,8);
  4199.        if($fp)
  4200.         $cfg['zlib']['close']($fp);
  4201.       }
  4202.       $cfg['errmute'] = false;                          // Fehlermeldungen pausieren
  4203.       if(!$dcdata)
  4204.        out(errmsg(0,'cfgdecrypt'));
  4205.  
  4206.      }
  4207.      else
  4208.       out(errmsg("10:Keine Konfig-Datei angegeben!"));
  4209.     }
  4210.     elseif($mode[8] and $mode[11] and is_file($file) and $pass = getArg('of',false,$pass))  // JSON Konverter (File -> File)
  4211.      if(function_exists('json_encode'))
  4212.       if($data = file_contents($file) and $array = konfig2array($data))
  4213.        if($data = json_encode($array) and file_contents($pass,$data))
  4214.         out("Konfig-Datei erflogreich in JSON konvertiert");
  4215.        else
  4216.         out(errmsg("64:JSON_Encode von PHP {$cfg['php'][0]} ist fehlgeschlagen"));
  4217.       else
  4218.        out(errmsg("16:Keine Konfig-Datei"));
  4219.      else
  4220.       out(errmsg("64:JSON wird von PHP {$cfg['php'][0]} nicht unterst�tzt"));
  4221.     else
  4222.      out(errmsg("10:Parameter-Ressourcen zu Konfig $mode[0] nicht gefunden oder nicht korrekt angegeben"));
  4223.    }
  4224.    else
  4225.     out(errmsg("2:Unbekannte Funktionsangabe f�r Konfig"));
  4226.   }
  4227.   elseif($val['kf']) {                  // Komfort-Funktionen Schalten
  4228.    if(ifset($cfg['help']) or !getArg(true))
  4229.     out("$self <fritz.box> [mode:Komfort|kf] <func> <cmd:an|on|aus|off|test> <id>\n
  4230. Funktionen: (func)\n{{{tt}
  4231. list ||Listet alle Komfortfunktionen auf, die geschaltet werden k�nnen
  4232. wlan |wifi |Das Haupt-WLAN an/abschalten
  4233. gast |guest |Das Gast-WLAN an/abschalten
  4234. wlan-wps |wifi-wps |WPS f�r das Haupt-WLAN ausl�sen
  4235. gast-wps |guest-wps |WPS f�r das Gast-WLAN ausl�sen
  4236. ruf |rules |Rufumleitungen an/abschalten
  4237. ab |tam |Anrufbeantworter an/abschalten
  4238. wecker |alarm |Weckruf an/abschalten}}".((ifset($cfg['help'],'/[ab]/i')) ? "\n
  4239. Beispiele:\n$self fritz.box kf list
  4240. $self fritz.box komfort wlan aus
  4241. $self fritz.box komfort gast-wps an
  4242. $self fritz.box mode:komfort func:rufumleitung cmd:aus id:rul_4
  4243. $self fritz.box komfort wecker test 2
  4244. $self fritz.box komfort test alarm1
  4245. $self fritz.box kf ab an 2
  4246. $self fritz.box kf wecker aus 0" : "")."\n");
  4247.    elseif(login(false) >= 680 or getArg('-f')) {            // Parameter �berpr�fen
  4248.     $func = getArg('func','/^(?:
  4249.     (list)                              # 1: list
  4250.     |(?:(wlan|wifi) |(gast-?(?:wlan)?|(?:wifi)?guest))(-?wps)?  # 2: wlan, 3: gast, 4: wps
  4251.     |(ru(?:les)?|(?:an)?ruf(?:umleitung(?:en)?)?|calles)        # 5: Rufumleitung
  4252.     |(t?a[bm]|answer|anruf(?:beanworter)?|sprachbox|voicemail)  # 6: Anrufbeantworter
  4253.     |(weck(?:er|ruf)|alarms?))($)/ix');             # 7: Weckruf
  4254.     $do = getArg('cmd','/^(?:(an|ein|on)|(aus|off)|(test))($)/i');  // Befehl
  4255.     $id = getArg('id','/^(([a-z]+_?)?\d+|(guest_)?wlan(_wps)?)$/0');    // ID des Ger�tes
  4256.     $fw = $cfg['fiwa'] < 720;                       // Versionsweiche
  4257.     dbug(array('func' => $func, 'do' => $do, 'id' => $id),9);
  4258.     if($fw and ($func or $id and $do) or !$fw and $func) {      // Parameter-Check
  4259.      if($sid = (ifset($cfg['bsid'])) ? $cfg['bsid'] : login()) {    // Login durchf�hren
  4260.       if($cfg['bsid'] or isset($cfg['auth']['BoxAdmin'])) {
  4261.        $page = $fw ? '/myfritz/areas/comfort.lua' : '/myfritz/api/data.lua';
  4262.        $cmd = $fw ? "ajax_id=".rand(1000,9999)."&sid=$sid&cmd=" : "sid=$sid&c=comfort&a=";
  4263.        $names = $fw
  4264.     ? array('wlan' => 'WLAN', 'tam' => 'Anrufbeantworter', 'rule' => 'Rufumleitung', 'alarm' => 'Weckruf')
  4265.     : array('wifi' => 'WLAN', 'wifiGuest' => 'Gast-WLAN', 'rules' => 'Rufumleitungen', 'answeringMachines' => 'Anrufbeantworter', 'alarms' => 'Weckrufe');
  4266.        $out = array();
  4267.        if($func and $func[1]) {                                                 // Liste anfordern
  4268.         if($fw and $data = request('POST',$page,$cmd."getData") and ifset($data,'/^\{.*\}$/') and $json = json2array($data)) {  // 6.80
  4269.          if(ifset($json['wlan']))
  4270.           foreach($json['wlan'] as $key => $var)
  4271.            $out['wlan'] = (isset($out['wlan']) ? $out['wlan'] : "ID |Name |Status\n")."$var[itemId] |$var[text] |"
  4272.         .(($var['state'] == 'on') ? " an" : "aus ")."\n";
  4273.          if(ifset($json['fon']))
  4274.           foreach($json['fon'] as $key => $var)
  4275.            if($var['type'] == 'tam')
  4276.             $out['tam'] = (isset($out['tam']) ? $out['tam'] : "ID |Name |Annahme |Status\n")
  4277.         ."$var[itemId] |$var[text] |$var[details] |".(($var['state'] == 'on') ? " an" : "aus ")."\n";
  4278.            elseif($var['type'] == 'rule')
  4279.             $out['rule'] = (isset($out['rule']) ? $out['rule'] : "ID |Name |Umleiten |Ziel |Modus |Status\n")
  4280.         ."$var[itemId] |$var[text] |".implode(" |",preg_replace('/^.*?: /u','',$var['details']))." |"
  4281.         .(($var['state'] == 'on') ? " an" : "aus ")."\n";
  4282.            elseif($var['type'] == 'alarm')
  4283.             $out['alarm'] = (isset($out['alarm']) ? $out['alarm'] : "ID |Name |Wiederholung |Weckzeit |Status\n")."$var[itemId] |$var[text] |$var[details] |"
  4284.         .preg_replace('/(\d\d)(\d\d)/','$1:$2',$var['time'])." |".(($var['state'] == 'on') ? " an" : "aus ")."\n";
  4285.          foreach($out as $key => $var)
  4286.           $out[$key] = $names[$key].":\n".textTable(out($var,1),0,"|","\n","|"," ");
  4287.         }
  4288.         elseif(!$fw and $data = request('GET',$page,$cmd."getData") and ifset($data,'/^\{.*\}$/') and $json = json2array($data)) { // 7.20
  4289.          ksort($json);
  4290.           $head = array('wifi' => 'Art |Status |Info', 'rules' => 'ID |Name |Umleiten |Ziel |Modus |Status', 'answeringMachines' => 'ID |Name |Annahme |Status', 'alarms' => 'ID |Name |Wiederholung |Weckzeit |Status');
  4291.          $out = array();
  4292.          foreach($json as $grp => $lst)
  4293.           if($lst)
  4294.            if($grp == 'wifi')
  4295.             $out[$grp] = "WLAN |".($lst['isEnabled'] ? " an" : "aus ")."|".(isset($lst['wps']) ? "WPS ist ".(ifset($lst['wps']['isDisabled']) ? "aus" : (ifset($lst['wps']['isActive']) ? "aktiv" : "verf�gbar")) : "" );
  4296.            elseif($grp == 'wifiGuest')
  4297.             $out['wifi'] .= "\nGast-WLAN |".($lst['isEnabled'] ? " an" : ($lst['isDisabled'] ? "deaktiviert" : "aus "))."|"
  4298.         .($lst['remainingTime'] ? "bleibt noch $lst[remainingTime] Minuten an": "dauerhaft an");
  4299.            elseif($grp == 'rules') {
  4300.             $list = "";
  4301.             foreach($lst as $key => $var)
  4302.              if(isset($var['displayDescription']))
  4303.               $list .= "$var[id] |$var[displayDescription] |$var[divertionVia] |$var[destination] |$var[divertionInfo] |".($var['isEnabled'] ? " an" : "aus ")."\n";
  4304.             if($list)
  4305.              $out[$grp] = $list;
  4306.            }
  4307.            elseif($grp == 'answeringMachines') {
  4308.             $list = "";
  4309.             foreach($lst as $key => $var)
  4310.              $list .= " $var[id]|$var[name] |".($var['fetchCallTimeInSeconds'] ? "$var[fetchCallTimeInSeconds] Sek" : "Sofort")." |".($var['isEnabled'] ? " an" : "aus ")."\n";
  4311.             if($list)
  4312.              $out[$grp] = $list;
  4313.            }
  4314.            elseif($grp == 'alarms') {
  4315.             $list = "";
  4316.             foreach($lst as $key => $var)
  4317.              $list .= " $var[id]|$var[displayName] |".(($var['repetition'] == 'NONE') ? "Einmalig"
  4318.         : (($var['repetition'] == 'DAILY') ? "T�glich" : implode(', ',preg_array('/'.implode('|',array_keys(preg_array('/1/',$var['alarmDays'],2)))
  4319.         .'/',array('mon' => 'Mo', 'tue' => 'Di', 'wed' => 'Mi', 'thu' => 'Do', 'fri' => 'Fr', 'sat' => 'Sa', 'sun' => 'So'),3))))." |"
  4320.         .preg_replace('/\b\d\b/','0$0',$var['alarmTime']['hour'].":".$var['alarmTime']['minute'])." |".($var['isEnabled'] ? " an" : "aus ")."\n";
  4321.              if($list)
  4322.               $out[$grp] = $list;
  4323.            }
  4324.            else
  4325.             dbug(array($grp => $lst));
  4326.          foreach($out as $key => $var)
  4327.           $out[$key] = $names[$key].":\n".texttable(out($head[$key]."\n$var",1),0,"|","\n","|"," ");
  4328.         }
  4329.         else
  4330.          out(errmsg("16:Unbekannte Daten erhalten oder Komfort-Funktionen werden nicht unterst�tzt"));
  4331.         dbug($json,9);
  4332.         if($out)
  4333.          print implode("\n\n",$out);
  4334.        }
  4335.        elseif($do[3])                           // Test
  4336.         if($data = request('POST',$page,$cmd."getData") and ifset($data,'/^\{.*\}$/') and $json = json2array($data)) {
  4337.          dbug($json,9);
  4338.          if($fw) {
  4339.           if(!$id and ($func[1] or $func[2] or $func[3]))
  4340.            $id = $func[0];
  4341.           if($id)
  4342.            foreach($json as $grp => $itms) {
  4343.             if(is_array($itms))
  4344.              foreach($itms as $key => $var)
  4345.               if(is_array($var) and $var['itemId'] == $id) {
  4346.                $id = true;
  4347.                out(($var['state'] == "on") ? errmsg("1:'$var[text]' ist an bzw. aktiv") : "'$var[text]' ist aus");
  4348.                break 2;
  4349.               }
  4350.            }
  4351.          }
  4352.          elseif($list = ifset($json[$name = ($func[2] or $func[3] or $func[4]) ? "wifi".($func[3] ? "Guest" : "") : ($func[5] ? 'rules' : ($func[6] ? "answeringMachines" : ($func[7] ? "alarms" : false)))],true)) {
  4353.           if(substr($name,0,4) == 'wifi') {
  4354.            $list = array($list + array('id' => $func[0], 'name' => $name));
  4355.            $id = $func[0];
  4356.           }
  4357.           foreach($list as $key => $var)
  4358.            if($var['id'] == $id) {
  4359.             $id = true;
  4360.             if($val = preg_array('/^(display(Description|Name)|name)$/',$var,1))
  4361.              $name = $val;
  4362.             if(isset($names[$name]))
  4363.              $name = $names[$name];
  4364.             out($var['isEnabled'] ? errmsg("1:'$name' ist an bzw. aktiv") : "'$name' ist aus");
  4365.             break;
  4366.            }
  4367.          }
  4368.          if($id !== true)
  4369.           out(errmsg("8:".($id ? $id : (isset($names[$name]) ? $names[$name] : $name))." nicht gefunden"));
  4370.         }
  4371.         else
  4372.          out(errmsg("16:Unbekannte Daten erhalten oder Komfort-Funktionen werden nicht unterst�tzt"));
  4373.        elseif($do or $func[4]) {                    // Schalten
  4374.         $cmd .= $fw ? "switchChange&itemId=" : "";
  4375.         if($func[2] or $func[3]) {                  // WLAN
  4376.          $cmd .= $fw ? ($func[3] ? "guest_" : "")."wlan".($func[4] ? "_wps" : "") : ($func[4] ? "startWps" : "switchWifi")."&iface=".($func[2] ? "wifi" : "guest");
  4377.          if($fw and $func[4] and !$do)
  4378.           $do = array(1,1);
  4379.         }
  4380.         elseif(($fw or $do) and $id !== false) {            // ID
  4381.          $cmd .= $fw ? $id : "switch";
  4382.          if(!$fw)
  4383.           if($func[5])                          // Rufumleitungen
  4384.            $cmd .= "Rule&rule=$id";
  4385.           elseif($func[6])                      // Anrufbeantworter
  4386.            $cmd .= "AnsweringMachine&answeringMachine=$id";
  4387.           elseif($func[7])                      // Wecker
  4388.            $cmd .= "Alarm&alarm=$id";
  4389.         }
  4390.         else {
  4391.          $cmd = false;
  4392.          out(errmsg("2:Keine ID angegeben"));
  4393.         }
  4394.         if($cmd) {
  4395.          dbug(array('cmd' => $cmd, 'do' => $do),9);
  4396.          $var = " nicht";
  4397.          if($fw) {
  4398.           if($data = request('POST',$page,$cmd."&cmdValue=".($do[1] ? 1 : 0)) and preg_match('/"status":"switchStateChangedSend"/',$data))
  4399.            $var = "";
  4400.          }
  4401.          elseif($data = request('GET',$page,$cmd.($do ? "&value=".($do[1] ? "true" : "false") : "")) and preg_match('/"successful":\b(true|1)\b/',$data))
  4402.           $var = "";
  4403.          out("Schaltvorgang wurde$var erfolgreich gesendet");
  4404.          dbug($data,9);
  4405.         }
  4406.        }
  4407.        else
  4408.         out(errmsg("2:Keinen Befehl zur Funktion angegeben"));
  4409.       }
  4410.       else
  4411.        out(errmsg("8:Benutzer hat nicht das Recht f�r die Administration"));
  4412.       if(!ifset($cfg['bsid']))                      // Abmelden
  4413.        logout($sid);
  4414.      }
  4415.      else
  4416.       out(errmsg(0,'login'));                       // Login fehlgeschlagen
  4417.     }
  4418.     else                                // Parameter fehlen
  4419.      out(errmsg("2:Fehler: Parameter nicht korrekt �bergeben!")); // Fehlermeldung
  4420.    }
  4421.    else
  4422.     out(errmsg("64:Die Komfort-Funktionen ben�tigen mindestens Fritz!OS 6.80"));
  4423.   }
  4424.   elseif($val['led']) {                 // LED
  4425.    if(!login(false,555))
  4426.     out(errmsg("64:Diese Funktion wird nicht von der Fritz!OS Firmware unterst�tzt!"));
  4427.    elseif(ifset($cfg['help']) or !$var = getArg('func','/(test)|(auto-?)?((off|aus)|(low|dunkel)|([oa]n|normal)|(high|hell)|(?<=auto))/i')) // Hilfe Ausgeben
  4428.     out("$self <fritz.box> [mode:LED] [func:auto|off|low|on|high|aus|dunkel|an|hell|test]".((ifset($cfg['help'],'/[ab]/i')) ? "\n
  4429. Beispiele:
  4430. $self fritz.box mode:led func:off
  4431. $self fritz.box led test
  4432. $self fritz.box led auto-low
  4433. $self fritz.box led hell
  4434. $self fritz.box led auto-an" : "")."\n");
  4435.    elseif($sid = (ifset($cfg['bsid'])) ? $cfg['bsid'] : login()) {          // Login durchf�hren
  4436.     if($cfg['bsid'] or $cfg['fiwa'] < 530 or isset($cfg['auth']['BoxAdmin'])) {
  4437.      if($var[1]) {                                  // LED Status Abfragen
  4438.       dbug("Ermittle LED-Status");
  4439.       if($val = request('GET','/query.lua',"sid=$sid&led=box:settings/led_display") and $var = ifset($val,'/"led":\s*"(\d+)"/'))
  4440.        out($var[1] ? errmsg("1:LED ist aus") : "LED ist an");               // LED Status ausgeben
  4441.       else
  4442.        out(errmsg("64:LED-Status nicht ermittelbar!"));
  4443.      }
  4444.      elseif($var[2] or $var[3]) {
  4445.       dbug("Schalte LED a".(($var[1]) ? "n" : "us"));
  4446.       $led = array((ifset($var[4])) ? 2 : 0, (ifset($var[2])) ? 1 : 0, (ifset($var[5])) ? 1 : ((ifset($var[7])) ? 3 : 2));
  4447.       if($cfg['fiwa'] > 715)
  4448.        request('POST','/data.lua',"sid=$sid&apply=&page=led&ledDisplay=$led[0]&envLight=$led[1]&dimValue=$led[2]"); // LED schalten: auto,off,low,on,high
  4449.       else
  4450.        request('POST','/system/led_display.lua',"sid=$sid&apply=&led_display=$led[0]"); // LED schalten: an / aus
  4451.      }
  4452.     }
  4453.     else
  4454.      out(errmsg("8:Benutzer hat nicht das Recht f�r die Administration"));
  4455.     if(!ifset($cfg['bsid']))                                // Abmelden
  4456.      logout($sid);
  4457.    }
  4458.    else
  4459.     out(errmsg(0,'login'));                             // Login fehlgeschlagen
  4460.   }
  4461.   elseif($val['lio']) {                 // Manuelles Login / Logout
  4462.    if(ifset($cfg['help'])) {
  4463.     out("$self <http://user:[email protected]:port#passui> [mode:LogIn|LogOut|LogInTest|li|lo|lit] <file:SID> <-s:sid|file>".((ifset($cfg['help'],'/[ab]/i')) ? "\n
  4464. Beispiele:
  4465. $self https://user:[email protected]:12345#password mode:login -o:sid
  4466. $self [email protected] login sid
  4467. $self login -o:sid -p:https -fb:example.org -pt:12345 -un:user -pw:pass -ui:password
  4468. $self fritz.box login -pw:password -o:sid
  4469. $self fritz.box logout -s:sid
  4470. $self fritz.box logout -s:0123456789abcdef
  4471. $self logintest -cc:/media/veracrypt1/Fritz!Box/fb_config.php -ps:meinebox
  4472. $self meinebox::'/media/veracrypt1/Fritz!Box/fb_config.php' logintest
  4473. $self https://max:[email protected]:12345#ABCDEFGHIJKLMNOPQRSTUVWXYZ234567 logintest -tf -d" : ""));
  4474.     if(!$cfg['help'] or $cfg['help'] === true)
  4475.      $cfg['help'] = -1;
  4476.    }
  4477.    elseif(preg_match('/^l(?:og)?(?:(in?)(-?t(?:est)?)?|(o(?:ut)?))($)/i',$val['lio'],$var)) {
  4478.     if($var[1] and !ifset($cfg['sid'])) {           // Login (User/Pass)
  4479.      if($cfg['dbug'] === true)
  4480.       $cfg['dbug'] = 513;
  4481.      $sid = login();
  4482.      if($var[2])                        // Test
  4483.       if($sid) {
  4484.        logout($cfg['sid']);
  4485.        out(errmsg("1:Login war erfolgreich"));
  4486.       }
  4487.       else
  4488.        out(errmsg(0,"login"));
  4489.      else {                         // SID-Modus
  4490.       if($file = getArg('file'))
  4491.        file_contents($file,call_user_func(function_exists("json_encode") ? "json_encode" : "serialize",preg_array('/^(host|port|sock|fiwa|sid)$/',$cfg,3)));
  4492.       out($sid);
  4493.      }
  4494.     }
  4495.     elseif(ifset($cfg['sid'])) {                // SID-Modus
  4496.      if($var[2])                        // Test
  4497.       out(errmsg("1:Die SID ist g�ltig"));
  4498.      elseif($var[3]) {                      // Logout
  4499.       logout($cfg['sid']);
  4500.       if($var = ifset($cfg['opts']['s'],"") and file_exists($var))// SID-Datei l�schen
  4501.        unlink($var);
  4502.      }
  4503.      else                           // SID ausgeben
  4504.       out(login(0,0,0,$cfg['sid']));
  4505.     }
  4506.    }
  4507.   }
  4508.   elseif($val['rc']) {                  // ReConnect
  4509.    if(ifset($cfg['help']))
  4510.     out("$self <fritz.box> [mode:ReConnect|rc]".((ifset($cfg['help'],'/[ab]/i')) ? "\n
  4511. Beispiele:
  4512. $self mode:reconnect
  4513. $self fritz.box rc" : ""));
  4514.    else
  4515.     out(($var = forcetermination()) ? "Reconnect ausgef�hrt" : errmsg(0,'getexternalip'));
  4516.   }
  4517.   elseif($val['sh']) {                  // SmartHome
  4518.    $var = getArg('func','/(?:([ao]n)|(off|aus)|(switch|schalt)|(info|set|test)|(list|csv|json|xml)|(close|down|runter)|(open|up|rauf)|(stop|halt)|(array))($)/i');
  4519.    $ain = getArg('ain');#    1       2         3           4           5           6               7          8       9
  4520.    $set = array();
  4521.    $set['hkr'] = getArg('hkr','/^((([8-9]|1\d|2[0-8])(\.[50])?)�?C?|spar|komfort|[ao]n|aus|off)$/i0');    // Temperatur f�r Heizk�rperregler
  4522.    $set['kelvin'] = getArg('kelvin','/^((2[789]|[345]\d|6[0-4])\d\d|6500)$/0'); // Farbtemperatur (2700-6500) f�r Lampe
  4523.    $set['dimm'] = getArg('dimm','/^1?\d?\d$/0');                // Helligkeit (0-100) f�r lampe
  4524.    $set['delay'] = getArg('delay','/^\d{1,8}$/0');              // Geschwindigkeit (?) der �nderung
  4525.    $set['hsv'] = getArg('hsv','/^([12]?\d?\d|3[0-5]\d)(\D1?\d?\d){0,2}$/0');    // Farbwinkel (0-359), Farbs�ttigung (0-100), Helligkeit (0-100) f�r Lampe
  4526.    if($val = getArg('color','/^[\w\s]+$/u0') or $val = getArg('color','/^[\w\s�������]+$/0')) // Farbname f�r Lampe
  4527.     $set['color'] = preg_replace('/\s+/','',$val);
  4528.    $file = getArg('file');
  4529.    if(!login(false,669) and !getArg('-f'))
  4530.     out(errmsg("64:Diese Funktion wird nicht von der Fritz!OS Firmware unterst�tzt!"));
  4531.    elseif(ifset($cfg['help']) or !$var) {               // Hilfe Ausgeben
  4532.     out("$self <fritz.box> [mode:SmartHome|sh] [func] <ain> <hkr|kelvin|dimm|hsv|color|file>\n
  4533. Funktionen (func):\n{{{tt}
  4534. list||-|�bersicht aller Aktoren ausgeben
  4535. close/down/runter|[ain:Aktor]|-|Rolll�den schlie�en
  4536. csv|<file:Datei>|-|�bersicht aller Aktoren als CSV-Datei speichern
  4537. json|<file:Datei>|-|Vollst�ndige Aktorenliste als JSON-Datei speichern
  4538. info|[ain:Aktor]|-|Informationen �ber Aktor ausgeben
  4539. on/an|[ain:Aktor]|-|Aktor einschalten
  4540. off/aus|[ain:Aktor]|-|Aktor ausschalten
  4541. open/up/rauf|[ain:Aktor]|-|Rolll�den �ffnen
  4542. stop/halt|[ain:Aktor]|-|Rolll�den anhalten
  4543. switch/schalt|[ain:Aktor]|-|Aktor umschalten
  4544. test|[ain:Aktor]|-|Schaltzustand des Aktors abfragen
  4545. xml|<file:Datei>|-|Rohdaten als XML-Datei speichern
  4546. set|[ain:Aktor]||<ain\|color\|dimm\|hkr\|hsv\|kelvin>}}\n
  4547. �bergabe-Parameter f�r die SET Funktion:\n{{{tt}
  4548. Farblampe:|[color:|Farbname 1-3]|Farbangabe mit S�ttigungsnummber|(3)
  4549. |[dimm:|0-100]|Helligkeit setzen|
  4550. |[hsv:|0-359,0-100,0-100]|Farbwinkel, Farbs�ttigung, Helligkeit|(2)
  4551. |[kelvin:|2700-6500]|Farbtemperatur in Kelvin|(2)
  4552. Heizregler:|[hkr:|8.0-28.0\|an\|aus\|komfort\|spar]|Temperatur setzen|(1)
  4553. Template:|[ain:|Template]|Aktor nach Vorgaben setzen}}
  4554. \n{{{tt}
  4555. (1) Temperatur auf 0.5� genau und �nderungen dauern bis zu 15 Minuten
  4556. (2) Akzeptiert z.Z. nur Vorgabewerte - Alternativ [color] nutzen
  4557. (3) Verf�gbare Farbwerte mit [func:info] abfragen}}".((ifset($cfg['help'],'/[ab]/i')) ? "\n
  4558. Beispiele:
  4559. $self fritz.box mode:smarthome func:test ain:11:23:58:13:21:34
  4560. $self fritz.box smarthome an Lampe
  4561. $self fritz.box sh set 01234-0001234 23
  4562. $self fritz.box sh json file.json" : "")."\n");
  4563.     if(!$cfg['help'] or $cfg['help'] === true)
  4564.      $cfg['help'] = -1;
  4565.     $opts .= "SmartHome:|-cs:|<Char>|CSV-Separator festlegen (;)
  4566. |-f||Aktor direkt per AIN Schalten (Fehler Ignorieren)";
  4567.    }
  4568.    elseif($sid = (ifset($cfg['bsid'])) ? $cfg['bsid'] : login()) {  // Login durchf�hren
  4569.     if($cfg['bsid'] or isset($cfg['auth']['HomeAuto'])) {
  4570.      $val = strtolower($var[0]);
  4571.      if(ifset($var[5])) {                       // list / csv / json / xml
  4572.       $set = array();
  4573.       if(ifset($val,'/csv|json|xml/')) {                // Dateiname f�r csv/json ermitteln
  4574.        if(!$file and $ain) {
  4575.         $file = $ain;
  4576.         $ain = false;
  4577.        }
  4578.        if($cs = getArg('-cs'))                      // CSV-Separator festlegen
  4579.         $set['csv'] = strtr($cs,array('\t' => "\t"));
  4580.        if($data = smarthome($val,0,$set))
  4581.         if($file)
  4582.          out((file_contents($file,$data)) ? "$file wurde erfolgreich gespeichert!" : errmsg("32:$file konnte nicht geschrieben werden!"));
  4583.         else
  4584.          echo utf8($data,1);
  4585.       }
  4586.       else
  4587.        if($data = smarthome($val,0,$set))
  4588.         print texttable(out(preg_replace('/\b((?<=aus|offline$)|(?=an|online$))/m',' ',$data),1))."\n";
  4589.        else
  4590.         out(errmsg(0,'smarthome'));
  4591.      }
  4592.      elseif(($var[1] or $var[2] or $var[3]) and $ain)           // on / off / switch
  4593.       out(($data = smarthome(($var[1]) ? 'on' : (($var[2]) ? "off" : "trip"),$ain,getArg('-f'))) ? $data : errmsg(0,'smarthome'));
  4594.      elseif($var[4] and $ain)                       // info / set / test
  4595.       out(($data = smarthome($val,$ain,$set)) ? "{{{tt}$data}}" : errmsg(0,'smarthome'));
  4596.      elseif(($var[6] or $var[7] or $var[8]) and $ain)           // Rolll�den
  4597.       out($data = smarthome(($var[6]) ? 'close' : (($var[7]) ? "open" : "stop"),$ain) ? $data : errmsg(0,'smarthome'));
  4598.      elseif($var[9])
  4599.       out(smarthome('array',$ain));
  4600.      else
  4601.       out(errmsg("2:Unbekannte Argumente angegeben!"));
  4602.     }
  4603.     else
  4604.      out(errmsg("8:Benutzer hat nicht das Recht f�r SmartHome-Steuerung"));
  4605.     if(!ifset($cfg['bsid']))                        // Abmelden
  4606.      logout($sid);
  4607.    }
  4608.    else
  4609.     out(errmsg(0,'login'));                     // Login fehlgeschlagen
  4610.   }
  4611.   elseif($val['sd']) {                  // Supportdaten
  4612.    if(ifset($cfg['help'])) {
  4613.     out("$self <fritz.box> [mode:SupportDaten|sd] <file:Datei|Ordner|.> <func:ExTrakt|Datei>".((ifset($cfg['help'],'/[ab]/i')) ? "\n
  4614. Beispiele:
  4615. $self fritz.box mode:supportdaten file:support.txt func:extrakt
  4616. $self fritz.box supportdaten . -tm
  4617. $self fritz.box supportdaten sd-ordner extrakt -d
  4618. $self fritz.box sd -pw:geheim
  4619. $self sd file:support.txt func:support.tar" : ""));
  4620.     if(!$cfg['help'] or $cfg['help'] === true)
  4621.      $cfg['help'] = -1;
  4622.     $opts .= "SupportDaten:|-tm:|<on/off>|Schaltet Telemetriedaten an/aus";
  4623.    }
  4624.    else {
  4625.     $file = getArg('file');
  4626.     $et = getArg('func');
  4627.     $mode = ($file and preg_match($cfg['ptar'],$file,$var)) ? (($cfg['bzip'] and ifset($var[3])) ? 3 : ((ifset($var[2])) ? 2 : 1)) : 0;
  4628.     if(!$mode and $et and $file and makedir($file))         // Neues Verzeichniss erstellen
  4629.      $file = './';
  4630.     if(file_exists($et) and is_file($et) and $data = file_contents($et) and $text = supportdataextrakt($data,$mode,$file))
  4631.      out("\n$text\n");
  4632.     elseif($sid = (ifset($cfg['bsid'])) ? $cfg['bsid'] : login()) {
  4633.      if($cfg['bsid'] or $cfg['fiwa'] < 530 or isset($cfg['auth']['BoxAdmin'])) {
  4634.       $tm = ($var = getArg('-tm','/^(?:[ao](?:(n)|(us|ff)))?$/i') and (ifset($var[1]) or !ifset($var[2])));
  4635.       if(ifset($et,'/^(extra[ck]t|et)$/i') and $cfg['fiwa'] >= 630) {   // Extrakt
  4636.        dbug("Hole Support-Daten zum extrahieren");
  4637.        if($data = supportdata(0,$tm) and $text = supportdataextrakt($data[1],$mode,$file))
  4638.         out("\n$text\n");
  4639.        elseif($data[1])
  4640.         file_contents((!preg_match($cfg['ptar'],$file) and substr($file,-1) != '/') ? $file : ((preg_match('/filename=(["\']?)(.*?)\1/i',$data['Content-Disposition'],$var))
  4641.          ? preg_replace('/[?\\\\\/<*>:"]+/','_',$var[2]) : "Supportdaten.txt"),$data[1]);
  4642.       }
  4643.       elseif(supportdata($file ? $file : './',$tm))
  4644.        out("Supportdaten wurden erfolgreich gespeichert");
  4645.       else
  4646.        out(errmsg(0,'supportdata'));
  4647.      }
  4648.      else
  4649.       out(errmsg("8:Benutzer hat nicht das Recht f�r die Administration"));
  4650.      if(!ifset($cfg['bsid']))
  4651.       logout($sid);
  4652.     }
  4653.     else
  4654.      out(errmsg(0,'login'));
  4655.    }
  4656.   }
  4657.   elseif($val['ss']) {                  // SystemStatus
  4658.    if(ifset($cfg['help'])) {
  4659.     out("$self <fritz.box> [mode:SystemStatus|Status|ss] <file|code>".((ifset($cfg['help'],'/[ab]/i')) ? "\n
  4660. Beispiele:
  4661. $self fritz.box mode:systemstatus
  4662. $self fritz.box status
  4663. $self fritz.box mode:status file:'./system_status.html'
  4664. $self ss code:\"FRITZ!Box Fon WLAN 7390-B-010203-040506-733454-124607-147902-840522-22574-avm-de\"" : ""));
  4665.     if(!$cfg['help'] or $cfg['help'] === true)
  4666.      $cfg['help'] = -1;
  4667.     $opts .= "System-Status:|-rd:|<path>|Schreibt die RAW-Daten";
  4668.    }
  4669.    elseif($data = supportcode(($file = getArg('file','file_exists')) ? file_contents($file) : getArg('code'))) {
  4670.     out($data);
  4671.     if($path = getArg('-rd')) {             // RAW-Daten Speichern
  4672.      if(!is_bool($path))
  4673.       if(!file_exists($path))
  4674.        makedir($path);
  4675.       elseif(is_dir($path))
  4676.        chdir($path);
  4677.      file_contents("system_status.html",$cfg['body']);
  4678.     }
  4679.    }
  4680.    else
  4681.     out(errmsg(0,'supportcode'));
  4682.   }
  4683.   elseif($val['t']) {                   // Traffic
  4684.    if(ifset($cfg['help']) /* or !getArg(true) */ )
  4685.     out("$self <fritz.box> [mode:Traffic|t]".((ifset($cfg['help'],'/[ab]/i')) ? "\n
  4686. Beispiel:
  4687. $self fritz.box mode:traffic" : ""));
  4688.    elseif($sid = (ifset($cfg['bsid'])) ? $cfg['bsid'] : login()) {
  4689.     if($cfg['bsid'] or $cfg['fiwa'] < 530 or isset($cfg['auth']['BoxAdmin'])) {
  4690.      if($traffic = gettraffic()) {
  4691.       $out = "| Verbindungen| Online| Ausgehend| Eingehend| Gesamt\n";
  4692.       foreach(array(
  4693.     'Today' => 'Heute',
  4694.     'Yesterday' => 'Gestern',
  4695.     'ThisWeek' => 'Diese Woche',
  4696.     'ThisMonth' => 'Dieser Monat',
  4697.     'LastMonth' => 'Letzter Monat') as $key => $var) {
  4698.        $val = $traffic[$key];
  4699.        $out .= "$var| ".number_format($val['connect'],0,',','.')
  4700.     ."| ".number_format(intval($val['time'] / 60),0,',','.').":".str_pad($val['time'] % 60,2,0,STR_PAD_LEFT)
  4701.     ."| ".number_format($val['out'],0,',','.')
  4702.     ."| ".number_format($val['in'],0,',','.')
  4703.     ."| ".number_format($val['sum'],0,',','.')
  4704.     ."\n";
  4705.       }
  4706.       if($out)
  4707.        out(textTable($out));
  4708.       if(isset($traffic['Counter'])) {
  4709.        $out = "";
  4710.        $val = $traffic['Counter'];
  4711.        if(ifset($val['sum']) and ifset($val['max']))
  4712.         $out .= "Daten-Budget| ".number_format($val['sum'],0,',','.')." bytes von ".number_format($val['max'],0,',','.')." bytes\n";
  4713.        if(ifset($val['time']) and ifset($val['maxtime']))
  4714.         $out .= "Zeit-Budget| ".intval(number_format($val['time'] / 60),0,',','.').":".str_pad($val['time'] % 60,2,0,STR_PAD_LEFT)
  4715.     ." von ".number_format(intval($val['maxtime'] / 60),0,',','.').":".str_pad($val['maxtime'] % 60,2,0,STR_PAD_LEFT)."\n";
  4716.        if($out)
  4717.         out("\n".textTable($out));
  4718.       }
  4719.      }
  4720.      else
  4721.       out(errmsg(0,'gettraffic'));
  4722.     }
  4723.     else
  4724.      out(errmsg("8:Benutzer hat nicht das Recht f�r die Administration"));
  4725.     if(!ifset($cfg['bsid']))
  4726.      logout($sid);
  4727.    }
  4728.    else
  4729.     out(errmsg(0,'login'));
  4730.   }
  4731.   elseif($val['wh']) {                  // Wahlhilfe
  4732.    if(ifset($cfg['help']) or !getArg(true))
  4733.     out("$self <fritz.box> [mode:WahlHilfe|wh|Dial|d] [tel:Rufnummer] <fon:Telefon>\n
  4734. Telefon:
  4735. FON1-4 | ISDN/DECT | ISDN1-8 | DECT1-6 | (Keine Unterst�tzung f�r IP-Telefone)
  4736. Ab OS 6.69 ist bei Telefon�nderung eine Zwei-Faktor-Authentisierung erforderlich, falls aktiviert".((ifset($cfg['help'],'/[ab]/i')) ? "\n
  4737. Beispiele:
  4738. $self fritz.box mode:wahlhilfe tel:0123456789 fon:isdn/dect
  4739. $self fritz.box dial \"#96*7*\"
  4740. $self fritz.box wh . -pw:geheim" : ""));
  4741.    elseif($tel = getArg('tel') and ($fon = getArg('fon') or 1))
  4742.     if($sid = (ifset($cfg['bsid'])) ? $cfg['bsid'] : login(0,0,(bool)$fon)) {
  4743.      out(($cfg['bsid'] or $cfg['fiwa'] < 530 or isset($cfg['auth']['Dial']))
  4744.     ? ((dial($tel,$fon)) ? "Rufnummer wurde gew�hlt" : errmsg(0,'dial'))
  4745.     : errmsg("8:Benutzer hat nicht das Recht f�r die Wahlhilfe"));
  4746.      if(!ifset($cfg['bsid']))
  4747.       logout($sid);
  4748.     }
  4749.     else
  4750.      out(errmsg(0,'login'));
  4751.    else
  4752.     out(errmsg("2:Keine Rufnummer �bergeben"));
  4753.   }
  4754.   elseif((ifset($val['rp']) or ifset($val['tg'])) and ifset($cfg['a1st'])) {    // Test-Funktion
  4755.    if($val['rp'])                   // Test RP
  4756.     out(($pass = getArg('pass','/^\w+$/0')) ? ($val = getupnppath('LANConfigSecurity')) ? (($val = upnprequest($val[1],$val[0],'ResetWebUi',$pass)) ? $val : errmsg("64:Fehlgeschlagen!"))
  4757.     : str_rot13($cfg['a1st'][4]) : "$self ".$cfg['a1st'][2].((ifset($cfg['help'],'/[ab]/i')) ? "\n\nBeispiele:\n$self fritz.box rp sonnig1337" : ""));
  4758.    elseif($val['tg'])                   // Test TG
  4759.     if((float)phpversion() >= 5.12) {
  4760.      if($mac = getArg('maca','/^[\da-f]{2}(?:[:-][\da-f]{2}){5}$/i0') and $a = ifset($cfg['a1st'][0],'/T\w+(?=\s)/')) {
  4761.       out($a[0],2);
  4762.       for($a=0, $b=2, $c=str_rot13('fyrrc'), $time = intval(time() / 30), $data = unbase(strtolower($mac),"0123456789abcdef"); $a < 10; $a++) {
  4763.        call_user_func($c,$a);
  4764.        $hash = hash_hmac('SHA1',str_pad(pack('N*',$time + $a),8,"\0",STR_PAD_LEFT),$data,true);
  4765.        $var = unpack('N',substr($hash,ord(substr($hash,-1)) & 15, 4));
  4766.        out(((($b = ($b + 13 < $cfg['wrap']) ? $b + 8 : 10) == 10) ? ($a ? str_pad("\n",$b," ") : ": ") : ", ")
  4767.     .str_pad(($var[1] & (1 << 31) - 1) % 1e6,6,0,STR_PAD_LEFT),2);
  4768.       }
  4769.       out("\n\n".str_rot13($cfg['a1st'][4]));
  4770.      }
  4771.      else
  4772.      out("$self ".$cfg['a1st'][3].((ifset($cfg['help'],'/[ab]/i')) ? "\n\nBeispiele:\n$self fritz.box tg 04:08:15:16:23:42" : ""));
  4773.     }
  4774.     else
  4775.      out(errmsg("64:Es wird mindestens PHP 5.1.2 ben�tigt"));
  4776.   }
  4777.   elseif($val['pi'] and !$cfg['help'] and ifset($cfg['uplink'],5) and isset($cfg['uplink']['host'])
  4778.     and $mode = getArg('func',$preg = '/^(?:(?P<c>check|c)|(?P<i>i(?:nstall)?)|(?P<l>liste?|l)|(?P<u>update|ud))$/i')) { // Plugin Update(1)
  4779.    if($cfg['sock'] == 'auto' and !$cfg['ssl'])          // SSL Laden
  4780.     $cfg['ssl'] = cfgdecrypt(0,'openssl');
  4781.    if($array = getArg('opt',$preg))             // Mode durch zweiten Parameter erweitern
  4782.     foreach($array as $key => $var)
  4783.      if($var and !ifset($mode[$key]))
  4784.       $mode[$key] = $var;
  4785.    $plug = ($var = getArg('plug',"/^($cfg[fbtm]|[\w-]+)$/0")) ? "/$var/i" : false;
  4786.    foreach($cfg['uplink']['port'] as $port)         // MD5-Liste f�r Plugins anfordern
  4787.     if($fbnet = request('GET-array',$cfg['uplink']['path'].$cfg['uplink']['fbtp'].".md5",0,0,$cfg['uplink']['host'],$port)) {
  4788.      if($var = ifset($fbnet['Location'],'/^(https?:)(\/\/.+)$/'))
  4789.       $fbnet = request("$var[1][array]$var[2]");
  4790.      break;
  4791.     }
  4792.    if($fbnet and ifset($fbnet['Content-MD5'],hash('md5',$fbnet[1])) and preg_match("/((\d\d)\.(\d\d)\.(\d{4}))\s([\d:]+)\s*\(([\w.-]+)\)/s",$fbnet[1],$up)  // Datum und Archivname
  4793.     and preg_match_all('/^(\w+)\s+([\d.]+)\s+\*([\w.-]+)\s*$/m',$fbnet[1],$list)) { // MD5, Version und Pluginname
  4794.     $usrid = (ifset($fbnet['X-Usrid'])) ? preg_replace('/^0+/','',bin2hex(base64_decode($fbnet['X-Usrid']))) : false;
  4795.     if(ifset($mode['l']))                   // Mode: List
  4796.      out($fbnet[1]);
  4797.     else {
  4798.      if((array)$pi = listDir($cfg['fbtg'],$cfg['fbta'],4))
  4799.       $pi = array_keys($pi);
  4800.      $out = $files = $install = $filter = $update = array();
  4801.      foreach($list[3] as $key => $val)              // Plugins-Liste mit Lokalen Verzeichnis abgleichen
  4802.       if($file = preg_array('/'.preg_quote($val,'/').'$/',$pi,2))
  4803.        $files = array_merge($files,$file);
  4804.       else
  4805.        $install[] = array('name' => $val, 'version' => $list[2][$key], 'hash' => $list[1][$key]);
  4806.      foreach($files as $key => $file)               // Von vorhandenen Plugins alle Daten zusammensuchen
  4807.       if($data = file_contents($file) and preg_match('/\$plugin\s*=\s*([\'"])(.*?)\1;[^$]*(?:\$info\s*=\s*([\'"])(.*?)\3;)?/',$data,$match)) {
  4808.        $name = preg_replace("/.*?$cfg[fbtm]$/",'$1',$file);
  4809.        $data = (preg_match('/^.*?('.preg_quote($name,'/').')\s([\d.]+)\s+(.*)$/i',$match[2],$var))
  4810.     ? array('name' => $var[1], 'version' => (float)$var[2], 'copyright' => $var[3]) : false;
  4811.        $update = (($var = preg_array('/'.preg_quote($name,'/').'/',$list[3],4)) !== false) ? array('version' => (float)$list[2][$var], 'hash' => $list[1][$var]) : false;
  4812.        $files[$key] = array('name' => $name, 'file' => basename($file), 'filename' => $file, 'plugin' => $match[2], 'info' => $match[4], 'data' => $data,
  4813.     'hash' => md5_file($file), 'update' => $update);
  4814.       }
  4815.      foreach($files as $key => $data) {             // Lokale Plugins mit Update-Liste vergleichen und Updates anzeigen
  4816.       if(ifset($data['data']['version']) and ifset($data['update']['version']) and $data['data']['version'] < $data['update']['version'])
  4817.        $update[$key] = 1;
  4818.       elseif(ifset($data['hash']) and ifset($data['update']['hash']) and $data['hash'] != $data['update']['hash'])
  4819.        $update[$key] = (getArg('-f')) ? 0 : 2;          // Mit -f die Warnung f�r ver�nderung ignorieren!
  4820.       if(ifset($update[$key])) {                // Ver�nderungen ausgeben
  4821.        if($update[$key])
  4822.         $filter[$key] = $data['file'];              // Preg-Filter mit dem Dateinamen
  4823.        $out[$data['name']] = ($update[$key] == 1)       // Update auflisten
  4824.     ? "Update: ".number_format($data['data']['version'],2)." -> ".number_format($data['update']['version'],2)   // Normale �nderung
  4825.     : "Plugin wurde ver�ndert";
  4826.       }
  4827.      }
  4828.      foreach($install as $file) {               // Neue (nicht installierte) Plugins anzeigen
  4829.       $out[preg_replace("/^$cfg[fbtm]$/",'$1',$file['name'])] = "NEU: ".number_format($file['version'],2);
  4830.       if(ifset($mode['i']))
  4831.        $filter[] = $file['name'];               // Preg-Filter mit dem Dateinamen
  4832.      }
  4833.      if($out) {                         // Updates ausgeben
  4834.       $max = max(array_map('strlen',array_keys($out))) + 1;
  4835.       out(errmsg("1:Es sind Updates/Plugins verf�gbar:"));
  4836.       foreach($out as $key => $var)
  4837.        out(str_pad($key,$max,' ').$var);
  4838.       if(!ifset($mode['c']) and $filter and (!$plug or preg_array($plug,$filter))) {    // Update/Install durchf�hren
  4839.        out("\nInstalliere/Aktualisiere Plugins...");
  4840.        foreach($cfg['uplink']['port'] as $port)
  4841.         if($tgz = request('GET-array',$cfg['uplink']['path']."$up[6]?$usrid",0,0,$cfg['uplink']['host'],$port)) // Tar-Archiv holen
  4842.          break;
  4843.        foreach($filter as $key => $var)
  4844.         $filter[$key] = preg_quote($var,'/');
  4845.        if($tgz and ifset($tgz['Content-MD5'],hash('md5',$tgz[1])) and $tgz = datatar2array($cfg['zlib']['decode']($tgz[1]),'/('.implode('|',$filter).')$/')) {  // Tar-Archiv in Array entpacken
  4846.         if(ifset($mode['u'])) {                 // Mode: Update
  4847.          foreach($update as $key => $file) {
  4848.           if($file and file_exists($files[$key]['filename']) and ifset($tgz[$files[$key]['file']]) and (!$plug or preg_match($plug,$file))) {
  4849.            if(hash('md5',$tgz[$files[$key]['file']]['data']) == $files[$key]['update']['hash'] or getArg('-f')) {
  4850.             if(!getArg('-ow')) {                // -ow f�r �berschreiben abfragen
  4851.              dbug("Sichere: ".$files[$key]['file']);
  4852.              if(file_exists($rename = preg_replace('/(\.\w+)$/','_'.number_format($files[$key]['data']['version'],2).'$1.bak',$files[$key]['filename'])))
  4853.               $rename = preg_replace('/(\.\w+)$/','_'.time().'$1',$rename);
  4854.              @rename($files[$key]['filename'],$rename);
  4855.             }
  4856.             else
  4857.              dbug("�berschreibe: ".$files[$key]['file']);
  4858.             out("Update: ".$files[$key]['file']." ... ",2);
  4859.             out((file_contents($files[$key]['filename'],$tgz[$files[$key]['file']]['data'])) ? "erfolgreich" : errmsg("32:fehlgeschlagen"));
  4860.            }
  4861.            else
  4862.             out(errmsg("16:Fehler: ".$files[$key]['file']." ist defekt oder ver�ndert worden!"));
  4863.           }
  4864.          }
  4865.         }
  4866.         if(ifset($mode['i']) and $install) {            // Neue Plugins installieren
  4867.          foreach(array_reverse($cfg['fbta']) as $var)       // Plugin-Ordner suchen
  4868.           if(file_exists($var) and is_dir($var)) {
  4869.            $path = $var;
  4870.            break;
  4871.           }
  4872.          dbug("Benutze Plugin-Ordner: $path");
  4873.          foreach($install as $file)             // Plugins aus Tar-Archiv installieren
  4874.           if(!$plug or preg_match($plug,$file['name']))
  4875.            if((hash('md5',$tgz[$file['name']]['data']) == $file['hash'] or getArg('-f'))) {
  4876.             out("Installiere: $file[name] ... ",2);
  4877.             out((file_contents("$path/$file[name]",$tgz[$file['name']]['data'])) ? "erfolgreich" : errmsg("32:fehlgeschlagen"));
  4878.            }
  4879.            else
  4880.             out(errmsg("16:Fehler: $file[name] ist defekt oder ver�ndert worden!"));
  4881.         }
  4882.        }
  4883.        else
  4884.         out(errmsg("16:Plugin-Archiv ist fehlerhaft!"));
  4885.       }
  4886.      }
  4887.      else
  4888.       out("Keine neuen Updates verf�gbar!");
  4889.     }
  4890.     if(ifset($fbnet['X-Cookie']))               // Coolen Spruch ausgeben
  4891.      out("\n".$fbnet['X-Cookie']);
  4892.    }
  4893.    else
  4894.     out(errmsg("64:Update-Server sagt NEIN!"));
  4895.   }
  4896.   elseif($file = (($val['pi'] and $file = getArg('plug')) ? $file : (($val['pit']) ? $val['pit'] : false)) and (file_exists($file) and is_file($file)
  4897.     or $file = preg_array('/'.preg_quote($file,'/').'/i',listDir("/$cfg[fbtm]\s*$/i",$cfg['fbta'],1)))) {   // Plugin Exec(2)
  4898.    $plug = preg_replace("!^.*?$cfg[fbtm]$!",'$1',$file);
  4899.    $array = array();
  4900.    $err = "";
  4901.    if($var = file_contents($file) and preg_match('/\$meta\s*=\s*\'(\{(?:[^"\n]+|(?<!\\\\)")+\})\';/',$var,$var)
  4902.     and $array = json2array($var[1])) { // JSON Plugininfo lesen
  4903.     if(ifset($array['php']) and (float)phpversion() < (float)$array['php'])
  4904.      $err = "ben�tigt mindestens PHP $array[php]!";
  4905.     elseif(ifset($array['fbt']) and $cfg['ver'][10] < (float)$array['fbt'])
  4906.      $err = "ben�tigt mindestens fb_Tools $array[fbt] oder neuer!";
  4907.     elseif(ifset($array['fos']) and (int)login(false) < ($var = (int)preg_replace('/^0*(\d+)\.?(\d\d)\d*$/','$1$2',"$array[fos]00")))
  4908.      $err = "16:ben�tigt mindestens Fritz!OS ".preg_replace('/(?=\d\d$)/','.',$var)." oder neuer!";
  4909.     elseif(ifset($array['ssl']) and (!cfgdecrypt(0,'openssl') or $cfg['osn'] < $array['ssl']))
  4910.      $err = "16:ben�tigt mindestens OpenSSL $array[ssl] oder neuer!";
  4911.    }
  4912.    if($err)
  4913.     out(errmsg("16:".ucfirst($plug)." $err"));
  4914.    else {
  4915.     if(isset($cfg['plugin'][$var = strtolower($plug)]) and is_array($cfg['plugin'][$var])) {    // Gibt es Voreinstellungen
  4916.      dbug("Lade Pluginvoreinstellungen");
  4917.      extract($cfg['plugin'][$var]);     // Konfiguration bereitstellen
  4918.     }
  4919.     unset($cfg['plugin']);          // Alle anderen Voreinstellungen l�schen!
  4920.     include_once $file;             // Plugin ausf�hren
  4921.    }
  4922.    if(ifset($cfg['error']) and !ifset($cfg['error']['main']))   // Nur fehler ausgeben, wenn es noch keine Fehlermeldung gab
  4923.     out(errmsg());
  4924.   }
  4925.   elseif($val['pi']) {                  // Plugin Liste(3)
  4926.    $var = (ifset($cfg['uplink'])) ? array("|opt:Check|Install|List|UpDate","
  4927. $self plugin update list
  4928. $self plugin update check
  4929. $self plugin update -ow
  4930. $self plugin install update
  4931. $self plugin install konfigdecrypt") : array(":list","");
  4932.    out("$self <fritz.box> <mode:PlugIn|pi> [plug:Plugin|Script-Datei] <...>
  4933. $self [mode:PlugIn|pi] [func$var[0]] <plug:Plugin>".((ifset($cfg['help'],'/[ab]/i')) ? "\n
  4934. Beispiele:
  4935. $self fritz.box plugin fbtp_led.php off
  4936. $self test \"Hello World\"
  4937. $self plugin$var[1]
  4938. $self plugin fbtp_test.php" : ""));
  4939.    if(!$cfg['help'] or $cfg['help'] === true) {
  4940.     $cfg['help'] = -1;
  4941.     $opts .= "PlugIn:|-em||Erweiterte Meta-Daten Auflisten
  4942. |-pp:|[Path]|Alternativen Plugin-Path setzen";
  4943.     if($array = listDir("/$cfg[fbtm]\s*$/i",array_merge($cfg['fbta'],array(str_replace('\\','/',(file_exists($file) and is_dir($file)) ? preg_replace('![\\\\/]+$!','',$file) : "."))),5)) {
  4944.      $plugins = "";
  4945.      if(ifset($cfg['os'],'/^(winnt|darwin)/i'))         // Gross/Kleinschreibung bei Windows ignorieren
  4946.       $array = array_unique($array);
  4947.      natcasesort($array);
  4948.      $em = getArg('-em');
  4949.      foreach($array as $file => $v)
  4950.       if($data = file_contents($file) and preg_match('/\$plugin\s*=\s*([\'"])(.*?(?:('.preg_quote((preg_match("/$cfg[fbtm]\s*$/i",$file,$var)) ? $var[1]
  4951.     : basename($file),'/').')\s+([\d.]+)\s+)?.*?)\1;[^$]*(?:\$info\s*=\s*([\'"])(.*?)\5;)?(?:\s*\$meta\s*=\s*\'(\{(?:[^"\n]+|(?<!\\\\)")+\})\';)?/i',$data,$var)
  4952.     and $data = preg_replace('/\|/','\|',$var)) {
  4953.        $data[7] = ifset($data[7]) ? json2array($data[7]) : array();
  4954.        $plugins .= "$data[3]|$data[4]".($em
  4955.     ?"|".(isset($data[7]['php']) ? number_format($data[7]['php'],1) : "-")
  4956.     ."|".(isset($data[7]['fbt']) ? number_format($data[7]['fbt'],2) : "-")
  4957.     ."|".(isset($data[7]['fos']) ? number_format($data[7]['fos'],2) : "-")
  4958.     ."|".(isset($data[7]['ssl']) ? number_format($data[7]['ssl'],1) : "-") : "")."|$data[6]\n";
  4959.       }
  4960.      out($plugins ? "\nVorhandene Plugins: (WARNUNG: Es gibt KEINE Pr�fung auf Malware!)\n\n{{{tt}Plugin|Version".($em ? "|PHP|fbT|F!OS|SSL" : "")."|Beschreibung\n$plugins}}\n" : errmsg("8:Keine g�ltigen Plugins gefunden!"),2);
  4961.     }
  4962.     else
  4963.      out(errmsg("8:Keine Plugins gefunden!"));
  4964.    }
  4965.    else {
  4966.     if(ifset($cfg['uplink']))
  4967.      $opts .= "Update:|-f||Force - Fehler Ignorieren\n|-ow||Dateien �berschreiben";
  4968.     if($cfg['help'] === true)
  4969.      $cfg['help'] = -1;
  4970.    }
  4971.   }
  4972.   else  # M�glichweise ist ein unbekannter und unerwarterer, sowie mysteri�ser Layer-8 Problem aufgetreten ;-)
  4973.    out(errmsg("10:Unbekannter Befehl oder Plugin nicht gefunden\nEine Hilfe erhalten Sie mit $self -h"));
  4974.  }
  4975.  elseif($cfg['dbug']%2)                 // DEBUG: $argv & $cfg ausgeben
  4976.   dbug(compact(explode(',','argv,pset,pmax,cfg')));
  4977.  else {                         // Hilfe ausgeben
  4978.   $_help = out("$self <http://user:[email protected]:port#otp> [mode] <Parameter> ... <Option>".((ifset($cfg['help'])) ? "\n
  4979. Modes (mode):\n{{{tt}
  4980. AnrufListe|-|Anrufliste abrufen/mit Datei Syncronisieren(2)
  4981. BoxInfo|-|Modell, Firmware-Version und MAC-Adresse ausgeben
  4982. Ereignisse|-|Systemmeldungen abrufen/mit Datei Syncronisieren(2)
  4983. GetIP|-|Aktuelle externe IPv4-Adresse ausgeben(1)
  4984. Info|-|FB-Tools/PHP Version, Checksum hasher, Update/Pr�fen(3)
  4985. KomFort|-|Verschiedene Komfortfunktionen f�r WLAN/Telefonie Schalten(2)
  4986. Konfig|-|Einstellungen Ex/Importieren, Daten entschl�sseln(2,3,4,5)
  4987. LED|-|LED an/ausschalten oder Status abfragen(2)
  4988. LogIn/LogOut|-|Manuelles Einloggen f�r Scriptdateien(2)
  4989. PlugIn|-|Weitere Funktion per Plugin-Script einbinden
  4990. ReConnect|-|Neueinwahl ins Internet(1)
  4991. SmartHome|-|Aktoren schalten und auslesen(2)
  4992. SupportDaten|-|AVM-Supportdaten Speichern(2)
  4993. SystemStatus|-|Modell, Version, Laufzeiten, Neustarts und Status ausgeben(3)
  4994. Traffic|-|Trafficz�hler ausgeben(2)
  4995. WahlHilfe/Dial|-|Rufnummer w�hlen(2,5)".(($cfg['a1st']) ? $cfg['a1st'][0] : "")."}}
  4996.  
  4997. {{{tt}(1)|Aktiviertes UPnP erforderlich (Nicht �ber https nutzbar)
  4998. (2)|Anmeldung mit Logindaten erforderlich
  4999. (3)|Teilweise ohne Fritz!Box nutzbar
  5000. (4)|OpenSSL, MCrypt oder Aes.php n�tig
  5001. (5)|Ab OS 6.69 ist beim Login eine Zwei-Faktor-Authentisierung erforderlich, falls aktiviert}}
  5002. [ ] Pflicht / < > Optional".((ifset($cfg['help'],'/[ab]/i')) ? "\n
  5003. Beispiele:
  5004. $self mode:getip filter:ipv4
  5005. $self [email protected] supportdaten
  5006. $self hans:[email protected] konfig export
  5007. $self http://[email protected] Ereignisse -w:80 -c:utf8 -o:file.txt
  5008. $self myfritz komfort AB an tam0
  5009. $self https://max:[email protected]:12345#ABCDEFGHIJKLMNOPQRSTUVWXYZ234567 konfig export-decrypt of:fb.export -d
  5010. $self myfritz AnrufListe /var/log/fb_call_%F.log -lf
  5011. $self wahlhilfe \"**51\" -fb:fritz.box -un:max -pw:geheim
  5012. $self fritz.box led off -pw:secret
  5013. $self -h:alles": "") : "\n\nWeitere Hilfe bekommen Sie mit der -h Option oder mehr Hilfe mit -h:all"));
  5014.  }
  5015.  if($cfg['help']) {                 // Weitere Hilfe ausgeben
  5016.   if((ifset($cfg['help'],'/k/i') or $cfg['help'] == -1) and ifset($opts))
  5017.    out("\nKontext-Optionen:\n{{{tt,0,|,\n, ;; ;, }$opts}}");
  5018.   elseif(ifset($cfg['help'],'/[ao]/i'))         // Optionen ausgeben
  5019.    out("\nAlle Optionen:\n{{{tt,0,|,\n, ;; ;, }
  5020. |-d||Debuginfos
  5021. |-h:|<a\|b\|o\|k\|s>|Hilfe (Alles, Beispiele, Optionen, Kontext, Standard)
  5022. |-cm||Cron-Modus
  5023. |-nu||Kein Update-Check
  5024. Console:|-c:|[CodePage]|Kodierung der Umlaute ({$cfg['char'][0]})
  5025. |-w:|[Breite]|Wortumbruch ($cfg[wrap])
  5026. |-o:|[Datei]|Ansi-Ausgabe in Datei
  5027. Login:|-s:|[SID\|Datei]|Manuelle SID Angabe (F�r Scriptdateien)
  5028. |-fb:|[Host]|Fritz!Box Angabe ($cfg[host])
  5029. |-fw:|[Version]|Manuelle Angabe der Firmware-Version ($cfg[fiwa])
  5030. |-pt:|[Port]|Port Angabe ($cfg[port])
  5031. |-ps:|[Name]|Fritz!Box Angaben aus Preset von -cc:file ausw�hlen
  5032. |-pw:|[Pass]|Kennwort Angabe
  5033. |-ui:|[Pass]|Anmeldekennwort (Bei Fernwartung)
  5034. |-tf:|<TOTP>|Zwei-Faktor-Authentisierung
  5035. |-un:|[User]|Benutzername Angabe
  5036. Request:|-b:|[Bytes]|Buffergr��e ($cfg[sbuf])
  5037. |-p:|[Protokoll]|Protokoll ($cfg[sock])
  5038. |-px:|[Proxy:Port]|HTTP-Proxy (".($cfg['proxy'] ? $cfg['proxy'] : "-").")
  5039. |-t:|[Sekunden]|TCP/IP Timeout ($cfg[tout])
  5040. |-ua:|[String]|User-Agent (".preg_replace('/\s.*$/',' ...',$cfg['head']['User-Agent']).")
  5041. Dateien:|-bz:|[Level]|ZIP Packstufe f�r BZip2-Mode festlegen ($cfg[bz])
  5042. |-gz:|[Level]|zlib/GZip/ZIP Packstufe festlegen ({$cfg['zlib']['mode']})
  5043. |-zb:|[Bits]|ZIP-Verschl�sselungsbits setzen (".($cfg['zb'] ? $cfg['zb'] : "-").")
  5044. |-zp:|[Pass]|ZIP-Verschl�sselungskennwort setzen
  5045. PHP:|-cc:|[ConfigFile]|L�dt eine Benutzerkonfig-Datei nach
  5046. |-pe:|[Extension]|L�dt ohne r�ckfrage eine PHP-Erweiterung nach".((ifset($opts) ? "\n$opts" : ""))."}}");
  5047.   elseif($cfg['help'] === true and !ifset($cfg['arg']) or $cfg['help'] === -1)
  5048.    out("\nMehr Hilfe bekommen Sie mit -h:a (Alles) -h:b (Beispiele) -h:k (Kontext) -h:o (Optionen)
  5049. Jede Funktion (mode) hat eine eigene Hilfe und bei bedarf Kontextabh�ngige Optionen");
  5050.   if(ifset($_help))
  5051.    out("\nEine Anleitung finden Sie auf ".preg_replace('/(?<=\/)www\./','',$cfg['ver'][7]).$cfg['ver'][8]);
  5052.  }
  5053.  if(ifset($cfg['error'])) {             // Wenn Fehler aufgetreten sind
  5054.   if($cfg['dbug'])
  5055.    dbug("Fehler:\n".print_r($cfg['error'],true));   // Fehler bei -d ausgeben
  5056.   $err = 0;                     // Nach Error-Codes suchen
  5057.   if(isset($cfg['error']['main']))
  5058.    foreach($cfg['error']['main'] as $var)
  5059.     if(preg_match('/^(\d+):/',$var,$m) and $e = intval($m[1]))
  5060.      $err = ($e & 128) ? max($err,$e) : $err | $e;  // Error-Code berechnen
  5061.    if(preg_array('/^1:/',$cfg['error'],18))     // Nach Infos oder Hinweisen suchen
  5062.     $err |= 1;
  5063.   if($err) {                        // Error-Code vorhanden
  5064.    if($cfg['dbug']) {                   // Error-Code entschl�sseln
  5065.     $msg = array();
  5066.     $bit = 1;
  5067.     foreach(explode(";",preg_replace('/[\t\r\n]+|#.*/','',"
  5068.     Info/Hinweis oder Warnung;                          # 0: 1
  5069.     Ung�ltige Parameter;                              # 1: 2
  5070.     Login Fehlgeschlagen (Falsches Kennwort);                   # 2: 4
  5071.     Ressource nicht gefunden/erhalten/verf�gbar (Ladefehler/Keine Berechtigung);  # 3: 8
  5072.     Falsche/defekte/ung�ltige Ressource;                      # 4: 16
  5073.     Schreibfehler (Kein Platz/Schreibberechtigung);                 # 5: 32
  5074.     Prozedur auf Ressource nicht m�glich")) as $var)              # 6: 64
  5075.      if($err & ($bit *= 2) / 2)
  5076.       $msg[] = $var;
  5077.     dbug("{{{tt}Error-Code: | $err".($msg ? "|".implode(", ",$msg) : "")." }}");    // Error-Code ausgeben
  5078.    }
  5079.    exit($err);                      // PHP mit Error-Code beenden
  5080.   }
  5081.  }
  5082. }
  5083. ?>
  5084.  
Add Comment
Please, Sign In to add comment