Plugin Directory

Changeset 3005252


Ignore:
Timestamp:
12/04/2023 06:25:01 PM (16 months ago)
Author:
unbouncewordpress
Message:

Releasing version 1.1.1

Location:
unbounce
Files:
22 edited
1 copied

Legend:

Unmodified
Added
Removed
  • unbounce/tags/1.1.1/UBConfig.php

    r2953445 r3005252  
    33class UBConfig
    44{
     5    const DYNAMIC_CONFIG_DEFAULT_TIMEOUT = 86400;
     6    const DYNAMIC_CONFIG_FAILURE_TIMEOUT = 1200;
    57
    68    const UB_PLUGIN_NAME           = 'ub-wordpress';
    79    const UB_CACHE_TIMEOUT_ENV_KEY = 'UB_WP_ROUTES_CACHE_EXP';
    8     const UB_USER_AGENT            = 'Unbounce WP Plugin 1.1.0';
    9     const UB_VERSION               = '1.1.0';
     10    const UB_USER_AGENT            = 'Unbounce WP Plugin 1.1.1';
     11    const UB_VERSION               = '1.1.1';
    1012
    1113    // WP Admin Pages
     
    1517
    1618    // Option keys
     19    const UB_DYNAMIC_CONFIG_CACHE_KEY   = 'ub-dynamic-config-cache';
    1720    const UB_ROUTES_CACHE_KEY        = 'ub-route-cache';
    1821    const UB_PAGE_SERVER_DOMAIN_KEY  = 'ub-page-server-domain';
     22    const UB_DYNAMIC_CONFIG_DOMAIN_KEY = 'ub-dynamic-config-domain';
    1923    const UB_API_URL_KEY             = 'ub-api-url';
    2024    const UB_API_CLIENT_ID_KEY       = 'ub-api-client-id';
     
    2327    const UB_USER_ID_KEY             = 'ub-user-id';
    2428    const UB_DOMAIN_ID_KEY           = 'ub-domain-id';
     29    const UB_DOMAIN_UUID_KEY         = 'ub-domain-uuid';
    2530    const UB_CLIENT_ID_KEY           = 'ub-client-id';
    2631    const UB_PROXY_ERROR_MESSAGE_KEY = 'ub-proxy-error-message';
     
    3338    const UB_RESPONSE_HEADERS_FORWARDED_KEY = 'ub-response-headers-forwarded';
    3439
     40    const UB_DEFAULT_REQUEST_HEADER_ALLOW = '/^(?:Accept|Content-Type|Referer|User-Agent|If-None-Match|Host|X-Forwarded-.+|X-Proxied-For|X-Ub-Wordpress-.+|Cookie|Accept-Language|Origin|Access-Control-Request-Headers|Access-Control-Request-Method)$/i';
     41    const UB_DEFAULT_REQUEST_HEADER_ADD = array();
     42    const UB_DEFAULT_REQUEST_COOKIE_ALLOW = array('ubvs', 'ubpv', 'ubvt', 'hubspotutk');
     43    const UB_DEFAULT_RESPONSE_HEADER_ALLOW = array(
     44        'content-length',
     45        'content-location',
     46        'content-type',
     47        'location',
     48        'link',
     49        'set-cookie',
     50        'cf-ray',
     51        'cf-cache-status',
     52        'access-control-allow-origin',
     53        'access-control-allow-credentials',
     54        'access-control-allow-headers',
     55        'access-control-max-age'
     56    );
     57
    3558    public static function ub_option_defaults()
    3659    {
     
    3861        // Arrays are not allowed in class constants, so use a function
    3962        return array(
     63            UBConfig::UB_DYNAMIC_CONFIG_CACHE_KEY => array(
     64                'request_header_allow' => UBConfig::UB_DEFAULT_REQUEST_HEADER_ALLOW,
     65                'request_header_add' => UBConfig::UB_DEFAULT_REQUEST_HEADER_ADD,
     66                'request_cookie_allow' => UBConfig::UB_DEFAULT_REQUEST_COOKIE_ALLOW,
     67                'response_header_allow' => UBConfig::UB_DEFAULT_RESPONSE_HEADER_ALLOW
     68            ),
    4069            UBConfig::UB_ROUTES_CACHE_KEY => array(),
    4170            UBConfig::UB_PAGE_SERVER_DOMAIN_KEY => UBConfig::default_page_server_domain(),
     71            UBConfig::UB_DYNAMIC_CONFIG_DOMAIN_KEY => UBConfig::default_dynamic_config_retrieval_domain(),
    4272            UBConfig::UB_API_URL_KEY => UBConfig::default_api_url(),
    4373            UBConfig::UB_API_CLIENT_ID_KEY => UBConfig::default_api_client_id(),
     
    4676            UBConfig::UB_USER_ID_KEY => '',
    4777            UBConfig::UB_DOMAIN_ID_KEY => '',
     78            UBConfig::UB_DOMAIN_UUID_KEY => '',
    4879            UBConfig::UB_CLIENT_ID_KEY => '',
    4980            UBConfig::UB_PROXY_ERROR_MESSAGE_KEY => '',
     
    76107    }
    77108
     109    public static function default_dynamic_config_retrieval_domain()
     110    {
     111        $domain = getenv('UB_DYNAMIC_CONFIG_DOMAIN');
     112        return $domain ? $domain : 'wp-config.unbouncepages.com';
     113    }
     114
    78115    public static function default_api_url()
    79116    {
     
    96133    public static function page_server_domain()
    97134    {
    98         return get_option(UBConfig::UB_PAGE_SERVER_DOMAIN_KEY, UBConfig::default_page_server_domain());
     135        $domain = get_option(UBConfig::UB_PAGE_SERVER_DOMAIN_KEY, UBConfig::default_page_server_domain());
     136
     137        return UBConfig::add_domain_uuid_subdomain($domain);
     138    }
     139
     140    public static function dynamic_config_retrieval_domain()
     141    {
     142        $domain = get_option(UBConfig::UB_DYNAMIC_CONFIG_DOMAIN_KEY, UBConfig::default_dynamic_config_retrieval_domain());
     143
     144        return UBConfig::add_domain_uuid_subdomain($domain);
     145    }
     146
     147    private static function add_domain_uuid_subdomain($domain)
     148    {
     149        $subdomain = get_option(UBConfig::UB_DOMAIN_UUID_KEY);
     150   
     151        if ($subdomain) {
     152            $domain = $subdomain . '.' . $domain;
     153        }
     154   
     155        return $domain;
    99156    }
    100157
     
    131188    public static function create_none_response()
    132189    {
    133         return array(array('status' => 'NONE'), null, null, null);
     190        return array(array('status' => 'NONE'));
    134191    }
    135192
    136193    public static function create_same_response($etag, $max_age)
    137194    {
    138         return array(array('status' => 'SAME'), $etag, $max_age, null);
    139     }
    140 
    141     public static function create_new_response($etag, $max_age, $proxyable_url_set)
     195        return array(array('status' => 'SAME'), $etag, $max_age);
     196    }
     197
     198    public static function create_new_response_proxyable_url_set($etag, $max_age, $proxyable_url_set)
    142199    {
    143200        return array(array('status' => 'NEW'), $etag, $max_age, $proxyable_url_set);
    144201    }
    145202
     203    public static function create_new_response_dynamic_config($etag, $max_age, $request_header_allow, $request_header_add, $request_cookie_allow, $response_header_allow)
     204    {
     205        return array(array('status' => 'NEW'), $etag, $max_age, $request_header_allow, $request_header_add, $request_cookie_allow, $response_header_allow);
     206    }
     207
    146208    public static function create_failure_response($failure_message)
    147209    {
    148210        return array(array('status' => 'FAILURE',
    149                        'failure_message' => $failure_message),
    150                  null, null, null);
     211                       'failure_message' => $failure_message));
    151212    }
    152213
     
    187248        try {
    188249            $url = 'https://' . $ps_domain . '/sitemap.xml';
    189             $curl = curl_init();
    190             $curl_options = array(
    191                 CURLOPT_URL => $url,
    192                 CURLOPT_CUSTOMREQUEST => "GET",
    193                 CURLOPT_HEADER => true,
    194                 CURLOPT_USERAGENT => UBConfig::UB_USER_AGENT,
    195                 CURLOPT_HTTPHEADER => UBHTTP::convert_headers_to_curl(
    196                     array(
    197                         'x-forwarded-host' => $domain,
    198                         'if-none-match' => $etag
    199                     )
    200                 ),
    201                 CURLOPT_RETURNTRANSFER => true,
    202                 CURLOPT_FOLLOWLOCATION => false,
    203                 CURLOPT_TIMEOUT => 5
    204             );
    205 
     250           
    206251            UBLogger::debug("Retrieving routes from '$url', etag: '$etag', host: '$domain'");
    207252
    208             curl_setopt_array($curl, $curl_options);
    209             $data = curl_exec($curl);
    210             $http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
    211             $header_size = strlen($data) - curl_getinfo($curl, CURLINFO_SIZE_DOWNLOAD);
    212             $curl_error = null;
    213             $etag = null;
    214             $max_age = null;
    215 
    216             // when having an CURL error, http_code is 0
    217             if ($http_code == 0) {
    218                   $curl_error = curl_error($curl);
    219             }
    220 
    221             curl_close($curl);
    222 
    223             $headers = substr($data, 0, $header_size);
    224 
    225             $matches = array();
    226             $does_match = preg_match('/ETag: (\S+)/is', $headers, $matches);
    227             if ($does_match) {
    228                   $etag = $matches[1];
    229             }
    230 
    231             $matches = array();
    232             $does_match = preg_match('/Cache-Control: max-age=(\S+)/is', $headers, $matches);
    233             if ($does_match) {
    234                   $max_age = $matches[1];
    235             }
     253            list($data, $http_code, $header_size, $curl_error) = UBConfig::make_curl_request($url, $domain, $etag);
     254            list($etag, $max_age) = UBConfig::process_headers($data, $header_size);
    236255
    237256            if ($http_code == 200) {
     
    241260                if ($success) {
    242261                    UBLogger::debug("Retrieved new routes, HTTP code: '$http_code'");
    243                     return UBConfig::create_new_response($etag, $max_age, $result);
     262                    return UBConfig::create_new_response_proxyable_url_set($etag, $max_age, $result);
    244263                } else {
    245264                    $errors = join(', ', $result);
     
    249268                }
    250269            }
    251             if ($http_code == 304) {
    252                   UBLogger::debug("Routes have not changed, HTTP code: '$http_code'");
    253                   return UBConfig::create_same_response($etag, $max_age);
    254             }
    255             if ($http_code == 404) {
    256                   UBLogger::debug("No routes to retrieve, HTTP code: '$http_code'");
    257                   return UBConfig::create_none_response();
    258             } else {
    259                   $failure_message = "An error occurred while retrieving routes;
    260                     HTTP code: '$http_code';
    261                     Error: " . $curl_error;
    262                   UBLogger::warning($failure_message);
    263                   return UBConfig::create_failure_response($failure_message);
    264             }
     270
     271            return UBConfig::handle_non_200_http_response($http_code, $etag, $max_age, $curl_error, 'routes');
    265272        } catch (Exception $e) {
    266273            $failure_message = "An error occurred while retrieving routes; Error: " . $e;
     
    323330        $cache_max_time_default = 10;
    324331
    325         $ps_domain = get_option(UBConfig::UB_PAGE_SERVER_DOMAIN_KEY, UBConfig::default_page_server_domain());
     332        $ps_domain = UBConfig::page_server_domain();
     333                     
    326334        $domains_info = get_option(UBConfig::UB_ROUTES_CACHE_KEY, array());
    327335
     
    396404    }
    397405
     406    // We are using a fetched dynamic config to retrieve information
     407    // such that we decide what request headers to allow and add,
     408    // as well as what response headers and request cookies to allow.
     409    public static function read_unbounce_dynamic_config($domain)
     410    {
     411        // Check if curl is installed to prevent fatal error
     412        if (!UBDiagnostics::is_curl_installed()) {
     413            return array();
     414        }
     415
     416        $cache_max_time_default = UBConfig::DYNAMIC_CONFIG_DEFAULT_TIMEOUT;
     417        $dynamic_config = get_option(UBConfig::UB_DYNAMIC_CONFIG_CACHE_KEY, array());
     418
     419        if (!is_array($dynamic_config)) {
     420            $dynamic_config = array();
     421        }
     422
     423        $dynamic_config_fetched_at = UBUtil::array_fetch($dynamic_config, 'fetched_at');
     424        $dynamic_config_cache_timeout = UBUtil::array_fetch($dynamic_config, 'cache_timeout');
     425        $dynamic_config_etag = UBUtil::array_fetch($dynamic_config, 'etag');
     426
     427        $cache_max_time = is_null($dynamic_config_cache_timeout) ? $cache_max_time_default : $dynamic_config_cache_timeout;
     428
     429        // regardless of dynamic_config_cache_timeout being set, if the last fetch failed or returned a 404, we want to try again in 20 minutes
     430        if ($dynamic_config['last_status'] === 'FAILURE' || $dynamic_config['last_status'] === 'NONE') {
     431            $cache_max_time = UBConfig::DYNAMIC_CONFIG_FAILURE_TIMEOUT;
     432        }
     433
     434        $current_time = time();
     435
     436        if (is_null($dynamic_config_fetched_at) ||
     437            ($current_time - $dynamic_config_fetched_at > $cache_max_time)) {
     438            try {
     439                $can_fetch = UBUtil::get_lock();
     440                UBLogger::debug('Locking: ' . $can_fetch);
     441
     442                if ($can_fetch) {
     443                    $result_array = UBConfig::fetch_dynamic_config($domain, $dynamic_config_etag);
     444                    list($routes_status, $etag, $max_age, $request_header_allow_new, $request_header_add_new, $request_cookie_allow_new, $response_header_allow_new) = $result_array;
     445
     446                    if ($routes_status['status'] === 'NEW') {
     447                        $dynamic_config['request_header_allow'] = $request_header_allow_new;
     448                        $dynamic_config['request_header_add'] = $request_header_add_new;
     449                        $dynamic_config['request_cookie_allow'] = $request_cookie_allow_new;
     450                        $dynamic_config['response_header_allow'] = $response_header_allow_new;
     451                        $dynamic_config['etag'] = $etag;
     452                        $dynamic_config['cache_timeout'] = $max_age;
     453                    } elseif ($routes_status['status'] === 'SAME') {
     454                        // Just extend the cache
     455                        $dynamic_config['cache_timeout'] = $max_age;
     456                    } elseif ($routes_status['status'] === 'FAILURE' || $routes_status['status'] === 'NONE') {
     457                        UBLogger::warning('Not updating the dynamic config: Fetching failed or 404 was returned');
     458                    } else {
     459                        UBLogger::warning("Unknown response from dynamic config fetcher: '$routes_status'");
     460                    }
     461
     462                    $dynamic_config['fetched_at'] = $current_time;
     463                    $dynamic_config['last_status'] = $routes_status['status'];
     464
     465                    if ($routes_status['status'] === 'FAILURE') {
     466                        $dynamic_config['failure_message'] = $routes_status['failure_message'];
     467                    }
     468
     469                    update_option(UBConfig::UB_DYNAMIC_CONFIG_CACHE_KEY, $dynamic_config, false);
     470                }
     471            } catch (Exception $e) {
     472                UBLogger::warning('Could not update dynamic config: ' . $e);
     473                $dynamic_config['last_status'] = 'FAILURE';
     474                $dynamic_config['failure_message'] = $e->getMessage();
     475                update_option(UBConfig::UB_DYNAMIC_CONFIG_CACHE_KEY, $dynamic_config, false);
     476            }
     477
     478            $release_result = UBUtil::release_lock();
     479            UBLogger::debug('Unlocking: ' . $release_result);
     480        }
     481       
     482        return UBUtil::array_select_by_key(
     483            $dynamic_config,
     484            array('request_header_allow', 'request_header_add', 'request_cookie_allow', 'response_header_allow')
     485        );
     486    }
     487
     488    private static function make_curl_request($url, $domain, $etag)
     489    {
     490        $curl = curl_init();
     491        $curl_options = array(
     492            CURLOPT_URL => $url,
     493            CURLOPT_CUSTOMREQUEST => "GET",
     494            CURLOPT_HEADER => true,
     495            CURLOPT_USERAGENT => UBConfig::UB_USER_AGENT,
     496            CURLOPT_HTTPHEADER => UBHTTP::convert_headers_to_curl(
     497                array(
     498                    'x-forwarded-host' => $domain,
     499                    'if-none-match' => $etag
     500                )
     501            ),
     502            CURLOPT_RETURNTRANSFER => true,
     503            CURLOPT_FOLLOWLOCATION => false,
     504            CURLOPT_TIMEOUT => 5
     505        );
     506        curl_setopt_array($curl, $curl_options);
     507       
     508        $data = curl_exec($curl);
     509        $http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
     510        $header_size = strlen($data) - curl_getinfo($curl, CURLINFO_SIZE_DOWNLOAD);
     511        $curl_error = $http_code == 0 ? curl_error($curl) : null;
     512       
     513        curl_close($curl);
     514       
     515        return array($data, $http_code, $header_size, $curl_error);
     516    }
     517
     518    private static function process_headers($data, $header_size)
     519    {
     520        $headers = substr($data, 0, $header_size);
     521        $etag = null;
     522        $max_age = null;
     523   
     524        $matches = array();
     525        $does_match = preg_match('/ETag: (\S+)/is', $headers, $matches);
     526        if ($does_match) {
     527            $etag = $matches[1];
     528        }
     529   
     530        $matches = array();
     531        $does_match = preg_match('/Cache-Control: max-age=(\S+)/is', $headers, $matches);
     532        if ($does_match) {
     533            $max_age = $matches[1];
     534        }
     535
     536        // Make sure Cache-Control header is numeric to avoid errors later on when it is used for comparison
     537        if (is_numeric($max_age)) {
     538            $max_age = (int) $max_age;
     539        } else {
     540            $max_age = null;
     541        }
     542       
     543        return array($etag, $max_age);
     544    }
     545   
     546   
     547
     548    public static function fetch_dynamic_config($domain, $etag)
     549    {
     550        if (!$domain) {
     551            $failure_message = 'Domain not provided, not fetching dynamic config';
     552            UBLogger::warning($failure_message);
     553            return UBConfig::create_failure_response($failure_message);
     554        }
     555       
     556        try {
     557            $url = 'https://' . UBConfig::dynamic_config_retrieval_domain() . '/v' . UBConfig::UB_VERSION;
     558            UBLogger::debug("Retrieving dynamic config from '$url', etag: '$etag', host: '$domain'");
     559
     560            list($data, $http_code, $header_size, $curl_error) = UBConfig::make_curl_request($url, $domain, $etag);
     561            list($etag, $max_age) = UBConfig::process_headers($data, $header_size);
     562
     563            if ($http_code == 200) {
     564                $body = substr($data, $header_size);
     565                $decoded_body = json_decode($body, true);
     566
     567                if (json_last_error() == JSON_ERROR_NONE) {
     568                    UBLogger::debug("Retrieved new dynamic config, HTTP code: '$http_code'");
     569                    return UBConfig::create_new_response_dynamic_config($etag, $max_age, $decoded_body['request_header_allow'], $decoded_body['request_header_add'], $decoded_body['request_cookie_allow'], $decoded_body['response_header_allow']);
     570                } else {
     571                    $failure_message = "An error occurred while processing dynamic config, JSON errors: " . json_last_error_msg();
     572                    UBLogger::warning($failure_message);
     573                    return UBConfig::create_failure_response($failure_message);
     574                }
     575            }
     576
     577            return UBConfig::handle_non_200_http_response($http_code, $etag, $max_age, $curl_error, 'dynamic config');
     578        } catch (Exception $e) {
     579            $failure_message = "An error occurred while retrieving dynamic config; Error: " . $e->getMessage();
     580            UBLogger::warning($failure_message);
     581            return UBConfig::create_failure_response($failure_message);
     582        }
     583    }
     584
     585    public static function handle_non_200_http_response($http_code, $etag, $max_age, $curl_error, $context)
     586    {
     587        if ($http_code == 304) {
     588            UBLogger::debug("$context have not changed, HTTP code: '$http_code'");
     589            return UBConfig::create_same_response($etag, $max_age);
     590        }
     591
     592        if ($http_code == 404) {
     593            UBLogger::debug("No $context to retrieve, HTTP code: '$http_code'");
     594            return UBConfig::create_none_response();
     595        }
     596
     597        $failure_message = "An error occurred while retrieving $context;HTTP code: '$http_code';
     598        Error: " . $curl_error;
     599        UBLogger::warning($failure_message);
     600        return UBConfig::create_failure_response($failure_message);
     601    }
     602   
    398603    public static function is_authorized_domain($domain0)
    399604    {
     
    407612        update_option(UBConfig::UB_USER_ID_KEY, $data['user_id']);
    408613        update_option(UBConfig::UB_DOMAIN_ID_KEY, $data['domain_id']);
     614        update_option(UBConfig::UB_DOMAIN_UUID_KEY, $data['domain_uuid']);
    409615        update_option(UBConfig::UB_CLIENT_ID_KEY, $data['client_id']);
    410616        update_option(UBConfig::UB_AUTHORIZED_DOMAINS_KEY, $domains);
  • unbounce/tags/1.1.1/UBDiagnostics.php

    r2953445 r3005252  
    1313    public static function domain_checks($domain, $domain_info)
    1414    {
    15         return array(
    16             'Domain is Authorized'        => UBConfig::is_authorized_domain($domain),
    17             'Can Fetch Page Listing'      => UBDiagnostics::last_status_success($domain_info),
    18         );
     15        $dynamic_config = get_option(UBConfig::UB_DYNAMIC_CONFIG_CACHE_KEY, array());
     16        $uuid = get_option(UBConfig::UB_DOMAIN_UUID_KEY, '');
     17
     18        $result = array(
     19            'Domain is Authorized'    => UBConfig::is_authorized_domain($domain),
     20            'Can Fetch Page Listing'  => UBDiagnostics::last_status_success($domain_info)
     21        );
     22
     23        if (UBConfig::has_authorized()) {
     24            $result['Domain UUID'] = $uuid !== '';
     25        }
     26
     27        if (isset($dynamic_config['last_status'])) {
     28            $result['Dynamic Config Retrieval'] = $dynamic_config['last_status'] !== 'FAILURE';
     29        }
     30
     31        return $result;
    1932    }
    2033
     
    101114        'PHP Version'             => phpversion(),
    102115        'WordPress Version'       => UBDiagnostics::wordpress_version(),
    103         'Unbounce Plugin Version' => '1.1.0',
     116        'Unbounce Plugin Version' => '1.1.1',
    104117        'Checks'                  => self::pp(UBDiagnostics::checks($domain, $domain_info)),
    105118        'Options'                 => self::pp(UBDiagnostics::ub_options()),
     
    179192            'php'                 => phpversion(),
    180193            'wordpress'           => UBDiagnostics::wordpress_version(),
    181             'plugin_version'      => '1.1.0',
     194            'plugin_version'      => '1.1.1',
    182195            'curl_installed'      => self::is_curl_installed(),
    183196            'xml_installed'       => self::is_xml_installed(),
  • unbounce/tags/1.1.1/UBHTTP.php

    r2953445 r3005252  
    77    public static $variant_url_regex = '/(.+)\/[a-z]+\.html/i';
    88    public static $pie_htc_url = '/PIE.htc';
    9     public static $request_header_blocklist = '/^(?:Accept-Encoding|Host|Forwarded)$/i';
    109    public static $location_header_regex = '/^(?:Location):/i';
    11     public static $cookie_allowlist = array('ubvs', 'ubpv', 'ubvt', 'hubspotutk');
    12     public static $response_headers_always_forwarded = array(
    13         'content-length',
    14         'content-location',
    15         'content-type',
    16         'location',
    17         'link',
    18         'set-cookie',
    19         'cf-ray',
    20         'cf-cache-status'
    21     );
    2210
    2311    public static function is_public_ip_address($ip_address)
     
    126114    }
    127115
    128     public static function stream_headers_function()
    129     {
    130         $header_filter = UBHTTP::create_curl_response_header_filter();
     116    public static function stream_headers_function($dynamic_config)
     117    {
     118        $header_filter = UBHTTP::create_curl_response_header_filter($dynamic_config);
    131119
    132120        return function ($curl, $header_line) use ($header_filter) {
     
    242230        // Always add this header to responses to show it comes from our plugin.
    243231        header("X-Unbounce-Plugin: 1", false);
     232        $dynamic_config = UBConfig::read_unbounce_dynamic_config($domain);
     233
    244234        if (UBConfig::use_curl()) {
    245235            return UBHTTP::stream_request_curl(
     
    249239                $current_headers,
    250240                $current_protocol,
    251                 $domain
     241                $domain,
     242                $dynamic_config
    252243            );
    253244        } else {
     
    258249                $current_headers,
    259250                $current_protocol,
    260                 $domain
     251                $domain,
     252                $dynamic_config
    261253            );
    262254        }
     
    269261        $current_headers,
    270262        $current_protocol,
    271         $domain
     263        $domain,
     264        $dynamic_config
    272265    ) {
    273266        $args = array(
     
    277270            'timeout' => 30,
    278271            'headers' => array_merge(
    279                 UBHTTP::prepare_request_headers($current_headers, $current_protocol, $domain),
     272                UBHTTP::prepare_request_headers($current_headers, $current_protocol, $domain, $dynamic_config),
    280273                array(
    281274                    'x-ub-wordpress-remote-request' => '1',
     
    297290            http_response_code($resp['response']['code']);
    298291            $response_headers = $resp['headers'];
    299             UBHTTP::set_response_headers($response_headers);
     292            UBHTTP::set_response_headers($response_headers, $dynamic_config);
    300293            echo $resp['body'];
    301294            return array(true, null);
     
    303296    }
    304297
    305     public static function prepare_request_headers($current_headers, $current_protocol, $domain)
    306     {
    307         $target_headers = array();
    308         array_walk($current_headers, function ($v, $k) use (&$target_headers) {
    309             if (!preg_match(UBHTTP::$request_header_blocklist, $k)) {
    310                 $target_headers[$k] = $v;
    311             }
    312         });
     298    public static function prepare_request_headers($current_headers, $current_protocol, $domain, $dynamic_config)
     299    {
     300       
     301        $request_header_allow = UBUtil::array_fetch($dynamic_config, 'request_header_allow', UBConfig::UB_DEFAULT_REQUEST_HEADER_ALLOW);
     302        $request_header_add = UBUtil::array_fetch($dynamic_config, 'request_header_add', UBConfig::UB_DEFAULT_REQUEST_HEADER_ADD);
     303        $request_cookie_allow = UBUtil::array_fetch($dynamic_config, 'request_cookie_allow', UBConfig::UB_DEFAULT_REQUEST_COOKIE_ALLOW);
    313304
    314305        $current_forwarded_for = UBUtil::array_fetch($current_headers, 'x-forwarded-for');
     
    316307        $current_remote_ip = UBUtil::array_fetch($_SERVER, 'REMOTE_ADDR');
    317308
    318         return array_merge(
    319             UBHTTP::sanitize_cookies($target_headers),
     309        // remove current host header as we will be setting it to the target domain
     310        unset($current_headers['host']);
     311   
     312        $merged_headers = array_merge(
     313            UBHTTP::sanitize_cookies($current_headers, $request_cookie_allow),
    320314            UBHTTP::get_forwarded_headers(
    321315                $domain,
     
    327321            UBHTTP::get_common_headers()
    328322        );
     323       
     324        $target_headers = array();
     325        array_walk($merged_headers, function ($v, $k) use (&$target_headers, $request_header_allow) {
     326            if (preg_match($request_header_allow, $k)) {
     327                $target_headers[$k] = $v;
     328            }
     329        });
     330
     331        foreach ($request_header_add as $key => $value) {
     332            $target_headers[$key] = $value;
     333        }
     334        return $target_headers;
    329335    }
    330336
     
    333339        $headers = array(
    334340            'host' => UBConfig::page_server_domain(),
    335             'x-ub-wordpress-plugin-version' => '1.1.0'
     341            'x-ub-wordpress-plugin-version' => '1.1.1'
    336342        );
    337343
     
    364370    }
    365371
    366     public static function sanitize_cookies($headers)
     372    public static function sanitize_cookies($headers, $request_cookie_allow)
    367373    {
    368374        $cookie_key = "Cookie";
     
    376382        $cookies_to_forward = UBUtil::array_select_by_key(
    377383            UBHTTP::cookie_array_from_string($headers[$cookie_key]),
    378             UBHTTP::$cookie_allowlist
    379         );
    380         if (sizeof($cookies_to_forward) > 0) {
    381             $headers[$cookie_key] = UBHTTP::cookie_string_from_array($cookies_to_forward);
    382         }
     384            $request_cookie_allow
     385        );
     386
     387        $headers[$cookie_key] = UBHTTP::cookie_string_from_array($cookies_to_forward);
    383388        return $headers;
    384389    }
     
    395400    }
    396401
    397     public static function set_response_headers($headers)
    398     {
    399         $header_filter = UBHTTP::create_response_header_filter();
     402    public static function set_response_headers($headers, $dynamic_config)
     403    {
     404        $header_filter = UBHTTP::create_response_header_filter($dynamic_config);
    400405
    401406        foreach ($headers as $h_key => $h_value) {
     
    418423        $current_headers,
    419424        $current_protocol,
    420         $domain
     425        $domain,
     426        $dynamic_config
    421427    ) {
    422428        $base_response_headers = headers_list();
    423429
    424         $target_headers = UBHTTP::prepare_request_headers($current_headers, $current_protocol, $domain);
     430        $target_headers = UBHTTP::prepare_request_headers($current_headers, $current_protocol, $domain, $dynamic_config);
    425431        $target_headers = UBHTTP::convert_headers_to_curl($target_headers);
    426432
     
    429435        UBLogger::debug_var('target_headers', print_r($target_headers, true));
    430436
    431         $stream_headers = UBHTTP::stream_headers_function();
     437        $stream_headers = UBHTTP::stream_headers_function($dynamic_config);
    432438        $stream_body = UBHTTP::stream_response_function();
    433439        $curl = curl_init();
     
    574580    }
    575581
    576     private static function create_curl_response_header_filter()
     582    private static function create_curl_response_header_filter($dynamic_config)
    577583    {
    578584        $blocklist_regex = '/^connection:/i';
     
    585591        }
    586592
    587         $allowlist = array_merge($config_headers_forwarded, UBHTTP::$response_headers_always_forwarded);
     593        $allowlist = array_merge($config_headers_forwarded, UBUtil::array_fetch($dynamic_config, 'response_header_allow', array()));
    588594        $allowlist_regex = '/^('.implode('|', $allowlist).'):/i';
    589595        return function ($header) use ($blocklist_regex, $allowlist_regex) {
     
    592598    }
    593599
    594     private static function create_response_header_filter()
     600    private static function create_response_header_filter($dynamic_config)
    595601    {
    596602        $config_headers_forwarded = UBConfig::response_headers_forwarded();
     
    602608        }
    603609
    604         $allowlist = array_merge($config_headers_forwarded, UBHTTP::$response_headers_always_forwarded);
     610        $allowlist = array_merge($config_headers_forwarded, UBUtil::array_fetch($dynamic_config, 'response_header_allow', array()));
    605611
    606612        return function ($header) use ($allowlist) {
  • unbounce/tags/1.1.1/Unbounce-Page.php

    r2953445 r3005252  
    44Plugin URI: http://unbounce.com
    55Description: Unbounce is the most powerful standalone landing page builder available.
    6 Version: 1.1.0
     6Version: 1.1.1
    77Author: Unbounce
    88Author URI: http://unbounce.com
     
    148148add_action('admin_init', function () {
    149149    $current_version = UBConfig::UB_VERSION;
    150 
    151     if (get_option(UBConfig::UB_PLUGIN_VERSION_KEY) != $current_version) {
     150    $saved_version = get_option(UBConfig::UB_PLUGIN_VERSION_KEY);
     151
     152    if ($saved_version != $current_version) {
    152153        UBConfig::set_options_if_not_exist();
    153154        update_option(UBConfig::UB_PLUGIN_VERSION_KEY, $current_version);
    154155
    155         // When upgrading to 1.1.0, override all previous ub-page-server-domain values to new default
    156         // TODO: Remove this in subsequent plugin versions
    157         update_option(UBConfig::UB_PAGE_SERVER_DOMAIN_KEY, UBConfig::default_page_server_domain());
     156        // When upgrading to 1.1.x from a 1.0.x version, override all previous ub-page-server-domain values to new default
     157        if (version_compare($saved_version, '1.1.0', '<')) {
     158            update_option(UBConfig::UB_PAGE_SERVER_DOMAIN_KEY, UBConfig::default_page_server_domain());
     159        }
    158160    }
    159161
     
    175177        'set-unbounce-domains-js',
    176178        plugins_url('js/set-unbounce-domains.js', __FILE__),
    177         array('jquery', 'ub-rx')
     179        array('jquery', 'ub-rx'),
     180        "1.1.1"
    178181    );
    179182    wp_enqueue_script(
     
    319322        'client_id' => UBUtil::array_fetch($_POST, 'client_id', ''),
    320323        'domain_id' => UBUtil::array_fetch($_POST, 'domain_id', ''),
     324        'domain_uuid' => UBUtil::array_fetch($_POST, 'domain_uuid', ''),
    321325        );
    322326
  • unbounce/tags/1.1.1/js/set-unbounce-domains.js

    r1266757 r3005252  
    2323              clientId: subAccount.id,
    2424              domainId: domain.id,
    25               name: domain.name
     25              name: domain.name,
     26              domainUUID: domain.uuid
    2627            };
    2728          } else {
     
    5556        $form.find('[name="domain_id"]').val(wordpressDomain.domainId);
    5657        $form.find('[name="client_id"]').val(wordpressDomain.clientId);
     58        $form.find('[name="domain_uuid"]').val(wordpressDomain.domainUUID);
    5759      }
    5860
  • unbounce/tags/1.1.1/readme.txt

    r2953445 r3005252  
    33Tags: Unbounce, AB testing, A/B testing, split testing, CRO, conversion optimization, wordpress landing page, wp landing pages, splash pages, landing pages, squeeze pages, lead gen, lead generation, email list, responsive landing pages, templates, inbound marketing, ppc, analytics
    44Requires at least: 4.1.5
    5 Tested up to: 6.3
    6 Stable tag: 1.1.0
     5Tested up to: 6.4
     6Stable tag: 1.1.1
    77Requires PHP: 7.2
    88License: GPLv2 or later
     
    104104== Changelog ==
    105105
     106= 1.1.1 =
     107* Changes to the way the plugin filters headers and cookies using a dynamic configuration.
     108* Tested with WP 6.4
     109
    106110= 1.1.0 =
    107111* Changes the method used to communicate with Unbounce servers, which will improve the resilience of
  • unbounce/tags/1.1.1/templates/authorize_button.php

    r2823212 r3005252  
    33  <input type="hidden" name="user_id" />
    44  <input type="hidden" name="domain_id" />
     5  <input type="hidden" name="domain_uuid" />
    56  <input type="hidden" name="client_id" />
    67    <?php if (isset($outer_text)) { ?>
  • unbounce/tags/1.1.1/templates/diagnostics.php

    r2953445 r3005252  
    3737$sni_support = 'The Unbounce Plugin communicates with the Unbounce servers using a TLS 1.2 connection, this requires SNI support in order to function. Our diagnostics indicate that your server does not currently have SNI support.';
    3838
     39$dynamic_config_retrieval = 'The Unbounce Plugin is unable to retrieve the dynamic configuration from Unbounce. This is required in order to make sure we are able to serve your Unbounce pages the correct way and prevent any errors. Please contact support if you continue to see this error for more than a few days.';
     40
     41$domain_uuid = 'Plugin requests are not sent to Unbounce servers with the uuid added as a subdomain, which compromises security. Please update wordpress enabled domains on the pages section.';
     42
    3943$diagnostic_descriptions = array(
    4044    'Curl Support' => $curl_support,
     
    4549    'Supported PHP Version' => $supported_php_version,
    4650    'Supported Wordpress Version' => $supported_wordpress_version,
    47     'SNI Support' => $sni_support
     51    'SNI Support' => $sni_support,
     52    'Dynamic Config Retrieval' => $dynamic_config_retrieval,
     53    "Domain UUID" => $domain_uuid,
    4854);
    4955
  • unbounce/tags/1.1.1/templates/main_authorized_footer.php

    r2953445 r3005252  
    2222  Click here for troubleshooting and plugin diagnostics
    2323</a>
    24 <p class="ub-version">Unbounce Version 1.1.0</p>
     24<p class="ub-version">Unbounce Version 1.1.1</p>
  • unbounce/tags/1.1.1/templates/main_unauthorized_footer.php

    r2953445 r3005252  
    55  Click here for troubleshooting and plugin diagnostics
    66</a>
    7 <p class="ub-version">Unbounce Version 1.1.0</p>
     7<p class="ub-version">Unbounce Version 1.1.1</p>
  • unbounce/tags/1.1.1/templates/settings_response_headers_forwarded.php

    r2823212 r3005252  
    1111    $headers = array_map(function ($header) {
    1212        return '<code>'.$header.'</code>';
    13     }, UBHTTP::$response_headers_always_forwarded);
     13    }, get_option(UBConfig::UB_DYNAMIC_CONFIG_CACHE_KEY, array())['response_header_allow']);
    1414    echo implode(',', array_slice($headers, 0, -1)).' and '.end($headers);
    1515    ?>
  • unbounce/trunk/UBConfig.php

    r2953445 r3005252  
    33class UBConfig
    44{
     5    const DYNAMIC_CONFIG_DEFAULT_TIMEOUT = 86400;
     6    const DYNAMIC_CONFIG_FAILURE_TIMEOUT = 1200;
    57
    68    const UB_PLUGIN_NAME           = 'ub-wordpress';
    79    const UB_CACHE_TIMEOUT_ENV_KEY = 'UB_WP_ROUTES_CACHE_EXP';
    8     const UB_USER_AGENT            = 'Unbounce WP Plugin 1.1.0';
    9     const UB_VERSION               = '1.1.0';
     10    const UB_USER_AGENT            = 'Unbounce WP Plugin 1.1.1';
     11    const UB_VERSION               = '1.1.1';
    1012
    1113    // WP Admin Pages
     
    1517
    1618    // Option keys
     19    const UB_DYNAMIC_CONFIG_CACHE_KEY   = 'ub-dynamic-config-cache';
    1720    const UB_ROUTES_CACHE_KEY        = 'ub-route-cache';
    1821    const UB_PAGE_SERVER_DOMAIN_KEY  = 'ub-page-server-domain';
     22    const UB_DYNAMIC_CONFIG_DOMAIN_KEY = 'ub-dynamic-config-domain';
    1923    const UB_API_URL_KEY             = 'ub-api-url';
    2024    const UB_API_CLIENT_ID_KEY       = 'ub-api-client-id';
     
    2327    const UB_USER_ID_KEY             = 'ub-user-id';
    2428    const UB_DOMAIN_ID_KEY           = 'ub-domain-id';
     29    const UB_DOMAIN_UUID_KEY         = 'ub-domain-uuid';
    2530    const UB_CLIENT_ID_KEY           = 'ub-client-id';
    2631    const UB_PROXY_ERROR_MESSAGE_KEY = 'ub-proxy-error-message';
     
    3338    const UB_RESPONSE_HEADERS_FORWARDED_KEY = 'ub-response-headers-forwarded';
    3439
     40    const UB_DEFAULT_REQUEST_HEADER_ALLOW = '/^(?:Accept|Content-Type|Referer|User-Agent|If-None-Match|Host|X-Forwarded-.+|X-Proxied-For|X-Ub-Wordpress-.+|Cookie|Accept-Language|Origin|Access-Control-Request-Headers|Access-Control-Request-Method)$/i';
     41    const UB_DEFAULT_REQUEST_HEADER_ADD = array();
     42    const UB_DEFAULT_REQUEST_COOKIE_ALLOW = array('ubvs', 'ubpv', 'ubvt', 'hubspotutk');
     43    const UB_DEFAULT_RESPONSE_HEADER_ALLOW = array(
     44        'content-length',
     45        'content-location',
     46        'content-type',
     47        'location',
     48        'link',
     49        'set-cookie',
     50        'cf-ray',
     51        'cf-cache-status',
     52        'access-control-allow-origin',
     53        'access-control-allow-credentials',
     54        'access-control-allow-headers',
     55        'access-control-max-age'
     56    );
     57
    3558    public static function ub_option_defaults()
    3659    {
     
    3861        // Arrays are not allowed in class constants, so use a function
    3962        return array(
     63            UBConfig::UB_DYNAMIC_CONFIG_CACHE_KEY => array(
     64                'request_header_allow' => UBConfig::UB_DEFAULT_REQUEST_HEADER_ALLOW,
     65                'request_header_add' => UBConfig::UB_DEFAULT_REQUEST_HEADER_ADD,
     66                'request_cookie_allow' => UBConfig::UB_DEFAULT_REQUEST_COOKIE_ALLOW,
     67                'response_header_allow' => UBConfig::UB_DEFAULT_RESPONSE_HEADER_ALLOW
     68            ),
    4069            UBConfig::UB_ROUTES_CACHE_KEY => array(),
    4170            UBConfig::UB_PAGE_SERVER_DOMAIN_KEY => UBConfig::default_page_server_domain(),
     71            UBConfig::UB_DYNAMIC_CONFIG_DOMAIN_KEY => UBConfig::default_dynamic_config_retrieval_domain(),
    4272            UBConfig::UB_API_URL_KEY => UBConfig::default_api_url(),
    4373            UBConfig::UB_API_CLIENT_ID_KEY => UBConfig::default_api_client_id(),
     
    4676            UBConfig::UB_USER_ID_KEY => '',
    4777            UBConfig::UB_DOMAIN_ID_KEY => '',
     78            UBConfig::UB_DOMAIN_UUID_KEY => '',
    4879            UBConfig::UB_CLIENT_ID_KEY => '',
    4980            UBConfig::UB_PROXY_ERROR_MESSAGE_KEY => '',
     
    76107    }
    77108
     109    public static function default_dynamic_config_retrieval_domain()
     110    {
     111        $domain = getenv('UB_DYNAMIC_CONFIG_DOMAIN');
     112        return $domain ? $domain : 'wp-config.unbouncepages.com';
     113    }
     114
    78115    public static function default_api_url()
    79116    {
     
    96133    public static function page_server_domain()
    97134    {
    98         return get_option(UBConfig::UB_PAGE_SERVER_DOMAIN_KEY, UBConfig::default_page_server_domain());
     135        $domain = get_option(UBConfig::UB_PAGE_SERVER_DOMAIN_KEY, UBConfig::default_page_server_domain());
     136
     137        return UBConfig::add_domain_uuid_subdomain($domain);
     138    }
     139
     140    public static function dynamic_config_retrieval_domain()
     141    {
     142        $domain = get_option(UBConfig::UB_DYNAMIC_CONFIG_DOMAIN_KEY, UBConfig::default_dynamic_config_retrieval_domain());
     143
     144        return UBConfig::add_domain_uuid_subdomain($domain);
     145    }
     146
     147    private static function add_domain_uuid_subdomain($domain)
     148    {
     149        $subdomain = get_option(UBConfig::UB_DOMAIN_UUID_KEY);
     150   
     151        if ($subdomain) {
     152            $domain = $subdomain . '.' . $domain;
     153        }
     154   
     155        return $domain;
    99156    }
    100157
     
    131188    public static function create_none_response()
    132189    {
    133         return array(array('status' => 'NONE'), null, null, null);
     190        return array(array('status' => 'NONE'));
    134191    }
    135192
    136193    public static function create_same_response($etag, $max_age)
    137194    {
    138         return array(array('status' => 'SAME'), $etag, $max_age, null);
    139     }
    140 
    141     public static function create_new_response($etag, $max_age, $proxyable_url_set)
     195        return array(array('status' => 'SAME'), $etag, $max_age);
     196    }
     197
     198    public static function create_new_response_proxyable_url_set($etag, $max_age, $proxyable_url_set)
    142199    {
    143200        return array(array('status' => 'NEW'), $etag, $max_age, $proxyable_url_set);
    144201    }
    145202
     203    public static function create_new_response_dynamic_config($etag, $max_age, $request_header_allow, $request_header_add, $request_cookie_allow, $response_header_allow)
     204    {
     205        return array(array('status' => 'NEW'), $etag, $max_age, $request_header_allow, $request_header_add, $request_cookie_allow, $response_header_allow);
     206    }
     207
    146208    public static function create_failure_response($failure_message)
    147209    {
    148210        return array(array('status' => 'FAILURE',
    149                        'failure_message' => $failure_message),
    150                  null, null, null);
     211                       'failure_message' => $failure_message));
    151212    }
    152213
     
    187248        try {
    188249            $url = 'https://' . $ps_domain . '/sitemap.xml';
    189             $curl = curl_init();
    190             $curl_options = array(
    191                 CURLOPT_URL => $url,
    192                 CURLOPT_CUSTOMREQUEST => "GET",
    193                 CURLOPT_HEADER => true,
    194                 CURLOPT_USERAGENT => UBConfig::UB_USER_AGENT,
    195                 CURLOPT_HTTPHEADER => UBHTTP::convert_headers_to_curl(
    196                     array(
    197                         'x-forwarded-host' => $domain,
    198                         'if-none-match' => $etag
    199                     )
    200                 ),
    201                 CURLOPT_RETURNTRANSFER => true,
    202                 CURLOPT_FOLLOWLOCATION => false,
    203                 CURLOPT_TIMEOUT => 5
    204             );
    205 
     250           
    206251            UBLogger::debug("Retrieving routes from '$url', etag: '$etag', host: '$domain'");
    207252
    208             curl_setopt_array($curl, $curl_options);
    209             $data = curl_exec($curl);
    210             $http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
    211             $header_size = strlen($data) - curl_getinfo($curl, CURLINFO_SIZE_DOWNLOAD);
    212             $curl_error = null;
    213             $etag = null;
    214             $max_age = null;
    215 
    216             // when having an CURL error, http_code is 0
    217             if ($http_code == 0) {
    218                   $curl_error = curl_error($curl);
    219             }
    220 
    221             curl_close($curl);
    222 
    223             $headers = substr($data, 0, $header_size);
    224 
    225             $matches = array();
    226             $does_match = preg_match('/ETag: (\S+)/is', $headers, $matches);
    227             if ($does_match) {
    228                   $etag = $matches[1];
    229             }
    230 
    231             $matches = array();
    232             $does_match = preg_match('/Cache-Control: max-age=(\S+)/is', $headers, $matches);
    233             if ($does_match) {
    234                   $max_age = $matches[1];
    235             }
     253            list($data, $http_code, $header_size, $curl_error) = UBConfig::make_curl_request($url, $domain, $etag);
     254            list($etag, $max_age) = UBConfig::process_headers($data, $header_size);
    236255
    237256            if ($http_code == 200) {
     
    241260                if ($success) {
    242261                    UBLogger::debug("Retrieved new routes, HTTP code: '$http_code'");
    243                     return UBConfig::create_new_response($etag, $max_age, $result);
     262                    return UBConfig::create_new_response_proxyable_url_set($etag, $max_age, $result);
    244263                } else {
    245264                    $errors = join(', ', $result);
     
    249268                }
    250269            }
    251             if ($http_code == 304) {
    252                   UBLogger::debug("Routes have not changed, HTTP code: '$http_code'");
    253                   return UBConfig::create_same_response($etag, $max_age);
    254             }
    255             if ($http_code == 404) {
    256                   UBLogger::debug("No routes to retrieve, HTTP code: '$http_code'");
    257                   return UBConfig::create_none_response();
    258             } else {
    259                   $failure_message = "An error occurred while retrieving routes;
    260                     HTTP code: '$http_code';
    261                     Error: " . $curl_error;
    262                   UBLogger::warning($failure_message);
    263                   return UBConfig::create_failure_response($failure_message);
    264             }
     270
     271            return UBConfig::handle_non_200_http_response($http_code, $etag, $max_age, $curl_error, 'routes');
    265272        } catch (Exception $e) {
    266273            $failure_message = "An error occurred while retrieving routes; Error: " . $e;
     
    323330        $cache_max_time_default = 10;
    324331
    325         $ps_domain = get_option(UBConfig::UB_PAGE_SERVER_DOMAIN_KEY, UBConfig::default_page_server_domain());
     332        $ps_domain = UBConfig::page_server_domain();
     333                     
    326334        $domains_info = get_option(UBConfig::UB_ROUTES_CACHE_KEY, array());
    327335
     
    396404    }
    397405
     406    // We are using a fetched dynamic config to retrieve information
     407    // such that we decide what request headers to allow and add,
     408    // as well as what response headers and request cookies to allow.
     409    public static function read_unbounce_dynamic_config($domain)
     410    {
     411        // Check if curl is installed to prevent fatal error
     412        if (!UBDiagnostics::is_curl_installed()) {
     413            return array();
     414        }
     415
     416        $cache_max_time_default = UBConfig::DYNAMIC_CONFIG_DEFAULT_TIMEOUT;
     417        $dynamic_config = get_option(UBConfig::UB_DYNAMIC_CONFIG_CACHE_KEY, array());
     418
     419        if (!is_array($dynamic_config)) {
     420            $dynamic_config = array();
     421        }
     422
     423        $dynamic_config_fetched_at = UBUtil::array_fetch($dynamic_config, 'fetched_at');
     424        $dynamic_config_cache_timeout = UBUtil::array_fetch($dynamic_config, 'cache_timeout');
     425        $dynamic_config_etag = UBUtil::array_fetch($dynamic_config, 'etag');
     426
     427        $cache_max_time = is_null($dynamic_config_cache_timeout) ? $cache_max_time_default : $dynamic_config_cache_timeout;
     428
     429        // regardless of dynamic_config_cache_timeout being set, if the last fetch failed or returned a 404, we want to try again in 20 minutes
     430        if ($dynamic_config['last_status'] === 'FAILURE' || $dynamic_config['last_status'] === 'NONE') {
     431            $cache_max_time = UBConfig::DYNAMIC_CONFIG_FAILURE_TIMEOUT;
     432        }
     433
     434        $current_time = time();
     435
     436        if (is_null($dynamic_config_fetched_at) ||
     437            ($current_time - $dynamic_config_fetched_at > $cache_max_time)) {
     438            try {
     439                $can_fetch = UBUtil::get_lock();
     440                UBLogger::debug('Locking: ' . $can_fetch);
     441
     442                if ($can_fetch) {
     443                    $result_array = UBConfig::fetch_dynamic_config($domain, $dynamic_config_etag);
     444                    list($routes_status, $etag, $max_age, $request_header_allow_new, $request_header_add_new, $request_cookie_allow_new, $response_header_allow_new) = $result_array;
     445
     446                    if ($routes_status['status'] === 'NEW') {
     447                        $dynamic_config['request_header_allow'] = $request_header_allow_new;
     448                        $dynamic_config['request_header_add'] = $request_header_add_new;
     449                        $dynamic_config['request_cookie_allow'] = $request_cookie_allow_new;
     450                        $dynamic_config['response_header_allow'] = $response_header_allow_new;
     451                        $dynamic_config['etag'] = $etag;
     452                        $dynamic_config['cache_timeout'] = $max_age;
     453                    } elseif ($routes_status['status'] === 'SAME') {
     454                        // Just extend the cache
     455                        $dynamic_config['cache_timeout'] = $max_age;
     456                    } elseif ($routes_status['status'] === 'FAILURE' || $routes_status['status'] === 'NONE') {
     457                        UBLogger::warning('Not updating the dynamic config: Fetching failed or 404 was returned');
     458                    } else {
     459                        UBLogger::warning("Unknown response from dynamic config fetcher: '$routes_status'");
     460                    }
     461
     462                    $dynamic_config['fetched_at'] = $current_time;
     463                    $dynamic_config['last_status'] = $routes_status['status'];
     464
     465                    if ($routes_status['status'] === 'FAILURE') {
     466                        $dynamic_config['failure_message'] = $routes_status['failure_message'];
     467                    }
     468
     469                    update_option(UBConfig::UB_DYNAMIC_CONFIG_CACHE_KEY, $dynamic_config, false);
     470                }
     471            } catch (Exception $e) {
     472                UBLogger::warning('Could not update dynamic config: ' . $e);
     473                $dynamic_config['last_status'] = 'FAILURE';
     474                $dynamic_config['failure_message'] = $e->getMessage();
     475                update_option(UBConfig::UB_DYNAMIC_CONFIG_CACHE_KEY, $dynamic_config, false);
     476            }
     477
     478            $release_result = UBUtil::release_lock();
     479            UBLogger::debug('Unlocking: ' . $release_result);
     480        }
     481       
     482        return UBUtil::array_select_by_key(
     483            $dynamic_config,
     484            array('request_header_allow', 'request_header_add', 'request_cookie_allow', 'response_header_allow')
     485        );
     486    }
     487
     488    private static function make_curl_request($url, $domain, $etag)
     489    {
     490        $curl = curl_init();
     491        $curl_options = array(
     492            CURLOPT_URL => $url,
     493            CURLOPT_CUSTOMREQUEST => "GET",
     494            CURLOPT_HEADER => true,
     495            CURLOPT_USERAGENT => UBConfig::UB_USER_AGENT,
     496            CURLOPT_HTTPHEADER => UBHTTP::convert_headers_to_curl(
     497                array(
     498                    'x-forwarded-host' => $domain,
     499                    'if-none-match' => $etag
     500                )
     501            ),
     502            CURLOPT_RETURNTRANSFER => true,
     503            CURLOPT_FOLLOWLOCATION => false,
     504            CURLOPT_TIMEOUT => 5
     505        );
     506        curl_setopt_array($curl, $curl_options);
     507       
     508        $data = curl_exec($curl);
     509        $http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
     510        $header_size = strlen($data) - curl_getinfo($curl, CURLINFO_SIZE_DOWNLOAD);
     511        $curl_error = $http_code == 0 ? curl_error($curl) : null;
     512       
     513        curl_close($curl);
     514       
     515        return array($data, $http_code, $header_size, $curl_error);
     516    }
     517
     518    private static function process_headers($data, $header_size)
     519    {
     520        $headers = substr($data, 0, $header_size);
     521        $etag = null;
     522        $max_age = null;
     523   
     524        $matches = array();
     525        $does_match = preg_match('/ETag: (\S+)/is', $headers, $matches);
     526        if ($does_match) {
     527            $etag = $matches[1];
     528        }
     529   
     530        $matches = array();
     531        $does_match = preg_match('/Cache-Control: max-age=(\S+)/is', $headers, $matches);
     532        if ($does_match) {
     533            $max_age = $matches[1];
     534        }
     535
     536        // Make sure Cache-Control header is numeric to avoid errors later on when it is used for comparison
     537        if (is_numeric($max_age)) {
     538            $max_age = (int) $max_age;
     539        } else {
     540            $max_age = null;
     541        }
     542       
     543        return array($etag, $max_age);
     544    }
     545   
     546   
     547
     548    public static function fetch_dynamic_config($domain, $etag)
     549    {
     550        if (!$domain) {
     551            $failure_message = 'Domain not provided, not fetching dynamic config';
     552            UBLogger::warning($failure_message);
     553            return UBConfig::create_failure_response($failure_message);
     554        }
     555       
     556        try {
     557            $url = 'https://' . UBConfig::dynamic_config_retrieval_domain() . '/v' . UBConfig::UB_VERSION;
     558            UBLogger::debug("Retrieving dynamic config from '$url', etag: '$etag', host: '$domain'");
     559
     560            list($data, $http_code, $header_size, $curl_error) = UBConfig::make_curl_request($url, $domain, $etag);
     561            list($etag, $max_age) = UBConfig::process_headers($data, $header_size);
     562
     563            if ($http_code == 200) {
     564                $body = substr($data, $header_size);
     565                $decoded_body = json_decode($body, true);
     566
     567                if (json_last_error() == JSON_ERROR_NONE) {
     568                    UBLogger::debug("Retrieved new dynamic config, HTTP code: '$http_code'");
     569                    return UBConfig::create_new_response_dynamic_config($etag, $max_age, $decoded_body['request_header_allow'], $decoded_body['request_header_add'], $decoded_body['request_cookie_allow'], $decoded_body['response_header_allow']);
     570                } else {
     571                    $failure_message = "An error occurred while processing dynamic config, JSON errors: " . json_last_error_msg();
     572                    UBLogger::warning($failure_message);
     573                    return UBConfig::create_failure_response($failure_message);
     574                }
     575            }
     576
     577            return UBConfig::handle_non_200_http_response($http_code, $etag, $max_age, $curl_error, 'dynamic config');
     578        } catch (Exception $e) {
     579            $failure_message = "An error occurred while retrieving dynamic config; Error: " . $e->getMessage();
     580            UBLogger::warning($failure_message);
     581            return UBConfig::create_failure_response($failure_message);
     582        }
     583    }
     584
     585    public static function handle_non_200_http_response($http_code, $etag, $max_age, $curl_error, $context)
     586    {
     587        if ($http_code == 304) {
     588            UBLogger::debug("$context have not changed, HTTP code: '$http_code'");
     589            return UBConfig::create_same_response($etag, $max_age);
     590        }
     591
     592        if ($http_code == 404) {
     593            UBLogger::debug("No $context to retrieve, HTTP code: '$http_code'");
     594            return UBConfig::create_none_response();
     595        }
     596
     597        $failure_message = "An error occurred while retrieving $context;HTTP code: '$http_code';
     598        Error: " . $curl_error;
     599        UBLogger::warning($failure_message);
     600        return UBConfig::create_failure_response($failure_message);
     601    }
     602   
    398603    public static function is_authorized_domain($domain0)
    399604    {
     
    407612        update_option(UBConfig::UB_USER_ID_KEY, $data['user_id']);
    408613        update_option(UBConfig::UB_DOMAIN_ID_KEY, $data['domain_id']);
     614        update_option(UBConfig::UB_DOMAIN_UUID_KEY, $data['domain_uuid']);
    409615        update_option(UBConfig::UB_CLIENT_ID_KEY, $data['client_id']);
    410616        update_option(UBConfig::UB_AUTHORIZED_DOMAINS_KEY, $domains);
  • unbounce/trunk/UBDiagnostics.php

    r2953445 r3005252  
    1313    public static function domain_checks($domain, $domain_info)
    1414    {
    15         return array(
    16             'Domain is Authorized'        => UBConfig::is_authorized_domain($domain),
    17             'Can Fetch Page Listing'      => UBDiagnostics::last_status_success($domain_info),
    18         );
     15        $dynamic_config = get_option(UBConfig::UB_DYNAMIC_CONFIG_CACHE_KEY, array());
     16        $uuid = get_option(UBConfig::UB_DOMAIN_UUID_KEY, '');
     17
     18        $result = array(
     19            'Domain is Authorized'    => UBConfig::is_authorized_domain($domain),
     20            'Can Fetch Page Listing'  => UBDiagnostics::last_status_success($domain_info)
     21        );
     22
     23        if (UBConfig::has_authorized()) {
     24            $result['Domain UUID'] = $uuid !== '';
     25        }
     26
     27        if (isset($dynamic_config['last_status'])) {
     28            $result['Dynamic Config Retrieval'] = $dynamic_config['last_status'] !== 'FAILURE';
     29        }
     30
     31        return $result;
    1932    }
    2033
     
    101114        'PHP Version'             => phpversion(),
    102115        'WordPress Version'       => UBDiagnostics::wordpress_version(),
    103         'Unbounce Plugin Version' => '1.1.0',
     116        'Unbounce Plugin Version' => '1.1.1',
    104117        'Checks'                  => self::pp(UBDiagnostics::checks($domain, $domain_info)),
    105118        'Options'                 => self::pp(UBDiagnostics::ub_options()),
     
    179192            'php'                 => phpversion(),
    180193            'wordpress'           => UBDiagnostics::wordpress_version(),
    181             'plugin_version'      => '1.1.0',
     194            'plugin_version'      => '1.1.1',
    182195            'curl_installed'      => self::is_curl_installed(),
    183196            'xml_installed'       => self::is_xml_installed(),
  • unbounce/trunk/UBHTTP.php

    r2953445 r3005252  
    77    public static $variant_url_regex = '/(.+)\/[a-z]+\.html/i';
    88    public static $pie_htc_url = '/PIE.htc';
    9     public static $request_header_blocklist = '/^(?:Accept-Encoding|Host|Forwarded)$/i';
    109    public static $location_header_regex = '/^(?:Location):/i';
    11     public static $cookie_allowlist = array('ubvs', 'ubpv', 'ubvt', 'hubspotutk');
    12     public static $response_headers_always_forwarded = array(
    13         'content-length',
    14         'content-location',
    15         'content-type',
    16         'location',
    17         'link',
    18         'set-cookie',
    19         'cf-ray',
    20         'cf-cache-status'
    21     );
    2210
    2311    public static function is_public_ip_address($ip_address)
     
    126114    }
    127115
    128     public static function stream_headers_function()
    129     {
    130         $header_filter = UBHTTP::create_curl_response_header_filter();
     116    public static function stream_headers_function($dynamic_config)
     117    {
     118        $header_filter = UBHTTP::create_curl_response_header_filter($dynamic_config);
    131119
    132120        return function ($curl, $header_line) use ($header_filter) {
     
    242230        // Always add this header to responses to show it comes from our plugin.
    243231        header("X-Unbounce-Plugin: 1", false);
     232        $dynamic_config = UBConfig::read_unbounce_dynamic_config($domain);
     233
    244234        if (UBConfig::use_curl()) {
    245235            return UBHTTP::stream_request_curl(
     
    249239                $current_headers,
    250240                $current_protocol,
    251                 $domain
     241                $domain,
     242                $dynamic_config
    252243            );
    253244        } else {
     
    258249                $current_headers,
    259250                $current_protocol,
    260                 $domain
     251                $domain,
     252                $dynamic_config
    261253            );
    262254        }
     
    269261        $current_headers,
    270262        $current_protocol,
    271         $domain
     263        $domain,
     264        $dynamic_config
    272265    ) {
    273266        $args = array(
     
    277270            'timeout' => 30,
    278271            'headers' => array_merge(
    279                 UBHTTP::prepare_request_headers($current_headers, $current_protocol, $domain),
     272                UBHTTP::prepare_request_headers($current_headers, $current_protocol, $domain, $dynamic_config),
    280273                array(
    281274                    'x-ub-wordpress-remote-request' => '1',
     
    297290            http_response_code($resp['response']['code']);
    298291            $response_headers = $resp['headers'];
    299             UBHTTP::set_response_headers($response_headers);
     292            UBHTTP::set_response_headers($response_headers, $dynamic_config);
    300293            echo $resp['body'];
    301294            return array(true, null);
     
    303296    }
    304297
    305     public static function prepare_request_headers($current_headers, $current_protocol, $domain)
    306     {
    307         $target_headers = array();
    308         array_walk($current_headers, function ($v, $k) use (&$target_headers) {
    309             if (!preg_match(UBHTTP::$request_header_blocklist, $k)) {
    310                 $target_headers[$k] = $v;
    311             }
    312         });
     298    public static function prepare_request_headers($current_headers, $current_protocol, $domain, $dynamic_config)
     299    {
     300       
     301        $request_header_allow = UBUtil::array_fetch($dynamic_config, 'request_header_allow', UBConfig::UB_DEFAULT_REQUEST_HEADER_ALLOW);
     302        $request_header_add = UBUtil::array_fetch($dynamic_config, 'request_header_add', UBConfig::UB_DEFAULT_REQUEST_HEADER_ADD);
     303        $request_cookie_allow = UBUtil::array_fetch($dynamic_config, 'request_cookie_allow', UBConfig::UB_DEFAULT_REQUEST_COOKIE_ALLOW);
    313304
    314305        $current_forwarded_for = UBUtil::array_fetch($current_headers, 'x-forwarded-for');
     
    316307        $current_remote_ip = UBUtil::array_fetch($_SERVER, 'REMOTE_ADDR');
    317308
    318         return array_merge(
    319             UBHTTP::sanitize_cookies($target_headers),
     309        // remove current host header as we will be setting it to the target domain
     310        unset($current_headers['host']);
     311   
     312        $merged_headers = array_merge(
     313            UBHTTP::sanitize_cookies($current_headers, $request_cookie_allow),
    320314            UBHTTP::get_forwarded_headers(
    321315                $domain,
     
    327321            UBHTTP::get_common_headers()
    328322        );
     323       
     324        $target_headers = array();
     325        array_walk($merged_headers, function ($v, $k) use (&$target_headers, $request_header_allow) {
     326            if (preg_match($request_header_allow, $k)) {
     327                $target_headers[$k] = $v;
     328            }
     329        });
     330
     331        foreach ($request_header_add as $key => $value) {
     332            $target_headers[$key] = $value;
     333        }
     334        return $target_headers;
    329335    }
    330336
     
    333339        $headers = array(
    334340            'host' => UBConfig::page_server_domain(),
    335             'x-ub-wordpress-plugin-version' => '1.1.0'
     341            'x-ub-wordpress-plugin-version' => '1.1.1'
    336342        );
    337343
     
    364370    }
    365371
    366     public static function sanitize_cookies($headers)
     372    public static function sanitize_cookies($headers, $request_cookie_allow)
    367373    {
    368374        $cookie_key = "Cookie";
     
    376382        $cookies_to_forward = UBUtil::array_select_by_key(
    377383            UBHTTP::cookie_array_from_string($headers[$cookie_key]),
    378             UBHTTP::$cookie_allowlist
    379         );
    380         if (sizeof($cookies_to_forward) > 0) {
    381             $headers[$cookie_key] = UBHTTP::cookie_string_from_array($cookies_to_forward);
    382         }
     384            $request_cookie_allow
     385        );
     386
     387        $headers[$cookie_key] = UBHTTP::cookie_string_from_array($cookies_to_forward);
    383388        return $headers;
    384389    }
     
    395400    }
    396401
    397     public static function set_response_headers($headers)
    398     {
    399         $header_filter = UBHTTP::create_response_header_filter();
     402    public static function set_response_headers($headers, $dynamic_config)
     403    {
     404        $header_filter = UBHTTP::create_response_header_filter($dynamic_config);
    400405
    401406        foreach ($headers as $h_key => $h_value) {
     
    418423        $current_headers,
    419424        $current_protocol,
    420         $domain
     425        $domain,
     426        $dynamic_config
    421427    ) {
    422428        $base_response_headers = headers_list();
    423429
    424         $target_headers = UBHTTP::prepare_request_headers($current_headers, $current_protocol, $domain);
     430        $target_headers = UBHTTP::prepare_request_headers($current_headers, $current_protocol, $domain, $dynamic_config);
    425431        $target_headers = UBHTTP::convert_headers_to_curl($target_headers);
    426432
     
    429435        UBLogger::debug_var('target_headers', print_r($target_headers, true));
    430436
    431         $stream_headers = UBHTTP::stream_headers_function();
     437        $stream_headers = UBHTTP::stream_headers_function($dynamic_config);
    432438        $stream_body = UBHTTP::stream_response_function();
    433439        $curl = curl_init();
     
    574580    }
    575581
    576     private static function create_curl_response_header_filter()
     582    private static function create_curl_response_header_filter($dynamic_config)
    577583    {
    578584        $blocklist_regex = '/^connection:/i';
     
    585591        }
    586592
    587         $allowlist = array_merge($config_headers_forwarded, UBHTTP::$response_headers_always_forwarded);
     593        $allowlist = array_merge($config_headers_forwarded, UBUtil::array_fetch($dynamic_config, 'response_header_allow', array()));
    588594        $allowlist_regex = '/^('.implode('|', $allowlist).'):/i';
    589595        return function ($header) use ($blocklist_regex, $allowlist_regex) {
     
    592598    }
    593599
    594     private static function create_response_header_filter()
     600    private static function create_response_header_filter($dynamic_config)
    595601    {
    596602        $config_headers_forwarded = UBConfig::response_headers_forwarded();
     
    602608        }
    603609
    604         $allowlist = array_merge($config_headers_forwarded, UBHTTP::$response_headers_always_forwarded);
     610        $allowlist = array_merge($config_headers_forwarded, UBUtil::array_fetch($dynamic_config, 'response_header_allow', array()));
    605611
    606612        return function ($header) use ($allowlist) {
  • unbounce/trunk/Unbounce-Page.php

    r2953445 r3005252  
    44Plugin URI: http://unbounce.com
    55Description: Unbounce is the most powerful standalone landing page builder available.
    6 Version: 1.1.0
     6Version: 1.1.1
    77Author: Unbounce
    88Author URI: http://unbounce.com
     
    148148add_action('admin_init', function () {
    149149    $current_version = UBConfig::UB_VERSION;
    150 
    151     if (get_option(UBConfig::UB_PLUGIN_VERSION_KEY) != $current_version) {
     150    $saved_version = get_option(UBConfig::UB_PLUGIN_VERSION_KEY);
     151
     152    if ($saved_version != $current_version) {
    152153        UBConfig::set_options_if_not_exist();
    153154        update_option(UBConfig::UB_PLUGIN_VERSION_KEY, $current_version);
    154155
    155         // When upgrading to 1.1.0, override all previous ub-page-server-domain values to new default
    156         // TODO: Remove this in subsequent plugin versions
    157         update_option(UBConfig::UB_PAGE_SERVER_DOMAIN_KEY, UBConfig::default_page_server_domain());
     156        // When upgrading to 1.1.x from a 1.0.x version, override all previous ub-page-server-domain values to new default
     157        if (version_compare($saved_version, '1.1.0', '<')) {
     158            update_option(UBConfig::UB_PAGE_SERVER_DOMAIN_KEY, UBConfig::default_page_server_domain());
     159        }
    158160    }
    159161
     
    175177        'set-unbounce-domains-js',
    176178        plugins_url('js/set-unbounce-domains.js', __FILE__),
    177         array('jquery', 'ub-rx')
     179        array('jquery', 'ub-rx'),
     180        "1.1.1"
    178181    );
    179182    wp_enqueue_script(
     
    319322        'client_id' => UBUtil::array_fetch($_POST, 'client_id', ''),
    320323        'domain_id' => UBUtil::array_fetch($_POST, 'domain_id', ''),
     324        'domain_uuid' => UBUtil::array_fetch($_POST, 'domain_uuid', ''),
    321325        );
    322326
  • unbounce/trunk/js/set-unbounce-domains.js

    r1266757 r3005252  
    2323              clientId: subAccount.id,
    2424              domainId: domain.id,
    25               name: domain.name
     25              name: domain.name,
     26              domainUUID: domain.uuid
    2627            };
    2728          } else {
     
    5556        $form.find('[name="domain_id"]').val(wordpressDomain.domainId);
    5657        $form.find('[name="client_id"]').val(wordpressDomain.clientId);
     58        $form.find('[name="domain_uuid"]').val(wordpressDomain.domainUUID);
    5759      }
    5860
  • unbounce/trunk/readme.txt

    r2953445 r3005252  
    33Tags: Unbounce, AB testing, A/B testing, split testing, CRO, conversion optimization, wordpress landing page, wp landing pages, splash pages, landing pages, squeeze pages, lead gen, lead generation, email list, responsive landing pages, templates, inbound marketing, ppc, analytics
    44Requires at least: 4.1.5
    5 Tested up to: 6.3
    6 Stable tag: 1.1.0
     5Tested up to: 6.4
     6Stable tag: 1.1.1
    77Requires PHP: 7.2
    88License: GPLv2 or later
     
    104104== Changelog ==
    105105
     106= 1.1.1 =
     107* Changes to the way the plugin filters headers and cookies using a dynamic configuration.
     108* Tested with WP 6.4
     109
    106110= 1.1.0 =
    107111* Changes the method used to communicate with Unbounce servers, which will improve the resilience of
  • unbounce/trunk/templates/authorize_button.php

    r2823212 r3005252  
    33  <input type="hidden" name="user_id" />
    44  <input type="hidden" name="domain_id" />
     5  <input type="hidden" name="domain_uuid" />
    56  <input type="hidden" name="client_id" />
    67    <?php if (isset($outer_text)) { ?>
  • unbounce/trunk/templates/diagnostics.php

    r2953445 r3005252  
    3737$sni_support = 'The Unbounce Plugin communicates with the Unbounce servers using a TLS 1.2 connection, this requires SNI support in order to function. Our diagnostics indicate that your server does not currently have SNI support.';
    3838
     39$dynamic_config_retrieval = 'The Unbounce Plugin is unable to retrieve the dynamic configuration from Unbounce. This is required in order to make sure we are able to serve your Unbounce pages the correct way and prevent any errors. Please contact support if you continue to see this error for more than a few days.';
     40
     41$domain_uuid = 'Plugin requests are not sent to Unbounce servers with the uuid added as a subdomain, which compromises security. Please update wordpress enabled domains on the pages section.';
     42
    3943$diagnostic_descriptions = array(
    4044    'Curl Support' => $curl_support,
     
    4549    'Supported PHP Version' => $supported_php_version,
    4650    'Supported Wordpress Version' => $supported_wordpress_version,
    47     'SNI Support' => $sni_support
     51    'SNI Support' => $sni_support,
     52    'Dynamic Config Retrieval' => $dynamic_config_retrieval,
     53    "Domain UUID" => $domain_uuid,
    4854);
    4955
  • unbounce/trunk/templates/main_authorized_footer.php

    r2953445 r3005252  
    2222  Click here for troubleshooting and plugin diagnostics
    2323</a>
    24 <p class="ub-version">Unbounce Version 1.1.0</p>
     24<p class="ub-version">Unbounce Version 1.1.1</p>
  • unbounce/trunk/templates/main_unauthorized_footer.php

    r2953445 r3005252  
    55  Click here for troubleshooting and plugin diagnostics
    66</a>
    7 <p class="ub-version">Unbounce Version 1.1.0</p>
     7<p class="ub-version">Unbounce Version 1.1.1</p>
  • unbounce/trunk/templates/settings_response_headers_forwarded.php

    r2823212 r3005252  
    1111    $headers = array_map(function ($header) {
    1212        return '<code>'.$header.'</code>';
    13     }, UBHTTP::$response_headers_always_forwarded);
     13    }, get_option(UBConfig::UB_DYNAMIC_CONFIG_CACHE_KEY, array())['response_header_allow']);
    1414    echo implode(',', array_slice($headers, 0, -1)).' and '.end($headers);
    1515    ?>
Note: See TracChangeset for help on using the changeset viewer.