<?php
/**
 * @copyright (c) Kufer Software GmbH, Loisachstrasse 4, D-84453 Mühldorf
 */

define('COOKIE_ENC_KEY_STRING', 'jds83*!9293#djeiIJMK');
define('COOKIE_ENC_IV', 24491102);



class SecurityOperations
{
  
  public static function PurgeInput($pWebtools = false)
  {
    $_REQUEST = self::purgeArrayRecursive($_REQUEST, $pWebtools);

    $_POST = self::purgeArrayRecursive($_POST, $pWebtools);

    $_GET = self::purgeArrayRecursive($_GET, $pWebtools);
  }

  public static function purgeArrayRecursive($array, $pWebtools = false)
  {
    static $filter = null;
    if (\is_null($filter)) {
      $filter = FilterFactory::getFilterClass($pWebtools);
    }

    foreach ($array as $key => $value) {
      if (\is_array($value)) {
        if (!\StringOperations::startsWith($key, 'tx_')) {
          $array[$key] = self::purgeArrayRecursive($value, $pWebtools);
        }
      } else {
        $array[$key] = $filter->filterString($key, $value);
      }
    }

    return $array;
  }

  
  public static function filterSQL($pString, $pInQuote = false, $pSimulateGetSQLValue = false)
  {
    $filter = new InputfilterTools();

    return $filter->filterSQLStatements($pString, $pInQuote, $pSimulateGetSQLValue);
  }

  
  private static function getRequiredAccessKeysForToolAndSection(int $toolId, int $toolSectionId)
  {
    $toolx = new ToolX();
    $firstSights = $toolx->getFirstToolSections();
    if (($firstSights[$toolId] ?? -1) == $toolSectionId) {
      return true; 
      
    }

    switch ($toolId) {
      case 0:
        switch ($toolSectionId) {
          case 0:
            return true; 
        }

        return null;
      case \ToolsAPI::TOOL_KURSUEBERSICHT_DOZ:
        switch ($toolSectionId) {
          
          
          case 334: 
            return array(
              '1.0.1', 
              array(
                '334.1.1', '334.1.2', '334.1.3', '334.1.4',
                '334.1.5', '334.1.6', '334.1.7', '334.1.8', '334.1.9', '344.1.10'
              )
            );
          case 2:
            return array('1.0.1', '334.1.1');
          case 4:
            return array('1.0.1', '334.1.3');
          case 318:
            return array('1.0.1', '334.1.6');
          case 332:
            return array('1.0.1', '334.1.7');
          case 552:
            return array('1.0.1', '334.1.8'); 
          case 345:
            
            
            
            return array('1.0.1');
          case 3:
            return array('1.0.1', '334.1.4'); 
          case 320:
            return array('1.0.1', '334.1.5'); 
          case 317:
            return array('1.0.1', '334.1.2'); 
          case 593:
            return array('1.0.1', '334.1.9'); 
          case 802:
            return array('1.0.1', '334.1.10'); 

          case 237:
            return array(array('334.0.3', '1.0.15')); 
          case 246:
            return array('1.0.6', array('246.0.2', '246.0.4', '246.0.6', '246.0.8', '246.0.10', '246.0.12', '246.0.14')); 
          case 247:
            return array(array('1.0.7', '1.0.17')); 
          case 248:
            return array('1.0.8'); 
          case 249:
            return array('1.0.9'); 
            
          case 226:
            return array('334.0.7');  
          case 679:
            return array('3.0.8'); 
          case 773:
            return array('1.0.1', '3.0.10'); 
        }

        return null;
      case \ToolsAPI::TOOL_KURSUEBERSICHT_TN:
        switch ($toolSectionId) {
          case 7:
            return array('6.0.1');
          case 8:
            return array('6.0.2');
          case 9:
            return array('6.0.3');
        }

        return null;
      case \ToolsAPI::TOOL_KURSPLANUNG_DOZ:
        switch ($toolSectionId) {
          case 9:
            return array('9.0.3');
          case 10:
            return array('9.0.2');
          case 11:
            return array('9.0.1');
          case 280:
            return array('282.0.1');
          case 281:
            return array('10.0.1');
          case 282:
            return array('9.0.4');
        }

        return null;
      case \ToolsAPI::TOOL_RAUMBELEGUNG_HM:
        switch ($toolSectionId) {
          case 18:
            return array('339.0.1'); 
          case 35:
            return array('15.0.2'); 
          case 240:
            return array('341.0.1'); 
          case 257:
            return array(array('15.0.3', '339.0.2')); 
          case 339:
            return array(
              '15.0.1',
              array('339.1.1', '339.1.2', '339.1.3')
            );
          
          
          case 341: 
            return array(
              array('35.0.1', '35.0.2', '16.0.1', '258.0.1'),
              array('341.1.1', '341.1.2', '341.1.3', '341.1.4', '341.1.5')
            );
          case 16:
            return array('339.1.1'); 
          case 258:
            return array('339.1.2');  
          case 554:
            return array('341.1.6'); 
            
          case 561:
            return true; 
        }

        return null;
      case \ToolsAPI::TOOL_ANMELDUNGBUCHEN_MA:
        switch ($toolSectionId) {
          case 434:
            return true;
          case 19:
            return array(array('131.0.3', '19.0.7', '19.0.4'));
          case 20:
            return array('19.0.1');
          case 21:
            return array('19.0.3');
          case 22:
            return array('19.0.2');
          case 145:
            return array('19.0.6');
          case 238:
            return array('19.0.8');
        }

        return null;
      case \ToolsAPI::TOOL_LEHRPLAN_DOZ:
        
        

        
        
        
        
        
        
        switch ($toolSectionId) {
          case 24:
            return array('23.0.1');  
        }

        return null;
      case \ToolsAPI::TOOL_KURSPLANUNG_MA:
        switch ($toolSectionId) {
          case 377: 
            return array(
              '26.0.1',
              array('377.1.1', '377.1.2', '377.1.3', '377.1.4', '377.1.5', '377.1.6', '377.1.7', '377.1.8', '377.1.9', '377.1.10')
            );
          
          
          
          
          
          
          case 27:
            return array('377.1.1'); 
          case 374:
            return array('377.1.2'); 
          case 28:
            return array('377.1.3'); 
          case 242:
            return array('26.0.1', '377.1.4'); 
            
          case 29:
            return array(array('377.1.5', '377.1.8')); 
          case 375:
            return array('377.1.6'); 
          case 376:
            return array('377.1.7'); 
          case 245:
            return array('377.1.8'); 
          case 553:
            return array('377.1.9'); 
          case 759:
            return array('377.1.10'); 
            
          case 243:
            return array(array('26.0.2', '377.0.3'));
            
          case 378:
            return array(array('28.0.1', '28.0.2'));
            
          case 379:
            return array(array('29.0.6', '245.0.4')); 
            
          case 380:
            return array('377.0.5');
            
          case 432:
            return array('377.0.8');
            
          case 458:
            return array('242.0.9');
            
          case 757:
            return array(array('757.0.2', '757.0.12'));
          case 777:
            return array('242.0.17', '26.0.1'); 
        }

        return null;
      case \ToolsAPI::TOOL_VERTRAG_DOZ:
        switch ($toolSectionId) {
          case 31:
            return array('30.0.1');
          case 32:
            return array('30.0.2');
          case 33:
            return array('30.0.3');
        }

        return null;
      case \ToolsAPI::TOOL_KURSBEWERBUNG_DOZ:
        switch ($toolSectionId) {
          case 49:
            return array('98.0.1');
          case 578:
            return array('49.1.1');
          case 579:
            return array('49.1.2');
          case 580:
            return array('49.1.3');
          case 581:
            return array('49.1.4');
          case 582:
            return array('49.0.1');
        }

        return null;
      case \ToolsAPI::TOOL_TEILNEHMERINFO_MA:
        switch ($toolSectionId) {
          case 41:
            return true;
            
            
          case 42:
            return array('41.0.1');
            
          case 411:
            return array('41.0.1', array('411.1.1', '411.1.3')); 

            
            
            
            
            
            
            
        }

        return null;
      case \ToolsAPI::TOOL_DOZENTENINFO_MA:
        switch ($toolSectionId) {
          case 54:
            return true;
            
          case 57:
            return array('54.0.1');
            
            
            
            
          case 397:
            return array('54.0.1', array('397.1.1', '397.1.3', '397.1.4')); 
            
          case 403:
            return array('397.0.7'); 
          case 404:
            return true; 
          case 405:
            return array('397.0.4'); 
          case 406:
            return array('397.0.5'); 
          case 407:
            return array('397.0.6'); 

            
        }

        return null;
      case \ToolsAPI::TOOL_PERSDATA:
        switch ($toolSectionId) {
          case 89:
            return true;
          case 90:
            return true;
          case 91:
            return true;
          case 92:
            return true;
        }

        return null;
      case \ToolsAPI::TOOL_ANMELDUNGBUCHEN_TN: 
        switch ($toolSectionId) {
          case 337:
            return array('94.0.1', array('337.1.1', '337.1.2', '337.1.3', '337.1.4', '337.1.5')); 
          case 96:
            return array('94.0.1', '337.1.3'); 
          case 97:
            return array(array('94.0.2', '337.0.1')); 
        }

        return null;
      case \ToolsAPI::TOOL_AKTUELLES:
        switch ($toolSectionId) {
          case 267:
            return array(array('266.0.1', '266.0.2'));
          case 268:
            return array(array('266.0.4', '267.0.1'));
        }

        return null;
      case \ToolsAPI::TOOL_TWITTER:
        switch ($toolSectionId) {
          case 269:
            return true; 
        }

        return null;
      case \ToolsAPI::TOOL_ANWESENHEIT_DOZ:
        switch ($toolSectionId) {
          
          
          case 270:
            return array('273.0.1');
          case 271:
            return array('273.0.2');
          case 272:
            return array('273.0.3');
          case 288:
            return array('273.0.4');
          case 289:
            return array('273.0.4');
          case 290:
            return array('273.0.4');
          case 283:
            return array(array('271.0.1', '291.0.1'));
          case 274:
            return array(array('271.0.2', '291.0.2'));
            
          case 291:
            return array('273.0.5');
        }

        return null;
      case \ToolsAPI::TOOL_TN:
        switch ($toolSectionId) {
          
          case 300:
            return array('293.0.1'); 
            
          case 335:
            return array(
              array(
                '293.0.6', 
                '300.0.4'   
              ),
              array(
                '335.1.1', '335.1.2', '335.1.3', '335.1.4', '335.1.5',
                '335.1.6', '335.1.7', '335.1.8'
              )
            );
          case 297:
            return array('335.1.4'); 
          case 764:
            return array('335.1.10'); 
          case 304:
            return array('293.0.2'); 
          case 316:
            return array('335.0.5'); 
          case 358:
            return array('335.0.1'); 
        }

        return null;
      case \ToolsAPI::TOOL_KURSUEBERSICHT_FA:
        $aryKursdetails = array(
          '305.0.6', 
          '313.0.4'  
        );
        switch ($toolSectionId) {
          
          case 309:
            return array('336.1.4'); 
          case 763:
            return array('336.1.9'); 
          case 312:
            return array(array('305.0.2', '309.0.1', '313.0.5')); 
          case 313:
            return array('305.0.1'); 
          case 319:
            return array('336.0.5'); 
          case 771:
            return array($aryKursdetails, '336.1.10'); 
            
            
          case 336:
            return array(
              $aryKursdetails,
              array('336.1.1', '336.1.2', '336.1.3', '336.1.4', '336.1.5', '336.1.6', '336.1.7', '336.1.8', '336.1.9', '336.1.10')
            );
          case 360:
            return array('336.0.1'); 
          case 479:
            return array('336.0.6');
          case 480:
            return array('336.0.7'); 
        }

        return null;
      case \ToolsAPI::TOOL_MITARBEITERUEBERSICHT_FA:
        switch ($toolSectionId) {
          case 481:
            return array('314.0.3');
          case 747:
            return array('314.0.5');
          case 746:
            return array('743.829');
        }

        return null;
      case \ToolsAPI::TOOL_NACHRICHT_AN_EINRICHTUNG:
        switch ($toolSectionId) {
          case 315:
            return true;
        }

        return null;
      case \ToolsAPI::TOOL_ANMELDUNGBUCHEN_FA:
        switch ($toolSectionId) {
          
          case 324:
            return array('322.0.1', '338.1.3'); 
          case 327:
            return array(array('322.0.2', '338.0.1')); 
          case 328:
            return array(array('322.0.2', '338.0.1')); 
          case 338: 
            return array(
              '322.0.1',
              array('338.1.1', '338.1.2', '338.1.3', '338.1.4', '338.1.5')
            );
        }

        return null;
      case \ToolsAPI::TOOL_KURSVORSCHLAG_TN:
        switch ($toolSectionId) {
          case 330:
            return true;
        }

        return null;
      case \ToolsAPI::TOOL_MOB_FEEDBACK:
        switch ($toolSectionId) {
          case 362:
            return true;
          case 363:
            return true;
        }

        return null;
      case \ToolsAPI::TOOL_ADRESSINFO_MA:
        switch ($toolSectionId) {
          
          case 55:
            return true;
            
            
            
          case 410:
            return array('55.0.1', array('410.1.1', '410.1.3')); 
        }

        return null;
      case \ToolsAPI::TOOL_RAUMBELEGUNG_MA:
        switch ($toolSectionId) {
          
          case 421:
            return array('417.0.1'); 
          case 422:
            return array('415.0.2'); 
          case 423:
            return array(array('415.0.3', '417.0.2')); 
          case 417: 
            return array('415.0.1', array('417.1.1', '417.1.2', '417.1.3'));
            
            
          case 418:
            return array('417.1.1'); 
          case 420:
            return array('417.1.2'); 
        }

        return null;
      case \ToolsAPI::TOOL_PORTRAIT_DOZ:
        switch ($toolSectionId) {
          case 457:
            return true;
          case 651:
            return true;
        }

        return null;
      case \ToolsAPI::TOOL_WEBVISITENKARTEN:
        switch ($toolSectionId) {
          case 496:
            return true;
        }

        return null;
      case \ToolsAPI::TOOL_KURSVORSCHLAG_MA:
        switch ($toolSectionId) {
          case 515:
            return true;
          case 516:
            return array('515.0.1'); 
        }

        return null;
      case 42: 
        switch ($toolSectionId) {
          
          case 527:
            return array('526.0.1', array('527.1.1', '527.1.2', '527.1.3')); 
          case 528:
            return array('526.0.1', '527.1.1');
          case 529:
            return array('526.0.1', '527.1.2');
          case 530:
            return array('526.0.1', '527.1.3');
        }

        return null;
      case 45: 
        switch ($toolSectionId) {
          case 550:
            return true;
          case 551:
            return true;
        }

        return null;
      case 46: 
        switch ($toolSectionId) {
          case 555:
            return true;
          case 556:
            return true;
          case 557:
            return true;
        }

        return null;
      case 47: 
        switch ($toolSectionId) {
          case 558:
            return true;
          case 559:
            return true;
          case 560:
            return true;
        }

        return null;
      case 48: 
        switch ($toolSectionId) {
          case 563:
            return true;
          case 564:
            return true;
          case 565:
            return true;
        }

        return null;
      case \ToolsAPI::TOOL_FEEDBACK_AUSWERTUNGEN_DOZ:
        switch ($toolSectionId) {
          case 568:
            return true;
        }

        return null;
      case \ToolsAPI::TOOL_FEEDBACK_AUSWERTUNGEN_MA:
        switch ($toolSectionId) {
          case 569:
            return true;
          case 570:
            return true;
        }

        return null;
      case \ToolsAPI::TOOL_KURSUEBERSICHT_VA: 
        switch ($toolSectionId) {
          
          case 632: 
            return array('622.0.1', array('632.1.1', '632.1.2', '632.1.3', '632.1.4', '632.1.5', '632.1.6', '632.1.7', '632.1.8', '632.1.9'));
          case 628:
            return array('622.0.1', '632.1.1');
          case 627:
            return array('622.0.1', '632.1.2');
          case 631:
            return array('622.0.1', '632.1.3');
          case 630:
            return array('622.0.1', '632.1.4');
          case 626:
            return array('622.0.1', '632.1.5');
          case 623:
            return array('622.0.1', '632.1.6');
          case 625:
            return array('622.0.1', '632.1.7');
          case 624:
            return array('622.0.1', '632.1.8');
          case 629:
            return array('622.0.1', '632.1.9');
          case 633:
            return array('622.0.1', '632.1.3');
          case 621:
            return array('622.0.1', '632.0.4');
          case 618:
            return array('622.0.1', '630.0.9');
          case 619:
            return array('622.0.1', array('626.0.6', '624.0.4'));
          case 620:
            return array(array('622.0.2', '632.0.1'));
          case 617:
            return array('632.0.2');
          case 775:
            return array('630.0.12'); 
        }

        return null;
      case \ToolsAPI::TOOL_KURSVORSCHLAG_VA:
        switch ($toolSectionId) {
          case 615:
            return array('616.0.1');
          case 701:
            return true;
          case 742:
            return true;
          case 702:
            return true;
          case 738:
            return true;
        }

        return null;
      case \ToolsAPI::TOOL_ANMELDUNGBUCHEN_VA:
        switch ($toolSectionId) {
          case 635:
            return true;
          case 636:
            return true;
          case 637:
            return array('634.0.13');
        }

        return null;
      case \ToolsAPI::TOOL_KURSUEBERSICHT_ANDERER_VERANSTALTER_VA:
        switch ($toolSectionId) {
          
          case 640:
            return array('639.0.1', array('640.1.1', '640.1.2', '640.1.3', '640.1.4')); 
          case 641:
            return array('639.0.1', array('640.1.1'));
          case 642:
            return array('639.0.1', array('640.1.2'));
          case 643:
            return array('639.0.1', array('640.1.3'));
          case 644:
            return array('639.0.1', array('640.1.4'));
        }

        return null;
      case 55: 
        switch ($toolSectionId) {
          
          case 652:
            return true;
            
          case 655:
            return array('652.0.1');
            
            
            
            
          case 654:
            return array('652.0.1', array('654.1.1', '654.1.3', '654.1.4')); 
            
          case 659:
            return array('654.0.7'); 
          case 660:
            return true; 
          case 661:
            return array('654.0.4'); 
          case 663:
            return array('654.0.5'); 
          case 662:
            return array('654.0.6'); 
        }

        return null;
      case 57: 
        switch ($toolSectionId) {
          case 681:
            return true;
          case 682:
            return true;
          case 683:
            return true;
        }

        return null;
      case \ToolsAPI::TOOL_TEILNEHMERINFO_VA:
        switch ($toolSectionId) {
          case 686:
            return true;
          case 690:
            return array('686.0.1');
          case 687:
            return array('686.0.1', array('687.1.1', '687.1.3')); 
        }

        return null;
      case 59: 
        switch ($toolSectionId) {
          case 694:
            return array('693.0.1');
        }

        return null;
      case \ToolsAPI::TOOL_LEITER_MITARBEITER_ANDERER_VERANSTALTER_VA:
        switch ($toolSectionId) {
          case 696:
            return true;
          case 698:
            return array('699.1.2'); 
          case 699:
            return array('696.0.1', array('699.1.1', '699.1.2')); 
        }

        return null;
      case 62: 
        switch ($toolSectionId) {
          case 745:
            return array('744.0.1');
        }

        return null;
      case \ToolsAPI::TOOL_FEEDBACK_AUSWERTUNGEN_FA:
        switch ($toolSectionId) {
          case 752:
            return true;
        }

        return null;
      case 64: 
        switch ($toolSectionId) {
          case 753:
            return array('754.0.1');
          case 754:
            return true;
        }

        return null;
      case 65: 
        switch ($toolSectionId) {
          case 756:
            return true;
          case 755:
            return array('756.0.1');
        }

        return null;
      case 66: 
        switch ($toolSectionId) {
          case 769:
          case 770:
            return true;
        }

        return null;
      case 61: 
        switch ($toolSectionId) {
          
          case 722:
            return array(
              array('721.0.6'),
              array('722.1.1', '722.1.2', '722.1.3', '722.1.4', '722.1.5', '722.1.6', '722.1.7')
            );
        }

        return null;
      case \ToolsAPI::TOOL_DOZ_WUNSCHTERMINE:
        switch ($toolSectionId) {
          case 796:
            return true;
          case 798:
            return array('796.0.1');
          case 799:
            return array('796.0.3');
        }

        return null;
      case \ToolsAPI::TOOL_DOZ_URLAUBE:
        switch ($toolSectionId) {
          case 797:
            return true;
          case 800:
            return array('797.0.1');
          case 801:
            return array('797.0.3');
        }

        return null;
      case \ToolsAPI::TOOL_DOZ_SAMMELVERTRAEGE:
        switch ($toolSectionId) {
          case 804:
          case 803:
            return true;
        }

        return null;
    }

    return null;
  }

  
  public static function checkToolAccess($pUserid, $pToolid, $pToolSection)
  {
    if ($pUserid->isEmpty(false)) {
      return false;
    }

    
    $dbwTools = \DBWorkTools::getDefaultInstance();
    if (!$dbwTools->isToolAllowed($pUserid, $pToolid)) {
      return false; 
    }
    unset($dbwTools);

    $accessKeys = static::getRequiredAccessKeysForToolAndSection((int)$pToolid, (int)$pToolSection);
    if (is_null($accessKeys)) {
      return false;
    } else {
      
      $fnAllowedOr = static function($keys) use ($pUserid, $pToolid) {
        if (!is_array($keys)) {
          $keys = array($keys);
        }

        foreach ($keys as $einzelrecht) {
          if (static::privilegAllowed($pUserid, $pToolid, $einzelrecht) == 2) {
            return true;
          }
        }

        return false;
      };
      
      $fnAllowedAnd = static function($keys) use ($fnAllowedOr) {
        if ($keys === true) {
          return true;
        }

        if ($keys === false) {
          return false;
        }

        if (!is_array($keys)) {
          $keys = array($keys);
        }

        assert(!empty($keys));

        foreach ($keys as $orKeys) {
          if (!call_user_func($fnAllowedOr, $orKeys)) {
            return false;
          }
        }

        return true;
      };

      return $fnAllowedAnd($accessKeys);
    }
  }

  

  
  public static function generateSalt($size = 32)
  {
    $result = \random\RandomBytes::getRandomBytes($size);
    if (false === $result) {
      Logger::logg('Es konnte beim Salt generieren keine Zufallszahl erzeugt werden', 55);
    }

    return base64_encode($result);
  }

  
  public static function getSaltedHash($pw, $pSalt)
  {
    if ($pSalt == '') {
      return '';
    }

    return md5($pSalt . $pw . SALT . $pSalt);
  }

