Plugin Directory

Changeset 3160131


Ignore:
Timestamp:
09/30/2024 10:30:03 PM (18 months ago)
Author:
termageddon
Message:

[1.5.0] Added five additional states for geolocation.

Location:
termageddon-usercentrics
Files:
154 added
71 edited

Legend:

Unmodified
Added
Removed
  • termageddon-usercentrics/trunk/README.txt

    r3148378 r3160131  
    55Requires at least: 3.0.1
    66Tested up to: 6.6.1
    7 Stable tag: 1.4.5
     7Stable tag: 1.5.0
    88License: GPLv2 or later
    99License URI: http://www.gnu.org/licenses/gpl-2.0.html
     
    2626
    2727== Changelog ==
     28
     29= 1.5.0 =
     30
     31-   [ADD] New states are now requiring cookie consent forms. The plugin now supports additional locations: Colorado, Virginia, Connecticut, Oregon, Texas, Utah
    2832
    2933= 1.4.5 =
  • termageddon-usercentrics/trunk/admin/class-termageddon-usercentrics-admin.php

    r3126962 r3160131  
    240240        $name        = ( isset( $options['name'] ) ? $options['name'] : false );
    241241        $description = ( isset( $options['description'] ) ? $options['description'] : false );
    242         $indent      = ( isset( $options['indent'] ) ? true === $options['indent'] : false );
    243         $slim        = ( isset( $options['slim'] ) ? true === $options['slim'] : false );
     242        // Indent specifies whether or not the subsection should be indented.
     243        $indent = ( isset( $options['indent'] ) ? true === $options['indent'] : false );
     244
     245        // Slim slims down the column width for the initial options.
     246        $slim = ( isset( $options['slim'] ) ? true === $options['slim'] : false );
     247
     248        // Helper slims down the divider and displays a helper text by itself.
     249        $helper = ( isset( $options['helper'] ) ? true === $options['helper'] : false );
     250
     251        $section_contents = $helper ?
     252        '
     253                    <span class="tu-section-title-helper">' . esc_html( $name ) . ':</span>
     254                    ' . ( empty( $description ) ? '' : '<p>' . wp_kses_post( $description ) . '</p>' )
     255        : ' </div>
     256                <div class="tu-toggle-section">
     257                    <span class="tu-section-title">' . esc_html( $name ) . ':</span>
     258                    ' . ( empty( $description ) ? '' : '<p>' . wp_kses_post( $description ) . '</p>' ) . '
     259                </div>
     260            <div class="' . ( $indent ? 'tu-toggle-section' : 'tu-settings-section' ) . ( $slim ? ' slim-section' : '' ) . '">';
    244261
    245262        add_settings_field(
    246263            'termageddon_usercentrics_end-section-' . Termageddon_Usercentrics::generate_random_string( 5 ),
    247264            '   </th></tr></tbody></table>
    248             </div>
    249             <div class="tu-toggle-section">
    250                 <span class="tu-section-title">' . esc_html( $name ) . ':</span>
    251                 ' . ( empty( $description ) ? '' : '<p>' . wp_kses_post( $description ) . '</p>' ) . '
    252             </div>
    253             <div class="' . ( $indent ? 'tu-toggle-section' : 'tu-settings-section' ) . ( $slim ? ' slim-section' : '' ) . '">
     265                ' . $section_contents . '
    254266                <table class="form-table" role="presentation">
    255267                    <tbody>
     
    263275    }
    264276
     277
     278    /** Generates and appends the popular label for a field.
     279     *
     280     *  @return string  */
     281    public static function mark_as_popular() {
     282        return ' <span class="tu-label-info">POPULAR</span>';
     283    }
    265284
    266285    /** Generates and appends the beta label for a field.
     
    635654        // ============================================ //
    636655
    637         // Show only in EU.
    638         add_settings_field(
    639             'termageddon_usercentrics_show_in_eu',
    640             __( 'European Union & European Economic Area (GDPR)', 'termageddon-usercentrics' ),
    641             array( &$this, 'show_in_eu_html' ), // function which prints the field.
    642             'termageddon-usercentrics', // page slug.
    643             'termageddon_usercentrics_section_geolocation', // section ID.
    644             array(
    645                 'label_for' => 'termageddon_usercentrics_show_in_eu',
    646             )
    647         );
    648 
    649         register_setting(
    650             'termageddon_usercentrics_settings', // settings group name.
    651             'termageddon_usercentrics_show_in_eu', // option name.
    652             '' // sanitization function.
    653         );
    654 
    655         // Show only in UK.
    656         add_settings_field(
    657             'termageddon_usercentrics_show_in_uk',
    658             __( 'United Kingdom (UK DPA)', 'termageddon-usercentrics' ),
    659             array( &$this, 'show_in_uk_html' ), // function which prints the field.
    660             'termageddon-usercentrics', // page slug.
    661             'termageddon_usercentrics_section_geolocation', // section ID.
    662             array(
    663                 'label_for' => 'termageddon_usercentrics_show_in_uk',
    664             )
    665         );
    666 
    667         register_setting(
    668             'termageddon_usercentrics_settings', // settings group name.
    669             'termageddon_usercentrics_show_in_uk', // option name.
    670             '' // sanitization function.
    671         );
    672 
    673         // Show only in Canada.
    674         add_settings_field(
    675             'termageddon_usercentrics_show_in_canada',
    676             __( 'Canada (PIPEDA)', 'termageddon-usercentrics' ),
    677             array( &$this, 'show_in_canada_html' ), // function which prints the field.
    678             'termageddon-usercentrics', // page slug.
    679             'termageddon_usercentrics_section_geolocation', // section ID.
    680             array(
    681                 'label_for' => 'termageddon_usercentrics_show_in_canada',
    682             )
    683         );
    684 
    685         register_setting(
    686             'termageddon_usercentrics_settings', // settings group name.
    687             'termageddon_usercentrics_show_in_canada', // option name.
    688             '' // sanitization function.
    689         );
     656        $register_geolocation_heading = function( $loc_key, $loc_name ) {
     657            // echo '<pre>' . json_encode( 'Register', JSON_PRETTY_PRINT ) . '</pre>';
     658            // BREAK SECTION FOR PSL SETTINGS.
     659            $this->add_new_subsection(
     660                'termageddon_usercentrics_section_geolocation',
     661                array(
     662                    'name'   => $loc_name,
     663                    'indent' => true,
     664                    'helper' => true,
     665                )
     666            );
     667        };
     668
     669        $register_geolocation = function( $loc_key, $loc ) {
     670            list ( 'title' => $loc_name, 'popular' => $loc_popular ) = $loc;
     671            add_settings_field(
     672                'termageddon_usercentrics_show_in_' . $loc_key,
     673                $loc_name . ( $loc_popular ? self::mark_as_popular() : '' ),
     674                array( &$this, 'geolocation_toggle_html' ), // function which prints the field.
     675                'termageddon-usercentrics', // page slug.
     676                'termageddon_usercentrics_section_geolocation', // section ID.
     677                array(
     678                    'label_for' => 'termageddon_usercentrics_show_in_' . $loc_key,
     679                    'location'  => $loc_key,
     680                )
     681            );
     682
     683            register_setting(
     684                'termageddon_usercentrics_settings', // settings group name.
     685                'termageddon_usercentrics_show_in_' . $loc_key, // option name.
     686                '' // sanitization function.
     687            );
     688        };
    690689
    691690        // Show only in California.
    692         add_settings_field(
    693             'termageddon_usercentrics_show_in_california',
    694             __( 'California (CPRA or CIPA)', 'termageddon-usercentrics' ),
    695             array( &$this, 'show_in_california_html' ), // function which prints the field.
    696             'termageddon-usercentrics', // page slug.
    697             'termageddon_usercentrics_section_geolocation', // section ID.
    698             array(
    699                 'label_for' => 'termageddon_usercentrics_show_in_california',
    700             )
    701         );
    702 
    703         register_setting(
    704             'termageddon_usercentrics_settings', // settings group name.
    705             'termageddon_usercentrics_show_in_california', // option name.
    706             '' // sanitization function.
    707         );
    708 
    709         // Show only in Virginia.
    710         add_settings_field(
    711             'termageddon_usercentrics_show_in_virginia',
    712             __( 'Virginia (VCDPA)', 'termageddon-usercentrics' ),
    713             array( &$this, 'show_in_virginia_html' ), // function which prints the field.
    714             'termageddon-usercentrics', // page slug.
    715             'termageddon_usercentrics_section_geolocation', // section ID.
    716             array(
    717                 'label_for' => 'termageddon_usercentrics_show_in_virginia',
    718             )
    719         );
    720 
    721         register_setting(
    722             'termageddon_usercentrics_settings', // settings group name.
    723             'termageddon_usercentrics_show_in_virginia', // option name.
    724             '' // sanitization function.
    725         );
     691        $current_section = null;
     692        foreach ( Termageddon_Usercentrics::get_geolocation_locations( true ) as $loc_key => $loc ) {
     693            list ( 'title' => $loc_name ) = $loc;
     694            if ( substr( $loc_key, 0, 8 ) === 'section_' ) { // Skip section headings.
     695                $current_section = substr( $loc_key, 8 );
     696                $register_geolocation_heading( $current_section, $loc_name );
     697                continue;
     698            }
     699            $register_geolocation( $loc_key, $loc, $current_section );
     700        }
    726701
    727702        // BREAK SECTION FOR GEOLOCATION SETTINGS.
     
    10321007
    10331008    /**
    1034      * The HTML field for the admin disable checkbox.
    1035      *
    1036      * @return void
    1037      */
    1038     public function show_in_eu_html() {
    1039         self::generate_checkbox( 'eu' );
    1040     }
    1041 
    1042     /**
    1043      * The HTML field for the admin disable checkbox.
    1044      *
    1045      * @return void
    1046      */
    1047     public function show_in_uk_html() {
    1048         self::generate_checkbox( 'uk' );
    1049 
    1050     }
    1051 
    1052     /**
    1053      * The HTML field for the admin disable checkbox.
    1054      *
    1055      * @return void
    1056      */
    1057     public function show_in_canada_html() {
    1058         self::generate_checkbox( 'canada' );
    1059 
    1060     }
    1061 
    1062     /**
    1063      * The HTML field for the admin disable checkbox.
    1064      *
    1065      * @return void
    1066      */
    1067     public function show_in_california_html() {
    1068         self::generate_checkbox( 'california' );
    1069 
    1070     }
    1071 
    1072     /**
    1073      * The HTML field for the admin disable checkbox.
    1074      *
    1075      * @return void
    1076      */
    1077     public function show_in_virginia_html() {
    1078         self::generate_checkbox( 'virginia' );
    1079 
     1009     * Generate the checkbox for the geolocation toggles.
     1010     *
     1011     * @param array $args are the arguments provided by the add_settings_field() method.
     1012     * @return void
     1013     */
     1014    public static function geolocation_toggle_html( array $args ) {
     1015        $location = $args['location'];
     1016        self::generate_checkbox( $location );
    10801017    }
    10811018
     
    11801117
    11811118        echo '<p>' .
    1182             esc_html__( 'Not sure what to select? Review', 'termageddon-usercentrics' ) . ' <a href="https://termageddon.freshdesk.com/support/solutions/articles/66000503289-how-to-activate-a-cookie-policy-and-cookie-consent-solution" target="_blank">' . esc_html__( 'this article', 'termageddon-usercentrics' ) . '</a>' . ' ' . esc_html__( 'along with page 1 of your Privacy Policy questionnaire within ', 'termageddon-usercentrics' ) . '<a href="https://app.termageddon.com/home" target="_blank">app.termageddon.com</a>.' .
     1119            esc_html__( 'Not sure what to select? Review', 'termageddon-usercentrics' ) . ' <a href="https://termageddon.freshdesk.com/support/solutions/articles/66000503289-how-to-activate-a-cookie-policy-and-cookie-consent-solution" target="_blank">' . esc_html__( 'this article', 'termageddon-usercentrics' ) . '</a> ' . esc_html__( 'along with page 1 of your Privacy Policy questionnaire within ', 'termageddon-usercentrics' ) . '<a href="https://app.termageddon.com/home" target="_blank">app.termageddon.com</a>.' .
    11831120        '</p>';
    11841121
     
    11861123            <div class="tu-section-settings">
    11871124                <div class="tu-toggle-section">
    1188                     <div class="tu-section-title">' . esc_html__( 'Show widget if visitor is located in' ) . ':</div>
    1189                     <div class="tu-section-title-helper">' . esc_html__( 'Not sure what to select? Review page 1 of your Privacy Policy questionnaire within' ) . ' <a href="https://app.termageddon.com" target="_blank">app.termageddon.com</a>.</div>
     1125                    <div class="tu-section-title">' . esc_html__( 'Show widget if visitor is located in', 'termageddon-usercentrics' ) . ':</div>
     1126                    <div class="tu-section-title-helper">' . esc_html__( 'Not sure what to select?', 'termageddon-usercentrics' ) . ' <a href="https://termageddon.freshdesk.com/support/solutions/articles/66000526304-using-the-geolocation-feature-of-the-termageddon-usercentrics-plugin" target="_blank">' . esc_html__( 'This article outlines which regions to select', 'termageddon-usercentrics' ) . '</a> ' . esc_html__( 'based on which privacy laws apply to you', 'termageddon-usercentrics' ) . '.</div>
    11901127                    <div class="notice-inline notice-alt notice-warning" id="no-geolocation-locations-selected" style="display:none">
    11911128                        <p><strong>' . esc_html__( 'Geo-Location is enabled, but no locations have been toggled on. This means that the cookie-consent will be hidden to all users.', 'termageddon-usercentrics' ) . '</strong></p>
  • termageddon-usercentrics/trunk/admin/css/termageddon-usercentrics-admin.css

    r3049451 r3160131  
    3838    padding: 0.5rem 0;
    3939}
     40.tu-toggle-section .form-table th {
     41    width: 300px;
     42}
    4043.tu-toggle-section.slim-section .form-table th {
    4144    width: 125px;
     
    4952.tu-section-hidden {
    5053    display: none;
     54}
     55.tu-label-success {
     56    background-color: #3db44c;
     57    color: white;
     58    padding: 3px 5px;
     59    border-radius: 5px;
     60    font-size: 60%;
     61}
     62.tu-label-info {
     63    background-color: #019ed5;
     64    color: white;
     65    padding: 3px 5px;
     66    border-radius: 5px;
     67    font-size: 60%;
    5168}
    5269.tu-label-warning {
  • termageddon-usercentrics/trunk/admin/css/termageddon-usercentrics-admin.min.css

    r3049451 r3160131  
    1 textarea.termageddon-embed-code{width:100%;height:250px}.tu-section-settings,.tu-toggle-section{margin-top:2rem}.tu-toggle-section .tu-section-title{font-size:125%;font-weight:800}.tu-toggle-section .tu-section-title-helper{padding:1rem;color:#6c6c6c;font-style:italic}.tu-toggle-section input[readonly]{opacity:50%;pointer-events:none}.tu-toggle-section .form-table{margin-left:2rem}.tu-toggle-section .form-table td,.tu-toggle-section .form-table th{padding:.5rem 0}.tu-toggle-section.slim-section .form-table th{width:125px}.tu-settings-section .form-table th{width:300px}.tu-section-hidden{display:none}.tu-label-warning{background-color:orange;color:#fff;padding:3px 5px;border-radius:5px;font-size:60%}input[type=checkbox].wppd-ui-toggle{-webkit-appearance:none;-moz-appearance:none;appearance:none;-webkit-tap-highlight-color:transparent;width:auto;height:auto;vertical-align:middle;position:relative;border:0;outline:0;cursor:pointer;margin:0 4px;background:0 0;box-shadow:none}input[type=checkbox].wppd-ui-toggle:focus{box-shadow:none}input[type=checkbox].wppd-ui-toggle:after{content:"";font-size:6px;font-weight:400;line-height:18px;text-indent:-14px;color:#fff;width:36px;height:18px;display:inline-block;background-color:#a7aaad;border-radius:72px;box-shadow:0 0 12px rgb(0 0 0 / 15%) inset}input[type=checkbox].wppd-ui-toggle:before{content:"";width:14px;height:14px;display:block;position:absolute;top:2px;left:2px;margin:0;border-radius:50%;background-color:#fff}input[type=checkbox].wppd-ui-toggle:checked:before{left:20px;margin:0;background-color:#fff}input[type=checkbox].wppd-ui-toggle,input[type=checkbox].wppd-ui-toggle:after,input[type=checkbox].wppd-ui-toggle:before,input[type=checkbox].wppd-ui-toggle:checked:after,input[type=checkbox].wppd-ui-toggle:checked:before{transition:ease .15s}input[type=checkbox].wppd-ui-toggle:checked:after{content:"ON";background-color:#2271b1}input[type=checkbox].wppd-ui-toggle.label-hidden:after{width:48px}input[type=checkbox].wppd-ui-toggle.label-hidden:checked:before{left:32px}input[type=checkbox].wppd-ui-toggle.label-hidden:checked:after{content:"HIDDEN"}input[type=checkbox].wppd-ui-toggle.label-enabled:after{font-size:8px;width:60px;content:"DISABLED";text-indent:15px}input[type=checkbox].wppd-ui-toggle.label-enabled:checked:before{left:44px}input[type=checkbox].wppd-ui-toggle.label-enabled:checked:after{background-color:#1ed14b;content:"ENABLED";text-indent:-14px}.notice-inline{border-top:1px solid #c3c4c7;border-bottom:1px solid #c3c4c7;border-right:1px solid #c3c4c7;border-left-width:4px;border-left-style:solid;background:#fff;box-shadow:0 1px 1px rgba(0,0,0,.04);margin:5px 15px 2px;padding:1px 12px}.tu-settings-section label em{font-size:12px;font-weight:400}
     1textarea.termageddon-embed-code{width:100%;height:250px}.tu-section-settings,.tu-toggle-section{margin-top:2rem}.tu-toggle-section .tu-section-title{font-size:125%;font-weight:800}.tu-toggle-section .tu-section-title-helper{padding:1rem;color:#6c6c6c;font-style:italic}.tu-toggle-section input[readonly]{opacity:50%;pointer-events:none}.tu-toggle-section .form-table{margin-left:2rem}.tu-toggle-section .form-table td,.tu-toggle-section .form-table th{padding:.5rem 0}.tu-toggle-section .form-table th{width:300px}.tu-toggle-section.slim-section .form-table th{width:125px}.tu-settings-section .form-table th{width:300px}.tu-section-hidden{display:none}.tu-label-success{background-color:#3db44c;color:#fff;padding:3px 5px;border-radius:5px;font-size:60%}.tu-label-info{background-color:#019ed5;color:#fff;padding:3px 5px;border-radius:5px;font-size:60%}.tu-label-warning{background-color:orange;color:#fff;padding:3px 5px;border-radius:5px;font-size:60%}input[type=checkbox].wppd-ui-toggle{-webkit-appearance:none;-moz-appearance:none;appearance:none;-webkit-tap-highlight-color:transparent;width:auto;height:auto;vertical-align:middle;position:relative;border:0;outline:0;cursor:pointer;margin:0 4px;background:0 0;box-shadow:none}input[type=checkbox].wppd-ui-toggle:focus{box-shadow:none}input[type=checkbox].wppd-ui-toggle:after{content:"";font-size:6px;font-weight:400;line-height:18px;text-indent:-14px;color:#fff;width:36px;height:18px;display:inline-block;background-color:#a7aaad;border-radius:72px;box-shadow:0 0 12px rgb(0 0 0 / 15%) inset}input[type=checkbox].wppd-ui-toggle:before{content:"";width:14px;height:14px;display:block;position:absolute;top:2px;left:2px;margin:0;border-radius:50%;background-color:#fff}input[type=checkbox].wppd-ui-toggle:checked:before{left:20px;margin:0;background-color:#fff}input[type=checkbox].wppd-ui-toggle,input[type=checkbox].wppd-ui-toggle:after,input[type=checkbox].wppd-ui-toggle:before,input[type=checkbox].wppd-ui-toggle:checked:after,input[type=checkbox].wppd-ui-toggle:checked:before{transition:ease .15s}input[type=checkbox].wppd-ui-toggle:checked:after{content:"ON";background-color:#2271b1}input[type=checkbox].wppd-ui-toggle.label-hidden:after{width:48px}input[type=checkbox].wppd-ui-toggle.label-hidden:checked:before{left:32px}input[type=checkbox].wppd-ui-toggle.label-hidden:checked:after{content:"HIDDEN"}input[type=checkbox].wppd-ui-toggle.label-enabled:after{font-size:8px;width:60px;content:"DISABLED";text-indent:15px}input[type=checkbox].wppd-ui-toggle.label-enabled:checked:before{left:44px}input[type=checkbox].wppd-ui-toggle.label-enabled:checked:after{background-color:#1ed14b;content:"ENABLED";text-indent:-14px}.notice-inline{border-top:1px solid #c3c4c7;border-bottom:1px solid #c3c4c7;border-right:1px solid #c3c4c7;border-left-width:4px;border-left-style:solid;background:#fff;box-shadow:0 1px 1px rgba(0,0,0,.04);margin:5px 15px 2px;padding:1px 12px}.tu-settings-section label em{font-size:12px;font-weight:400}
  • termageddon-usercentrics/trunk/includes/class-termageddon-usercentrics.php

    r3126965 r3160131  
    110110
    111111    /**
     112     *  Returns a key value pair of geolocations to iterate over.
     113     *  To add support for a new state, add a new key to the array and add the state to the $GEOLOCATION_KEY_TO_STATE array.
     114     *
     115     *  @param boolean $include_sections Whether or not to include the section keys. Defaults to false.
     116     *  @return array
     117     */
     118    public static function get_geolocation_locations( $include_sections = false ): array {
     119        $list = array(
     120            'eu'          => array(
     121                'title'   => __( 'European Union & European Economic Area (GDPR)', 'termageddon-usercentrics' ),
     122                'popular' => true,
     123            ),
     124            'uk'          => array(
     125                'title'   => __( 'United Kingdom (UK DPA)', 'termageddon-usercentrics' ),
     126                'popular' => true,
     127            ),
     128            'canada'      => array(
     129                'title'   => __( 'Canada (PIPEDA, Quebec 25)', 'termageddon-usercentrics' ),
     130                'popular' => true,
     131            ),
     132            'section_usa' => array(
     133                'title'   => __( 'United States of America', 'termageddon-usercentrics' ),
     134                'popular' => false,
     135            ),
     136            'california'  => array(
     137                'title'   => __( 'California (CPRA, CIPA)', 'termageddon-usercentrics' ),
     138                'popular' => true,
     139            ),
     140            'colorado'    => array(
     141                'title'   => __( 'Colorado (CPA)', 'termageddon-usercentrics' ),
     142                'popular' => false,
     143            ),
     144            'connecticut' => array(
     145                'title'   => __( 'Connecticut (CTDPA)', 'termageddon-usercentrics' ),
     146                'popular' => false,
     147            ),
     148            'oregon'      => array(
     149                'title'   => __( 'Oregon (OCPA)', 'termageddon-usercentrics' ),
     150                'popular' => false,
     151            ),
     152            'texas'       => array(
     153                'title'   => __( 'Texas (TDPSA)', 'termageddon-usercentrics' ),
     154                'popular' => false,
     155            ),
     156            'utah'        => array(
     157                'title'   => __( 'Utah (UCPA)', 'termageddon-usercentrics' ),
     158                'popular' => false,
     159            ),
     160            'virginia'    => array(
     161                'title'   => __( 'Virginia (VCDPA)', 'termageddon-usercentrics' ),
     162                'popular' => false,
     163            ),
     164        );
     165
     166        if ( $include_sections ) {
     167            return $list;
     168        }
     169        return array_filter(
     170            $list,
     171            function( $key ) {
     172                return strpos( $key, 'section_' ) !== 0;
     173            },
     174            ARRAY_FILTER_USE_KEY
     175        );
     176    }
     177
     178    /**
     179     *  Maps the geolocation key to the state returned by the geolocation lookup.
     180     *
     181     *  @return array of key value matchups
     182     */
     183    public const GEOLOCATION_KEY_TO_STATE = array(
     184        'california'  => 'California',
     185        'colorado'    => 'Colorado',
     186        'connecticut' => 'Connecticut',
     187        'oregon'      => 'Oregon',
     188        'texas'       => 'Texas',
     189        'utah'        => 'Utah',
     190        'virginia'    => 'Virginia',
     191    );
     192
     193    /**
    112194     * Load the required dependencies for this plugin.
    113195     *
     
    9731055     */
    9741056    public static function is_geoip_location_enabled(): bool {
    975         $show_in_eu         = get_option( 'termageddon_usercentrics_show_in_eu', false ) ? true : false;
    976         $show_in_uk         = get_option( 'termageddon_usercentrics_show_in_uk', false ) ? true : false;
    977         $show_in_canada     = get_option( 'termageddon_usercentrics_show_in_canada', false ) ? true : false;
    978         $show_in_california = get_option( 'termageddon_usercentrics_show_in_california', false ) ? true : false;
    979         $show_in_virginia   = get_option( 'termageddon_usercentrics_show_in_virginia', false ) ? true : false;
    980         return ( $show_in_eu || $show_in_uk || $show_in_canada || $show_in_california || $show_in_virginia );
     1057        $enabled = false;
     1058
     1059        foreach ( self::get_geolocation_locations() as $loc_key => $loc ) {
     1060            if ( self::is_geoip_location_enabled_in( $loc_key ) ) {
     1061                $enabled = true;
     1062                break;
     1063            }
     1064        }
     1065        return $enabled;
     1066    }
     1067
     1068    /**
     1069     * Identifies if geoip location is required for a specific location.
     1070     *
     1071     * @param string $loc_key The location key to check.
     1072     * @return bool
     1073     */
     1074    public static function is_geoip_location_enabled_in( string $loc_key ): bool {
     1075        return get_option( 'termageddon_usercentrics_show_in_' . $loc_key, false ) ? true : false;
    9811076    }
    9821077
     
    10111106     * Helper method to identify if the user is located in Colorado.
    10121107     *
    1013      * @return bool  */
    1014     public static function is_located_in_colorado(): bool {
     1108     * @param string $loc_key The location key to check.
     1109     * @return bool
     1110     * @throws Exception If unable to locate location key.
     1111     */
     1112    public static function is_located_in( string $loc_key ): bool {
     1113        $function_name = 'is_located_in_' . $loc_key;
     1114        if ( is_callable( array( self::class, $function_name ) ) ) {
     1115            return call_user_func( array( self::class, $function_name ) );
     1116        }
     1117        // Default to state. Check if state mapping exists.
     1118        if ( ! array_key_exists( $loc_key, self::GEOLOCATION_KEY_TO_STATE ) ) {
     1119            throw new Exception( 'Unable to locate location key for ' . $loc_key );
     1120        }
     1121
     1122        $loc_key                  = self::GEOLOCATION_KEY_TO_STATE[ $loc_key ];
    10151123        list( 'state' => $state ) = self::lookup_ip_address();
    1016         return ( null === $state || 'Colorado' === $state );
    1017 
    1018     }
    1019 
    1020     /**
    1021      * Helper method to identify if the user is located in California.
    1022      *
    1023      * @return bool  */
    1024     public static function is_located_in_california(): bool {
    1025         list( 'state' => $state ) = self::lookup_ip_address();
    1026         return ( null === $state || 'California' === $state );
    1027 
    1028     }
    1029 
    1030     /**
    1031      * Helper method to identify if the user is located in Virginia.
    1032      *
    1033      * @return bool  */
    1034     public static function is_located_in_virginia(): bool {
    1035         list( 'state' => $state ) = self::lookup_ip_address();
    1036         return ( null === $state || 'Virginia' === $state );
     1124        return ( null === $state || $loc_key === $state );
    10371125
    10381126    }
     
    11081196     * @return bool  */
    11091197    public static function should_hide_due_to_location(): bool {
    1110         $show_in_eu         = get_option( 'termageddon_usercentrics_show_in_eu', false ) ? true : false;
    1111         $show_in_uk         = get_option( 'termageddon_usercentrics_show_in_uk', false ) ? true : false;
    1112         $show_in_canada     = get_option( 'termageddon_usercentrics_show_in_canada', false ) ? true : false;
    1113         $show_in_california = get_option( 'termageddon_usercentrics_show_in_california', false ) ? true : false;
    1114         $show_in_virginia   = get_option( 'termageddon_usercentrics_show_in_virginia', false ) ? true : false;
    1115 
    1116         // Hide if all of the rules come back negative for specific locations.
    1117         $located_in_eu         = self::is_located_in_eu();
    1118         $located_in_uk         = self::is_located_in_uk();
    1119         $located_in_canada     = self::is_located_in_canada();
    1120         $located_in_california = self::is_located_in_california();
    1121         $located_in_virginia   = self::is_located_in_virginia();
     1198
     1199        // Iterate through locations and identify if user is located in any of them, and site has it enabled. If so, hide consent.
     1200        $located_in_location_that_needs_consent = false;
     1201        foreach ( self::get_geolocation_locations() as $loc_key => $loc ) {
     1202            $is_located_in = self::is_located_in( $loc_key );
     1203            if ( $is_located_in ) {
     1204                $located_in_location_that_needs_consent = true;
     1205            }
     1206            if ( $is_located_in && ! self::is_geoip_location_enabled_in( $loc_key ) ) {
     1207                return true; // User is located in a location that needs it, but it is disabled, so hide.
     1208            }
     1209        }
    11221210
    11231211        // If not in any applicable zones, hide cookie consent.
    1124         if ( ! $located_in_eu && ! $located_in_uk && ! $located_in_canada && ! $located_in_california && ! $located_in_virginia ) {
    1125             return true;
    1126         }
    1127 
    1128         // Based on where you are located, check the location.
    1129         if ( $located_in_eu && ! $show_in_eu ) {
    1130             return true;
    1131         }
    1132         if ( $located_in_uk && ! $show_in_uk ) {
    1133             return true;
    1134         }
    1135         if ( $located_in_canada && ! $show_in_canada ) {
    1136             return true;
    1137         }
    1138         if ( $located_in_california && ! $show_in_california ) {
    1139             return true;
    1140         }
    1141         if ( $located_in_virginia && ! $show_in_virginia ) {
    1142             return true;
     1212        if ( ! $located_in_location_that_needs_consent ) {
     1213            return true; // Not in a location that needs it, so continue.
    11431214        }
    11441215
     
    11831254            list('city' => $city, 'state' => $state, 'country' => $country) = self::lookup_ip_address( $ip_address );
    11841255
    1185             $result['ipAddress']    = $ip_address;
    1186             $result['city']         = ( $city ?? 'Unknown' );
    1187             $result['state']        = ( $state ?? 'Unknown' );
    1188             $result['country']      = ( $country ?? 'Unknown' );
    1189             $result['inEU']         = self::is_located_in_eu();
    1190             $result['inUK']         = self::is_located_in_uk();
    1191             $result['inCanada']     = self::is_located_in_canada();
    1192             $result['inCalifornia'] = self::is_located_in_california();
    1193             $result['inVirginia']   = self::is_located_in_virginia();
     1256            $result['ipAddress'] = $ip_address;
     1257            $result['city']      = ( $city ?? 'Unknown' );
     1258            $result['state']     = ( $state ?? 'Unknown' );
     1259            $result['country']   = ( $country ?? 'Unknown' );
     1260
     1261            // Iterate through locations.
     1262            $locations = array();
     1263            foreach ( self::get_geolocation_locations() as $loc_key => $loc ) {
     1264                $locations[ $loc_key ] = self::is_located_in( $loc_key );
     1265            }
     1266            $result['locations'] = $locations;
    11941267        }
    11951268
  • termageddon-usercentrics/trunk/languages/termageddon-usercentrics.pot

    r3126962 r3160131  
    44"Project-Id-Version: Termageddon + Usercentrics\n"
    55"Report-Msgid-Bugs-To: \n"
    6 "POT-Creation-Date: 2024-07-29 01:53+0000\n"
     6"POT-Creation-Date: 2024-09-24 04:08+0000\n"
    77"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
    88"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
     
    1717"X-Domain: termageddon-usercentrics"
    1818
    19 #: admin/class-termageddon-usercentrics-admin.php:394
     19#: admin/class-termageddon-usercentrics-admin.php:413
    2020msgid "Administrators"
    2121msgstr ""
     
    2929msgstr ""
    3030
    31 #: admin/class-termageddon-usercentrics-admin.php:1182
     31#: admin/class-termageddon-usercentrics-admin.php:1119
    3232msgid "along with page 1 of your Privacy Policy questionnaire within "
    3333msgstr ""
    3434
    35 #: admin/class-termageddon-usercentrics-admin.php:694
    36 msgid "California (CPRA or CIPA)"
    37 msgstr ""
    38 
    39 #: admin/class-termageddon-usercentrics-admin.php:676
    40 msgid "Canada (PIPEDA)"
     35#: admin/class-termageddon-usercentrics-admin.php:1126
     36msgid "based on which privacy laws apply to you"
     37msgstr ""
     38
     39#: includes/class-termageddon-usercentrics.php:137
     40msgid "California (CPRA, CIPA)"
     41msgstr ""
     42
     43#: includes/class-termageddon-usercentrics.php:129
     44msgid "Canada (PIPEDA, Quebec 25)"
     45msgstr ""
     46
     47#: includes/class-termageddon-usercentrics.php:141
     48msgid "Colorado (CPA)"
     49msgstr ""
     50
     51#: includes/class-termageddon-usercentrics.php:145
     52msgid "Connecticut (CTDPA)"
    4153msgstr ""
    4254
    4355#. section ID.
    44 #: admin/class-termageddon-usercentrics-admin.php:786
     56#: admin/class-termageddon-usercentrics-admin.php:761
    4557msgid "Control Panel"
    4658msgstr ""
    4759
    48 #: admin/class-termageddon-usercentrics-admin.php:1142
     60#: admin/class-termageddon-usercentrics-admin.php:1079
    4961msgid "Cookie Policy and Consent Solution"
    5062msgstr ""
     
    5466msgstr ""
    5567
    56 #: admin/class-termageddon-usercentrics-admin.php:592
     68#: admin/class-termageddon-usercentrics-admin.php:611
    5769msgid "Disable for Troubleshooting"
    5870msgstr ""
    5971
    60 #: admin/class-termageddon-usercentrics-admin.php:505
     72#: admin/class-termageddon-usercentrics-admin.php:524
    6173msgid "Divi Video Player Integration"
    6274msgstr ""
     
    6880msgstr ""
    6981
    70 #: admin/class-termageddon-usercentrics-admin.php:412
     82#: admin/class-termageddon-usercentrics-admin.php:431
    7183msgid "Editors"
    7284msgstr ""
    7385
    74 #: admin/class-termageddon-usercentrics-admin.php:524
     86#: admin/class-termageddon-usercentrics-admin.php:543
    7587msgid "Elementor Video Player Integration"
    7688msgstr ""
    7789
    7890#: admin/class-termageddon-usercentrics-admin.php:170
    79 #: admin/class-termageddon-usercentrics-admin.php:357
     91#: admin/class-termageddon-usercentrics-admin.php:376
    8092msgid "Embed Code"
    8193msgstr ""
    8294
    83 #: admin/class-termageddon-usercentrics-admin.php:570
     95#: admin/class-termageddon-usercentrics-admin.php:589
    8496msgid "Embed Code Priority"
    8597msgstr ""
    8698
    87 #: admin/class-termageddon-usercentrics-admin.php:739
     99#: admin/class-termageddon-usercentrics-admin.php:714
    88100msgid "Enable location logging"
    89101msgstr ""
    90102
    91 #: admin/class-termageddon-usercentrics-admin.php:759
     103#: admin/class-termageddon-usercentrics-admin.php:734
    92104msgid "Enable page caching support via AJAX"
    93105msgstr ""
    94106
    95 #: admin/class-termageddon-usercentrics-admin.php:800
     107#: admin/class-termageddon-usercentrics-admin.php:775
    96108msgid "Error Count"
    97109msgstr ""
     
    101113msgstr ""
    102114
    103 #: admin/class-termageddon-usercentrics-admin.php:818
     115#: admin/class-termageddon-usercentrics-admin.php:793
    104116msgid "Error List"
    105117msgstr ""
    106118
    107 #: admin/class-termageddon-usercentrics-admin.php:640
     119#: includes/class-termageddon-usercentrics.php:121
    108120msgid "European Union & European Economic Area (GDPR)"
    109121msgstr ""
    110122
    111 #: includes/class-termageddon-usercentrics.php:225
     123#: includes/class-termageddon-usercentrics.php:307
    112124msgid "Every Month"
    113125msgstr ""
    114126
    115 #: admin/class-termageddon-usercentrics-admin.php:483
     127#: admin/class-termageddon-usercentrics-admin.php:502
    116128msgid ""
    117129"For some theme builders including Divi, the footer (bottom bar) does not "
     
    123135#. section ID.
    124136#: admin/class-termageddon-usercentrics-admin.php:172
    125 #: admin/class-termageddon-usercentrics-admin.php:620
     137#: admin/class-termageddon-usercentrics-admin.php:639
    126138msgid "Geo-Location"
    127139msgstr ""
    128140
    129141#: admin/class-termageddon-usercentrics-admin.php:143
    130 #: admin/class-termageddon-usercentrics-admin.php:1191
     142#: admin/class-termageddon-usercentrics-admin.php:1128
    131143msgid ""
    132144"Geo-Location is enabled, but no locations have been toggled on. This means "
     
    158170msgstr ""
    159171
    160 #: admin/class-termageddon-usercentrics-admin.php:458
     172#: admin/class-termageddon-usercentrics-admin.php:477
    161173msgid "Hide Privacy Settings Link when cookie consent tool is disabled"
    162174msgstr ""
     
    166178msgstr ""
    167179
    168 #: admin/class-termageddon-usercentrics-admin.php:1160
     180#: admin/class-termageddon-usercentrics-admin.php:1097
    169181msgid "If you are using the Divi theme"
    170182msgstr ""
    171183
    172 #: admin/class-termageddon-usercentrics-admin.php:1159
     184#: admin/class-termageddon-usercentrics-admin.php:1096
    173185msgid ""
    174186"If you would like to remove Usercentrics for logged in users such as admins, "
     
    184196msgstr ""
    185197
    186 #: admin/class-termageddon-usercentrics-admin.php:430
     198#: admin/class-termageddon-usercentrics-admin.php:449
    187199msgid "Logged-in Users"
    188200msgstr ""
    189201
    190 #: admin/class-termageddon-usercentrics-admin.php:1182
     202#: admin/class-termageddon-usercentrics-admin.php:1126
     203msgid "Not sure what to select?"
     204msgstr ""
     205
     206#: admin/class-termageddon-usercentrics-admin.php:1119
    191207msgid "Not sure what to select? Review"
    192208msgstr ""
    193209
    194 #: admin/class-termageddon-usercentrics-admin.php:576
     210#: includes/class-termageddon-usercentrics.php:149
     211msgid "Oregon (OCPA)"
     212msgstr ""
     213
     214#: admin/class-termageddon-usercentrics-admin.php:595
    195215msgid ""
    196216"Override the default priority of the embed code (Defaults to 1). By "
     
    206226msgstr ""
    207227
    208 #: admin/class-termageddon-usercentrics-admin.php:543
     228#: admin/class-termageddon-usercentrics-admin.php:562
    209229msgid "Presto Player"
    210230msgstr ""
    211231
    212 #: admin/class-termageddon-usercentrics-admin.php:477
     232#: admin/class-termageddon-usercentrics-admin.php:496
    213233msgid "Privacy Settings Link - Alternative Implementation"
    214234msgstr ""
    215235
    216236#. section ID.
    217 #: includes/class-termageddon-usercentrics.php:411
     237#: includes/class-termageddon-usercentrics.php:492
    218238#: admin/class-termageddon-usercentrics-admin.php:171
    219 #: admin/class-termageddon-usercentrics-admin.php:385
     239#: admin/class-termageddon-usercentrics-admin.php:404
    220240msgid "Settings"
     241msgstr ""
     242
     243#: admin/class-termageddon-usercentrics-admin.php:1125
     244msgid "Show widget if visitor is located in"
    221245msgstr ""
    222246
     
    230254msgstr ""
    231255
    232 #: admin/class-termageddon-usercentrics-admin.php:1182
     256#: includes/class-termageddon-usercentrics.php:153
     257msgid "Texas (TDPSA)"
     258msgstr ""
     259
     260#: admin/class-termageddon-usercentrics-admin.php:1119
    233261msgid "this article"
     262msgstr ""
     263
     264#: admin/class-termageddon-usercentrics-admin.php:1126
     265msgid "This article outlines which regions to select"
    234266msgstr ""
    235267
     
    240272msgstr ""
    241273
    242 #: admin/class-termageddon-usercentrics-admin.php:506
     274#: admin/class-termageddon-usercentrics-admin.php:525
    243275msgid ""
    244276"This resolves and improves the cookie-consent implementation when using an "
     
    246278msgstr ""
    247279
    248 #: admin/class-termageddon-usercentrics-admin.php:525
     280#: admin/class-termageddon-usercentrics-admin.php:544
    249281msgid ""
    250282"This resolves and improves the cookie-consent implementation when using an "
     
    252284msgstr ""
    253285
    254 #: admin/class-termageddon-usercentrics-admin.php:1203
     286#: admin/class-termageddon-usercentrics-admin.php:1140
    255287msgid ""
    256288"To reset any of the backend variables, update the values below and save your "
     
    258290msgstr ""
    259291
    260 #: admin/class-termageddon-usercentrics-admin.php:658
     292#: includes/class-termageddon-usercentrics.php:125
    261293msgid "United Kingdom (UK DPA)"
    262294msgstr ""
    263295
    264 #: admin/class-termageddon-usercentrics-admin.php:1141
     296#: includes/class-termageddon-usercentrics.php:133
     297msgid "United States of America"
     298msgstr ""
     299
     300#: admin/class-termageddon-usercentrics-admin.php:1078
    265301msgid "Upon generating your "
    266302msgstr ""
    267303
    268 #: admin/class-termageddon-usercentrics-admin.php:1127
     304#: admin/class-termageddon-usercentrics-admin.php:1064
    269305msgid "Upon saving, all previous errors in the log will be deleted."
    270306msgstr ""
    271307
    272 #: admin/class-termageddon-usercentrics-admin.php:712
     308#: includes/class-termageddon-usercentrics.php:157
     309msgid "Utah (UCPA)"
     310msgstr ""
     311
     312#: includes/class-termageddon-usercentrics.php:161
    273313msgid "Virginia (VCDPA)"
    274314msgstr ""
     
    281321msgstr ""
    282322
    283 #: admin/class-termageddon-usercentrics-admin.php:464
     323#: admin/class-termageddon-usercentrics-admin.php:483
    284324msgid ""
    285325"When enabled, the Privacy Settings link will be hidden from certain users, "
     
    294334msgstr ""
    295335
    296 #: admin/class-termageddon-usercentrics-admin.php:745
     336#: admin/class-termageddon-usercentrics-admin.php:720
    297337msgid ""
    298338"When enabled, the visitor's location can be viewed in the browser console, "
     
    300340msgstr ""
    301341
    302 #: admin/class-termageddon-usercentrics-admin.php:765
     342#: admin/class-termageddon-usercentrics-admin.php:740
    303343msgid ""
    304344"When enabled, the visitor's location is checked via javascript to allow "
     
    306346msgstr ""
    307347
    308 #: admin/class-termageddon-usercentrics-admin.php:598
     348#: admin/class-termageddon-usercentrics-admin.php:617
    309349msgid ""
    310350"When enabled, this feature allows you to turn off the consent tool for all "
     
    315355msgstr ""
    316356
    317 #: admin/class-termageddon-usercentrics-admin.php:1178
     357#: admin/class-termageddon-usercentrics-admin.php:1115
    318358msgid ""
    319359"When enabled, you will be collecting IP addresses for the purposes of "
     
    331371msgstr ""
    332372
    333 #: admin/class-termageddon-usercentrics-admin.php:1143
     373#: admin/class-termageddon-usercentrics-admin.php:1080
    334374msgid ""
    335375"within your Termageddon account, you will be brought to the \"View embed "
     
    338378msgstr ""
    339379
    340 #: admin/class-termageddon-usercentrics-admin.php:1161
     380#: admin/class-termageddon-usercentrics-admin.php:1098
    341381msgid ""
    342382"you will need to enable at least one of the settings below to ensure logged "
  • termageddon-usercentrics/trunk/public/class-termageddon-usercentrics-public.php

    r3148378 r3160131  
    135135                list('city' => $city, 'state' => $state, 'country' => $country) = Termageddon_Usercentrics::lookup_ip_address();
    136136
     137                // Iterate through locations.
     138                $locations = array_map(
     139                    function( $loc_key, $loc ) {
     140                        list ( 'title' => $loc_name ) = $loc;
     141                        return 'Located in ' . $loc_name . ': ' . ( Termageddon_Usercentrics::is_located_in( $loc_key ) ? 'Yes' : 'No' );
     142                    },
     143                    Termageddon_Usercentrics::get_geolocation_locations()
     144                );
     145
    137146                // Output debug message to console.
    138147                Termageddon_Usercentrics::debug(
     
    142151                    'Country: ' . ( $country ?? 'Unknown' ),
    143152                    '--',
    144                     'Located in EU?: ' . ( Termageddon_Usercentrics::is_located_in_eu() ? 'Yes' : 'No' ),
    145                     'Located in UK?: ' . ( Termageddon_Usercentrics::is_located_in_uk() ? 'Yes' : 'No' ),
    146                     'Located in Canada?: ' . ( Termageddon_Usercentrics::is_located_in_canada() ? 'Yes' : 'No' ),
    147                     'Located in California?: ' . ( Termageddon_Usercentrics::is_located_in_california() ? 'Yes' : 'No' ),
    148                     'Located in Virginia?: ' . ( Termageddon_Usercentrics::is_located_in_virginia() ? 'Yes' : 'No' ),
     153                    $locations,
    149154                    '--',
    150155                    'Geo-Location Mode?: ' . ( Termageddon_Usercentrics::is_geoip_enabled() ? 'Yes' : 'No' ),
  • termageddon-usercentrics/trunk/public/js/termageddon-usercentrics-ajax.js

    r3104855 r3160131  
    126126                            (data.country || "Unknown") +
    127127                            "\n" +
    128                             "--" +
    129                             "\n" +
    130                             "Located in EU?: " +
    131                             (data.inEU ? "Yes" : "No") +
    132                             "\n" +
    133                             "Located in UK?: " +
    134                             (data.inUK ? "Yes" : "No") +
    135                             "\n" +
    136                             "Located in Canada?: " +
    137                             (data.inCanada ? "Yes" : "No") +
    138                             "\n" +
    139                             "Located in California?: " +
    140                             (data.inCalifornia ? "Yes" : "No") +
    141                             "\n" +
    142                             "Located in Virginia?: " +
    143                             (data.inVirginia ? "Yes" : "No")
     128                            "Locations: ",
     129                        data.locations
    144130                    );
    145131                }
  • termageddon-usercentrics/trunk/public/js/termageddon-usercentrics-ajax.min.js

    r3104855 r3160131  
    1 const tuCookieHideName="tu-geoip-hide",tuDebug="true"===termageddon_usercentrics_obj.debug,tuPSLHide="true"===termageddon_usercentrics_obj.psl_hide;tuDebug&&console.log("UC: AJAX script initialized"),window.addEventListener("UC_UI_INITIALIZED",(function(){const getCookie=name=>{const value=`; ${document.cookie}`,parts=value.split(`; ${name}=`);if(2===parts.length)return parts.pop().split(";").shift()},getQueryParams=param=>{const params=new Proxy(new URLSearchParams(window.location.search),{get:(searchParams,prop)=>searchParams.get(prop)});return params[param]},setCookie=(name,value,days)=>{var expires="";if(days){var date=new Date;date.setTime(date.getTime()+24*days*60*60*1e3),expires="; expires="+date.toUTCString()}document.cookie=name+"="+(value||"")+expires+"; path=/"},updateCookieConsent=hide=>{if(!hide)return tuDebug&&console.log("UC: Showing consent widget"),tuPSLHide&&jQuery("#usercentrics-psl, .usercentrics-psl").show(),jQuery("div#usercentrics-root").show(),UC_UI.isConsentRequired()?UC_UI.showFirstLayer():UC_UI.closeCMP();tuDebug&&console.log("UC: Hiding consent widget"),tuPSLHide&&jQuery("#usercentrics-psl, .usercentrics-psl").hide(),jQuery("div#usercentrics-root").hide(),UC_UI.areAllConsentsAccepted()||UC_UI.acceptAllConsents().then(()=>{tuDebug&&console.log("UC: All consents have been accepted."),UC_UI.closeCMP().then(()=>{tuDebug&&console.log("UC: CMP Widget has been closed.")})})};if("undefined"==typeof UC_UI)return console.error("Usercentrics not loaded");const query_hide=""===getQueryParams("enable-usercentrics"),cookie_hide=getCookie("tu-geoip-hide");if(null==cookie_hide||tuDebug){tuDebug&&console.log("UC: Making AJAX Call");var data={action:"uc_geolocation_lookup",nonce:termageddon_usercentrics_obj.nonce};void 0!==termageddon_usercentrics_obj.location&&(data.location=termageddon_usercentrics_obj.location),jQuery.post(termageddon_usercentrics_obj.ajax_url,data).done((function(response){if(!response.success)return console.error("Unable to lookup location.",response.message||"");if(!response.data)return console.error("Location data was not provided.",response.data);const data=response.data;if(tuDebug&&console.log("TERMAGEDDON USERCENTRICS (AJAX)\nIP Address: "+data.ipAddress+"\nCity: "+(data.city||"Unknown")+"\nState: "+(data.state||"Unknown")+"\nCountry: "+(data.country||"Unknown")+"\n--\nLocated in EU?: "+(data.inEU?"Yes":"No")+"\nLocated in UK?: "+(data.inUK?"Yes":"No")+"\nLocated in Canada?: "+(data.inCanada?"Yes":"No")+"\nLocated in California?: "+(data.inCalifornia?"Yes":"No")+"\nLocated in Virginia?: "+(data.inVirginia?"Yes":"No")),query_hide)return tuDebug&&console.log("UC: Enabling due to query parameter override.","Showing Usercentrics"),updateCookieConsent(!1);setCookie("tu-geoip-hide",data.hide?"true":"false"),updateCookieConsent(data.hide)})).fail((function(response){console.error("Usercentrics: Invalid response returned. Showing widget as a default.",response),updateCookieConsent(!1)}))}else tuDebug&&console.log("UC: Cookie found.",(cookie_hide?"Showing":"Hiding")+" Usercentrics"),updateCookieConsent("true"===cookie_hide)}));
     1const tuCookieHideName="tu-geoip-hide",tuDebug="true"===termageddon_usercentrics_obj.debug,tuPSLHide="true"===termageddon_usercentrics_obj.psl_hide;tuDebug&&console.log("UC: AJAX script initialized"),window.addEventListener("UC_UI_INITIALIZED",(function(){const getCookie=name=>{const value=`; ${document.cookie}`,parts=value.split(`; ${name}=`);if(2===parts.length)return parts.pop().split(";").shift()},getQueryParams=param=>{const params=new Proxy(new URLSearchParams(window.location.search),{get:(searchParams,prop)=>searchParams.get(prop)});return params[param]},setCookie=(name,value,days)=>{var expires="";if(days){var date=new Date;date.setTime(date.getTime()+24*days*60*60*1e3),expires="; expires="+date.toUTCString()}document.cookie=name+"="+(value||"")+expires+"; path=/"},updateCookieConsent=hide=>{if(!hide)return tuDebug&&console.log("UC: Showing consent widget"),tuPSLHide&&jQuery("#usercentrics-psl, .usercentrics-psl").show(),jQuery("div#usercentrics-root").show(),UC_UI.isConsentRequired()?UC_UI.showFirstLayer():UC_UI.closeCMP();tuDebug&&console.log("UC: Hiding consent widget"),tuPSLHide&&jQuery("#usercentrics-psl, .usercentrics-psl").hide(),jQuery("div#usercentrics-root").hide(),UC_UI.areAllConsentsAccepted()||UC_UI.acceptAllConsents().then(()=>{tuDebug&&console.log("UC: All consents have been accepted."),UC_UI.closeCMP().then(()=>{tuDebug&&console.log("UC: CMP Widget has been closed.")})})};if("undefined"==typeof UC_UI)return console.error("Usercentrics not loaded");const query_hide=""===getQueryParams("enable-usercentrics"),cookie_hide=getCookie("tu-geoip-hide");if(null==cookie_hide||tuDebug){tuDebug&&console.log("UC: Making AJAX Call");var data={action:"uc_geolocation_lookup",nonce:termageddon_usercentrics_obj.nonce};void 0!==termageddon_usercentrics_obj.location&&(data.location=termageddon_usercentrics_obj.location),jQuery.post(termageddon_usercentrics_obj.ajax_url,data).done((function(response){if(!response.success)return console.error("Unable to lookup location.",response.message||"");if(!response.data)return console.error("Location data was not provided.",response.data);const data=response.data;if(tuDebug&&console.log("TERMAGEDDON USERCENTRICS (AJAX)\nIP Address: "+data.ipAddress+"\nCity: "+(data.city||"Unknown")+"\nState: "+(data.state||"Unknown")+"\nCountry: "+(data.country||"Unknown")+"\nLocations: ",data.locations),query_hide)return tuDebug&&console.log("UC: Enabling due to query parameter override.","Showing Usercentrics"),updateCookieConsent(!1);setCookie("tu-geoip-hide",data.hide?"true":"false"),updateCookieConsent(data.hide)})).fail((function(response){console.error("Usercentrics: Invalid response returned. Showing widget as a default.",response),updateCookieConsent(!1)}))}else tuDebug&&console.log("UC: Cookie found.",(cookie_hide?"Showing":"Hiding")+" Usercentrics"),updateCookieConsent("true"===cookie_hide)}));
  • termageddon-usercentrics/trunk/termageddon-usercentrics.php

    r3148378 r3160131  
    1515 * Plugin Name:       Termageddon + Usercentrics
    1616 * Description:       Easily integrate the Usercentrics consent solution into your website while controlling visibility for logged in users and admins.
    17  * Version:           1.4.5
     17 * Version:           1.5.0
    1818 * Author:            Termageddon
    1919 * Author URI:        https://termageddon.com
     
    3434 * Rename this for your plugin and update it as you release new versions.
    3535 */
    36 define( 'TERMAGEDDON_COOKIE_VERSION', '1.4.5' );
     36define( 'TERMAGEDDON_COOKIE_VERSION', '1.5.0' );
    3737
    3838define( 'TERMAGEDDON_COOKIE_PLUGIN_PATH', dirname( __FILE__ ) );// No trailing slash.
  • termageddon-usercentrics/trunk/vendor/autoload.php

    r2771752 r3160131  
    33// autoload.php @generated by Composer
    44
    5 if (PHP_VERSION_ID < 50600) {
    6     echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
    7     exit(1);
     5if ( PHP_VERSION_ID < 50600 ) {
     6    echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running ' . PHP_VERSION . ', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.' . PHP_EOL;
     7    exit( 1 );
    88}
    99
  • termageddon-usercentrics/trunk/vendor/composer/ClassLoader.php

    r2976730 r3160131  
    4141 * @see    https://www.php-fig.org/psr/psr-4/
    4242 */
    43 class ClassLoader
    44 {
    45     /** @var ?string */
    46     private $vendorDir;
    47 
    48     // PSR-4
    49     /**
    50      * @var array[]
    51      * @psalm-var array<string, array<string, int>>
    52      */
    53     private $prefixLengthsPsr4 = array();
    54     /**
    55      * @var array[]
    56      * @psalm-var array<string, array<int, string>>
    57      */
    58     private $prefixDirsPsr4 = array();
    59     /**
    60      * @var array[]
    61      * @psalm-var array<string, string>
    62      */
    63     private $fallbackDirsPsr4 = array();
    64 
    65     // PSR-0
    66     /**
    67      * @var array[]
    68      * @psalm-var array<string, array<string, string[]>>
    69      */
    70     private $prefixesPsr0 = array();
    71     /**
    72      * @var array[]
    73      * @psalm-var array<string, string>
    74      */
    75     private $fallbackDirsPsr0 = array();
    76 
    77     /** @var bool */
    78     private $useIncludePath = false;
    79 
    80     /**
    81      * @var string[]
    82      * @psalm-var array<string, string>
    83      */
    84     private $classMap = array();
    85 
    86     /** @var bool */
    87     private $classMapAuthoritative = false;
    88 
    89     /**
    90      * @var bool[]
    91      * @psalm-var array<string, bool>
    92      */
    93     private $missingClasses = array();
    94 
    95     /** @var ?string */
    96     private $apcuPrefix;
    97 
    98     /**
    99      * @var self[]
    100      */
    101     private static $registeredLoaders = array();
    102 
    103     /**
    104      * @param ?string $vendorDir
    105      */
    106     public function __construct($vendorDir = null)
    107     {
    108         $this->vendorDir = $vendorDir;
    109     }
    110 
    111     /**
    112      * @return string[]
    113      */
    114     public function getPrefixes()
    115     {
    116         if (!empty($this->prefixesPsr0)) {
    117             return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
    118         }
    119 
    120         return array();
    121     }
    122 
    123     /**
    124      * @return array[]
    125      * @psalm-return array<string, array<int, string>>
    126      */
    127     public function getPrefixesPsr4()
    128     {
    129         return $this->prefixDirsPsr4;
    130     }
    131 
    132     /**
    133      * @return array[]
    134      * @psalm-return array<string, string>
    135      */
    136     public function getFallbackDirs()
    137     {
    138         return $this->fallbackDirsPsr0;
    139     }
    140 
    141     /**
    142      * @return array[]
    143      * @psalm-return array<string, string>
    144      */
    145     public function getFallbackDirsPsr4()
    146     {
    147         return $this->fallbackDirsPsr4;
    148     }
    149 
    150     /**
    151      * @return string[] Array of classname => path
    152      * @psalm-return array<string, string>
    153      */
    154     public function getClassMap()
    155     {
    156         return $this->classMap;
    157     }
    158 
    159     /**
    160      * @param string[] $classMap Class to filename map
    161      * @psalm-param array<string, string> $classMap
    162      *
    163      * @return void
    164      */
    165     public function addClassMap(array $classMap)
    166     {
    167         if ($this->classMap) {
    168             $this->classMap = array_merge($this->classMap, $classMap);
    169         } else {
    170             $this->classMap = $classMap;
    171         }
    172     }
    173 
    174     /**
    175      * Registers a set of PSR-0 directories for a given prefix, either
    176      * appending or prepending to the ones previously set for this prefix.
    177      *
    178      * @param string          $prefix  The prefix
    179      * @param string[]|string $paths   The PSR-0 root directories
    180      * @param bool            $prepend Whether to prepend the directories
    181      *
    182      * @return void
    183      */
    184     public function add($prefix, $paths, $prepend = false)
    185     {
    186         if (!$prefix) {
    187             if ($prepend) {
    188                 $this->fallbackDirsPsr0 = array_merge(
    189                     (array) $paths,
    190                     $this->fallbackDirsPsr0
    191                 );
    192             } else {
    193                 $this->fallbackDirsPsr0 = array_merge(
    194                     $this->fallbackDirsPsr0,
    195                     (array) $paths
    196                 );
    197             }
    198 
    199             return;
    200         }
    201 
    202         $first = $prefix[0];
    203         if (!isset($this->prefixesPsr0[$first][$prefix])) {
    204             $this->prefixesPsr0[$first][$prefix] = (array) $paths;
    205 
    206             return;
    207         }
    208         if ($prepend) {
    209             $this->prefixesPsr0[$first][$prefix] = array_merge(
    210                 (array) $paths,
    211                 $this->prefixesPsr0[$first][$prefix]
    212             );
    213         } else {
    214             $this->prefixesPsr0[$first][$prefix] = array_merge(
    215                 $this->prefixesPsr0[$first][$prefix],
    216                 (array) $paths
    217             );
    218         }
    219     }
    220 
    221     /**
    222      * Registers a set of PSR-4 directories for a given namespace, either
    223      * appending or prepending to the ones previously set for this namespace.
    224      *
    225      * @param string          $prefix  The prefix/namespace, with trailing '\\'
    226      * @param string[]|string $paths   The PSR-4 base directories
    227      * @param bool            $prepend Whether to prepend the directories
    228      *
    229      * @throws \InvalidArgumentException
    230      *
    231      * @return void
    232      */
    233     public function addPsr4($prefix, $paths, $prepend = false)
    234     {
    235         if (!$prefix) {
    236             // Register directories for the root namespace.
    237             if ($prepend) {
    238                 $this->fallbackDirsPsr4 = array_merge(
    239                     (array) $paths,
    240                     $this->fallbackDirsPsr4
    241                 );
    242             } else {
    243                 $this->fallbackDirsPsr4 = array_merge(
    244                     $this->fallbackDirsPsr4,
    245                     (array) $paths
    246                 );
    247             }
    248         } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
    249             // Register directories for a new namespace.
    250             $length = strlen($prefix);
    251             if ('\\' !== $prefix[$length - 1]) {
    252                 throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
    253             }
    254             $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
    255             $this->prefixDirsPsr4[$prefix] = (array) $paths;
    256         } elseif ($prepend) {
    257             // Prepend directories for an already registered namespace.
    258             $this->prefixDirsPsr4[$prefix] = array_merge(
    259                 (array) $paths,
    260                 $this->prefixDirsPsr4[$prefix]
    261             );
    262         } else {
    263             // Append directories for an already registered namespace.
    264             $this->prefixDirsPsr4[$prefix] = array_merge(
    265                 $this->prefixDirsPsr4[$prefix],
    266                 (array) $paths
    267             );
    268         }
    269     }
    270 
    271     /**
    272      * Registers a set of PSR-0 directories for a given prefix,
    273      * replacing any others previously set for this prefix.
    274      *
    275      * @param string          $prefix The prefix
    276      * @param string[]|string $paths  The PSR-0 base directories
    277      *
    278      * @return void
    279      */
    280     public function set($prefix, $paths)
    281     {
    282         if (!$prefix) {
    283             $this->fallbackDirsPsr0 = (array) $paths;
    284         } else {
    285             $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
    286         }
    287     }
    288 
    289     /**
    290      * Registers a set of PSR-4 directories for a given namespace,
    291      * replacing any others previously set for this namespace.
    292      *
    293      * @param string          $prefix The prefix/namespace, with trailing '\\'
    294      * @param string[]|string $paths  The PSR-4 base directories
    295      *
    296      * @throws \InvalidArgumentException
    297      *
    298      * @return void
    299      */
    300     public function setPsr4($prefix, $paths)
    301     {
    302         if (!$prefix) {
    303             $this->fallbackDirsPsr4 = (array) $paths;
    304         } else {
    305             $length = strlen($prefix);
    306             if ('\\' !== $prefix[$length - 1]) {
    307                 throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
    308             }
    309             $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
    310             $this->prefixDirsPsr4[$prefix] = (array) $paths;
    311         }
    312     }
    313 
    314     /**
    315      * Turns on searching the include path for class files.
    316      *
    317      * @param bool $useIncludePath
    318      *
    319      * @return void
    320      */
    321     public function setUseIncludePath($useIncludePath)
    322     {
    323         $this->useIncludePath = $useIncludePath;
    324     }
    325 
    326     /**
    327      * Can be used to check if the autoloader uses the include path to check
    328      * for classes.
    329      *
    330      * @return bool
    331      */
    332     public function getUseIncludePath()
    333     {
    334         return $this->useIncludePath;
    335     }
    336 
    337     /**
    338      * Turns off searching the prefix and fallback directories for classes
    339      * that have not been registered with the class map.
    340      *
    341      * @param bool $classMapAuthoritative
    342      *
    343      * @return void
    344      */
    345     public function setClassMapAuthoritative($classMapAuthoritative)
    346     {
    347         $this->classMapAuthoritative = $classMapAuthoritative;
    348     }
    349 
    350     /**
    351      * Should class lookup fail if not found in the current class map?
    352      *
    353      * @return bool
    354      */
    355     public function isClassMapAuthoritative()
    356     {
    357         return $this->classMapAuthoritative;
    358     }
    359 
    360     /**
    361      * APCu prefix to use to cache found/not-found classes, if the extension is enabled.
    362      *
    363      * @param string|null $apcuPrefix
    364      *
    365      * @return void
    366      */
    367     public function setApcuPrefix($apcuPrefix)
    368     {
    369         $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
    370     }
    371 
    372     /**
    373      * The APCu prefix in use, or null if APCu caching is not enabled.
    374      *
    375      * @return string|null
    376      */
    377     public function getApcuPrefix()
    378     {
    379         return $this->apcuPrefix;
    380     }
    381 
    382     /**
    383      * Registers this instance as an autoloader.
    384      *
    385      * @param bool $prepend Whether to prepend the autoloader or not
    386      *
    387      * @return void
    388      */
    389     public function register($prepend = false)
    390     {
    391         spl_autoload_register(array($this, 'loadClass'), true, $prepend);
    392 
    393         if (null === $this->vendorDir) {
    394             return;
    395         }
    396 
    397         if ($prepend) {
    398             self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;
    399         } else {
    400             unset(self::$registeredLoaders[$this->vendorDir]);
    401             self::$registeredLoaders[$this->vendorDir] = $this;
    402         }
    403     }
    404 
    405     /**
    406      * Unregisters this instance as an autoloader.
    407      *
    408      * @return void
    409      */
    410     public function unregister()
    411     {
    412         spl_autoload_unregister(array($this, 'loadClass'));
    413 
    414         if (null !== $this->vendorDir) {
    415             unset(self::$registeredLoaders[$this->vendorDir]);
    416         }
    417     }
    418 
    419     /**
    420      * Loads the given class or interface.
    421      *
    422      * @param  string    $class The name of the class
    423      * @return true|null True if loaded, null otherwise
    424      */
    425     public function loadClass($class)
    426     {
    427         if ($file = $this->findFile($class)) {
    428             includeFile($file);
    429 
    430             return true;
    431         }
    432 
    433         return null;
    434     }
    435 
    436     /**
    437      * Finds the path to the file where the class is defined.
    438      *
    439      * @param string $class The name of the class
    440      *
    441      * @return string|false The path if found, false otherwise
    442      */
    443     public function findFile($class)
    444     {
    445         // class map lookup
    446         if (isset($this->classMap[$class])) {
    447             return $this->classMap[$class];
    448         }
    449         if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
    450             return false;
    451         }
    452         if (null !== $this->apcuPrefix) {
    453             $file = apcu_fetch($this->apcuPrefix.$class, $hit);
    454             if ($hit) {
    455                 return $file;
    456             }
    457         }
    458 
    459         $file = $this->findFileWithExtension($class, '.php');
    460 
    461         // Search for Hack files if we are running on HHVM
    462         if (false === $file && defined('HHVM_VERSION')) {
    463             $file = $this->findFileWithExtension($class, '.hh');
    464         }
    465 
    466         if (null !== $this->apcuPrefix) {
    467             apcu_add($this->apcuPrefix.$class, $file);
    468         }
    469 
    470         if (false === $file) {
    471             // Remember that this class does not exist.
    472             $this->missingClasses[$class] = true;
    473         }
    474 
    475         return $file;
    476     }
    477 
    478     /**
    479      * Returns the currently registered loaders indexed by their corresponding vendor directories.
    480      *
    481      * @return self[]
    482      */
    483     public static function getRegisteredLoaders()
    484     {
    485         return self::$registeredLoaders;
    486     }
    487 
    488     /**
    489      * @param  string       $class
    490      * @param  string       $ext
    491      * @return string|false
    492      */
    493     private function findFileWithExtension($class, $ext)
    494     {
    495         // PSR-4 lookup
    496         $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
    497 
    498         $first = $class[0];
    499         if (isset($this->prefixLengthsPsr4[$first])) {
    500             $subPath = $class;
    501             while (false !== $lastPos = strrpos($subPath, '\\')) {
    502                 $subPath = substr($subPath, 0, $lastPos);
    503                 $search = $subPath . '\\';
    504                 if (isset($this->prefixDirsPsr4[$search])) {
    505                     $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
    506                     foreach ($this->prefixDirsPsr4[$search] as $dir) {
    507                         if (file_exists($file = $dir . $pathEnd)) {
    508                             return $file;
    509                         }
    510                     }
    511                 }
    512             }
    513         }
    514 
    515         // PSR-4 fallback dirs
    516         foreach ($this->fallbackDirsPsr4 as $dir) {
    517             if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
    518                 return $file;
    519             }
    520         }
    521 
    522         // PSR-0 lookup
    523         if (false !== $pos = strrpos($class, '\\')) {
    524             // namespaced class name
    525             $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
    526                 . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
    527         } else {
    528             // PEAR-like class name
    529             $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
    530         }
    531 
    532         if (isset($this->prefixesPsr0[$first])) {
    533             foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
    534                 if (0 === strpos($class, $prefix)) {
    535                     foreach ($dirs as $dir) {
    536                         if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
    537                             return $file;
    538                         }
    539                     }
    540                 }
    541             }
    542         }
    543 
    544         // PSR-0 fallback dirs
    545         foreach ($this->fallbackDirsPsr0 as $dir) {
    546             if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
    547                 return $file;
    548             }
    549         }
    550 
    551         // PSR-0 include paths.
    552         if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
    553             return $file;
    554         }
    555 
    556         return false;
    557     }
     43class ClassLoader {
     44
     45    /** @var ?string */
     46    private $vendorDir;
     47
     48    // PSR-4
     49    /**
     50     * @var array[]
     51     * @psalm-var array<string, array<string, int>>
     52     */
     53    private $prefixLengthsPsr4 = array();
     54    /**
     55     * @var array[]
     56     * @psalm-var array<string, array<int, string>>
     57     */
     58    private $prefixDirsPsr4 = array();
     59    /**
     60     * @var array[]
     61     * @psalm-var array<string, string>
     62     */
     63    private $fallbackDirsPsr4 = array();
     64
     65    // PSR-0
     66    /**
     67     * @var array[]
     68     * @psalm-var array<string, array<string, string[]>>
     69     */
     70    private $prefixesPsr0 = array();
     71    /**
     72     * @var array[]
     73     * @psalm-var array<string, string>
     74     */
     75    private $fallbackDirsPsr0 = array();
     76
     77    /** @var bool */
     78    private $useIncludePath = false;
     79
     80    /**
     81     * @var string[]
     82     * @psalm-var array<string, string>
     83     */
     84    private $classMap = array();
     85
     86    /** @var bool */
     87    private $classMapAuthoritative = false;
     88
     89    /**
     90     * @var bool[]
     91     * @psalm-var array<string, bool>
     92     */
     93    private $missingClasses = array();
     94
     95    /** @var ?string */
     96    private $apcuPrefix;
     97
     98    /**
     99     * @var self[]
     100     */
     101    private static $registeredLoaders = array();
     102
     103    /**
     104     * @param ?string $vendorDir
     105     */
     106    public function __construct( $vendorDir = null ) {
     107        $this->vendorDir = $vendorDir;
     108    }
     109
     110    /**
     111     * @return string[]
     112     */
     113    public function getPrefixes() {
     114        if ( ! empty( $this->prefixesPsr0 ) ) {
     115            return call_user_func_array( 'array_merge', array_values( $this->prefixesPsr0 ) );
     116        }
     117
     118        return array();
     119    }
     120
     121    /**
     122     * @return array[]
     123     * @psalm-return array<string, array<int, string>>
     124     */
     125    public function getPrefixesPsr4() {
     126        return $this->prefixDirsPsr4;
     127    }
     128
     129    /**
     130     * @return array[]
     131     * @psalm-return array<string, string>
     132     */
     133    public function getFallbackDirs() {
     134        return $this->fallbackDirsPsr0;
     135    }
     136
     137    /**
     138     * @return array[]
     139     * @psalm-return array<string, string>
     140     */
     141    public function getFallbackDirsPsr4() {
     142        return $this->fallbackDirsPsr4;
     143    }
     144
     145    /**
     146     * @return string[] Array of classname => path
     147     * @psalm-return array<string, string>
     148     */
     149    public function getClassMap() {
     150        return $this->classMap;
     151    }
     152
     153    /**
     154     * @param string[] $classMap Class to filename map
     155     * @psalm-param array<string, string> $classMap
     156     *
     157     * @return void
     158     */
     159    public function addClassMap( array $classMap ) {
     160        if ( $this->classMap ) {
     161            $this->classMap = array_merge( $this->classMap, $classMap );
     162        } else {
     163            $this->classMap = $classMap;
     164        }
     165    }
     166
     167    /**
     168     * Registers a set of PSR-0 directories for a given prefix, either
     169     * appending or prepending to the ones previously set for this prefix.
     170     *
     171     * @param string          $prefix  The prefix
     172     * @param string[]|string $paths   The PSR-0 root directories
     173     * @param bool            $prepend Whether to prepend the directories
     174     *
     175     * @return void
     176     */
     177    public function add( $prefix, $paths, $prepend = false ) {
     178        if ( ! $prefix ) {
     179            if ( $prepend ) {
     180                $this->fallbackDirsPsr0 = array_merge(
     181                    (array) $paths,
     182                    $this->fallbackDirsPsr0
     183                );
     184            } else {
     185                $this->fallbackDirsPsr0 = array_merge(
     186                    $this->fallbackDirsPsr0,
     187                    (array) $paths
     188                );
     189            }
     190
     191            return;
     192        }
     193
     194        $first = $prefix[0];
     195        if ( ! isset( $this->prefixesPsr0[ $first ][ $prefix ] ) ) {
     196            $this->prefixesPsr0[ $first ][ $prefix ] = (array) $paths;
     197
     198            return;
     199        }
     200        if ( $prepend ) {
     201            $this->prefixesPsr0[ $first ][ $prefix ] = array_merge(
     202                (array) $paths,
     203                $this->prefixesPsr0[ $first ][ $prefix ]
     204            );
     205        } else {
     206            $this->prefixesPsr0[ $first ][ $prefix ] = array_merge(
     207                $this->prefixesPsr0[ $first ][ $prefix ],
     208                (array) $paths
     209            );
     210        }
     211    }
     212
     213    /**
     214     * Registers a set of PSR-4 directories for a given namespace, either
     215     * appending or prepending to the ones previously set for this namespace.
     216     *
     217     * @param string          $prefix  The prefix/namespace, with trailing '\\'
     218     * @param string[]|string $paths   The PSR-4 base directories
     219     * @param bool            $prepend Whether to prepend the directories
     220     *
     221     * @throws \InvalidArgumentException
     222     *
     223     * @return void
     224     */
     225    public function addPsr4( $prefix, $paths, $prepend = false ) {
     226        if ( ! $prefix ) {
     227            // Register directories for the root namespace.
     228            if ( $prepend ) {
     229                $this->fallbackDirsPsr4 = array_merge(
     230                    (array) $paths,
     231                    $this->fallbackDirsPsr4
     232                );
     233            } else {
     234                $this->fallbackDirsPsr4 = array_merge(
     235                    $this->fallbackDirsPsr4,
     236                    (array) $paths
     237                );
     238            }
     239        } elseif ( ! isset( $this->prefixDirsPsr4[ $prefix ] ) ) {
     240            // Register directories for a new namespace.
     241            $length = strlen( $prefix );
     242            if ( '\\' !== $prefix[ $length - 1 ] ) {
     243                throw new \InvalidArgumentException( 'A non-empty PSR-4 prefix must end with a namespace separator.' );
     244            }
     245            $this->prefixLengthsPsr4[ $prefix[0] ][ $prefix ] = $length;
     246            $this->prefixDirsPsr4[ $prefix ]                  = (array) $paths;
     247        } elseif ( $prepend ) {
     248            // Prepend directories for an already registered namespace.
     249            $this->prefixDirsPsr4[ $prefix ] = array_merge(
     250                (array) $paths,
     251                $this->prefixDirsPsr4[ $prefix ]
     252            );
     253        } else {
     254            // Append directories for an already registered namespace.
     255            $this->prefixDirsPsr4[ $prefix ] = array_merge(
     256                $this->prefixDirsPsr4[ $prefix ],
     257                (array) $paths
     258            );
     259        }
     260    }
     261
     262    /**
     263     * Registers a set of PSR-0 directories for a given prefix,
     264     * replacing any others previously set for this prefix.
     265     *
     266     * @param string          $prefix The prefix
     267     * @param string[]|string $paths  The PSR-0 base directories
     268     *
     269     * @return void
     270     */
     271    public function set( $prefix, $paths ) {
     272        if ( ! $prefix ) {
     273            $this->fallbackDirsPsr0 = (array) $paths;
     274        } else {
     275            $this->prefixesPsr0[ $prefix[0] ][ $prefix ] = (array) $paths;
     276        }
     277    }
     278
     279    /**
     280     * Registers a set of PSR-4 directories for a given namespace,
     281     * replacing any others previously set for this namespace.
     282     *
     283     * @param string          $prefix The prefix/namespace, with trailing '\\'
     284     * @param string[]|string $paths  The PSR-4 base directories
     285     *
     286     * @throws \InvalidArgumentException
     287     *
     288     * @return void
     289     */
     290    public function setPsr4( $prefix, $paths ) {
     291        if ( ! $prefix ) {
     292            $this->fallbackDirsPsr4 = (array) $paths;
     293        } else {
     294            $length = strlen( $prefix );
     295            if ( '\\' !== $prefix[ $length - 1 ] ) {
     296                throw new \InvalidArgumentException( 'A non-empty PSR-4 prefix must end with a namespace separator.' );
     297            }
     298            $this->prefixLengthsPsr4[ $prefix[0] ][ $prefix ] = $length;
     299            $this->prefixDirsPsr4[ $prefix ]                  = (array) $paths;
     300        }
     301    }
     302
     303    /**
     304     * Turns on searching the include path for class files.
     305     *
     306     * @param bool $useIncludePath
     307     *
     308     * @return void
     309     */
     310    public function setUseIncludePath( $useIncludePath ) {
     311        $this->useIncludePath = $useIncludePath;
     312    }
     313
     314    /**
     315     * Can be used to check if the autoloader uses the include path to check
     316     * for classes.
     317     *
     318     * @return bool
     319     */
     320    public function getUseIncludePath() {
     321        return $this->useIncludePath;
     322    }
     323
     324    /**
     325     * Turns off searching the prefix and fallback directories for classes
     326     * that have not been registered with the class map.
     327     *
     328     * @param bool $classMapAuthoritative
     329     *
     330     * @return void
     331     */
     332    public function setClassMapAuthoritative( $classMapAuthoritative ) {
     333        $this->classMapAuthoritative = $classMapAuthoritative;
     334    }
     335
     336    /**
     337     * Should class lookup fail if not found in the current class map?
     338     *
     339     * @return bool
     340     */
     341    public function isClassMapAuthoritative() {
     342        return $this->classMapAuthoritative;
     343    }
     344
     345    /**
     346     * APCu prefix to use to cache found/not-found classes, if the extension is enabled.
     347     *
     348     * @param string|null $apcuPrefix
     349     *
     350     * @return void
     351     */
     352    public function setApcuPrefix( $apcuPrefix ) {
     353        $this->apcuPrefix = function_exists( 'apcu_fetch' ) && filter_var( ini_get( 'apc.enabled' ), FILTER_VALIDATE_BOOLEAN ) ? $apcuPrefix : null;
     354    }
     355
     356    /**
     357     * The APCu prefix in use, or null if APCu caching is not enabled.
     358     *
     359     * @return string|null
     360     */
     361    public function getApcuPrefix() {
     362        return $this->apcuPrefix;
     363    }
     364
     365    /**
     366     * Registers this instance as an autoloader.
     367     *
     368     * @param bool $prepend Whether to prepend the autoloader or not
     369     *
     370     * @return void
     371     */
     372    public function register( $prepend = false ) {
     373        spl_autoload_register( array( $this, 'loadClass' ), true, $prepend );
     374
     375        if ( null === $this->vendorDir ) {
     376            return;
     377        }
     378
     379        if ( $prepend ) {
     380            self::$registeredLoaders = array( $this->vendorDir => $this ) + self::$registeredLoaders;
     381        } else {
     382            unset( self::$registeredLoaders[ $this->vendorDir ] );
     383            self::$registeredLoaders[ $this->vendorDir ] = $this;
     384        }
     385    }
     386
     387    /**
     388     * Unregisters this instance as an autoloader.
     389     *
     390     * @return void
     391     */
     392    public function unregister() {
     393        spl_autoload_unregister( array( $this, 'loadClass' ) );
     394
     395        if ( null !== $this->vendorDir ) {
     396            unset( self::$registeredLoaders[ $this->vendorDir ] );
     397        }
     398    }
     399
     400    /**
     401     * Loads the given class or interface.
     402     *
     403     * @param  string $class The name of the class
     404     * @return true|null True if loaded, null otherwise
     405     */
     406    public function loadClass( $class ) {
     407        if ( $file = $this->findFile( $class ) ) {
     408            includeFile( $file );
     409
     410            return true;
     411        }
     412
     413        return null;
     414    }
     415
     416    /**
     417     * Finds the path to the file where the class is defined.
     418     *
     419     * @param string $class The name of the class
     420     *
     421     * @return string|false The path if found, false otherwise
     422     */
     423    public function findFile( $class ) {
     424        // class map lookup
     425        if ( isset( $this->classMap[ $class ] ) ) {
     426            return $this->classMap[ $class ];
     427        }
     428        if ( $this->classMapAuthoritative || isset( $this->missingClasses[ $class ] ) ) {
     429            return false;
     430        }
     431        if ( null !== $this->apcuPrefix ) {
     432            $file = apcu_fetch( $this->apcuPrefix . $class, $hit );
     433            if ( $hit ) {
     434                return $file;
     435            }
     436        }
     437
     438        $file = $this->findFileWithExtension( $class, '.php' );
     439
     440        // Search for Hack files if we are running on HHVM
     441        if ( false === $file && defined( 'HHVM_VERSION' ) ) {
     442            $file = $this->findFileWithExtension( $class, '.hh' );
     443        }
     444
     445        if ( null !== $this->apcuPrefix ) {
     446            apcu_add( $this->apcuPrefix . $class, $file );
     447        }
     448
     449        if ( false === $file ) {
     450            // Remember that this class does not exist.
     451            $this->missingClasses[ $class ] = true;
     452        }
     453
     454        return $file;
     455    }
     456
     457    /**
     458     * Returns the currently registered loaders indexed by their corresponding vendor directories.
     459     *
     460     * @return self[]
     461     */
     462    public static function getRegisteredLoaders() {
     463        return self::$registeredLoaders;
     464    }
     465
     466    /**
     467     * @param  string $class
     468     * @param  string $ext
     469     * @return string|false
     470     */
     471    private function findFileWithExtension( $class, $ext ) {
     472        // PSR-4 lookup
     473        $logicalPathPsr4 = strtr( $class, '\\', DIRECTORY_SEPARATOR ) . $ext;
     474
     475        $first = $class[0];
     476        if ( isset( $this->prefixLengthsPsr4[ $first ] ) ) {
     477            $subPath = $class;
     478            while ( false !== $lastPos = strrpos( $subPath, '\\' ) ) {
     479                $subPath = substr( $subPath, 0, $lastPos );
     480                $search  = $subPath . '\\';
     481                if ( isset( $this->prefixDirsPsr4[ $search ] ) ) {
     482                    $pathEnd = DIRECTORY_SEPARATOR . substr( $logicalPathPsr4, $lastPos + 1 );
     483                    foreach ( $this->prefixDirsPsr4[ $search ] as $dir ) {
     484                        if ( file_exists( $file = $dir . $pathEnd ) ) {
     485                            return $file;
     486                        }
     487                    }
     488                }
     489            }
     490        }
     491
     492        // PSR-4 fallback dirs
     493        foreach ( $this->fallbackDirsPsr4 as $dir ) {
     494            if ( file_exists( $file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4 ) ) {
     495                return $file;
     496            }
     497        }
     498
     499        // PSR-0 lookup
     500        if ( false !== $pos = strrpos( $class, '\\' ) ) {
     501            // namespaced class name
     502            $logicalPathPsr0 = substr( $logicalPathPsr4, 0, $pos + 1 )
     503                . strtr( substr( $logicalPathPsr4, $pos + 1 ), '_', DIRECTORY_SEPARATOR );
     504        } else {
     505            // PEAR-like class name
     506            $logicalPathPsr0 = strtr( $class, '_', DIRECTORY_SEPARATOR ) . $ext;
     507        }
     508
     509        if ( isset( $this->prefixesPsr0[ $first ] ) ) {
     510            foreach ( $this->prefixesPsr0[ $first ] as $prefix => $dirs ) {
     511                if ( 0 === strpos( $class, $prefix ) ) {
     512                    foreach ( $dirs as $dir ) {
     513                        if ( file_exists( $file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0 ) ) {
     514                            return $file;
     515                        }
     516                    }
     517                }
     518            }
     519        }
     520
     521        // PSR-0 fallback dirs
     522        foreach ( $this->fallbackDirsPsr0 as $dir ) {
     523            if ( file_exists( $file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0 ) ) {
     524                return $file;
     525            }
     526        }
     527
     528        // PSR-0 include paths.
     529        if ( $this->useIncludePath && $file = stream_resolve_include_path( $logicalPathPsr0 ) ) {
     530            return $file;
     531        }
     532
     533        return false;
     534    }
    558535}
    559536
     
    567544 * @private
    568545 */
    569 function includeFile($file)
    570 {
    571     include $file;
     546function includeFile( $file ) {
     547    include $file;
    572548}
  • termageddon-usercentrics/trunk/vendor/composer/InstalledVersions.php

    r2976730 r3160131  
    2525 * @final
    2626 */
    27 class InstalledVersions
    28 {
    29     /**
    30      * @var mixed[]|null
    31      * @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}|array{}|null
    32      */
    33     private static $installed;
    34 
    35     /**
    36      * @var bool|null
    37      */
    38     private static $canGetVendors;
    39 
    40     /**
    41      * @var array[]
    42      * @psalm-var array<string, array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
    43      */
    44     private static $installedByVendor = array();
    45 
    46     /**
    47      * Returns a list of all package names which are present, either by being installed, replaced or provided
    48      *
    49      * @return string[]
    50      * @psalm-return list<string>
    51      */
    52     public static function getInstalledPackages()
    53     {
    54         $packages = array();
    55         foreach (self::getInstalled() as $installed) {
    56             $packages[] = array_keys($installed['versions']);
    57         }
    58 
    59         if (1 === \count($packages)) {
    60             return $packages[0];
    61         }
    62 
    63         return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
    64     }
    65 
    66     /**
    67      * Returns a list of all package names with a specific type e.g. 'library'
    68      *
    69      * @param  string   $type
    70      * @return string[]
    71      * @psalm-return list<string>
    72      */
    73     public static function getInstalledPackagesByType($type)
    74     {
    75         $packagesByType = array();
    76 
    77         foreach (self::getInstalled() as $installed) {
    78             foreach ($installed['versions'] as $name => $package) {
    79                 if (isset($package['type']) && $package['type'] === $type) {
    80                     $packagesByType[] = $name;
    81                 }
    82             }
    83         }
    84 
    85         return $packagesByType;
    86     }
    87 
    88     /**
    89      * Checks whether the given package is installed
    90      *
    91      * This also returns true if the package name is provided or replaced by another package
    92      *
    93      * @param  string $packageName
    94      * @param  bool   $includeDevRequirements
    95      * @return bool
    96      */
    97     public static function isInstalled($packageName, $includeDevRequirements = true)
    98     {
    99         foreach (self::getInstalled() as $installed) {
    100             if (isset($installed['versions'][$packageName])) {
    101                 return $includeDevRequirements || empty($installed['versions'][$packageName]['dev_requirement']);
    102             }
    103         }
    104 
    105         return false;
    106     }
    107 
    108     /**
    109      * Checks whether the given package satisfies a version constraint
    110      *
    111      * e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call:
    112      *
    113      *   Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3')
    114      *
    115      * @param  VersionParser $parser      Install composer/semver to have access to this class and functionality
    116      * @param  string        $packageName
    117      * @param  string|null   $constraint  A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package
    118      * @return bool
    119      */
    120     public static function satisfies(VersionParser $parser, $packageName, $constraint)
    121     {
    122         $constraint = $parser->parseConstraints($constraint);
    123         $provided = $parser->parseConstraints(self::getVersionRanges($packageName));
    124 
    125         return $provided->matches($constraint);
    126     }
    127 
    128     /**
    129      * Returns a version constraint representing all the range(s) which are installed for a given package
    130      *
    131      * It is easier to use this via isInstalled() with the $constraint argument if you need to check
    132      * whether a given version of a package is installed, and not just whether it exists
    133      *
    134      * @param  string $packageName
    135      * @return string Version constraint usable with composer/semver
    136      */
    137     public static function getVersionRanges($packageName)
    138     {
    139         foreach (self::getInstalled() as $installed) {
    140             if (!isset($installed['versions'][$packageName])) {
    141                 continue;
    142             }
    143 
    144             $ranges = array();
    145             if (isset($installed['versions'][$packageName]['pretty_version'])) {
    146                 $ranges[] = $installed['versions'][$packageName]['pretty_version'];
    147             }
    148             if (array_key_exists('aliases', $installed['versions'][$packageName])) {
    149                 $ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
    150             }
    151             if (array_key_exists('replaced', $installed['versions'][$packageName])) {
    152                 $ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
    153             }
    154             if (array_key_exists('provided', $installed['versions'][$packageName])) {
    155                 $ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
    156             }
    157 
    158             return implode(' || ', $ranges);
    159         }
    160 
    161         throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
    162     }
    163 
    164     /**
    165      * @param  string      $packageName
    166      * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
    167      */
    168     public static function getVersion($packageName)
    169     {
    170         foreach (self::getInstalled() as $installed) {
    171             if (!isset($installed['versions'][$packageName])) {
    172                 continue;
    173             }
    174 
    175             if (!isset($installed['versions'][$packageName]['version'])) {
    176                 return null;
    177             }
    178 
    179             return $installed['versions'][$packageName]['version'];
    180         }
    181 
    182         throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
    183     }
    184 
    185     /**
    186      * @param  string      $packageName
    187      * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
    188      */
    189     public static function getPrettyVersion($packageName)
    190     {
    191         foreach (self::getInstalled() as $installed) {
    192             if (!isset($installed['versions'][$packageName])) {
    193                 continue;
    194             }
    195 
    196             if (!isset($installed['versions'][$packageName]['pretty_version'])) {
    197                 return null;
    198             }
    199 
    200             return $installed['versions'][$packageName]['pretty_version'];
    201         }
    202 
    203         throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
    204     }
    205 
    206     /**
    207      * @param  string      $packageName
    208      * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference
    209      */
    210     public static function getReference($packageName)
    211     {
    212         foreach (self::getInstalled() as $installed) {
    213             if (!isset($installed['versions'][$packageName])) {
    214                 continue;
    215             }
    216 
    217             if (!isset($installed['versions'][$packageName]['reference'])) {
    218                 return null;
    219             }
    220 
    221             return $installed['versions'][$packageName]['reference'];
    222         }
    223 
    224         throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
    225     }
    226 
    227     /**
    228      * @param  string      $packageName
    229      * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path.
    230      */
    231     public static function getInstallPath($packageName)
    232     {
    233         foreach (self::getInstalled() as $installed) {
    234             if (!isset($installed['versions'][$packageName])) {
    235                 continue;
    236             }
    237 
    238             return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null;
    239         }
    240 
    241         throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
    242     }
    243 
    244     /**
    245      * @return array
    246      * @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}
    247      */
    248     public static function getRootPackage()
    249     {
    250         $installed = self::getInstalled();
    251 
    252         return $installed[0]['root'];
    253     }
    254 
    255     /**
    256      * Returns the raw installed.php data for custom implementations
    257      *
    258      * @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
    259      * @return array[]
    260      * @psalm-return array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}
    261      */
    262     public static function getRawData()
    263     {
    264         @trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED);
    265 
    266         if (null === self::$installed) {
    267             // only require the installed.php file if this file is loaded from its dumped location,
    268             // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
    269             if (substr(__DIR__, -8, 1) !== 'C') {
    270                 self::$installed = include __DIR__ . '/installed.php';
    271             } else {
    272                 self::$installed = array();
    273             }
    274         }
    275 
    276         return self::$installed;
    277     }
    278 
    279     /**
    280      * Returns the raw data of all installed.php which are currently loaded for custom implementations
    281      *
    282      * @return array[]
    283      * @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
    284      */
    285     public static function getAllRawData()
    286     {
    287         return self::getInstalled();
    288     }
    289 
    290     /**
    291      * Lets you reload the static array from another file
    292      *
    293      * This is only useful for complex integrations in which a project needs to use
    294      * this class but then also needs to execute another project's autoloader in process,
    295      * and wants to ensure both projects have access to their version of installed.php.
    296      *
    297      * A typical case would be PHPUnit, where it would need to make sure it reads all
    298      * the data it needs from this class, then call reload() with
    299      * `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure
    300      * the project in which it runs can then also use this class safely, without
    301      * interference between PHPUnit's dependencies and the project's dependencies.
    302      *
    303      * @param  array[] $data A vendor/composer/installed.php data set
    304      * @return void
    305      *
    306      * @psalm-param array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $data
    307      */
    308     public static function reload($data)
    309     {
    310         self::$installed = $data;
    311         self::$installedByVendor = array();
    312     }
    313 
    314     /**
    315      * @return array[]
    316      * @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
    317      */
    318     private static function getInstalled()
    319     {
    320         if (null === self::$canGetVendors) {
    321             self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders');
    322         }
    323 
    324         $installed = array();
    325 
    326         if (self::$canGetVendors) {
    327             foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
    328                 if (isset(self::$installedByVendor[$vendorDir])) {
    329                     $installed[] = self::$installedByVendor[$vendorDir];
    330                 } elseif (is_file($vendorDir.'/composer/installed.php')) {
    331                     $installed[] = self::$installedByVendor[$vendorDir] = require $vendorDir.'/composer/installed.php';
    332                     if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
    333                         self::$installed = $installed[count($installed) - 1];
    334                     }
    335                 }
    336             }
    337         }
    338 
    339         if (null === self::$installed) {
    340             // only require the installed.php file if this file is loaded from its dumped location,
    341             // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
    342             if (substr(__DIR__, -8, 1) !== 'C') {
    343                 self::$installed = require __DIR__ . '/installed.php';
    344             } else {
    345                 self::$installed = array();
    346             }
    347         }
    348         $installed[] = self::$installed;
    349 
    350         return $installed;
    351     }
     27class InstalledVersions {
     28
     29    /**
     30     * @var mixed[]|null
     31     * @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}|array{}|null
     32     */
     33    private static $installed;
     34
     35    /**
     36     * @var bool|null
     37     */
     38    private static $canGetVendors;
     39
     40    /**
     41     * @var array[]
     42     * @psalm-var array<string, array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
     43     */
     44    private static $installedByVendor = array();
     45
     46    /**
     47     * Returns a list of all package names which are present, either by being installed, replaced or provided
     48     *
     49     * @return string[]
     50     * @psalm-return list<string>
     51     */
     52    public static function getInstalledPackages() {
     53        $packages = array();
     54        foreach ( self::getInstalled() as $installed ) {
     55            $packages[] = array_keys( $installed['versions'] );
     56        }
     57
     58        if ( 1 === \count( $packages ) ) {
     59            return $packages[0];
     60        }
     61
     62        return array_keys( array_flip( \call_user_func_array( 'array_merge', $packages ) ) );
     63    }
     64
     65    /**
     66     * Returns a list of all package names with a specific type e.g. 'library'
     67     *
     68     * @param  string $type
     69     * @return string[]
     70     * @psalm-return list<string>
     71     */
     72    public static function getInstalledPackagesByType( $type ) {
     73        $packagesByType = array();
     74
     75        foreach ( self::getInstalled() as $installed ) {
     76            foreach ( $installed['versions'] as $name => $package ) {
     77                if ( isset( $package['type'] ) && $package['type'] === $type ) {
     78                    $packagesByType[] = $name;
     79                }
     80            }
     81        }
     82
     83        return $packagesByType;
     84    }
     85
     86    /**
     87     * Checks whether the given package is installed
     88     *
     89     * This also returns true if the package name is provided or replaced by another package
     90     *
     91     * @param  string $packageName
     92     * @param  bool   $includeDevRequirements
     93     * @return bool
     94     */
     95    public static function isInstalled( $packageName, $includeDevRequirements = true ) {
     96        foreach ( self::getInstalled() as $installed ) {
     97            if ( isset( $installed['versions'][ $packageName ] ) ) {
     98                return $includeDevRequirements || empty( $installed['versions'][ $packageName ]['dev_requirement'] );
     99            }
     100        }
     101
     102        return false;
     103    }
     104
     105    /**
     106     * Checks whether the given package satisfies a version constraint
     107     *
     108     * e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call:
     109     *
     110     *   Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3')
     111     *
     112     * @param  VersionParser $parser      Install composer/semver to have access to this class and functionality
     113     * @param  string        $packageName
     114     * @param  string|null   $constraint  A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package
     115     * @return bool
     116     */
     117    public static function satisfies( VersionParser $parser, $packageName, $constraint ) {
     118        $constraint = $parser->parseConstraints( $constraint );
     119        $provided   = $parser->parseConstraints( self::getVersionRanges( $packageName ) );
     120
     121        return $provided->matches( $constraint );
     122    }
     123
     124    /**
     125     * Returns a version constraint representing all the range(s) which are installed for a given package
     126     *
     127     * It is easier to use this via isInstalled() with the $constraint argument if you need to check
     128     * whether a given version of a package is installed, and not just whether it exists
     129     *
     130     * @param  string $packageName
     131     * @return string Version constraint usable with composer/semver
     132     */
     133    public static function getVersionRanges( $packageName ) {
     134        foreach ( self::getInstalled() as $installed ) {
     135            if ( ! isset( $installed['versions'][ $packageName ] ) ) {
     136                continue;
     137            }
     138
     139            $ranges = array();
     140            if ( isset( $installed['versions'][ $packageName ]['pretty_version'] ) ) {
     141                $ranges[] = $installed['versions'][ $packageName ]['pretty_version'];
     142            }
     143            if ( array_key_exists( 'aliases', $installed['versions'][ $packageName ] ) ) {
     144                $ranges = array_merge( $ranges, $installed['versions'][ $packageName ]['aliases'] );
     145            }
     146            if ( array_key_exists( 'replaced', $installed['versions'][ $packageName ] ) ) {
     147                $ranges = array_merge( $ranges, $installed['versions'][ $packageName ]['replaced'] );
     148            }
     149            if ( array_key_exists( 'provided', $installed['versions'][ $packageName ] ) ) {
     150                $ranges = array_merge( $ranges, $installed['versions'][ $packageName ]['provided'] );
     151            }
     152
     153            return implode( ' || ', $ranges );
     154        }
     155
     156        throw new \OutOfBoundsException( 'Package "' . $packageName . '" is not installed' );
     157    }
     158
     159    /**
     160     * @param  string $packageName
     161     * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
     162     */
     163    public static function getVersion( $packageName ) {
     164        foreach ( self::getInstalled() as $installed ) {
     165            if ( ! isset( $installed['versions'][ $packageName ] ) ) {
     166                continue;
     167            }
     168
     169            if ( ! isset( $installed['versions'][ $packageName ]['version'] ) ) {
     170                return null;
     171            }
     172
     173            return $installed['versions'][ $packageName ]['version'];
     174        }
     175
     176        throw new \OutOfBoundsException( 'Package "' . $packageName . '" is not installed' );
     177    }
     178
     179    /**
     180     * @param  string $packageName
     181     * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
     182     */
     183    public static function getPrettyVersion( $packageName ) {
     184        foreach ( self::getInstalled() as $installed ) {
     185            if ( ! isset( $installed['versions'][ $packageName ] ) ) {
     186                continue;
     187            }
     188
     189            if ( ! isset( $installed['versions'][ $packageName ]['pretty_version'] ) ) {
     190                return null;
     191            }
     192
     193            return $installed['versions'][ $packageName ]['pretty_version'];
     194        }
     195
     196        throw new \OutOfBoundsException( 'Package "' . $packageName . '" is not installed' );
     197    }
     198
     199    /**
     200     * @param  string $packageName
     201     * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference
     202     */
     203    public static function getReference( $packageName ) {
     204        foreach ( self::getInstalled() as $installed ) {
     205            if ( ! isset( $installed['versions'][ $packageName ] ) ) {
     206                continue;
     207            }
     208
     209            if ( ! isset( $installed['versions'][ $packageName ]['reference'] ) ) {
     210                return null;
     211            }
     212
     213            return $installed['versions'][ $packageName ]['reference'];
     214        }
     215
     216        throw new \OutOfBoundsException( 'Package "' . $packageName . '" is not installed' );
     217    }
     218
     219    /**
     220     * @param  string $packageName
     221     * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path.
     222     */
     223    public static function getInstallPath( $packageName ) {
     224        foreach ( self::getInstalled() as $installed ) {
     225            if ( ! isset( $installed['versions'][ $packageName ] ) ) {
     226                continue;
     227            }
     228
     229            return isset( $installed['versions'][ $packageName ]['install_path'] ) ? $installed['versions'][ $packageName ]['install_path'] : null;
     230        }
     231
     232        throw new \OutOfBoundsException( 'Package "' . $packageName . '" is not installed' );
     233    }
     234
     235    /**
     236     * @return array
     237     * @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}
     238     */
     239    public static function getRootPackage() {
     240        $installed = self::getInstalled();
     241
     242        return $installed[0]['root'];
     243    }
     244
     245    /**
     246     * Returns the raw installed.php data for custom implementations
     247     *
     248     * @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
     249     * @return array[]
     250     * @psalm-return array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}
     251     */
     252    public static function getRawData() {
     253        @trigger_error( 'getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED );
     254
     255        if ( null === self::$installed ) {
     256            // only require the installed.php file if this file is loaded from its dumped location,
     257            // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
     258            if ( substr( __DIR__, -8, 1 ) !== 'C' ) {
     259                self::$installed = include __DIR__ . '/installed.php';
     260            } else {
     261                self::$installed = array();
     262            }
     263        }
     264
     265        return self::$installed;
     266    }
     267
     268    /**
     269     * Returns the raw data of all installed.php which are currently loaded for custom implementations
     270     *
     271     * @return array[]
     272     * @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
     273     */
     274    public static function getAllRawData() {
     275        return self::getInstalled();
     276    }
     277
     278    /**
     279     * Lets you reload the static array from another file
     280     *
     281     * This is only useful for complex integrations in which a project needs to use
     282     * this class but then also needs to execute another project's autoloader in process,
     283     * and wants to ensure both projects have access to their version of installed.php.
     284     *
     285     * A typical case would be PHPUnit, where it would need to make sure it reads all
     286     * the data it needs from this class, then call reload() with
     287     * `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure
     288     * the project in which it runs can then also use this class safely, without
     289     * interference between PHPUnit's dependencies and the project's dependencies.
     290     *
     291     * @param  array[] $data A vendor/composer/installed.php data set
     292     * @return void
     293     *
     294     * @psalm-param array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $data
     295     */
     296    public static function reload( $data ) {
     297        self::$installed         = $data;
     298        self::$installedByVendor = array();
     299    }
     300
     301    /**
     302     * @return array[]
     303     * @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
     304     */
     305    private static function getInstalled() {
     306        if ( null === self::$canGetVendors ) {
     307            self::$canGetVendors = method_exists( 'Composer\Autoload\ClassLoader', 'getRegisteredLoaders' );
     308        }
     309
     310        $installed = array();
     311
     312        if ( self::$canGetVendors ) {
     313            foreach ( ClassLoader::getRegisteredLoaders() as $vendorDir => $loader ) {
     314                if ( isset( self::$installedByVendor[ $vendorDir ] ) ) {
     315                    $installed[] = self::$installedByVendor[ $vendorDir ];
     316                } elseif ( is_file( $vendorDir . '/composer/installed.php' ) ) {
     317                    $installed[] = self::$installedByVendor[ $vendorDir ] = require $vendorDir . '/composer/installed.php';
     318                    if ( null === self::$installed && strtr( $vendorDir . '/composer', '\\', '/' ) === strtr( __DIR__, '\\', '/' ) ) {
     319                        self::$installed = $installed[ count( $installed ) - 1 ];
     320                    }
     321                }
     322            }
     323        }
     324
     325        if ( null === self::$installed ) {
     326            // only require the installed.php file if this file is loaded from its dumped location,
     327            // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
     328            if ( substr( __DIR__, -8, 1 ) !== 'C' ) {
     329                self::$installed = require __DIR__ . '/installed.php';
     330            } else {
     331                self::$installed = array();
     332            }
     333        }
     334        $installed[] = self::$installed;
     335
     336        return $installed;
     337    }
    352338}
  • termageddon-usercentrics/trunk/vendor/composer/autoload_classmap.php

    r2771752 r3160131  
    33// autoload_classmap.php @generated by Composer
    44
    5 $vendorDir = dirname(__DIR__);
    6 $baseDir = dirname($vendorDir);
     5$vendorDir = dirname( __DIR__ );
     6$baseDir   = dirname( $vendorDir );
    77
    88return array(
    9     'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
     9    'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
    1010);
  • termageddon-usercentrics/trunk/vendor/composer/autoload_namespaces.php

    r2771752 r3160131  
    33// autoload_namespaces.php @generated by Composer
    44
    5 $vendorDir = dirname(__DIR__);
    6 $baseDir = dirname($vendorDir);
     5$vendorDir = dirname( __DIR__ );
     6$baseDir   = dirname( $vendorDir );
    77
    8 return array(
    9 );
     8return array();
  • termageddon-usercentrics/trunk/vendor/composer/autoload_psr4.php

    r2771752 r3160131  
    33// autoload_psr4.php @generated by Composer
    44
    5 $vendorDir = dirname(__DIR__);
    6 $baseDir = dirname($vendorDir);
     5$vendorDir = dirname( __DIR__ );
     6$baseDir   = dirname( $vendorDir );
    77
    88return array(
    9     'MaxMind\\WebService\\' => array($vendorDir . '/maxmind/web-service-common/src/WebService'),
    10     'MaxMind\\Exception\\' => array($vendorDir . '/maxmind/web-service-common/src/Exception'),
    11     'MaxMind\\Db\\' => array($vendorDir . '/maxmind-db/reader/src/MaxMind/Db'),
    12     'GeoIp2\\' => array($vendorDir . '/geoip2/geoip2/src'),
    13     'Composer\\CaBundle\\' => array($vendorDir . '/composer/ca-bundle/src'),
     9    'MaxMind\\WebService\\' => array( $vendorDir . '/maxmind/web-service-common/src/WebService' ),
     10    'MaxMind\\Exception\\'  => array( $vendorDir . '/maxmind/web-service-common/src/Exception' ),
     11    'MaxMind\\Db\\'         => array( $vendorDir . '/maxmind-db/reader/src/MaxMind/Db' ),
     12    'GeoIp2\\'              => array( $vendorDir . '/geoip2/geoip2/src' ),
     13    'Composer\\CaBundle\\'  => array( $vendorDir . '/composer/ca-bundle/src' ),
    1414);
  • termageddon-usercentrics/trunk/vendor/composer/autoload_real.php

    r2976730 r3160131  
    33// autoload_real.php @generated by Composer
    44
    5 class ComposerAutoloaderInit68df2c2b623d60a4301d3d70719d751e
    6 {
    7     private static $loader;
     5class ComposerAutoloaderInit68df2c2b623d60a4301d3d70719d751e {
    86
    9     public static function loadClassLoader($class)
    10     {
    11         if ('Composer\Autoload\ClassLoader' === $class) {
    12             require __DIR__ . '/ClassLoader.php';
    13         }
    14     }
     7    private static $loader;
    158
    16     /**
    17      * @return \Composer\Autoload\ClassLoader
    18      */
    19     public static function getLoader()
    20     {
    21         if (null !== self::$loader) {
    22             return self::$loader;
    23         }
     9    public static function loadClassLoader( $class ) {
     10        if ( 'Composer\Autoload\ClassLoader' === $class ) {
     11            require __DIR__ . '/ClassLoader.php';
     12        }
     13    }
    2414
    25         require __DIR__ . '/platform_check.php';
     15    /**
     16     * @return \Composer\Autoload\ClassLoader
     17     */
     18    public static function getLoader() {
     19        if ( null !== self::$loader ) {
     20            return self::$loader;
     21        }
    2622
    27         spl_autoload_register(array('ComposerAutoloaderInit68df2c2b623d60a4301d3d70719d751e', 'loadClassLoader'), true, true);
    28         self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
    29         spl_autoload_unregister(array('ComposerAutoloaderInit68df2c2b623d60a4301d3d70719d751e', 'loadClassLoader'));
     23        require __DIR__ . '/platform_check.php';
    3024
    31         require __DIR__ . '/autoload_static.php';
    32         call_user_func(\Composer\Autoload\ComposerStaticInit68df2c2b623d60a4301d3d70719d751e::getInitializer($loader));
     25        spl_autoload_register( array( 'ComposerAutoloaderInit68df2c2b623d60a4301d3d70719d751e', 'loadClassLoader' ), true, true );
     26        self::$loader = $loader = new \Composer\Autoload\ClassLoader( \dirname( __DIR__ ) );
     27        spl_autoload_unregister( array( 'ComposerAutoloaderInit68df2c2b623d60a4301d3d70719d751e', 'loadClassLoader' ) );
    3328
    34         $loader->register(true);
     29        require __DIR__ . '/autoload_static.php';
     30        call_user_func( \Composer\Autoload\ComposerStaticInit68df2c2b623d60a4301d3d70719d751e::getInitializer( $loader ) );
    3531
    36         return $loader;
    37     }
     32        $loader->register( true );
     33
     34        return $loader;
     35    }
    3836}
  • termageddon-usercentrics/trunk/vendor/composer/autoload_static.php

    r2976730 r3160131  
    55namespace Composer\Autoload;
    66
    7 class ComposerStaticInit68df2c2b623d60a4301d3d70719d751e
    8 {
    9     public static $prefixLengthsPsr4 = array (
    10         'M' =>
    11         array (
    12             'MaxMind\\WebService\\' => 19,
    13             'MaxMind\\Exception\\' => 18,
    14             'MaxMind\\Db\\' => 11,
    15         ),
    16         'G' =>
    17         array (
    18             'GeoIp2\\' => 7,
    19         ),
    20         'C' =>
    21         array (
    22             'Composer\\CaBundle\\' => 18,
    23         ),
    24     );
     7class ComposerStaticInit68df2c2b623d60a4301d3d70719d751e {
    258
    26     public static $prefixDirsPsr4 = array (
    27         'MaxMind\\WebService\\' =>
    28         array (
    29             0 => __DIR__ . '/..' . '/maxmind/web-service-common/src/WebService',
    30         ),
    31         'MaxMind\\Exception\\' =>
    32         array (
    33             0 => __DIR__ . '/..' . '/maxmind/web-service-common/src/Exception',
    34         ),
    35         'MaxMind\\Db\\' =>
    36         array (
    37             0 => __DIR__ . '/..' . '/maxmind-db/reader/src/MaxMind/Db',
    38         ),
    39         'GeoIp2\\' =>
    40         array (
    41             0 => __DIR__ . '/..' . '/geoip2/geoip2/src',
    42         ),
    43         'Composer\\CaBundle\\' =>
    44         array (
    45             0 => __DIR__ . '/..' . '/composer/ca-bundle/src',
    46         ),
    47     );
     9    public static $prefixLengthsPsr4 = array(
     10        'M' =>
     11        array(
     12            'MaxMind\\WebService\\' => 19,
     13            'MaxMind\\Exception\\'  => 18,
     14            'MaxMind\\Db\\'         => 11,
     15        ),
     16        'G' =>
     17        array(
     18            'GeoIp2\\' => 7,
     19        ),
     20        'C' =>
     21        array(
     22            'Composer\\CaBundle\\' => 18,
     23        ),
     24    );
    4825
    49     public static $classMap = array (
    50         'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
    51     );
     26    public static $prefixDirsPsr4 = array(
     27        'MaxMind\\WebService\\' =>
     28        array(
     29            0 => __DIR__ . '/..' . '/maxmind/web-service-common/src/WebService',
     30        ),
     31        'MaxMind\\Exception\\'  =>
     32        array(
     33            0 => __DIR__ . '/..' . '/maxmind/web-service-common/src/Exception',
     34        ),
     35        'MaxMind\\Db\\'         =>
     36        array(
     37            0 => __DIR__ . '/..' . '/maxmind-db/reader/src/MaxMind/Db',
     38        ),
     39        'GeoIp2\\'              =>
     40        array(
     41            0 => __DIR__ . '/..' . '/geoip2/geoip2/src',
     42        ),
     43        'Composer\\CaBundle\\'  =>
     44        array(
     45            0 => __DIR__ . '/..' . '/composer/ca-bundle/src',
     46        ),
     47    );
    5248
    53     public static function getInitializer(ClassLoader $loader)
    54     {
    55         return \Closure::bind(function () use ($loader) {
    56             $loader->prefixLengthsPsr4 = ComposerStaticInit68df2c2b623d60a4301d3d70719d751e::$prefixLengthsPsr4;
    57             $loader->prefixDirsPsr4 = ComposerStaticInit68df2c2b623d60a4301d3d70719d751e::$prefixDirsPsr4;
    58             $loader->classMap = ComposerStaticInit68df2c2b623d60a4301d3d70719d751e::$classMap;
     49    public static $classMap = array(
     50        'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
     51    );
    5952
    60         }, null, ClassLoader::class);
    61     }
     53    public static function getInitializer( ClassLoader $loader ) {
     54        return \Closure::bind(
     55            function () use ( $loader ) {
     56                $loader->prefixLengthsPsr4 = ComposerStaticInit68df2c2b623d60a4301d3d70719d751e::$prefixLengthsPsr4;
     57                $loader->prefixDirsPsr4    = ComposerStaticInit68df2c2b623d60a4301d3d70719d751e::$prefixDirsPsr4;
     58                $loader->classMap          = ComposerStaticInit68df2c2b623d60a4301d3d70719d751e::$classMap;
     59
     60            },
     61            null,
     62            ClassLoader::class
     63        );
     64    }
    6265}
  • termageddon-usercentrics/trunk/vendor/composer/ca-bundle/src/CaBundle.php

    r2976730 r3160131  
    1919 * @author Jordi Boggiano <j.boggiano@seld.be>
    2020 */
    21 class CaBundle
    22 {
    23     /** @var string|null */
    24     private static $caPath;
    25     /** @var array<string, bool> */
    26     private static $caFileValidity = array();
    27     /** @var bool|null */
    28     private static $useOpensslParse;
    29 
    30     /**
    31     * Returns the system CA bundle path, or a path to the bundled one
    32     *
    33     * This method was adapted from Sslurp.
    34     * https://github.com/EvanDotPro/Sslurp
    35     *
    36     * (c) Evan Coury <me@evancoury.com>
    37     *
    38     * For the full copyright and license information, please see below:
    39     *
    40     * Copyright (c) 2013, Evan Coury
    41     * All rights reserved.
    42     *
    43     * Redistribution and use in source and binary forms, with or without modification,
    44     * are permitted provided that the following conditions are met:
    45     *
    46     *     * Redistributions of source code must retain the above copyright notice,
    47     *       this list of conditions and the following disclaimer.
    48     *
    49     *     * Redistributions in binary form must reproduce the above copyright notice,
    50     *       this list of conditions and the following disclaimer in the documentation
    51     *       and/or other materials provided with the distribution.
    52     *
    53     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
    54     * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
    55     * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
    56     * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
    57     * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
    58     * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
    59     * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
    60     * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    61     * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
    62     * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    63     *
    64     * @param  LoggerInterface $logger optional logger for information about which CA files were loaded
    65     * @return string          path to a CA bundle file or directory
    66     */
    67     public static function getSystemCaRootBundlePath(LoggerInterface $logger = null)
    68     {
    69         if (self::$caPath !== null) {
    70             return self::$caPath;
    71         }
    72         $caBundlePaths = array();
    73 
    74         // If SSL_CERT_FILE env variable points to a valid certificate/bundle, use that.
    75         // This mimics how OpenSSL uses the SSL_CERT_FILE env variable.
    76         $caBundlePaths[] = self::getEnvVariable('SSL_CERT_FILE');
    77 
    78         // If SSL_CERT_DIR env variable points to a valid certificate/bundle, use that.
    79         // This mimics how OpenSSL uses the SSL_CERT_FILE env variable.
    80         $caBundlePaths[] = self::getEnvVariable('SSL_CERT_DIR');
    81 
    82         $caBundlePaths[] = ini_get('openssl.cafile');
    83         $caBundlePaths[] = ini_get('openssl.capath');
    84 
    85         $otherLocations = array(
    86             '/etc/pki/tls/certs/ca-bundle.crt', // Fedora, RHEL, CentOS (ca-certificates package)
    87             '/etc/ssl/certs/ca-certificates.crt', // Debian, Ubuntu, Gentoo, Arch Linux (ca-certificates package)
    88             '/etc/ssl/ca-bundle.pem', // SUSE, openSUSE (ca-certificates package)
    89             '/usr/local/share/certs/ca-root-nss.crt', // FreeBSD (ca_root_nss_package)
    90             '/usr/ssl/certs/ca-bundle.crt', // Cygwin
    91             '/opt/local/share/curl/curl-ca-bundle.crt', // OS X macports, curl-ca-bundle package
    92             '/usr/local/share/curl/curl-ca-bundle.crt', // Default cURL CA bunde path (without --with-ca-bundle option)
    93             '/usr/share/ssl/certs/ca-bundle.crt', // Really old RedHat?
    94             '/etc/ssl/cert.pem', // OpenBSD
    95             '/usr/local/etc/ssl/cert.pem', // FreeBSD 10.x
    96             '/usr/local/etc/openssl/cert.pem', // OS X homebrew, openssl package
    97             '/usr/local/etc/openssl@1.1/cert.pem', // OS X homebrew, openssl@1.1 package
    98         );
    99 
    100         foreach($otherLocations as $location) {
    101             $otherLocations[] = dirname($location);
    102         }
    103 
    104         $caBundlePaths = array_merge($caBundlePaths, $otherLocations);
    105 
    106         foreach ($caBundlePaths as $caBundle) {
    107             if ($caBundle && self::caFileUsable($caBundle, $logger)) {
    108                 return self::$caPath = $caBundle;
    109             }
    110 
    111             if ($caBundle && self::caDirUsable($caBundle, $logger)) {
    112                 return self::$caPath = $caBundle;
    113             }
    114         }
    115 
    116         return self::$caPath = static::getBundledCaBundlePath(); // Bundled CA file, last resort
    117     }
    118 
    119     /**
    120      * Returns the path to the bundled CA file
    121      *
    122      * In case you don't want to trust the user or the system, you can use this directly
    123      *
    124      * @return string path to a CA bundle file
    125      */
    126     public static function getBundledCaBundlePath()
    127     {
    128         $caBundleFile = __DIR__.'/../res/cacert.pem';
    129 
    130         // cURL does not understand 'phar://' paths
    131         // see https://github.com/composer/ca-bundle/issues/10
    132         if (0 === strpos($caBundleFile, 'phar://')) {
    133             $tempCaBundleFile = tempnam(sys_get_temp_dir(), 'openssl-ca-bundle-');
    134             if (false === $tempCaBundleFile) {
    135                 throw new \RuntimeException('Could not create a temporary file to store the bundled CA file');
    136             }
    137 
    138             file_put_contents(
    139                 $tempCaBundleFile,
    140                 file_get_contents($caBundleFile)
    141             );
    142 
    143             register_shutdown_function(function() use ($tempCaBundleFile) {
    144                 @unlink($tempCaBundleFile);
    145             });
    146 
    147             $caBundleFile = $tempCaBundleFile;
    148         }
    149 
    150         return $caBundleFile;
    151     }
    152 
    153     /**
    154     * Validates a CA file using opensl_x509_parse only if it is safe to use
    155     *
    156     * @param string          $filename
    157     * @param LoggerInterface $logger   optional logger for information about which CA files were loaded
    158     *
    159     * @return bool
    160     */
    161     public static function validateCaFile($filename, LoggerInterface $logger = null)
    162     {
    163         static $warned = false;
    164 
    165         if (isset(self::$caFileValidity[$filename])) {
    166             return self::$caFileValidity[$filename];
    167         }
    168 
    169         $contents = file_get_contents($filename);
    170 
    171         // assume the CA is valid if php is vulnerable to
    172         // https://www.sektioneins.de/advisories/advisory-012013-php-openssl_x509_parse-memory-corruption-vulnerability.html
    173         if (!static::isOpensslParseSafe()) {
    174             if (!$warned && $logger) {
    175                 $logger->warning(sprintf(
    176                     'Your version of PHP, %s, is affected by CVE-2013-6420 and cannot safely perform certificate validation, we strongly suggest you upgrade.',
    177                     PHP_VERSION
    178                 ));
    179                 $warned = true;
    180             }
    181 
    182             $isValid = !empty($contents);
    183         } elseif (is_string($contents) && strlen($contents) > 0) {
    184             $contents = preg_replace("/^(\\-+(?:BEGIN|END))\\s+TRUSTED\\s+(CERTIFICATE\\-+)\$/m", '$1 $2', $contents);
    185             if (null === $contents) {
    186                 // regex extraction failed
    187                 $isValid = false;
    188             } else {
    189                 $isValid = (bool) openssl_x509_parse($contents);
    190             }
    191         } else {
    192             $isValid = false;
    193         }
    194 
    195         if ($logger) {
    196             $logger->debug('Checked CA file '.realpath($filename).': '.($isValid ? 'valid' : 'invalid'));
    197         }
    198 
    199         return self::$caFileValidity[$filename] = $isValid;
    200     }
    201 
    202     /**
    203      * Test if it is safe to use the PHP function openssl_x509_parse().
    204      *
    205      * This checks if OpenSSL extensions is vulnerable to remote code execution
    206      * via the exploit documented as CVE-2013-6420.
    207      *
    208      * @return bool
    209      */
    210     public static function isOpensslParseSafe()
    211     {
    212         if (null !== self::$useOpensslParse) {
    213             return self::$useOpensslParse;
    214         }
    215 
    216         if (PHP_VERSION_ID >= 50600) {
    217             return self::$useOpensslParse = true;
    218         }
    219 
    220         // Vulnerable:
    221         // PHP 5.3.0 - PHP 5.3.27
    222         // PHP 5.4.0 - PHP 5.4.22
    223         // PHP 5.5.0 - PHP 5.5.6
    224         if (
    225                (PHP_VERSION_ID < 50400 && PHP_VERSION_ID >= 50328)
    226             || (PHP_VERSION_ID < 50500 && PHP_VERSION_ID >= 50423)
    227             || PHP_VERSION_ID >= 50507
    228         ) {
    229             // This version of PHP has the fix for CVE-2013-6420 applied.
    230             return self::$useOpensslParse = true;
    231         }
    232 
    233         if (defined('PHP_WINDOWS_VERSION_BUILD')) {
    234             // Windows is probably insecure in this case.
    235             return self::$useOpensslParse = false;
    236         }
    237 
    238         $compareDistroVersionPrefix = function ($prefix, $fixedVersion) {
    239             $regex = '{^'.preg_quote($prefix).'([0-9]+)$}';
    240 
    241             if (preg_match($regex, PHP_VERSION, $m)) {
    242                 return ((int) $m[1]) >= $fixedVersion;
    243             }
    244 
    245             return false;
    246         };
    247 
    248         // Hard coded list of PHP distributions with the fix backported.
    249         if (
    250             $compareDistroVersionPrefix('5.3.3-7+squeeze', 18) // Debian 6 (Squeeze)
    251             || $compareDistroVersionPrefix('5.4.4-14+deb7u', 7) // Debian 7 (Wheezy)
    252             || $compareDistroVersionPrefix('5.3.10-1ubuntu3.', 9) // Ubuntu 12.04 (Precise)
    253         ) {
    254             return self::$useOpensslParse = true;
    255         }
    256 
    257         // Symfony Process component is missing so we assume it is unsafe at this point
    258         if (!class_exists('Symfony\Component\Process\PhpProcess')) {
    259             return self::$useOpensslParse = false;
    260         }
    261 
    262         // This is where things get crazy, because distros backport security
    263         // fixes the chances are on NIX systems the fix has been applied but
    264         // it's not possible to verify that from the PHP version.
    265         //
    266         // To verify exec a new PHP process and run the issue testcase with
    267         // known safe input that replicates the bug.
    268 
    269         // Based on testcase in https://github.com/php/php-src/commit/c1224573c773b6845e83505f717fbf820fc18415
    270         // changes in https://github.com/php/php-src/commit/76a7fd893b7d6101300cc656058704a73254d593
    271         $cert = 'LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUVwRENDQTR5Z0F3SUJBZ0lKQUp6dThyNnU2ZUJjTUEwR0NTcUdTSWIzRFFFQkJRVUFNSUhETVFzd0NRWUQKVlFRR0V3SkVSVEVjTUJvR0ExVUVDQXdUVG05eVpISm9aV2x1TFZkbGMzUm1ZV3hsYmpFUU1BNEdBMVVFQnd3SApTOE9Ed3Jac2JqRVVNQklHQTFVRUNnd0xVMlZyZEdsdmJrVnBibk14SHpBZEJnTlZCQXNNRmsxaGJHbGphVzkxCmN5QkRaWEowSUZObFkzUnBiMjR4SVRBZkJnTlZCQU1NR0cxaGJHbGphVzkxY3k1elpXdDBhVzl1WldsdWN5NWsKWlRFcU1DZ0dDU3FHU0liM0RRRUpBUlliYzNSbFptRnVMbVZ6YzJWeVFITmxhM1JwYjI1bGFXNXpMbVJsTUhVWQpaREU1TnpBd01UQXhNREF3TURBd1dnQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBCkFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUEKQUFBQUFBQVhEVEUwTVRFeU9ERXhNemt6TlZvd2djTXhDekFKQmdOVkJBWVRBa1JGTVJ3d0dnWURWUVFJREJOTwpiM0prY21obGFXNHRWMlZ6ZEdaaGJHVnVNUkF3RGdZRFZRUUhEQWRMdzRQQ3RteHVNUlF3RWdZRFZRUUtEQXRUClpXdDBhVzl1UldsdWN6RWZNQjBHQTFVRUN3d1dUV0ZzYVdOcGIzVnpJRU5sY25RZ1UyVmpkR2x2YmpFaE1COEcKQTFVRUF3d1liV0ZzYVdOcGIzVnpMbk5sYTNScGIyNWxhVzV6TG1SbE1Tb3dLQVlKS29aSWh2Y05BUWtCRmh0egpkR1ZtWVc0dVpYTnpaWEpBYzJWcmRHbHZibVZwYm5NdVpHVXdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRRERBZjNobDdKWTBYY0ZuaXlFSnBTU0RxbjBPcUJyNlFQNjV1c0pQUnQvOFBhRG9xQnUKd0VZVC9OYSs2ZnNnUGpDMHVLOURaZ1dnMnRIV1dvYW5TYmxBTW96NVBINlorUzRTSFJaN2UyZERJalBqZGhqaAowbUxnMlVNTzV5cDBWNzk3R2dzOWxOdDZKUmZIODFNTjJvYlhXczROdHp0TE11RDZlZ3FwcjhkRGJyMzRhT3M4CnBrZHVpNVVhd1Raa3N5NXBMUEhxNWNNaEZHbTA2djY1Q0xvMFYyUGQ5K0tBb2tQclBjTjVLTEtlYno3bUxwazYKU01lRVhPS1A0aWRFcXh5UTdPN2ZCdUhNZWRzUWh1K3ByWTNzaTNCVXlLZlF0UDVDWm5YMmJwMHdLSHhYMTJEWAoxbmZGSXQ5RGJHdkhUY3lPdU4rblpMUEJtM3ZXeG50eUlJdlZBZ01CQUFHalFqQkFNQWtHQTFVZEV3UUNNQUF3CkVRWUpZSVpJQVliNFFnRUJCQVFEQWdlQU1Bc0dBMVVkRHdRRUF3SUZvREFUQmdOVkhTVUVEREFLQmdnckJnRUYKQlFjREFqQU5CZ2txaGtpRzl3MEJBUVVGQUFPQ0FRRUFHMGZaWVlDVGJkajFYWWMrMVNub2FQUit2SThDOENhRAo4KzBVWWhkbnlVNGdnYTBCQWNEclk5ZTk0ZUVBdTZacXljRjZGakxxWFhkQWJvcHBXb2NyNlQ2R0QxeDMzQ2tsClZBcnpHL0t4UW9oR0QySmVxa2hJTWxEb214SE83a2EzOStPYThpMnZXTFZ5alU4QVp2V01BcnVIYTRFRU55RzcKbFcyQWFnYUZLRkNyOVRuWFRmcmR4R1ZFYnY3S1ZRNmJkaGc1cDVTanBXSDErTXEwM3VSM1pYUEJZZHlWODMxOQpvMGxWajFLRkkyRENML2xpV2lzSlJvb2YrMWNSMzVDdGQwd1lCY3BCNlRac2xNY09QbDc2ZHdLd0pnZUpvMlFnClpzZm1jMnZDMS9xT2xOdU5xLzBUenprVkd2OEVUVDNDZ2FVK1VYZTRYT1Z2a2NjZWJKbjJkZz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K';
    272         $script = <<<'EOT'
     21class CaBundle {
     22
     23    /** @var string|null */
     24    private static $caPath;
     25    /** @var array<string, bool> */
     26    private static $caFileValidity = array();
     27    /** @var bool|null */
     28    private static $useOpensslParse;
     29
     30    /**
     31    * Returns the system CA bundle path, or a path to the bundled one
     32    *
     33    * This method was adapted from Sslurp.
     34    * https://github.com/EvanDotPro/Sslurp
     35    *
     36    * (c) Evan Coury <me@evancoury.com>
     37    *
     38    * For the full copyright and license information, please see below:
     39    *
     40    * Copyright (c) 2013, Evan Coury
     41    * All rights reserved.
     42    *
     43    * Redistribution and use in source and binary forms, with or without modification,
     44    * are permitted provided that the following conditions are met:
     45    *
     46    *     * Redistributions of source code must retain the above copyright notice,
     47    *       this list of conditions and the following disclaimer.
     48    *
     49    *     * Redistributions in binary form must reproduce the above copyright notice,
     50    *       this list of conditions and the following disclaimer in the documentation
     51    *       and/or other materials provided with the distribution.
     52    *
     53    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
     54    * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     55    * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     56    * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
     57    * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     58    * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     59    * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
     60    * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     61    * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     62    * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     63    *
     64    * @param  LoggerInterface $logger optional logger for information about which CA files were loaded
     65    * @return string          path to a CA bundle file or directory
     66    */
     67    public static function getSystemCaRootBundlePath( LoggerInterface $logger = null ) {
     68        if ( self::$caPath !== null ) {
     69            return self::$caPath;
     70        }
     71        $caBundlePaths = array();
     72
     73        // If SSL_CERT_FILE env variable points to a valid certificate/bundle, use that.
     74        // This mimics how OpenSSL uses the SSL_CERT_FILE env variable.
     75        $caBundlePaths[] = self::getEnvVariable( 'SSL_CERT_FILE' );
     76
     77        // If SSL_CERT_DIR env variable points to a valid certificate/bundle, use that.
     78        // This mimics how OpenSSL uses the SSL_CERT_FILE env variable.
     79        $caBundlePaths[] = self::getEnvVariable( 'SSL_CERT_DIR' );
     80
     81        $caBundlePaths[] = ini_get( 'openssl.cafile' );
     82        $caBundlePaths[] = ini_get( 'openssl.capath' );
     83
     84        $otherLocations = array(
     85            '/etc/pki/tls/certs/ca-bundle.crt', // Fedora, RHEL, CentOS (ca-certificates package)
     86            '/etc/ssl/certs/ca-certificates.crt', // Debian, Ubuntu, Gentoo, Arch Linux (ca-certificates package)
     87            '/etc/ssl/ca-bundle.pem', // SUSE, openSUSE (ca-certificates package)
     88            '/usr/local/share/certs/ca-root-nss.crt', // FreeBSD (ca_root_nss_package)
     89            '/usr/ssl/certs/ca-bundle.crt', // Cygwin
     90            '/opt/local/share/curl/curl-ca-bundle.crt', // OS X macports, curl-ca-bundle package
     91            '/usr/local/share/curl/curl-ca-bundle.crt', // Default cURL CA bunde path (without --with-ca-bundle option)
     92            '/usr/share/ssl/certs/ca-bundle.crt', // Really old RedHat?
     93            '/etc/ssl/cert.pem', // OpenBSD
     94            '/usr/local/etc/ssl/cert.pem', // FreeBSD 10.x
     95            '/usr/local/etc/openssl/cert.pem', // OS X homebrew, openssl package
     96            '/usr/local/etc/openssl@1.1/cert.pem', // OS X homebrew, openssl@1.1 package
     97        );
     98
     99        foreach ( $otherLocations as $location ) {
     100            $otherLocations[] = dirname( $location );
     101        }
     102
     103        $caBundlePaths = array_merge( $caBundlePaths, $otherLocations );
     104
     105        foreach ( $caBundlePaths as $caBundle ) {
     106            if ( $caBundle && self::caFileUsable( $caBundle, $logger ) ) {
     107                return self::$caPath = $caBundle;
     108            }
     109
     110            if ( $caBundle && self::caDirUsable( $caBundle, $logger ) ) {
     111                return self::$caPath = $caBundle;
     112            }
     113        }
     114
     115        return self::$caPath = static::getBundledCaBundlePath(); // Bundled CA file, last resort
     116    }
     117
     118    /**
     119     * Returns the path to the bundled CA file
     120     *
     121     * In case you don't want to trust the user or the system, you can use this directly
     122     *
     123     * @return string path to a CA bundle file
     124     */
     125    public static function getBundledCaBundlePath() {
     126        $caBundleFile = __DIR__ . '/../res/cacert.pem';
     127
     128        // cURL does not understand 'phar://' paths
     129        // see https://github.com/composer/ca-bundle/issues/10
     130        if ( 0 === strpos( $caBundleFile, 'phar://' ) ) {
     131            $tempCaBundleFile = tempnam( sys_get_temp_dir(), 'openssl-ca-bundle-' );
     132            if ( false === $tempCaBundleFile ) {
     133                throw new \RuntimeException( 'Could not create a temporary file to store the bundled CA file' );
     134            }
     135
     136            file_put_contents(
     137                $tempCaBundleFile,
     138                file_get_contents( $caBundleFile )
     139            );
     140
     141            register_shutdown_function(
     142                function() use ( $tempCaBundleFile ) {
     143                    @unlink( $tempCaBundleFile );
     144                }
     145            );
     146
     147            $caBundleFile = $tempCaBundleFile;
     148        }
     149
     150        return $caBundleFile;
     151    }
     152
     153    /**
     154    * Validates a CA file using opensl_x509_parse only if it is safe to use
     155    *
     156    * @param string          $filename
     157    * @param LoggerInterface $logger   optional logger for information about which CA files were loaded
     158    *
     159    * @return bool
     160    */
     161    public static function validateCaFile( $filename, LoggerInterface $logger = null ) {
     162        static $warned = false;
     163
     164        if ( isset( self::$caFileValidity[ $filename ] ) ) {
     165            return self::$caFileValidity[ $filename ];
     166        }
     167
     168        $contents = file_get_contents( $filename );
     169
     170        // assume the CA is valid if php is vulnerable to
     171        // https://www.sektioneins.de/advisories/advisory-012013-php-openssl_x509_parse-memory-corruption-vulnerability.html
     172        if ( ! static::isOpensslParseSafe() ) {
     173            if ( ! $warned && $logger ) {
     174                $logger->warning(
     175                    sprintf(
     176                        'Your version of PHP, %s, is affected by CVE-2013-6420 and cannot safely perform certificate validation, we strongly suggest you upgrade.',
     177                        PHP_VERSION
     178                    )
     179                );
     180                $warned = true;
     181            }
     182
     183            $isValid = ! empty( $contents );
     184        } elseif ( is_string( $contents ) && strlen( $contents ) > 0 ) {
     185            $contents = preg_replace( '/^(\\-+(?:BEGIN|END))\\s+TRUSTED\\s+(CERTIFICATE\\-+)$/m', '$1 $2', $contents );
     186            if ( null === $contents ) {
     187                // regex extraction failed
     188                $isValid = false;
     189            } else {
     190                $isValid = (bool) openssl_x509_parse( $contents );
     191            }
     192        } else {
     193            $isValid = false;
     194        }
     195
     196        if ( $logger ) {
     197            $logger->debug( 'Checked CA file ' . realpath( $filename ) . ': ' . ( $isValid ? 'valid' : 'invalid' ) );
     198        }
     199
     200        return self::$caFileValidity[ $filename ] = $isValid;
     201    }
     202
     203    /**
     204     * Test if it is safe to use the PHP function openssl_x509_parse().
     205     *
     206     * This checks if OpenSSL extensions is vulnerable to remote code execution
     207     * via the exploit documented as CVE-2013-6420.
     208     *
     209     * @return bool
     210     */
     211    public static function isOpensslParseSafe() {
     212        if ( null !== self::$useOpensslParse ) {
     213            return self::$useOpensslParse;
     214        }
     215
     216        if ( PHP_VERSION_ID >= 50600 ) {
     217            return self::$useOpensslParse = true;
     218        }
     219
     220        // Vulnerable:
     221        // PHP 5.3.0 - PHP 5.3.27
     222        // PHP 5.4.0 - PHP 5.4.22
     223        // PHP 5.5.0 - PHP 5.5.6
     224        if (
     225               ( PHP_VERSION_ID < 50400 && PHP_VERSION_ID >= 50328 )
     226            || ( PHP_VERSION_ID < 50500 && PHP_VERSION_ID >= 50423 )
     227            || PHP_VERSION_ID >= 50507
     228        ) {
     229            // This version of PHP has the fix for CVE-2013-6420 applied.
     230            return self::$useOpensslParse = true;
     231        }
     232
     233        if ( defined( 'PHP_WINDOWS_VERSION_BUILD' ) ) {
     234            // Windows is probably insecure in this case.
     235            return self::$useOpensslParse = false;
     236        }
     237
     238        $compareDistroVersionPrefix = function ( $prefix, $fixedVersion ) {
     239            $regex = '{^' . preg_quote( $prefix ) . '([0-9]+)$}';
     240
     241            if ( preg_match( $regex, PHP_VERSION, $m ) ) {
     242                return ( (int) $m[1] ) >= $fixedVersion;
     243            }
     244
     245            return false;
     246        };
     247
     248        // Hard coded list of PHP distributions with the fix backported.
     249        if (
     250            $compareDistroVersionPrefix( '5.3.3-7+squeeze', 18 ) // Debian 6 (Squeeze)
     251            || $compareDistroVersionPrefix( '5.4.4-14+deb7u', 7 ) // Debian 7 (Wheezy)
     252            || $compareDistroVersionPrefix( '5.3.10-1ubuntu3.', 9 ) // Ubuntu 12.04 (Precise)
     253        ) {
     254            return self::$useOpensslParse = true;
     255        }
     256
     257        // Symfony Process component is missing so we assume it is unsafe at this point
     258        if ( ! class_exists( 'Symfony\Component\Process\PhpProcess' ) ) {
     259            return self::$useOpensslParse = false;
     260        }
     261
     262        // This is where things get crazy, because distros backport security
     263        // fixes the chances are on NIX systems the fix has been applied but
     264        // it's not possible to verify that from the PHP version.
     265        //
     266        // To verify exec a new PHP process and run the issue testcase with
     267        // known safe input that replicates the bug.
     268
     269        // Based on testcase in https://github.com/php/php-src/commit/c1224573c773b6845e83505f717fbf820fc18415
     270        // changes in https://github.com/php/php-src/commit/76a7fd893b7d6101300cc656058704a73254d593
     271        $cert  = 'LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUVwRENDQTR5Z0F3SUJBZ0lKQUp6dThyNnU2ZUJjTUEwR0NTcUdTSWIzRFFFQkJRVUFNSUhETVFzd0NRWUQKVlFRR0V3SkVSVEVjTUJvR0ExVUVDQXdUVG05eVpISm9aV2x1TFZkbGMzUm1ZV3hsYmpFUU1BNEdBMVVFQnd3SApTOE9Ed3Jac2JqRVVNQklHQTFVRUNnd0xVMlZyZEdsdmJrVnBibk14SHpBZEJnTlZCQXNNRmsxaGJHbGphVzkxCmN5QkRaWEowSUZObFkzUnBiMjR4SVRBZkJnTlZCQU1NR0cxaGJHbGphVzkxY3k1elpXdDBhVzl1WldsdWN5NWsKWlRFcU1DZ0dDU3FHU0liM0RRRUpBUlliYzNSbFptRnVMbVZ6YzJWeVFITmxhM1JwYjI1bGFXNXpMbVJsTUhVWQpaREU1TnpBd01UQXhNREF3TURBd1dnQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBCkFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUEKQUFBQUFBQVhEVEUwTVRFeU9ERXhNemt6TlZvd2djTXhDekFKQmdOVkJBWVRBa1JGTVJ3d0dnWURWUVFJREJOTwpiM0prY21obGFXNHRWMlZ6ZEdaaGJHVnVNUkF3RGdZRFZRUUhEQWRMdzRQQ3RteHVNUlF3RWdZRFZRUUtEQXRUClpXdDBhVzl1UldsdWN6RWZNQjBHQTFVRUN3d1dUV0ZzYVdOcGIzVnpJRU5sY25RZ1UyVmpkR2x2YmpFaE1COEcKQTFVRUF3d1liV0ZzYVdOcGIzVnpMbk5sYTNScGIyNWxhVzV6TG1SbE1Tb3dLQVlKS29aSWh2Y05BUWtCRmh0egpkR1ZtWVc0dVpYTnpaWEpBYzJWcmRHbHZibVZwYm5NdVpHVXdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRRERBZjNobDdKWTBYY0ZuaXlFSnBTU0RxbjBPcUJyNlFQNjV1c0pQUnQvOFBhRG9xQnUKd0VZVC9OYSs2ZnNnUGpDMHVLOURaZ1dnMnRIV1dvYW5TYmxBTW96NVBINlorUzRTSFJaN2UyZERJalBqZGhqaAowbUxnMlVNTzV5cDBWNzk3R2dzOWxOdDZKUmZIODFNTjJvYlhXczROdHp0TE11RDZlZ3FwcjhkRGJyMzRhT3M4CnBrZHVpNVVhd1Raa3N5NXBMUEhxNWNNaEZHbTA2djY1Q0xvMFYyUGQ5K0tBb2tQclBjTjVLTEtlYno3bUxwazYKU01lRVhPS1A0aWRFcXh5UTdPN2ZCdUhNZWRzUWh1K3ByWTNzaTNCVXlLZlF0UDVDWm5YMmJwMHdLSHhYMTJEWAoxbmZGSXQ5RGJHdkhUY3lPdU4rblpMUEJtM3ZXeG50eUlJdlZBZ01CQUFHalFqQkFNQWtHQTFVZEV3UUNNQUF3CkVRWUpZSVpJQVliNFFnRUJCQVFEQWdlQU1Bc0dBMVVkRHdRRUF3SUZvREFUQmdOVkhTVUVEREFLQmdnckJnRUYKQlFjREFqQU5CZ2txaGtpRzl3MEJBUVVGQUFPQ0FRRUFHMGZaWVlDVGJkajFYWWMrMVNub2FQUit2SThDOENhRAo4KzBVWWhkbnlVNGdnYTBCQWNEclk5ZTk0ZUVBdTZacXljRjZGakxxWFhkQWJvcHBXb2NyNlQ2R0QxeDMzQ2tsClZBcnpHL0t4UW9oR0QySmVxa2hJTWxEb214SE83a2EzOStPYThpMnZXTFZ5alU4QVp2V01BcnVIYTRFRU55RzcKbFcyQWFnYUZLRkNyOVRuWFRmcmR4R1ZFYnY3S1ZRNmJkaGc1cDVTanBXSDErTXEwM3VSM1pYUEJZZHlWODMxOQpvMGxWajFLRkkyRENML2xpV2lzSlJvb2YrMWNSMzVDdGQwd1lCY3BCNlRac2xNY09QbDc2ZHdLd0pnZUpvMlFnClpzZm1jMnZDMS9xT2xOdU5xLzBUenprVkd2OEVUVDNDZ2FVK1VYZTRYT1Z2a2NjZWJKbjJkZz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K';
     272        $script = <<<'EOT'
    273273
    274274error_reporting(-1);
     
    277277
    278278EOT;
    279         $script = '<'."?php\n".sprintf($script, $cert);
    280 
    281         try {
    282             $process = new PhpProcess($script);
    283             $process->mustRun();
    284         } catch (\Exception $e) {
    285             // In the case of any exceptions just accept it is not possible to
    286             // determine the safety of openssl_x509_parse and bail out.
    287             return self::$useOpensslParse = false;
    288         }
    289 
    290         $output = preg_split('{\r?\n}', trim($process->getOutput()));
    291         $errorOutput = trim($process->getErrorOutput());
    292 
    293         if (
    294             is_array($output)
    295             && count($output) === 3
    296             && $output[0] === sprintf('string(%d) "%s"', strlen(PHP_VERSION), PHP_VERSION)
    297             && $output[1] === 'string(27) "stefan.esser@sektioneins.de"'
    298             && $output[2] === 'int(-1)'
    299             && preg_match('{openssl_x509_parse\(\): illegal (?:ASN1 data type for|length in) timestamp in - on line \d+}', $errorOutput)
    300         ) {
    301             // This PHP has the fix backported probably by a distro security team.
    302             return self::$useOpensslParse = true;
    303         }
    304 
    305         return self::$useOpensslParse = false;
    306     }
    307 
    308     /**
    309      * Resets the static caches
    310      * @return void
    311      */
    312     public static function reset()
    313     {
    314         self::$caFileValidity = array();
    315         self::$caPath = null;
    316         self::$useOpensslParse = null;
    317     }
    318 
    319     /**
    320      * @param  string $name
    321      * @return string|false
    322      */
    323     private static function getEnvVariable($name)
    324     {
    325         if (isset($_SERVER[$name])) {
    326             return (string) $_SERVER[$name];
    327         }
    328 
    329         if (PHP_SAPI === 'cli' && ($value = getenv($name)) !== false && $value !== null) {
    330             return (string) $value;
    331         }
    332 
    333         return false;
    334     }
    335 
    336     /**
    337      * @param  string|false $certFile
    338      * @param  LoggerInterface|null $logger
    339      * @return bool
    340      */
    341     private static function caFileUsable($certFile, LoggerInterface $logger = null)
    342     {
    343         return $certFile
    344             && static::isFile($certFile, $logger)
    345             && static::isReadable($certFile, $logger)
    346             && static::validateCaFile($certFile, $logger);
    347     }
    348 
    349     /**
    350      * @param  string|false $certDir
    351      * @param  LoggerInterface|null $logger
    352      * @return bool
    353      */
    354     private static function caDirUsable($certDir, LoggerInterface $logger = null)
    355     {
    356         return $certDir
    357             && static::isDir($certDir, $logger)
    358             && static::isReadable($certDir, $logger)
    359             && static::glob($certDir . '/*', $logger);
    360     }
    361 
    362     /**
    363      * @param  string $certFile
    364      * @param  LoggerInterface|null $logger
    365      * @return bool
    366      */
    367     private static function isFile($certFile, LoggerInterface $logger = null)
    368     {
    369         $isFile = @is_file($certFile);
    370         if (!$isFile && $logger) {
    371             $logger->debug(sprintf('Checked CA file %s does not exist or it is not a file.', $certFile));
    372         }
    373 
    374         return $isFile;
    375     }
    376 
    377     /**
    378      * @param  string $certDir
    379      * @param  LoggerInterface|null $logger
    380      * @return bool
    381      */
    382     private static function isDir($certDir, LoggerInterface $logger = null)
    383     {
    384         $isDir = @is_dir($certDir);
    385         if (!$isDir && $logger) {
    386             $logger->debug(sprintf('Checked directory %s does not exist or it is not a directory.', $certDir));
    387         }
    388 
    389         return $isDir;
    390     }
    391 
    392     /**
    393      * @param  string $certFileOrDir
    394      * @param  LoggerInterface|null $logger
    395      * @return bool
    396      */
    397     private static function isReadable($certFileOrDir, LoggerInterface $logger = null)
    398     {
    399         $isReadable = @is_readable($certFileOrDir);
    400         if (!$isReadable && $logger) {
    401             $logger->debug(sprintf('Checked file or directory %s is not readable.', $certFileOrDir));
    402         }
    403 
    404         return $isReadable;
    405     }
    406 
    407     /**
    408      * @param  string $pattern
    409      * @param  LoggerInterface|null $logger
    410      * @return bool
    411      */
    412     private static function glob($pattern, LoggerInterface $logger = null)
    413     {
    414         $certs = glob($pattern);
    415         if ($certs === false) {
    416             if ($logger) {
    417                 $logger->debug(sprintf("An error occurred while trying to find certificates for pattern: %s", $pattern));
    418             }
    419             return false;
    420         }
    421 
    422         if (count($certs) === 0) {
    423             if ($logger) {
    424                 $logger->debug(sprintf("No CA files found for pattern: %s", $pattern));
    425             }
    426             return false;
    427         }
    428 
    429         return true;
    430     }
     279        $script = '<' . "?php\n" . sprintf( $script, $cert );
     280
     281        try {
     282            $process = new PhpProcess( $script );
     283            $process->mustRun();
     284        } catch ( \Exception $e ) {
     285            // In the case of any exceptions just accept it is not possible to
     286            // determine the safety of openssl_x509_parse and bail out.
     287            return self::$useOpensslParse = false;
     288        }
     289
     290        $output      = preg_split( '{\r?\n}', trim( $process->getOutput() ) );
     291        $errorOutput = trim( $process->getErrorOutput() );
     292
     293        if (
     294            is_array( $output )
     295            && count( $output ) === 3
     296            && $output[0] === sprintf( 'string(%d) "%s"', strlen( PHP_VERSION ), PHP_VERSION )
     297            && $output[1] === 'string(27) "stefan.esser@sektioneins.de"'
     298            && $output[2] === 'int(-1)'
     299            && preg_match( '{openssl_x509_parse\(\): illegal (?:ASN1 data type for|length in) timestamp in - on line \d+}', $errorOutput )
     300        ) {
     301            // This PHP has the fix backported probably by a distro security team.
     302            return self::$useOpensslParse = true;
     303        }
     304
     305        return self::$useOpensslParse = false;
     306    }
     307
     308    /**
     309     * Resets the static caches
     310     *
     311     * @return void
     312     */
     313    public static function reset() {
     314        self::$caFileValidity  = array();
     315        self::$caPath          = null;
     316        self::$useOpensslParse = null;
     317    }
     318
     319    /**
     320     * @param  string $name
     321     * @return string|false
     322     */
     323    private static function getEnvVariable( $name ) {
     324        if ( isset( $_SERVER[ $name ] ) ) {
     325            return (string) $_SERVER[ $name ];
     326        }
     327
     328        if ( PHP_SAPI === 'cli' && ( $value = getenv( $name ) ) !== false && $value !== null ) {
     329            return (string) $value;
     330        }
     331
     332        return false;
     333    }
     334
     335    /**
     336     * @param  string|false         $certFile
     337     * @param  LoggerInterface|null $logger
     338     * @return bool
     339     */
     340    private static function caFileUsable( $certFile, LoggerInterface $logger = null ) {
     341        return $certFile
     342            && static::isFile( $certFile, $logger )
     343            && static::isReadable( $certFile, $logger )
     344            && static::validateCaFile( $certFile, $logger );
     345    }
     346
     347    /**
     348     * @param  string|false         $certDir
     349     * @param  LoggerInterface|null $logger
     350     * @return bool
     351     */
     352    private static function caDirUsable( $certDir, LoggerInterface $logger = null ) {
     353        return $certDir
     354            && static::isDir( $certDir, $logger )
     355            && static::isReadable( $certDir, $logger )
     356            && static::glob( $certDir . '/*', $logger );
     357    }
     358
     359    /**
     360     * @param  string               $certFile
     361     * @param  LoggerInterface|null $logger
     362     * @return bool
     363     */
     364    private static function isFile( $certFile, LoggerInterface $logger = null ) {
     365        $isFile = @is_file( $certFile );
     366        if ( ! $isFile && $logger ) {
     367            $logger->debug( sprintf( 'Checked CA file %s does not exist or it is not a file.', $certFile ) );
     368        }
     369
     370        return $isFile;
     371    }
     372
     373    /**
     374     * @param  string               $certDir
     375     * @param  LoggerInterface|null $logger
     376     * @return bool
     377     */
     378    private static function isDir( $certDir, LoggerInterface $logger = null ) {
     379        $isDir = @is_dir( $certDir );
     380        if ( ! $isDir && $logger ) {
     381            $logger->debug( sprintf( 'Checked directory %s does not exist or it is not a directory.', $certDir ) );
     382        }
     383
     384        return $isDir;
     385    }
     386
     387    /**
     388     * @param  string               $certFileOrDir
     389     * @param  LoggerInterface|null $logger
     390     * @return bool
     391     */
     392    private static function isReadable( $certFileOrDir, LoggerInterface $logger = null ) {
     393        $isReadable = @is_readable( $certFileOrDir );
     394        if ( ! $isReadable && $logger ) {
     395            $logger->debug( sprintf( 'Checked file or directory %s is not readable.', $certFileOrDir ) );
     396        }
     397
     398        return $isReadable;
     399    }
     400
     401    /**
     402     * @param  string               $pattern
     403     * @param  LoggerInterface|null $logger
     404     * @return bool
     405     */
     406    private static function glob( $pattern, LoggerInterface $logger = null ) {
     407        $certs = glob( $pattern );
     408        if ( $certs === false ) {
     409            if ( $logger ) {
     410                $logger->debug( sprintf( 'An error occurred while trying to find certificates for pattern: %s', $pattern ) );
     411            }
     412            return false;
     413        }
     414
     415        if ( count( $certs ) === 0 ) {
     416            if ( $logger ) {
     417                $logger->debug( sprintf( 'No CA files found for pattern: %s', $pattern ) );
     418            }
     419            return false;
     420        }
     421
     422        return true;
     423    }
    431424}
  • termageddon-usercentrics/trunk/vendor/composer/installed.php

    r2976730 r3160131  
    11<?php return array(
    2     'root' => array(
    3         'name' => 'termageddon/termageddon-usercentrics',
    4         'pretty_version' => 'dev-main',
    5         'version' => 'dev-main',
    6         'reference' => '88511e7dd7de711d12c6d12147b0bb96908a84c5',
    7         'type' => 'library',
    8         'install_path' => __DIR__ . '/../../',
    9         'aliases' => array(),
    10         'dev' => true,
    11     ),
    12     'versions' => array(
    13         'composer/ca-bundle' => array(
    14             'pretty_version' => '1.3.7',
    15             'version' => '1.3.7.0',
    16             'reference' => '76e46335014860eec1aa5a724799a00a2e47cc85',
    17             'type' => 'library',
    18             'install_path' => __DIR__ . '/./ca-bundle',
    19             'aliases' => array(),
    20             'dev_requirement' => false,
    21         ),
    22         'geoip2/geoip2' => array(
    23             'pretty_version' => 'v2.10.0',
    24             'version' => '2.10.0.0',
    25             'reference' => '419557cd21d9fe039721a83490701a58c8ce784a',
    26             'type' => 'library',
    27             'install_path' => __DIR__ . '/../geoip2/geoip2',
    28             'aliases' => array(),
    29             'dev_requirement' => false,
    30         ),
    31         'maxmind-db/reader' => array(
    32             'pretty_version' => 'v1.11.0',
    33             'version' => '1.11.0.0',
    34             'reference' => 'b1f3c0699525336d09cc5161a2861268d9f2ae5b',
    35             'type' => 'library',
    36             'install_path' => __DIR__ . '/../maxmind-db/reader',
    37             'aliases' => array(),
    38             'dev_requirement' => false,
    39         ),
    40         'maxmind/web-service-common' => array(
    41             'pretty_version' => 'v0.9.0',
    42             'version' => '0.9.0.0',
    43             'reference' => '4dc5a3e8df38aea4ca3b1096cee3a038094e9b53',
    44             'type' => 'library',
    45             'install_path' => __DIR__ . '/../maxmind/web-service-common',
    46             'aliases' => array(),
    47             'dev_requirement' => false,
    48         ),
    49         'termageddon/termageddon-usercentrics' => array(
    50             'pretty_version' => 'dev-main',
    51             'version' => 'dev-main',
    52             'reference' => '88511e7dd7de711d12c6d12147b0bb96908a84c5',
    53             'type' => 'library',
    54             'install_path' => __DIR__ . '/../../',
    55             'aliases' => array(),
    56             'dev_requirement' => false,
    57         ),
    58     ),
     2    'root'    => array(
     3        'name'          => 'termageddon/termageddon-usercentrics',
     4        'pretty_version' => 'dev-main',
     5        'version'        => 'dev-main',
     6        'reference'      => '88511e7dd7de711d12c6d12147b0bb96908a84c5',
     7        'type'          => 'library',
     8        'install_path'  => __DIR__ . '/../../',
     9        'aliases'        => array(),
     10        'dev'            => true,
     11    ),
     12    'versions' => array(
     13        'composer/ca-bundle'                  => array(
     14            'pretty_version' => '1.3.7',
     15            'version'        => '1.3.7.0',
     16            'reference'      => '76e46335014860eec1aa5a724799a00a2e47cc85',
     17            'type'            => 'library',
     18            'install_path'    => __DIR__ . '/./ca-bundle',
     19            'aliases'        => array(),
     20            'dev_requirement' => false,
     21        ),
     22        'geoip2/geoip2'                        => array(
     23            'pretty_version' => 'v2.10.0',
     24            'version'        => '2.10.0.0',
     25            'reference'      => '419557cd21d9fe039721a83490701a58c8ce784a',
     26            'type'            => 'library',
     27            'install_path'    => __DIR__ . '/../geoip2/geoip2',
     28            'aliases'        => array(),
     29            'dev_requirement' => false,
     30        ),
     31        'maxmind-db/reader'                    => array(
     32            'pretty_version' => 'v1.11.0',
     33            'version'        => '1.11.0.0',
     34            'reference'      => 'b1f3c0699525336d09cc5161a2861268d9f2ae5b',
     35            'type'            => 'library',
     36            'install_path'    => __DIR__ . '/../maxmind-db/reader',
     37            'aliases'        => array(),
     38            'dev_requirement' => false,
     39        ),
     40        'maxmind/web-service-common'          => array(
     41            'pretty_version' => 'v0.9.0',
     42            'version'        => '0.9.0.0',
     43            'reference'      => '4dc5a3e8df38aea4ca3b1096cee3a038094e9b53',
     44            'type'            => 'library',
     45            'install_path'    => __DIR__ . '/../maxmind/web-service-common',
     46            'aliases'        => array(),
     47            'dev_requirement' => false,
     48        ),
     49        'termageddon/termageddon-usercentrics' => array(
     50            'pretty_version' => 'dev-main',
     51            'version'        => 'dev-main',
     52            'reference'      => '88511e7dd7de711d12c6d12147b0bb96908a84c5',
     53            'type'            => 'library',
     54            'install_path'    => __DIR__ . '/../../',
     55            'aliases'        => array(),
     56            'dev_requirement' => false,
     57        ),
     58    ),
    5959);
  • termageddon-usercentrics/trunk/vendor/composer/platform_check.php

    r2771752 r3160131  
    55$issues = array();
    66
    7 if (!(PHP_VERSION_ID >= 70200)) {
    8     $issues[] = 'Your Composer dependencies require a PHP version ">= 7.2.0". You are running ' . PHP_VERSION . '.';
     7if ( ! ( PHP_VERSION_ID >= 70200 ) ) {
     8    $issues[] = 'Your Composer dependencies require a PHP version ">= 7.2.0". You are running ' . PHP_VERSION . '.';
    99}
    1010
    11 if ($issues) {
    12     if (!headers_sent()) {
    13         header('HTTP/1.1 500 Internal Server Error');
    14     }
    15     if (!ini_get('display_errors')) {
    16         if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
    17             fwrite(STDERR, 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . implode(PHP_EOL, $issues) . PHP_EOL.PHP_EOL);
    18         } elseif (!headers_sent()) {
    19             echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL;
    20         }
    21     }
    22     trigger_error(
    23         'Composer detected issues in your platform: ' . implode(' ', $issues),
    24         E_USER_ERROR
    25     );
     11if ( $issues ) {
     12    if ( ! headers_sent() ) {
     13        header( 'HTTP/1.1 500 Internal Server Error' );
     14    }
     15    if ( ! ini_get( 'display_errors' ) ) {
     16        if ( PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg' ) {
     17            fwrite( STDERR, 'Composer detected issues in your platform:' . PHP_EOL . PHP_EOL . implode( PHP_EOL, $issues ) . PHP_EOL . PHP_EOL );
     18        } elseif ( ! headers_sent() ) {
     19            echo 'Composer detected issues in your platform:' . PHP_EOL . PHP_EOL . str_replace( 'You are running ' . PHP_VERSION . '.', '', implode( PHP_EOL, $issues ) ) . PHP_EOL . PHP_EOL;
     20        }
     21    }
     22    trigger_error(
     23        'Composer detected issues in your platform: ' . implode( ' ', $issues ),
     24        E_USER_ERROR
     25    );
    2626}
  • termageddon-usercentrics/trunk/vendor/geoip2/geoip2/examples/benchmark.php

    r2976730 r3160131  
    55use GeoIp2\Database\Reader;
    66
    7 srand(0);
     7srand( 0 );
    88
    9 $reader = new Reader('GeoIP2-City.mmdb');
    10 $count = 500000;
    11 $startTime = microtime(true);
    12 for ($i = 0; $i < $count; ++$i) {
    13     $ip = long2ip(rand(0, pow(2, 32) - 1));
    14     try {
    15         $t = $reader->city($ip);
    16     } catch (\GeoIp2\Exception\AddressNotFoundException $e) {
    17     }
    18     if ($i % 10000 === 0) {
    19         echo $i . ' ' . $ip . "\n";
    20     }
     9$reader    = new Reader( 'GeoIP2-City.mmdb' );
     10$count     = 500000;
     11$startTime = microtime( true );
     12for ( $i = 0; $i < $count; ++$i ) {
     13    $ip = long2ip( rand( 0, pow( 2, 32 ) - 1 ) );
     14    try {
     15        $t = $reader->city( $ip );
     16    } catch ( \GeoIp2\Exception\AddressNotFoundException $e ) {
     17    }
     18    if ( $i % 10000 === 0 ) {
     19        echo $i . ' ' . $ip . "\n";
     20    }
    2121}
    22 $endTime = microtime(true);
     22$endTime = microtime( true );
    2323
    2424$duration = $endTime - $startTime;
  • termageddon-usercentrics/trunk/vendor/geoip2/geoip2/src/Database/Reader.php

    r2976730 r3160131  
    3232 * will be thrown.
    3333 */
    34 class Reader implements ProviderInterface
    35 {
    36     private $dbReader;
    37     private $dbType;
    38     private $locales;
    39 
    40     /**
    41      * Constructor.
    42      *
    43      * @param string $filename the path to the GeoIP2 database file
    44      * @param array  $locales  list of locale codes to use in name property
    45      *                         from most preferred to least preferred
    46      *
    47      * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
    48      *                                                     is corrupt or invalid
    49      */
    50     public function __construct(
    51         $filename,
    52         $locales = ['en']
    53     ) {
    54         $this->dbReader = new DbReader($filename);
    55         $this->dbType = $this->dbReader->metadata()->databaseType;
    56         $this->locales = $locales;
    57     }
    58 
    59     /**
    60      * This method returns a GeoIP2 City model.
    61      *
    62      * @param string $ipAddress an IPv4 or IPv6 address as a string
    63      *
    64      * @throws \GeoIp2\Exception\AddressNotFoundException  if the address is
    65      *                                                     not in the database
    66      * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
    67      *                                                     is corrupt or invalid
    68      *
    69      * @return \GeoIp2\Model\City
    70      */
    71     public function city($ipAddress)
    72     {
    73         return $this->modelFor('City', 'City', $ipAddress);
    74     }
    75 
    76     /**
    77      * This method returns a GeoIP2 Country model.
    78      *
    79      * @param string $ipAddress an IPv4 or IPv6 address as a string
    80      *
    81      * @throws \GeoIp2\Exception\AddressNotFoundException  if the address is
    82      *                                                     not in the database
    83      * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
    84      *                                                     is corrupt or invalid
    85      *
    86      * @return \GeoIp2\Model\Country
    87      */
    88     public function country($ipAddress)
    89     {
    90         return $this->modelFor('Country', 'Country', $ipAddress);
    91     }
    92 
    93     /**
    94      * This method returns a GeoIP2 Anonymous IP model.
    95      *
    96      * @param string $ipAddress an IPv4 or IPv6 address as a string
    97      *
    98      * @throws \GeoIp2\Exception\AddressNotFoundException  if the address is
    99      *                                                     not in the database
    100      * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
    101      *                                                     is corrupt or invalid
    102      *
    103      * @return \GeoIp2\Model\AnonymousIp
    104      */
    105     public function anonymousIp($ipAddress)
    106     {
    107         return $this->flatModelFor(
    108             'AnonymousIp',
    109             'GeoIP2-Anonymous-IP',
    110             $ipAddress
    111         );
    112     }
    113 
    114     /**
    115      * This method returns a GeoLite2 ASN model.
    116      *
    117      * @param string $ipAddress an IPv4 or IPv6 address as a string
    118      *
    119      * @throws \GeoIp2\Exception\AddressNotFoundException  if the address is
    120      *                                                     not in the database
    121      * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
    122      *                                                     is corrupt or invalid
    123      *
    124      * @return \GeoIp2\Model\Asn
    125      */
    126     public function asn($ipAddress)
    127     {
    128         return $this->flatModelFor(
    129             'Asn',
    130             'GeoLite2-ASN',
    131             $ipAddress
    132         );
    133     }
    134 
    135     /**
    136      * This method returns a GeoIP2 Connection Type model.
    137      *
    138      * @param string $ipAddress an IPv4 or IPv6 address as a string
    139      *
    140      * @throws \GeoIp2\Exception\AddressNotFoundException  if the address is
    141      *                                                     not in the database
    142      * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
    143      *                                                     is corrupt or invalid
    144      *
    145      * @return \GeoIp2\Model\ConnectionType
    146      */
    147     public function connectionType($ipAddress)
    148     {
    149         return $this->flatModelFor(
    150             'ConnectionType',
    151             'GeoIP2-Connection-Type',
    152             $ipAddress
    153         );
    154     }
    155 
    156     /**
    157      * This method returns a GeoIP2 Domain model.
    158      *
    159      * @param string $ipAddress an IPv4 or IPv6 address as a string
    160      *
    161      * @throws \GeoIp2\Exception\AddressNotFoundException  if the address is
    162      *                                                     not in the database
    163      * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
    164      *                                                     is corrupt or invalid
    165      *
    166      * @return \GeoIp2\Model\Domain
    167      */
    168     public function domain($ipAddress)
    169     {
    170         return $this->flatModelFor(
    171             'Domain',
    172             'GeoIP2-Domain',
    173             $ipAddress
    174         );
    175     }
    176 
    177     /**
    178      * This method returns a GeoIP2 Enterprise model.
    179      *
    180      * @param string $ipAddress an IPv4 or IPv6 address as a string
    181      *
    182      * @throws \GeoIp2\Exception\AddressNotFoundException  if the address is
    183      *                                                     not in the database
    184      * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
    185      *                                                     is corrupt or invalid
    186      *
    187      * @return \GeoIp2\Model\Enterprise
    188      */
    189     public function enterprise($ipAddress)
    190     {
    191         return $this->modelFor('Enterprise', 'Enterprise', $ipAddress);
    192     }
    193 
    194     /**
    195      * This method returns a GeoIP2 ISP model.
    196      *
    197      * @param string $ipAddress an IPv4 or IPv6 address as a string
    198      *
    199      * @throws \GeoIp2\Exception\AddressNotFoundException  if the address is
    200      *                                                     not in the database
    201      * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
    202      *                                                     is corrupt or invalid
    203      *
    204      * @return \GeoIp2\Model\Isp
    205      */
    206     public function isp($ipAddress)
    207     {
    208         return $this->flatModelFor(
    209             'Isp',
    210             'GeoIP2-ISP',
    211             $ipAddress
    212         );
    213     }
    214 
    215     private function modelFor($class, $type, $ipAddress)
    216     {
    217         list($record, $prefixLen) = $this->getRecord($class, $type, $ipAddress);
    218 
    219         $record['traits']['ip_address'] = $ipAddress;
    220         $record['traits']['prefix_len'] = $prefixLen;
    221 
    222         $class = 'GeoIp2\\Model\\' . $class;
    223 
    224         return new $class($record, $this->locales);
    225     }
    226 
    227     private function flatModelFor($class, $type, $ipAddress)
    228     {
    229         list($record, $prefixLen) = $this->getRecord($class, $type, $ipAddress);
    230 
    231         $record['ip_address'] = $ipAddress;
    232         $record['prefix_len'] = $prefixLen;
    233         $class = 'GeoIp2\\Model\\' . $class;
    234 
    235         return new $class($record);
    236     }
    237 
    238     private function getRecord($class, $type, $ipAddress)
    239     {
    240         if (strpos($this->dbType, $type) === false) {
    241             $method = lcfirst($class);
    242             throw new \BadMethodCallException(
    243                 "The $method method cannot be used to open a {$this->dbType} database"
    244             );
    245         }
    246         list($record, $prefixLen) = $this->dbReader->getWithPrefixLen($ipAddress);
    247         if ($record === null) {
    248             throw new AddressNotFoundException(
    249                 "The address $ipAddress is not in the database."
    250             );
    251         }
    252         if (!\is_array($record)) {
    253             // This can happen on corrupt databases. Generally,
    254             // MaxMind\Db\Reader will throw a
    255             // MaxMind\Db\Reader\InvalidDatabaseException, but occasionally
    256             // the lookup may result in a record that looks valid but is not
    257             // an array. This mostly happens when the user is ignoring all
    258             // exceptions and the more frequent InvalidDatabaseException
    259             // exceptions go unnoticed.
    260             throw new InvalidDatabaseException(
    261                 "Expected an array when looking up $ipAddress but received: "
    262                 . \gettype($record)
    263             );
    264         }
    265 
    266         return [$record, $prefixLen];
    267     }
    268 
    269     /**
    270      * @throws \InvalidArgumentException if arguments are passed to the method
    271      * @throws \BadMethodCallException   if the database has been closed
    272      *
    273      * @return \MaxMind\Db\Reader\Metadata object for the database
    274      */
    275     public function metadata()
    276     {
    277         return $this->dbReader->metadata();
    278     }
    279 
    280     /**
    281      * Closes the GeoIP2 database and returns the resources to the system.
    282      */
    283     public function close()
    284     {
    285         $this->dbReader->close();
    286     }
     34class Reader implements ProviderInterface {
     35
     36    private $dbReader;
     37    private $dbType;
     38    private $locales;
     39
     40    /**
     41     * Constructor.
     42     *
     43     * @param string $filename the path to the GeoIP2 database file
     44     * @param array  $locales  list of locale codes to use in name property
     45     *                         from most preferred to least preferred
     46     *
     47     * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
     48     *                                                     is corrupt or invalid
     49     */
     50    public function __construct(
     51        $filename,
     52        $locales = array( 'en' )
     53    ) {
     54        $this->dbReader = new DbReader( $filename );
     55        $this->dbType   = $this->dbReader->metadata()->databaseType;
     56        $this->locales  = $locales;
     57    }
     58
     59    /**
     60     * This method returns a GeoIP2 City model.
     61     *
     62     * @param string $ipAddress an IPv4 or IPv6 address as a string
     63     *
     64     * @throws \GeoIp2\Exception\AddressNotFoundException  if the address is
     65     *                                                     not in the database
     66     * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
     67     *                                                     is corrupt or invalid
     68     *
     69     * @return \GeoIp2\Model\City
     70     */
     71    public function city( $ipAddress ) {
     72        return $this->modelFor( 'City', 'City', $ipAddress );
     73    }
     74
     75    /**
     76     * This method returns a GeoIP2 Country model.
     77     *
     78     * @param string $ipAddress an IPv4 or IPv6 address as a string
     79     *
     80     * @throws \GeoIp2\Exception\AddressNotFoundException  if the address is
     81     *                                                     not in the database
     82     * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
     83     *                                                     is corrupt or invalid
     84     *
     85     * @return \GeoIp2\Model\Country
     86     */
     87    public function country( $ipAddress ) {
     88        return $this->modelFor( 'Country', 'Country', $ipAddress );
     89    }
     90
     91    /**
     92     * This method returns a GeoIP2 Anonymous IP model.
     93     *
     94     * @param string $ipAddress an IPv4 or IPv6 address as a string
     95     *
     96     * @throws \GeoIp2\Exception\AddressNotFoundException  if the address is
     97     *                                                     not in the database
     98     * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
     99     *                                                     is corrupt or invalid
     100     *
     101     * @return \GeoIp2\Model\AnonymousIp
     102     */
     103    public function anonymousIp( $ipAddress ) {
     104        return $this->flatModelFor(
     105            'AnonymousIp',
     106            'GeoIP2-Anonymous-IP',
     107            $ipAddress
     108        );
     109    }
     110
     111    /**
     112     * This method returns a GeoLite2 ASN model.
     113     *
     114     * @param string $ipAddress an IPv4 or IPv6 address as a string
     115     *
     116     * @throws \GeoIp2\Exception\AddressNotFoundException  if the address is
     117     *                                                     not in the database
     118     * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
     119     *                                                     is corrupt or invalid
     120     *
     121     * @return \GeoIp2\Model\Asn
     122     */
     123    public function asn( $ipAddress ) {
     124        return $this->flatModelFor(
     125            'Asn',
     126            'GeoLite2-ASN',
     127            $ipAddress
     128        );
     129    }
     130
     131    /**
     132     * This method returns a GeoIP2 Connection Type model.
     133     *
     134     * @param string $ipAddress an IPv4 or IPv6 address as a string
     135     *
     136     * @throws \GeoIp2\Exception\AddressNotFoundException  if the address is
     137     *                                                     not in the database
     138     * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
     139     *                                                     is corrupt or invalid
     140     *
     141     * @return \GeoIp2\Model\ConnectionType
     142     */
     143    public function connectionType( $ipAddress ) {
     144        return $this->flatModelFor(
     145            'ConnectionType',
     146            'GeoIP2-Connection-Type',
     147            $ipAddress
     148        );
     149    }
     150
     151    /**
     152     * This method returns a GeoIP2 Domain model.
     153     *
     154     * @param string $ipAddress an IPv4 or IPv6 address as a string
     155     *
     156     * @throws \GeoIp2\Exception\AddressNotFoundException  if the address is
     157     *                                                     not in the database
     158     * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
     159     *                                                     is corrupt or invalid
     160     *
     161     * @return \GeoIp2\Model\Domain
     162     */
     163    public function domain( $ipAddress ) {
     164        return $this->flatModelFor(
     165            'Domain',
     166            'GeoIP2-Domain',
     167            $ipAddress
     168        );
     169    }
     170
     171    /**
     172     * This method returns a GeoIP2 Enterprise model.
     173     *
     174     * @param string $ipAddress an IPv4 or IPv6 address as a string
     175     *
     176     * @throws \GeoIp2\Exception\AddressNotFoundException  if the address is
     177     *                                                     not in the database
     178     * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
     179     *                                                     is corrupt or invalid
     180     *
     181     * @return \GeoIp2\Model\Enterprise
     182     */
     183    public function enterprise( $ipAddress ) {
     184        return $this->modelFor( 'Enterprise', 'Enterprise', $ipAddress );
     185    }
     186
     187    /**
     188     * This method returns a GeoIP2 ISP model.
     189     *
     190     * @param string $ipAddress an IPv4 or IPv6 address as a string
     191     *
     192     * @throws \GeoIp2\Exception\AddressNotFoundException  if the address is
     193     *                                                     not in the database
     194     * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
     195     *                                                     is corrupt or invalid
     196     *
     197     * @return \GeoIp2\Model\Isp
     198     */
     199    public function isp( $ipAddress ) {
     200        return $this->flatModelFor(
     201            'Isp',
     202            'GeoIP2-ISP',
     203            $ipAddress
     204        );
     205    }
     206
     207    private function modelFor( $class, $type, $ipAddress ) {
     208        list($record, $prefixLen) = $this->getRecord( $class, $type, $ipAddress );
     209
     210        $record['traits']['ip_address'] = $ipAddress;
     211        $record['traits']['prefix_len'] = $prefixLen;
     212
     213        $class = 'GeoIp2\\Model\\' . $class;
     214
     215        return new $class( $record, $this->locales );
     216    }
     217
     218    private function flatModelFor( $class, $type, $ipAddress ) {
     219        list($record, $prefixLen) = $this->getRecord( $class, $type, $ipAddress );
     220
     221        $record['ip_address'] = $ipAddress;
     222        $record['prefix_len'] = $prefixLen;
     223        $class                = 'GeoIp2\\Model\\' . $class;
     224
     225        return new $class( $record );
     226    }
     227
     228    private function getRecord( $class, $type, $ipAddress ) {
     229        if ( strpos( $this->dbType, $type ) === false ) {
     230            $method = lcfirst( $class );
     231            throw new \BadMethodCallException(
     232                "The $method method cannot be used to open a {$this->dbType} database"
     233            );
     234        }
     235        list($record, $prefixLen) = $this->dbReader->getWithPrefixLen( $ipAddress );
     236        if ( $record === null ) {
     237            throw new AddressNotFoundException(
     238                "The address $ipAddress is not in the database."
     239            );
     240        }
     241        if ( ! \is_array( $record ) ) {
     242            // This can happen on corrupt databases. Generally,
     243            // MaxMind\Db\Reader will throw a
     244            // MaxMind\Db\Reader\InvalidDatabaseException, but occasionally
     245            // the lookup may result in a record that looks valid but is not
     246            // an array. This mostly happens when the user is ignoring all
     247            // exceptions and the more frequent InvalidDatabaseException
     248            // exceptions go unnoticed.
     249            throw new InvalidDatabaseException(
     250                "Expected an array when looking up $ipAddress but received: "
     251                . \gettype( $record )
     252            );
     253        }
     254
     255        return array( $record, $prefixLen );
     256    }
     257
     258    /**
     259     * @throws \InvalidArgumentException if arguments are passed to the method
     260     * @throws \BadMethodCallException   if the database has been closed
     261     *
     262     * @return \MaxMind\Db\Reader\Metadata object for the database
     263     */
     264    public function metadata() {
     265        return $this->dbReader->metadata();
     266    }
     267
     268    /**
     269     * Closes the GeoIP2 database and returns the resources to the system.
     270     */
     271    public function close() {
     272        $this->dbReader->close();
     273    }
    287274}
  • termageddon-usercentrics/trunk/vendor/geoip2/geoip2/src/Exception/AddressNotFoundException.php

    r2976730 r3160131  
    66 * This class represents a generic error.
    77 */
    8 class AddressNotFoundException extends GeoIp2Exception
    9 {
     8class AddressNotFoundException extends GeoIp2Exception {
     9
    1010}
  • termageddon-usercentrics/trunk/vendor/geoip2/geoip2/src/Exception/AuthenticationException.php

    r2976730 r3160131  
    66 * This class represents a generic error.
    77 */
    8 class AuthenticationException extends GeoIp2Exception
    9 {
     8class AuthenticationException extends GeoIp2Exception {
     9
    1010}
  • termageddon-usercentrics/trunk/vendor/geoip2/geoip2/src/Exception/GeoIp2Exception.php

    r2976730 r3160131  
    66 * This class represents a generic error.
    77 */
    8 class GeoIp2Exception extends \Exception
    9 {
     8class GeoIp2Exception extends \Exception {
     9
    1010}
  • termageddon-usercentrics/trunk/vendor/geoip2/geoip2/src/Exception/HttpException.php

    r2976730 r3160131  
    66 *  This class represents an HTTP transport error.
    77 */
    8 class HttpException extends GeoIp2Exception
    9 {
    10     /**
    11      * The URI queried.
    12      */
    13     public $uri;
     8class HttpException extends GeoIp2Exception {
    149
    15     public function __construct(
    16         $message,
    17         $httpStatus,
    18         $uri,
    19         \Exception $previous = null
    20     ) {
    21         $this->uri = $uri;
    22         parent::__construct($message, $httpStatus, $previous);
    23     }
     10    /**
     11     * The URI queried.
     12     */
     13    public $uri;
     14
     15    public function __construct(
     16        $message,
     17        $httpStatus,
     18        $uri,
     19        \Exception $previous = null
     20    ) {
     21        $this->uri = $uri;
     22        parent::__construct( $message, $httpStatus, $previous );
     23    }
    2424}
  • termageddon-usercentrics/trunk/vendor/geoip2/geoip2/src/Exception/InvalidRequestException.php

    r2976730 r3160131  
    77 * web service.
    88 */
    9 class InvalidRequestException extends HttpException
    10 {
    11     /**
    12      * The code returned by the MaxMind web service.
    13      */
    14     public $error;
     9class InvalidRequestException extends HttpException {
    1510
    16     public function __construct(
    17         $message,
    18         $error,
    19         $httpStatus,
    20         $uri,
    21         \Exception $previous = null
    22     ) {
    23         $this->error = $error;
    24         parent::__construct($message, $httpStatus, $uri, $previous);
    25     }
     11    /**
     12     * The code returned by the MaxMind web service.
     13     */
     14    public $error;
     15
     16    public function __construct(
     17        $message,
     18        $error,
     19        $httpStatus,
     20        $uri,
     21        \Exception $previous = null
     22    ) {
     23        $this->error = $error;
     24        parent::__construct( $message, $httpStatus, $uri, $previous );
     25    }
    2626}
  • termageddon-usercentrics/trunk/vendor/geoip2/geoip2/src/Exception/OutOfQueriesException.php

    r2976730 r3160131  
    66 * This class represents a generic error.
    77 */
    8 class OutOfQueriesException extends GeoIp2Exception
    9 {
     8class OutOfQueriesException extends GeoIp2Exception {
     9
    1010}
  • termageddon-usercentrics/trunk/vendor/geoip2/geoip2/src/Model/AbstractModel.php

    r2976730 r3160131  
    66 * @ignore
    77 */
    8 abstract class AbstractModel implements \JsonSerializable
    9 {
    10     protected $raw;
     8abstract class AbstractModel implements \JsonSerializable {
    119
    12     /**
    13      * @ignore
    14      *
    15      * @param mixed $raw
    16      */
    17     public function __construct($raw)
    18     {
    19         $this->raw = $raw;
    20     }
     10    protected $raw;
    2111
    22     /**
    23      * @ignore
    24      *
    25      * @param mixed $field
    26      */
    27     protected function get($field)
    28     {
    29         if (isset($this->raw[$field])) {
    30             return $this->raw[$field];
    31         }
    32         if (preg_match('/^is_/', $field)) {
    33             return false;
    34         }
     12    /**
     13     * @ignore
     14     *
     15     * @param mixed $raw
     16     */
     17    public function __construct( $raw ) {
     18        $this->raw = $raw;
     19    }
    3520
    36         return null;
    37     }
     21    /**
     22     * @ignore
     23     *
     24     * @param mixed $field
     25     */
     26    protected function get( $field ) {
     27        if ( isset( $this->raw[ $field ] ) ) {
     28            return $this->raw[ $field ];
     29        }
     30        if ( preg_match( '/^is_/', $field ) ) {
     31            return false;
     32        }
    3833
    39     /**
    40      * @ignore
    41      *
    42      * @param mixed $attr
    43      */
    44     public function __get($attr)
    45     {
    46         if ($attr !== 'instance' && property_exists($this, $attr)) {
    47             return $this->$attr;
    48         }
     34        return null;
     35    }
    4936
    50         throw new \RuntimeException("Unknown attribute: $attr");
    51     }
     37    /**
     38     * @ignore
     39     *
     40     * @param mixed $attr
     41     */
     42    public function __get( $attr ) {
     43        if ( $attr !== 'instance' && property_exists( $this, $attr ) ) {
     44            return $this->$attr;
     45        }
    5246
    53     /**
    54      * @ignore
    55      *
    56      * @param mixed $attr
    57      */
    58     public function __isset($attr)
    59     {
    60         return $attr !== 'instance' && isset($this->$attr);
    61     }
     47        throw new \RuntimeException( "Unknown attribute: $attr" );
     48    }
    6249
    63     public function jsonSerialize()
    64     {
    65         return $this->raw;
    66     }
     50    /**
     51     * @ignore
     52     *
     53     * @param mixed $attr
     54     */
     55    public function __isset( $attr ) {
     56        return $attr !== 'instance' && isset( $this->$attr );
     57    }
     58
     59    public function jsonSerialize() {
     60        return $this->raw;
     61    }
    6762}
  • termageddon-usercentrics/trunk/vendor/geoip2/geoip2/src/Model/AnonymousIp.php

    r2976730 r3160131  
    2626 *      fields besides $ipAddress have the same value.
    2727 */
    28 class AnonymousIp extends AbstractModel
    29 {
    30     protected $isAnonymous;
    31     protected $isAnonymousVpn;
    32     protected $isHostingProvider;
    33     protected $isPublicProxy;
    34     protected $isTorExitNode;
    35     protected $ipAddress;
    36     protected $network;
     28class AnonymousIp extends AbstractModel {
    3729
    38     /**
    39      * @ignore
    40      *
    41      * @param mixed $raw
    42      */
    43     public function __construct($raw)
    44     {
    45         parent::__construct($raw);
     30    protected $isAnonymous;
     31    protected $isAnonymousVpn;
     32    protected $isHostingProvider;
     33    protected $isPublicProxy;
     34    protected $isTorExitNode;
     35    protected $ipAddress;
     36    protected $network;
    4637
    47         $this->isAnonymous = $this->get('is_anonymous');
    48         $this->isAnonymousVpn = $this->get('is_anonymous_vpn');
    49         $this->isHostingProvider = $this->get('is_hosting_provider');
    50         $this->isPublicProxy = $this->get('is_public_proxy');
    51         $this->isTorExitNode = $this->get('is_tor_exit_node');
    52         $ipAddress = $this->get('ip_address');
    53         $this->ipAddress = $ipAddress;
    54         $this->network = Util::cidr($ipAddress, $this->get('prefix_len'));
    55     }
     38    /**
     39     * @ignore
     40     *
     41     * @param mixed $raw
     42     */
     43    public function __construct( $raw ) {
     44        parent::__construct( $raw );
     45
     46        $this->isAnonymous       = $this->get( 'is_anonymous' );
     47        $this->isAnonymousVpn    = $this->get( 'is_anonymous_vpn' );
     48        $this->isHostingProvider = $this->get( 'is_hosting_provider' );
     49        $this->isPublicProxy     = $this->get( 'is_public_proxy' );
     50        $this->isTorExitNode     = $this->get( 'is_tor_exit_node' );
     51        $ipAddress               = $this->get( 'ip_address' );
     52        $this->ipAddress         = $ipAddress;
     53        $this->network           = Util::cidr( $ipAddress, $this->get( 'prefix_len' ) );
     54    }
    5655}
  • termageddon-usercentrics/trunk/vendor/geoip2/geoip2/src/Model/Asn.php

    r2976730 r3160131  
    1919 *      fields besides $ipAddress have the same value.
    2020 */
    21 class Asn extends AbstractModel
    22 {
    23     protected $autonomousSystemNumber;
    24     protected $autonomousSystemOrganization;
    25     protected $ipAddress;
    26     protected $network;
     21class Asn extends AbstractModel {
    2722
    28     /**
    29      * @ignore
    30      *
    31      * @param mixed $raw
    32      */
    33     public function __construct($raw)
    34     {
    35         parent::__construct($raw);
    36         $this->autonomousSystemNumber = $this->get('autonomous_system_number');
    37         $this->autonomousSystemOrganization =
    38             $this->get('autonomous_system_organization');
    39         $ipAddress = $this->get('ip_address');
    40         $this->ipAddress = $ipAddress;
    41         $this->network = Util::cidr($ipAddress, $this->get('prefix_len'));
    42     }
     23    protected $autonomousSystemNumber;
     24    protected $autonomousSystemOrganization;
     25    protected $ipAddress;
     26    protected $network;
     27
     28    /**
     29     * @ignore
     30     *
     31     * @param mixed $raw
     32     */
     33    public function __construct( $raw ) {
     34        parent::__construct( $raw );
     35        $this->autonomousSystemNumber       = $this->get( 'autonomous_system_number' );
     36        $this->autonomousSystemOrganization =
     37            $this->get( 'autonomous_system_organization' );
     38        $ipAddress                          = $this->get( 'ip_address' );
     39        $this->ipAddress                    = $ipAddress;
     40        $this->network                      = Util::cidr( $ipAddress, $this->get( 'prefix_len' ) );
     41    }
    4342}
  • termageddon-usercentrics/trunk/vendor/geoip2/geoip2/src/Model/City.php

    r2976730 r3160131  
    2828 * \GeoIp2\Record\Subdivision object.
    2929 */
    30 class City extends Country
    31 {
    32     /**
    33      * @ignore
    34      */
    35     protected $city;
    36     /**
    37      * @ignore
    38      */
    39     protected $location;
    40     /**
    41      * @ignore
    42      */
    43     protected $postal;
    44     /**
    45      * @ignore
    46      */
    47     protected $subdivisions = [];
     30class City extends Country {
    4831
    49     /**
    50      * @ignore
    51      *
    52      * @param mixed $raw
    53      * @param mixed $locales
    54      */
    55     public function __construct($raw, $locales = ['en'])
    56     {
    57         parent::__construct($raw, $locales);
     32    /**
     33     * @ignore
     34     */
     35    protected $city;
     36    /**
     37     * @ignore
     38     */
     39    protected $location;
     40    /**
     41     * @ignore
     42     */
     43    protected $postal;
     44    /**
     45     * @ignore
     46     */
     47    protected $subdivisions = array();
    5848
    59         $this->city = new \GeoIp2\Record\City($this->get('city'), $locales);
    60         $this->location = new \GeoIp2\Record\Location($this->get('location'));
    61         $this->postal = new \GeoIp2\Record\Postal($this->get('postal'));
     49    /**
     50     * @ignore
     51     *
     52     * @param mixed $raw
     53     * @param mixed $locales
     54     */
     55    public function __construct( $raw, $locales = array( 'en' ) ) {
     56        parent::__construct( $raw, $locales );
    6257
    63         $this->createSubdivisions($raw, $locales);
    64     }
     58        $this->city     = new \GeoIp2\Record\City( $this->get( 'city' ), $locales );
     59        $this->location = new \GeoIp2\Record\Location( $this->get( 'location' ) );
     60        $this->postal   = new \GeoIp2\Record\Postal( $this->get( 'postal' ) );
    6561
    66     private function createSubdivisions($raw, $locales)
    67     {
    68         if (!isset($raw['subdivisions'])) {
    69             return;
    70         }
     62        $this->createSubdivisions( $raw, $locales );
     63    }
    7164
    72         foreach ($raw['subdivisions'] as $sub) {
    73             array_push(
    74                 $this->subdivisions,
    75                 new \GeoIp2\Record\Subdivision($sub, $locales)
    76             );
    77         }
    78     }
     65    private function createSubdivisions( $raw, $locales ) {
     66        if ( ! isset( $raw['subdivisions'] ) ) {
     67            return;
     68        }
    7969
    80     /**
    81      * @ignore
    82      *
    83      * @param mixed $attr
    84      */
    85     public function __get($attr)
    86     {
    87         if ($attr === 'mostSpecificSubdivision') {
    88             return $this->$attr();
    89         }
     70        foreach ( $raw['subdivisions'] as $sub ) {
     71            array_push(
     72                $this->subdivisions,
     73                new \GeoIp2\Record\Subdivision( $sub, $locales )
     74            );
     75        }
     76    }
    9077
    91         return parent::__get($attr);
    92     }
     78    /**
     79     * @ignore
     80     *
     81     * @param mixed $attr
     82     */
     83    public function __get( $attr ) {
     84        if ( $attr === 'mostSpecificSubdivision' ) {
     85            return $this->$attr();
     86        }
    9387
    94     /**
    95      * @ignore
    96      *
    97      * @param mixed $attr
    98      */
    99     public function __isset($attr)
    100     {
    101         if ($attr === 'mostSpecificSubdivision') {
    102             // We always return a mostSpecificSubdivision, even if it is the
    103             // empty subdivision
    104             return true;
    105         }
     88        return parent::__get( $attr );
     89    }
    10690
    107         return parent::__isset($attr);
    108     }
     91    /**
     92     * @ignore
     93     *
     94     * @param mixed $attr
     95     */
     96    public function __isset( $attr ) {
     97        if ( $attr === 'mostSpecificSubdivision' ) {
     98            // We always return a mostSpecificSubdivision, even if it is the
     99            // empty subdivision
     100            return true;
     101        }
    109102
    110     private function mostSpecificSubdivision()
    111     {
    112         return empty($this->subdivisions) ?
    113             new \GeoIp2\Record\Subdivision([], $this->locales) :
    114             end($this->subdivisions);
    115     }
     103        return parent::__isset( $attr );
     104    }
     105
     106    private function mostSpecificSubdivision() {
     107        return empty( $this->subdivisions ) ?
     108            new \GeoIp2\Record\Subdivision( array(), $this->locales ) :
     109            end( $this->subdivisions );
     110    }
    116111}
  • termageddon-usercentrics/trunk/vendor/geoip2/geoip2/src/Model/ConnectionType.php

    r2976730 r3160131  
    1717 *      fields besides $ipAddress have the same value.
    1818 */
    19 class ConnectionType extends AbstractModel
    20 {
    21     protected $connectionType;
    22     protected $ipAddress;
    23     protected $network;
     19class ConnectionType extends AbstractModel {
    2420
    25     /**
    26      * @ignore
    27      *
    28      * @param mixed $raw
    29      */
    30     public function __construct($raw)
    31     {
    32         parent::__construct($raw);
     21    protected $connectionType;
     22    protected $ipAddress;
     23    protected $network;
    3324
    34         $this->connectionType = $this->get('connection_type');
    35         $ipAddress = $this->get('ip_address');
    36         $this->ipAddress = $ipAddress;
    37         $this->network = Util::cidr($ipAddress, $this->get('prefix_len'));
    38     }
     25    /**
     26     * @ignore
     27     *
     28     * @param mixed $raw
     29     */
     30    public function __construct( $raw ) {
     31        parent::__construct( $raw );
     32
     33        $this->connectionType = $this->get( 'connection_type' );
     34        $ipAddress            = $this->get( 'ip_address' );
     35        $this->ipAddress      = $ipAddress;
     36        $this->network        = Util::cidr( $ipAddress, $this->get( 'prefix_len' ) );
     37    }
    3938}
  • termageddon-usercentrics/trunk/vendor/geoip2/geoip2/src/Model/Country.php

    r2976730 r3160131  
    2828 * requested IP address.
    2929 */
    30 class Country extends AbstractModel
    31 {
    32     protected $continent;
    33     protected $country;
    34     protected $locales;
    35     protected $maxmind;
    36     protected $registeredCountry;
    37     protected $representedCountry;
    38     protected $traits;
     30class Country extends AbstractModel {
    3931
    40     /**
    41      * @ignore
    42      *
    43      * @param mixed $raw
    44      * @param mixed $locales
    45      */
    46     public function __construct($raw, $locales = ['en'])
    47     {
    48         parent::__construct($raw);
     32    protected $continent;
     33    protected $country;
     34    protected $locales;
     35    protected $maxmind;
     36    protected $registeredCountry;
     37    protected $representedCountry;
     38    protected $traits;
    4939
    50         $this->continent = new \GeoIp2\Record\Continent(
    51             $this->get('continent'),
    52             $locales
    53         );
    54         $this->country = new \GeoIp2\Record\Country(
    55             $this->get('country'),
    56             $locales
    57         );
    58         $this->maxmind = new \GeoIp2\Record\MaxMind($this->get('maxmind'));
    59         $this->registeredCountry = new \GeoIp2\Record\Country(
    60             $this->get('registered_country'),
    61             $locales
    62         );
    63         $this->representedCountry = new \GeoIp2\Record\RepresentedCountry(
    64             $this->get('represented_country'),
    65             $locales
    66         );
    67         $this->traits = new \GeoIp2\Record\Traits($this->get('traits'));
     40    /**
     41     * @ignore
     42     *
     43     * @param mixed $raw
     44     * @param mixed $locales
     45     */
     46    public function __construct( $raw, $locales = array( 'en' ) ) {
     47        parent::__construct( $raw );
    6848
    69         $this->locales = $locales;
    70     }
     49        $this->continent          = new \GeoIp2\Record\Continent(
     50            $this->get( 'continent' ),
     51            $locales
     52        );
     53        $this->country            = new \GeoIp2\Record\Country(
     54            $this->get( 'country' ),
     55            $locales
     56        );
     57        $this->maxmind            = new \GeoIp2\Record\MaxMind( $this->get( 'maxmind' ) );
     58        $this->registeredCountry  = new \GeoIp2\Record\Country(
     59            $this->get( 'registered_country' ),
     60            $locales
     61        );
     62        $this->representedCountry = new \GeoIp2\Record\RepresentedCountry(
     63            $this->get( 'represented_country' ),
     64            $locales
     65        );
     66        $this->traits             = new \GeoIp2\Record\Traits( $this->get( 'traits' ) );
     67
     68        $this->locales = $locales;
     69    }
    7170}
  • termageddon-usercentrics/trunk/vendor/geoip2/geoip2/src/Model/Domain.php

    r2976730 r3160131  
    1717 *      fields besides $ipAddress have the same value.
    1818 */
    19 class Domain extends AbstractModel
    20 {
    21     protected $domain;
    22     protected $ipAddress;
    23     protected $network;
     19class Domain extends AbstractModel {
    2420
    25     /**
    26      * @ignore
    27      *
    28      * @param mixed $raw
    29      */
    30     public function __construct($raw)
    31     {
    32         parent::__construct($raw);
     21    protected $domain;
     22    protected $ipAddress;
     23    protected $network;
    3324
    34         $this->domain = $this->get('domain');
    35         $ipAddress = $this->get('ip_address');
    36         $this->ipAddress = $ipAddress;
    37         $this->network = Util::cidr($ipAddress, $this->get('prefix_len'));
    38     }
     25    /**
     26     * @ignore
     27     *
     28     * @param mixed $raw
     29     */
     30    public function __construct( $raw ) {
     31        parent::__construct( $raw );
     32
     33        $this->domain    = $this->get( 'domain' );
     34        $ipAddress       = $this->get( 'ip_address' );
     35        $this->ipAddress = $ipAddress;
     36        $this->network   = Util::cidr( $ipAddress, $this->get( 'prefix_len' ) );
     37    }
    3938}
  • termageddon-usercentrics/trunk/vendor/geoip2/geoip2/src/Model/Enterprise.php

    r2976730 r3160131  
    1010 * https://dev.maxmind.com/geoip/geoip2/web-services for more details.
    1111 */
    12 class Enterprise extends City
    13 {
     12class Enterprise extends City {
     13
    1414}
  • termageddon-usercentrics/trunk/vendor/geoip2/geoip2/src/Model/Insights.php

    r2976730 r3160131  
    1010 * https://dev.maxmind.com/geoip/geoip2/web-services for more details.
    1111 */
    12 class Insights extends City
    13 {
     12class Insights extends City {
     13
    1414}
  • termageddon-usercentrics/trunk/vendor/geoip2/geoip2/src/Model/Isp.php

    r2976730 r3160131  
    2323 *      fields besides $ipAddress have the same value.
    2424 */
    25 class Isp extends AbstractModel
    26 {
    27     protected $autonomousSystemNumber;
    28     protected $autonomousSystemOrganization;
    29     protected $isp;
    30     protected $organization;
    31     protected $ipAddress;
    32     protected $network;
     25class Isp extends AbstractModel {
    3326
    34     /**
    35      * @ignore
    36      *
    37      * @param mixed $raw
    38      */
    39     public function __construct($raw)
    40     {
    41         parent::__construct($raw);
    42         $this->autonomousSystemNumber = $this->get('autonomous_system_number');
    43         $this->autonomousSystemOrganization =
    44             $this->get('autonomous_system_organization');
    45         $this->isp = $this->get('isp');
    46         $this->organization = $this->get('organization');
     27    protected $autonomousSystemNumber;
     28    protected $autonomousSystemOrganization;
     29    protected $isp;
     30    protected $organization;
     31    protected $ipAddress;
     32    protected $network;
    4733
    48         $ipAddress = $this->get('ip_address');
    49         $this->ipAddress = $ipAddress;
    50         $this->network = Util::cidr($ipAddress, $this->get('prefix_len'));
    51     }
     34    /**
     35     * @ignore
     36     *
     37     * @param mixed $raw
     38     */
     39    public function __construct( $raw ) {
     40        parent::__construct( $raw );
     41        $this->autonomousSystemNumber       = $this->get( 'autonomous_system_number' );
     42        $this->autonomousSystemOrganization =
     43            $this->get( 'autonomous_system_organization' );
     44        $this->isp                          = $this->get( 'isp' );
     45        $this->organization                 = $this->get( 'organization' );
     46
     47        $ipAddress       = $this->get( 'ip_address' );
     48        $this->ipAddress = $ipAddress;
     49        $this->network   = Util::cidr( $ipAddress, $this->get( 'prefix_len' ) );
     50    }
    5251}
  • termageddon-usercentrics/trunk/vendor/geoip2/geoip2/src/ProviderInterface.php

    r2976730 r3160131  
    33namespace GeoIp2;
    44
    5 interface ProviderInterface
    6 {
    7     /**
    8      * @param string $ipAddress an IPv4 or IPv6 address to lookup
    9      *
    10      * @return \GeoIp2\Model\Country a Country model for the requested IP address
    11      */
    12     public function country($ipAddress);
     5interface ProviderInterface {
    136
    14     /**
    15      * @param string $ipAddress an IPv4 or IPv6 address to lookup
    16      *
    17      * @return \GeoIp2\Model\City a City model for the requested IP address
    18      */
    19     public function city($ipAddress);
     7    /**
     8     * @param string $ipAddress an IPv4 or IPv6 address to lookup
     9     *
     10     * @return \GeoIp2\Model\Country a Country model for the requested IP address
     11     */
     12    public function country( $ipAddress);
     13
     14    /**
     15     * @param string $ipAddress an IPv4 or IPv6 address to lookup
     16     *
     17     * @return \GeoIp2\Model\City a City model for the requested IP address
     18     */
     19    public function city( $ipAddress);
    2020}
  • termageddon-usercentrics/trunk/vendor/geoip2/geoip2/src/Record/AbstractPlaceRecord.php

    r2976730 r3160131  
    33namespace GeoIp2\Record;
    44
    5 abstract class AbstractPlaceRecord extends AbstractRecord
    6 {
    7     private $locales;
     5abstract class AbstractPlaceRecord extends AbstractRecord {
    86
    9     /**
    10      * @ignore
    11      *
    12      * @param mixed $record
    13      * @param mixed $locales
    14      */
    15     public function __construct($record, $locales = ['en'])
    16     {
    17         $this->locales = $locales;
    18         parent::__construct($record);
    19     }
     7    private $locales;
    208
    21     /**
    22     * @ignore
    23     *
    24      * @param mixed $attr
    25      */
    26     public function __get($attr)
    27     {
    28         if ($attr === 'name') {
    29             return $this->name();
    30         }
     9    /**
     10    * @ignore
     11    *
     12     * @param mixed $record
     13     * @param mixed $locales
     14     */
     15    public function __construct( $record, $locales = array( 'en' ) ) {
     16        $this->locales = $locales;
     17        parent::__construct( $record );
     18    }
    3119
    32         return parent::__get($attr);
    33     }
     20    /**
     21     * @ignore
     22     *
     23     * @param mixed $attr
     24     */
     25    public function __get( $attr ) {
     26        if ( $attr === 'name' ) {
     27            return $this->name();
     28        }
    3429
    35     /**
    36      * @ignore
    37      *
    38      * @param mixed $attr
    39      */
    40     public function __isset($attr)
    41     {
    42         if ($attr === 'name') {
    43             return $this->firstSetNameLocale() === null ? false : true;
    44         }
     30        return parent::__get( $attr );
     31    }
    4532
    46         return parent::__isset($attr);
    47     }
     33    /**
     34     * @ignore
     35     *
     36     * @param mixed $attr
     37     */
     38    public function __isset( $attr ) {
     39        if ( $attr === 'name' ) {
     40            return $this->firstSetNameLocale() === null ? false : true;
     41        }
    4842
    49     private function name()
    50     {
    51         $locale = $this->firstSetNameLocale();
     43        return parent::__isset( $attr );
     44    }
    5245
    53         return $locale === null ? null : $this->names[$locale];
    54     }
     46    private function name() {
     47        $locale = $this->firstSetNameLocale();
    5548
    56     private function firstSetNameLocale()
    57     {
    58         foreach ($this->locales as $locale) {
    59             if (isset($this->names[$locale])) {
    60                 return $locale;
    61             }
    62         }
     49        return $locale === null ? null : $this->names[ $locale ];
     50    }
    6351
    64         return null;
    65     }
     52    private function firstSetNameLocale() {
     53        foreach ( $this->locales as $locale ) {
     54            if ( isset( $this->names[ $locale ] ) ) {
     55                return $locale;
     56            }
     57        }
     58
     59        return null;
     60    }
    6661}
  • termageddon-usercentrics/trunk/vendor/geoip2/geoip2/src/Record/AbstractRecord.php

    r2976730 r3160131  
    33namespace GeoIp2\Record;
    44
    5 abstract class AbstractRecord implements \JsonSerializable
    6 {
    7     private $record;
     5abstract class AbstractRecord implements \JsonSerializable {
    86
    9     /**
    10      * @ignore
    11      *
    12      * @param mixed $record
    13      */
    14     public function __construct($record)
    15     {
    16         $this->record = isset($record) ? $record : [];
    17     }
     7    private $record;
    188
    19     /**
    20      * @ignore
    21      *
    22      * @param mixed $attr
    23      */
    24     public function __get($attr)
    25     {
    26         // XXX - kind of ugly but greatly reduces boilerplate code
    27         $key = $this->attributeToKey($attr);
     9    /**
     10     * @ignore
     11     *
     12     * @param mixed $record
     13     */
     14    public function __construct( $record ) {
     15        $this->record = isset( $record ) ? $record : array();
     16    }
    2817
    29         if ($this->__isset($attr)) {
    30             return $this->record[$key];
    31         } elseif ($this->validAttribute($attr)) {
    32             if (preg_match('/^is_/', $key)) {
    33                 return false;
    34             }
     18    /**
     19     * @ignore
     20     *
     21     * @param mixed $attr
     22     */
     23    public function __get( $attr ) {
     24        // XXX - kind of ugly but greatly reduces boilerplate code
     25        $key = $this->attributeToKey( $attr );
    3526
    36             return null;
    37         }
    38         throw new \RuntimeException("Unknown attribute: $attr");
    39     }
     27        if ( $this->__isset( $attr ) ) {
     28            return $this->record[ $key ];
     29        } elseif ( $this->validAttribute( $attr ) ) {
     30            if ( preg_match( '/^is_/', $key ) ) {
     31                return false;
     32            }
    4033
    41     public function __isset($attr)
    42     {
    43         return $this->validAttribute($attr) &&
    44              isset($this->record[$this->attributeToKey($attr)]);
    45     }
     34            return null;
     35        }
     36        throw new \RuntimeException( "Unknown attribute: $attr" );
     37    }
    4638
    47     private function attributeToKey($attr)
    48     {
    49         return strtolower(preg_replace('/([A-Z])/', '_\1', $attr));
    50     }
     39    public function __isset( $attr ) {
     40        return $this->validAttribute( $attr ) &&
     41             isset( $this->record[ $this->attributeToKey( $attr ) ] );
     42    }
    5143
    52     private function validAttribute($attr)
    53     {
    54         return \in_array($attr, $this->validAttributes, true);
    55     }
     44    private function attributeToKey( $attr ) {
     45        return strtolower( preg_replace( '/([A-Z])/', '_\1', $attr ) );
     46    }
    5647
    57     public function jsonSerialize()
    58     {
    59         return $this->record;
    60     }
     48    private function validAttribute( $attr ) {
     49        return \in_array( $attr, $this->validAttributes, true );
     50    }
     51
     52    public function jsonSerialize() {
     53        return $this->record;
     54    }
    6155}
  • termageddon-usercentrics/trunk/vendor/geoip2/geoip2/src/Record/City.php

    r2976730 r3160131  
    2121 * services and databases.
    2222 */
    23 class City extends AbstractPlaceRecord
    24 {
    25     /**
    26     * @ignore
    27     */
    28     protected $validAttributes = ['confidence', 'geonameId', 'names'];
     23class City extends AbstractPlaceRecord {
     24
     25    /**
     26    * @ignore
     27    */
     28    protected $validAttributes = array( 'confidence', 'geonameId', 'names' );
    2929}
  • termageddon-usercentrics/trunk/vendor/geoip2/geoip2/src/Record/Continent.php

    r2976730 r3160131  
    2020 * services and databases.
    2121 */
    22 class Continent extends AbstractPlaceRecord
    23 {
    24     /**
    25     * @ignore
    26     */
    27     protected $validAttributes = [
    28         'code',
    29         'geonameId',
    30         'names',
    31     ];
     22class Continent extends AbstractPlaceRecord {
     23
     24    /**
     25    * @ignore
     26    */
     27    protected $validAttributes = array(
     28        'code',
     29        'geonameId',
     30        'names',
     31    );
    3232}
  • termageddon-usercentrics/trunk/vendor/geoip2/geoip2/src/Record/Country.php

    r2976730 r3160131  
    2626 * services and databases.
    2727 */
    28 class Country extends AbstractPlaceRecord
    29 {
    30     /**
    31     * @ignore
    32     */
    33     protected $validAttributes = [
    34         'confidence',
    35         'geonameId',
    36         'isInEuropeanUnion',
    37         'isoCode',
    38         'names',
    39     ];
     28class Country extends AbstractPlaceRecord {
     29
     30    /**
     31    * @ignore
     32    */
     33    protected $validAttributes = array(
     34        'confidence',
     35        'geonameId',
     36        'isInEuropeanUnion',
     37        'isoCode',
     38        'names',
     39    );
    4040}
  • termageddon-usercentrics/trunk/vendor/geoip2/geoip2/src/Record/Location.php

    r2976730 r3160131  
    3434 * https://www.iana.org/time-zones.
    3535 */
    36 class Location extends AbstractRecord
    37 {
    38     /**
    39     * @ignore
    40     */
    41     protected $validAttributes = [
    42         'averageIncome',
    43         'accuracyRadius',
    44         'latitude',
    45         'longitude',
    46         'metroCode',
    47         'populationDensity',
    48         'postalCode',
    49         'postalConfidence',
    50         'timeZone',
    51     ];
     36class Location extends AbstractRecord {
     37
     38    /**
     39    * @ignore
     40    */
     41    protected $validAttributes = array(
     42        'averageIncome',
     43        'accuracyRadius',
     44        'latitude',
     45        'longitude',
     46        'metroCode',
     47        'populationDensity',
     48        'postalCode',
     49        'postalConfidence',
     50        'timeZone',
     51    );
    5252}
  • termageddon-usercentrics/trunk/vendor/geoip2/geoip2/src/Record/MaxMind.php

    r2976730 r3160131  
    1111 * have for the service you are calling.
    1212 */
    13 class MaxMind extends AbstractRecord
    14 {
    15     /**
    16     * @ignore
    17     */
    18     protected $validAttributes = ['queriesRemaining'];
     13class MaxMind extends AbstractRecord {
     14
     15    /**
     16    * @ignore
     17    */
     18    protected $validAttributes = array( 'queriesRemaining' );
    1919}
  • termageddon-usercentrics/trunk/vendor/geoip2/geoip2/src/Record/Postal.php

    r2976730 r3160131  
    1818 * database.
    1919 */
    20 class Postal extends AbstractRecord
    21 {
    22     /**
    23     * @ignore
    24     */
    25     protected $validAttributes = ['code', 'confidence'];
     20class Postal extends AbstractRecord {
     21
     22    /**
     23    * @ignore
     24    */
     25    protected $validAttributes = array( 'code', 'confidence' );
    2626}
  • termageddon-usercentrics/trunk/vendor/geoip2/geoip2/src/Record/RepresentedCountry.php

    r2976730 r3160131  
    1414 * but this could expand to include other types in the future.
    1515 */
    16 class RepresentedCountry extends Country
    17 {
    18     protected $validAttributes = [
    19         'confidence',
    20         'geonameId',
    21         'isInEuropeanUnion',
    22         'isoCode',
    23         'names',
    24         'type',
    25     ];
     16class RepresentedCountry extends Country {
     17
     18    protected $validAttributes = array(
     19        'confidence',
     20        'geonameId',
     21        'isInEuropeanUnion',
     22        'isoCode',
     23        'names',
     24        'type',
     25    );
    2626}
  • termageddon-usercentrics/trunk/vendor/geoip2/geoip2/src/Record/Subdivision.php

    r2976730 r3160131  
    2727 * databases and services besides Country.
    2828 */
    29 class Subdivision extends AbstractPlaceRecord
    30 {
    31     /**
    32     * @ignore
    33     */
    34     protected $validAttributes = [
    35         'confidence',
    36         'geonameId',
    37         'isoCode',
    38         'names',
    39     ];
     29class Subdivision extends AbstractPlaceRecord {
     30
     31    /**
     32    * @ignore
     33    */
     34    protected $validAttributes = array(
     35        'confidence',
     36        'geonameId',
     37        'isoCode',
     38        'names',
     39    );
    4040}
  • termageddon-usercentrics/trunk/vendor/geoip2/geoip2/src/Record/Traits.php

    r2976730 r3160131  
    103103 * </p>
    104104 */
    105 class Traits extends AbstractRecord
    106 {
    107     /**
    108      * @ignore
    109      */
    110     protected $validAttributes = [
    111         'autonomousSystemNumber',
    112         'autonomousSystemOrganization',
    113         'connectionType',
    114         'domain',
    115         'ipAddress',
    116         'isAnonymous',
    117         'isAnonymousProxy',
    118         'isAnonymousVpn',
    119         'isHostingProvider',
    120         'isLegitimateProxy',
    121         'isp',
    122         'isPublicProxy',
    123         'isSatelliteProvider',
    124         'isTorExitNode',
    125         'network',
    126         'organization',
    127         'staticIpScore',
    128         'userCount',
    129         'userType',
    130     ];
     105class Traits extends AbstractRecord {
    131106
    132     public function __construct($record)
    133     {
    134         if (!isset($record['network']) && isset($record['ip_address']) && isset($record['prefix_len'])) {
    135             $record['network'] = Util::cidr($record['ip_address'], $record['prefix_len']);
    136         }
     107    /**
     108     * @ignore
     109     */
     110    protected $validAttributes = array(
     111        'autonomousSystemNumber',
     112        'autonomousSystemOrganization',
     113        'connectionType',
     114        'domain',
     115        'ipAddress',
     116        'isAnonymous',
     117        'isAnonymousProxy',
     118        'isAnonymousVpn',
     119        'isHostingProvider',
     120        'isLegitimateProxy',
     121        'isp',
     122        'isPublicProxy',
     123        'isSatelliteProvider',
     124        'isTorExitNode',
     125        'network',
     126        'organization',
     127        'staticIpScore',
     128        'userCount',
     129        'userType',
     130    );
    137131
    138         parent::__construct($record);
    139     }
     132    public function __construct( $record ) {
     133        if ( ! isset( $record['network'] ) && isset( $record['ip_address'] ) && isset( $record['prefix_len'] ) ) {
     134            $record['network'] = Util::cidr( $record['ip_address'], $record['prefix_len'] );
     135        }
     136
     137        parent::__construct( $record );
     138    }
    140139}
  • termageddon-usercentrics/trunk/vendor/geoip2/geoip2/src/Util.php

    r2976730 r3160131  
    33namespace GeoIp2;
    44
    5 class Util
    6 {
    7     /**
    8      * This returns the network in CIDR notation for the given IP and prefix
    9      * length. This is for internal use only.
    10      *
    11      * @internal
    12      * @ignore
    13      *
    14      * @param mixed $ipAddress
    15      * @param mixed $prefixLen
    16      */
    17     public static function cidr($ipAddress, $prefixLen)
    18     {
    19         $ipBytes = inet_pton($ipAddress);
    20         $networkBytes = str_repeat("\0", \strlen($ipBytes));
     5class Util {
    216
    22         $curPrefix = $prefixLen;
    23         for ($i = 0; $i < \strlen($ipBytes) && $curPrefix > 0; $i++) {
    24             $b = $ipBytes[$i];
    25             if ($curPrefix < 8) {
    26                 $shiftN = 8 - $curPrefix;
    27                 $b = \chr(0xFF & (\ord($b) >> $shiftN) << $shiftN);
    28             }
    29             $networkBytes[$i] = $b;
    30             $curPrefix -= 8;
    31         }
     7    /**
     8     * This returns the network in CIDR notation for the given IP and prefix
     9     * length. This is for internal use only.
     10     *
     11     * @internal
     12     * @ignore
     13     *
     14     * @param mixed $ipAddress
     15     * @param mixed $prefixLen
     16     */
     17    public static function cidr( $ipAddress, $prefixLen ) {
     18        $ipBytes      = inet_pton( $ipAddress );
     19        $networkBytes = str_repeat( "\0", \strlen( $ipBytes ) );
    3220
    33         $network = inet_ntop($networkBytes);
     21        $curPrefix = $prefixLen;
     22        for ( $i = 0; $i < \strlen( $ipBytes ) && $curPrefix > 0; $i++ ) {
     23            $b = $ipBytes[ $i ];
     24            if ( $curPrefix < 8 ) {
     25                $shiftN = 8 - $curPrefix;
     26                $b      = \chr( 0xFF & ( \ord( $b ) >> $shiftN ) << $shiftN );
     27            }
     28            $networkBytes[ $i ] = $b;
     29            $curPrefix         -= 8;
     30        }
    3431
    35         return "$network/$prefixLen";
    36     }
     32        $network = inet_ntop( $networkBytes );
     33
     34        return "$network/$prefixLen";
     35    }
    3736}
  • termageddon-usercentrics/trunk/vendor/geoip2/geoip2/src/WebService/Client.php

    r2976730 r3160131  
    4242 * If the request fails, the client class throws an exception.
    4343 */
    44 class Client implements ProviderInterface
    45 {
    46     private $locales;
    47     private $client;
    48     private static $basePath = '/geoip/v2.1';
    49 
    50     const VERSION = 'v2.10.0';
    51 
    52     /**
    53      * Constructor.
    54      *
    55      * @param int    $accountId  your MaxMind account ID
    56      * @param string $licenseKey your MaxMind license key
    57      * @param array  $locales    list of locale codes to use in name property
    58      *                           from most preferred to least preferred
    59      * @param array  $options    array of options. Valid options include:
    60      *                           * `host` - The host to use when querying the web service.
    61      *                           * `timeout` - Timeout in seconds.
    62      *                           * `connectTimeout` - Initial connection timeout in seconds.
    63      *                           * `proxy` - The HTTP proxy to use. May include a schema, port,
    64      *                           username, and password, e.g.,
    65      *                           `http://username:password@127.0.0.1:10`.
    66      */
    67     public function __construct(
    68         $accountId,
    69         $licenseKey,
    70         $locales = ['en'],
    71         $options = []
    72     ) {
    73         $this->locales = $locales;
    74 
    75         // This is for backwards compatibility. Do not remove except for a
    76         // major version bump.
    77         if (\is_string($options)) {
    78             $options = ['host' => $options];
    79         }
    80 
    81         if (!isset($options['host'])) {
    82             $options['host'] = 'geoip.maxmind.com';
    83         }
    84 
    85         $options['userAgent'] = $this->userAgent();
    86 
    87         $this->client = new WsClient($accountId, $licenseKey, $options);
    88     }
    89 
    90     private function userAgent()
    91     {
    92         return 'GeoIP2-API/' . self::VERSION;
    93     }
    94 
    95     /**
    96      * This method calls the GeoIP2 Precision: City service.
    97      *
    98      * @param string $ipAddress IPv4 or IPv6 address as a string. If no
    99      *                          address is provided, the address that the web service is called
    100      *                          from will be used.
    101      *
    102      * @throws \GeoIp2\Exception\AddressNotFoundException if the address you
    103      *                                                    provided is not in our database (e.g., a private address).
    104      * @throws \GeoIp2\Exception\AuthenticationException  if there is a problem
    105      *                                                    with the account ID or license key that you provided
    106      * @throws \GeoIp2\Exception\OutOfQueriesException    if your account is out
    107      *                                                    of queries
    108      * @throws \GeoIp2\Exception\InvalidRequestException} if your request was received by the web service but is
    109      *                                                    invalid for some other reason.  This may indicate an issue
    110      *                                                    with this API. Please report the error to MaxMind.
    111      * @throws \GeoIp2\Exception\HttpException            if an unexpected HTTP error code or message was returned.
    112      *                                                    This could indicate a problem with the connection between
    113      *                                                    your server and the web service or that the web service
    114      *                                                    returned an invalid document or 500 error code
    115      * @throws \GeoIp2\Exception\GeoIp2Exception          This serves as the parent
    116      *                                                    class to the above exceptions. It will be thrown directly
    117      *                                                    if a 200 status code is returned but the body is invalid.
    118      *
    119      * @return \GeoIp2\Model\City
    120      */
    121     public function city($ipAddress = 'me')
    122     {
    123         return $this->responseFor('city', 'City', $ipAddress);
    124     }
    125 
    126     /**
    127      * This method calls the GeoIP2 Precision: Country service.
    128      *
    129      * @param string $ipAddress IPv4 or IPv6 address as a string. If no
    130      *                          address is provided, the address that the web service is called
    131      *                          from will be used.
    132      *
    133      * @throws \GeoIp2\Exception\AddressNotFoundException if the address you provided is not in our database (e.g.,
    134      *                                                    a private address).
    135      * @throws \GeoIp2\Exception\AuthenticationException  if there is a problem
    136      *                                                    with the account ID or license key that you provided
    137      * @throws \GeoIp2\Exception\OutOfQueriesException    if your account is out of queries
    138      * @throws \GeoIp2\Exception\InvalidRequestException} if your request was received by the web service but is
    139      *                                                    invalid for some other reason.  This may indicate an
    140      *                                                    issue with this API. Please report the error to MaxMind.
    141      * @throws \GeoIp2\Exception\HttpException            if an unexpected HTTP error
    142      *                                                    code or message was returned. This could indicate a problem
    143      *                                                    with the connection between your server and the web service
    144      *                                                    or that the web service returned an invalid document or 500
    145      *                                                    error code.
    146      * @throws \GeoIp2\Exception\GeoIp2Exception          This serves as the parent class to the above exceptions. It
    147      *                                                    will be thrown directly if a 200 status code is returned but
    148      *                                                    the body is invalid.
    149      *
    150      * @return \GeoIp2\Model\Country
    151      */
    152     public function country($ipAddress = 'me')
    153     {
    154         return $this->responseFor('country', 'Country', $ipAddress);
    155     }
    156 
    157     /**
    158      * This method calls the GeoIP2 Precision: Insights service.
    159      *
    160      * @param string $ipAddress IPv4 or IPv6 address as a string. If no
    161      *                          address is provided, the address that the web service is called
    162      *                          from will be used.
    163      *
    164      * @throws \GeoIp2\Exception\AddressNotFoundException if the address you
    165      *                                                    provided is not in our database (e.g., a private address).
    166      * @throws \GeoIp2\Exception\AuthenticationException  if there is a problem
    167      *                                                    with the account ID or license key that you provided
    168      * @throws \GeoIp2\Exception\OutOfQueriesException    if your account is out
    169      *                                                    of queries
    170      * @throws \GeoIp2\Exception\InvalidRequestException} if your request was received by the web service but is
    171      *                                                    invalid for some other reason.  This may indicate an
    172      *                                                    issue with this API. Please report the error to MaxMind.
    173      * @throws \GeoIp2\Exception\HttpException            if an unexpected HTTP error code or message was returned.
    174      *                                                    This could indicate a problem with the connection between
    175      *                                                    your server and the web service or that the web service
    176      *                                                    returned an invalid document or 500 error code
    177      * @throws \GeoIp2\Exception\GeoIp2Exception          This serves as the parent
    178      *                                                    class to the above exceptions. It will be thrown directly
    179      *                                                    if a 200 status code is returned but the body is invalid.
    180      *
    181      * @return \GeoIp2\Model\Insights
    182      */
    183     public function insights($ipAddress = 'me')
    184     {
    185         return $this->responseFor('insights', 'Insights', $ipAddress);
    186     }
    187 
    188     private function responseFor($endpoint, $class, $ipAddress)
    189     {
    190         $path = implode('/', [self::$basePath, $endpoint, $ipAddress]);
    191 
    192         try {
    193             $body = $this->client->get('GeoIP2 ' . $class, $path);
    194         } catch (\MaxMind\Exception\IpAddressNotFoundException $ex) {
    195             throw new AddressNotFoundException(
    196                 $ex->getMessage(),
    197                 $ex->getStatusCode(),
    198                 $ex
    199             );
    200         } catch (\MaxMind\Exception\AuthenticationException $ex) {
    201             throw new AuthenticationException(
    202                 $ex->getMessage(),
    203                 $ex->getStatusCode(),
    204                 $ex
    205             );
    206         } catch (\MaxMind\Exception\InsufficientFundsException $ex) {
    207             throw new OutOfQueriesException(
    208                 $ex->getMessage(),
    209                 $ex->getStatusCode(),
    210                 $ex
    211             );
    212         } catch (\MaxMind\Exception\InvalidRequestException $ex) {
    213             throw new InvalidRequestException(
    214                 $ex->getMessage(),
    215                 $ex->getErrorCode(),
    216                 $ex->getStatusCode(),
    217                 $ex->getUri(),
    218                 $ex
    219             );
    220         } catch (\MaxMind\Exception\HttpException $ex) {
    221             throw new HttpException(
    222                 $ex->getMessage(),
    223                 $ex->getStatusCode(),
    224                 $ex->getUri(),
    225                 $ex
    226             );
    227         } catch (\MaxMind\Exception\WebServiceException $ex) {
    228             throw new GeoIp2Exception(
    229                 $ex->getMessage(),
    230                 $ex->getCode(),
    231                 $ex
    232             );
    233         }
    234 
    235         $class = 'GeoIp2\\Model\\' . $class;
    236 
    237         return new $class($body, $this->locales);
    238     }
     44class Client implements ProviderInterface {
     45
     46    private $locales;
     47    private $client;
     48    private static $basePath = '/geoip/v2.1';
     49
     50    const VERSION = 'v2.10.0';
     51
     52    /**
     53     * Constructor.
     54     *
     55     * @param int    $accountId  your MaxMind account ID
     56     * @param string $licenseKey your MaxMind license key
     57     * @param array  $locales    list of locale codes to use in name property
     58     *                           from most preferred to least preferred
     59     * @param array  $options    array of options. Valid options include:
     60     *                           * `host` - The host to use when querying the web service.
     61     *                           * `timeout` - Timeout in seconds.
     62     *                           * `connectTimeout` - Initial connection timeout in seconds.
     63     *                           * `proxy` - The HTTP proxy to use. May include a schema, port,
     64     *                           username, and password, e.g.,
     65     *                           `http://username:password@127.0.0.1:10`.
     66     */
     67    public function __construct(
     68        $accountId,
     69        $licenseKey,
     70        $locales = array( 'en' ),
     71        $options = array()
     72    ) {
     73        $this->locales = $locales;
     74
     75        // This is for backwards compatibility. Do not remove except for a
     76        // major version bump.
     77        if ( \is_string( $options ) ) {
     78            $options = array( 'host' => $options );
     79        }
     80
     81        if ( ! isset( $options['host'] ) ) {
     82            $options['host'] = 'geoip.maxmind.com';
     83        }
     84
     85        $options['userAgent'] = $this->userAgent();
     86
     87        $this->client = new WsClient( $accountId, $licenseKey, $options );
     88    }
     89
     90    private function userAgent() {
     91        return 'GeoIP2-API/' . self::VERSION;
     92    }
     93
     94    /**
     95     * This method calls the GeoIP2 Precision: City service.
     96     *
     97     * @param string $ipAddress IPv4 or IPv6 address as a string. If no
     98     *                          address is provided, the address that the web service is called
     99     *                          from will be used.
     100     *
     101     * @throws \GeoIp2\Exception\AddressNotFoundException if the address you
     102     *                                                    provided is not in our database (e.g., a private address).
     103     * @throws \GeoIp2\Exception\AuthenticationException  if there is a problem
     104     *                                                    with the account ID or license key that you provided
     105     * @throws \GeoIp2\Exception\OutOfQueriesException    if your account is out
     106     *                                                    of queries
     107     * @throws \GeoIp2\Exception\InvalidRequestException} if your request was received by the web service but is
     108     *                                                    invalid for some other reason.  This may indicate an issue
     109     *                                                    with this API. Please report the error to MaxMind.
     110     * @throws \GeoIp2\Exception\HttpException            if an unexpected HTTP error code or message was returned.
     111     *                                                    This could indicate a problem with the connection between
     112     *                                                    your server and the web service or that the web service
     113     *                                                    returned an invalid document or 500 error code
     114     * @throws \GeoIp2\Exception\GeoIp2Exception          This serves as the parent
     115     *                                                    class to the above exceptions. It will be thrown directly
     116     *                                                    if a 200 status code is returned but the body is invalid.
     117     *
     118     * @return \GeoIp2\Model\City
     119     */
     120    public function city( $ipAddress = 'me' ) {
     121        return $this->responseFor( 'city', 'City', $ipAddress );
     122    }
     123
     124    /**
     125     * This method calls the GeoIP2 Precision: Country service.
     126     *
     127     * @param string $ipAddress IPv4 or IPv6 address as a string. If no
     128     *                          address is provided, the address that the web service is called
     129     *                          from will be used.
     130     *
     131     * @throws \GeoIp2\Exception\AddressNotFoundException if the address you provided is not in our database (e.g.,
     132     *                                                    a private address).
     133     * @throws \GeoIp2\Exception\AuthenticationException  if there is a problem
     134     *                                                    with the account ID or license key that you provided
     135     * @throws \GeoIp2\Exception\OutOfQueriesException    if your account is out of queries
     136     * @throws \GeoIp2\Exception\InvalidRequestException} if your request was received by the web service but is
     137     *                                                    invalid for some other reason.  This may indicate an
     138     *                                                    issue with this API. Please report the error to MaxMind.
     139     * @throws \GeoIp2\Exception\HttpException            if an unexpected HTTP error
     140     *                                                    code or message was returned. This could indicate a problem
     141     *                                                    with the connection between your server and the web service
     142     *                                                    or that the web service returned an invalid document or 500
     143     *                                                    error code.
     144     * @throws \GeoIp2\Exception\GeoIp2Exception          This serves as the parent class to the above exceptions. It
     145     *                                                    will be thrown directly if a 200 status code is returned but
     146     *                                                    the body is invalid.
     147     *
     148     * @return \GeoIp2\Model\Country
     149     */
     150    public function country( $ipAddress = 'me' ) {
     151        return $this->responseFor( 'country', 'Country', $ipAddress );
     152    }
     153
     154    /**
     155     * This method calls the GeoIP2 Precision: Insights service.
     156     *
     157     * @param string $ipAddress IPv4 or IPv6 address as a string. If no
     158     *                          address is provided, the address that the web service is called
     159     *                          from will be used.
     160     *
     161     * @throws \GeoIp2\Exception\AddressNotFoundException if the address you
     162     *                                                    provided is not in our database (e.g., a private address).
     163     * @throws \GeoIp2\Exception\AuthenticationException  if there is a problem
     164     *                                                    with the account ID or license key that you provided
     165     * @throws \GeoIp2\Exception\OutOfQueriesException    if your account is out
     166     *                                                    of queries
     167     * @throws \GeoIp2\Exception\InvalidRequestException} if your request was received by the web service but is
     168     *                                                    invalid for some other reason.  This may indicate an
     169     *                                                    issue with this API. Please report the error to MaxMind.
     170     * @throws \GeoIp2\Exception\HttpException            if an unexpected HTTP error code or message was returned.
     171     *                                                    This could indicate a problem with the connection between
     172     *                                                    your server and the web service or that the web service
     173     *                                                    returned an invalid document or 500 error code
     174     * @throws \GeoIp2\Exception\GeoIp2Exception          This serves as the parent
     175     *                                                    class to the above exceptions. It will be thrown directly
     176     *                                                    if a 200 status code is returned but the body is invalid.
     177     *
     178     * @return \GeoIp2\Model\Insights
     179     */
     180    public function insights( $ipAddress = 'me' ) {
     181        return $this->responseFor( 'insights', 'Insights', $ipAddress );
     182    }
     183
     184    private function responseFor( $endpoint, $class, $ipAddress ) {
     185        $path = implode( '/', array( self::$basePath, $endpoint, $ipAddress ) );
     186
     187        try {
     188            $body = $this->client->get( 'GeoIP2 ' . $class, $path );
     189        } catch ( \MaxMind\Exception\IpAddressNotFoundException $ex ) {
     190            throw new AddressNotFoundException(
     191                $ex->getMessage(),
     192                $ex->getStatusCode(),
     193                $ex
     194            );
     195        } catch ( \MaxMind\Exception\AuthenticationException $ex ) {
     196            throw new AuthenticationException(
     197                $ex->getMessage(),
     198                $ex->getStatusCode(),
     199                $ex
     200            );
     201        } catch ( \MaxMind\Exception\InsufficientFundsException $ex ) {
     202            throw new OutOfQueriesException(
     203                $ex->getMessage(),
     204                $ex->getStatusCode(),
     205                $ex
     206            );
     207        } catch ( \MaxMind\Exception\InvalidRequestException $ex ) {
     208            throw new InvalidRequestException(
     209                $ex->getMessage(),
     210                $ex->getErrorCode(),
     211                $ex->getStatusCode(),
     212                $ex->getUri(),
     213                $ex
     214            );
     215        } catch ( \MaxMind\Exception\HttpException $ex ) {
     216            throw new HttpException(
     217                $ex->getMessage(),
     218                $ex->getStatusCode(),
     219                $ex->getUri(),
     220                $ex
     221            );
     222        } catch ( \MaxMind\Exception\WebServiceException $ex ) {
     223            throw new GeoIp2Exception(
     224                $ex->getMessage(),
     225                $ex->getCode(),
     226                $ex
     227            );
     228        }
     229
     230        $class = 'GeoIp2\\Model\\' . $class;
     231
     232        return new $class( $body, $this->locales );
     233    }
    239234}
  • termageddon-usercentrics/trunk/vendor/maxmind-db/reader/autoload.php

    r2771752 r3160131  
    1717 *                      the name of the class to load
    1818 */
    19 function mmdb_autoload($class): void
    20 {
    21     /*
    22     * A project-specific mapping between the namespaces and where
    23     * they're located. By convention, we include the trailing
    24     * slashes. The one-element array here simply makes things easy
    25     * to extend in the future if (for example) the test classes
    26     * begin to use one another.
    27     */
    28     $namespace_map = ['MaxMind\\Db\\' => __DIR__ . '/src/MaxMind/Db/'];
     19function mmdb_autoload( $class ): void {
     20    /*
     21    * A project-specific mapping between the namespaces and where
     22    * they're located. By convention, we include the trailing
     23    * slashes. The one-element array here simply makes things easy
     24    * to extend in the future if (for example) the test classes
     25    * begin to use one another.
     26    */
     27    $namespace_map = array( 'MaxMind\\Db\\' => __DIR__ . '/src/MaxMind/Db/' );
    2928
    30     foreach ($namespace_map as $prefix => $dir) {
    31         // First swap out the namespace prefix with a directory...
    32         $path = str_replace($prefix, $dir, $class);
     29    foreach ( $namespace_map as $prefix => $dir ) {
     30        // First swap out the namespace prefix with a directory...
     31        $path = str_replace( $prefix, $dir, $class );
    3332
    34         // replace the namespace separator with a directory separator...
    35         $path = str_replace('\\', '/', $path);
     33        // replace the namespace separator with a directory separator...
     34        $path = str_replace( '\\', '/', $path );
    3635
    37         // and finally, add the PHP file extension to the result.
    38         $path = $path . '.php';
     36        // and finally, add the PHP file extension to the result.
     37        $path = $path . '.php';
    3938
    40         // $path should now contain the path to a PHP file defining $class
    41         if (file_exists($path)) {
    42             include $path;
    43         }
    44     }
     39        // $path should now contain the path to a PHP file defining $class
     40        if ( file_exists( $path ) ) {
     41            include $path;
     42        }
     43    }
    4544}
    4645
    47 spl_autoload_register('mmdb_autoload');
     46spl_autoload_register( 'mmdb_autoload' );
  • termageddon-usercentrics/trunk/vendor/maxmind-db/reader/src/MaxMind/Db/Reader.php

    r2771752 r3160131  
    1919 * addresses can be looked up using the get method.
    2020 */
    21 class Reader
    22 {
    23     /**
    24      * @var int
    25      */
    26     private static $DATA_SECTION_SEPARATOR_SIZE = 16;
    27     /**
    28      * @var string
    29      */
    30     private static $METADATA_START_MARKER = "\xAB\xCD\xEFMaxMind.com";
    31     /**
    32      * @var int
    33      */
    34     private static $METADATA_START_MARKER_LENGTH = 14;
    35     /**
    36      * @var int
    37      */
    38     private static $METADATA_MAX_SIZE = 131072; // 128 * 1024 = 128KiB
    39 
    40     /**
    41      * @var Decoder
    42      */
    43     private $decoder;
    44     /**
    45      * @var resource
    46      */
    47     private $fileHandle;
    48     /**
    49      * @var int
    50      */
    51     private $fileSize;
    52     /**
    53      * @var int
    54      */
    55     private $ipV4Start;
    56     /**
    57      * @var Metadata
    58      */
    59     private $metadata;
    60 
    61     /**
    62      * Constructs a Reader for the MaxMind DB format. The file passed to it must
    63      * be a valid MaxMind DB file such as a GeoIp2 database file.
    64      *
    65      * @param string $database
    66      *                         the MaxMind DB file to use
    67      *
    68      * @throws InvalidArgumentException for invalid database path or unknown arguments
    69      * @throws InvalidDatabaseException
    70      *                                  if the database is invalid or there is an error reading
    71      *                                  from it
    72      */
    73     public function __construct(string $database)
    74     {
    75         if (\func_num_args() !== 1) {
    76             throw new ArgumentCountError(
    77                 sprintf('%s() expects exactly 1 parameter, %d given', __METHOD__, \func_num_args())
    78             );
    79         }
    80 
    81         $fileHandle = @fopen($database, 'rb');
    82         if ($fileHandle === false) {
    83             throw new InvalidArgumentException(
    84                 "The file \"$database\" does not exist or is not readable."
    85             );
    86         }
    87         $this->fileHandle = $fileHandle;
    88 
    89         $fileSize = @filesize($database);
    90         if ($fileSize === false) {
    91             throw new UnexpectedValueException(
    92                 "Error determining the size of \"$database\"."
    93             );
    94         }
    95         $this->fileSize = $fileSize;
    96 
    97         $start = $this->findMetadataStart($database);
    98         $metadataDecoder = new Decoder($this->fileHandle, $start);
    99         [$metadataArray] = $metadataDecoder->decode($start);
    100         $this->metadata = new Metadata($metadataArray);
    101         $this->decoder = new Decoder(
    102             $this->fileHandle,
    103             $this->metadata->searchTreeSize + self::$DATA_SECTION_SEPARATOR_SIZE
    104         );
    105         $this->ipV4Start = $this->ipV4StartNode();
    106     }
    107 
    108     /**
    109      * Retrieves the record for the IP address.
    110      *
    111      * @param string $ipAddress
    112      *                          the IP address to look up
    113      *
    114      * @throws BadMethodCallException   if this method is called on a closed database
    115      * @throws InvalidArgumentException if something other than a single IP address is passed to the method
    116      * @throws InvalidDatabaseException
    117      *                                  if the database is invalid or there is an error reading
    118      *                                  from it
    119      *
    120      * @return mixed the record for the IP address
    121      */
    122     public function get(string $ipAddress)
    123     {
    124         if (\func_num_args() !== 1) {
    125             throw new ArgumentCountError(
    126                 sprintf('%s() expects exactly 1 parameter, %d given', __METHOD__, \func_num_args())
    127             );
    128         }
    129         [$record] = $this->getWithPrefixLen($ipAddress);
    130 
    131         return $record;
    132     }
    133 
    134     /**
    135      * Retrieves the record for the IP address and its associated network prefix length.
    136      *
    137      * @param string $ipAddress
    138      *                          the IP address to look up
    139      *
    140      * @throws BadMethodCallException   if this method is called on a closed database
    141      * @throws InvalidArgumentException if something other than a single IP address is passed to the method
    142      * @throws InvalidDatabaseException
    143      *                                  if the database is invalid or there is an error reading
    144      *                                  from it
    145      *
    146      * @return array an array where the first element is the record and the
    147      *               second the network prefix length for the record
    148      */
    149     public function getWithPrefixLen(string $ipAddress): array
    150     {
    151         if (\func_num_args() !== 1) {
    152             throw new ArgumentCountError(
    153                 sprintf('%s() expects exactly 1 parameter, %d given', __METHOD__, \func_num_args())
    154             );
    155         }
    156 
    157         if (!\is_resource($this->fileHandle)) {
    158             throw new BadMethodCallException(
    159                 'Attempt to read from a closed MaxMind DB.'
    160             );
    161         }
    162 
    163         [$pointer, $prefixLen] = $this->findAddressInTree($ipAddress);
    164         if ($pointer === 0) {
    165             return [null, $prefixLen];
    166         }
    167 
    168         return [$this->resolveDataPointer($pointer), $prefixLen];
    169     }
    170 
    171     private function findAddressInTree(string $ipAddress): array
    172     {
    173         $packedAddr = @inet_pton($ipAddress);
    174         if ($packedAddr === false) {
    175             throw new InvalidArgumentException(
    176                 "The value \"$ipAddress\" is not a valid IP address."
    177             );
    178         }
    179 
    180         $rawAddress = unpack('C*', $packedAddr);
    181 
    182         $bitCount = \count($rawAddress) * 8;
    183 
    184         // The first node of the tree is always node 0, at the beginning of the
    185         // value
    186         $node = 0;
    187 
    188         $metadata = $this->metadata;
    189 
    190         // Check if we are looking up an IPv4 address in an IPv6 tree. If this
    191         // is the case, we can skip over the first 96 nodes.
    192         if ($metadata->ipVersion === 6) {
    193             if ($bitCount === 32) {
    194                 $node = $this->ipV4Start;
    195             }
    196         } elseif ($metadata->ipVersion === 4 && $bitCount === 128) {
    197             throw new InvalidArgumentException(
    198                 "Error looking up $ipAddress. You attempted to look up an"
    199                 . ' IPv6 address in an IPv4-only database.'
    200             );
    201         }
    202 
    203         $nodeCount = $metadata->nodeCount;
    204 
    205         for ($i = 0; $i < $bitCount && $node < $nodeCount; ++$i) {
    206             $tempBit = 0xFF & $rawAddress[($i >> 3) + 1];
    207             $bit = 1 & ($tempBit >> 7 - ($i % 8));
    208 
    209             $node = $this->readNode($node, $bit);
    210         }
    211         if ($node === $nodeCount) {
    212             // Record is empty
    213             return [0, $i];
    214         }
    215         if ($node > $nodeCount) {
    216             // Record is a data pointer
    217             return [$node, $i];
    218         }
    219 
    220         throw new InvalidDatabaseException(
    221             'Invalid or corrupt database. Maximum search depth reached without finding a leaf node'
    222         );
    223     }
    224 
    225     private function ipV4StartNode(): int
    226     {
    227         // If we have an IPv4 database, the start node is the first node
    228         if ($this->metadata->ipVersion === 4) {
    229             return 0;
    230         }
    231 
    232         $node = 0;
    233 
    234         for ($i = 0; $i < 96 && $node < $this->metadata->nodeCount; ++$i) {
    235             $node = $this->readNode($node, 0);
    236         }
    237 
    238         return $node;
    239     }
    240 
    241     private function readNode(int $nodeNumber, int $index): int
    242     {
    243         $baseOffset = $nodeNumber * $this->metadata->nodeByteSize;
    244 
    245         switch ($this->metadata->recordSize) {
    246         case 24:
    247             $bytes = Util::read($this->fileHandle, $baseOffset + $index * 3, 3);
    248             [, $node] = unpack('N', "\x00" . $bytes);
    249 
    250             return $node;
    251 
    252         case 28:
    253             $bytes = Util::read($this->fileHandle, $baseOffset + 3 * $index, 4);
    254             if ($index === 0) {
    255                 $middle = (0xF0 & \ord($bytes[3])) >> 4;
    256             } else {
    257                 $middle = 0x0F & \ord($bytes[0]);
    258             }
    259             [, $node] = unpack('N', \chr($middle) . substr($bytes, $index, 3));
    260 
    261             return $node;
    262 
    263         case 32:
    264             $bytes = Util::read($this->fileHandle, $baseOffset + $index * 4, 4);
    265             [, $node] = unpack('N', $bytes);
    266 
    267             return $node;
    268 
    269         default:
    270             throw new InvalidDatabaseException(
    271                 'Unknown record size: '
    272                     . $this->metadata->recordSize
    273             );
    274         }
    275     }
    276 
    277     /**
    278      * @return mixed
    279      */
    280     private function resolveDataPointer(int $pointer)
    281     {
    282         $resolved = $pointer - $this->metadata->nodeCount
    283             + $this->metadata->searchTreeSize;
    284         if ($resolved >= $this->fileSize) {
    285             throw new InvalidDatabaseException(
    286                 "The MaxMind DB file's search tree is corrupt"
    287             );
    288         }
    289 
    290         [$data] = $this->decoder->decode($resolved);
    291 
    292         return $data;
    293     }
    294 
    295     /*
    296      * This is an extremely naive but reasonably readable implementation. There
    297      * are much faster algorithms (e.g., Boyer-Moore) for this if speed is ever
    298      * an issue, but I suspect it won't be.
    299      */
    300     private function findMetadataStart(string $filename): int
    301     {
    302         $handle = $this->fileHandle;
    303         $fstat = fstat($handle);
    304         $fileSize = $fstat['size'];
    305         $marker = self::$METADATA_START_MARKER;
    306         $markerLength = self::$METADATA_START_MARKER_LENGTH;
    307 
    308         $minStart = $fileSize - min(self::$METADATA_MAX_SIZE, $fileSize);
    309 
    310         for ($offset = $fileSize - $markerLength; $offset >= $minStart; --$offset) {
    311             if (fseek($handle, $offset) !== 0) {
    312                 break;
    313             }
    314 
    315             $value = fread($handle, $markerLength);
    316             if ($value === $marker) {
    317                 return $offset + $markerLength;
    318             }
    319         }
    320 
    321         throw new InvalidDatabaseException(
    322             "Error opening database file ($filename). " .
    323             'Is this a valid MaxMind DB file?'
    324         );
    325     }
    326 
    327     /**
    328      * @throws InvalidArgumentException if arguments are passed to the method
    329      * @throws BadMethodCallException   if the database has been closed
    330      *
    331      * @return Metadata object for the database
    332      */
    333     public function metadata(): Metadata
    334     {
    335         if (\func_num_args()) {
    336             throw new ArgumentCountError(
    337                 sprintf('%s() expects exactly 0 parameters, %d given', __METHOD__, \func_num_args())
    338             );
    339         }
    340 
    341         // Not technically required, but this makes it consistent with
    342         // C extension and it allows us to change our implementation later.
    343         if (!\is_resource($this->fileHandle)) {
    344             throw new BadMethodCallException(
    345                 'Attempt to read from a closed MaxMind DB.'
    346             );
    347         }
    348 
    349         return clone $this->metadata;
    350     }
    351 
    352     /**
    353      * Closes the MaxMind DB and returns resources to the system.
    354      *
    355      * @throws Exception
    356      *                   if an I/O error occurs
    357      */
    358     public function close(): void
    359     {
    360         if (\func_num_args()) {
    361             throw new ArgumentCountError(
    362                 sprintf('%s() expects exactly 0 parameters, %d given', __METHOD__, \func_num_args())
    363             );
    364         }
    365 
    366         if (!\is_resource($this->fileHandle)) {
    367             throw new BadMethodCallException(
    368                 'Attempt to close a closed MaxMind DB.'
    369             );
    370         }
    371         fclose($this->fileHandle);
    372     }
     21class Reader {
     22
     23    /**
     24     * @var int
     25     */
     26    private static $DATA_SECTION_SEPARATOR_SIZE = 16;
     27    /**
     28     * @var string
     29     */
     30    private static $METADATA_START_MARKER = "\xAB\xCD\xEFMaxMind.com";
     31    /**
     32     * @var int
     33     */
     34    private static $METADATA_START_MARKER_LENGTH = 14;
     35    /**
     36     * @var int
     37     */
     38    private static $METADATA_MAX_SIZE = 131072; // 128 * 1024 = 128KiB
     39
     40    /**
     41     * @var Decoder
     42     */
     43    private $decoder;
     44    /**
     45     * @var resource
     46     */
     47    private $fileHandle;
     48    /**
     49     * @var int
     50     */
     51    private $fileSize;
     52    /**
     53     * @var int
     54     */
     55    private $ipV4Start;
     56    /**
     57     * @var Metadata
     58     */
     59    private $metadata;
     60
     61    /**
     62     * Constructs a Reader for the MaxMind DB format. The file passed to it must
     63     * be a valid MaxMind DB file such as a GeoIp2 database file.
     64     *
     65     * @param string $database
     66     *                         the MaxMind DB file to use
     67     *
     68     * @throws InvalidArgumentException for invalid database path or unknown arguments
     69     * @throws InvalidDatabaseException
     70     *                                  if the database is invalid or there is an error reading
     71     *                                  from it
     72     */
     73    public function __construct( string $database ) {
     74        if ( \func_num_args() !== 1 ) {
     75            throw new ArgumentCountError(
     76                sprintf( '%s() expects exactly 1 parameter, %d given', __METHOD__, \func_num_args() )
     77            );
     78        }
     79
     80        $fileHandle = @fopen( $database, 'rb' );
     81        if ( $fileHandle === false ) {
     82            throw new InvalidArgumentException(
     83                "The file \"$database\" does not exist or is not readable."
     84            );
     85        }
     86        $this->fileHandle = $fileHandle;
     87
     88        $fileSize = @filesize( $database );
     89        if ( $fileSize === false ) {
     90            throw new UnexpectedValueException(
     91                "Error determining the size of \"$database\"."
     92            );
     93        }
     94        $this->fileSize = $fileSize;
     95
     96        $start           = $this->findMetadataStart( $database );
     97        $metadataDecoder = new Decoder( $this->fileHandle, $start );
     98        [$metadataArray] = $metadataDecoder->decode( $start );
     99        $this->metadata  = new Metadata( $metadataArray );
     100        $this->decoder   = new Decoder(
     101            $this->fileHandle,
     102            $this->metadata->searchTreeSize + self::$DATA_SECTION_SEPARATOR_SIZE
     103        );
     104        $this->ipV4Start = $this->ipV4StartNode();
     105    }
     106
     107    /**
     108     * Retrieves the record for the IP address.
     109     *
     110     * @param string $ipAddress
     111     *                          the IP address to look up
     112     *
     113     * @throws BadMethodCallException   if this method is called on a closed database
     114     * @throws InvalidArgumentException if something other than a single IP address is passed to the method
     115     * @throws InvalidDatabaseException
     116     *                                  if the database is invalid or there is an error reading
     117     *                                  from it
     118     *
     119     * @return mixed the record for the IP address
     120     */
     121    public function get( string $ipAddress ) {
     122        if ( \func_num_args() !== 1 ) {
     123            throw new ArgumentCountError(
     124                sprintf( '%s() expects exactly 1 parameter, %d given', __METHOD__, \func_num_args() )
     125            );
     126        }
     127        [$record] = $this->getWithPrefixLen( $ipAddress );
     128
     129        return $record;
     130    }
     131
     132    /**
     133     * Retrieves the record for the IP address and its associated network prefix length.
     134     *
     135     * @param string $ipAddress
     136     *                          the IP address to look up
     137     *
     138     * @throws BadMethodCallException   if this method is called on a closed database
     139     * @throws InvalidArgumentException if something other than a single IP address is passed to the method
     140     * @throws InvalidDatabaseException
     141     *                                  if the database is invalid or there is an error reading
     142     *                                  from it
     143     *
     144     * @return array an array where the first element is the record and the
     145     *               second the network prefix length for the record
     146     */
     147    public function getWithPrefixLen( string $ipAddress ): array {
     148        if ( \func_num_args() !== 1 ) {
     149            throw new ArgumentCountError(
     150                sprintf( '%s() expects exactly 1 parameter, %d given', __METHOD__, \func_num_args() )
     151            );
     152        }
     153
     154        if ( ! \is_resource( $this->fileHandle ) ) {
     155            throw new BadMethodCallException(
     156                'Attempt to read from a closed MaxMind DB.'
     157            );
     158        }
     159
     160        [$pointer, $prefixLen] = $this->findAddressInTree( $ipAddress );
     161        if ( $pointer === 0 ) {
     162            return array( null, $prefixLen );
     163        }
     164
     165        return array( $this->resolveDataPointer( $pointer ), $prefixLen );
     166    }
     167
     168    private function findAddressInTree( string $ipAddress ): array {
     169        $packedAddr = @inet_pton( $ipAddress );
     170        if ( $packedAddr === false ) {
     171            throw new InvalidArgumentException(
     172                "The value \"$ipAddress\" is not a valid IP address."
     173            );
     174        }
     175
     176        $rawAddress = unpack( 'C*', $packedAddr );
     177
     178        $bitCount = \count( $rawAddress ) * 8;
     179
     180        // The first node of the tree is always node 0, at the beginning of the
     181        // value
     182        $node = 0;
     183
     184        $metadata = $this->metadata;
     185
     186        // Check if we are looking up an IPv4 address in an IPv6 tree. If this
     187        // is the case, we can skip over the first 96 nodes.
     188        if ( $metadata->ipVersion === 6 ) {
     189            if ( $bitCount === 32 ) {
     190                $node = $this->ipV4Start;
     191            }
     192        } elseif ( $metadata->ipVersion === 4 && $bitCount === 128 ) {
     193            throw new InvalidArgumentException(
     194                "Error looking up $ipAddress. You attempted to look up an"
     195                . ' IPv6 address in an IPv4-only database.'
     196            );
     197        }
     198
     199        $nodeCount = $metadata->nodeCount;
     200
     201        for ( $i = 0; $i < $bitCount && $node < $nodeCount; ++$i ) {
     202            $tempBit = 0xFF & $rawAddress[ ( $i >> 3 ) + 1 ];
     203            $bit     = 1 & ( $tempBit >> 7 - ( $i % 8 ) );
     204
     205            $node = $this->readNode( $node, $bit );
     206        }
     207        if ( $node === $nodeCount ) {
     208            // Record is empty
     209            return array( 0, $i );
     210        }
     211        if ( $node > $nodeCount ) {
     212            // Record is a data pointer
     213            return array( $node, $i );
     214        }
     215
     216        throw new InvalidDatabaseException(
     217            'Invalid or corrupt database. Maximum search depth reached without finding a leaf node'
     218        );
     219    }
     220
     221    private function ipV4StartNode(): int {
     222        // If we have an IPv4 database, the start node is the first node
     223        if ( $this->metadata->ipVersion === 4 ) {
     224            return 0;
     225        }
     226
     227        $node = 0;
     228
     229        for ( $i = 0; $i < 96 && $node < $this->metadata->nodeCount; ++$i ) {
     230            $node = $this->readNode( $node, 0 );
     231        }
     232
     233        return $node;
     234    }
     235
     236    private function readNode( int $nodeNumber, int $index ): int {
     237        $baseOffset = $nodeNumber * $this->metadata->nodeByteSize;
     238
     239        switch ( $this->metadata->recordSize ) {
     240            case 24:
     241                $bytes    = Util::read( $this->fileHandle, $baseOffset + $index * 3, 3 );
     242                [, $node] = unpack( 'N', "\x00" . $bytes );
     243
     244                return $node;
     245
     246            case 28:
     247                $bytes = Util::read( $this->fileHandle, $baseOffset + 3 * $index, 4 );
     248                if ( $index === 0 ) {
     249                    $middle = ( 0xF0 & \ord( $bytes[3] ) ) >> 4;
     250                } else {
     251                    $middle = 0x0F & \ord( $bytes[0] );
     252                }
     253                [, $node] = unpack( 'N', \chr( $middle ) . substr( $bytes, $index, 3 ) );
     254
     255                return $node;
     256
     257            case 32:
     258                $bytes    = Util::read( $this->fileHandle, $baseOffset + $index * 4, 4 );
     259                [, $node] = unpack( 'N', $bytes );
     260
     261                return $node;
     262
     263            default:
     264                throw new InvalidDatabaseException(
     265                    'Unknown record size: '
     266                    . $this->metadata->recordSize
     267                );
     268        }
     269    }
     270
     271    /**
     272     * @return mixed
     273     */
     274    private function resolveDataPointer( int $pointer ) {
     275        $resolved = $pointer - $this->metadata->nodeCount
     276            + $this->metadata->searchTreeSize;
     277        if ( $resolved >= $this->fileSize ) {
     278            throw new InvalidDatabaseException(
     279                "The MaxMind DB file's search tree is corrupt"
     280            );
     281        }
     282
     283        [$data] = $this->decoder->decode( $resolved );
     284
     285        return $data;
     286    }
     287
     288    /*
     289     * This is an extremely naive but reasonably readable implementation. There
     290     * are much faster algorithms (e.g., Boyer-Moore) for this if speed is ever
     291     * an issue, but I suspect it won't be.
     292     */
     293    private function findMetadataStart( string $filename ): int {
     294        $handle       = $this->fileHandle;
     295        $fstat        = fstat( $handle );
     296        $fileSize     = $fstat['size'];
     297        $marker       = self::$METADATA_START_MARKER;
     298        $markerLength = self::$METADATA_START_MARKER_LENGTH;
     299
     300        $minStart = $fileSize - min( self::$METADATA_MAX_SIZE, $fileSize );
     301
     302        for ( $offset = $fileSize - $markerLength; $offset >= $minStart; --$offset ) {
     303            if ( fseek( $handle, $offset ) !== 0 ) {
     304                break;
     305            }
     306
     307            $value = fread( $handle, $markerLength );
     308            if ( $value === $marker ) {
     309                return $offset + $markerLength;
     310            }
     311        }
     312
     313        throw new InvalidDatabaseException(
     314            "Error opening database file ($filename). " .
     315            'Is this a valid MaxMind DB file?'
     316        );
     317    }
     318
     319    /**
     320     * @throws InvalidArgumentException if arguments are passed to the method
     321     * @throws BadMethodCallException   if the database has been closed
     322     *
     323     * @return Metadata object for the database
     324     */
     325    public function metadata(): Metadata {
     326        if ( \func_num_args() ) {
     327            throw new ArgumentCountError(
     328                sprintf( '%s() expects exactly 0 parameters, %d given', __METHOD__, \func_num_args() )
     329            );
     330        }
     331
     332        // Not technically required, but this makes it consistent with
     333        // C extension and it allows us to change our implementation later.
     334        if ( ! \is_resource( $this->fileHandle ) ) {
     335            throw new BadMethodCallException(
     336                'Attempt to read from a closed MaxMind DB.'
     337            );
     338        }
     339
     340        return clone $this->metadata;
     341    }
     342
     343    /**
     344     * Closes the MaxMind DB and returns resources to the system.
     345     *
     346     * @throws Exception
     347     *                   if an I/O error occurs
     348     */
     349    public function close(): void {
     350        if ( \func_num_args() ) {
     351            throw new ArgumentCountError(
     352                sprintf( '%s() expects exactly 0 parameters, %d given', __METHOD__, \func_num_args() )
     353            );
     354        }
     355
     356        if ( ! \is_resource( $this->fileHandle ) ) {
     357            throw new BadMethodCallException(
     358                'Attempt to close a closed MaxMind DB.'
     359            );
     360        }
     361        fclose( $this->fileHandle );
     362    }
    373363}
  • termageddon-usercentrics/trunk/vendor/maxmind-db/reader/src/MaxMind/Db/Reader/Decoder.php

    r2771752 r3160131  
    88use RuntimeException;
    99
    10 class Decoder
    11 {
    12     /**
    13      * @var resource
    14      */
    15     private $fileStream;
    16     /**
    17      * @var int
    18      */
    19     private $pointerBase;
    20     /**
    21      * @var float
    22      */
    23     private $pointerBaseByteSize;
    24     /**
    25      * This is only used for unit testing.
    26      *
    27      * @var bool
    28      */
    29     private $pointerTestHack;
    30     /**
    31      * @var bool
    32      */
    33     private $switchByteOrder;
    34 
    35     private const _EXTENDED = 0;
    36     private const _POINTER = 1;
    37     private const _UTF8_STRING = 2;
    38     private const _DOUBLE = 3;
    39     private const _BYTES = 4;
    40     private const _UINT16 = 5;
    41     private const _UINT32 = 6;
    42     private const _MAP = 7;
    43     private const _INT32 = 8;
    44     private const _UINT64 = 9;
    45     private const _UINT128 = 10;
    46     private const _ARRAY = 11;
    47     private const _CONTAINER = 12;
    48     private const _END_MARKER = 13;
    49     private const _BOOLEAN = 14;
    50     private const _FLOAT = 15;
    51 
    52     /**
    53      * @param resource $fileStream
    54      */
    55     public function __construct(
    56         $fileStream,
    57         int $pointerBase = 0,
    58         bool $pointerTestHack = false
    59     ) {
    60         $this->fileStream = $fileStream;
    61         $this->pointerBase = $pointerBase;
    62 
    63         $this->pointerBaseByteSize = $pointerBase > 0 ? log($pointerBase, 2) / 8 : 0;
    64         $this->pointerTestHack = $pointerTestHack;
    65 
    66         $this->switchByteOrder = $this->isPlatformLittleEndian();
    67     }
    68 
    69     public function decode(int $offset): array
    70     {
    71         $ctrlByte = \ord(Util::read($this->fileStream, $offset, 1));
    72         ++$offset;
    73 
    74         $type = $ctrlByte >> 5;
    75 
    76         // Pointers are a special case, we don't read the next $size bytes, we
    77         // use the size to determine the length of the pointer and then follow
    78         // it.
    79         if ($type === self::_POINTER) {
    80             [$pointer, $offset] = $this->decodePointer($ctrlByte, $offset);
    81 
    82             // for unit testing
    83             if ($this->pointerTestHack) {
    84                 return [$pointer];
    85             }
    86 
    87             [$result] = $this->decode($pointer);
    88 
    89             return [$result, $offset];
    90         }
    91 
    92         if ($type === self::_EXTENDED) {
    93             $nextByte = \ord(Util::read($this->fileStream, $offset, 1));
    94 
    95             $type = $nextByte + 7;
    96 
    97             if ($type < 8) {
    98                 throw new InvalidDatabaseException(
    99                     'Something went horribly wrong in the decoder. An extended type '
    100                     . 'resolved to a type number < 8 ('
    101                     . $type
    102                     . ')'
    103                 );
    104             }
    105 
    106             ++$offset;
    107         }
    108 
    109         [$size, $offset] = $this->sizeFromCtrlByte($ctrlByte, $offset);
    110 
    111         return $this->decodeByType($type, $offset, $size);
    112     }
    113 
    114     private function decodeByType(int $type, int $offset, int $size): array
    115     {
    116         switch ($type) {
    117         case self::_MAP:
    118             return $this->decodeMap($size, $offset);
    119 
    120         case self::_ARRAY:
    121             return $this->decodeArray($size, $offset);
    122 
    123         case self::_BOOLEAN:
    124             return [$this->decodeBoolean($size), $offset];
    125         }
    126 
    127         $newOffset = $offset + $size;
    128         $bytes = Util::read($this->fileStream, $offset, $size);
    129 
    130         switch ($type) {
    131         case self::_BYTES:
    132         case self::_UTF8_STRING:
    133             return [$bytes, $newOffset];
    134 
    135         case self::_DOUBLE:
    136             $this->verifySize(8, $size);
    137 
    138             return [$this->decodeDouble($bytes), $newOffset];
    139 
    140         case self::_FLOAT:
    141             $this->verifySize(4, $size);
    142 
    143             return [$this->decodeFloat($bytes), $newOffset];
    144 
    145         case self::_INT32:
    146             return [$this->decodeInt32($bytes, $size), $newOffset];
    147 
    148         case self::_UINT16:
    149         case self::_UINT32:
    150         case self::_UINT64:
    151         case self::_UINT128:
    152             return [$this->decodeUint($bytes, $size), $newOffset];
    153 
    154         default:
    155             throw new InvalidDatabaseException(
    156                 'Unknown or unexpected type: ' . $type
    157             );
    158         }
    159     }
    160 
    161     private function verifySize(int $expected, int $actual): void
    162     {
    163         if ($expected !== $actual) {
    164             throw new InvalidDatabaseException(
    165                 "The MaxMind DB file's data section contains bad data (unknown data type or corrupt data)"
    166             );
    167         }
    168     }
    169 
    170     private function decodeArray(int $size, int $offset): array
    171     {
    172         $array = [];
    173 
    174         for ($i = 0; $i < $size; ++$i) {
    175             [$value, $offset] = $this->decode($offset);
    176             $array[] = $value;
    177         }
    178 
    179         return [$array, $offset];
    180     }
    181 
    182     private function decodeBoolean(int $size): bool
    183     {
    184         return $size !== 0;
    185     }
    186 
    187     private function decodeDouble(string $bytes): float
    188     {
    189         // This assumes IEEE 754 doubles, but most (all?) modern platforms
    190         // use them.
    191         [, $double] = unpack('E', $bytes);
    192 
    193         return $double;
    194     }
    195 
    196     private function decodeFloat(string $bytes): float
    197     {
    198         // This assumes IEEE 754 floats, but most (all?) modern platforms
    199         // use them.
    200         [, $float] = unpack('G', $bytes);
    201 
    202         return $float;
    203     }
    204 
    205     private function decodeInt32(string $bytes, int $size): int
    206     {
    207         switch ($size) {
    208         case 0:
    209             return 0;
    210 
    211         case 1:
    212         case 2:
    213         case 3:
    214             $bytes = str_pad($bytes, 4, "\x00", \STR_PAD_LEFT);
    215 
    216             break;
    217 
    218         case 4:
    219             break;
    220 
    221         default:
    222             throw new InvalidDatabaseException(
    223                 "The MaxMind DB file's data section contains bad data (unknown data type or corrupt data)"
    224             );
    225         }
    226 
    227         [, $int] = unpack('l', $this->maybeSwitchByteOrder($bytes));
    228 
    229         return $int;
    230     }
    231 
    232     private function decodeMap(int $size, int $offset): array
    233     {
    234         $map = [];
    235 
    236         for ($i = 0; $i < $size; ++$i) {
    237             [$key, $offset] = $this->decode($offset);
    238             [$value, $offset] = $this->decode($offset);
    239             $map[$key] = $value;
    240         }
    241 
    242         return [$map, $offset];
    243     }
    244 
    245     private function decodePointer(int $ctrlByte, int $offset): array
    246     {
    247         $pointerSize = (($ctrlByte >> 3) & 0x3) + 1;
    248 
    249         $buffer = Util::read($this->fileStream, $offset, $pointerSize);
    250         $offset = $offset + $pointerSize;
    251 
    252         switch ($pointerSize) {
    253         case 1:
    254             $packed = \chr($ctrlByte & 0x7) . $buffer;
    255             [, $pointer] = unpack('n', $packed);
    256             $pointer += $this->pointerBase;
    257 
    258             break;
    259 
    260         case 2:
    261             $packed = "\x00" . \chr($ctrlByte & 0x7) . $buffer;
    262             [, $pointer] = unpack('N', $packed);
    263             $pointer += $this->pointerBase + 2048;
    264 
    265             break;
    266 
    267         case 3:
    268             $packed = \chr($ctrlByte & 0x7) . $buffer;
    269 
    270             // It is safe to use 'N' here, even on 32 bit machines as the
    271             // first bit is 0.
    272             [, $pointer] = unpack('N', $packed);
    273             $pointer += $this->pointerBase + 526336;
    274 
    275             break;
    276 
    277         case 4:
    278             // We cannot use unpack here as we might overflow on 32 bit
    279             // machines
    280             $pointerOffset = $this->decodeUint($buffer, $pointerSize);
    281 
    282             $pointerBase = $this->pointerBase;
    283 
    284             if (\PHP_INT_MAX - $pointerBase >= $pointerOffset) {
    285                 $pointer = $pointerOffset + $pointerBase;
    286             } else {
    287                 throw new RuntimeException(
    288                     'The database offset is too large to be represented on your platform.'
    289                 );
    290             }
    291 
    292             break;
    293 
    294         default:
    295             throw new InvalidDatabaseException(
    296                 'Unexpected pointer size ' . $pointerSize
    297             );
    298         }
    299 
    300         return [$pointer, $offset];
    301     }
    302 
    303     // @phpstan-ignore-next-line
    304     private function decodeUint(string $bytes, int $byteLength)
    305     {
    306         if ($byteLength === 0) {
    307             return 0;
    308         }
    309 
    310         $integer = 0;
    311 
    312         // PHP integers are signed. PHP_INT_SIZE - 1 is the number of
    313         // complete bytes that can be converted to an integer. However,
    314         // we can convert another byte if the leading bit is zero.
    315         $useRealInts = $byteLength <= \PHP_INT_SIZE - 1
    316             || ($byteLength === \PHP_INT_SIZE && (\ord($bytes[0]) & 0x80) === 0);
    317 
    318         for ($i = 0; $i < $byteLength; ++$i) {
    319             $part = \ord($bytes[$i]);
    320 
    321             // We only use gmp or bcmath if the final value is too big
    322             if ($useRealInts) {
    323                 $integer = ($integer << 8) + $part;
    324             } elseif (\extension_loaded('gmp')) {
    325                 $integer = gmp_strval(gmp_add(gmp_mul((string) $integer, '256'), $part));
    326             } elseif (\extension_loaded('bcmath')) {
    327                 $integer = bcadd(bcmul((string) $integer, '256'), (string) $part);
    328             } else {
    329                 throw new RuntimeException(
    330                     'The gmp or bcmath extension must be installed to read this database.'
    331                 );
    332             }
    333         }
    334 
    335         return $integer;
    336     }
    337 
    338     private function sizeFromCtrlByte(int $ctrlByte, int $offset): array
    339     {
    340         $size = $ctrlByte & 0x1F;
    341 
    342         if ($size < 29) {
    343             return [$size, $offset];
    344         }
    345 
    346         $bytesToRead = $size - 28;
    347         $bytes = Util::read($this->fileStream, $offset, $bytesToRead);
    348 
    349         if ($size === 29) {
    350             $size = 29 + \ord($bytes);
    351         } elseif ($size === 30) {
    352             [, $adjust] = unpack('n', $bytes);
    353             $size = 285 + $adjust;
    354         } else {
    355             [, $adjust] = unpack('N', "\x00" . $bytes);
    356             $size = $adjust + 65821;
    357         }
    358 
    359         return [$size, $offset + $bytesToRead];
    360     }
    361 
    362     private function maybeSwitchByteOrder(string $bytes): string
    363     {
    364         return $this->switchByteOrder ? strrev($bytes) : $bytes;
    365     }
    366 
    367     private function isPlatformLittleEndian(): bool
    368     {
    369         $testint = 0x00FF;
    370         $packed = pack('S', $testint);
    371 
    372         return $testint === current(unpack('v', $packed));
    373     }
     10class Decoder {
     11
     12    /**
     13     * @var resource
     14     */
     15    private $fileStream;
     16    /**
     17     * @var int
     18     */
     19    private $pointerBase;
     20    /**
     21     * @var float
     22     */
     23    private $pointerBaseByteSize;
     24    /**
     25     * This is only used for unit testing.
     26     *
     27     * @var bool
     28     */
     29    private $pointerTestHack;
     30    /**
     31     * @var bool
     32     */
     33    private $switchByteOrder;
     34
     35    private const _EXTENDED    = 0;
     36    private const _POINTER     = 1;
     37    private const _UTF8_STRING = 2;
     38    private const _DOUBLE      = 3;
     39    private const _BYTES       = 4;
     40    private const _UINT16      = 5;
     41    private const _UINT32      = 6;
     42    private const _MAP         = 7;
     43    private const _INT32       = 8;
     44    private const _UINT64      = 9;
     45    private const _UINT128     = 10;
     46    private const _ARRAY       = 11;
     47    private const _CONTAINER   = 12;
     48    private const _END_MARKER  = 13;
     49    private const _BOOLEAN     = 14;
     50    private const _FLOAT       = 15;
     51
     52    /**
     53     * @param resource $fileStream
     54     */
     55    public function __construct(
     56        $fileStream,
     57        int $pointerBase = 0,
     58        bool $pointerTestHack = false
     59    ) {
     60        $this->fileStream  = $fileStream;
     61        $this->pointerBase = $pointerBase;
     62
     63        $this->pointerBaseByteSize = $pointerBase > 0 ? log( $pointerBase, 2 ) / 8 : 0;
     64        $this->pointerTestHack     = $pointerTestHack;
     65
     66        $this->switchByteOrder = $this->isPlatformLittleEndian();
     67    }
     68
     69    public function decode( int $offset ): array {
     70        $ctrlByte = \ord( Util::read( $this->fileStream, $offset, 1 ) );
     71        ++$offset;
     72
     73        $type = $ctrlByte >> 5;
     74
     75        // Pointers are a special case, we don't read the next $size bytes, we
     76        // use the size to determine the length of the pointer and then follow
     77        // it.
     78        if ( $type === self::_POINTER ) {
     79            [$pointer, $offset] = $this->decodePointer( $ctrlByte, $offset );
     80
     81            // for unit testing
     82            if ( $this->pointerTestHack ) {
     83                return array( $pointer );
     84            }
     85
     86            [$result] = $this->decode( $pointer );
     87
     88            return array( $result, $offset );
     89        }
     90
     91        if ( $type === self::_EXTENDED ) {
     92            $nextByte = \ord( Util::read( $this->fileStream, $offset, 1 ) );
     93
     94            $type = $nextByte + 7;
     95
     96            if ( $type < 8 ) {
     97                throw new InvalidDatabaseException(
     98                    'Something went horribly wrong in the decoder. An extended type '
     99                    . 'resolved to a type number < 8 ('
     100                    . $type
     101                    . ')'
     102                );
     103            }
     104
     105            ++$offset;
     106        }
     107
     108        [$size, $offset] = $this->sizeFromCtrlByte( $ctrlByte, $offset );
     109
     110        return $this->decodeByType( $type, $offset, $size );
     111    }
     112
     113    private function decodeByType( int $type, int $offset, int $size ): array {
     114        switch ( $type ) {
     115            case self::_MAP:
     116                return $this->decodeMap( $size, $offset );
     117
     118            case self::_ARRAY:
     119                return $this->decodeArray( $size, $offset );
     120
     121            case self::_BOOLEAN:
     122                return array( $this->decodeBoolean( $size ), $offset );
     123        }
     124
     125        $newOffset = $offset + $size;
     126        $bytes     = Util::read( $this->fileStream, $offset, $size );
     127
     128        switch ( $type ) {
     129            case self::_BYTES:
     130            case self::_UTF8_STRING:
     131                return array( $bytes, $newOffset );
     132
     133            case self::_DOUBLE:
     134                $this->verifySize( 8, $size );
     135
     136                return array( $this->decodeDouble( $bytes ), $newOffset );
     137
     138            case self::_FLOAT:
     139                $this->verifySize( 4, $size );
     140
     141                return array( $this->decodeFloat( $bytes ), $newOffset );
     142
     143            case self::_INT32:
     144                return array( $this->decodeInt32( $bytes, $size ), $newOffset );
     145
     146            case self::_UINT16:
     147            case self::_UINT32:
     148            case self::_UINT64:
     149            case self::_UINT128:
     150                return array( $this->decodeUint( $bytes, $size ), $newOffset );
     151
     152            default:
     153                throw new InvalidDatabaseException(
     154                    'Unknown or unexpected type: ' . $type
     155                );
     156        }
     157    }
     158
     159    private function verifySize( int $expected, int $actual ): void {
     160        if ( $expected !== $actual ) {
     161            throw new InvalidDatabaseException(
     162                "The MaxMind DB file's data section contains bad data (unknown data type or corrupt data)"
     163            );
     164        }
     165    }
     166
     167    private function decodeArray( int $size, int $offset ): array {
     168        $array = array();
     169
     170        for ( $i = 0; $i < $size; ++$i ) {
     171            [$value, $offset] = $this->decode( $offset );
     172            $array[]          = $value;
     173        }
     174
     175        return array( $array, $offset );
     176    }
     177
     178    private function decodeBoolean( int $size ): bool {
     179        return $size !== 0;
     180    }
     181
     182    private function decodeDouble( string $bytes ): float {
     183        // This assumes IEEE 754 doubles, but most (all?) modern platforms
     184        // use them.
     185        [, $double] = unpack( 'E', $bytes );
     186
     187        return $double;
     188    }
     189
     190    private function decodeFloat( string $bytes ): float {
     191        // This assumes IEEE 754 floats, but most (all?) modern platforms
     192        // use them.
     193        [, $float] = unpack( 'G', $bytes );
     194
     195        return $float;
     196    }
     197
     198    private function decodeInt32( string $bytes, int $size ): int {
     199        switch ( $size ) {
     200            case 0:
     201                return 0;
     202
     203            case 1:
     204            case 2:
     205            case 3:
     206                $bytes = str_pad( $bytes, 4, "\x00", \STR_PAD_LEFT );
     207
     208                break;
     209
     210            case 4:
     211                break;
     212
     213            default:
     214                throw new InvalidDatabaseException(
     215                    "The MaxMind DB file's data section contains bad data (unknown data type or corrupt data)"
     216                );
     217        }
     218
     219        [, $int] = unpack( 'l', $this->maybeSwitchByteOrder( $bytes ) );
     220
     221        return $int;
     222    }
     223
     224    private function decodeMap( int $size, int $offset ): array {
     225        $map = array();
     226
     227        for ( $i = 0; $i < $size; ++$i ) {
     228            [$key, $offset]   = $this->decode( $offset );
     229            [$value, $offset] = $this->decode( $offset );
     230            $map[ $key ]      = $value;
     231        }
     232
     233        return array( $map, $offset );
     234    }
     235
     236    private function decodePointer( int $ctrlByte, int $offset ): array {
     237        $pointerSize = ( ( $ctrlByte >> 3 ) & 0x3 ) + 1;
     238
     239        $buffer = Util::read( $this->fileStream, $offset, $pointerSize );
     240        $offset = $offset + $pointerSize;
     241
     242        switch ( $pointerSize ) {
     243            case 1:
     244                $packed      = \chr( $ctrlByte & 0x7 ) . $buffer;
     245                [, $pointer] = unpack( 'n', $packed );
     246                $pointer    += $this->pointerBase;
     247
     248                break;
     249
     250            case 2:
     251                $packed      = "\x00" . \chr( $ctrlByte & 0x7 ) . $buffer;
     252                [, $pointer] = unpack( 'N', $packed );
     253                $pointer    += $this->pointerBase + 2048;
     254
     255                break;
     256
     257            case 3:
     258                $packed = \chr( $ctrlByte & 0x7 ) . $buffer;
     259
     260                // It is safe to use 'N' here, even on 32 bit machines as the
     261                // first bit is 0.
     262                [, $pointer] = unpack( 'N', $packed );
     263                $pointer    += $this->pointerBase + 526336;
     264
     265                break;
     266
     267            case 4:
     268                // We cannot use unpack here as we might overflow on 32 bit
     269                // machines
     270                $pointerOffset = $this->decodeUint( $buffer, $pointerSize );
     271
     272                $pointerBase = $this->pointerBase;
     273
     274                if ( \PHP_INT_MAX - $pointerBase >= $pointerOffset ) {
     275                    $pointer = $pointerOffset + $pointerBase;
     276                } else {
     277                    throw new RuntimeException(
     278                        'The database offset is too large to be represented on your platform.'
     279                    );
     280                }
     281
     282                break;
     283
     284            default:
     285                throw new InvalidDatabaseException(
     286                    'Unexpected pointer size ' . $pointerSize
     287                );
     288        }
     289
     290        return array( $pointer, $offset );
     291    }
     292
     293    // @phpstan-ignore-next-line
     294    private function decodeUint( string $bytes, int $byteLength ) {
     295        if ( $byteLength === 0 ) {
     296            return 0;
     297        }
     298
     299        $integer = 0;
     300
     301        // PHP integers are signed. PHP_INT_SIZE - 1 is the number of
     302        // complete bytes that can be converted to an integer. However,
     303        // we can convert another byte if the leading bit is zero.
     304        $useRealInts = $byteLength <= \PHP_INT_SIZE - 1
     305            || ( $byteLength === \PHP_INT_SIZE && ( \ord( $bytes[0] ) & 0x80 ) === 0 );
     306
     307        for ( $i = 0; $i < $byteLength; ++$i ) {
     308            $part = \ord( $bytes[ $i ] );
     309
     310            // We only use gmp or bcmath if the final value is too big
     311            if ( $useRealInts ) {
     312                $integer = ( $integer << 8 ) + $part;
     313            } elseif ( \extension_loaded( 'gmp' ) ) {
     314                $integer = gmp_strval( gmp_add( gmp_mul( (string) $integer, '256' ), $part ) );
     315            } elseif ( \extension_loaded( 'bcmath' ) ) {
     316                $integer = bcadd( bcmul( (string) $integer, '256' ), (string) $part );
     317            } else {
     318                throw new RuntimeException(
     319                    'The gmp or bcmath extension must be installed to read this database.'
     320                );
     321            }
     322        }
     323
     324        return $integer;
     325    }
     326
     327    private function sizeFromCtrlByte( int $ctrlByte, int $offset ): array {
     328        $size = $ctrlByte & 0x1F;
     329
     330        if ( $size < 29 ) {
     331            return array( $size, $offset );
     332        }
     333
     334        $bytesToRead = $size - 28;
     335        $bytes       = Util::read( $this->fileStream, $offset, $bytesToRead );
     336
     337        if ( $size === 29 ) {
     338            $size = 29 + \ord( $bytes );
     339        } elseif ( $size === 30 ) {
     340            [, $adjust] = unpack( 'n', $bytes );
     341            $size       = 285 + $adjust;
     342        } else {
     343            [, $adjust] = unpack( 'N', "\x00" . $bytes );
     344            $size       = $adjust + 65821;
     345        }
     346
     347        return array( $size, $offset + $bytesToRead );
     348    }
     349
     350    private function maybeSwitchByteOrder( string $bytes ): string {
     351        return $this->switchByteOrder ? strrev( $bytes ) : $bytes;
     352    }
     353
     354    private function isPlatformLittleEndian(): bool {
     355        $testint = 0x00FF;
     356        $packed  = pack( 'S', $testint );
     357
     358        return $testint === current( unpack( 'v', $packed ) );
     359    }
    374360}
  • termageddon-usercentrics/trunk/vendor/maxmind-db/reader/src/MaxMind/Db/Reader/InvalidDatabaseException.php

    r2771752 r3160131  
    1010 * This class should be thrown when unexpected data is found in the database.
    1111 */
    12 class InvalidDatabaseException extends Exception
    13 {
     12class InvalidDatabaseException extends Exception {
     13
    1414}
  • termageddon-usercentrics/trunk/vendor/maxmind-db/reader/src/MaxMind/Db/Reader/Metadata.php

    r2771752 r3160131  
    1010 * This class provides the metadata for the MaxMind DB file.
    1111 */
    12 class Metadata
    13 {
    14     /**
    15      * This is an unsigned 16-bit integer indicating the major version number
    16      * for the database's binary format.
    17      *
    18      * @var int
    19      */
    20     public $binaryFormatMajorVersion;
    21     /**
    22      * This is an unsigned 16-bit integer indicating the minor version number
    23      * for the database's binary format.
    24      *
    25      * @var int
    26      */
    27     public $binaryFormatMinorVersion;
    28     /**
    29      * This is an unsigned 64-bit integer that contains the database build
    30      * timestamp as a Unix epoch value.
    31      *
    32      * @var int
    33      */
    34     public $buildEpoch;
    35     /**
    36      * This is a string that indicates the structure of each data record
    37      * associated with an IP address.  The actual definition of these
    38      * structures is left up to the database creator.
    39      *
    40      * @var string
    41      */
    42     public $databaseType;
    43     /**
    44      * This key will always point to a map (associative array). The keys of
    45      * that map will be language codes, and the values will be a description
    46      * in that language as a UTF-8 string. May be undefined for some
    47      * databases.
    48      *
    49      * @var array
    50      */
    51     public $description;
    52     /**
    53      * This is an unsigned 16-bit integer which is always 4 or 6. It indicates
    54      * whether the database contains IPv4 or IPv6 address data.
    55      *
    56      * @var int
    57      */
    58     public $ipVersion;
    59     /**
    60      * An array of strings, each of which is a language code. A given record
    61      * may contain data items that have been localized to some or all of
    62      * these languages. This may be undefined.
    63      *
    64      * @var array
    65      */
    66     public $languages;
    67     /**
    68      * @var int
    69      */
    70     public $nodeByteSize;
    71     /**
    72      * This is an unsigned 32-bit integer indicating the number of nodes in
    73      * the search tree.
    74      *
    75      * @var int
    76      */
    77     public $nodeCount;
    78     /**
    79      * This is an unsigned 16-bit integer. It indicates the number of bits in a
    80      * record in the search tree. Note that each node consists of two records.
    81      *
    82      * @var int
    83      */
    84     public $recordSize;
    85     /**
    86      * @var int
    87      */
    88     public $searchTreeSize;
     12class Metadata {
    8913
    90     public function __construct(array $metadata)
    91     {
    92         if (\func_num_args() !== 1) {
    93             throw new ArgumentCountError(
    94                 sprintf('%s() expects exactly 1 parameter, %d given', __METHOD__, \func_num_args())
    95             );
    96         }
     14    /**
     15     * This is an unsigned 16-bit integer indicating the major version number
     16     * for the database's binary format.
     17     *
     18     * @var int
     19     */
     20    public $binaryFormatMajorVersion;
     21    /**
     22     * This is an unsigned 16-bit integer indicating the minor version number
     23     * for the database's binary format.
     24     *
     25     * @var int
     26     */
     27    public $binaryFormatMinorVersion;
     28    /**
     29     * This is an unsigned 64-bit integer that contains the database build
     30     * timestamp as a Unix epoch value.
     31     *
     32     * @var int
     33     */
     34    public $buildEpoch;
     35    /**
     36     * This is a string that indicates the structure of each data record
     37     * associated with an IP address.  The actual definition of these
     38     * structures is left up to the database creator.
     39     *
     40     * @var string
     41     */
     42    public $databaseType;
     43    /**
     44     * This key will always point to a map (associative array). The keys of
     45     * that map will be language codes, and the values will be a description
     46     * in that language as a UTF-8 string. May be undefined for some
     47     * databases.
     48     *
     49     * @var array
     50     */
     51    public $description;
     52    /**
     53     * This is an unsigned 16-bit integer which is always 4 or 6. It indicates
     54     * whether the database contains IPv4 or IPv6 address data.
     55     *
     56     * @var int
     57     */
     58    public $ipVersion;
     59    /**
     60     * An array of strings, each of which is a language code. A given record
     61     * may contain data items that have been localized to some or all of
     62     * these languages. This may be undefined.
     63     *
     64     * @var array
     65     */
     66    public $languages;
     67    /**
     68     * @var int
     69     */
     70    public $nodeByteSize;
     71    /**
     72     * This is an unsigned 32-bit integer indicating the number of nodes in
     73     * the search tree.
     74     *
     75     * @var int
     76     */
     77    public $nodeCount;
     78    /**
     79     * This is an unsigned 16-bit integer. It indicates the number of bits in a
     80     * record in the search tree. Note that each node consists of two records.
     81     *
     82     * @var int
     83     */
     84    public $recordSize;
     85    /**
     86     * @var int
     87     */
     88    public $searchTreeSize;
    9789
    98         $this->binaryFormatMajorVersion =
    99             $metadata['binary_format_major_version'];
    100         $this->binaryFormatMinorVersion =
    101             $metadata['binary_format_minor_version'];
    102         $this->buildEpoch = $metadata['build_epoch'];
    103         $this->databaseType = $metadata['database_type'];
    104         $this->languages = $metadata['languages'];
    105         $this->description = $metadata['description'];
    106         $this->ipVersion = $metadata['ip_version'];
    107         $this->nodeCount = $metadata['node_count'];
    108         $this->recordSize = $metadata['record_size'];
    109         $this->nodeByteSize = $this->recordSize / 4;
    110         $this->searchTreeSize = $this->nodeCount * $this->nodeByteSize;
    111     }
     90    public function __construct( array $metadata ) {
     91        if ( \func_num_args() !== 1 ) {
     92            throw new ArgumentCountError(
     93                sprintf( '%s() expects exactly 1 parameter, %d given', __METHOD__, \func_num_args() )
     94            );
     95        }
     96
     97        $this->binaryFormatMajorVersion =
     98            $metadata['binary_format_major_version'];
     99        $this->binaryFormatMinorVersion =
     100            $metadata['binary_format_minor_version'];
     101        $this->buildEpoch               = $metadata['build_epoch'];
     102        $this->databaseType             = $metadata['database_type'];
     103        $this->languages                = $metadata['languages'];
     104        $this->description              = $metadata['description'];
     105        $this->ipVersion                = $metadata['ip_version'];
     106        $this->nodeCount                = $metadata['node_count'];
     107        $this->recordSize               = $metadata['record_size'];
     108        $this->nodeByteSize             = $this->recordSize / 4;
     109        $this->searchTreeSize           = $this->nodeCount * $this->nodeByteSize;
     110    }
    112111}
  • termageddon-usercentrics/trunk/vendor/maxmind-db/reader/src/MaxMind/Db/Reader/Util.php

    r2771752 r3160131  
    55namespace MaxMind\Db\Reader;
    66
    7 class Util
    8 {
    9     /**
    10      * @param resource $stream
    11      */
    12     public static function read($stream, int $offset, int $numberOfBytes): string
    13     {
    14         if ($numberOfBytes === 0) {
    15             return '';
    16         }
    17         if (fseek($stream, $offset) === 0) {
    18             $value = fread($stream, $numberOfBytes);
     7class Util {
    198
    20             // We check that the number of bytes read is equal to the number
    21             // asked for. We use ftell as getting the length of $value is
    22             // much slower.
    23             if ($value !== false && ftell($stream) - $offset === $numberOfBytes) {
    24                 return $value;
    25             }
    26         }
     9    /**
     10     * @param resource $stream
     11     */
     12    public static function read( $stream, int $offset, int $numberOfBytes ): string {
     13        if ( $numberOfBytes === 0 ) {
     14            return '';
     15        }
     16        if ( fseek( $stream, $offset ) === 0 ) {
     17            $value = fread( $stream, $numberOfBytes );
    2718
    28         throw new InvalidDatabaseException(
    29             'The MaxMind DB file contains bad data'
    30         );
    31     }
     19            // We check that the number of bytes read is equal to the number
     20            // asked for. We use ftell as getting the length of $value is
     21            // much slower.
     22            if ( $value !== false && ftell( $stream ) - $offset === $numberOfBytes ) {
     23                return $value;
     24            }
     25        }
     26
     27        throw new InvalidDatabaseException(
     28            'The MaxMind DB file contains bad data'
     29        );
     30    }
    3231}
  • termageddon-usercentrics/trunk/vendor/maxmind/web-service-common/src/Exception/AuthenticationException.php

    r2771752 r3160131  
    88 * This class represents an error authenticating.
    99 */
    10 class AuthenticationException extends InvalidRequestException
    11 {
     10class AuthenticationException extends InvalidRequestException {
     11
    1212}
  • termageddon-usercentrics/trunk/vendor/maxmind/web-service-common/src/Exception/HttpException.php

    r2771752 r3160131  
    88 *  This class represents an HTTP transport error.
    99 */
    10 class HttpException extends WebServiceException
    11 {
    12     /**
    13      * The URI queried.
    14      *
    15      * @var string
    16      */
    17     private $uri;
     10class HttpException extends WebServiceException {
    1811
    19     /**
    20      * @param string     $message    a message describing the error
    21      * @param int        $httpStatus the HTTP status code of the response
    22      * @param string     $uri        the URI used in the request
    23      * @param \Exception $previous   the previous exception, if any
    24      */
    25     public function __construct(
    26         string $message,
    27         int $httpStatus,
    28         string $uri,
    29         \Exception $previous = null
    30     ) {
    31         $this->uri = $uri;
    32         parent::__construct($message, $httpStatus, $previous);
    33     }
     12    /**
     13     * The URI queried.
     14     *
     15     * @var string
     16     */
     17    private $uri;
    3418
    35     public function getUri(): string
    36     {
    37         return $this->uri;
    38     }
     19    /**
     20     * @param string     $message    a message describing the error
     21     * @param int        $httpStatus the HTTP status code of the response
     22     * @param string     $uri        the URI used in the request
     23     * @param \Exception $previous   the previous exception, if any
     24     */
     25    public function __construct(
     26        string $message,
     27        int $httpStatus,
     28        string $uri,
     29        \Exception $previous = null
     30    ) {
     31        $this->uri = $uri;
     32        parent::__construct( $message, $httpStatus, $previous );
     33    }
    3934
    40     public function getStatusCode(): int
    41     {
    42         return $this->getCode();
    43     }
     35    public function getUri(): string {
     36        return $this->uri;
     37    }
     38
     39    public function getStatusCode(): int {
     40        return $this->getCode();
     41    }
    4442}
  • termageddon-usercentrics/trunk/vendor/maxmind/web-service-common/src/Exception/InsufficientFundsException.php

    r2771752 r3160131  
    88 * Thrown when the account is out of credits.
    99 */
    10 class InsufficientFundsException extends InvalidRequestException
    11 {
     10class InsufficientFundsException extends InvalidRequestException {
     11
    1212}
  • termageddon-usercentrics/trunk/vendor/maxmind/web-service-common/src/Exception/InvalidInputException.php

    r2771752 r3160131  
    1010 * is a missing or invalid field.
    1111 */
    12 class InvalidInputException extends WebServiceException
    13 {
     12class InvalidInputException extends WebServiceException {
     13
    1414}
  • termageddon-usercentrics/trunk/vendor/maxmind/web-service-common/src/Exception/InvalidRequestException.php

    r2771752 r3160131  
    88 * Thrown when a MaxMind web service returns an error relating to the request.
    99 */
    10 class InvalidRequestException extends HttpException
    11 {
    12     /**
    13      * The code returned by the MaxMind web service.
    14      *
    15      * @var string
    16      */
    17     private $error;
     10class InvalidRequestException extends HttpException {
    1811
    19     /**
    20      * @param string     $message    the exception message
    21      * @param string     $error      the error code returned by the MaxMind web service
    22      * @param int        $httpStatus the HTTP status code of the response
    23      * @param string     $uri        the URI queries
    24      * @param \Exception $previous   the previous exception, if any
    25      */
    26     public function __construct(
    27         string $message,
    28         string $error,
    29         int $httpStatus,
    30         string $uri,
    31         \Exception $previous = null
    32     ) {
    33         $this->error = $error;
    34         parent::__construct($message, $httpStatus, $uri, $previous);
    35     }
     12    /**
     13     * The code returned by the MaxMind web service.
     14     *
     15     * @var string
     16     */
     17    private $error;
    3618
    37     public function getErrorCode(): string
    38     {
    39         return $this->error;
    40     }
     19    /**
     20     * @param string     $message    the exception message
     21     * @param string     $error      the error code returned by the MaxMind web service
     22     * @param int        $httpStatus the HTTP status code of the response
     23     * @param string     $uri        the URI queries
     24     * @param \Exception $previous   the previous exception, if any
     25     */
     26    public function __construct(
     27        string $message,
     28        string $error,
     29        int $httpStatus,
     30        string $uri,
     31        \Exception $previous = null
     32    ) {
     33        $this->error = $error;
     34        parent::__construct( $message, $httpStatus, $uri, $previous );
     35    }
     36
     37    public function getErrorCode(): string {
     38        return $this->error;
     39    }
    4140}
  • termageddon-usercentrics/trunk/vendor/maxmind/web-service-common/src/Exception/IpAddressNotFoundException.php

    r2771752 r3160131  
    55namespace MaxMind\Exception;
    66
    7 class IpAddressNotFoundException extends InvalidRequestException
    8 {
     7class IpAddressNotFoundException extends InvalidRequestException {
     8
    99}
  • termageddon-usercentrics/trunk/vendor/maxmind/web-service-common/src/Exception/PermissionRequiredException.php

    r2771752 r3160131  
    88 * This exception is thrown when the service requires permission to access.
    99 */
    10 class PermissionRequiredException extends InvalidRequestException
    11 {
     10class PermissionRequiredException extends InvalidRequestException {
     11
    1212}
  • termageddon-usercentrics/trunk/vendor/maxmind/web-service-common/src/Exception/WebServiceException.php

    r2771752 r3160131  
    88 * This class represents a generic web service error.
    99 */
    10 class WebServiceException extends \Exception
    11 {
     10class WebServiceException extends \Exception {
     11
    1212}
  • termageddon-usercentrics/trunk/vendor/maxmind/web-service-common/src/WebService/Client.php

    r2771752 r3160131  
    2323 * @internal
    2424 */
    25 class Client
    26 {
    27     public const VERSION = '0.2.0';
    28 
    29     /**
    30      * @var string|null
    31      */
    32     private $caBundle;
    33 
    34     /**
    35      * @var float|null
    36      */
    37     private $connectTimeout;
    38 
    39     /**
    40      * @var string
    41      */
    42     private $host = 'api.maxmind.com';
    43 
    44     /**
    45      * @var bool
    46      */
    47     private $useHttps = true;
    48 
    49     /**
    50      * @var RequestFactory
    51      */
    52     private $httpRequestFactory;
    53 
    54     /**
    55      * @var string
    56      */
    57     private $licenseKey;
    58 
    59     /**
    60      * @var string|null
    61      */
    62     private $proxy;
    63 
    64     /**
    65      * @var float|null
    66      */
    67     private $timeout;
    68 
    69     /**
    70      * @var string
    71      */
    72     private $userAgentPrefix;
    73 
    74     /**
    75      * @var int
    76      */
    77     private $accountId;
    78 
    79     /**
    80      * @param int    $accountId  your MaxMind account ID
    81      * @param string $licenseKey your MaxMind license key
    82      * @param array  $options    an array of options. Possible keys:
    83      *                           * `host` - The host to use when connecting to the web service.
    84      *                           * `useHttps` - A boolean flag for sending the request via https.(True by default)
    85      *                           * `userAgent` - The prefix of the User-Agent to use in the request.
    86      *                           * `caBundle` - The bundle of CA root certificates to use in the request.
    87      *                           * `connectTimeout` - The connect timeout to use for the request.
    88      *                           * `timeout` - The timeout to use for the request.
    89      *                           * `proxy` - The HTTP proxy to use. May include a schema, port,
    90      *                           username, and password, e.g., `http://username:password@127.0.0.1:10`.
    91      */
    92     public function __construct(
    93         int $accountId,
    94         string $licenseKey,
    95         array $options = []
    96     ) {
    97         $this->accountId = $accountId;
    98         $this->licenseKey = $licenseKey;
    99 
    100         $this->httpRequestFactory = isset($options['httpRequestFactory'])
    101             ? $options['httpRequestFactory']
    102             : new RequestFactory();
    103 
    104         if (isset($options['host'])) {
    105             $this->host = $options['host'];
    106         }
    107         if (isset($options['useHttps'])) {
    108             $this->useHttps = $options['useHttps'];
    109         }
    110         if (isset($options['userAgent'])) {
    111             $this->userAgentPrefix = $options['userAgent'] . ' ';
    112         }
    113 
    114         $this->caBundle = isset($options['caBundle']) ?
    115             $this->caBundle = $options['caBundle'] : $this->getCaBundle();
    116 
    117         if (isset($options['connectTimeout'])) {
    118             $this->connectTimeout = $options['connectTimeout'];
    119         }
    120         if (isset($options['timeout'])) {
    121             $this->timeout = $options['timeout'];
    122         }
    123 
    124         if (isset($options['proxy'])) {
    125             $this->proxy = $options['proxy'];
    126         }
    127     }
    128 
    129     /**
    130      * @param string $service name of the service querying
    131      * @param string $path    the URI path to use
    132      * @param array  $input   the data to be posted as JSON
    133      *
    134      * @throws InvalidInputException      when the request has missing or invalid
    135      *                                    data
    136      * @throws AuthenticationException    when there is an issue authenticating the
    137      *                                    request
    138      * @throws InsufficientFundsException when your account is out of funds
    139      * @throws InvalidRequestException    when the request is invalid for some
    140      *                                    other reason, e.g., invalid JSON in the POST.
    141      * @throws HttpException              when an unexpected HTTP error occurs
    142      * @throws WebServiceException        when some other error occurs. This also
    143      *                                    serves as the base class for the above exceptions.
    144      *
    145      * @return array|null The decoded content of a successful response
    146      */
    147     public function post(string $service, string $path, array $input): ?array
    148     {
    149         $requestBody = json_encode($input);
    150         if ($requestBody === false) {
    151             throw new InvalidInputException(
    152                 'Error encoding input as JSON: '
    153                 . $this->jsonErrorDescription()
    154             );
    155         }
    156 
    157         $request = $this->createRequest(
    158             $path,
    159             ['Content-Type: application/json']
    160         );
    161 
    162         [$statusCode, $contentType, $responseBody] = $request->post($requestBody);
    163 
    164         return $this->handleResponse(
    165             $statusCode,
    166             $contentType,
    167             $responseBody,
    168             $service,
    169             $path
    170         );
    171     }
    172 
    173     public function get(string $service, string $path): ?array
    174     {
    175         $request = $this->createRequest(
    176             $path
    177         );
    178 
    179         [$statusCode, $contentType, $responseBody] = $request->get();
    180 
    181         return $this->handleResponse(
    182             $statusCode,
    183             $contentType,
    184             $responseBody,
    185             $service,
    186             $path
    187         );
    188     }
    189 
    190     private function userAgent(): string
    191     {
    192         $curlVersion = curl_version();
    193 
    194         return $this->userAgentPrefix . 'MaxMind-WS-API/' . self::VERSION . ' PHP/' . \PHP_VERSION .
    195            ' curl/' . $curlVersion['version'];
    196     }
    197 
    198     private function createRequest(string $path, array $headers = []): Http\Request
    199     {
    200         array_push(
    201             $headers,
    202             'Authorization: Basic '
    203             . base64_encode($this->accountId . ':' . $this->licenseKey),
    204             'Accept: application/json'
    205         );
    206 
    207         return $this->httpRequestFactory->request(
    208             $this->urlFor($path),
    209             [
    210                 'caBundle' => $this->caBundle,
    211                 'connectTimeout' => $this->connectTimeout,
    212                 'headers' => $headers,
    213                 'proxy' => $this->proxy,
    214                 'timeout' => $this->timeout,
    215                 'userAgent' => $this->userAgent(),
    216             ]
    217         );
    218     }
    219 
    220     /**
    221      * @param int         $statusCode   the HTTP status code of the response
    222      * @param string|null $contentType  the Content-Type of the response
    223      * @param string|null $responseBody the response body
    224      * @param string      $service      the name of the service
    225      * @param string      $path         the path used in the request
    226      *
    227      * @throws AuthenticationException    when there is an issue authenticating the
    228      *                                    request
    229      * @throws InsufficientFundsException when your account is out of funds
    230      * @throws InvalidRequestException    when the request is invalid for some
    231      *                                    other reason, e.g., invalid JSON in the POST.
    232      * @throws HttpException              when an unexpected HTTP error occurs
    233      * @throws WebServiceException        when some other error occurs. This also
    234      *                                    serves as the base class for the above exceptions
    235      *
    236      * @return array|null The decoded content of a successful response
    237      */
    238     private function handleResponse(
    239         int $statusCode,
    240         ?string $contentType,
    241         ?string $responseBody,
    242         string $service,
    243         string $path
    244     ): ?array {
    245         if ($statusCode >= 400 && $statusCode <= 499) {
    246             $this->handle4xx($statusCode, $contentType, $responseBody, $service, $path);
    247         } elseif ($statusCode >= 500) {
    248             $this->handle5xx($statusCode, $service, $path);
    249         } elseif ($statusCode !== 200 && $statusCode !== 204) {
    250             $this->handleUnexpectedStatus($statusCode, $service, $path);
    251         }
    252 
    253         return $this->handleSuccess($statusCode, $responseBody, $service);
    254     }
    255 
    256     /**
    257      * @return string describing the JSON error
    258      */
    259     private function jsonErrorDescription(): string
    260     {
    261         $errno = json_last_error();
    262 
    263         switch ($errno) {
    264         case \JSON_ERROR_DEPTH:
    265             return 'The maximum stack depth has been exceeded.';
    266 
    267         case \JSON_ERROR_STATE_MISMATCH:
    268             return 'Invalid or malformed JSON.';
    269 
    270         case \JSON_ERROR_CTRL_CHAR:
    271             return 'Control character error.';
    272 
    273         case \JSON_ERROR_SYNTAX:
    274             return 'Syntax error.';
    275 
    276         case \JSON_ERROR_UTF8:
    277             return 'Malformed UTF-8 characters.';
    278 
    279         default:
    280             return "Other JSON error ($errno).";
    281         }
    282     }
    283 
    284     /**
    285      * @param string $path the path to use in the URL
    286      *
    287      * @return string the constructed URL
    288      */
    289     private function urlFor(string $path): string
    290     {
    291         return ($this->useHttps ? 'https://' : 'http://') . $this->host . $path;
    292     }
    293 
    294     /**
    295      * @param int         $statusCode  the HTTP status code
    296      * @param string|null $contentType the response content-type
    297      * @param string|null $body        the response body
    298      * @param string      $service     the service name
    299      * @param string      $path        the path used in the request
    300      *
    301      * @throws AuthenticationException
    302      * @throws HttpException
    303      * @throws InsufficientFundsException
    304      * @throws InvalidRequestException
    305      */
    306     private function handle4xx(
    307         int $statusCode,
    308         ?string $contentType,
    309         ?string $body,
    310         string $service,
    311         string $path
    312     ): void {
    313         if ($body === null || $body === '') {
    314             throw new HttpException(
    315                 "Received a $statusCode error for $service with no body",
    316                 $statusCode,
    317                 $this->urlFor($path)
    318             );
    319         }
    320         if ($contentType === null || !strstr($contentType, 'json')) {
    321             throw new HttpException(
    322                 "Received a $statusCode error for $service with " .
    323                 'the following body: ' . $body,
    324                 $statusCode,
    325                 $this->urlFor($path)
    326             );
    327         }
    328 
    329         $message = json_decode($body, true);
    330         if ($message === null) {
    331             throw new HttpException(
    332                 "Received a $statusCode error for $service but could " .
    333                 'not decode the response as JSON: '
    334                 . $this->jsonErrorDescription() . ' Body: ' . $body,
    335                 $statusCode,
    336                 $this->urlFor($path)
    337             );
    338         }
    339 
    340         if (!isset($message['code']) || !isset($message['error'])) {
    341             throw new HttpException(
    342                 'Error response contains JSON but it does not ' .
    343                 'specify code or error keys: ' . $body,
    344                 $statusCode,
    345                 $this->urlFor($path)
    346             );
    347         }
    348 
    349         $this->handleWebServiceError(
    350             $message['error'],
    351             $message['code'],
    352             $statusCode,
    353             $path
    354         );
    355     }
    356 
    357     /**
    358      * @param string $message    the error message from the web service
    359      * @param string $code       the error code from the web service
    360      * @param int    $statusCode the HTTP status code
    361      * @param string $path       the path used in the request
    362      *
    363      * @throws AuthenticationException
    364      * @throws InvalidRequestException
    365      * @throws InsufficientFundsException
    366      */
    367     private function handleWebServiceError(
    368         string $message,
    369         string $code,
    370         int $statusCode,
    371         string $path
    372     ): void {
    373         switch ($code) {
    374         case 'IP_ADDRESS_NOT_FOUND':
    375         case 'IP_ADDRESS_RESERVED':
    376             throw new IpAddressNotFoundException(
    377                 $message,
    378                 $code,
    379                 $statusCode,
    380                 $this->urlFor($path)
    381             );
    382 
    383         case 'ACCOUNT_ID_REQUIRED':
    384         case 'ACCOUNT_ID_UNKNOWN':
    385         case 'AUTHORIZATION_INVALID':
    386         case 'LICENSE_KEY_REQUIRED':
    387         case 'USER_ID_REQUIRED':
    388         case 'USER_ID_UNKNOWN':
    389             throw new AuthenticationException(
    390                 $message,
    391                 $code,
    392                 $statusCode,
    393                 $this->urlFor($path)
    394             );
    395 
    396         case 'OUT_OF_QUERIES':
    397         case 'INSUFFICIENT_FUNDS':
    398             throw new InsufficientFundsException(
    399                 $message,
    400                 $code,
    401                 $statusCode,
    402                 $this->urlFor($path)
    403             );
    404 
    405         case 'PERMISSION_REQUIRED':
    406             throw new PermissionRequiredException(
    407                 $message,
    408                 $code,
    409                 $statusCode,
    410                 $this->urlFor($path)
    411             );
    412 
    413         default:
    414             throw new InvalidRequestException(
    415                 $message,
    416                 $code,
    417                 $statusCode,
    418                 $this->urlFor($path)
    419             );
    420         }
    421     }
    422 
    423     /**
    424      * @param int    $statusCode the HTTP status code
    425      * @param string $service    the service name
    426      * @param string $path       the URI path used in the request
    427      *
    428      * @throws HttpException
    429      */
    430     private function handle5xx(int $statusCode, string $service, string $path): void
    431     {
    432         throw new HttpException(
    433             "Received a server error ($statusCode) for $service",
    434             $statusCode,
    435             $this->urlFor($path)
    436         );
    437     }
    438 
    439     /**
    440      * @param int    $statusCode the HTTP status code
    441      * @param string $service    the service name
    442      * @param string $path       the URI path used in the request
    443      *
    444      * @throws HttpException
    445      */
    446     private function handleUnexpectedStatus(int $statusCode, string $service, string $path): void
    447     {
    448         throw new HttpException(
    449             'Received an unexpected HTTP status ' .
    450             "($statusCode) for $service",
    451             $statusCode,
    452             $this->urlFor($path)
    453         );
    454     }
    455 
    456     /**
    457      * @param int         $statusCode the HTTP status code
    458      * @param string|null $body       the successful request body
    459      * @param string      $service    the service name
    460      *
    461      * @throws WebServiceException if a response body is included but not
    462      *                             expected, or is not expected but not
    463      *                             included, or is expected and included
    464      *                             but cannot be decoded as JSON
    465      *
    466      * @return array|null the decoded request body
    467      */
    468     private function handleSuccess(int $statusCode, ?string $body, string $service): ?array
    469     {
    470         // A 204 should have no response body
    471         if ($statusCode === 204) {
    472             if ($body !== null && $body !== '') {
    473                 throw new WebServiceException(
    474                     "Received a 204 response for $service along with an " .
    475                     "unexpected HTTP body: $body"
    476                 );
    477             }
    478 
    479             return null;
    480         }
    481 
    482         // A 200 should have a valid JSON body
    483         if ($body === null || $body === '') {
    484             throw new WebServiceException(
    485                 "Received a 200 response for $service but did not " .
    486                 'receive a HTTP body.'
    487             );
    488         }
    489 
    490         $decodedContent = json_decode($body, true);
    491         if ($decodedContent === null) {
    492             throw new WebServiceException(
    493                 "Received a 200 response for $service but could " .
    494                 'not decode the response as JSON: '
    495                 . $this->jsonErrorDescription() . ' Body: ' . $body
    496             );
    497         }
    498 
    499         return $decodedContent;
    500     }
    501 
    502     private function getCaBundle(): ?string
    503     {
    504         $curlVersion = curl_version();
    505 
    506         // On OS X, when the SSL version is "SecureTransport", the system's
    507         // keychain will be used.
    508         if ($curlVersion['ssl_version'] === 'SecureTransport') {
    509             return null;
    510         }
    511         $cert = CaBundle::getSystemCaRootBundlePath();
    512 
    513         // Check if the cert is inside a phar. If so, we need to copy the cert
    514         // to a temp file so that curl can see it.
    515         if (substr($cert, 0, 7) === 'phar://') {
    516             $tempDir = sys_get_temp_dir();
    517             $newCert = tempnam($tempDir, 'geoip2-');
    518             if ($newCert === false) {
    519                 throw new \RuntimeException(
    520                     "Unable to create temporary file in $tempDir"
    521                 );
    522             }
    523             if (!copy($cert, $newCert)) {
    524                 throw new \RuntimeException(
    525                     "Could not copy $cert to $newCert: "
    526                     . var_export(error_get_last(), true)
    527                 );
    528             }
    529 
    530             // We use a shutdown function rather than the destructor as the
    531             // destructor isn't called on a fatal error such as an uncaught
    532             // exception.
    533             register_shutdown_function(
    534                 function () use ($newCert) {
    535                     unlink($newCert);
    536                 }
    537             );
    538             $cert = $newCert;
    539         }
    540         if (!file_exists($cert)) {
    541             throw new \RuntimeException("CA cert does not exist at $cert");
    542         }
    543 
    544         return $cert;
    545     }
     25class Client {
     26
     27    public const VERSION = '0.2.0';
     28
     29    /**
     30     * @var string|null
     31     */
     32    private $caBundle;
     33
     34    /**
     35     * @var float|null
     36     */
     37    private $connectTimeout;
     38
     39    /**
     40     * @var string
     41     */
     42    private $host = 'api.maxmind.com';
     43
     44    /**
     45     * @var bool
     46     */
     47    private $useHttps = true;
     48
     49    /**
     50     * @var RequestFactory
     51     */
     52    private $httpRequestFactory;
     53
     54    /**
     55     * @var string
     56     */
     57    private $licenseKey;
     58
     59    /**
     60     * @var string|null
     61     */
     62    private $proxy;
     63
     64    /**
     65     * @var float|null
     66     */
     67    private $timeout;
     68
     69    /**
     70     * @var string
     71     */
     72    private $userAgentPrefix;
     73
     74    /**
     75     * @var int
     76     */
     77    private $accountId;
     78
     79    /**
     80     * @param int    $accountId  your MaxMind account ID
     81     * @param string $licenseKey your MaxMind license key
     82     * @param array  $options    an array of options. Possible keys:
     83     *                           * `host` - The host to use when connecting to the web service.
     84     *                           * `useHttps` - A boolean flag for sending the request via https.(True by default)
     85     *                           * `userAgent` - The prefix of the User-Agent to use in the request.
     86     *                           * `caBundle` - The bundle of CA root certificates to use in the request.
     87     *                           * `connectTimeout` - The connect timeout to use for the request.
     88     *                           * `timeout` - The timeout to use for the request.
     89     *                           * `proxy` - The HTTP proxy to use. May include a schema, port,
     90     *                           username, and password, e.g., `http://username:password@127.0.0.1:10`.
     91     */
     92    public function __construct(
     93        int $accountId,
     94        string $licenseKey,
     95        array $options = array()
     96    ) {
     97        $this->accountId  = $accountId;
     98        $this->licenseKey = $licenseKey;
     99
     100        $this->httpRequestFactory = isset( $options['httpRequestFactory'] )
     101            ? $options['httpRequestFactory']
     102            : new RequestFactory();
     103
     104        if ( isset( $options['host'] ) ) {
     105            $this->host = $options['host'];
     106        }
     107        if ( isset( $options['useHttps'] ) ) {
     108            $this->useHttps = $options['useHttps'];
     109        }
     110        if ( isset( $options['userAgent'] ) ) {
     111            $this->userAgentPrefix = $options['userAgent'] . ' ';
     112        }
     113
     114        $this->caBundle     = isset( $options['caBundle'] ) ?
     115            $this->caBundle = $options['caBundle'] : $this->getCaBundle();
     116
     117        if ( isset( $options['connectTimeout'] ) ) {
     118            $this->connectTimeout = $options['connectTimeout'];
     119        }
     120        if ( isset( $options['timeout'] ) ) {
     121            $this->timeout = $options['timeout'];
     122        }
     123
     124        if ( isset( $options['proxy'] ) ) {
     125            $this->proxy = $options['proxy'];
     126        }
     127    }
     128
     129    /**
     130     * @param string $service name of the service querying
     131     * @param string $path    the URI path to use
     132     * @param array  $input   the data to be posted as JSON
     133     *
     134     * @throws InvalidInputException      when the request has missing or invalid
     135     *                                    data
     136     * @throws AuthenticationException    when there is an issue authenticating the
     137     *                                    request
     138     * @throws InsufficientFundsException when your account is out of funds
     139     * @throws InvalidRequestException    when the request is invalid for some
     140     *                                    other reason, e.g., invalid JSON in the POST.
     141     * @throws HttpException              when an unexpected HTTP error occurs
     142     * @throws WebServiceException        when some other error occurs. This also
     143     *                                    serves as the base class for the above exceptions.
     144     *
     145     * @return array|null The decoded content of a successful response
     146     */
     147    public function post( string $service, string $path, array $input ): ?array {
     148        $requestBody = json_encode( $input );
     149        if ( $requestBody === false ) {
     150            throw new InvalidInputException(
     151                'Error encoding input as JSON: '
     152                . $this->jsonErrorDescription()
     153            );
     154        }
     155
     156        $request = $this->createRequest(
     157            $path,
     158            array( 'Content-Type: application/json' )
     159        );
     160
     161        [$statusCode, $contentType, $responseBody] = $request->post( $requestBody );
     162
     163        return $this->handleResponse(
     164            $statusCode,
     165            $contentType,
     166            $responseBody,
     167            $service,
     168            $path
     169        );
     170    }
     171
     172    public function get( string $service, string $path ): ?array {
     173        $request = $this->createRequest(
     174            $path
     175        );
     176
     177        [$statusCode, $contentType, $responseBody] = $request->get();
     178
     179        return $this->handleResponse(
     180            $statusCode,
     181            $contentType,
     182            $responseBody,
     183            $service,
     184            $path
     185        );
     186    }
     187
     188    private function userAgent(): string {
     189        $curlVersion = curl_version();
     190
     191        return $this->userAgentPrefix . 'MaxMind-WS-API/' . self::VERSION . ' PHP/' . \PHP_VERSION .
     192           ' curl/' . $curlVersion['version'];
     193    }
     194
     195    private function createRequest( string $path, array $headers = array() ): Http\Request {
     196        array_push(
     197            $headers,
     198            'Authorization: Basic '
     199            . base64_encode( $this->accountId . ':' . $this->licenseKey ),
     200            'Accept: application/json'
     201        );
     202
     203        return $this->httpRequestFactory->request(
     204            $this->urlFor( $path ),
     205            array(
     206                'caBundle'       => $this->caBundle,
     207                'connectTimeout' => $this->connectTimeout,
     208                'headers'        => $headers,
     209                'proxy'          => $this->proxy,
     210                'timeout'        => $this->timeout,
     211                'userAgent'      => $this->userAgent(),
     212            )
     213        );
     214    }
     215
     216    /**
     217     * @param int         $statusCode   the HTTP status code of the response
     218     * @param string|null $contentType  the Content-Type of the response
     219     * @param string|null $responseBody the response body
     220     * @param string      $service      the name of the service
     221     * @param string      $path         the path used in the request
     222     *
     223     * @throws AuthenticationException    when there is an issue authenticating the
     224     *                                    request
     225     * @throws InsufficientFundsException when your account is out of funds
     226     * @throws InvalidRequestException    when the request is invalid for some
     227     *                                    other reason, e.g., invalid JSON in the POST.
     228     * @throws HttpException              when an unexpected HTTP error occurs
     229     * @throws WebServiceException        when some other error occurs. This also
     230     *                                    serves as the base class for the above exceptions
     231     *
     232     * @return array|null The decoded content of a successful response
     233     */
     234    private function handleResponse(
     235        int $statusCode,
     236        ?string $contentType,
     237        ?string $responseBody,
     238        string $service,
     239        string $path
     240    ): ?array {
     241        if ( $statusCode >= 400 && $statusCode <= 499 ) {
     242            $this->handle4xx( $statusCode, $contentType, $responseBody, $service, $path );
     243        } elseif ( $statusCode >= 500 ) {
     244            $this->handle5xx( $statusCode, $service, $path );
     245        } elseif ( $statusCode !== 200 && $statusCode !== 204 ) {
     246            $this->handleUnexpectedStatus( $statusCode, $service, $path );
     247        }
     248
     249        return $this->handleSuccess( $statusCode, $responseBody, $service );
     250    }
     251
     252    /**
     253     * @return string describing the JSON error
     254     */
     255    private function jsonErrorDescription(): string {
     256        $errno = json_last_error();
     257
     258        switch ( $errno ) {
     259            case \JSON_ERROR_DEPTH:
     260                return 'The maximum stack depth has been exceeded.';
     261
     262            case \JSON_ERROR_STATE_MISMATCH:
     263                return 'Invalid or malformed JSON.';
     264
     265            case \JSON_ERROR_CTRL_CHAR:
     266                return 'Control character error.';
     267
     268            case \JSON_ERROR_SYNTAX:
     269                return 'Syntax error.';
     270
     271            case \JSON_ERROR_UTF8:
     272                return 'Malformed UTF-8 characters.';
     273
     274            default:
     275                return "Other JSON error ($errno).";
     276        }
     277    }
     278
     279    /**
     280     * @param string $path the path to use in the URL
     281     *
     282     * @return string the constructed URL
     283     */
     284    private function urlFor( string $path ): string {
     285        return ( $this->useHttps ? 'https://' : 'http://' ) . $this->host . $path;
     286    }
     287
     288    /**
     289     * @param int         $statusCode  the HTTP status code
     290     * @param string|null $contentType the response content-type
     291     * @param string|null $body        the response body
     292     * @param string      $service     the service name
     293     * @param string      $path        the path used in the request
     294     *
     295     * @throws AuthenticationException
     296     * @throws HttpException
     297     * @throws InsufficientFundsException
     298     * @throws InvalidRequestException
     299     */
     300    private function handle4xx(
     301        int $statusCode,
     302        ?string $contentType,
     303        ?string $body,
     304        string $service,
     305        string $path
     306    ): void {
     307        if ( $body === null || $body === '' ) {
     308            throw new HttpException(
     309                "Received a $statusCode error for $service with no body",
     310                $statusCode,
     311                $this->urlFor( $path )
     312            );
     313        }
     314        if ( $contentType === null || ! strstr( $contentType, 'json' ) ) {
     315            throw new HttpException(
     316                "Received a $statusCode error for $service with " .
     317                'the following body: ' . $body,
     318                $statusCode,
     319                $this->urlFor( $path )
     320            );
     321        }
     322
     323        $message = json_decode( $body, true );
     324        if ( $message === null ) {
     325            throw new HttpException(
     326                "Received a $statusCode error for $service but could " .
     327                'not decode the response as JSON: '
     328                . $this->jsonErrorDescription() . ' Body: ' . $body,
     329                $statusCode,
     330                $this->urlFor( $path )
     331            );
     332        }
     333
     334        if ( ! isset( $message['code'] ) || ! isset( $message['error'] ) ) {
     335            throw new HttpException(
     336                'Error response contains JSON but it does not ' .
     337                'specify code or error keys: ' . $body,
     338                $statusCode,
     339                $this->urlFor( $path )
     340            );
     341        }
     342
     343        $this->handleWebServiceError(
     344            $message['error'],
     345            $message['code'],
     346            $statusCode,
     347            $path
     348        );
     349    }
     350
     351    /**
     352     * @param string $message    the error message from the web service
     353     * @param string $code       the error code from the web service
     354     * @param int    $statusCode the HTTP status code
     355     * @param string $path       the path used in the request
     356     *
     357     * @throws AuthenticationException
     358     * @throws InvalidRequestException
     359     * @throws InsufficientFundsException
     360     */
     361    private function handleWebServiceError(
     362        string $message,
     363        string $code,
     364        int $statusCode,
     365        string $path
     366    ): void {
     367        switch ( $code ) {
     368            case 'IP_ADDRESS_NOT_FOUND':
     369            case 'IP_ADDRESS_RESERVED':
     370                throw new IpAddressNotFoundException(
     371                    $message,
     372                    $code,
     373                    $statusCode,
     374                    $this->urlFor( $path )
     375                );
     376
     377            case 'ACCOUNT_ID_REQUIRED':
     378            case 'ACCOUNT_ID_UNKNOWN':
     379            case 'AUTHORIZATION_INVALID':
     380            case 'LICENSE_KEY_REQUIRED':
     381            case 'USER_ID_REQUIRED':
     382            case 'USER_ID_UNKNOWN':
     383                throw new AuthenticationException(
     384                    $message,
     385                    $code,
     386                    $statusCode,
     387                    $this->urlFor( $path )
     388                );
     389
     390            case 'OUT_OF_QUERIES':
     391            case 'INSUFFICIENT_FUNDS':
     392                throw new InsufficientFundsException(
     393                    $message,
     394                    $code,
     395                    $statusCode,
     396                    $this->urlFor( $path )
     397                );
     398
     399            case 'PERMISSION_REQUIRED':
     400                throw new PermissionRequiredException(
     401                    $message,
     402                    $code,
     403                    $statusCode,
     404                    $this->urlFor( $path )
     405                );
     406
     407            default:
     408                throw new InvalidRequestException(
     409                    $message,
     410                    $code,
     411                    $statusCode,
     412                    $this->urlFor( $path )
     413                );
     414        }
     415    }
     416
     417    /**
     418     * @param int    $statusCode the HTTP status code
     419     * @param string $service    the service name
     420     * @param string $path       the URI path used in the request
     421     *
     422     * @throws HttpException
     423     */
     424    private function handle5xx( int $statusCode, string $service, string $path ): void {
     425        throw new HttpException(
     426            "Received a server error ($statusCode) for $service",
     427            $statusCode,
     428            $this->urlFor( $path )
     429        );
     430    }
     431
     432    /**
     433     * @param int    $statusCode the HTTP status code
     434     * @param string $service    the service name
     435     * @param string $path       the URI path used in the request
     436     *
     437     * @throws HttpException
     438     */
     439    private function handleUnexpectedStatus( int $statusCode, string $service, string $path ): void {
     440        throw new HttpException(
     441            'Received an unexpected HTTP status ' .
     442            "($statusCode) for $service",
     443            $statusCode,
     444            $this->urlFor( $path )
     445        );
     446    }
     447
     448    /**
     449     * @param int         $statusCode the HTTP status code
     450     * @param string|null $body       the successful request body
     451     * @param string      $service    the service name
     452     *
     453     * @throws WebServiceException if a response body is included but not
     454     *                             expected, or is not expected but not
     455     *                             included, or is expected and included
     456     *                             but cannot be decoded as JSON
     457     *
     458     * @return array|null the decoded request body
     459     */
     460    private function handleSuccess( int $statusCode, ?string $body, string $service ): ?array {
     461        // A 204 should have no response body
     462        if ( $statusCode === 204 ) {
     463            if ( $body !== null && $body !== '' ) {
     464                throw new WebServiceException(
     465                    "Received a 204 response for $service along with an " .
     466                    "unexpected HTTP body: $body"
     467                );
     468            }
     469
     470            return null;
     471        }
     472
     473        // A 200 should have a valid JSON body
     474        if ( $body === null || $body === '' ) {
     475            throw new WebServiceException(
     476                "Received a 200 response for $service but did not " .
     477                'receive a HTTP body.'
     478            );
     479        }
     480
     481        $decodedContent = json_decode( $body, true );
     482        if ( $decodedContent === null ) {
     483            throw new WebServiceException(
     484                "Received a 200 response for $service but could " .
     485                'not decode the response as JSON: '
     486                . $this->jsonErrorDescription() . ' Body: ' . $body
     487            );
     488        }
     489
     490        return $decodedContent;
     491    }
     492
     493    private function getCaBundle(): ?string {
     494        $curlVersion = curl_version();
     495
     496        // On OS X, when the SSL version is "SecureTransport", the system's
     497        // keychain will be used.
     498        if ( $curlVersion['ssl_version'] === 'SecureTransport' ) {
     499            return null;
     500        }
     501        $cert = CaBundle::getSystemCaRootBundlePath();
     502
     503        // Check if the cert is inside a phar. If so, we need to copy the cert
     504        // to a temp file so that curl can see it.
     505        if ( substr( $cert, 0, 7 ) === 'phar://' ) {
     506            $tempDir = sys_get_temp_dir();
     507            $newCert = tempnam( $tempDir, 'geoip2-' );
     508            if ( $newCert === false ) {
     509                throw new \RuntimeException(
     510                    "Unable to create temporary file in $tempDir"
     511                );
     512            }
     513            if ( ! copy( $cert, $newCert ) ) {
     514                throw new \RuntimeException(
     515                    "Could not copy $cert to $newCert: "
     516                    . var_export( error_get_last(), true )
     517                );
     518            }
     519
     520            // We use a shutdown function rather than the destructor as the
     521            // destructor isn't called on a fatal error such as an uncaught
     522            // exception.
     523            register_shutdown_function(
     524                function () use ( $newCert ) {
     525                    unlink( $newCert );
     526                }
     527            );
     528            $cert = $newCert;
     529        }
     530        if ( ! file_exists( $cert ) ) {
     531            throw new \RuntimeException( "CA cert does not exist at $cert" );
     532        }
     533
     534        return $cert;
     535    }
    546536}
  • termageddon-usercentrics/trunk/vendor/maxmind/web-service-common/src/WebService/Http/CurlRequest.php

    r2771752 r3160131  
    1212 * @internal
    1313 */
    14 class CurlRequest implements Request
    15 {
    16     /**
    17      * @var \CurlHandle
    18      */
    19     private $ch;
     14class CurlRequest implements Request {
    2015
    21     /**
    22      * @var string
    23     */
    24     private $url;
     16    /**
     17     * @var \CurlHandle
     18    */
     19    private $ch;
    2520
    26     /**
    27      * @var array
    28     */
    29     private $options;
     21    /**
     22     * @var string
     23    */
     24    private $url;
    3025
    31     public function __construct(string $url, array $options)
    32     {
    33         $this->url = $url;
    34         $this->options = $options;
    35         $this->ch = $options['curlHandle'];
    36     }
     26    /**
     27     * @var array
     28     */
     29    private $options;
    3730
    38     /**
    39      * @throws HttpException
    40      */
    41     public function post(string $body): array
    42     {
    43         $curl = $this->createCurl();
     31    public function __construct( string $url, array $options ) {
     32        $this->url     = $url;
     33        $this->options = $options;
     34        $this->ch      = $options['curlHandle'];
     35    }
    4436
    45         curl_setopt($curl, \CURLOPT_POST, true);
    46         curl_setopt($curl, \CURLOPT_POSTFIELDS, $body);
     37    /**
     38     * @throws HttpException
     39     */
     40    public function post( string $body ): array {
     41        $curl = $this->createCurl();
    4742
    48         return $this->execute($curl);
    49     }
     43        curl_setopt( $curl, \CURLOPT_POST, true );
     44        curl_setopt( $curl, \CURLOPT_POSTFIELDS, $body );
    5045
    51     public function get(): array
    52     {
    53         $curl = $this->createCurl();
     46        return $this->execute( $curl );
     47    }
    5448
    55         curl_setopt($curl, \CURLOPT_HTTPGET, true);
     49    public function get(): array {
     50        $curl = $this->createCurl();
    5651
    57         return $this->execute($curl);
    58     }
     52        curl_setopt( $curl, \CURLOPT_HTTPGET, true );
    5953
    60     /**
    61      * @return \CurlHandle
    62      */
    63     private function createCurl()
    64     {
    65         curl_reset($this->ch);
     54        return $this->execute( $curl );
     55    }
    6656
    67         $opts = [];
    68         $opts[\CURLOPT_URL] = $this->url;
     57    /**
     58     * @return \CurlHandle
     59     */
     60    private function createCurl() {
     61        curl_reset( $this->ch );
    6962
    70         if (!empty($this->options['caBundle'])) {
    71             $opts[\CURLOPT_CAINFO] = $this->options['caBundle'];
    72         }
     63        $opts                 = array();
     64        $opts[ \CURLOPT_URL ] = $this->url;
    7365
    74         $opts[\CURLOPT_ENCODING] = '';
    75         $opts[\CURLOPT_SSL_VERIFYHOST] = 2;
    76         $opts[\CURLOPT_FOLLOWLOCATION] = false;
    77         $opts[\CURLOPT_SSL_VERIFYPEER] = true;
    78         $opts[\CURLOPT_RETURNTRANSFER] = true;
     66        if ( ! empty( $this->options['caBundle'] ) ) {
     67            $opts[ \CURLOPT_CAINFO ] = $this->options['caBundle'];
     68        }
    7969
    80         $opts[\CURLOPT_HTTPHEADER] = $this->options['headers'];
    81         $opts[\CURLOPT_USERAGENT] = $this->options['userAgent'];
    82         $opts[\CURLOPT_PROXY] = $this->options['proxy'];
     70        $opts[ \CURLOPT_ENCODING ]       = '';
     71        $opts[ \CURLOPT_SSL_VERIFYHOST ] = 2;
     72        $opts[ \CURLOPT_FOLLOWLOCATION ] = false;
     73        $opts[ \CURLOPT_SSL_VERIFYPEER ] = true;
     74        $opts[ \CURLOPT_RETURNTRANSFER ] = true;
    8375
    84         // The defined()s are here as the *_MS opts are not available on older
    85         // cURL versions
    86         $connectTimeout = $this->options['connectTimeout'];
    87         if (\defined('CURLOPT_CONNECTTIMEOUT_MS')) {
    88             $opts[\CURLOPT_CONNECTTIMEOUT_MS] = ceil($connectTimeout * 1000);
    89         } else {
    90             $opts[\CURLOPT_CONNECTTIMEOUT] = ceil($connectTimeout);
    91         }
     76        $opts[ \CURLOPT_HTTPHEADER ] = $this->options['headers'];
     77        $opts[ \CURLOPT_USERAGENT ]  = $this->options['userAgent'];
     78        $opts[ \CURLOPT_PROXY ]      = $this->options['proxy'];
    9279
    93         $timeout = $this->options['timeout'];
    94         if (\defined('CURLOPT_TIMEOUT_MS')) {
    95             $opts[\CURLOPT_TIMEOUT_MS] = ceil($timeout * 1000);
    96         } else {
    97             $opts[\CURLOPT_TIMEOUT] = ceil($timeout);
    98         }
     80        // The defined()s are here as the *_MS opts are not available on older
     81        // cURL versions
     82        $connectTimeout = $this->options['connectTimeout'];
     83        if ( \defined( 'CURLOPT_CONNECTTIMEOUT_MS' ) ) {
     84            $opts[ \CURLOPT_CONNECTTIMEOUT_MS ] = ceil( $connectTimeout * 1000 );
     85        } else {
     86            $opts[ \CURLOPT_CONNECTTIMEOUT ] = ceil( $connectTimeout );
     87        }
    9988
    100         curl_setopt_array($this->ch, $opts);
     89        $timeout = $this->options['timeout'];
     90        if ( \defined( 'CURLOPT_TIMEOUT_MS' ) ) {
     91            $opts[ \CURLOPT_TIMEOUT_MS ] = ceil( $timeout * 1000 );
     92        } else {
     93            $opts[ \CURLOPT_TIMEOUT ] = ceil( $timeout );
     94        }
    10195
    102         return $this->ch;
    103     }
     96        curl_setopt_array( $this->ch, $opts );
    10497
    105     /**
    106      * @param \CurlHandle $curl
    107      *
    108      * @throws HttpException
    109      */
    110     private function execute($curl): array
    111     {
    112         $body = curl_exec($curl);
    113         if ($errno = curl_errno($curl)) {
    114             $errorMessage = curl_error($curl);
     98        return $this->ch;
     99    }
    115100
    116             throw new HttpException(
    117                 "cURL error ({$errno}): {$errorMessage}",
    118                 0,
    119                 $this->url
    120             );
    121         }
     101    /**
     102     * @param \CurlHandle $curl
     103     *
     104     * @throws HttpException
     105     */
     106    private function execute( $curl ): array {
     107        $body = curl_exec( $curl );
     108        if ( $errno = curl_errno( $curl ) ) {
     109            $errorMessage = curl_error( $curl );
    122110
    123         $statusCode = curl_getinfo($curl, \CURLINFO_HTTP_CODE);
    124         $contentType = curl_getinfo($curl, \CURLINFO_CONTENT_TYPE);
     111            throw new HttpException(
     112                "cURL error ({$errno}): {$errorMessage}",
     113                0,
     114                $this->url
     115            );
     116        }
    125117
    126         return [
    127             $statusCode,
    128             // The PHP docs say "Content-Type: of the requested document. NULL
    129             // indicates server did not send valid Content-Type: header" for
    130             // CURLINFO_CONTENT_TYPE. However, it will return FALSE if no header
    131             // is set. To keep our types simple, we return null in this case.
    132             ($contentType === false ? null : $contentType),
    133             $body,
    134         ];
    135     }
     118        $statusCode  = curl_getinfo( $curl, \CURLINFO_HTTP_CODE );
     119        $contentType = curl_getinfo( $curl, \CURLINFO_CONTENT_TYPE );
     120
     121        return array(
     122            $statusCode,
     123            // The PHP docs say "Content-Type: of the requested document. NULL
     124            // indicates server did not send valid Content-Type: header" for
     125            // CURLINFO_CONTENT_TYPE. However, it will return FALSE if no header
     126            // is set. To keep our types simple, we return null in this case.
     127            ( $contentType === false ? null : $contentType ),
     128            $body,
     129        );
     130    }
    136131}
  • termageddon-usercentrics/trunk/vendor/maxmind/web-service-common/src/WebService/Http/Request.php

    r2771752 r3160131  
    1010 * @internal
    1111 */
    12 interface Request
    13 {
    14     public function __construct(string $url, array $options);
     12interface Request {
    1513
    16     public function post(string $body): array;
     14    public function __construct( string $url, array $options);
    1715
    18     public function get(): array;
     16    public function post( string $body): array;
     17
     18    public function get(): array;
    1919}
  • termageddon-usercentrics/trunk/vendor/maxmind/web-service-common/src/WebService/Http/RequestFactory.php

    r2771752 r3160131  
    1010 * @internal
    1111 */
    12 class RequestFactory
    13 {
    14     /**
    15      * Keep the cURL resource here, so that if there are multiple API requests
    16      * done the connection is kept alive, SSL resumption can be used
    17      * etcetera.
    18      *
    19      * @var \CurlHandle|null
    20      */
    21     private $ch;
     12class RequestFactory {
    2213
    23     public function __destruct()
    24     {
    25         if (!empty($this->ch)) {
    26             curl_close($this->ch);
    27         }
    28     }
     14    /**
     15     * Keep the cURL resource here, so that if there are multiple API requests
     16     * done the connection is kept alive, SSL resumption can be used
     17     * etcetera.
     18     *
     19     * @var \CurlHandle|null
     20     */
     21    private $ch;
    2922
    30     /**
    31      * @return \CurlHandle
    32      */
    33     private function getCurlHandle()
    34     {
    35         if (empty($this->ch)) {
    36             $this->ch = curl_init();
    37         }
     23    public function __destruct() {
     24        if ( ! empty( $this->ch ) ) {
     25            curl_close( $this->ch );
     26        }
     27    }
    3828
    39         return $this->ch;
    40     }
     29    /**
     30     * @return \CurlHandle
     31     */
     32    private function getCurlHandle() {
     33        if ( empty( $this->ch ) ) {
     34            $this->ch = curl_init();
     35        }
    4136
    42     public function request(string $url, array $options): Request
    43     {
    44         $options['curlHandle'] = $this->getCurlHandle();
     37        return $this->ch;
     38    }
    4539
    46         return new CurlRequest($url, $options);
    47     }
     40    public function request( string $url, array $options ): Request {
     41        $options['curlHandle'] = $this->getCurlHandle();
     42
     43        return new CurlRequest( $url, $options );
     44    }
    4845}
Note: See TracChangeset for help on using the changeset viewer.