ÿØÿà JFIF    ÿÛ „ ( %!1!%*+...983,7(-.- ea4/ea_php_cli.pm000064400000025667152342432450007662 0ustar00#!/usr/local/cpanel/3rdparty/bin/perl # Copyright 2025 WebPros International, LLC # All rights reserved. # copyright@cpanel.net http://cpanel.net # This code is subject to the cPanel license. Unauthorized copying is prohibited. package ea_php_cli; use strict; use warnings; my $PATH_MAX = 4096; my $SYSCALL_GETCWD = 79; # 64bit only our $EUID; $EUID = $> if ${^GLOBAL_PHASE} eq "START"; my %types = ( php => 'CLI', pear => 'CLI', 'php-cgi' => 'CGI', lsphp => 'LSAPI', ); sub run { my ( $type, $pkg, $dir, @args ) = proc_args(@_); $pkg ||= get_pkg_for_dir( $type, $dir ); die "Could not determine package for “$dir”\n" if !$pkg; return exec_via_pkg( $type, $pkg, @args ); } sub proc_args { my ( $type, @raw_args ) = @_; $type //= "undefined"; die "Invalid type ($type)\n" if !exists $types{$type}; my ( $dir, @args ); my $idx = -1; my $skipidx = -1; my $arg; # buffer for $arg (@raw_args) { $idx++; next if $idx == $skipidx; if ( substr( $arg, 0, 19 ) eq "--ea-reference-dir=" ) { # --ea-reference-dir=DIR ( undef, $dir ) = split( /=/, $arg, 2 ); # if set from -f $arg: blow it away } elsif ( _file_exists($arg) ) { # ZC-11178: use a wrapper in place of -f for testing purposes push @args, $arg; if ( !defined $dir ) { # set if not already set from --ea-reference-dir $dir = $arg; if ( index( $dir, "/" ) == -1 ) { $dir = "."; # foo.php } else { $dir =~ s{/[^/]+$}{}; $dir = "/" if $dir eq ""; # /foo.php } } } else { push @args, $arg; } } $dir //= "."; # since the lookup is based on abs path: if ( $dir eq "." ) { $dir = _getcwd(); } elsif ( substr( $dir, 0, 1 ) ne "/" || index( $dir, ".." ) != -1 ) { require Cwd; $dir = Cwd::abs_path($dir); } die "Could not determine path to lookup PHP setting for based on arguments\n" if !$dir; # this would be pretty odd return ( $type, undef, $dir, @args ); # This function no longer returns package data as of EA-7961. } sub _file_exists { return -f $_[0] } sub get_pkg_for_dir { my ( $type, $dir ) = @_; $type //= "undefined"; die "Invalid type ($type)\n" if !exists $types{$type}; my $dir_stat = [ stat($dir) ]; die "“$dir” is not a directory\n" if !-d _; return _get_default_pkg() if $dir_stat->[4] == 0; my $pkg; if ( !$ENV{NO_EA_PHP_CLI_CACHE} ) { $pkg = _get_from_cache( $dir, $dir_stat ); return $pkg if $pkg; } else { _unlink_cache_file( $dir, $dir_stat ); } $pkg = _get_pkg_for_path($dir); _cache_it_if_you_can( $dir, $dir_stat, $pkg ) unless $ENV{NO_EA_PHP_CLI_CACHE}; return $pkg || _get_default_pkg(); # get_php_config_for_users() factors in default, so $pkg should always be set but just in case … } sub exec_via_pkg { my ( $type, $pkg, @args ) = @_; $type //= "undefined"; die "Invalid type ($type)\n" if !exists $types{$type}; _pkg_name_check($pkg); my $prefix = _get_scl_prefix($pkg); my $binary = "$prefix/root/usr/bin/$type"; if ( !-x $binary ) { warn "There is no “$types{$type}” binary for “$pkg”, using default …\n"; $pkg = _get_default_pkg(); $prefix = _get_scl_prefix($pkg); $binary = "$prefix/root/usr/bin/$type"; die "Could not determine binary for “$pkg”\n" if !-x $binary; } exec( $binary, @args ); die "Could not execute “$binary”: $!\n"; return; } ################################# #### get_pkg_for_dir() helpers ## ################################# sub _get_pkg_for_path { my ($dir) = @_; my $pkg; if ( $ENV{'PWD'} && $dir eq $ENV{'PWD'} ) { if ( substr( $dir, 0, 1 ) eq '/' ) { $pkg = _lookup_pkg_for_path($dir); # false if the directory they they think they are in is not configured so we can fall back to abspath } else { # this should not be possible naturally i.e. what does PWD of 'i/am/here' mean, what is it relative to? why would it be set to ../bar/../../foo/bar? warn "Relative \$PWD detected! Since that can be ambiguous we are ignoring \$PWD value and using absolute path for lookup instead\n"; # Patches welcome for this rabbit hole ;p file under YAGNI for now } # no package yet? check the directory they are actually in # and call abs_path to resolve any symlinks if ( !$pkg ) { require Cwd; $pkg = _lookup_pkg_for_path( Cwd::abs_path( _getcwd() ) ); } } else { $pkg = _lookup_pkg_for_path($dir); # false if the directory they they think they want is not configured so we can fall back to abspath if ( !$pkg ) { require Cwd; my $abs = Cwd::abs_path($dir); if ( defined $abs && $abs ne $dir ) { $pkg = _lookup_pkg_for_path($abs); } } } $pkg = _get_default_pkg() if !$pkg; return $pkg; } sub _get_from_cache { my ( $dir, $dir_stat ) = @_; my ( $user, $home ) = ( getpwuid( $dir_stat->[4] ) )[ 0, 7 ]; my $cachedir = _dir_to_cache_dir( $home, $dir ); my $pkg; if ( my $dir_cache_mtime = ( lstat("$cachedir/.ea-php-cli.cache") )[9] ) { my $userdata_cache_mtime = ( stat("/var/cpanel/userdata/$user/cache") )[9]; if ( !$Cpanel::PHPFPM::Constants::php_conf_path ) { require Cpanel::PHPFPM::Constants } my $phpconf_mtime = ( stat($Cpanel::PHPFPM::Constants::php_conf_path) )[9]; if ( $userdata_cache_mtime && $userdata_cache_mtime < $dir_cache_mtime && $phpconf_mtime < $dir_cache_mtime ) { $pkg = readlink("$cachedir/.ea-php-cli.cache"); eval { _pkg_name_check($pkg); _get_scl_prefix($pkg) }; warn "$@\n" if $@; return $pkg if $pkg; } } return; } sub _unlink_cache_file { my ( $dir, $dir_stat ) = @_; my $home = ( getpwuid( $dir_stat->[4] ) )[7]; my $cachedir = _dir_to_cache_dir( $home, $dir ); unlink("$cachedir/.ea-php-cli.cache"); return; } sub _lookup_pkg_for_path { my ($dir) = @_; my $pkg; my %dir_cache; my %uid_cache; my ( $dom, $uid ); # buffers my %getpwuid_cache; require Cpanel::PHP::Config; $dir =~ s{/+$}{}; # remove trailing /’s to since lookup is based on not having a trailing slash $dir =~ tr{/}{}s; # squash repetitive sequences of slashes, i.e. //// -> / while ($dir) { # walk the path looking for the first configured PHP (if any) $uid = _get_uid($dir); # EUID may not own $dir last if !$uid; # root can't own a domain, thus can't set a PHP version if ( !exists $dir_cache{$dir} ) { $getpwuid_cache{$uid} //= [ getpwuid($uid) ]; eval { $uid_cache{$uid} //= Cpanel::PHP::Config::get_php_config_for_users( [ $getpwuid_cache{$uid}->[0] ] ) }; last if $@; # non-cpanel users can't own a domain, thus can't set a PHP version for $dom ( keys %{ $uid_cache{$uid} } ) { $dir_cache{ $uid_cache{$uid}->{$dom}{documentroot} } = $uid_cache{$uid}->{$dom}{phpversion}; } } if ( $dir_cache{$dir} ) { $pkg = $dir_cache{$dir}; last; } elsif ( defined $getpwuid_cache{$uid} && defined $getpwuid_cache{$uid}->[7] && $dir eq $getpwuid_cache{$uid}->[7] ) { # because we can cache this one still last; } $dir =~ s{/[^/]+$}{}; } return $pkg; } sub _cache_it_if_you_can { my ( $dir, $dir_stat, $pkg ) = @_; # attempt to cache for non-root if ( $EUID && $EUID == $dir_stat->[4] && $pkg ) { # get_php_config_for_users() factors in default, so $pkg should always be set but just in case … local $!; unlink "$dir/.ea-php-cli.cache"; # clean up old cache location if necessary my ( $user, $home ) = ( getpwuid( $dir_stat->[4] ) )[ 0, 7 ]; my $cachedir = _dir_to_cache_dir( $home, $dir ); require File::Path::Tiny; File::Path::Tiny::mk($cachedir) or warn "Could not ensure ea-php-cli cache directory!\n"; unlink "$cachedir/.ea-php-cli.cache"; symlink( $pkg, "$cachedir/.ea-php-cli.cache" ); } } sub _dir_to_cache_dir { my ( $home, $dir ) = @_; $dir =~ s{^\Q$home\E}{$home/.cpanel/ea-php-cli}; return $dir; } ############### #### helpers ## ############### sub _pkg_name_check { my ($pkg) = @_; if ( index( $pkg, "/" ) != -1 || index( $pkg, "\0" ) != -1 || index( $pkg, ".." ) != -1 ) { $pkg =~ s/\0/{NULL-BYTE}/g; die "Package, $pkg, has invalid characters\n"; } return 1; } sub _get_default_pkg { require Cpanel::PHP::Config; my $default_pkg = Cpanel::PHP::Config::get_php_version_info()->{default}; # this calls a cached lookup woot woot die "Default PHP is not configured!\n" if !$default_pkg; return $default_pkg; } my %_get_scl_prefix; sub _get_scl_prefix { my ($pkg) = @_; return $_get_scl_prefix{$pkg} if $_get_scl_prefix{$pkg}; require Cpanel::SysPkgs::SCL; my $prefix = Cpanel::SysPkgs::SCL::get_scl_prefix($pkg); die "“$pkg” is not an EA4 SCL PHP\n" if !$prefix || !-d $prefix; $_get_scl_prefix{$pkg} = $prefix; return $_get_scl_prefix{$pkg}; } sub _get_uid { my ($dir) = @_; return $EUID || ( stat($dir) )[4]; } sub _getcwd { length( pack( 'l!', 1000 ) ) * 8 == 64 or die "This system only support 64-bit Linux"; my $cwd = "\0" x 4096; my $syscall_result = syscall( $SYSCALL_GETCWD, $cwd, $PATH_MAX ); if ( $syscall_result && $syscall_result != -1 ) { $cwd =~ tr{\0}{}d; } else { require Cwd; $cwd = Cwd::getcwd(); } if ( $ENV{'PWD'} && $cwd ne $ENV{'PWD'} && index( $ENV{'PWD'}, '../' ) == -1 ) { require Cwd; my $abs_path = Cwd::abs_path( $ENV{'PWD'} ); if ( $abs_path eq $cwd && ( stat($abs_path) )[4] == ( stat($cwd) )[4] ) { # If the absolute path of $ENV{'PWD'} points the the directory we are # currently in and it has the same owner than we except $ENV{'PWD'} # as truthy return $ENV{'PWD'}; } } return $cwd; } 1; __END__ =head1 This is not intended to be consumed outside of the package that installed it. The functions are meant to consolidate logic and facilitate testing. For usage see L. userdata/saje4058/webelevationfr.saje4058.odns.fr_SSL.cache000064400000001000152342432460017147 0ustar00{"hascgi":"1","servername":"webelevationfr.saje4058.odns.fr","owner":"root","phpopenbasedirprotect":null,"usecanonicalname":"Off","ip":"109.234.165.185","serveradmin":"webmaster@webelevationfr.saje4058.odns.fr","group":"saje4058","documentroot":"/home/saje4058/webelevation.fr","secruleengineoff":null,"port":"4430","ipv6":null,"user":"saje4058","serveralias":"mail.webelevation.fr webelevation.fr www.webelevation.fr www.webelevationfr.saje4058.odns.fr","userdirprotect":"","ssl":"1","homedir":"/home/saje4058"}userdata/saje4058/paysagevertfr.saje4058.odns.fr_SSL000064400000000713152342432460015765 0ustar00--- documentroot: /home/saje4058/paysagevert.fr group: saje4058 hascgi: 1 homedir: /home/saje4058 ip: 109.234.165.185 ipv6: ~ owner: root phpopenbasedirprotect: ~ port: 4430 secruleengineoff: ~ serveradmin: webmaster@paysagevertfr.saje4058.odns.fr serveralias: mail.paysagevert.fr paysagevert.fr www.paysagevert.fr www.paysagevertfr.saje4058.odns.fr servername: paysagevertfr.saje4058.odns.fr ssl: 1 usecanonicalname: 'Off' user: saje4058 userdirprotect: '' userdata/saje4058/paysagevertfr.saje4058.odns.fr.cache000064400000000736152342432460016313 0ustar00{"user":"saje4058","serveralias":"mail.paysagevert.fr paysagevert.fr www.paysagevert.fr www.paysagevertfr.saje4058.odns.fr","userdirprotect":"","homedir":"/home/saje4058","ipv6":null,"phpopenbasedirprotect":"1","usecanonicalname":"Off","ip":"109.234.165.185","group":"saje4058","documentroot":"/home/saje4058/paysagevert.fr","serveradmin":"webmaster@paysagevertfr.saje4058.odns.fr","hascgi":"1","no_cache_update":"0","servername":"paysagevertfr.saje4058.odns.fr","owner":"root"}userdata/saje4058/saje4058.odns.fr000064400000001152152342432460012361 0ustar00--- customlog: - format: combined target: /etc/apache2/logs/domlogs/saje4058.odns.fr - format: "\"%{%s}t %I .\\n%{%s}t %O .\"" target: /etc/apache2/logs/domlogs/saje4058.odns.fr-bytes_log documentroot: /home/saje4058/public_html group: saje4058 hascgi: 1 homedir: /home/saje4058 ip: 109.234.165.185 owner: root phpopenbasedirprotect: 1 port: 8081 scriptalias: - path: /home/saje4058/public_html/cgi-bin url: /cgi-bin/ serveradmin: webmaster@saje4058.odns.fr serveralias: mail.saje4058.odns.fr www.saje4058.odns.fr servername: saje4058.odns.fr usecanonicalname: 'Off' user: saje4058 userdata/saje4058/main.cache000064400000000401152342432460011530 0ustar00{"main_domain":"saje4058.odns.fr","sub_domains":["webelevationfr.saje4058.odns.fr","paysagevertfr.saje4058.odns.fr"],"parked_domains":[],"addon_domains":{"webelevation.fr":"webelevationfr.saje4058.odns.fr","paysagevert.fr":"paysagevertfr.saje4058.odns.fr"}}userdata/saje4058/saje4058.odns.fr_SSL.cache000064400000000654152342432460014152 0ustar00{"homedir":"/home/saje4058","ssl":"1","userdirprotect":"","serveralias":"mail.saje4058.odns.fr www.saje4058.odns.fr","user":"saje4058","ipv6":null,"port":"4430","secruleengineoff":null,"serveradmin":"webmaster@saje4058.odns.fr","group":"saje4058","documentroot":"/home/saje4058/public_html","ip":"109.234.165.185","usecanonicalname":"Off","phpopenbasedirprotect":null,"owner":"root","servername":"saje4058.odns.fr","hascgi":"1"}userdata/saje4058/cache000064400000001345152342432460010615 0ustar00paysagevert.fr: saje4058==root==addon==paysagevertfr.saje4058.odns.fr==/home/saje4058/paysagevert.fr==109.234.165.185:80==109.234.165.185:4430====0== paysagevertfr.saje4058.odns.fr: saje4058==root==sub==saje4058.odns.fr==/home/saje4058/paysagevert.fr==109.234.165.185:80==109.234.165.185:4430====0== saje4058.odns.fr: saje4058==root==main==saje4058.odns.fr==/home/saje4058/public_html==109.234.165.185:8081==109.234.165.185:4430====0== webelevation.fr: saje4058==root==addon==webelevationfr.saje4058.odns.fr==/home/saje4058/webelevation.fr==109.234.165.185:80==109.234.165.185:4430====0== webelevationfr.saje4058.odns.fr: saje4058==root==sub==saje4058.odns.fr==/home/saje4058/webelevation.fr==109.234.165.185:80==109.234.165.185:4430====0== userdata/saje4058/webelevationfr.saje4058.odns.fr_SSL000064400000000721152342432460016116 0ustar00--- documentroot: /home/saje4058/webelevation.fr group: saje4058 hascgi: 1 homedir: /home/saje4058 ip: 109.234.165.185 ipv6: ~ owner: root phpopenbasedirprotect: ~ port: 4430 secruleengineoff: ~ serveradmin: webmaster@webelevationfr.saje4058.odns.fr serveralias: mail.webelevation.fr webelevation.fr www.webelevation.fr www.webelevationfr.saje4058.odns.fr servername: webelevationfr.saje4058.odns.fr ssl: 1 usecanonicalname: 'Off' user: saje4058 userdirprotect: '' userdata/saje4058/webelevationfr.saje4058.odns.fr.cache000064400000000745152342432460016445 0ustar00{"owner":"root","servername":"webelevationfr.saje4058.odns.fr","no_cache_update":"0","hascgi":"1","group":"saje4058","serveradmin":"webmaster@webelevationfr.saje4058.odns.fr","documentroot":"/home/saje4058/webelevation.fr","phpopenbasedirprotect":"1","ip":"109.234.165.185","usecanonicalname":"Off","ipv6":null,"userdirprotect":"","homedir":"/home/saje4058","user":"saje4058","serveralias":"mail.webelevation.fr webelevation.fr www.webelevation.fr www.webelevationfr.saje4058.odns.fr"}userdata/saje4058/paysagevertfr.saje4058.odns.fr000064400000000670152342432460015246 0ustar00--- documentroot: /home/saje4058/paysagevert.fr group: saje4058 hascgi: 1 homedir: /home/saje4058 ip: 109.234.165.185 ipv6: ~ no_cache_update: 0 owner: root phpopenbasedirprotect: 1 serveradmin: webmaster@paysagevertfr.saje4058.odns.fr serveralias: mail.paysagevert.fr paysagevert.fr www.paysagevert.fr www.paysagevertfr.saje4058.odns.fr servername: paysagevertfr.saje4058.odns.fr usecanonicalname: 'Off' user: saje4058 userdirprotect: '' userdata/saje4058/webelevationfr.saje4058.odns.fr000064400000000677152342432460015407 0ustar00--- documentroot: /home/saje4058/webelevation.fr group: saje4058 hascgi: 1 homedir: /home/saje4058 ip: 109.234.165.185 ipv6: ~ no_cache_update: 0 owner: root phpopenbasedirprotect: 1 serveradmin: webmaster@webelevationfr.saje4058.odns.fr serveralias: mail.webelevation.fr webelevation.fr www.webelevation.fr www.webelevationfr.saje4058.odns.fr servername: webelevationfr.saje4058.odns.fr usecanonicalname: 'Off' user: saje4058 userdirprotect: '' userdata/saje4058/cache.json000064400000001454152342432460011566 0ustar00{"saje4058.odns.fr":["saje4058","root","main","saje4058.odns.fr","/home/saje4058/public_html","109.234.165.185:8081","109.234.165.185:4430","","0",""],"webelevation.fr":["saje4058","root","addon","webelevationfr.saje4058.odns.fr","/home/saje4058/webelevation.fr","109.234.165.185:80","109.234.165.185:4430","","0",""],"paysagevertfr.saje4058.odns.fr":["saje4058","root","sub","saje4058.odns.fr","/home/saje4058/paysagevert.fr","109.234.165.185:80","109.234.165.185:4430","","0",""],"paysagevert.fr":["saje4058","root","addon","paysagevertfr.saje4058.odns.fr","/home/saje4058/paysagevert.fr","109.234.165.185:80","109.234.165.185:4430","","0",""],"webelevationfr.saje4058.odns.fr":["saje4058","root","sub","saje4058.odns.fr","/home/saje4058/webelevation.fr","109.234.165.185:80","109.234.165.185:4430","","0",""]}userdata/saje4058/paysagevertfr.saje4058.odns.fr_SSL.cache000064400000000771152342432460017033 0ustar00{"ssl":"1","userdirprotect":"","homedir":"/home/saje4058","user":"saje4058","serveralias":"mail.paysagevert.fr paysagevert.fr www.paysagevert.fr www.paysagevertfr.saje4058.odns.fr","ipv6":null,"secruleengineoff":null,"port":"4430","group":"saje4058","serveradmin":"webmaster@paysagevertfr.saje4058.odns.fr","documentroot":"/home/saje4058/paysagevert.fr","phpopenbasedirprotect":null,"usecanonicalname":"Off","ip":"109.234.165.185","owner":"root","hascgi":"1","servername":"paysagevertfr.saje4058.odns.fr"}userdata/saje4058/main000064400000000400152342432460010465 0ustar00--- addon_domains: paysagevert.fr: paysagevertfr.saje4058.odns.fr webelevation.fr: webelevationfr.saje4058.odns.fr main_domain: saje4058.odns.fr parked_domains: [] sub_domains: - webelevationfr.saje4058.odns.fr - paysagevertfr.saje4058.odns.fr userdata/saje4058/saje4058.odns.fr_SSL000064400000000576152342432460013113 0ustar00--- documentroot: /home/saje4058/public_html group: saje4058 hascgi: 1 homedir: /home/saje4058 ip: 109.234.165.185 ipv6: ~ owner: root phpopenbasedirprotect: ~ port: 4430 secruleengineoff: ~ serveradmin: webmaster@saje4058.odns.fr serveralias: mail.saje4058.odns.fr www.saje4058.odns.fr servername: saje4058.odns.fr ssl: 1 usecanonicalname: 'Off' user: saje4058 userdirprotect: '' userdata/saje4058/saje4058.odns.fr.cache000064400000001176152342432460013431 0ustar00{"serveradmin":"webmaster@saje4058.odns.fr","group":"saje4058","documentroot":"/home/saje4058/public_html","phpopenbasedirprotect":"1","ip":"109.234.165.185","usecanonicalname":"Off","owner":"root","scriptalias":[{"url":"/cgi-bin/","path":"/home/saje4058/public_html/cgi-bin"}],"customlog":[{"format":"combined","target":"/etc/apache2/logs/domlogs/saje4058.odns.fr"},{"format":"\"%{%s}t %I .\\n%{%s}t %O .\"","target":"/etc/apache2/logs/domlogs/saje4058.odns.fr-bytes_log"}],"servername":"saje4058.odns.fr","hascgi":"1","homedir":"/home/saje4058","user":"saje4058","serveralias":"mail.saje4058.odns.fr www.saje4058.odns.fr","port":"8081"}