  public static function checkSaltedHash($pw, $pSalt, $pHash)
  {
    return (StringOperations::strtolower(trim($pHash)) === StringOperations::strtolower(trim(SecurityOperations::getSaltedHash($pw, $pSalt))));
  }

  
  public static function smartBlockBots($checkPage = true)
  {
    if ($checkPage) {
      $urls = array('/kathaupt(=|:|%3A|%253A)(3|4|5|6|16|18|26|203)/', '/(month|year)(=|:|%3A|%253A)[0-9]{1,4}/',
            '/(knradd|suchesetzen|blkeep)(=|:|%3A|%253A)/', '/browse(=|:|%3A|%253A)backward/',
            '/(einzeltermine|reiter|Fsize|Layout|history)=/'
          );
      foreach ($urls as $regex) {
        if (preg_match($regex, $_SERVER['QUERY_STRING'])) {
          $checkPage = false;
        }
      }
    }

    if (!$checkPage) {
      $bots = array('/bot/i', '/crawler/i', '/search/i', '/spider/i');
      foreach ($bots as $regex) {
        if (preg_match($regex, RequestOperations::getUserAgent())) {
          RequestOperations::sendHttpStatusAndQuit(403);
        }
      }
    }
  }

  
  public static function doWtLogin()
  {
    return (SecurityOperations::doWtLoginNew(RequestOperations::getVarValue('Kennwort'), RequestOperations::getVarValue('Passwort')) >= 0);
  }

  
  public static function doWtLoginNew($pUser, $pPassword)
  {
    $filter = FilterFactory::getFilterClass();
    $user = $filter->filterLogin($pUser);
    $password = $pPassword; 

    $dblogin = new DBWorkLogin();
    $dbuser_id = $dblogin->LoginOK($user, $password);

    if (\Kufer\KuferTools\Utils\LDAP\BaseLoginLDAP::hasEinrichtungTeilnehmerLDAPLogin() && is_int($dbuser_id) && $dbuser_id < 0) {
      $dbuser_id = $dblogin->loginViaLDAP($user, $password, $dbuser_id);
    }

    $result = false;
    if ($dbuser_id instanceof \Kufer\Web\Classes\Identifier\Identifier) {
      $result = true;
      SessionOperations::session_destroy_selective();
      session_regenerate_id(true); 
      self::setWtUserToSession($user, $dbuser_id, $dblogin->isAdmin($dbuser_id));
    }

    $allgSettings = AllgSettingsAPI::getAllgSettings();
    $file = StringOperations::getURLwithoutParams(true);
    if ($file != 'toolsInterface.php' && $file != 'aktuellesByEmail.php') {
      if ($allgSettings->login_log_enabled) {
        SecurityOperations::fillLoginProtocol($user, false, $result);
      }

      SecurityOperations::checkLoginErrCount($user, $dbuser_id);
      if ($result) {
        SecurityOperations::setLoginDate();
      }
    }

    return ($result) ? true : $dbuser_id; 
  }

  
  public static function setWtUserToSession($pUsername, \Kufer\Web\Classes\Identifier\Identifier $id, $pAdminId)
  {
    assert(!$id->isEmpty(false)); 

    \SessionOperations::setVarValueWTIntern('login', $pUsername);
    \SessionOperations::setVarValueWTIntern('user_id', $id->getId());
    \SessionOperations::setVarValueWTIntern('user_guid', (string)$id->getGuid());
    \SessionOperations::setVarValueWTIntern('admin_id', $pAdminId);
  }

  
  private static function setLoginDate()
  {
    $user = SessionOperations::getCurrentWebToolsUser();
    $user->zuletzt_eingeloggt = DateTimeOperations::getDateTimeNow();

    
    
    
    
    

    if (false) { 
      
      
      $personKeys = array_keys(get_class_vars('Personn'));
      $userKeys = array_keys(get_class_vars('Benutzer'));
      $diffKeys = array_intersect($personKeys, $userKeys);
      $diffKeys = array_diff($diffKeys, array('id'));
      
      $diffKeys = array_merge($diffKeys, array('dnr', 'tnr', 'anr', 'ben', 'admin', 'name_titel'));

      $infoNode = new XMLNode();
      $infoNode = $infoNode->getXMLNode($user, 'web_users', $diffKeys, true);

      try {
        $abgleichApi = new AbgleichAPI();
        $result = $abgleichApi->sendeNachricht(
          AbgleichAPI::ABGLEICH_WEB_USER,
          new Nutzlast($infoNode)
        );
      } catch (Exception $e) {
        Logger::logg('Loginvorgang - Folgende Exception ist aufgetreten: ' . $e->getMessage() . ' [' . $e->getTraceAsString() . ']', 200);
        
      }
    } else {
      $dbwUser = new DBWorkUser(1, true);
      $dbwUser->updateUser($user);
    }
  }

  
  private static function checkLoginErrCount($pLoginName, $pFehlerCode)
  {
    
    
    if ($pFehlerCode === DBWorkLogin::LOGIN_ERR_NO_USER_OR_PW
        || $pFehlerCode === DBWorkLogin::LOGIN_ERR_LOGIN_DISABLED
        || $pFehlerCode === DBWorkLogin::LOGIN_ERR_MISSING_STAMMDATEN) {
      return;
    }
    $dbwUser = new DBWorkUser(1, true);
    $user = $dbwUser->getUserbyLogin($pLoginName);


    $dbwWPU = new DBWorkWebPasswordsUsers(1, true);
    $wpu = $dbwWPU->getWebPasswordsUsersByLogin($user->login);
    if (is_null($wpu->id)) {
      return;
    }

    $objsettings = ToolSettingsAPI::getToolSettings(0);

    if ($pFehlerCode === DBWorkLogin::LOGIN_ERR_MULTI_PW) {
      
      $wpu->gesperrt_bis = '31.12.2300 ' . DEFAULTTIME_WITH_SECONDS;
      Logger::Logg('Login: Mehrfaches Passwort für ' . $user->login . '. Verdacht auf SQL-Injection.', 200);
    } elseif ($pFehlerCode === DBWorkLogin::LOGIN_ERR_WRONG_PW) {
      

      

      $wpu->anzahl_fehlversuche++;
      if ($objsettings->login_err_count > 0 && $wpu->anzahl_fehlversuche >= $objsettings->login_err_count) {
        
        
        $tmpWpu = clone $wpu;
        
        
        $wpu = SecurityOperations::maxLoginVersucheErreicht($wpu, $objsettings);
        if ($objsettings->login_err_email && $tmpWpu->anzahl_fehlversuche == $objsettings->login_err_count) {
          
          SecurityOperations::maxLoginEMail($user, $tmpWpu->anzahl_fehlversuche, $wpu->gesperrt_bis);
        }
      }
    } elseif ($pFehlerCode instanceof \Kufer\Web\Classes\Identifier\Identifier && !$pFehlerCode->isEmpty()) {
      $wpu->anzahl_fehlversuche = 0;
    }

    $dbwWPU->updateWebPasswordsUsers($wpu);


    
    
    
    

    if (false) {  
      $infoNode = new XMLNode();
      $infoNode = $infoNode->getXMLNode($wpu, 'web_passwords_users', array(), true);

      try {
        $abgleichApi = new AbgleichAPI();
        $result = $abgleichApi->sendeNachricht(
          AbgleichAPI::ABGLEICH_WEB_PASSWORDS_USERS,
          new Nutzlast($infoNode)
        );
      } catch (Exception $e) {
        Logger::logg('Loginvorgang - Folgende Exception ist aufgetreten: ' . $e->getMessage() . ' [' . $e->getTraceAsString() . ']', 200);
        
      }
    } 
  }

  
  private static function maxLoginEMail($pUser, $pAnzFehlversuche, $pGesperrtBis): bool
  {
    $nameKomplett = (trim($pUser->name_titel) != '') ? $pUser->name_titel . ' ' : '';
    $nameKomplett .= $pUser->name;
    $nameKomplett .= (trim($pUser->vorname) != '') ? ' ' . $pUser->vorname : '';
    $eMail = $nameKomplett . ' hat ' . $pAnzFehlversuche . ' mal in Folge '
             . 'ein falsches Passwort zum Login ' . $pUser->login . ' eingegeben.' . "\n\n";

    $timeDistanceSeconds = DateTimeOperations::getTimeDistanceToNow(StringOperations::substr($pGesperrtBis, 0, 10), StringOperations::substr($pGesperrtBis, 11));

    $showKuferSQLInfo = false;
    if ($timeDistanceSeconds >= 0) {
      
      $gesperrt = 'nicht';
    } elseif ($timeDistanceSeconds < -3075840000) {
      
      $gesperrt = 'dauerhaft';
      $showKuferSQLInfo = true;
    } else {
      $gesperrt = 'vorübergehend bis ' . $pGesperrtBis;
      
      
    }

    $eMail .= 'Das Login wurde ' . $gesperrt . ' gesperrt.' . "\n\n";

    if ($showKuferSQLInfo) {
      $eMail .= 'Das Login kann in KuferSQL im Reiter Login der entsprechenden Stammdaten '
                . 'wieder freigegeben werden.';
    }

    $eMailBetreff = 'KuferTools - fehlerhafte Loginversuche: ' . $nameKomplett;

    $email = new \Kufer\Mail\EMail\EMailPlaintext($eMailBetreff, $eMail);
    $email->addKuferToolsFooter('Login KuferTools', $pUser);
    $sender = \Kufer\Mail\Sender\EMailSenderFactory::create();

    return $sender->informEinrichtung($email)->hasSentAnyMails();
  }

  
  private static function maxLoginVersucheErreicht($pPasswordUsers, $pObjsettings)
  {
    
    switch ($pObjsettings->login_err_disable) {
      default:
      case $pObjsettings::LOGIN_ERR_DISABLE_NICHT_SPERREN:
        break;

      case $pObjsettings::LOGIN_ERR_DISABLE_DAUERHAFT_SPERREN:
        $pPasswordUsers->gesperrt_bis = '31.12.2300 ' . DEFAULTTIME_WITH_SECONDS;
        break;

      case $pObjsettings::LOGIN_ERR_DISABLE_VORUEBERGEHEND_SPERREN:
        
        
        
        $dateTime = DateTimeOperations::getDateTimeNow();
        $shiftVal = $pObjsettings->login_err_disable_value;
        if ($shiftVal > 0) {
          switch ($pObjsettings->login_err_disable_unit) {
            case $pObjsettings::LOGIN_ERR_DISABLE_UNIT_MINUTEN:
              $minuten = StringOperations::substr($dateTime, 14, 2);
              $newMinuten = $minuten + $shiftVal;

              $shiftVal = floor($newMinuten / 60);
              $newMinuten = $newMinuten % 60;
              if ($newMinuten < 10) {
                $newMinuten = '0' . $newMinuten;
              }

              $dateTime = substr_replace($dateTime, $newMinuten, 14, 2);

              
              
              if ($shiftVal == 0) {
                break;
              }
              
            case $pObjsettings::LOGIN_ERR_DISABLE_UNIT_STUNDEN:
              $stunden = StringOperations::substr($dateTime, 11, 2);
              $newStunden = $stunden + $shiftVal;

              $shiftVal = floor($newStunden / 24);
              $newStunden = $newStunden % 24;
              if ($newStunden < 10) {
                $newStunden = '0' . $newStunden;
              }

              $dateTime = substr_replace($dateTime, $newStunden, 11, 2);

              
              
              if ($shiftVal == 0) {
                break;
              }

              
            case $pObjsettings::LOGIN_ERR_DISABLE_UNIT_TAGE:
              $datum = StringOperations::substr($dateTime, 0, 10);
              $datum = DateTimeOperations::getDateDaysBefore($datum, -$shiftVal);
              $dateTime = substr_replace($dateTime, $datum, 0, 10);
              break;
          }

          $pPasswordUsers->anzahl_fehlversuche = 0;
        }

        $pPasswordUsers->gesperrt_bis = $dateTime;
        break;
    }

    return $pPasswordUsers;
  }

  
  public static function fillLoginProtocol($pUserName, $pLogOut, $pLoginOK = true)
  {
    $dbwWlp = new DBWorkWebLoginProtocol(1, true);
    $wlp = $dbwWlp->getNewObject();

    $wlp->login = StringOperations::strtoupper($pUserName);
    $wlp->zeitpunkt = DateTimeOperations::getDateTimeNow();

    
    if (SessionOperations::isKuferTools()) {
      $wlp->modul = WebLoginProtocol::LOGIN_PROT_MODUL_KUFERTOOLS;
    } elseif (defined('ISWEBADMIN') && ISWEBADMIN) {
      $wlp->modul = WebLoginProtocol::LOGIN_PROT_MODUL_WEBADMIN;
    } else {
      return; 
    }

    
    if ($pLogOut) {
      $wlp->vorgang = WebLoginProtocol::LOGIN_PROT_VORGANG_LOGOUT;
    } elseif ($pLoginOK) {
      $wlp->vorgang = WebLoginProtocol::LOGIN_PROT_VORGANG_LOGIN;
    } else {
      $wlp->vorgang = WebLoginProtocol::LOGIN_PROT_VORGANG_LOGIN_ERR;
    }

    if (defined('ISWEBADMIN') && ISWEBADMIN) {
      $wlp->user_id = -1; 
    } else {
      $dbUser = new DBWorkUser(1, true);
      $user = $dbUser->getUserbyLogin($pUserName);
      $wlp->user_id = ($user->id > 0) ? $user->id : -1;
    }

    $dbwWlp->insertWebLoginProtocol($wlp);
  }

  
  public static function checkWtLogout()
  {
    if (isset($_REQUEST['Abmelden']) && $_REQUEST['Abmelden'] != '') {
      return static::doWtLogout();
    } else {
      return false;
    }
  }

