| Server IP : 43.141.49.107 / Your IP : 113.219.202.44 Web Server : Apache System : Linux VM-8-5-opencloudos 6.6.34-9.oc9.x86_64 #1 SMP PREEMPT_DYNAMIC Wed Jun 19 19:35:45 CST 2024 x86_64 User : www ( 1000) PHP Version : 8.1.27 Disable Function : passthru,exec,system,putenv,chroot,chgrp,chown,shell_exec,popen,proc_open,pcntl_exec,ini_alter,ini_restore,dl,openlog,syslog,readlink,symlink,popepassthru,pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,imap_open,apache_setenv MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : ON Directory : /www/wwwroot/wordpress/wordpress/wp-content/plugins/wpjam-basic/includes/ |
Upload File : |
<?php
class WPJAM_Var extends WPJAM_Args{
private function __construct(){
$this->args = self::parse_user_agent();
}
public function supports($feature){
if($feature == 'webp'){
return $this->browser == 'chrome' || $this->os == 'Android' || ($this->os == 'iOS' && version_compare($this->os_version, 14) >= 0);
}
}
public static function parse_user_agent($user_agent=null, $referer=null){
$user_agent ??= $_SERVER['HTTP_USER_AGENT'] ?? '';
$referer ??= $_SERVER['HTTP_REFERER'] ?? '';
$os = 'unknown';
$device = $browser = $app = '';
$os_version = $browser_version = $app_version = 0;
$rule = wpjam_find([
['iPhone', 'iOS', 'iPhone'],
['iPad', 'iOS', 'iPad'],
['iPod', 'iOS', 'iPod'],
['Android', 'Android'],
['Windows NT', 'Windows'],
['Macintosh', 'Macintosh'],
['Windows Phone', 'Windows Phone'],
['BlackBerry', 'BlackBerry'],
['BB10', 'BlackBerry'],
['Symbian', 'Symbian'],
], fn($rule) => stripos($user_agent, $rule[0]));
if($rule){
$os = $rule[1];
if(isset($rule[2])){
$device = $rule[2];
}
}
if($os == 'iOS'){
if(preg_match('/OS (.*?) like Mac OS X[\)]{1}/i', $user_agent, $matches)){
$os_version = (float)(trim(str_replace('_', '.', $matches[1])));
}
}elseif($os == 'Android'){
if(preg_match('/Android ([0-9\.]{1,}?); (.*?) Build\/(.*?)[\)\s;]{1}/i', $user_agent, $matches)){
if(!empty($matches[1]) && !empty($matches[2])){
$os_version = trim($matches[1]);
if(strpos($matches[2],';')!==false){
$device = substr($matches[2], strpos($matches[2],';')+1, strlen($matches[2])-strpos($matches[2],';'));
}else{
$device = $matches[2];
}
$device = trim($device);
// $build = trim($matches[3]);
}
}
}
foreach([
'lynx' => ['lynx'],
'safari' => ['safari', '/version\/([\d\.]+).*safari/i'],
'edge' => ['edg', '/edge\/([\d\.]+)/i'],
'chrome' => ['chrome', '/chrome\/([\d\.]+)/i'],
'firefox' => ['firefox', '/firefox\/([\d\.]+)/i'],
'opera' => ['opera', '/(?:opera).([\d\.]+)/i'],
'opera' => ['opr/', '/(?:opr).([\d\.]+)/i'],
'ie' => ['msie'],
'ie' => ['trident'],
'gecko' => ['gecko'],
'nav' => ['nav']
] as $key => $value){
if(stripos($user_agent, $value[0]) !== false){
$browser = $key;
}
if($browser){
if(!empty($value[1]) && preg_match($value[1], $user_agent, $matches)){
$browser_version = (float)(trim($matches[1]));
}
break;
}
}
if(strpos($user_agent, 'MicroMessenger') !== false){
$app = str_contains($referer, 'https://servicewechat.com') ? 'weapp' : 'weixin';
if(preg_match('/MicroMessenger\/(.*?)\s/', $user_agent, $matches)){
$app_version = (float)$matches[1];
}
}elseif(strpos($user_agent, 'ToutiaoMicroApp') !== false
|| strpos($referer, 'https://tmaservice.developer.toutiao.com') !== false
){
$app = 'bytedance';
}
return compact('os', 'device', 'app', 'browser', 'os_version', 'browser_version', 'app_version');
}
public static function parse_ip($ip=null){
$ip = $ip ?: wpjam_get_ip();
if($ip == 'unknown'){
return false;
}
$data = [
'ip' => $ip,
'country' => '',
'region' => '',
'city' => '',
];
if(file_exists(WP_CONTENT_DIR.'/uploads/17monipdb.dat')){
$ipdata = IP::find($ip);
return array_merge($data, [
'country' => $ipdata['0'] ?? '',
'region' => $ipdata['1'] ?? '',
'city' => $ipdata['2'] ?? '',
]);
}
return $data;
}
public static function get_instance(){
static $object;
return $object ??= new static();
}
public static function get_current_user($required=false){
$object = self::get_instance();
if(isset($object->user)){
$value = $object->user;
}else{
$value = apply_filters('wpjam_current_user', null);
if(!is_null($value) && !is_wp_error($value)){
$object->user = $value;
}
}
if($required){
return is_null($value) ? new WP_Error('bad_authentication') : $value;
}else{
return is_wp_error($value) ? null : $value;
}
}
}
class WPJAM_JWT{
protected static function hash($jwt, $key=''){
return base64_urlencode(hash_hmac('sha256', $jwt, ($key ?: wp_salt()), true));
}
public static function generate($payload, $key='', $header=[]){
if(is_array($payload)){
$header = wp_parse_args($header, ['alg'=>'HS256', 'typ'=>'JWT']);
if($header['alg'] == 'HS256'){
$encode = fn($data)=> base64_urlencode(wpjam_json_encode($data));
$jwt = $encode($header).'.'.$encode($payload);
return $jwt.'.'.self::hash($jwt, $key);
}
}
return false;
}
public static function verify($token, $key=''){
$tokens = $token ? explode('.', $token) : [];
if(count($tokens) != 3 || !hash_equals(self::hash($tokens[0].'.'.$tokens[1], $key), $tokens[2])){
return false;
}
$decode = fn($str)=> wpjam_json_decode(base64_urldecode($str));
$header = $decode($tokens[0]);
$payload = $decode($tokens[1]);
if(empty($header['alg']) || $header['alg'] != 'HS256'){
return false;
}
//iat 签发时间不能大于当前时间
//nbf 时间之前不接收处理该Token
//exp 过期时间不能小于当前时间
if(wpjam_some(['iat'=>'>', 'nbf'=>'>', 'exp'=>'<'], fn($v, $k)=> isset($payload[$k]) && wpjam_compare($payload[$k], $v, time()))){
return false;
}
return $payload;
}
public static function get($param='access_token', $required=false){
$headers = getallheaders();
if(isset($headers['Authorization']) && str_starts_with($headers['Authorization'], 'Bearer')){
return trim(wpjam_remove_prefix($headers['Authorization'], 'Bearer'));
}
return wpjam_get_parameter($param, ['required'=>$required]);
}
}
class WPJAM_Crypt extends WPJAM_Args{
public function __construct(...$args){
if($args && is_string($args[0])){
$key = $args[0];
$args = $args[1] ?? [];
$args = array_merge($args, ['key'=>$key]);
}else{
$args = $args[0] ?? [];
}
$this->args = wp_parse_args($args, [
'method' => 'aes-256-cbc',
'key' => '',
'iv' => '',
'options' => OPENSSL_ZERO_PADDING,
]);
}
public function encrypt($text){
if($this->pad == 'weixin' && $this->appid){
$text = $this->pad($text, 'weixin', $this->appid);
}
if($this->options == OPENSSL_ZERO_PADDING && $this->block_size){
$text = $this->pad($text, 'pkcs7', $this->block_size);
}
return openssl_encrypt($text, $this->method, $this->key, $this->options, $this->iv);
}
public function decrypt($text){
$text = openssl_decrypt($text, $this->method, $this->key, $this->options, $this->iv);
if($this->options == OPENSSL_ZERO_PADDING && $this->block_size){
$text = $this->unpad($text, 'pkcs7', $this->block_size);
}
if($this->pad == 'weixin' && $this->appid){
$text = $this->unpad($text, 'weixin', $this->appid);
}
return $text;
}
public static function pad($text, $method, ...$args){
if($method == 'pkcs7'){
$pad = $args[0] - (strlen($text) % $args[0]);
return $text.str_repeat(chr($pad), $pad);
}elseif($method == 'weixin'){
return wp_generate_password(16, false).pack("N", strlen($text)).$text.$args[0];
}
return $text;
}
public static function unpad($text, $method, ...$args){
if($method == 'pkcs7'){
$pad = ord(substr($text, -1));
if($pad < 1 || $pad > $args[0]){
$pad = 0;
}
return substr($text, 0, -1 * $pad);
}elseif($method == 'weixin'){
$text = substr($text, 16);
$length = (unpack("N", substr($text, 0, 4)))[1];
if(substr($text, $length + 4) != $args[0]){
return new WP_Error('invalid_appid', 'Appid 校验错误');
}
return substr($text, 4, $length);
}
return $text;
}
public static function generate_signature(...$args){
return sha1(implode(wpjam_sort($args, SORT_STRING)));
}
public static function weixin_pad($text, $appid){
return self::pad($text, 'weixin', $appid);
}
public static function weixin_unpad($text, &$appid){
$text = substr($text, 16, strlen($text));
$len_list = unpack("N", substr($text, 0, 4));
$text_len = $len_list[1];
$appid = substr($text, $text_len + 4);
return substr($text, 4, $text_len);
}
public static function generate_weixin_signature($token, &$ts='', &$nonce='', $encrypt_msg=''){
$ts = $ts ?: time();
$nonce = $nonce ?: wp_generate_password(8, false);
return self::generate_signature($token, $ts, $nonce, $encrypt_msg);
}
}
class WPJAM_Updater extends WPJAM_Args{
public function get_data($file){ // https://api.wordpress.org/plugins/update-check/1.1/
$key = 'update_'.$this->plural.':'.$this->hostname;
$response = wpjam_transient($key, fn()=> wpjam_remote_request($this->update_url), MINUTE_IN_SECONDS);
if(is_wp_error($response)){
return false;
}
$response = $response['template']['table'] ?? $response[$this->plural];
if(isset($response['fields']) && isset($response['content'])){
$fields = array_column($response['fields'], 'index', 'title');
$index = $fields[$this->label];
foreach($response['content'] as $item){
if($item['i'.$index] == $file){
$data = [];
foreach($fields as $name => $index){
$data[$name] = $item['i'.$index] ?? '';
}
return [
$this->type => $file,
'url' => $data['更新地址'],
'package' => $data['下载地址'],
'icons' => [],
'banners' => [],
'banners_rtl' => [],
'new_version' => $data['版本'],
'requires_php' => $data['PHP最低版本'],
'requires' => $data['最低要求版本'],
'tested' => $data['最新测试版本'],
];
}
}
}else{
return $response[$file] ?? [];
}
}
public function filter_update($update, $data, $file, $locales){
$new_data = $this->get_data($file);
if($new_data){
return wp_parse_args($new_data, [
'id' => $data['UpdateURI'],
'version' => $data['Version'],
]);
}
return $update;
}
public function filter_pre_set_site_transient($updates){
if(isset($updates->no_update) || isset($updates->response)){
$file = 'wpjam-basic/wpjam-basic.php';
$update = $this->get_data($file);
if($update){
$plugin = get_plugin_data(WP_PLUGIN_DIR.'/'.$file);
$key = version_compare($update['new_version'], $plugin['Version'], '>') ? 'response' : 'no_update';
if(isset($updates->$key[$file])){
$update = array_merge((array)$updates->$key[$file], $update);
}
$updates->$key[$file] = (object)$update;
}
}
return $updates;
}
public static function create($type, $hostname, $update_url){
if(in_array($type, ['plugin', 'theme'])){
$plural = $type.'s';
$object = new self([
'type' => $type,
'plural' => $plural,
'label' => $type == 'plugin' ? '插件' : '主题',
'hostname' => $hostname,
'update_url' => $update_url
]);
add_filter('update_'.$plural.'_'.$hostname, [$object, 'filter_update'], 10, 4);
if($plural == 'plugins' && $hostname == 'blog.wpjam.com'){
add_filter('pre_set_site_transient_update_plugins', [$object, 'filter_pre_set_site_transient']);
}
}
}
}
class WPJAM_Cache extends WPJAM_Args{
public function __call($method, $args){
if(str_starts_with($method, 'cache_')){
$method = wpjam_remove_prefix($method, 'cache_');
}
$cb = [];
$key = array_shift($args);
$gnd = str_contains($method, 'get') || str_contains($method, 'delete');
if(str_contains($method, '_multiple')){
if($gnd){
$cb[] = $keys = array_map([$this, 'key'], $key);
}else{
$cb[] = wpjam_array($key, fn($k) => $this->key($k));
}
}else{
$cb[] = $this->key($key);
if(!$gnd){
$cb[] = array_shift($args);
}
}
$cb[] = $this->group;
if(!$gnd){
$cb[] = $this->time(array_shift($args));
}
$callback = 'wp_cache_'.$method;
$result = $callback(...$cb);
if($result && $method == 'get_multiple'){
$result = wpjam_array($key, fn($i, $k) => [$k, $result[$keys[$i]]]);
$result = array_filter($result, fn($v) => $v !== false);
}
return $result;
}
protected function key($key){
return wpjam_join(':', $this->prefix, $key);
}
protected function time($time){
return (int)($time) ?: ($this->time ?: DAY_IN_SECONDS);
}
public function cas($token, $key, $value, $time=0){
return wp_cache_cas($token, $this->key($key), $value, $this->group, $this->time($time));
}
public function get_with_cas($key, &$token, $default=null){
if(is_object($token)){
$object = $token;
$token = null;
}
$key = $this->key($key);
$result = wp_cache_get_with_cas($key, $this->group, $token);
if($result === false && isset($default)){
$this->set($key, $default);
$result = wp_cache_get_with_cas($key, $this->group, $token);
}
if(isset($object)){
$object->cas_token = $token;
}
return $result;
}
public function generate($key){
$result = $this->is_exceeded($key);
if(is_wp_error($result)){
return $result;
}
if($this->interval && $this->get($key.':time') !== false){
return new WP_Error('error', '验证码'.((int)($this->interval/60)).'分钟前已发送了。');
}
$code = rand(100000, 999999);
$this->set($key.':code', $code, $this->cache_time);
if($this->interval){
$this->set($key.':time', time(), MINUTE_IN_SECONDS);
}
return $code;
}
public function verify($key, $code){
$result = $this->is_exceeded($key);
if(is_wp_error($result)){
return $result;
}
$cached = $code ? $this->get($key.':code') : false;
if($cached === false){
return new WP_Error('invalid_code');
}elseif($cached != $code){
if($this->failed_times){
$failed_times = $this->get($key.':failed_times') ?: 0;
$failed_times = $failed_times + 1;
$this->set($key.':failed_times', $failed_times, $this->cache_time/2);
}
return new WP_Error('invalid_code');
}
return true;
}
protected function is_exceeded($key){
if($this->failed_times && (int)$this->get($key.':failed_times') > $this->failed_times){
return new WP_Error('failed_times_exceeded', ['尝试的失败次数', '请15分钟后重试。']);
}
}
public static function get_verification($args){
if(is_array($args)){
$name = wpjam_pull($args, 'group');
}else{
$name = $args;
$args = [];
}
return self::get_instance([
'group' => 'verification_code',
'prefix' => $name ?: 'default',
'global' => true,
]+wp_parse_args($args, [
'failed_times' => 5,
'cache_time' => MINUTE_IN_SECONDS*30,
'interval' => MINUTE_IN_SECONDS
]));
}
public static function get_instance($group, $args=[]){
if(is_array($group)){
$args = $group;
$group = $args['group'] ?? '';
}else{
$args = array_merge($args, ['group'=>$group]);
}
if($group){
$name = wpjam_join(':', $group, ($args['prefix'] ?? ''));
return wpjam_get_instance('cache', $name, fn()=> self::create($args));
}
}
public static function create($args=[]){
if(!empty($args['group'])){
if(wpjam_pull($args, 'global')){
wp_cache_add_global_groups($args['group']);
}
return new self($args);
}
}
}
class WPJAM_Error extends WPJAM_Model{
public static function get_handler(){
return wpjam_get_handler('wpjam_errors', [
'option_name' => 'wpjam_errors',
'primary_key' => 'errcode',
'primary_title' => '代码',
]);
}
public static function filter($data){
$error = self::get($data['errcode']);
if($error){
$data['errmsg'] = $error['errmsg'];
if(!empty($error['show_modal'])){
if(!empty($error['modal']['title']) && !empty($error['modal']['content'])){
$data['modal'] = $error['modal'];
}
}
}else{
if(empty($data['errmsg'])){
$item = self::get_setting($data['errcode']);
if($item){
if($item['message']){
$data['errmsg'] = $item['message'];
}
if($item['modal']){
$data['modal'] = $item['modal'];
}
}
}
}
return $data;
}
public static function parse($data){
if(is_wp_error($data)){
$errdata = $data->get_error_data();
$data = [
'errcode' => $data->get_error_code(),
'errmsg' => $data->get_error_message(),
];
if($errdata){
$errdata = is_array($errdata) ? $errdata : ['errdata'=>$errdata];
$data = $data + $errdata;
}
}else{
if($data === true){
return ['errcode'=>0];
}elseif($data === false || is_null($data)){
return ['errcode'=>'-1', 'errmsg'=>'系统数据错误或者回调函数返回错误'];
}elseif(is_array($data)){
if(!$data || !wp_is_numeric_array($data)){
$data = wp_parse_args($data, ['errcode'=>0]);
}
}
}
return empty($data['errcode']) ? $data : self::filter($data);
}
public static function if($data, $err=[]){
$err = wp_parse_args($err, [
'errcode' => 'errcode',
'errmsg' => 'errmsg',
'detail' => 'detail',
'success' => '0',
]);
$code = wpjam_pull($data, $err['errcode']);
if($code && $code != $err['success']){
$msg = wpjam_pull($data, $err['errmsg']);
$detail = wpjam_pull($data, $err['detail']);
$detail = is_null($detail) ? array_filter($data) : $detail;
return new WP_Error($code, $msg, $detail);
}
return $data;
}
public static function convert($message, $title='', $args=[]){
if(is_wp_error($message)){
return $message;
}
$code = is_scalar($args) ? $args : '';
if($code){
$detail = $title ? ['modal'=>['title'=>$title, 'content'=>$message]] : [];
return new WP_Error($code, $message, $detail);
}
if($title){
$code = $title;
}else{
$code = 'error';
if(is_scalar($message)){
if(self::get_setting($message)){
[$code, $message] = [$message, ''];
}else{
$parsed = self::parse_message($message);
if($parsed){
[$code, $message] = [$message, $parsed];
}
}
}
}
return new WP_Error($code, $message);
}
public static function parse_message($code, $message=[]){
$fn = fn($map, $key)=> $map[$key] ?? ucwords($key);
if(str_starts_with($code, 'invalid_')){
$key = wpjam_remove_prefix($code, 'invalid_');
if($key == 'parameter'){
return $message ? '无效的参数:'.$message[0].'。' : '参数错误。';
}elseif($key == 'callback'){
return '无效的回调函数'.($message ? ':'.$message[0] : '').'。';
}elseif($key == 'name'){
return $message ? $message[0].'不能为纯数字。' : '无效的名称';
}else{
return [
'nonce' => '验证失败,请刷新重试。',
'code' => '验证码错误。',
'password' => '两次输入的密码不一致。'
][$key] ?? '无效的'.$fn([
'id' => ' ID',
'post_type' => '文章类型',
'taxonomy' => '分类模式',
'post' => '文章',
'term' => '分类',
'user' => '用户',
'comment_type' => '评论类型',
'comment_id' => '评论 ID',
'comment' => '评论',
'type' => '类型',
'signup_type' => '登录方式',
'email' => '邮箱地址',
'data_type' => '数据类型',
'qrcode' => '二维码',
], $key);
}
}elseif(str_starts_with($code, 'illegal_')){
$key = wpjam_remove_prefix($code, 'illegal_');
return $fn([
'access_token' => 'Access Token ',
'refresh_token' => 'Refresh Token ',
'verify_code' => '验证码',
], $key).'无效或已过期。';
}elseif(str_ends_with($code, '_required')){
$key = wpjam_remove_postfix($code, '_required');
$format = $key == 'parameter' ? '参数%s' : '%s的值';
return $message ? sprintf($format.'为空或无效。', ...$message) : '参数或者值无效';
}elseif(str_ends_with($code, '_occupied')){
$key = wpjam_remove_postfix($code, '_occupied');
return $fn([
'phone' => '手机号码',
'email' => '邮箱地址',
'nickname' => '昵称',
], $key).'已被其他账号使用。';
}
return '';
}
public static function get_setting($code){
return wpjam_get_item('error', $code);
}
public static function add_setting($code, $message, $modal=[]){
if(!wpjam_get_items('error')){
add_action('wp_error_added', [self::class, 'on_wp_error_added'], 10, 4);
}
if($message){
wpjam_add_item('error', $code, ['message'=>$message, 'modal'=>$modal]);
}
}
public static function on_wp_error_added($code, $message, $data, $wp_error){
if($code && (!$message || is_array($message)) && count($wp_error->get_error_messages($code)) <= 1){
if(is_array($code)){
trigger_error(var_export($code, true));
}
$item = self::get_setting($code);
if($item){
if($item['modal']){
$data = is_array($data) ? $data : [];
$data = array_merge($data, ['modal'=>$item['modal']]);
}
if(is_callable($item['message'])){
$parsed = $item['message']($message, $code);
}else{
$parsed = is_array($message) ? sprintf($item['message'], ...$message) : $item['message'];
}
}else{
$parsed = self::parse_message($code, $message);
}
$wp_error->remove($code);
$wp_error->add($code, ($parsed ?: $code), $data);
}
}
}
class WPJAM_Exception extends Exception{
private $errcode = '';
public function __construct($errmsg, $errcode=null, Throwable $previous=null){
if(is_array($errmsg)){
$errmsg = new WP_Error($errcode, $errmsg);
}
if(is_wp_error($errmsg)){
$errcode = $errmsg->get_error_code();
$errmsg = $errmsg->get_error_message();
}else{
$errcode = $errcode ?: 'error';
}
$this->errcode = $errcode;
parent::__construct($errmsg, (is_numeric($errcode) ? (int)$errcode : 1), $previous);
}
public function get_error_code(){
return $this->errcode;
}
public function get_error_message(){
return $this->getMessage();
}
public function get_wp_error(){
return new WP_Error($this->errcode, $this->getMessage());
}
}
class WPJAM_Asset{
public static function do($type, $handle, $args){
$method = wpjam_pull($args, 'method') ?: 'enqueue';
$if = wpjam_pull($args, $method.'_if');
if($if && !$if($handle, $type)){
return;
}
$src = wpjam_pull($args, 'src');
$deps = wpjam_pull($args, 'deps');
$ver = wpjam_pull($args, 'ver');
$data = wpjam_pull($args, 'data');
if($type == 'script'){
$pos = wpjam_pull($args, 'position') ?: 'after';
}else{
$pos = null;
$args = wpjam_pull($args, 'media') ?: 'all';
}
if($src && is_closure($src)){
$src = $src($handle);
}
if($src || !$data){
call_user_func('wp_'.$method.'_'.$type, $handle, $src, $deps, $ver, $args);
}
if($data){
call_user_func('wp_add_inline_'.$type, $handle, $data, $pos);
}
}
public static function handle($type, $handle, $args){
$args = is_array($args) ? $args : ['src'=>$args];
$postfix = '_enqueue_scripts';
if(wpjam_some(['wp', 'admin', 'login'], fn($part)=> doing_action($part.$postfix))){
self::do($type, $handle, $args);
}else{
$for = wpjam_pull($args, 'for');
$for = is_null($for) ? ['admin', 'login', 'wp'] : ($for ? wp_parse_list($for) : ['wp']);
$parts = is_admin() ? ['admin', 'wp'] : (is_login() ? ['login'] : ['wp']);
$parts = array_intersect($parts, $for);
$priority = wpjam_pull($args, 'priority') ?? 10;
array_walk($parts, fn($part)=> wpjam_load($part.$postfix, fn()=> self::do($type, $handle, $args), $priority));
}
}
public static function add_static_cdn($host){
if(!wpjam_get_items('static_cdn')){
add_filter('wp_resource_hints', [self::class, 'filter_resource_hints'], 10, 2);
add_filter('style_loader_src', [self::class, 'filter_loader_src']);
add_filter('script_loader_src', [self::class, 'filter_loader_src']);
add_filter('current_theme_supports-style', [self::class, 'filter_current_theme_supports'], 10, 3);
add_filter('current_theme_supports-script', [self::class, 'filter_current_theme_supports'], 10, 3);
}
wpjam_add_item('static_cdn', $host);
}
public static function get_static_cdn(){
$hosts = wpjam_get_items('static_cdn');
return apply_filters('wpjam_static_cdn_host', $hosts[0], $hosts);
}
protected static function get_static_search(){
$search = array_diff(wpjam_get_items('static_cdn'), [self::get_static_cdn()]);
return [...$search, 'https://cdn.staticfile.net', 'https://cdn.staticfile.org', 'https://cdn.bootcdn.net/ajax/libs'];
}
public static function filter_loader_src($src){
if($src){
$cdn = self::get_static_cdn();
if(!str_starts_with($src, $cdn)){
return str_replace(self::get_static_search(), $cdn, $src);
}
}
return $src;
}
public static function filter_resource_hints($urls, $type){
if($type == 'dns-prefetch'){
$search = self::get_static_search();
$urls = array_diff($urls, wpjam_map($search, fn($host)=> parse_url($host, PHP_URL_HOST)));
$urls[] = self::get_static_cdn();
}
return $urls;
}
public static function filter_current_theme_supports($check, $args, $value){
return !array_diff($args, (is_array($value[0]) ? $value[0] : $value));
}
}
class WPJAM_Callback{
public static function call_method($class, $method, ...$args){
$parsed = self::parse_method($class, $method, $args);
return is_wp_error($parsed) ? $parsed : $parsed(...$args);
}
public static function parse_method($class, $method, &$args=[], $number=1){
if(is_object($class)){
$object = $class;
$class = get_class($class);
}else{
if(!class_exists($class)){
return new WP_Error('invalid_model', [$class]);
}
}
if(!method_exists($class, $method)){
if(method_exists($class, '__callStatic')){
$is_public = true;
$is_static = true;
}elseif(method_exists($class, '__call')){
$is_public = true;
$is_static = false;
}else{
return new WP_Error('undefined_method', [$class.'->'.$method.'()']);
}
}else{
$reflection = self::get_reflection([$class, $method]);
$is_public = $reflection->isPublic();
$is_static = $reflection->isStatic();
}
if($is_static){
return $is_public ? [$class, $method] : $reflection->getClosure();
}else{
$object ??= self::get_instance($class, $args, $number);
if(is_wp_error($object)){
return $object;
}
return $is_public ? [$object, $method] : $reflection->getClosure($object);
}
}
public static function get_instance($class, &$args, $number=1){
if(!method_exists($class, 'get_instance')){
return new WP_Error('undefined_method', [$class.'->get_instance()']);
}
for($i=0; $i < $number; $i++){
$params[] = $param = array_shift($args);
if(is_null($param)){
return new WP_Error('instance_required', '实例方法对象才能调用');
}
}
return $class::get_instance(...$params) ?: new WP_Error('invalid_id', [$class]);
}
public static function get_parameters($callback){
return (self::get_reflection($callback))->getParameters();
}
public static function verify($callback, $verify){
$reflection = self::get_reflection($callback);
return $verify($reflection->getParameters(), $reflection);
}
public static function get_reflection($callback){
$id = self::build_unique_id($callback);
return wpjam_get_instance('reflection', $id, fn()=> is_array($callback) ? new ReflectionMethod(...$callback) : new ReflectionFunction($callback));
}
public static function build_unique_id($callback){
return _wp_filter_build_unique_id(null, $callback, null);
}
}
class WPJAM_Parameter{
public static function get_value($name, $args=[], $method=''){
if(is_array($name)){
if(!$name){
return [];
}
if(wp_is_numeric_array($name)){
return wpjam_fill($name, fn($n) => self::get_value($n, $args, $method));
}else{
return wpjam_array($name, fn($n, $v) => self::get_value($n, $v, $method));
}
}
$method = $method ?: (array_get($args, 'method') ?: 'GET');
$method = strtoupper($method);
$value = self::get_by_name($name, $method);
if($name){
if(is_null($value) && !empty($args['fallback'])){
$value = self::get_by_name($args['fallback'], $method);
}
if(is_null($value)){
if(isset($args['default'])){
$value = $args['default'];
}else{
$defaults = wpjam_var('defaults') ?: [];
$value = $defaults[$name] ?? null;
}
}
$args = wpjam_except($args, ['method', 'fallback', 'default']);
if($args){
$args['key'] = $name;
$args['type'] ??= '';
if($args['type'] == 'int'){ // 兼容
$args['type'] = 'number';
}
$field = wpjam_field($args);
if(!$args['type']){
$field->set_schema(false);
}
$value = wpjam_catch([$field, 'validate'], $value, 'parameter');
if(is_wp_error($value) && array_get($args, 'send') !== false){
wpjam_send_json($value);
}
}
}
return $value;
}
private static function get_by_name($name, $method){
if($method == 'DATA'){
if($name && isset($_GET[$name])){
return wp_unslash($_GET[$name]);
}
$data = self::get_data();
}else{
$data = ['POST'=>$_POST, 'REQUEST'=>$_REQUEST][$method] ?? $_GET;
if($name){
if(isset($data[$name])){
return wp_unslash($data[$name]);
}
if($_POST || !in_array($method, ['POST', 'REQUEST'])){
return null;
}
}else{
if($data || in_array($method, ['GET', 'REQUEST'])){
return wp_unslash($data);
}
}
$data = self::get_input();
}
return $name ? ($data[$name] ?? null) : $data;
}
private static function get_input(){
static $_input;
if(!isset($_input)){
$input = file_get_contents('php://input');
$input = is_string($input) ? @wpjam_json_decode($input) : $input;
$_input = is_array($input) ? $input : [];
}
return $_input;
}
private static function get_data(){
static $_data;
if(!isset($_data)){
$_data = [];
foreach(['defaults', 'data'] as $key){
$data = self::get_by_name($key, 'REQUEST') ?? [];
$data = ($data && is_string($data) && str_starts_with($data, '{')) ? wpjam_json_decode($data) : wp_parse_args($data);
$_data = wpjam_merge($_data, $data);
}
}
return $_data;
}
public static function method_allow($method){
if($_SERVER['REQUEST_METHOD'] != strtoupper($method)){
return wp_die('method_not_allow', '接口不支持 '.$_SERVER['REQUEST_METHOD'].' 方法,请使用 '.$method.' 方法!');
}
return true;
}
}
class WPJAM_Http{
public static function request($url, $args=[], $err=[]){
$args = wp_parse_args($args, [
'body' => [],
'headers' => [],
'sslverify' => false,
'stream' => false,
]);
$method = strtoupper(wpjam_pull($args, 'method', '')) ?: ($args['body'] ? 'POST' : 'GET');
if($method == 'GET'){
$response = wp_remote_get($url, $args);
}elseif($method == 'FILE'){
$response = (new WP_Http_Curl())->request($url, wp_parse_args($args, [
'method' => $args['body'] ? 'POST' : 'GET',
'sslcertificates' => ABSPATH.WPINC.'/certificates/ca-bundle.crt',
'user-agent' => 'WordPress',
'decompress' => true,
]));
}else{
$response = wp_remote_request($url, array_merge(self::encode($args), ['method'=>$method]));
}
$args['url'] = $url;
if(is_wp_error($response)){
return self::log($response, $args);
}
$body = &$response['body'];
if($body && !$args['stream']){
if(str_contains(wp_remote_retrieve_header($response, 'content-disposition'), 'attachment;')){
$body = wpjam_bits($body);
}else{
$body = self::decode($body, $args, $err);
if(is_wp_error($body)){
return $body;
}
}
}
$code = $response['response']['code'] ?? 0;
if($code && ($code < 200 || $code >= 300)){
return new WP_Error($code, '远程服务器错误:'.$code.' - '.$response['response']['message']);
}
return $response;
}
private static function encode($args){
$content_type = $args['headers']['Content-Type'] ?? ($args['headers']['content-type'] ?? '');
if(str_contains($content_type, 'application/json')){
$encode = true;
}else{
$encode = wpjam_pull($args, 'json_encode_required', wpjam_pull($args, 'need_json_encode'));
}
if($encode){
if(is_array($args['body'])){
$args['body'] = wpjam_json_encode($args['body'] ?: new stdClass);
}
if(empty($args['headers']['Content-Type']) && empty($args['headers']['content-type'])){
$args['headers']['Content-Type'] = 'application/json';
}
}
return $args;
}
private static function decode($body, $args=[], $err=[]){
if(wpjam_pull($args, 'json_decode') !== false && str_starts_with($body, '{') && str_ends_with($body, '}')){
$decoded = wpjam_json_decode($body);
if(!is_wp_error($decoded)){
$body = WPJAM_Error::if($decoded, $err);
if(is_wp_error($body)){
self::log($body, $args);
}
}
}
return $body;
}
private static function log($error, $args=[]){
$code = $error->get_error_code();
$msg = $error->get_error_message();
if(apply_filters('wpjam_http_response_error_debug', true, $code, $msg)){
$detail = $error->get_error_data();
$detail = $detail ? var_export($detail, true)."\n" : '';
trigger_error($args['url']."\n".$code.' : '.$msg."\n".$detail.var_export($args['body'], true));
}
return $error;
}
}
class WPJAM_File{
public static function upload($name){
require_once ABSPATH.'wp-admin/includes/file.php';
if(is_array($name)){
if(isset($name['bits'])){
$upload = wp_upload_bits(($name['name'] ?? ''), null, $name['bits']);
}else{
$upload = wp_handle_sideload($name, ['test_form'=>false]);
}
}else{
$upload = wp_handle_upload($_FILES[$name], ['test_form'=>false]);
}
return self::is_error($upload) ?: $upload+['path'=>self::convert($upload['file'], 'file', 'path')];
}
public static function upload_bits($bits, $name, $media=true, $post_id=0){
$args = self::parse_args($name, $media, $post_id);
$name = $args['name'];
$field = $args['field'];
$pos = strrpos($name, '.');
$part = $pos ? substr($name, 0, $pos) : $name;
if(preg_match('/data:image\/([^;]+);base64,(.*)/i', $bits, $matches)){
$bits = base64_decode(trim($matches[2]));
$name = $part.'.'.$matches[1];
}
$upload = wp_upload_bits($name, null, $bits);
$error = self::is_error($upload);
if($error){
return $error;
}
if($args['media']){
$id = self::add_to_media($upload, $part, $args['post_id']);
if(is_wp_error($id) || $field == 'id'){
return $id;
}
}
return $upload[$field];
}
public static function download_url($url, $name='', $media=true, $post_id=0){
$id = self::get_id_by_meta($url, 'source_url');
$args = self::parse_args($name, $media, $post_id);
$name = $args['name'];
$field = $args['field'];
if($id){
return self::convert($id, 'id', $field);
}
$tmp_file = download_url($url);
if(is_wp_error($tmp_file)){
return $tmp_file;
}
if(!$name){
$type = wp_get_image_mime($tmp_file);
$name = md5($url).'.'.(explode('/', $type)[1]);
}
$file = ['name'=>$name, 'tmp_name'=>$tmp_file];
if($args['media']){
$id = media_handle_sideload($file, $args['post_id']);
if(is_wp_error($id)){
@unlink($tmp_file);
return $id;
}
update_post_meta($id, 'source_url', $url);
return self::convert($id, 'id', $field);
}else{
$upload = self::upload($file);
return is_wp_error($upload) ? $upload : $upload[$field];
}
}
public static function scandir($dir, $callback=null){
$files = [];
foreach(scandir($dir) as $file){
if($file == '.' || $file == '..'){
continue;
}
$file = $dir.'/'.$file;
$files = array_merge($files, (is_dir($file) ? self::scandir($file) : [$file]));
}
if($callback && is_callable($callback)){
$output = [];
foreach($files as $file){
$callback($file, $output);
}
return $output;
}
return $files;
}
public static function convert($value, $from='path', $to='file'){
if($from == 'id'){
if($value && get_post_type($value) == 'attachment'){
if($to == 'id'){
return $value;
}elseif($to == 'file'){
return get_attached_file($value);
}elseif($to == 'url'){
return wp_get_attachment_url($value);
}elseif($to == 'size'){
$data = wp_get_attachment_metadata($value);
return $data ? wp_array_slice_assoc($data, ['width', 'height']) : [];
}
}
return null;
}
$dir = wp_get_upload_dir();
if($from == 'path'){
$path = $value;
}else{
if($from == 'url'){
$value = parse_url($value, PHP_URL_PATH);
$base = parse_url($dir['baseurl'], PHP_URL_PATH);
}elseif($from == 'file'){
$base = $dir['basedir'];
}
if(!str_starts_with($value, $base)){
return null;
}
$path = wpjam_remove_prefix($value, $base);
}
if($to == 'path'){
return $path;
}elseif($to == 'file'){
return $dir['basedir'].$path;
}elseif($to == 'url'){
return $dir['baseurl'].$path;
}elseif($to == 'size'){
$file = $dir['basedir'].$path;
$size = file_exists($file) ? wp_getimagesize($file) : [];
if($size){
return ['width'=>$size[0], 'height'=>$size[1]];
}
}
$id = self::get_id_by_meta($path);
return $id ? self::convert($id, 'id', $to) : null;
}
public static function get_id_by_meta($value, $key='_wp_attached_file'){
if($key == '_wp_attached_file'){
$value = ltrim($value, '/');
}
$meta = wpjam_get_by_meta('post', $key, $value);
if($meta){
$id = current($meta)['post_id'];
if(get_post_type($id) == 'attachment'){
return $id;
}
}
return '';
}
private static function add_to_media($file, $post_id=0){
if(is_array($file)){
$upload = $file;
$file = $upload['file'] ?? '';
$url = $upload['url'] ?? '';
$type = $upload['type'] ?? '';
}else{
$url = $type = '';
}
if(!$file){
return;
}
$id = self::convert($file, 'file', 'id');
if($id){
return $id;
}
$url = $url ?: self::convert($file, 'file', 'url');
$type = $type ?: mime_content_type($file);
if(!$url){
return;
}
require_once ABSPATH.'wp-admin/includes/image.php';
$title = preg_replace('/\.[^.]+$/', '', wp_basename($file));
$content = '';
$image_meta = wp_read_image_metadata($file);
if($image_meta ) {
if(trim($image_meta['title']) && !is_numeric(sanitize_title($image_meta['title']))){
$title = $image_meta['title'];
}
if(trim($image_meta['caption'])){
$content = $image_meta['caption'];
}
}
$id = wp_insert_attachment([
'post_title' => $title,
'post_content' => $content,
'post_parent' => $post_id,
'post_mime_type' => $type,
'guid' => $url,
], $file, $post_id, true);
if(!is_wp_error($id)){
wp_update_attachment_metadata($id, wp_generate_attachment_metadata($id, $file));
}
return $id;
}
private static function is_error($upload){
if(isset($upload['error']) && $upload['error'] !== false){
return new WP_Error('upload_error', $upload['error']);
}
}
private static function parse_args($name, $media=true, $post_id=0){
$args = is_array($name) ? wp_parse_args($name, [
'name' => '',
'media' => false,
'post_id' => 0,
]) : [
'name' => $name,
'media' => $media,
'post_id' => $post_id,
];
if(empty($args['field'])){
$args['field'] = $args['media'] ? 'id' : 'file';
}
return $args;
}
// $size, $ratio
// $size, $ratio, [$max_width, $max_height]
// $size, [$max_width, $max_height]
public static function parse_size($size, ...$args){
$ratio = 1;
$max = [0, 0];
if($args){
if(is_array($args[0])){
$max = array_replace($max, $args[0]);
}else{
$ratio = $args[0];
if(isset($args[1]) && is_array($args[1])){
$max = array_replace($max, $args[1]);
}
}
}
if(is_array($size)){
if(wp_is_numeric_array($size)){
$size = ['width'=>($size[0] ?? 0), 'height'=>($size[1] ?? 0)];
}
$size['width'] = !empty($size['width']) ? ((int)$size['width'])*$ratio : 0;
$size['height'] = !empty($size['height']) ? ((int)$size['height'])*$ratio : 0;
$size['crop'] ??= $size['width'] && $size['height'];
}else{
$size = $size ? str_replace(['*','X'], 'x', $size) : '';
if(strpos($size, 'x') !== false){
$size = explode('x', $size);
$width = $size[0];
$height = $size[1];
$crop = true;
}elseif(is_numeric($size)){
$width = $size;
$height = 0;
}elseif($size == 'thumb' || $size == 'thumbnail'){
$width = get_option('thumbnail_size_w') ?: 100;
$height = get_option('thumbnail_size_h') ?: 100;
$crop = get_option('thumbnail_crop');
}elseif($size == 'medium'){
$width = get_option('medium_size_w') ?: 300;
$height = get_option('medium_size_h') ?: 300;
$crop = false;
}else{
if($size == 'medium_large'){
$width = get_option('medium_large_size_w');
$height = get_option('medium_large_size_h');
$crop = false;
}elseif($size == 'large'){
$width = get_option('large_size_w') ?: 1024;
$height = get_option('large_size_h') ?: 1024;
$crop = false;
}else{
$sizes = wp_get_additional_image_sizes();
if(isset($sizes[$size])){
$width = $sizes[$size]['width'];
$height = $sizes[$size]['height'];
$crop = $sizes[$size]['crop'];
}else{
$width = $height = 0;
}
}
if($width && !empty($GLOBALS['content_width'])){
$width = min($GLOBALS['content_width'] * $ratio, $width);
}
}
$size = [
'crop' => $crop ?? ($width && $height),
'width' => (int)$width * $ratio,
'height' => (int)$height * $ratio
];
}
if($max[0] && $max[1]){
if($size['width'] && $size['height']){
list($size['width'], $size['height']) = wp_constrain_dimensions($size['width'], $size['height'], $max[0], $max[1]);
}elseif($size['width']){
$size['width'] = $size['width'] < $max[0] ? $size['width'] : $max[0];
}else{
$size['height'] = $size['height'] < $max[1] ? $size['height'] : $max[1];
}
}
return $size;
}
public static function get_thumbnail($url, ...$args){
if(!$args){ // 1. 无参数
$args = [];
}elseif(count($args) == 1){
// 2. ['width'=>100, 'height'=>100] 标准版
// 3. [100,100]
// 4. 100x100
// 5. 100
$args = self::parse_size($args[0]);
}elseif(is_numeric($args[0])){
// 6. 100, 100, $crop=1
$args = [
'width' => $args[0] ?? 0,
'height' => $args[1] ?? 0,
'crop' => $args[2] ?? 1
];
}else{
// 7.【100,100], $crop=1
$args = array_merge(self::parse_size($args[0]), ['crop'=>$args[1] ?? 1]);
}
return apply_filters('wpjam_thumbnail', $url, $args);
}
public static function import($file, $columns=[]){
$parts = explode('.', $file);
$ext = end($parts);
$file = wp_get_upload_dir()['basedir'].$file;
if(!$file || !file_exists($file)){
return new WP_Error('file_not_exists', '文件不存在');
}
if($ext == 'csv'){
if(($handle = fopen($file, 'r')) !== false){
$indexes = [];
$i = 0;
while(($row = fgetcsv($handle)) !== false){
$i ++;
if($i == 1){
$encoding = mb_detect_encoding(implode('', $row), mb_list_encodings(), true);
}
if($encoding != 'UTF-8'){
$row = array_map(fn($v) => mb_convert_encoding($v, 'UTF-8', 'GBK'), $row);
}
if($i == 1){
$fn = fn($v)=> trim(trim($v), "\xEF\xBB\xBF");
$row = array_flip(array_map($fn, $row));
foreach(array_map($fn, $columns) as $key => $title){
if(isset($row[$title])){
$indexes[$key] = $row[$title];
}
}
}else{
$data[] = wpjam_map($indexes, fn($index)=> $row[$index]);
}
}
fclose($handle);
}
}else{
$data = file_get_contents($file);
if($ext == 'txt' && is_serialized($data)){
$data = maybe_unserialize($data);
}
}
unlink($file);
return $data ?? [];
}
public static function export($file, $data, $columns=[]){
$parts = explode('.', $file);
$ext = end($parts);
$handle = fopen('php://output', 'w');
header('Content-Disposition: attachment;filename='.$file);
header('Pragma: no-cache');
header('Expires: 0');
if($ext == 'csv'){
header('Content-Type: text/csv');
fwrite($handle, chr(0xEF).chr(0xBB).chr(0xBF));
if($columns){
fputcsv($handle, $columns);
array_walk($data, fn($item)=> fputcsv($handle, wpjam_map($columns, fn($v, $k)=> $item[$k] ?? '')));
}else{
array_walk($data, fn($item)=> fputcsv($handle, $item));
}
}elseif($ext == 'txt'){
header('Content-Type: text/plain');
fputs($handle, is_scalar($data) ? $data : maybe_serialize($data));
}
fclose($handle);
exit;
}
}
class WPJAM_Video{
public static function get_mp4($id_or_url){
if(filter_var($id_or_url, FILTER_VALIDATE_URL)){
if(preg_match('#http://www.miaopai.com/show/(.*?).htm#i',$id_or_url, $matches)){
return 'http://gslb.miaopai.com/stream/'.esc_attr($matches[1]).'.mp4';
}elseif(preg_match('#https://v.qq.com/x/page/(.*?).html#i',$id_or_url, $matches)){
return self::get_qqv_mp4($matches[1]);
}elseif(preg_match('#https://v.qq.com/x/cover/.*/(.*?).html#i',$id_or_url, $matches)){
return self::get_qqv_mp4($matches[1]);
}else{
return wpjam_zh_urlencode($id_or_url);
}
}else{
return self::get_qqv_mp4($id_or_url);
}
}
public static function get_qqv_id($id_or_url){
if(filter_var($id_or_url, FILTER_VALIDATE_URL)){
foreach([
'#https://v.qq.com/x/page/(.*?).html#i',
'#https://v.qq.com/x/cover/.*/(.*?).html#i'
] as $pattern){
if(preg_match($pattern,$id_or_url, $matches)){
return $matches[1];
}
}
return '';
}
return $id_or_url;
}
public static function get_qqv_mp4($vid, $cache=true){
if(strlen($vid) > 20){
return new WP_Error('error', '无效的腾讯视频');
}
if($cache){
return wpjam_transient('qqv_mp4:'.$vid, fn()=> self::get_qqv_mp4($vid, false), HOUR_IN_SECONDS*6);
}
$response = wpjam_remote_request('http://vv.video.qq.com/getinfo?otype=json&platform=11001&vid='.$vid, ['timeout'=>4]);
if(is_wp_error($response)){
return $response;
}
$response = trim(substr($response, strpos($response, '{')),';');
$response = wpjam_try('wpjam_json_decode', $response);
if(empty($response['vl'])){
return new WP_Error('error', '腾讯视频不存在或者为收费视频!');
}
$u = $response['vl']['vi'][0];
$p0 = $u['ul']['ui'][0]['url'];
$p1 = $u['fn'];
$p2 = $u['fvkey'];
return $p0.$p1.'?vkey='.$p2;
}
public static function render($content, $attr){
if(preg_match('#//www.bilibili.com/video/(BV[a-zA-Z0-9]+)#i',$content, $matches)){
$src = 'https://player.bilibili.com/player.html?bvid='.esc_attr($matches[1]);
}elseif(preg_match('#//v.qq.com/(.*)iframe/(player|preview).html\?vid=(.+)#i',$content, $matches)){
$src = 'https://v.qq.com/'.esc_attr($matches[1]).'iframe/player.html?vid='.esc_attr($matches[3]);
}elseif(preg_match('#//v.youku.com/v_show/id_(.*?).html#i',$content, $matches)){
$src = 'https://player.youku.com/embed/'.esc_attr($matches[1]);
}elseif(preg_match('#//www.tudou.com/programs/view/(.*?)#i',$content, $matches)){
$src = 'https://www.tudou.com/programs/view/html5embed.action?code='.esc_attr($matches[1]);
}elseif(preg_match('#//tv.sohu.com/upload/static/share/share_play.html\#(.+)#i',$content, $matches)){
$src = 'https://tv.sohu.com/upload/static/share/share_play.html#'.esc_attr($matches[1]);
}elseif(preg_match('#//www.youtube.com/watch\?v=([a-zA-Z0-9\_]+)#i',$content, $matches)){
$src = 'https://www.youtube.com/embed/'.esc_attr($matches[1]);
}
if(!empty($src)){
$attr = shortcode_atts(['width'=>0, 'height'=>0], $attr);
if($attr['width'] || $attr['height']){
$attr_string = image_hwstring($attr['width'], $attr['height']).' style="aspect-ratio:4/3;"';
}else{
$attr_string = 'style="width:100%; aspect-ratio:4/3;"';
}
return '<iframe class="wpjam_video" '.$attr_string.' src="'.$src.'" scrolling="no" border="0" frameborder="no" framespacing="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>';
}
}
}
class IP{
private static $ip = null;
private static $fp = null;
private static $offset = null;
private static $index = null;
private static $cached = [];
public static function find($ip){
if (empty( $ip ) === true) {
return 'N/A';
}
$nip = gethostbyname($ip);
$ipdot = explode('.', $nip);
if ($ipdot[0] < 0 || $ipdot[0] > 255 || count($ipdot) !== 4) {
return 'N/A';
}
if (isset( self::$cached[$nip] ) === true) {
return self::$cached[$nip];
}
if (self::$fp === null) {
self::init();
}
$nip2 = pack('N', ip2long($nip));
$tmp_offset = (int) $ipdot[0] * 4;
$start = unpack('Vlen',
self::$index[$tmp_offset].self::$index[$tmp_offset + 1].self::$index[$tmp_offset + 2].self::$index[$tmp_offset + 3]);
$index_offset = $index_length = null;
$max_comp_len = self::$offset['len'] - 1024 - 4;
for ($start = $start['len'] * 8 + 1024; $start < $max_comp_len; $start += 8) {
if (self::$index[$start].self::$index[$start+1].self::$index[$start+2].self::$index[$start+3] >= $nip2) {
$index_offset = unpack('Vlen',
self::$index[$start+4].self::$index[$start+5].self::$index[$start+6]."\x0");
$index_length = unpack('Clen', self::$index[$start+7]);
break;
}
}
if ($index_offset === null) {
return 'N/A';
}
fseek(self::$fp, self::$offset['len'] + $index_offset['len'] - 1024);
self::$cached[$nip] = explode("\t", fread(self::$fp, $index_length['len']));
return self::$cached[$nip];
}
private static function init(){
if(self::$fp === null){
self::$ip = new self();
self::$fp = fopen(WP_CONTENT_DIR.'/uploads/17monipdb.dat', 'rb');
if (self::$fp === false) {
throw new Exception('Invalid 17monipdb.dat file!');
}
self::$offset = unpack('Nlen', fread(self::$fp, 4));
if (self::$offset['len'] < 4) {
throw new Exception('Invalid 17monipdb.dat file!');
}
self::$index = fread(self::$fp, self::$offset['len'] - 4);
}
}
public function __destruct(){
if(self::$fp !== null){
fclose(self::$fp);
}
}
}