Plugin Directory

Changeset 1510336


Ignore:
Timestamp:
10/07/2016 09:17:53 PM (9 years ago)
Author:
davejesch
Message:

1.2.1 - Oct 7, 2016

  • Fix: Update collation on created table for some hosts.
  • Enhancement: Add checks for updates to add-ons via WPSiteSync.com site.
  • Fix: Sanitize password hash for encryption algorithms. (thanks Jonah W.)
  • Enhancement: Specify timeout for API calls.
  • Enhancement: Remove any error output interfering with JSON data in API calls.
  • Enhancement: Improve error handling/recovery on API calls.
  • Fix: Update checks for allowed post types. (thanks Cathy E.)
  • Enhancement: Improve UX for License Keys.
Location:
wpsitesynccontent
Files:
43 added
10 edited

Legend:

Unmodified
Added
Removed
  • wpsitesynccontent/trunk/classes/admin.php

    r1492115 r1510336  
    185185        echo '<div id="sync-success-msg">', __('Content successfully sent to Target system.', 'wpsitesynccontent'), '</div>';
    186186        if (!class_exists('WPSiteSync_Pull', FALSE))
    187                 echo '<div id="sync-pull-msg"><div style="color: #0085ba;">', __('Coming soon in Premium Membership!', 'wpsitesynccontent'), '</div></div>';
     187                echo '<div id="sync-pull-msg"><div style="color: #0085ba;">', __('Please activate the Pull extension.', 'wpsitesynccontent'), '</div></div>';
    188188        echo '</div>';
    189189
  • wpsitesynccontent/trunk/classes/apicontroller.php

    r1492115 r1510336  
    7070            $response->send();      // calls die()
    7171        }
     72
     73//SyncDebug::log(__METHOD__.'():' . __LINE__ . ' checking auth argument args=' . var_export($args, TRUE));
    7274        if (isset($args['auth']) && 0 === $args['auth']) {
    73 SyncDebug::log(__METHOD__.'() skipping authentication as per args');
     75//SyncDebug::log(__METHOD__.'() skipping authentication as per args');
    7476            $this->_auth = 0;
    7577        } else {
     
    7981                $user = $auth->check_credentials($response);
    8082                // check to see if credentials passed
     83//SyncDebug::log(__METHOD__.'():' . __LINE__ . ' auth failed ' . var_export($user, TRUE));
    8184                if ($response->has_errors())
    8285                    $response->send();
     
    8487        }
    8588
     89//SyncDebug::log(__METHOD__.'():' . __LINE__ . ' check action: ' . $action);
    8690        switch ($action) {
    8791        case '':
     
    283287
    284288        // do not allow the push if it's not a recognized post type
    285         if (NULL !== $post &&
    286             (!in_array($post->post_type, apply_filters('spectrom_sync_allowed_post_types', array('post', 'page'))))) {
    287 SyncDebug::log(' - checking post type: ' . $post->post_type);
     289        if (!in_array($post_data['post_type']/*$post->post_type*/, apply_filters('spectrom_sync_allowed_post_types', array('post', 'page')))) {
     290SyncDebug::log(' - checking post type: ' . $post_data['post_type']/*$post->post_type*/);
    288291            $response->error_code(SyncApiRequest::ERROR_INVALID_POST_TYPE);
    289292            return;
     
    301304                return;
    302305            }
    303             // fixup the parent post id with the Target's id value
     306            // fixup the Source's parent post id with the Target's id value
    304307SyncDebug::log(__METHOD__.'() setting parent post to #' . $parent_post->target_content_id);
    305308            $post_data['post_parent'] = intval($parent_post->target_content_id);
    306309        }
    307 
    308         // TODO: also check the post_type in the $post_data array
    309310
    310311        // change references to source URL to target URL
     
    321322//SyncDebug::log(' - has permission');
    322323                $target_post_id = $post_data['ID'] = $post->ID;
    323                 wp_update_post($post_data); // ;here;
     324                $res = wp_update_post($post_data, TRUE); // ;here;
     325                if (is_wp_error($res)) {
     326                    $response->error_code(SyncApiRequest::ERROR_CONTENT_UPDATE_FAILED, $res->get_error_message());
     327                }
    324328            } else {
    325329                $response->error_code(SyncApiRequest::ERROR_NO_PERMISSION);
  • wpsitesynccontent/trunk/classes/apirequest.php

    r1492115 r1510336  
    3131    const ERROR_INVALID_IMG_TYPE = 24;
    3232    const ERROR_POST_NOT_FOUND = 25;
     33    const ERROR_CONTENT_UPDATE_FAILED = 26;
    3334
    3435    const NOTICE_FILE_EXISTS = 1;
     
    141142        $remote_args['headers'][self::HEADER_SITE_KEY] = SyncOptions::get('site_key'); // $model->generate_site_key();
    142143//SyncDebug::log(__METHOD__.'() plugin sitekey=' . WPSiteSyncContent::get_option('site_key') . ' // option sitekey=' . SyncOptions::get('site_key'));
     144        if (!isset($remote_args['timeout']))
     145            $remote_args['timeout'] = 30;
    143146
    144147        // send data where it's going
     
    173176
    174177            // API request went through, check for error_code returned in JSON results
    175 
    176             $response->response = json_decode($request['body']);
     178            $request_body = $this->_adjust_response_body($request['body']);
     179//SyncDebug::log(__METHOD__.'():' . __LINE__ . ' response body: ' . $request_body); // $request['body']);
     180            $response->response = json_decode($request_body /*$request['body']*/);
    177181            // TODO: convert error/notice codes into strings at this point.
    178182SyncDebug::log(__METHOD__.'():' . __LINE__ . ' received response from Target for "' . $action . '":');
     
    262266        // API request successful. Return results to caller.
    263267        return $response;
     268    }
     269
     270    /**
     271     * Strips any error messages contained withing JSON response content
     272     * @param string $body The response body of a JSON API request
     273     * @return string The response body with any error messages stripped off
     274     */
     275    private function _adjust_response_body($body)
     276    {
     277        if ('{' !== $body[0]) {
     278            $pos = strpos($body, '{"error_code":');
     279            if (FALSE !== $pos)
     280                $body = substr($body, $pos);
     281            $pos = strpos($body, '"}}');
     282            if (FALSE !== $pos)
     283                $body = substr($body, 0, $pos + 3);
     284        }
     285        return $body;
    264286    }
    265287
     
    859881        case self::ERROR_INVALID_IMG_TYPE:      $error = __('The image uploaded is not a valid image type.', 'wpsitesynccontent'); break;
    860882        case self::ERROR_POST_NOT_FOUND:        $error = __('Requested post cannot be found.', 'wpsitesynccontent'); break;
     883        case self::ERROR_CONTENT_UPDATE_FAILED: $error = __('Content update on Target failed.', 'wpsitesynccontent'); break;
    861884
    862885        default:
  • wpsitesynccontent/trunk/classes/auth.php

    r1492115 r1510336  
    151151        $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
    152152        $cleartext = mcrypt_decrypt(MCRYPT_BLOWFISH, $key, $decoded, MCRYPT_MODE_ECB, $iv);
    153 //SyncDebug::log('  cleartext: ' . $cleartext);
     153//SyncDebug::log('  cleartext: ' . var_export($cleartext, TRUE));
     154        $cleartext = trim($cleartext, "\0");
     155//SyncDebug::log('  cleartext: ' . var_export($cleartext, TRUE));
    154156        return $cleartext;
    155157    }
  • wpsitesynccontent/trunk/classes/licensesettings.php

    r1451657 r1510336  
    5151                $field_id,                                  // field id
    5252                sprintf(__('%s License Key:', 'wpsitesynccontent'), $extension['name']),// title
    53                 array(&$this, 'render_license_field'),          // callback
     53                array($this, 'render_license_field'),           // callback
    5454                SyncSettings::SETTINGS_PAGE,                    // page
    5555                $section_id,                                    // section id
     
    6363            );
    6464        }
     65
     66        add_settings_field(
     67            'license_msg',                                  // field id
     68            '',                                             // title
     69            array(SyncSettings::get_instance(), 'render_message_field'),    // callback
     70            SyncSettings::SETTINGS_PAGE,                    // page
     71            $section_id,                                    // section id
     72            array(
     73                'name' => 'license_msg',
     74                'description' => sprintf(__('License keys are required to activate add-on\'s functionality and to be notified of updates.', 'wpsitesynccontent')),
     75            )
     76        );
    6577SyncDebug::log(__METHOD__.'() - returning');
    6678    }
     
    90102            __('Status: ', 'wpsitesynccontent'), '<span>', $args['status'], '</span></span>';
    91103
    92         echo '<button id="sync-license-act-', $args['name'], '" type="button" class="button sync-license sync-license-activate" data="', $args['name'], '" ';
    93         echo ' onclick="sync_settings.activate(this, \'', $args['name'] , '\'); return false;" >';
    94         _e('Activate');
    95         echo '</button>';
     104        if (!empty($args['value']) && 32 === strlen($args['value'])) {
     105            echo '<button id="sync-license-act-', $args['name'], '" type="button" class="button sync-license sync-license-activate" data="', $args['name'], '" ';
     106            echo ' onclick="sync_settings.activate(this, \'', $args['name'] , '\'); return false;" >';
     107            _e('Activate');
     108            echo '</button>';
    96109
    97         echo '<button id="sync-license-deact-', $args['name'], '" type="button" class="button sync-license sync-license-deactivate" data="', $args['name'], '" ';
    98         echo ' onclick="sync_settings.deactivate(this, \'', $args['name'] , '\'); return false;" >';
    99         _e('Dectivate');
    100         echo '</button>';
     110            echo '<button id="sync-license-deact-', $args['name'], '" type="button" class="button sync-license sync-license-deactivate" data="', $args['name'], '" ';
     111            echo ' onclick="sync_settings.deactivate(this, \'', $args['name'] , '\'); return false;" >';
     112            _e('Dectivate');
     113            echo '</button>';
    101114
    102         echo '<div id="sync-license-msg-', $args['name'], '" style="display:none" class="sync-license-msg"></div>';
     115            echo '<div id="sync-license-msg-', $args['name'], '" style="display:none" class="sync-license-msg"></div>';
     116        }
    103117
    104118        if (!empty($args['description']))
  • wpsitesynccontent/trunk/classes/licensing.php

    r1451657 r1510336  
    258258
    259259    /**
     260     * Retrieves the add-on's version from the EDD API
     261     * @param string $slug The slug for the add-on to retrieve version information for
     262     * @param string $name The name of the add-on for version retrieval
     263     * @return string|boolean The version number as a string (allowing for numbers x.x.x) or FALSE if the add-on is not recognized
     264     */
     265    public function get_version($slug, $name)
     266    {
     267//SyncDebug::log(__METHOD__."('{$slug}', '{$name}')");
     268        $this->_load_licenses();
     269        if (empty(self::$_licenses[$name])) {
     270//SyncDebug::log(' - license empty ' . __LINE__);
     271            return FALSE;
     272        }
     273
     274        $extensions = SyncExtensionModel::get_extensions(TRUE);
     275        if (empty($extensions[$name])) {
     276//SyncDebug::log(' - extension empty ' . __LINE__);
     277            return FALSE;
     278        }
     279
     280        $api_params = array(
     281            'edd_action' => 'get_version',
     282            'url' => site_url(),
     283            'license' => self::$_licenses[$name],
     284            'name' => urlencode($name),
     285            'slug' => $slug,
     286        );
     287//SyncDebug::log(__METHOD__.'() sending ' . var_export($api_params, TRUE) . ' to ' . $this->_get_api_url());
     288        $response = wp_remote_get($this->_get_api_url(), array(
     289            'timeout' => 15,
     290            'sslverify' => FALSE
     291        ));
     292//SyncDebug::log(__METHOD__.'() results=' . var_export($response, TRUE));
     293/**
     294            'new_version'   => $version,
     295            'name'          => $download->post_title,
     296            'slug'          => $slug,
     297            'url'           => esc_url( add_query_arg( 'changelog', '1', get_permalink( $item_id ) ) ),
     298            'last_updated'  => $download->post_modified,
     299            'homepage'      => get_permalink( $item_id ),
     300            'package'       => $this->get_encoded_download_package_url( $item_id, $license, $url ),
     301            'download_link' => $this->get_encoded_download_package_url( $item_id, $license, $url ),
     302            'sections'      => serialize(
     303                array(
     304                    'description' => wpautop( strip_tags( $description, '<p><li><ul><ol><strong><a><em><span><br>' ) ),
     305                    'changelog'   => wpautop( strip_tags( stripslashes( $changelog ), '<p><li><ul><ol><strong><a><em><span><br>' ) ),
     306                )
     307            ),
     308 */
     309        // check for errors
     310        if (is_wp_error($response))
     311            return FALSE;
     312
     313        // decode the response
     314        $license_data = json_decode(wp_remote_retrieve_body($response));
     315//SyncDebug::log(__METHOD__.'() data=' . var_export($license_data, TRUE));
     316    }
     317
     318    /**
    260319     * Deactivates the License Key for the named add-on
    261320     * @param string $name The name of the add-on to activate the License Key for
     
    379438        update_option(self::OPTION_NAME, self::$_licenses);
    380439    }
     440
     441    /**
     442     * Used to retrieve information on the Licensing API and known add-ons
     443     */
     444    public function get_update_data()
     445    {
     446        $ret = array(
     447            'store_url' => $this->_get_api_url(),
     448            'extensions' => array(),
     449        );
     450
     451        $extensions = apply_filters('spectrom_sync_active_extensions', array(), TRUE);
     452        $this->_load_licenses();
     453//SyncDebug::log(__METHOD__.'() licenses=' . var_export(self::$_licenses, TRUE));
     454//SyncDebug::log(__METHOD__.'() extensions=' . var_export($extensions, TRUE));
     455
     456        foreach ($extensions as $ext_slug => $extension) {
     457            if (isset(self::$_licenses[$ext_slug]))
     458                $lic = self::$_licenses[$ext_slug];
     459            else
     460                $lic = '';
     461            $extension['license'] = $lic;
     462            $ret['extensions'][] = $extension;
     463        }
     464//SyncDebug::log(__METHOD__.'() returning data: ' . var_export($ret, TRUE));
     465        return $ret;
     466    }
    381467}
  • wpsitesynccontent/trunk/classes/settings.php

    r1492115 r1510336  
    393393        }
    394394        echo '</select>';
     395    }
     396
     397    /**
     398     * Renders a message as part of the settings/form
     399     * @param array $args Arguments used to construct the message
     400     */
     401    public function render_message_field($args)
     402    {
     403        $class = '';
     404        if (!empty($args['class']))
     405            $class = ' class="' . $args['class'] . '" ';
     406        if (!empty($args['description']))
     407            echo "<p {$class}>", esc_html($args['description']), '</p>';
    395408    }
    396409
  • wpsitesynccontent/trunk/install/activate.php

    r1492115 r1510336  
    132132        if (defined('DB_COLLATE'))
    133133            $collate = DB_COLLATE;                          // if the constant is declared, use it
     134        if ('utf8_unicode_ci' === $collate)                 // fix for CREATE TABLEs on WPEngine
     135            $collate = 'utf8mb4_unicode_ci';
    134136        if (empty($collate) && !empty($wpdb->collate))      // otherwise allow wpdb class to specify
    135137            $collate = $wpdb->collate;
  • wpsitesynccontent/trunk/readme.txt

    r1492115 r1510336  
    107107
    108108== Changelog ==
     109= 1.2.1 - Oct 7, 2016 =
     110* Fix: Update collation on created table for some hosts.
     111* Enhancement: Add checks for updates to add-ons via WPSiteSync.com site.
     112* Fix: Sanitize password hash for encryption algorithms. (thanks Jonah W.)
     113* Enhancement: Specify timeout for API calls.
     114* Enhancement: Remove any error output interfering with JSON data in API calls.
     115* Enhancement: Improve error handling/recovery on API calls.
     116* Fix: Update checks for allowed post types. (thanks Cathy E.)
     117* Enhancement: Improve UX for License Keys.
     118
    109119= 1.2 - Sep 7, 2016 =
    110120* Fix: Changes to resolve authentication issues. (thanks to Craig S., Cathy E., Josh C. and Jason H.)
  • wpsitesynccontent/trunk/wpsitesynccontent.php

    r1492115 r1510336  
    66Author: WPSiteSync
    77Author URI: http://wpsitesync.com
    8 Version: 1.2
     8Version: 1.2.1
    99Text Domain: wpsitesynccontent
    1010Domain path: /language
     
    2525    class WPSiteSyncContent
    2626    {
    27         const PLUGIN_VERSION = '1.2';
     27        const PLUGIN_VERSION = '1.2.1';
    2828        const PLUGIN_NAME = 'WPSiteSyncContent';
    2929
     
    3131        const DEBUG = TRUE;
    3232
    33         /* options data */
    34         private static $_config = NULL;
    35         /* array of paths to use in autoloading */
    36         private static $_autoload_paths = array();
    37 
    38         const API_ENDPOINT = 'wpsitesync_api';      // name of endpoint: /wpsitesync_api/ - underscores less likely in name
     33        private static $_license = NULL;                // instance of licensing module
     34        private static $_autoload_paths = array();      // array of paths to use in autoloading
     35
     36        const API_ENDPOINT = 'wpsitesync_api';          // name of endpoint: /wpsitesync_api/ - underscores less likely in name
     37
     38        private $_performing_upgrade = FALSE;           // set to TRUE during plugin update process
    3939
    4040        private function __construct()
     
    5252
    5353            add_action('plugins_loaded', array(&$this, 'plugins_loaded'));
     54
     55            // the following are needed during add-on updates to fix problem with long file names on Windows
     56            add_filter('wp_unique_filename', array($this, 'filter_unique_filename'), 10, 4);
     57            add_filter('upgrader_pre_download', array($this, 'filter_upgrader_download'), 10, 3);
    5458
    5559            if (is_admin())
     
    165169
    166170        /**
     171         * Return instance of licensing object
     172         * @return SyncLicensing
     173         */
     174        public function get_license()
     175        {
     176            return self::$_license;
     177        }
     178
     179        /**
    167180         * Callback for the 'plugins_loaded' action. Load text doamin and notify other WPSiteSync add-ons that WPSiteSync is loaded.
    168181         */
    169182        public function plugins_loaded()
    170183        {
     184//SyncDebug::log(__METHOD__.'()');
     185//SyncDebug::log(__METHOD__.'() url=' . $_SERVER['REQUEST_URI']);
     186//SyncDebug::log(__METHOD__.'() post=' . var_export($_POST, TRUE));
     187//SyncDebug::log(__METHOD__.'() req=' . var_export($_REQUEST, TRUE));
    171188            load_plugin_textdomain('wpsitesynccontent', FALSE, plugin_basename(dirname(__FILE__)) . '/languages');
    172189            do_action('spectrom_sync_init');
     190            self::check_updates();
     191        }
     192
     193        /**
     194         * setup checks for plugin update notifications
     195         */
     196        public static function check_updates()
     197        {
     198            // load updater class
     199            if (!class_exists('EDD_SL_Plugin_Updater', FALSE)) {
     200                $file = dirname(__FILE__) . '/install/pluginupdater.php';
     201                require_once($file);
     202            }
     203
     204            self::$_license = new SyncLicensing();
     205            $update_data = self::$_license->get_update_data();
     206
     207            // setup the updater instance for each add-on
     208            foreach ($update_data['extensions'] as $extension) {
     209//SyncDebug::log(__METHOD__.'() creating updater instance for ' . $extension['name']);
     210                $edd_updater = new EDD_SL_Plugin_Updater($update_data['store_url'], $extension['file'], array(
     211                    'version'   => $extension['version'],                       // current version number
     212                    'license'   => $extension['license'],                       // license key
     213                    'item_name' => $extension['name'],                          // name of this plugin
     214                    'author'    => 'WPSiteSync',                                // author of this plugin
     215                    'url'       => home_url(),
     216                ));
     217            }
     218        }
     219
     220        /**
     221         * Callback function to filter the filename created in wp_tmpname()
     222         * @param string $filename The filename being created
     223         * @param string $ext The file's extension
     224         * @param string $dir The file's directory
     225         * @param callback $unique_filename_callback
     226         * @return string The file name to use
     227         */
     228        public function filter_unique_filename($filename, $ext, $dir, $unique_filename_callback)
     229        {
     230SyncDebug::log(__METHOD__.'() filename=' . $filename . ' ext=' . $ext . ' dir=' . $dir);
     231            // if WP is upgrading a plugin and the filename is too long, shorten it
     232            if ($this->_performing_upgrade && (strlen($filename) > 120 && '.tmp' === $ext)) {
     233                $filename = md5($filename) . $ext;
     234SyncDebug::log(__METHOD__.'() modifying filename=' . $filename);
     235            }
     236            return $filename;
     237        }
     238        /**
     239         * Callback for 'upgrader_pre_download' filter called in WP_Upgrader->download_package().
     240         * Used to signal the filter_unique_filename() method to modify the filename if it's too long
     241         * @param boolean $result Result value
     242         * @param string $package The package URL
     243         * @param WP_Upgrader $wp_upgrader The instance of the WP_Upgrader class
     244         * @return boolean The unmodified $result value
     245         */
     246        public function filter_upgrader_download($result, $package, $wp_upgrader)
     247        {
     248SyncDebug::log(__METHOD__.'() package=' . var_export($package, TRUE));
     249            // use this filter from WP_Upgrader->download_package() to signal that a download package filename needs to be checked
     250            $this->_performing_upgrade = TRUE;
     251            return $result;
    173252        }
    174253    }
Note: See TracChangeset for help on using the changeset viewer.