ript' ); $item -> setAttribute( 'type', 'text/seraph-accel-lazypart-sep' ); $item -> setAttribute( 'id', $id ); return( $item ); } function ContentMarkGetPartSep( $id ) { $doc = new \DOMDocument(); $sep = ContentMarkSeparate_CreateLazyPartSepElem( $doc, $id ); return( $doc -> saveHTML( $sep ) ); } function ContentMarkSeparateSofter( &$content, $hide = true ) { $content = str_replace( ContentMarkGetSep(), $hide ? '' : '', $content ); } function GetCacheSiteIdAdjustPath( $sites, &$addr, &$siteSubId, &$path ) { if( !is_array( $sites ) ) return( null ); if( $path ) $addr .= '/' . $path; $addrSite = $addr; for( ;; ) { $id = (isset($sites[ $addrSite ])?$sites[ $addrSite ]:null); if( $id ) { $path = ltrim( substr( $addr, strlen( $addrSite ) ), '/' ); $posSubSite = strpos( $id, '-' ); if( $posSubSite !== false ) { $siteSubId = substr( $id, $posSubSite + 1 ); $id = substr( $id, 0, $posSubSite ); } $addr = $addrSite; return( $id ); } $addrSiteNext = dirname( $addrSite ); if( $addrSiteNext === $addrSite ) break; $addrSite = $addrSiteNext; unset( $addrSiteNext ); } return( null ); } function GetSiteIds() { static $aIds; if( $aIds !== null ) return( $aIds ); global $seraph_accel_sites; $aIds = array(); foreach( ( array )$seraph_accel_sites as $id ) { $posSubSite = strpos( $id, '-' ); if( $posSubSite !== false ) $id = substr( $id, 0, $posSubSite ); $aIds[ $id ] = true; } return( $aIds = array_keys( $aIds ) ); } function CachePathNormalize( $path, &$pathIsDir ) { if( $path == '/' ) { $pathIsDir = true; $path = ''; } else { $path = strtolower( ltrim( $path, '/' ) ); if( substr( $path, -1 ) == '/' ) { $pathIsDir = true; $path = rtrim( $path, '/' ); } } return( Gen::GetNormalizedPath( $path ) ); } function ParseContCachePathArgs( $serverArgs, &$args ) { $path = (isset($serverArgs[ 'REQUEST_URI' ])?$serverArgs[ 'REQUEST_URI' ]:null); $posQuery = strpos( $path, '?' ); if( $posQuery !== false ) { $queryOrig = substr( $path, $posQuery + 1 ); if( $args === null || $queryOrig != (isset($serverArgs[ 'QUERY_STRING' ])?$serverArgs[ 'QUERY_STRING' ]:null) ) { $args = array(); @parse_str( $queryOrig, $args ); } $path = substr( $path, 0, $posQuery ); } else $args = array(); return( $path ); } function GetContCacheEarlySkipData( &$path = null , &$pathIsDir = null , &$args = null ) { global $seraph_accel_g_cacheSkipData; if( $seraph_accel_g_cacheSkipData !== null ) return( $seraph_accel_g_cacheSkipData ); $seraph_accel_g_cacheSkipData = false; if( defined( 'SID' ) && SID != '' ) $seraph_accel_g_cacheSkipData = array( 'skipped', array( 'reason' => 'sid' ) ); else if( is_admin() ) $seraph_accel_g_cacheSkipData = array( 'skipped', array( 'reason' => 'admin' ) ); else if( defined( 'DOING_CRON' ) || isset( $_REQUEST[ 'doing_wp_cron' ] ) ) $seraph_accel_g_cacheSkipData = array( 'skipped', array( 'reason' => 'cron' ) ); else if( defined( 'XMLRPC_REQUEST' ) ) $seraph_accel_g_cacheSkipData = array( 'skipped', array( 'reason' => 'xmlrpc' ) ); else { $path = CachePathNormalize( ParseContCachePathArgs( $_SERVER, $args ), $pathIsDir ); if( strpos( $path, 'robots.txt' ) !== false ) $seraph_accel_g_cacheSkipData = array( 'skipped', array( 'reason' => 'robots' ) ); else if( strpos( $path, '.htaccess' ) !== false ) $seraph_accel_g_cacheSkipData = array( 'skipped', array( 'reason' => 'htaccess' ) ); else if( strpos( '/' . $path, '/wp-' ) !== false ) $seraph_accel_g_cacheSkipData = array( 'skipped', array( 'reason' => 'wpUrl' ) ); } return( $seraph_accel_g_cacheSkipData ); } function _NormalizeExclPath( &$path ) { if( strlen( $path ) > 1 && $path[ 0 ] === '/' ) $path = substr( $path, 1 ); } function IsUriByPartsExcluded( $settCache, $path, $args ) { if( is_string( $args ) ) $args = Net::UrlParseQuery( $args ); _NormalizeExclPath( $path ); return( !!_ContProcGetExclStatus( $settCache, Gen::GetArrField( $settCache, array( 'ctxGrps' ), array() ), null, null, $path, $args ) ); } function CheckPathInUriList( $a, $path ) { foreach( $a as $aa ) { _NormalizeExclPath( $aa ); $matched = false; foreach( ExprConditionsSet_Parse( $aa ) as $e ) { $isRegExp = IsStrRegExp( $e[ 'expr' ] ); if( $isRegExp ) { if( @preg_match( $e[ 'expr' ], $path, $valFound ) ) $valFound = count( $valFound ) > 1 ? $valFound[ 1 ] : $valFound[ 0 ]; else $valFound = ''; } else if( strpos( $path, $e[ 'expr' ] ) === 0 ) $valFound = $path; else $valFound = ''; $matched = ExprConditionsSet_ItemOp( $e, $valFound ); if( !$matched ) break; } if( $matched ) return( $aa ); } return( null ); } function _ContProcGetExclStatus( $settCache, $ctxGrps, $userAgent, $cookies, $path, &$args, $adjustArgs = false ) { if( !empty( $args ) ) { if( Gen::GetArrField( $settCache, array( 'exclArgsAll' ), true ) ) return( 'exclArgsAll' ); if( Gen::GetArrField( $settCache, array( 'skipArgsAll' ), false ) ) $args = array(); $exclArgs = Gen::GetArrField( $settCache, array( 'exclArgs' ), array() ); $skipArgs = Gen::GetArrField( $settCache, array( 'skipArgs' ), array() ); foreach( $args as $argKey => $argVal ) { $argKeyCmp = strtolower( $argKey ); foreach( $exclArgs as $a ) if( strpos( $argKeyCmp, $a ) === 0 ) return( 'exclArgs:' . $a ); foreach( $ctxGrps as $ctxGrp ) { if( !(isset($ctxGrp[ 'enable' ])?$ctxGrp[ 'enable' ]:null) ) continue; $ctxArgs = Gen::GetArrField( $ctxGrp, array( 'args' ), array() ); foreach( $ctxArgs as $a ) if( strpos( $argKeyCmp, $a ) === 0 ) return( 'userCtxArgs:' . $a ); } if( $adjustArgs ) foreach( $skipArgs as $a ) if( strpos( $argKeyCmp, $a ) === 0 ) unset( $args[ $argKey ] ); } } if( $uriExcl = CheckPathInUriList( Gen::GetArrField( $settCache, array( 'urisExcl' ), array() ), $path ) ) return( 'urisExcl:' . $uriExcl ); if( $userAgent ) foreach( Gen::GetArrField( $settCache, array( 'exclAgents' ), array() ) as $e ) if( strpos( $userAgent, $e ) !== false ) return( 'exclAgents:' . $e ); $exclCookies = Gen::GetArrField( $settCache, array( 'exclCookies' ), array() ); if( $exclCookies && $cookies ) foreach( $cookies as $cookKey => $cookVal ) foreach( $exclCookies as $e ) if( strpos( $cookKey, $e ) === 0 ) return( 'exclCookies:' . $e ); return( false ); } function ContProcGetExclStatus( $siteId, $settCache, $path, $pathIsDir, &$args, &$varsOut, $adjustArgs = true, $adjustStat = true ) { global $seraph_accel_g_contProcGetExclStatus; global $seraph_accel_g_prepContIsUserCtx; global $seraph_accel_g_cacheCtxSkip; if( $seraph_accel_g_contProcGetExclStatus !== null ) return( $seraph_accel_g_contProcGetExclStatus ); $tmCur = Gen::GetCurRequestTime(); $varsOut = array(); $userAgent = strtolower( (isset($_SERVER[ 'HTTP_USER_AGENT' ])?$_SERVER[ 'HTTP_USER_AGENT' ]:null) ); $varsOut[ 'tmCur' ] = $tmCur; $varsOut[ 'userAgent' ] = $userAgent; $ctxGrps = Gen::GetArrField( $settCache, array( 'ctxGrps' ), array() ); if( $pathIsDir ) $path .= '/'; $seraph_accel_g_contProcGetExclStatus = _ContProcGetExclStatus( $settCache, $ctxGrps, $userAgent, $_COOKIE, $path, $args, $adjustArgs ); if( $seraph_accel_g_contProcGetExclStatus ) return( $seraph_accel_g_contProcGetExclStatus ); $sessInfo = GetCacheCurUserSession( $siteId, $seraph_accel_g_cacheCtxSkip ); $userId = (isset($sessInfo[ 'userId' ])?$sessInfo[ 'userId' ]:null); $varsOut[ 'sessInfo' ] = $sessInfo; $varsOut[ 'userId' ] = $userId; if( !$seraph_accel_g_cacheCtxSkip ) { $stateCookId = GetCookiesState( $ctxGrps, $_COOKIE ); if( $stateCookId || $userId ) { $seraph_accel_g_prepContIsUserCtx = true; if( !Gen::GetArrField( $settCache, array( 'ctx' ), false ) ) $seraph_accel_g_contProcGetExclStatus = 'userCtx'; } } else { $stateCookId = ''; $viewsGrps = Gen::GetArrField( $settCache, array( 'viewsGrps' ), array() ); foreach( array_keys( $_COOKIE ) as $cookKey ) { $viewStateIdProbe = ''; if( (isset($settCache[ 'views' ])?$settCache[ 'views' ]:null) ) foreach( $viewsGrps as $viewsGrp ) if( (isset($viewsGrp[ 'enable' ])?$viewsGrp[ 'enable' ]:null) ) AccomulateCookiesState( $viewStateIdProbe, array( $cookKey => $_COOKIE[ $cookKey ] ), Gen::GetArrField( $viewsGrp, array( 'cookies' ), array() ) ); if( !strlen( $viewStateIdProbe ) ) unset( $_COOKIE[ $cookKey ] ); } } $varsOut[ 'stateCookId' ] = $stateCookId; $shouldCurUserSessionExist = ShouldCurUserSessionExist(); if( ( !(isset($sessInfo[ 'sessId' ])?$sessInfo[ 'sessId' ]:null) && ( $shouldCurUserSessionExist || $stateCookId ) ) || ( $shouldCurUserSessionExist && !$userId ) ) $seraph_accel_g_contProcGetExclStatus = Gen::GetArrField( $settCache, array( 'ctx' ), false ) ? 'noCacheSession' : 'userCtx'; return( $seraph_accel_g_contProcGetExclStatus ); } function IsStrRegExp( $s ) { return( strpos( '/~@;%`#', (isset($s[ 0 ])?$s[ 0 ]:null) ) !== false ); } function ExprConditionsSet_Parse( $expr ) { $a = explode( ' & ', $expr ); foreach( $a as &$e ) { $e = trim( $e ); if( ( $posVal = strpos( $e, ' != ' ) ) !== false ) $e = array( 'expr' => trim( substr( $e, 0, $posVal ) ), 'op' => 'ne', 'v' => trim( substr( $e, $posVal + 4 ) ) ); else if( ( $posVal = strpos( $e, ' = ' ) ) !== false ) $e = array( 'expr' => trim( substr( $e, 0, $posVal ) ), 'op' => 'e', 'v' => trim( substr( $e, $posVal + 3 ) ) ); else if( ( $posVal = strpos( $e, ' < ' ) ) !== false ) $e = array( 'expr' => trim( substr( $e, 0, $posVal ) ), 'op' => '<', 'v' => trim( substr( $e, $posVal + 3 ) ) ); else if( ( $posVal = strpos( $e, ' > ' ) ) !== false ) $e = array( 'expr' => trim( substr( $e, 0, $posVal ) ), 'op' => '>', 'v' => trim( substr( $e, $posVal + 3 ) ) ); else if( ( $posVal = strpos( $e, ' >= ' ) ) !== false ) $e = array( 'expr' => trim( substr( $e, 0, $posVal ) ), 'op' => '>=', 'v' => trim( substr( $e, $posVal + 4 ) ) ); else if( ( $posVal = strpos( $e, ' <= ' ) ) !== false ) $e = array( 'expr' => trim( substr( $e, 0, $posVal ) ), 'op' => '<=', 'v' => trim( substr( $e, $posVal + 4 ) ) ); else if( Gen::StrStartsWith( $e, '!' ) ) $e = array( 'expr' => trim( substr( $e, 1 ) ), 'op' => 'v' ); else $e = array( 'expr' => $e, 'op' => '' ); } return( $a ); } function ExprConditionsSet_ItemOp( $e, $v ) { switch( $e[ 'op' ] ) { case 'ne': return( $v !== $e[ 'v' ] ); case 'e': return( $v === $e[ 'v' ] ); case 'v': return( !strlen( $v ) ); case '<': case '>': case '>=': case '<=': return( strlen( $v ) ? @version_compare( $v, $e[ 'v' ], $e[ 'op' ] ) : false ); } return( !!strlen( $v ) ); } function ExprConditionsSet_IsItemOpFullSearch( $e ) { switch( $e[ 'op' ] ) { case 'ne': case 'e': return( true ); case '<': case '>': case '>=': case '<=': return( true ); } return( false ); } function ExprConditionsSet_IsTrivial( $ee ) { return( count( $ee ) == 1 && $ee[ 0 ][ 'op' ] === '' ); } function AccomulateCookiesState( &$state, $cookies, $elems ) { foreach( $elems as $ee ) { $statePart = ''; foreach( ExprConditionsSet_Parse( $ee ) as $e ) { $isRegExp = IsStrRegExp( $e[ 'expr' ] ); $cookieVals = array(); foreach( $cookies as $cookKey => $cookVal ) if( $isRegExp ? @preg_match( $e[ 'expr' ], $cookKey ) : Gen::StrStartsWith( $cookKey, $e[ 'expr' ] ) ) $cookieVals[] = $cookVal; if( !$cookieVals ) $cookieVals = array( '' ); $found = false; foreach( $cookieVals as $cookVal ) { if( ExprConditionsSet_ItemOp( $e, $cookVal ) ) { $statePart .= strlen( $cookVal ) ? $cookVal : '!'; $found = true; } } if( !$found ) { $statePart = ''; break; } } $state .= $statePart; } } function AccomulateHdrsState( &$state, &$aCurHdr, $elems ) { foreach( $elems as $ee ) { $statePart = ''; foreach( ExprConditionsSet_Parse( $ee ) as $e ) { if( $aCurHdr === null ) $aCurHdr = Net::GetRequestHeaders( null, false, true ); $isRegExp = IsStrRegExp( $e[ 'expr' ] ); $vals = array(); foreach( $aCurHdr as $hdr ) { if( $isRegExp ) { if( @preg_match( $e[ 'expr' ], $hdr, $m ) ) $vals[] = count( $m ) > 1 ? $m[ 1 ] : $m[ 0 ]; } else if( Gen::StrStartsWith( $hdr, $e[ 'expr' ] ) ) $vals[] = $hdr; } if( !$vals ) $vals = array( '' ); $found = false; foreach( $vals as $val ) { if( ExprConditionsSet_ItemOp( $e, $val ) ) { $statePart .= strlen( $val ) ? $val : '!'; $found = true; } } if( !$found ) { $statePart = ''; break; } } $state .= $statePart; } } function GetCookiesState( $ctxGrps, $cookies ) { $stateCookId = ''; foreach( $ctxGrps as $ctxGrp ) if( (isset($ctxGrp[ 'enable' ])?$ctxGrp[ 'enable' ]:null) ) AccomulateCookiesState( $stateCookId, $cookies, Gen::GetArrField( $ctxGrp, array( 'cookies' ), array() ) ); return( $stateCookId ); } function ContProcGetSkipStatus( $content ) { global $seraph_accel_g_contProcGetSkipStatus; global $seraph_accel_g_sRedirLocation; if( $seraph_accel_g_contProcGetSkipStatus !== null ) return( $seraph_accel_g_contProcGetSkipStatus ); if( defined( 'REST_REQUEST' ) && REST_REQUEST ) return( $seraph_accel_g_contProcGetSkipStatus = 'restapi' ); if( defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST ) return( $seraph_accel_g_contProcGetSkipStatus = 'xmlrpc' ); $errLast = error_get_last(); if( Gen::GetArrField( $errLast, array( 'type' ), 0 ) & ( E_ERROR | E_PARSE | E_CORE_ERROR | E_COMPILE_ERROR | E_USER_ERROR | E_RECOVERABLE_ERROR ) ) { $msg = $errLast[ 'message' ]; if( strpos( $msg, $errLast[ 'file' ] ) === false ) $msg .= "\n" . $errLast[ 'file' ] . ':' . $errLast[ 'line' ]; return( $seraph_accel_g_contProcGetSkipStatus = 'err:php:' . rawurlencode( $msg ) ); } $http_response_code = http_response_code(); if( $http_response_code !== 200 ) { $skipStatus = 'httpCode:' . $http_response_code; if( in_array( $http_response_code, array( 301, 302, 307, 308 ) ) && $seraph_accel_g_sRedirLocation ) $skipStatus .= ':' . rawurlencode( $seraph_accel_g_sRedirLocation ); return( $seraph_accel_g_contProcGetSkipStatus = $skipStatus ); } if( is_404() ) return( $seraph_accel_g_contProcGetSkipStatus = 'httpCode:404' ); if( is_search() ) return( $seraph_accel_g_contProcGetSkipStatus = 'search' ); if( is_feed() ) return( $seraph_accel_g_contProcGetSkipStatus = 'feed' ); if( PluginLic::CheckFeature() != Gen::S_OK ) return( $seraph_accel_g_contProcGetSkipStatus = 'outOfLicense' ); if( Gen::StrPosArr( $content, array( '', '' ) ) === false && Gen::StrPosArr( $content, array( '', '' ) ) === false ) return( $seraph_accel_g_contProcGetSkipStatus = 'noHdrOrBody' ); return( $seraph_accel_g_contProcGetSkipStatus = false ); } function MatchUserAgentExpressions( $userAgent, $aAgent, $aAgentPS = array() ) { foreach( $aAgent as $aa ) { $bPS = false; foreach( $aAgentPS as $agentPS ) { if( !@preg_match( $agentPS, $aa ) ) continue; $bPS = true; break; } if( $bPS ) continue; $matched = false; foreach( ExprConditionsSet_Parse( $aa ) as $a ) { $isRegExp = IsStrRegExp( $a[ 'expr' ] ); if( $isRegExp ) { if( @preg_match( $a[ 'expr' ], $userAgent, $userAgentFoundVal ) ) $userAgentFoundVal = count( $userAgentFoundVal ) > 1 ? $userAgentFoundVal[ 1 ] : $userAgentFoundVal[ 0 ]; else $userAgentFoundVal = ''; } else if( strpos( $userAgent, $a[ 'expr' ] ) !== false ) $userAgentFoundVal = $userAgent; else $userAgentFoundVal = ''; $matched = ExprConditionsSet_ItemOp( $a, $userAgentFoundVal ); if( !$matched ) break; } if( $matched ) return( true ); } return( false ); } function ContProcIsCompatView( $settCache, $userAgent ) { global $seraph_accel_g_contProcCompatView; if( $seraph_accel_g_contProcCompatView !== null ) return( $seraph_accel_g_contProcCompatView ); $compatView = false; $viewsCompatGrps = Gen::GetArrField( $settCache, array( 'viewsCompatGrps' ), array() ); foreach( $viewsCompatGrps as $viewsCompatGrp ) { if( !(isset($viewsCompatGrp[ 'enable' ])?$viewsCompatGrp[ 'enable' ]:null) ) continue; if( MatchUserAgentExpressions( $userAgent, Gen::GetArrField( $viewsCompatGrp, array( 'agents' ), array() ) ) ) { $compatView = (isset($viewsCompatGrp[ 'id' ])?$viewsCompatGrp[ 'id' ]:null); break; } } return( $seraph_accel_g_contProcCompatView = $compatView ); } function GetViewTypeUserAgent( $viewsDeviceGrp ) { return( 'Mozilla/99999.9 AppleWebKit/9999999.99 (KHTML, like Gecko) Chrome/999999.0.9999.99 Safari/9999999.99 seraph-accel-Agent/2.21.1 ' . ucwords( implode( ' ', Gen::GetArrField( $viewsDeviceGrp, array( 'agents' ), array() ) ) ) ); } function CorrectRequestScheme( &$serverArgs, $target = null ) { if( strtolower( (isset($serverArgs[ 'HTTPS' ])?$serverArgs[ 'HTTPS' ]:null) ) == 'on' || ( $target == 'client' && strtolower( (isset($serverArgs[ 'HTTP_X_FORWARDED_PROTO' ])?$serverArgs[ 'HTTP_X_FORWARDED_PROTO' ]:null) ) == 'https' ) ) { if( (isset($serverArgs[ 'REQUEST_SCHEME' ])?$serverArgs[ 'REQUEST_SCHEME' ]:null) == 'http' && (isset($serverArgs[ 'SERVER_PORT' ])?$serverArgs[ 'SERVER_PORT' ]:null) == 80 ) $serverArgs[ 'SERVER_PORT' ] = 443; $serverArgs[ 'REQUEST_SCHEME' ] = 'https'; } else if( !(isset($serverArgs[ 'REQUEST_SCHEME' ])?$serverArgs[ 'REQUEST_SCHEME' ]:null) ) $serverArgs[ 'REQUEST_SCHEME' ] = 'http'; } function GetRequestHost( $serverArgs ) { return( strtolower( Net::GetRequestHost( $serverArgs ) ) ); } function GetCurRequestUrl() { $serverArgsTmp = Gen::ArrCopy( $_SERVER ); CorrectRequestScheme( $serverArgsTmp, 'client' ); return( $serverArgsTmp[ 'REQUEST_SCHEME' ] . '://' . GetRequestHost( $serverArgsTmp ) . $serverArgsTmp[ 'REQUEST_URI' ] ); } function Queue_GetStgPrms( $dirQueue, $state ) { return( array( 'dirFilesPattern' => $dirQueue . '/' . $state . '/*.dat.gz', 'options' => array( 'countPerFirstChunk' => 100, 'cbSort' => function( $item1, $item2 ) { $iCmp = Gen::VarCmp( (isset($item1[ 'p' ])?$item1[ 'p' ]:null), (isset($item2[ 'p' ])?$item2[ 'p' ]:null) ); if( $iCmp !== 0 ) return( $iCmp ); $iCmp = Gen::VarCmp( (isset($item1[ 't' ])?$item1[ 't' ]:null), (isset($item2[ 't' ])?$item2[ 't' ]:null) ); if( $iCmp !== 0 ) return( $iCmp ); return( 0 ); } ) ) ); } function Queue_IsPriorFirst( $siteId, $priority ) { $dirQueue = GetCacheDir() . '/q/' . $siteId; $lock = new Lock( 'l', $dirQueue ); if( !$lock -> Acquire() ) return( false ); $res = false; foreach( array( 1, 0 ) as $state ) { $a = new ArrayOnFiles( Queue_GetStgPrms( $dirQueue, $state ) ); $b = Gen::GetArrField( current( $a -> slice( 0, 1 ) ), array( 'p' ), 0 ) == $priority; $a -> dispose(); if( $b ) { $res = true; break; } } $lock -> Release(); return( $res ); } function OnAsyncTask_QueueProcessItems( $args ) { $settGlobal = Plugin::SettGetGlobal(); $settCacheGlobal = Gen::GetArrField( $settGlobal, array( 'cache' ), array() ); $nMaxItems = (isset($settCacheGlobal[ 'maxProc' ])?$settCacheGlobal[ 'maxProc' ]:null); if( !$nMaxItems ) $nMaxItems = 1; $nMaxItemsTotal = $nMaxItems; $procTmLim = Gen::GetArrField( Plugin::SettGet(), array( 'cache', 'procTmLim' ), 570 ); $tmCur = microtime( true ); foreach( glob( GetCacheDir() . '/qt/*.dat' ) as $fileTempQueue ) { $data = @unserialize( @file_get_contents( $fileTempQueue ) ); @unlink( $fileTempQueue ); if( $data ) CachePostPreparePageEx( Gen::GetArrField( $data, array( 'u' ), '' ), Gen::GetArrField( $data, array( 's' ), '' ), Gen::GetArrField( $data, array( 'p' ), 10 ), null, Gen::GetArrField( $data, array( 'h' ), array() ), Gen::GetArrField( $data, array( 't' ), 0.0 ) ); } $aCurItemsPrior = array(); foreach( GetSiteIds() as $siteId ) { $dirQueue = GetCacheDir() . '/q/' . $siteId; $lock = new Lock( 'l', $dirQueue ); if( !$lock -> Acquire() ) continue; $aProgress = new ArrayOnFiles( Queue_GetStgPrms( $dirQueue, 1 ) ); $aDone = new ArrayOnFiles( Queue_GetStgPrms( $dirQueue, 2 ) ); foreach( $aProgress -> slice( 0 ) as $id => $item ) { $data = Gen::GetArrField( Gen::Unserialize( (isset($item[ 'd' ])?$item[ 'd' ]:null) ), array( '' ), array() ); $hrItemForce = Gen::S_OK; $tmDur = $tmCur - ( float )(isset($item[ 't' ])?$item[ 't' ]:null); $fileCtl = ProcessCtlData_GetFullPath( (isset($data[ 'pc' ])?$data[ 'pc' ]:null) ); if( $tmDur <= $procTmLim + 30 ) { if( $tmDur > ( 30 ) && $fileCtl ) { $ctlRes = ProcessCtlData_Get( $fileCtl, $isLive ); if( $ctlRes === null ) $hrItemForce = Gen::S_ABORTED; else if( Gen::GetArrField( $ctlRes, array( 'stage' ) ) && !Gen::GetArrField( $ctlRes, array( 'finish' ) ) && !$isLive ) $hrItemForce = Gen::E_INVALID_STATE; } } else $hrItemForce = Gen::E_TIMEOUT; if( $hrItemForce == Gen::S_OK ) { if( $nMaxItems > 0 ) $nMaxItems --; $aCurItemsPrior[ ( int )(isset($item[ 'p' ])?$item[ 'p' ]:null) ] = true; continue; } if( $fileCtl ) ProcessCtlData_Del( $fileCtl ); $data[ 'td' ] = $tmDur; $data[ 'hr' ] = $hrItemForce; $item[ 'd' ] = Gen::Serialize( $data ); $item[ 'p' ] = -1000; $item[ 't' ] = $tmCur; unset( $aProgress[ $id ] ); $aDone[ $id ] = $item; } { $n = $aDone -> count(); if( Gen::GetArrField( $settGlobal, array( 'debug' ), false ) ) { if( $n > 2 * 10 ) { $aDoneNew = array(); $nDone = 0; $nDoneErr = 0; for( $aDone -> end(); $aDone -> valid(); $aDone -> prev() ) { $item = $aDone -> current(); $data = Gen::GetArrField( Gen::Unserialize( (isset($item[ 'd' ])?$item[ 'd' ]:null) ), array( '' ), array() ); list( $iconClr, $state, $stateDsc, $duration ) = GetQueueItem_Done_Attrs( $data ); unset( $state, $stateDsc, $duration ); $bPut = false; if( $iconClr == 'error' ) { if( $nDoneErr < 10 ) { $bPut = true; $nDoneErr++; } } else { if( $nDone < 10 ) { $bPut = true; $nDone++; } } if( $bPut ) Gen::ArrSplice( $aDoneNew, 0, 0, array( $aDone -> key() => $item ) ); if( $nDone == 10 && $nDoneErr == 10 ) break; } $aDone -> clear(); $aDone -> setItems( $aDoneNew ); } } else { if( $n > 10 ) $aDone -> splice( 0, $n - 10 ); } } $aDone -> dispose(); $aProgress -> dispose(); $lock -> Release(); unset( $aDone, $aProgress, $lock ); } if( !$nMaxItems ) { return; } $procInterval = (isset($settCacheGlobal[ 'procInterval' ])?$settCacheGlobal[ 'procInterval' ]:null); if( $procInterval ) { if( $nMaxItems < $nMaxItemsTotal ) return; $procEndLastTime = intval( get_option( 'seraph_accel_procEndLastTime' ) ); if( $tmCur - $procEndLastTime < $procInterval ) return; } $items = array(); foreach( GetSiteIds() as $siteId ) { $dirQueue = GetCacheDir() . '/q/' . $siteId; $lock = new Lock( 'l', $dirQueue ); if( !$lock -> Acquire() ) continue; $aInitial = new ArrayOnFiles( Queue_GetStgPrms( $dirQueue, 0 ) ); foreach( $aInitial -> slice( 0, $nMaxItems ) as $id => $item ) { $item[ 's' ] = $siteId; $items[ $id ] = $item; } unset( $item ); $aInitial -> dispose(); $lock -> Release(); unset( $aInitial, $lock ); } if( !$items ) { return; } uasort( $items, Gen::GetArrField( Queue_GetStgPrms( '', 0 ), array( 'options', 'cbSort' ) ) ); $items = array_slice( $items, 0, $nMaxItems, true ); foreach( $items as $id => $item ) { $prior = ( int )(isset($item[ 'p' ])?$item[ 'p' ]:null); if( isset( $aCurItemsPrior[ -480 ] ) && $prior > -480 ) continue; $aCurItemsPrior[ $prior ] = true; Plugin::AsyncTaskPost( 'CacheProcessItem', array( 'id' => $id, 'siteId' => $item[ 's' ] ) ); } } function CacheInitQueueProcessor() { $tmCur = time(); { $time = $tmCur + ( 30 ); $time -= $time % ( 30 ); Plugin::AsyncFastTaskPost( 'QueueProcessItems', null, array( $time, 30 ), false, function( $args, $argsPrev ) { return( false ); } ); } { $time = $tmCur + ( 120 ); $time -= $time % ( 120 ); Plugin::AsyncTaskPost( 'CheckUpdatePostProcess', null, array( $time, 24 * 60 * 60 ), false, function( $args, $argsPrev ) { return( false ); } ); } } function CachePushQueueProcessor( $next = false, $immediately = false, $shortInterval = false ) { $procInterval = 0; if( $next && $immediately === false ) { $settCacheGlobal = Gen::GetArrField( Plugin::SettGetGlobal(), array( 'cache' ), array() ); $procInterval = $shortInterval ? (isset($settCacheGlobal[ 'procIntervalShort' ])?$settCacheGlobal[ 'procIntervalShort' ]:null) : (isset($settCacheGlobal[ 'procInterval' ])?$settCacheGlobal[ 'procInterval' ]:null); } $time = time() + $procInterval; if( !is_bool( $immediately ) ) { $timeLast = get_option( 'seraph_accel_queueProcessItemNext' ); if( $timeLast && ( $time - $timeLast < $immediately ) ) $procInterval = 99999; } else if( $next && ( $immediately || $shortInterval ) ) update_option( 'seraph_accel_procEndLastTime', 0, false ); update_option( 'seraph_accel_queueProcessItemNext', $time, false ); Plugin::AsyncFastTaskPost( 'QueueProcessItems', null, array( $time ), false, true ); if( !$next && !IsCronEnabled() ) return; if( $procInterval <= 5 ) { if( $procInterval ) sleep( $procInterval ); Plugin::AsyncTaskPush( 0 ); } } function ContentProcess_IsAborted( $settCache = null ) { global $seraph_accel_g_prepPrms; if( $seraph_accel_g_prepPrms === null ) return; return( !Gen::SliceExecTime( (isset($settCache[ 'procWorkInt' ])?$settCache[ 'procWorkInt' ]:null), (isset($settCache[ 'procPauseInt' ])?$settCache[ 'procPauseInt' ]:null), 2, function() { global $seraph_accel_g_prepPrms; return( ProcessCtlData_IsAborted( (isset($seraph_accel_g_prepPrms[ 'pc' ])?$seraph_accel_g_prepPrms[ 'pc' ]:null) ) ); } ) ); } function ProcessCtlData_GetFullPath( $file = '' ) { if( $file === null ) return( null ); return( GetCacheDir() . '/pc' . ( $file ? ( '/' . $file ) : '' ) ); } function ProcessCtlData_IsAborted( $fileCtl ) { if( !$fileCtl ) return; $lock = new Lock( 'pl', GetCacheDir() ); if( !$lock -> Acquire() ) return; $res = !@file_exists( $fileCtl . '.dat' ); $lock -> Release(); return( $res ); } function ProcessCtlData_Init( $fileCtlDir, $data ) { if( Gen::HrFail( Gen::MakeDir( $fileCtlDir, true ) ) ) return( null ); $fileCtl = @tempnam( $fileCtlDir, '' ); if( !$fileCtl ) return( null ); if( !@file_put_contents( $fileCtl . '.dat', @serialize( $data ) ) ) { @unlink( $fileCtl ); return( null ); } return( $fileCtl ); } function ProcessCtlData_Del( $fileCtl ) { $lock = new Lock( 'pl', GetCacheDir() ); if( !$lock -> Acquire() ) return; @unlink( $fileCtl . '.dat' ); @unlink( $fileCtl ); $lock -> Release(); } function ProcessCtlData_Get( $fileCtl, &$isLive = null ) { $lock = new Lock( 'pl', GetCacheDir() ); if( !$lock -> Acquire() ) return( Gen::E_FAIL ); if( Gen::FileContentExclusive_Open( $hFileCtl, $fileCtl ) !== Gen::E_BUSY ) { if( !$hFileCtl ) { $lock -> Release(); return( null ); } Gen::FileContentExclusive_Close( $hFileCtl ); $isLive = false; } else $isLive = true; $data = @file_get_contents( $fileCtl . '.dat' ); $data = is_string( $data ) ? @unserialize( $data ) : null; $lock -> Release(); return( $data ); } function ProcessCtlData_Update( $fileCtl, $data, $clearPrev = false, $lifeCtlOpenClose = null ) { if( !$fileCtl ) return( true ); $lock = new Lock( 'pl', GetCacheDir() ); if( !$lock -> Acquire() ) { return( false ); } global $seraph_accel_g_hFileCtl; $dataPrev = @file_get_contents( $fileCtl . '.dat' ); if( $dataPrev === false ) { $lock -> Release(); return( null ); } if( $lifeCtlOpenClose === true ) { Gen::FileContentExclusive_Open( $seraph_accel_g_hFileCtl, $fileCtl, false ); if( !$seraph_accel_g_hFileCtl ) { $lock -> Release(); return( false ); } } else if( $lifeCtlOpenClose === false ) Gen::FileContentExclusive_Close( $seraph_accel_g_hFileCtl ); if( !$dataPrev || $clearPrev ) $dataPrev = array(); else $dataPrev = @unserialize( $dataPrev ); $res = @file_put_contents( $fileCtl . '.dat', @serialize( array_merge( $dataPrev, $data ) ) ) !== false; $lock -> Release(); return( $res ); } function OnAsyncTask_CacheProcessItem( $args ) { $id = (isset($args[ 'id' ])?$args[ 'id' ]:null); $siteId = Gen::SanitizeId( (isset($args[ 'siteId' ])?$args[ 'siteId' ]:null) ); if( !$id || !$siteId ) return; $dirQueue = GetCacheDir() . '/q/' . $siteId; $item = null; { $lock = new Lock( 'l', $dirQueue ); if( !$lock -> Acquire() ) return; $aInitial = new ArrayOnFiles( Queue_GetStgPrms( $dirQueue, 0 ) ); $item = $aInitial[ $id ]; $aInitial -> dispose(); $lock -> Release(); unset( $aInitial, $lock ); } if( !$item ) return; $data = Gen::GetArrField( Gen::Unserialize( (isset($item[ 'd' ])?$item[ 'd' ]:null) ), array( '' ), array() ); if( !$data ) return; { if( !isset( $data[ 'p' ] ) ) $data[ 'p' ] = ( int )(isset($item[ 'p' ])?$item[ 'p' ]:null); } $procTmLim = Gen::GetArrField( Plugin::SettGet(), array( 'cache', 'procTmLim' ), 570 ); @set_time_limit( $procTmLim + 30 ); $fileCtlDir = ProcessCtlData_GetFullPath(); if( !( $fileCtl = ProcessCtlData_Init( $fileCtlDir, array() ) ) ) { $data[ 'td' ] = 0; $data[ 'hr' ] = Gen::E_FAIL; $data[ 'r' ] = 'init:Can\'t modify files in \'' . $fileCtlDir . '\''; $item[ 'd' ] = Gen::Serialize( $data ); $lock = new Lock( 'l', $dirQueue ); if( $lock -> Acquire() ) { $aInitial = new ArrayOnFiles( Queue_GetStgPrms( $dirQueue, 0 ) ); $aDone = new ArrayOnFiles( Queue_GetStgPrms( $dirQueue, 2 ) ); unset( $aInitial[ $id ] ); $aDone[ $id ] = $item; $aInitial -> dispose(); $aDone -> dispose(); } $lock -> Release(); unset( $aInitial, $aDone, $lock ); return; } unset( $fileCtlDir ); $data[ 'pc' ] = Gen::GetFileName( $fileCtl ); $tmBegin = microtime( true ); $tmOrig = ( float )(isset($item[ 't' ])?$item[ 't' ]:null); $priorOrig = ( int )(isset($item[ 'p' ])?$item[ 'p' ]:null); $item[ 't' ] = $tmBegin; $item[ 'd' ] = Gen::Serialize( $data ); { $lock = new Lock( 'l', $dirQueue ); if( !$lock -> Acquire() ) { return; } $aInitial = new ArrayOnFiles( Queue_GetStgPrms( $dirQueue, 0 ) ); $aProgress = new ArrayOnFiles( Queue_GetStgPrms( $dirQueue, 1 ) ); $ok = true; if( $aInitial -> unsetItem( $id ) === false ) $ok = false; if( $ok && $aProgress -> setItem( $id, $item ) === false ) $ok = false; $aInitial -> dispose(); $aProgress -> dispose(); if( !$ok ) { ProcessCtlData_Del( $fileCtl ); $lock -> Release(); return; } $lock -> Release(); unset( $aInitial, $aProgress, $lock ); } $prepArgs = array( 'nonce' => hash_hmac( 'md5', '' . $tmBegin, NONCE_SALT ), '_tm' => '' . $tmBegin, 'pc' => $data[ 'pc' ] ); if( $priorOrig == -480 ) $prepArgs[ 'lrn' ] = (isset($data[ 'l' ])?$data[ 'l' ]:null); $url = add_query_arg( array( 'seraph_accel_prep' => @rawurlencode( @base64_encode( @json_encode( $prepArgs ) ) ) ), (isset($data[ 'u' ])?$data[ 'u' ]:null) ); $hdrs = (isset($data[ 'h' ])?$data[ 'h' ]:null); if( !is_array( $hdrs ) ) $hdrs = array(); { $hdrsForRequest = $hdrs; Net::GetUrlWithoutProtoEx( $url, $proto ); if( strtolower( $proto ) == 'https' ) { Net::RemoveHeader( $hdrsForRequest, 'Upgrade-Insecure-Requests' ); Net::RemoveHeader( $hdrsForRequest, 'Ssl' ); } Net::RemoveHeader( $hdrsForRequest, 'Accept-Encoding' ); Net::RemoveHeader( $hdrsForRequest, 'Cloud-Protector-Client-Ip' ); unset( $proto ); $asyncMode = OnAsyncTasksPushGetMode(); if( $asyncMode == 're' ) $requestRes = PluginRe::MakeRequest( 'GET', $url, $hdrsForRequest, 30, false ); else $requestRes = Wp::RemoteGet( $url, array( 'local' => $asyncMode == 'loc', 'redirection' => 0, 'timeout' => 30, 'sslverify' => false, 'headers' => $hdrsForRequest ) ); $tmFinish = microtime( true ); $hr = Net::GetHrFromWpRemoteGet( $requestRes, true ); $httpCode = Net::GetResponseCodeFromHr( $hr ); } $needRepeat = false; $needLrn = false; $repeatIdx = null; $skipStatus = null; $warns = null; $ctlRes = ProcessCtlData_Get( $fileCtl, $isLive ); if( Gen::GetArrField( $ctlRes, array( 'stage' ) ) ) { for( ;; ) { $tmFinish = microtime( true ); if( $tmFinish - $tmBegin > $procTmLim ) { $hr = Gen::E_TIMEOUT; $requestRes = null; break; } if( is_int( $ctlRes ) ) { $hr = $ctlRes; $requestRes = null; break; } if( $ctlRes === null ) { $hr = Gen::S_ABORTED; $requestRes = null; break; } if( Gen::GetArrField( $ctlRes, array( 'finish' ) ) ) { $skipStatus = Gen::GetArrField( $ctlRes, array( 'skip' ) ); $hr = $skipStatus ? ( Gen::StrStartsWith( $skipStatus, 'err:' ) ? Gen::E_FAIL : Gen::S_FALSE ) : Gen::S_OK; $warns = Gen::GetArrField( $ctlRes, array( 'warns' ), array() ); break; } if( !$isLive ) { $hr = Gen::E_INVALID_STATE; $requestRes = null; break; } sleep( 1 ); $ctlRes = ProcessCtlData_Get( $fileCtl, $isLive ); } } else { if( ProcessCtlData_IsAborted( $fileCtl ) ) { $hr = Gen::S_ABORTED; $requestRes = null; } else if( $httpCode && $httpCode != 500 ) { if( $httpCode == 524 || $httpCode == 522 || $httpCode == 504 || $httpCode == 503 ) if( ( $repeatIdx = (isset($data[ 'rdr' ])?$data[ 'rdr' ]:0) ) <= 3 ) $needRepeat = true; $hr = Gen::HrSuccFromFail( $hr ); } } $immediatelyPushQueue = false; $urlRedir = trim( wp_remote_retrieve_header( $requestRes, 'location' ) ); if( !$urlRedir && $skipStatus && preg_match( '@^httpCode\\:(?:301|302|307|308)\\:@', $skipStatus ) ) $urlRedir = rawurldecode( substr( $skipStatus, 13 ) ); if( $urlRedir ) { $urlRedir = remove_query_arg( array( 'seraph_accel_prep' ), $urlRedir ); if( Gen::StrStartsWith( $urlRedir, '//' ) ) { GetUrlWithoutProtoEx( $url, $proto ); $urlRedir = $proto . ':' . $urlRedir; unset( $proto ); } else if( strpos( $urlRedir, '://' ) === false ) $urlRedir = Net::GetSiteAddrFromUrl( $url, true ) . $urlRedir; if( $priorOrig !== 10 ) if( ( $redirIdx = (isset($data[ 'rdr' ])?$data[ 'rdr' ]:0) ) <= 4 ) if( CachePostPreparePageEx( $urlRedir, $siteId, $priorOrig, (isset($data[ 'p' ])?$data[ 'p' ]:null), $hdrs, $tmOrig, $redirIdx + 1, (isset($data[ 'l' ])?$data[ 'l' ]:null) ) ) $immediatelyPushQueue = true; } $data[ 'td' ] = $tmFinish - $tmBegin; if( $hr != Gen::S_OK && !$skipStatus && $httpCode ) $skipStatus = 'httpCode:' . $httpCode; if( $skipStatus ) { if( Gen::StrStartsWith( $skipStatus, 'httpCode:' ) && $urlRedir && strlen( $skipStatus ) === 12 ) $skipStatus .= ':' . rawurlencode( $urlRedir ); $data[ 'hr' ] = ( $hr = Gen::StrStartsWith( $skipStatus, 'err:' ) ? Gen::E_FAIL : Gen::S_FALSE ); $data[ 'r' ] = $skipStatus; if( $skipStatus == 'alreadyProcessing' || $skipStatus == 'lrnNeed' ) $needRepeat = true; else if( Gen::StrStartsWith( $skipStatus, 'lrnNeed:' ) ) $needLrn = substr( $skipStatus, 8 ); } else if( $hr != Gen::S_OK ) { $data[ 'hr' ] = $hr; if( is_wp_error( $requestRes ) ) $data[ 'r' ] = rawurlencode( $requestRes -> get_error_message() ) . ':' . rawurlencode( LocId::Pack( 'RequestHeadersTrace_%1$s', null, array( strip_tags( str_replace( array( '
' ), array( "\n" ), GetHeadersResString( $hdrsForRequest ) ) ) ) ) ); if( $skipStatus ) $data[ 'r' ] = $skipStatus; } if( $needLrn ) { { $lock = new Lock( 'l', $dirQueue ); if( !$lock -> Acquire() ) { return; } $aProgress = new ArrayOnFiles( Queue_GetStgPrms( $dirQueue, 1 ) ); unset( $aProgress[ $id ] ); $aProgress -> dispose(); $lock -> Release(); unset( $aProgress, $lock ); } CachePostPreparePageEx( (isset($data[ 'u' ])?$data[ 'u' ]:null), $siteId, -480, (isset($data[ 'p' ])?$data[ 'p' ]:null), $hdrs, $tmOrig, null, $needLrn ); $immediatelyPushQueue = true; } else { if( $hr == Gen::S_OK && $warns ) $data[ 'w' ] = $warns; if( isset( $data[ 'hr' ] ) && $data[ 'hr' ] != Gen::S_OK && $urlRedir && $urlRedir == (isset($data[ 'u' ])?$data[ 'u' ]:null) ) { $data[ 'hr' ] = ( $hr = Gen::E_FAIL ); $data[ 'r' ] = 'redirectToItself'; } { $lock = new Lock( 'l', $dirQueue ); if( !$lock -> Acquire() ) { return; } $aProgress = new ArrayOnFiles( Queue_GetStgPrms( $dirQueue, 1 ) ); $aDone = new ArrayOnFiles( Queue_GetStgPrms( $dirQueue, 2 ) ); { $dataExtUpdated = $aProgress[ $id ]; if( $dataExtUpdated ) { if( $dataExtUpdated = Gen::GetArrField( Gen::Unserialize( (isset($dataExtUpdated[ 'd' ])?$dataExtUpdated[ 'd' ]:null) ), array( '' ), array() ) ) if( (isset($dataExtUpdated[ 'rpt' ])?$dataExtUpdated[ 'rpt' ]:null) ) $needRepeat = true; unset( $dataExtUpdated ); } } $item[ 't' ] = $tmFinish; $item[ 'p' ] = -1000; $item[ 'd' ] = Gen::Serialize( $data ); unset( $aProgress[ $id ] ); $aDone[ $id ] = $item; $aProgress -> dispose(); $aDone -> dispose(); $lock -> Release(); unset( $aProgress, $aDone, $lock ); } } ProcessCtlData_Del( $fileCtl ); update_option( 'seraph_accel_procEndLastTime', ( int )$tmFinish, false ); if( $needRepeat && CachePostPreparePageEx( (isset($data[ 'u' ])?$data[ 'u' ]:null), $siteId, $priorOrig, (isset($data[ 'p' ])?$data[ 'p' ]:null), $hdrs, $tmOrig, $repeatIdx !== null ? ( $repeatIdx + 1 ) : null, (isset($data[ 'l' ])?$data[ 'l' ]:null) ) ) $immediatelyPushQueue = true; CachePushQueueProcessor( true, $immediatelyPushQueue, $hr != Gen::S_OK && Gen::HrSucc( $hr ) ); } function GetHeadersResString( $hdrs ) { $res = ''; foreach( $hdrs as $hdrId => $hdrVals ) { if( !is_array( $hdrVals ) ) $hdrVals = array( $hdrVals ); foreach( $hdrVals as $hdrVal ) { if( $res ) $res .= '
'; $res .= Ui::Tag( 'em', htmlspecialchars( $hdrId ) ) . ': ' . htmlspecialchars( $hdrVal ); } } return( $res ); } function CacheInitQueueTable( $force = false ) { $data = Plugin::DataGet(); $dbVer = Gen::GetArrField( $data, 'queueDbVer', 0 ); if( !$force && $dbVer == QUEUE_DB_VER ) return; Gen::SetArrField( $data, 'queueDbVer', QUEUE_DB_VER ); Plugin::DataSet( $data ); if( $dbVer && $dbVer < 4 ) { $nRowsChunk = 100; $dbtran = new Lock( 'ql', GetCacheDir() ); if( $dbtran -> Acquire() ) { $run = true; $tmStart = time(); foreach( array( 2, 1, 0 ) as $state ) { for( $i = 0; ; $i++ ) { $items = DbTbl::GetRows( Db::GetTblPrefix( 'seraph_accel_queue' ), null, array( $i * $nRowsChunk, $nRowsChunk ), array( 'state' => $state ) ); if( !$items ) break; foreach( $items as $itemFromDb ) { $id = @hex2bin( (isset($itemFromDb[ 'id' ])?$itemFromDb[ 'id' ]:null) ); $siteId = (isset($itemFromDb[ 'site_id' ])?$itemFromDb[ 'site_id' ]:null); if( !$siteId ) $siteId = 'm'; $item = array( 'p' => ( int )(isset($itemFromDb[ 'prior' ])?$itemFromDb[ 'prior' ]:null), 't' => ( float )(isset($itemFromDb[ 'tm' ])?$itemFromDb[ 'tm' ]:null), 'd' => (isset($itemFromDb[ 'data' ])?$itemFromDb[ 'data' ]:null) ); { $dirQueue = GetCacheDir() . '/q/' . $siteId; $lock = new Lock( 'l', $dirQueue ); if( $lock -> Acquire() ) { $a = new ArrayOnFiles( Queue_GetStgPrms( $dirQueue, $state ) ); $a[ $id ] = $item; $a -> dispose(); unset( $a ); $lock -> Release(); } unset( $lock ); } if( time() - $tmStart > 10 ) { $run = false; break; } } if( !$run ) break; } if( !$run ) break; } DbTbl::DeleteRows( Db::GetTblPrefix( 'seraph_accel_queue' ) ); $dbtran -> Release(); } } } function GetViewDeviceGrpNameFromData( $viewsDeviceGrp ) { $viewName = (isset($viewsDeviceGrp[ 'name' ])?$viewsDeviceGrp[ 'name' ]:null); if( !$viewName ) $viewName = 'id:' . (isset($viewsDeviceGrp[ 'id' ])?$viewsDeviceGrp[ 'id' ]:null); return( $viewName ); } function _CachePostPreparePageEx_StopAndRepeat( $aProgress, $id, $data = null ) { $item = $aProgress[ $id ]; if( !$item ) return; $itemInProgressData = Gen::GetArrField( Gen::Unserialize( (isset($item[ 'd' ])?$item[ 'd' ]:null) ), array( '' ), array() ); if( (isset($itemInProgressData[ 'rpt' ])?$itemInProgressData[ 'rpt' ]:null) || !( $fileCtl = ProcessCtlData_GetFullPath( (isset($itemInProgressData[ 'pc' ])?$itemInProgressData[ 'pc' ]:null) ) ) ) return; ProcessCtlData_Del( $fileCtl ); if( $data ) $itemInProgressData = array_merge( $data, $itemInProgressData ); $itemInProgressData[ 'rpt' ] = true; $item[ 'd' ] = Gen::Serialize( $itemInProgressData ); $aProgress[ $id ] = $item; } function CachePostPreparePageEx( $url, $siteId, $priority, $priorityInitiator, $headers = null, $time = null, $redirIdx = null, $lrnId = null ) { if( !$url ) return( false ); if( $priority == -480 && !$lrnId ) return( false ); if( $priorityInitiator === null ) $priorityInitiator = $priority; $settCache = Gen::GetArrField( Plugin::SettGet(), array( 'cache' ), array() ); if( $time === null ) $time = microtime( true ); if( !is_array( $headers ) ) $headers = array(); $id = $url . $priority; $idLearn = $url . -480; foreach( $headers as $header => $headerVal ) { $headerVal = $header . ( is_array( $headerVal ) ? implode( '', $headerVal ) : $headerVal ); $id .= $headerVal; $idLearn .= $headerVal; } $id = md5( $id, true ); $idLearn = md5( $idLearn, true ); $viewName = null; if( $viewsDeviceGrp = GetCacheViewDeviceGrp( $settCache, strtolower( (isset($headers[ 'User-Agent' ])?$headers[ 'User-Agent' ]:null) ) ) ) $viewName = GetViewDeviceGrpNameFromData( $viewsDeviceGrp ); $dirQueue = GetCacheDir() . '/q/' . $siteId; if( $priority == 10 ) { $count = 0; { $lock = new Lock( 'l', $dirQueue ); if( $lock -> Acquire() ) { $aInitial = new ArrayOnFiles( Queue_GetStgPrms( $dirQueue, 0 ) ); $count = $aInitial -> count(); $aInitial -> dispose(); $lock -> Release(); } unset( $aInitial, $lock ); } if( $count > 1000 ) { return( null ); } } $data = array( 'p' => $priorityInitiator, 'u' => $url, 'h' => $headers, 'v' => $viewName ); if( $redirIdx ) $data[ 'rdr' ] = $redirIdx; if( $lrnId ) $data[ 'l' ] = $lrnId; { $lock = new Lock( 'l', $dirQueue ); if( !$lock -> Acquire() ) { return( false ); } $aInitial = new ArrayOnFiles( Queue_GetStgPrms( $dirQueue, 0 ) ); $aProgress = new ArrayOnFiles( Queue_GetStgPrms( $dirQueue, 1 ) ); $aDone = new ArrayOnFiles( Queue_GetStgPrms( $dirQueue, 2 ) ); unset( $aDone[ $id ] ); $res = false; if( !isset( $aProgress[ $id ] ) ) { $aInitial[ $id ] = array( 'p' => $priority, 't' => $time, 'd' => Gen::Serialize( $data ) ); $res = true; } if( $priority !== 10 ) { _CachePostPreparePageEx_StopAndRepeat( $aProgress, $id, $data ); if( $id != $idLearn ) _CachePostPreparePageEx_StopAndRepeat( $aProgress, $idLearn ); } $aInitial -> dispose(); $aProgress -> dispose(); $aDone -> dispose(); $lock -> Release(); unset( $aInitial, $aProgress, $aDone, $lock ); } return( $res ); } function CacheQueueDelete( $siteId ) { $res = true; foreach( ( $siteId ? array( $siteId ) : GetSiteIds() ) as $siteIdEnum ) { $dirQueue = GetCacheDir() . '/q/' . $siteIdEnum; $lock = new Lock( 'l', $dirQueue ); if( !$lock -> Acquire() ) { $res = false; continue; } $aInitial = new ArrayOnFiles( Queue_GetStgPrms( $dirQueue, 0 ) ); $aDone = new ArrayOnFiles( Queue_GetStgPrms( $dirQueue, 2 ) ); $aInitial -> clear(); $aDone -> clear(); $aInitial -> dispose(); $aDone -> dispose(); $lock -> Release(); unset( $aInitial, $aDone, $lock ); } return( $res ); } function GetExtContents( $url, &$contMimeType = null, $userAgentCmn = true, $timeout = 30, $rememberServerState = true ) { $args = array( 'sslverify' => false, 'timeout' => $timeout ); if( $userAgentCmn ) $args[ 'user-agent' ] = 'Mozilla/99999.9 AppleWebKit/9999999.99 (KHTML, like Gecko) Chrome/999999.0.9999.99 Safari/9999999.99 seraph-accel-Agent/2.21.1'; global $seraph_accel_g_aGetExtContentsFailedSrvs; if( $serverId = Net::UrlParse( $url ) ) $serverId = Net::UrlDeParse( $serverId, 0, array( PHP_URL_USER, PHP_URL_PASS, PHP_URL_PATH, PHP_URL_QUERY, PHP_URL_FRAGMENT ) ); if( $rememberServerState && $serverId && Gen::HrFail( (isset($seraph_accel_g_aGetExtContentsFailedSrvs[ $serverId ])?$seraph_accel_g_aGetExtContentsFailedSrvs[ $serverId ]:null) ) ) return( false ); $res = Wp::RemoteGet( $url, $args ); $hr = Net::GetHrFromWpRemoteGet( $res ); if( Gen::HrFail( $hr ) ) { if( $rememberServerState && ( $hr == Gen::E_TIMEOUT || $hr == Net::E_TIMEOUT ) && $serverId ) $seraph_accel_g_aGetExtContentsFailedSrvs[ $serverId ] = $hr; return( false ); } $contMimeType = ( string )wp_remote_retrieve_header( $res, 'content-type' ); if( ( $nPos = strpos( $contMimeType, ';' ) ) !== false ) $contMimeType = substr( $contMimeType, 0, $nPos ); $contMimeType = trim( $contMimeType ); return( wp_remote_retrieve_body( $res ) ); } function CacheExtractPreparePageParams( &$args ) { $prms = (isset($args[ 'seraph_accel_prep' ])?$args[ 'seraph_accel_prep' ]:null); if( !$prms ) return( null ); Net::CurRequestRemoveArgs( $args, array( 'seraph_accel_prep' ) ); $prms = @json_decode( @base64_decode( Gen::SanitizeTextData( $prms ) ), true ); if( hash_hmac( 'md5', '' . (isset($prms[ '_tm' ])?$prms[ '_tm' ]:null), NONCE_SALT ) != (isset($prms[ 'nonce' ])?$prms[ 'nonce' ]:null) ) return( false ); unset( $prms[ '_tm' ] ); unset( $prms[ 'nonce' ] ); if( isset( $prms[ 'pc' ] ) ) $prms[ 'pc' ] = ProcessCtlData_GetFullPath( $prms[ 'pc' ] ); if( isset( $_SERVER[ 'HTTP_X_SERAPH_ACCEL_GEO_REMOTE_ADDR' ] ) ) $_SERVER[ 'REMOTE_ADDR' ] = $_SERVER[ 'HTTP_X_SERAPH_ACCEL_GEO_REMOTE_ADDR' ]; return( $prms ); } function GetCacheViewDeviceGrp( $settCache, $userAgent ) { if( !(isset($settCache[ 'views' ])?$settCache[ 'views' ]:null) ) return( null ); $viewsDeviceGrps = Gen::GetArrField( $settCache, array( 'viewsDeviceGrps' ), array() ); foreach( $viewsDeviceGrps as $viewsDeviceGrp ) { if( !(isset($viewsDeviceGrp[ 'enable' ])?$viewsDeviceGrp[ 'enable' ]:null) ) continue; $a = implode( ' ', Gen::GetArrField( $viewsDeviceGrp, array( 'agents' ), array() ) ); if( $a && strpos( $userAgent, $a ) !== false ) return( $viewsDeviceGrp ); } foreach( $viewsDeviceGrps as $viewsDeviceGrp ) { if( !(isset($viewsDeviceGrp[ 'enable' ])?$viewsDeviceGrp[ 'enable' ]:null) ) continue; if( MatchUserAgentExpressions( $userAgent, Gen::GetArrField( $viewsDeviceGrp, array( 'agents' ), array() ) ) ) return( $viewsDeviceGrp ); } return( null ); } function GetCurHdrsToStoreInCache( $settCache ) { $res = array(); $hdrPatterns = (isset($settCache[ 'hdrs' ])?$settCache[ 'hdrs' ]:null); if( !$hdrPatterns ) return( $res ); foreach( headers_list() as $hdr ) { foreach( $hdrPatterns as $hdrPattern ) { if( @preg_match( $hdrPattern, $hdr ) ) { $res[] = $hdr; break; } } } return( $res ); } function LastWarnDscs_Add( $txt ) { global $seraph_accel_g_aLastWarnDsc; $seraph_accel_g_aLastWarnDsc[] = $txt; } function LastWarnDscs_Get() { global $seraph_accel_g_aLastWarnDsc; return( $seraph_accel_g_aLastWarnDsc !== null ? $seraph_accel_g_aLastWarnDsc : array() ); } function _SetExpirableOption( $option, $value, $timeout ) { update_option( $option, $value, false ); update_option( $option . '_tmMax', time() + $timeout, false ); } function _DelExpirableOption( $option ) { delete_option( $option ); delete_option( $option . '_tmMax' ); } function _DelExpiredOption( $option ) { $tmMax = get_option( $option . '_tmMax' ); if( $tmMax && $tmMax < time() ) _DelExpirableOption( $option ); } function GetCountryCodeByIp( $settCache, &$ip_address ) { $country_code = '^'; if( !class_exists( 'MaxMind\\Db\\Reader' ) ) return( $country_code ); try { $reader = new \MaxMind\Db\Reader( Gen::GetArrField( $settCache, array( 'viewsGeo', 'fileMmDb' ), '' ) ); $data = $reader -> get( $ip_address ); if( isset( $data[ 'country' ][ 'iso_code' ] ) ) $country_code = strtoupper( $data[ 'country' ][ 'iso_code' ] ); $reader -> close(); } catch( \Exception $e ) { } return( $country_code ); } function GetViewGeoIdByIp( $settCache, &$ip ) { $countryCode = GetCountryCodeByIp( $settCache, $ip ); $viewGeoId = null; $grpIsFirst = true; $countryCodeForce = null; foreach( Gen::GetArrField( $settCache, array( 'viewsGeo', 'grps' ), array() ) as $grpId => $grp ) { if( !(isset($grp[ 'enable' ])?$grp[ 'enable' ]:null) ) continue; $matched = false; $countryCodeFirstTmp = null; foreach( Gen::GetArrField( $grp, array( 'items' ), array() ) as $grpItem ) { $aa = ExprConditionsSet_Parse( $grpItem ); if( $countryCodeFirstTmp === null && ExprConditionsSet_IsTrivial( $aa ) ) $countryCodeFirstTmp = $grpItem; foreach( $aa as $a ) { $v = null; if( IsStrRegExp( $a[ 'expr' ] ) ) { if( @preg_match( $a[ 'expr' ], $countryCode ) ) $v = $countryCode; } else if( $countryCode === $a[ 'expr' ] ) $v = $countryCode; $matched = ExprConditionsSet_ItemOp( $a, $v ); if( !$matched ) break; } if( $matched ) break; } if( $matched ) { $viewGeoId = $grpIsFirst ? '' : $grpId; $countryCodeForce = $countryCodeFirstTmp; break; } $grpIsFirst = false; } if( $viewGeoId === null ) $viewGeoId = $countryCode; if( $countryCodeForce ) { static $g_aRegIpDef = array( 'IN' => '165.22.217.1', 'BG' => '195.123.228.1', 'US' => '161.35.130.1', ); if( isset( $g_aRegIpDef[ $countryCodeForce ] ) ) $ip = $g_aRegIpDef[ $countryCodeForce ]; } return( $viewGeoId ); } function DepsExpand( $a, $bExpand = true ) { $aRes = array(); foreach( $a as $type => $aId ) $aRes[ $type ] = $bExpand ? array_fill_keys( $aId, array() ) : array_keys( $aId ); return( $aRes ); } function DepsDiff( $a, $aNew ) { $aRes = array_diff_key( $aNew, $a ); foreach( $a as $type => $aoiCi ) $aRes[ $type ] = array_diff_key( Gen::GetArrField( $aNew, array( $type ), array() ), $aoiCi ); return( $aRes ); } function DepsAdd( &$a, $type, $oiCi ) { $a[ $type ][ $oiCi ] = array(); } function DepsRemove( &$a, $aRem ) { foreach( $aRem as $type => $aoiCi ) { foreach( $aoiCi as $oiCi => $v ) unset( $a[ $type ][ $oiCi ] ); if( isset( $a[ $type ] ) && !count( $a[ $type ] ) ) unset( $a[ $type ] ); } } function LogGetRelativeFile() { static $g_fileRel; if( $g_fileRel === null ) $g_fileRel = '/logs/log.' . Gen::GetNonce( 'logFileSfx', NONCE_SALT ) . '.txt'; return( $g_fileRel ); } function LogWrite( $text, $severity = Ui::MsgInfo, $category = 'DEBUG' ) { Gen::LogWrite( GetCacheDir() . LogGetRelativeFile(), $text, $severity, $category ); }