File: //proc/self/cwd/wp-content/mu-plugins/extendify.php
<?php
define('EXTENDIFY_PARTNER_ID', 'tj1390ksf');
define('EXTENDIFY_SHOW_ONBOARDING', get_option('stylesheet', '') === 'extendable');
define('EXTENDIFY_SITE_LICENSE', '3458290385902375729843');
define('EXTENDIFY_INSIGHTS_URL', 'https://insights.extendify.com');
/*************************************
*! Do not make changes below this line
*************************************/
/** Method to prefetch relevant branding information */
if (!get_transient('extendify_partner_data')) {
set_transient('extendify_partner_data', current_time('timestamp'), MONTH_IN_SECONDS);
try {
$extPartnerData = @json_decode(@wp_remote_retrieve_body(@wp_remote_get(
'https://dashboard.extendify.com/api/onboarding/partner-data/?partner=' . EXTENDIFY_PARTNER_ID,
[
'headers' => ['Accept' => 'application/json'],
'timeout' => 1,
]
)), true);
// We don't want this to show warnings
@update_option('extendify_partner_data', [
'foregroundColor' => $extPartnerData['data']['foregroundColor'],
'backgroundColor' => $extPartnerData['data']['backgroundColor'],
'logo' => $extPartnerData['data']['logo'],
]);
} catch (Exception $e) {
// Fail without error and just try again in a month
}
}
/** Method to register a site with Extendify */
add_action('admin_init', function () {
// If not enabled, don't do anything
if (!defined('EXTENDIFY_INSIGHTS_URL')) {
return;
}
// Only register if not already registered
if (get_option('extendify_site_id', false)) {
return;
}
// Don't try too often.
if (get_transient('extendify_registering')) {
return;
}
set_transient('extendify_registering', true, DAY_IN_SECONDS);
// Attempt to find when the site was created
// by checking the date on the first post.
// This is only reliable on new sites.
$firstPost = get_posts([
'order' => 'ASC',
'posts_per_page' => -1,
'post_status' => ['trash', 'publish', 'any']
]);
if (isset($firstPost[0]->post_date_gmt)) {
$createdAt = $firstPost[0]->post_date_gmt;
}
try {
// Send request for Extendify site id
$extendifySite = wp_remote_post(
apply_filters('extendify_register_url', trailingslashit(EXTENDIFY_INSIGHTS_URL) . 'api/v1/register'),
[
'headers' => [
'Content-Type' => 'application/json',
'X-Extendify' => true,
],
'timeout' => 1,
'body' => wp_json_encode([
'launch' => defined('EXTENDIFY_SHOW_ONBOARDING')
? EXTENDIFY_SHOW_ONBOARDING
: false,
'siteCreatedAt' => $createdAt,
]),
]
);
$extendifySite = wp_remote_retrieve_body($extendifySite);
$extendifySite = json_decode($extendifySite, true);
if (isset($extendifySite['siteId'])) {
update_option('extendify_site_id', $extendifySite['siteId']);
if (class_exists('ExtendifyInsights')) {
(new ExtendifyInsights)->run();
}
}
} catch (Exception $e) {
// Do nothing
}
});
/** Insights */
if (!wp_next_scheduled('extendify_insights')) {
if (get_option('extendify_insights_stop', false)) {
return;
}
wp_schedule_event(current_time('timestamp'), 'daily', 'extendify_insights');
}
add_action('init', function () {
add_action('extendify_insights', [new ExtendifyInsights, 'run']);
});
class ExtendifyInsights
{
public $domain;
public function __construct()
{
$url = trailingslashit(EXTENDIFY_INSIGHTS_URL) . 'api/v1/insights';
$this->domain = defined('EXTENDIFY_INSIGHTS_URL')
? apply_filters('extendify_insights_url', $url)
: null;
$this->showRestEndpoint();
$this->trackLogins();
}
public function run()
{
if (!$this->domain) {
return;
}
if (!$siteId = get_option('extendify_site_id', false)) {
return;
}
$data = apply_filters('extendify_insights_data', [
'site' => $this->getSiteData(),
'pages' => $this->getPageData(),
'plugins' => get_option('active_plugins'),
]);
$res = wp_remote_post($this->domain, [
'headers' => [
'Content-Type' => 'application/json',
'X-Extendify-Site-Id' => $siteId,
],
'timeout' => 1,
'body' => wp_json_encode($data),
]);
$response = json_decode(wp_remote_retrieve_body($res));
if (isset($response->stop)) {
update_option('extendify_insights_stop', true);
wp_clear_scheduled_hook('extendify_insights');
}
}
private function getSiteData()
{
$partner = defined('EXTENDIFY_PARTNER_ID')
? EXTENDIFY_PARTNER_ID
: null;
if (!$partner && isset($GLOBALS['extendify_sdk_partner'])) {
$partner = $GLOBALS['extendify_sdk_partner'];
};
$devBuild = defined('EXTENDIFY_PATH')
? @is_readable(EXTENDIFY_PATH . 'public/build/.devbuild')
: null;
$siteType = get_option('extendify_siteType', '');
$siteType = isset($siteType['slug']) ? $siteType['slug'] : '';
$media = get_posts([
'post_type' => 'attachment',
'posts_per_page' => -1,
'post_parent' => 0,
]);
$users = get_users();
$adminUsers = array_filter($users, function ($user) {
return $user->has_cap('manage_options');
});
try {
$home = @wp_remote_retrieve_body(@wp_remote_get(get_bloginfo('url'), [
'timeout' => 1,
]));
} catch (Exception $e) {
$home = '';
}
return [
'title' => get_bloginfo('name'),
'description' => get_bloginfo('description'),
'url' => get_bloginfo('url'),
'restEndpoint' => rest_url(),
'adminUrl' => admin_url(),
'adminUsers' => count($adminUsers),
'users' => count($users),
'homeUrls' => $this->getUrlsFromContent(preg_replace('#<head>(.*?)</head>#is', '', $home)),
'mediaLibraryCount' => count($media),
'wpVersion' => get_bloginfo('version'),
'language' => get_bloginfo('language'),
'siteLogo' => get_option('site_logo', 0),
'loginTotals' => get_option('extendify_login_count', 0),
'siteType' => $siteType,
'theme' => get_option('stylesheet', ''),
'partner' => $partner,
'isDev' => $devBuild,
];
}
private function getPageData()
{
$pages = get_posts([
'posts_per_page' => -1,
'post_status' => ['trash', 'publish', 'any'],
'post_type' => 'page'
]);
$pageData = array_map(function ($page) {
$revisions = wp_get_post_revisions($page->ID, ['posts_per_page' => -1]);
return [
'ID' => $page->ID,
'usedLaunch' => filter_var(get_post_meta($page->ID, 'made_with_extendify_launch', true), FILTER_VALIDATE_BOOLEAN),
'name' => $page->post_name,
'title' => $page->post_title,
'status' => $page->post_status,
'date' => $page->post_date_gmt,
'hasExtendifyPattern' => strpos($page->post_content, 'ext-') !== false,
'hasUnsplashImage' => strpos($page->post_content, 'unsplash') !== false,
'template' => get_page_template_slug($page->ID),
'pageUrls' => $this->getUrlsFromContent($page->post_content),
'pageEmails' => $this->getEmailsFromContent($page->post_content),
'revisions' => array_map(function ($pageRevision) {
return [
'ID' => $pageRevision->ID,
'name' => $pageRevision->post_name,
'status' => $pageRevision->post_status,
'title' => $pageRevision->post_title,
'date' => $pageRevision->post_date_gmt,
'hasExtendifyPattern' => strpos($pageRevision->post_content, 'ext-') !== false,
'hasUnsplashImage' => strpos($pageRevision->post_content, 'unsplash') !== false,
'pageUrls' => $this->getUrlsFromContent($pageRevision->post_content),
'pageEmails' => $this->getEmailsFromContent($pageRevision->post_content),
];
}, $revisions)
];
return $page;
}, $pages);
// Check whether the page data matches our last check
// if it does, we can just not send the same data over
$pageDataLastTime = get_option('extendify_page_data_last_time', []);
if ($pageData === $pageDataLastTime) {
return;
}
update_option('extendify_page_data_last_time', $pageData);
return $pageData;
}
private function showRestEndpoint() {
add_filter('rest_route_data', function ($available) {
unset($available['/extendify-insights']);
return $available;
});
@add_filter('rest_index', function ($response) {
try {
$response->data['routes'] = @array_filter($response->data['routes'], function ($key) {
return strpos($key, 'extendify-insights') === false;
}, ARRAY_FILTER_USE_KEY);
$response->data['namespaces'] = @array_values(
@array_filter($response->data['namespaces'], function ($value) {
return strpos($value, 'extendify-insights') === false;
})
);
} catch (Exception $e) {
// Do nothing
}
return $response;
});
@add_action('rest_api_init', function () {
@register_rest_route('extendify-insights', 'active', [
'methods' => 'GET',
'permission_callback' => '__return_true',
'show_in_index' => false,
'callback' => function($request) {
// Just to hide it from anyone fuzzing endpoints
if ($request->get_param('token') === 'o9vbeXa88iwuYvzTQQcQ6ZCfXZny1zYPKaz3SaeL') {
return true;
}
// Return the same response WP uses when the route isnt registered
return new WP_Error(
'rest_no_route',
'No route was found matching the URL and request method.',
['status' => 404]
);
},
]);
});
}
private function trackLogins() {
add_filter('login_redirect', function ($url) {
$count = get_option('extendify_login_count', 0);
update_option('extendify_login_count', intval($count) + 1);
return $url;
});
}
private function getUrlsFromContent($content) {
preg_match_all('#\bhttps?://[^,\s()<>]+(?:\([\w\d]+\)|([^,[:punct:]\s]|/))#', $content, $urls);
return array_values(array_unique(
array_filter($urls[0], function($url) {
return !preg_match("/w3\.org|schema\.org|wordpress.org|w.org|wp-json|unsplash|\.(svg|png|jpe?g|js|css|xml|php)/", $url);
})
));
}
private function getEmailsFromContent($content) {
preg_match_all('#\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b#i', $content, $emails);
return array_values(array_unique($emails[0]));
}
}