  public static function doWtLogout()
  {
    $allgSettings = AllgSettingsAPI::getAllgSettings();

    if ($allgSettings->login_log_enabled) {
      $user = SessionOperations::getCurrentWebToolsUser();
      SecurityOperations::fillLoginProtocol((!$user->isEmpty()) ? $user->login : null, true);
    }

    session_unset(); 
    session_regenerate_id(true); 
    
    $id = SessionOperations::getUserIdentifier();

    return is_null($id);
  }

  
  public static function anonymizeString($pString, $pDigits = 3)
  {
    $length = StringOperations::strlen($pString);
    $pString = StringOperations::substr($pString, $length - $pDigits, $pDigits);
    for ($i = $pDigits; $i < $length; $i++) {
      $pString = '*' . $pString;
    }

    return $pString;
  }

  
  public static function setCookieDomainFromSettings()
  {
    static $alreadySet = false;
    if (!$alreadySet) {
      $alreadySet = true;
      $allgsettings = AllgSettingsAPI::getAllgSettings();
      $sessionCookieDomain = $allgsettings->sessionDomain;

      if ($sessionCookieDomain != '') {
        $sessionCookieValues = session_get_cookie_params();

        session_set_cookie_params(
          $sessionCookieValues['lifetime'],
          $sessionCookieValues['path'],
          $sessionCookieDomain,
          $sessionCookieValues['secure'],
          $sessionCookieValues['httponly']
        );
      }
    }
  }

  
  public static function privilegAllowedCurrentUser($toolId, $privilegId, $dbTyp = 1)
  {
    return static::privilegAllowed(\SessionOperations::getUserIdentifier(), $toolId, $privilegId, $dbTyp);
  }

  
  public static function privilegAllowed(\Kufer\Web\Classes\Identifier\Identifier $userId, $toolId, $pPrivileg_id, $dbtyp = 1)
  {
    if ($userId->isEmpty(false)) {
      return 0; 
    }

    assert(!$userId->isIdEmpty(false));

    static $cachePrivilegAllowed_sonderrechteDesUsers = array();
    static $cachePrivilegAllowed_vorlagenrechteDesUsers = array();

    $cacheKey = $userId->getCacheKey();

    $keySonderrechte = $toolId . '|' . $pPrivileg_id;
    $dboperation = DBOperation::getInstance($dbtyp, true); 

    if (SessionOperations::getVarValueWTIntern('admin_id') == 1) {
      
      return 2;
    }

    $returnvalue = 0;

    if (!isset($cachePrivilegAllowed_sonderrechteDesUsers[$cacheKey])) {
      
      $builder = (\DBWorkTools::getDefaultInstance($dbtyp))->getSelectQueryBuilder()
        ->select('tu.tool_id, p.keynumber, ptu.accessnumber')
        ->from('web_tools_users', 'tu')
        ->innerJoin('web_privileges_t_u ptu', 'ptu.tool_user_id = tu.id')
        ->innerJoin('web_privileges p', 'ptu.privileg_id = p.id')
        ->where('tu.user_id = :userId:')
        ->paramInt('userId', $userId->getId());

      $dboperation->clear();
      $dboperation->query($builder->getSQL());
      
      $cachePrivilegAllowed_sonderrechteDesUsers[$cacheKey] = array();
      while ($dboperation->selectNextRow()) {
        
        $key = $dboperation->decodeStringFromDb($dboperation->fieldbyname('tool_id')) . '|' . $dboperation->decodeStringFromDb($dboperation->fieldbyname('keynumber'));
        $cachePrivilegAllowed_sonderrechteDesUsers[$cacheKey][$key] = intval($dboperation->decodeStringFromDb($dboperation->fieldbyname('accessnumber')));
      }
    }

    
    if (isset($cachePrivilegAllowed_sonderrechteDesUsers[$cacheKey][$keySonderrechte])) {
      return $cachePrivilegAllowed_sonderrechteDesUsers[$cacheKey][$keySonderrechte];
    }

    if (!isset($cachePrivilegAllowed_vorlagenrechteDesUsers[$cacheKey])) {
      $cachePrivilegAllowed_vorlagenrechteDesUsers[$cacheKey] = array();
    }

    if (!isset($cachePrivilegAllowed_vorlagenrechteDesUsers[$cacheKey][$toolId])) {
      

      $builder = (new \DBWorkTools($dbtyp))->getSelectQueryBuilder();
      $builder
        ->select('tu.tool_id, p.keynumber, pt.accessnumber')
        ->from('web_tools_users', 'tu')
        ->innerJoin('web_templates t', 't.id = tu.template_id')
        ->innerJoin('web_privileges_t pt', 'pt.template_id = t.id')
        ->innerJoin('web_privileges p', 'pt.privileg_id = p.id')
        ->where('tu.user_id = :userId:')
        ->and('tu.tool_id = :toolId:')
        ->paramInt('userId', $userId->getId())
        ->paramInt('toolId', $toolId);

      $dboperation->clear();
      $dboperation->query($builder->getSQL());
      $cachePrivilegAllowed_vorlagenrechteDesUsers[$cacheKey][$toolId] = array();
      
      while ($dboperation->selectNextRow()) {
        
        $key = $dboperation->decodeStringFromDb($dboperation->fieldbyname('tool_id')) . '|' . $dboperation->decodeStringFromDb($dboperation->fieldbyname('keynumber'));
        $cachePrivilegAllowed_vorlagenrechteDesUsers[$cacheKey][$toolId][$key] = intval($dboperation->decodeStringFromDb($dboperation->fieldbyname('accessnumber')));
      }
    }

    if (array_key_exists($keySonderrechte, $cachePrivilegAllowed_vorlagenrechteDesUsers[$cacheKey][$toolId])) {
      $returnvalue = $cachePrivilegAllowed_vorlagenrechteDesUsers[$cacheKey][$toolId][$keySonderrechte];
    }

    return $returnvalue;
  }
}