Plugin Directory

Changeset 1492115


Ignore:
Timestamp:
09/08/2016 12:17:51 AM (9 years ago)
Author:
davejesch
Message:
  • Fix: Changes to resolve authentication issues. (thanks to Craig S., Cathy E., Josh C. and Jason H.)
  • Enhancement: Some optimizations and code cleanup.
  • Enhancement: Updates in the Settings page for validating URLs. (thanks to Craig S.)
  • Fix: Fixing a table name reference when removing tables on uninstall.
  • Enhancement: Code to protect JSON data being returned via API calls when third-party plugins throw runtime errors.
  • Fix: Fix URL references in the Help text. (thanks to Pedro M.)
  • Fix: Fix text domain reference. (thanks to Pedro M.)
  • Fix: authentication token save. (thanks to Jeff C.)
  • Enhancement: Changes to allow new features in upcoming add-ons.
  • Enhancement: Change API code to work with any Permalink setting on Target site.
Location:
wpsitesynccontent/trunk
Files:
5 deleted
18 edited

Legend:

Unmodified
Added
Removed
  • wpsitesynccontent/trunk/assets/css/sync-admin.css

    r1451657 r1492115  
    1616    background-size: contain; /* 100px 82px; */
    1717    vertical-align: top;
     18}
     19.notice #sync-logo {
     20    margin-top: .5rem;
    1821}
    1922#spectrom_sync {
     
    164167    margin: 0 .7rem;
    165168}
    166 /* TODO: can be removed?? */
    167 /*.spectrom-sync-settings div.spectrom-mkt-right {
    168   float: right;
    169   display: inline-block;
    170   width: 300px;
    171   padding: 0 5px;
    172   margin: 25px 0 0 0;
    173   height: 100%;
    174   min-height: 100px;
    175 }
    176 .spectrom-sync-settings div.spectrom-mkt-right div.spectrom-logo {
    177     width: 100%;
    178 width: 260px;
    179     height: 150px;
    180     background-image: url('../imgs/spectrom.png');
    181     background-repeat: no-repeat;
    182     background-size: contain;
    183     background-position: center;
    184 } */
    185169
    186170.spectrom-sync-settings div.spectrom-page {
  • wpsitesynccontent/trunk/classes/admin.php

    r1451657 r1492115  
    5959
    6060        wp_register_style('sync-admin', WPSiteSyncContent::get_asset('css/sync-admin.css'), array(), WPSiteSyncContent::PLUGIN_VERSION, 'all');
    61         wp_register_style('font-awesome', WPSiteSyncContent::get_asset('css/font-awesome.min.css'), array(), WPSiteSyncContent::PLUGIN_VERSION, 'all');
    6261
    6362        $screen = get_current_screen();
     
    6968                wp_enqueue_script('sync');
    7069
    71             $option_data = array('site_key' => WPSiteSyncContent::get_option('site_key'));
     70            $option_data = array('site_key' => SyncOptions::get('site_key'));
    7271            wp_localize_script('sync-settings', 'syncdata', $option_data);
    7372
     
    123122        echo '<span>', __('Push content to Target: ', 'wpsitesynccontent'), '<br/>',
    124123            sprintf('<span title="%2$s"><b>%1$s</b></span>',
    125                 WPSiteSyncContent::get_option('host'),
     124                SyncOptions::get('host'),
    126125                esc_attr(__('The "Target" is the WordPress install that the Content will be pushed to.', 'wpsitesynccontent'))),
    127126            '</span>';
     
    263262                    } else if (0 !== $response_body->error_code) {
    264263                        $msg = $api->error_code_to_string($response_body->error_code);
    265                         echo '<p>', sprintf(__('Error #%1$d: %2$s', 'wpsitesync-pull'), $response_body->error_code, $msg), '</p>';
     264                        echo '<p>', sprintf(__('Error #%1$d: %2$s', 'wpsitesynccontent'), $response_body->error_code, $msg), '</p>';
    266265                        $pull_active = FALSE;
    267266                    }
  • wpsitesynccontent/trunk/classes/ajax.php

    r1451657 r1492115  
    2424        // also include the user name of the user on the Source site that is Pushing the Content
    2525        $current_user = wp_get_current_user();
    26         if (0 !== $current_user->ID) {
     26//SyncDebug::log(__METHOD__.'() current user=' . var_export($current_user, TRUE));
     27        if (NULL !== $current_user && 0 !== $current_user->ID) {
    2728            $data['username'] = $current_user->user_login;
    2829            $data['user_id'] = $current_user->ID;
     
    3637    public function dispatch()
    3738    {
    38         // TODO: add authentication checking: must be logged in, an 'Author' role or higher, check nonce
    39 
    4039        $operation = $this->post('operation');
    4140SyncDebug::log(__METHOD__."('{$operation}')");
    42         $response = new SyncApiResponse();
     41        $response = new SyncApiResponse(TRUE);
     42
     43        // perform authentication checking: must be logged in, an 'Author' role or higher
     44        if (!is_user_logged_in()) {
     45            $response->error_code(SyncApiRequest::ERROR_SESSION_EXPIRED, $operation);
     46            $response->send();
     47        }
     48        if (!current_user_can('publish_posts')) {
     49            $response->error_code(SyncApiRequest::ERROR_NO_PERMISSION, $operation);
     50            $response->send();
     51        }
     52        // TODO: check nonce
    4353
    4454        switch ($operation) {
     
    7484            if (FALSE === apply_filters('spectrom_sync_ajax_operation', FALSE, $operation, $response)) {
    7585                // No method found, fallback to error message.
    76                 $response->success(FALSE);
     86//              $response->success(FALSE);
    7787                $response->error_code(SyncApiRequest::ERROR_EXTENSION_MISSING, $operation);
    7888                // TODO: error_code() data parameter
     
    95105        $input = new SyncInput();
    96106        $settings = array_merge(
    97             get_option(SyncOptions::OPTION_NAME),
     107            SyncOptions::get_all(), // get_option(SyncOptions::OPTION_NAME),
    98108            $input->post(SyncOptions::OPTION_NAME)
    99109        );
  • wpsitesynccontent/trunk/classes/apicontroller.php

    r1451657 r1492115  
    3636    public function __construct($args)
    3737    {
     38//SyncDebug::log(__METHOD__.'() args=' . var_export($args, TRUE));
    3839        self::$_instance = $this;
    3940        $this->args = $args;
     
    4748            $response = $args['response'];
    4849        else
    49             $response = new SyncApiResponse();
     50            $response = new SyncApiResponse(TRUE);
    5051
    5152        if (isset($args['site_key']))
     
    171172        if (NULL === $this->_headers) {
    172173            if (!function_exists('apache_request_headers')) {
    173                 $this->_headers = $this->_get_request_headers();
     174//SyncDebug::log(__METHOD__.'() using _get_request_headers()');
     175                $hdrs = $this->_get_request_headers();
    174176            } else {
    175                 $this->_headers = apache_request_headers();
    176             }
    177 SyncDebug::log(__METHOD__.'() read request headers: ' . var_export($this->_headers, TRUE));
     177//SyncDebug::log(__METHOD__.'() using apache_request_headers()');
     178                $hdrs = apache_request_headers();
     179            }
     180            $this->_headers = array();
     181            foreach ($hdrs as $key => $value) {
     182                $this->_headers[strtolower($key)] = $value;
     183            }
     184//SyncDebug::log(__METHOD__.'() read request headers: ' . var_export($this->_headers, TRUE));
    178185        }
    179186
     
    212219            }
    213220        }
     221//SyncDebug::log(__METHOD__.'() headers: ' . var_export($arh, TRUE));
    214222        return $arh;
    215223    }
     
    223231SyncDebug::log(__METHOD__.'()');
    224232SyncDebug::log(' post data: ' . var_export($_POST, TRUE));
    225 SyncDebug::log(' request data: ' . var_export($_REQUEST, TRUE));
     233//SyncDebug::log(' request data: ' . var_export($_REQUEST, TRUE));
    226234        // TODO: need to assume failure, not success - then set to success when successful
    227235        $response->success(TRUE);
     
    235243//SyncDebug::log(__METHOD__.'():' . __LINE__ . ' - post_data=' . var_export($post_data, TRUE));
    236244
    237         $this->source_post_id = intval($post_data['ID']);
     245        $this->source_post_id = abs($post_data['ID']);
     246//      if (0 === $this->source_post_id && isset($post_data['post_id']))
     247//          $this->source_post_id = abs($post_data['post_id']);
    238248SyncDebug::log('- syncing post data Source ID#'. $this->source_post_id . ' - "' . $post_data['post_title'] . '"');
    239249
     
    313323                wp_update_post($post_data); // ;here;
    314324            } else {
    315                 $response->error_code(SyncApiResponse::ERROR_NO_PERMISSION);
     325                $response->error_code(SyncApiRequest::ERROR_NO_PERMISSION);
    316326                $response->send();
    317327            }
     
    324334                $target_post_id = wp_insert_post($new_post_data); // ;here;
    325335            } else {
    326                 $response->error_code(SyncApiResponse::ERROR_NO_PERMISSION);
     336                $response->error_code(SyncApiRequest::ERROR_NO_PERMISSION);
    327337                $response->send();
    328338            }
    329339        }
    330340        $this->post_id = $target_post_id;
     341SyncDebug::log(__METHOD__ . '():' . __LINE__. '  performing sync');
    331342
    332343        // save the source and target post information for later reference
  • wpsitesynccontent/trunk/classes/apimodel.php

    r1399948 r1492115  
    2828            return;
    2929
    30 SyncDebug::log(__METHOD__.'() request uri=' . $_SERVER['REQUEST_URI']);
     30//SyncDebug::log(__METHOD__.'() request uri=' . $_SERVER['REQUEST_URI']);
    3131        add_filter('request', array(&$this, 'set_query_var'));
    3232        // hook in late to allow other plugins to operate earlier
     
    7676    public function set_query_var(array $vars)
    7777    {
     78//SyncDebug::log(__METHOD__.'() vars=' . var_export($vars, TRUE));
    7879        if (!empty($vars[$this->options['name']]))
    7980            return $vars;
     
    104105
    105106        $parts = explode('/', $api);
    106 SyncDebug::log(__METHOD__.'() parts=' . var_export($parts, TRUE));
     107//SyncDebug::log(__METHOD__.'() parts=' . var_export($parts, TRUE));
    107108
    108109        // spectrom - using json only for now
     
    113114        // TODO: this can be simplified. assume only Sync callback are made, which will always be array type
    114115        if (is_string($callback)) {
     116//SyncDebug::log(__METHOD__.'() string callback');
    115117            call_user_func($callback, $values);
    116118        } else if (is_array($callback)) {
     119//SyncDebug::log(__METHOD__.'() array callback');
    117120            if ('__construct' === $callback[1])
    118121                new $callback[0]($values);
     
    120123                call_user_func($callback, $values);
    121124        } else {
     125//SyncDebug::log(__METHOD__.'() no callback');
    122126            // TODO: use exception
    123127            trigger_error(
     
    128132
    129133        // WP will render main page if we leave this out
     134        // TODO: shouldn't be needed. SyncApiController calls die() when sending results
    130135        exit;
    131136    }
  • wpsitesynccontent/trunk/classes/apirequest.php

    r1451657 r1492115  
    138138        $remote_args['headers'][self::HEADER_WP_VERSION] = $wp_version;
    139139        $remote_args['headers'][self::HEADER_SOURCE] = site_url();
    140         $remote_args['headers'][self::HEADER_SITE_KEY] = WPSiteSyncContent::get_option('site_key'); // $model->generate_site_key();
     140//      $remote_args['headers'][self::HEADER_SITE_KEY] = WPSiteSyncContent::get_option('site_key'); // $model->generate_site_key();
     141        $remote_args['headers'][self::HEADER_SITE_KEY] = SyncOptions::get('site_key'); // $model->generate_site_key();
     142//SyncDebug::log(__METHOD__.'() plugin sitekey=' . WPSiteSyncContent::get_option('site_key') . ' // option sitekey=' . SyncOptions::get('site_key'));
    141143
    142144        // send data where it's going
    143         $url = $this->host . '/' . WPSiteSyncContent::API_ENDPOINT . '?action=' . $action;
     145//      $url = $this->host . '/' . WPSiteSyncContent::API_ENDPOINT . '?action=' . $action;
     146        $url = $this->host . '?pagename=' . WPSiteSyncContent::API_ENDPOINT . '&action=' . $action;
    144147SyncDebug::log(__METHOD__.'():' . __LINE__ . ' sending API request to ' . $url, TRUE);
    145148SyncDebug::log('  sending data array: ' . SyncDebug::arr_dump($remote_args));
    146149
     150        $remote_args = apply_filters('spectrom_sync_api_arguments', $remote_args, $action);
     151
    147152        $request = wp_remote_post($url, $remote_args);
    148153        if (is_wp_error($request)) {
    149 //SyncDebug::log(__METHOD__.'():' . __LINE__ . ' error in wp_remote_post(): ' . var_export($request, TRUE));
     154SyncDebug::log(__METHOD__.'():' . __LINE__ . ' error in wp_remote_post(): ' . var_export($request, TRUE));
    150155            // handle error
    151156            $response->error_code(self::ERROR_REMOTE_REQUEST_FAILED, $request->get_error_message());
     
    214219                            update_user_meta($this->_user_id, 'spectrom_site_target_uid', $response->response->data->user_id);
    215220
    216 SyncDebug::log(__METHOD__.'() saving auth token ' . var_export($response, TRUE));
     221SyncDebug::log(__METHOD__.'() saving auth token');
    217222                            // store the returned token for later authentication uses
    218223                            $sources_model = new SyncSourcesModel();
     
    396401        // the success or error message will be returned as part of the response for the AJAX request and displayed just
    397402        // underneath the ( Sync ) button within the MetaBox.
    398         $response = new SyncApiResponse();
     403//      $response = new SyncApiResponse();
    399404        if (!is_wp_error($result)) {
    400405            // PARSE IMAGES FROM SOURCE ONLY
     
    402407            $response->success(TRUE);
    403408            $response->notice_code(SyncApiRequest::NOTICE_CONTENT_SYNCD);
    404 //          $response->notice(__('Content SYNCd.', 'wpsitesynccontent'));
    405409            $response->set('post_id', $result->data->post_id);
    406410
  • wpsitesynccontent/trunk/classes/apiresponse.php

    r1451657 r1492115  
    2828    public $data = array();
    2929
     30    private $_headers_sent = FALSE;             // TRUE when headers are sent on instantiation
     31    private $_capture = FALSE;                  // TRUE when capturing output
     32
    3033    // constructor
    31     public function __construct()
    32     {
     34    public function __construct($send_headers = FALSE)
     35    {
     36        if ($send_headers) {
     37            $this->_send_headers(TRUE);
     38        }
     39
    3340        if (!is_user_logged_in())
    3441            $this->session_timeout = 1;
     
    170177            return;
    171178
    172         global $wp_version;
    173         header(self::HEADER_SYNC_VERSION . ': ' . WPSiteSyncContent::PLUGIN_VERSION);       // send this header so sources will know that they're talking to SYNC
    174         header(self::HEADER_WP_VERSION . ': ' . $wp_version);                               // send this header so sources will know that they're talking to WP
    175         header('Content-Type: application/json');
     179        $this->_send_headers();
    176180
    177181        if ($this->has_errors()) {
     
    185189        if ($exit)
    186190            exit(0);                            // stop script
     191    }
     192
     193    /**
     194     * Send the HTTP headers for the JSON response
     195     */
     196    private function _send_headers($capture = FALSE)
     197    {
     198        if (!$this->_headers_sent) {
     199            global $wp_version;
     200
     201            header(self::HEADER_SYNC_VERSION . ': ' . WPSiteSyncContent::PLUGIN_VERSION);       // send this header so sources will know that they're talking to SYNC
     202            header(self::HEADER_WP_VERSION . ': ' . $wp_version);                               // send this header so sources will know that they're talking to WP
     203            header('Content-Type: application/json');
     204            $this->_headers_sent = TRUE;
     205
     206            if ($this->_capture) {
     207                // headers have already been sent and ob_start() has been called.
     208                // clear the output buffer so our JSON data can be sent
     209                ob_get_clean();
     210            }
     211            if ($capture) {
     212                ob_start();
     213                $this->_capture = TRUE;
     214            }
     215        }
    187216    }
    188217
  • wpsitesynccontent/trunk/classes/auth.php

    r1451657 r1492115  
    3636//SyncDebug::log(__METHOD__.'() authenticating via token');
    3737//SyncDebug::log(' - source: ' . $source . ' site_key: ' . $site_key . ' user: ' . $username . ' token: ' . $token);
    38 ### $site_key = ''; ###
    3938            $user_signon = $source_model->check_auth($source, $site_key, $username, $token);
    4039//SyncDebug::log(__METHOD__.'() source->check_auth() returned ' . var_export($user_signon, TRUE));
  • wpsitesynccontent/trunk/classes/extensionsettings.php

    r1451657 r1492115  
    44{
    55    const FEED_URL = 'https://wpsitesync.com/downloads/feed/';
     6    const TRANSIENT_KEY = 'wpsitesync_extension_list';
     7    const TRANSIENT_TTL = 86400;                    // 24 hours
     8
     9    private static $_instance = NULL;
     10
     11    private function __construct()
     12    {
     13    }
     14
     15    public static function get_instance()
     16    {
     17        if (NULL === self::$_instance)
     18            self::$_instance = new self();
     19        return self::$_instance;
     20    }
    621
    722    public function init_settings()
    823    {
     24        // no settings fields to display so nothing to initialize
     25    }
     26
     27    public function show_settings()
     28    {
     29        echo '<h3>Available Extensions:</h3>';
     30
     31        $extens = $this->_get_extension_data();
     32        if (FALSE === $extens) {
     33            echo '<p><b>Error:</b> Temporarily unable to read data from https://wpsitesync.com</p>';
     34        } else {
     35            $count = 0;
     36            foreach ($extens as $ext_info) {
     37                // image is 491x309
     38                echo '<div class="sync-extension">';
     39                echo '<h3>', esc_html($ext_info['title']), ' ', $ext_info['price'], '</h3>';
     40                echo '</div>';
     41                ++$count;
     42            }
     43            echo '<p>', sprintf(__('%1$d extensions found.', 'wpsitesynccontent')), '</p>';
     44        }
     45    }
     46
     47    private function _get_extension_data()
     48    {
     49        $data = get_transient(self::TRANSIENT_KEY);
     50        if (FALSE === $data) {
     51            $url = self::FEED_URL;
     52$url = 'http://wpsitesync.dev/downloadfeed/';
     53            $response = wp_remote_get($url);
     54//echo 'reading data from ', $url, '<br/>';
     55            if (is_wp_error($response)) {
     56                return FALSE;
     57die('error');
     58            } else {
     59                $data = wp_remote_retrieve_body($response);
     60            }
     61//          set_transient(self::TRANSIENT_KEY, $data, self::TRANSIENT_TTL);
     62        }
     63
     64//echo '<pre>', $data, '</pre>';
     65//echo 'read ', strlen($data), ' bytes of data<br/>';
     66
     67        $ret = array();
     68        $info = array();
     69
     70        $xmldoc = simplexml_load_string($data);
     71//echo 'found ', count($xmldoc->channel->item), ' items<br/>';
     72        foreach ($xmldoc->channel->item as $item) {
     73//echo 'title=', $item->title, '<br/>';
     74            $info = array(
     75                'title' => $item->title,
     76                'link' => $item->link,
     77                'price' => $item->price,
     78                'saleprice' => isset($item->saleprice) ? $item->saleprice : '',
     79                'image' => isset($item->image) ? $item->image : '',
     80            );
     81            $ret[] = $info;
     82        }
     83//echo '<pre>', var_export($xmldoc, TRUE), '</pre>';
     84        return $ret;
     85####
     86        $parser = xml_parser_create();
     87        xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
     88        xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
     89        xml_parse_into_struct($parser, $data, $values, $tags);
     90        xml_parser_free($parser);
     91
     92        foreach ($tags as $key => $val) {
     93            echo $key, ' = ', esc_html($val), '<br/>';
     94            if ('item' === $key) {
     95                echo var_export($val, TRUE), '<br/>';
     96                foreach ($val as $idx) {
     97                    echo 'value=', var_export($values[$idx], TRUE), '<br/>';
     98                }
     99            }
     100        }
     101
     102        return $ret;
     103####
     104       
     105
     106        // parse the XML data
     107        $xml = new DOMDocument();
     108        $xml->loadHTML($data);
     109        $items = $xml->getElementsByTagName('item');
     110
     111        // loop through each <item> tag and return them
     112        $nodes = $xml->documentElement;
     113        $count = 0;
     114        foreach ($nodes->childNodes as $item) {
     115            echo $item->nodeName, ' = ', esc_html($item->nodeValue), '<br/>';
     116            ++$count;
     117        }
     118        echo '<p>found ', $count, ' nodes<br/>';
     119
     120/*      for ($i = $items->length - 1; $i >= 0; $i--) {
     121            $node = $items->item($i);
     122            $title = $node->get('title');
     123echo $title, '<br/>';
     124            if (FALSE !== stripos($title, 'wpsitesync')) {
     125                $ret[] = array(
     126                    'title' => $title,
     127                );
     128            }
     129        } */
     130
     131        return $ret;
    9132    }
    10133}
  • wpsitesynccontent/trunk/classes/logmodel.php

    r1421284 r1492115  
    4040        if (!isset($data['source_user']))
    4141            $data['source_user'] = 0;
     42        if (!isset($data['post_title']))
     43            $data['post_title'] = '';
    4244
    4345        return $wpdb->insert($this->_log_table, $data);
  • wpsitesynccontent/trunk/classes/model.php

    r1446190 r1492115  
    182182            'p' => $post_id,
    183183            'post_type' => apply_filters('spectrom_sync_allowed_post_types', array('post', 'page')),
     184            'post_status' => array('publish', 'pending', 'draft', 'future', 'private', 'trash'),
    184185            'posts_per_page' => 1,
    185186        );
     
    188189        // TODO: add failure checking
    189190SyncDebug::log(__METHOD__.'() post id=' . $post_id);
     191
     192        if (0 === $query->found_posts)
     193            return $push_data;
    190194
    191195        $push_data['post_data'] = (array) $query->posts[0];
  • wpsitesynccontent/trunk/classes/settings.php

    r1451657 r1492115  
    1111    private static $_instance = NULL;
    1212
    13     private $_options = array();
     13//  private $_options = array();
    1414    private $_tab = '';
    1515
     
    2222        add_action('load-settings_page_sync', array(&$this, 'contextual_help'));
    2323
    24         $this->_options = SyncOptions::get_all();
     24//      $this->_options = SyncOptions::get_all();
    2525    }
    2626
     
    4141     * @param string $default (optional) The default value to be returned
    4242     * @return mixed The value if it exists, else $default
    43      */
    44     public function get_option($option, $default = NULL)
    45     {
     43     * @deprecated
     44     */
     45/*  public function get_option($option, $default = NULL)
     46    {
     47        // TODO: remove this method
    4648        return isset($this->_options[$option]) ? $this->_options[$option] : $default;
    47     }
     49    } */
    4850
    4951    /**
     
    8385//SyncDebug::log(__METHOD__.'() tab=' . $this->_tab);
    8486        wp_enqueue_script('sync-settings');
    85         wp_enqueue_style('font-awesome');
    8687
    8788        do_action('spectrom_sync_before_render_settings');
     
    138139
    139140        case 'extensions':
     141//          $ext = SyncExtensionSettings::get_instance();
     142//          $ext->show_settings();
    140143            break;
    141144
     
    154157        submit_button();
    155158        echo '</form>';
    156         echo '<p>', __('WPSiteSync for Content Site key: ', 'wpsitesynccontent'), '<b>', $this->get_option('site_key'), '</b></p>';
     159        echo '<p>', __('WPSiteSync for Content Site key: ', 'wpsitesynccontent'), '<b>', SyncOptions::get('site_key'), '</b></p>';
    157160        echo '</div><!-- #tab_container -->';
    158161    }
     
    174177            break;
    175178        case 'extensions':
     179//          $ext = SyncExtensionSettings::get_instance();
     180//          $ext->init_settings();
    176181            break;
    177182        case 'license':
     
    192197    {
    193198//SyncDebug::log(__METHOD__.'() tab=' . $this->_tab);
    194         $option_values = $this->_options;
     199        $option_values = SyncOptions::get_all(); // $this->_options;
    195200
    196201        $default_values = apply_filters('spectrom_sync_default_settings',
     
    251256                'size' => '50',
    252257                'value' => $data['username'],
    253                 'description' => __('Username on Target to authenticate API calls with. Must be able to create Content with this username.', 'wpsitesynccontent'),
     258                'description' => __('Username on Target for authentication. Must be able to create Content with this username.', 'wpsitesynccontent'),
    254259            )
    255260        );
     
    459464
    460465//SyncDebug::log(__METHOD__.'() values=' . var_export($values, TRUE));
    461         $settings = $this->_options;
     466        $settings = SyncOptions::get_all(); // $this->_options;
    462467//SyncDebug::log(__METHOD__.'() settings: ' . var_export($settings, TRUE));
    463468
     
    466471
    467472        $missing_error = FALSE;
     473        $re_auth = FALSE;
    468474        foreach ($values as $key => $value) {
    469475//SyncDebug::log(" key={$key}  value=[{$value}]");
    470476            if (empty($values[$key]) && 'password' === $key) {
    471477                // ignore this so that passwords are not required on every settings update
    472 //              $out[$key] = $settings[$key];
    473478            } else {
    474                 if ('host' === $key && FALSE === filter_var($value, FILTER_VALIDATE_URL)) {
    475                     add_settings_error('sync_options_group', 'invalid-url', __('Invalid URL.', 'wpsitesynccontent'));
    476                     $out[$key] = $settings[$key];
     479                if ('host' === $key) {
     480                    if (FALSE === $this->_is_valid_url($value)) {
     481                        add_settings_error('sync_options_group', 'invalid-url', __('Invalid URL.', 'wpsitesynccontent'));
     482                        $out[$key] = $settings[$key];
     483                    } else {
     484                        $out[$key] = $value;
     485                        if ($out[$key] !== $settings[$key])
     486                            $re_auth = TRUE;
     487                    }
    477488                } else if (0 === strlen(trim($value))) {
    478489                    if (!$missing_error) {
     
    487498                } else {
    488499                    $out[$key] = $value;
     500                    if ('username' === $key && $out[$key] !== $settings[$key])
     501                        $re_auth = TRUE;
    489502                }
    490503            }
     
    492505//SyncDebug::log(__METHOD__.'()  output array: ' . var_export($out, TRUE));
    493506
    494         // authenticate if there was a password provided
    495         if (!empty($out['password'])) {
     507        // authenticate if there was a password provided or the host/username are different
     508        if ($re_auth && empty($out['password'])) {
     509            add_settings_error('sync_options_group', 'no-password', __('Changed Host Name of Target or Username but did not provide password.', 'wpsitesynccontent'));
     510            $re_auth = FALSE;
     511        }
     512        if (!empty($out['password']) || $re_auth) {
    496513            $out['auth'] = 0;
    497514
     
    524541
    525542    /**
     543     * Performs validation on URL. Note: filter_var() checks for schema but does not validate it. Also allows trailing '.' characters
     544     * @param string $url The URL to validate
     545     * @return boolean TRUE on successful validation; FALSE on failure
     546     */
     547    private function _is_valid_url($url)
     548    {
     549        $res = filter_var($url, FILTER_VALIDATE_URL, FILTER_FLAG_SCHEME_REQUIRED | FILTER_FLAG_HOST_REQUIRED);
     550        if (FALSE === $res)
     551            return FALSE;
     552
     553        if (0 !== stripos($url, 'http://') && 0 !== stripos($url, 'https://'))
     554            return FALSE;
     555        else if ('.' === substr($url, -1))
     556            return FALSE;
     557
     558        return TRUE;
     559    }
     560
     561    /**
    526562     * Callback for adding contextual help to Sync Settings page
    527563     */
     
    535571            '<p><strong>' . __('For more information:', 'wpsitesynccontent') . '</strong></p>' .
    536572            '<p>' . sprintf(__('Visit the <a href="%s" target="_blank">documentation</a> on the WPSiteSync for Content website.', 'wpsitesynccontent'),
    537                         esc_url('https://wpsitesync.com/documentation/')) . '</p>' .
     573                        esc_url('http://wpsitesync.com/knowledgebase/use-wpsitesync-content/')) . '</p>' .
    538574            '<p>' . sprintf(
    539575                        __('<a href="%s" target="_blank">Post an issue</a> on <a href="%s" target="_blank">GitHub</a>.', 'wpsitesynccontent'),
    540                         esc_url('https://github.com/ServerPress/sync/issues'),
    541                         esc_url('https://github.com/ServerPress/sync/')) .
     576                        esc_url('https://github.com/ServerPress/wpsitesync/issues'),
     577                        esc_url('https://github.com/ServerPress/wpsitesync')) .
    542578            '</p>'
    543579        );
  • wpsitesynccontent/trunk/classes/sourcesmodel.php

    r1457902 r1492115  
    3636     * @param string $name The username to authenticate
    3737     * @param string $token The user's Token to authenticate against
    38      * @return object The found row if the user is authenticated; otherwise NULL
     38     * @return WP_User|WP_Error The user associated with the found row if the user is authenticated; otherwise WP_Error
    3939     */
    4040    public function check_auth($source, $site_key, $name, $token)
     
    6969     * @return object The Source site's information that matches the $domain and $site_key; or NULL if not found
    7070     */
    71     public function find_source($source, $site_key)
     71    public function find_source($source, $site_key, $auth_name = NULL)
    7272    {
    7373        global $wpdb;
    7474        $source = $this->_fix_domain($source);
     75
     76        if (NULL !== $auth_name) {
     77            $sql = "SELECT *
     78                    FROM `{$this->_sources_table}`
     79                    WHERE `site_key`=%s AND `domain`=%s AND `auth_name`=%s";
     80            $res = $wpdb->get_row($exec = $wpdb->prepare($sql, $site_key, $source, $auth_name));
     81//SyncDebug::log(__METHOD__.'():' . __LINE__ . ' sql=' . $exec . ' res=' . var_export($res, TRUE));
     82            if (NULL !== $res)
     83                return $res;
     84        }
    7585
    7686        $sql = "SELECT *
     
    90100    {
    91101        global $wpdb;
    92 //SyncDebug::log(__METHOD__.'() data=' . var_export($data, TRUE));
     102//SyncDebug::log(__METHOD__.'() data=' . var_export($data, TRUE), TRUE);
    93103        $token = '';
    94104        $data['domain'] = $this->_fix_domain($data['domain']);
     
    111121//SyncDebug::log(__METHOD__.'() - existing');
    112122                // update existing source token
     123                if (empty($data['token']))
     124                    $data['token'] = $this->_make_token();
    113125                if ($row->token !== $data['token'])
    114126                    $wpdb->update($this->_sources_table, array('token' => $data['token']), array('id' => $row->id));
    115                 $token = $data['token;']; // $row->token
     127                $token = $data['token']; // $row->token
    116128            }
    117129        } else {
     
    119131//SyncDebug::log(__METHOD__.'() - adding source');
    120132            // first, check to see if the domain already exists
    121             $row = $this->find_source($data['domain'], $data['site_key']);
    122             if (NULL === $row) {
     133            $row = $this->find_source($data['domain'], $data['site_key'], $data['auth_name']);
     134            if (NULL === $row || $row->auth_name !== $data['auth_name']) {
    123135//SyncDebug::log(__METHOD__.'() - adding ' . __LINE__);
    124136                // no record found, add it
     
    128140                // update existing source
    129141//SyncDebug::log(__METHOD__.'() updating id ' . $row->id . ' with token '); //  . $data['token']);
    130                 if ($row->token !== $data['token'])
     142                if (empty($data['token']) || $row->token !== $data['token']) {
     143                    // TODO: ensure no duplicate tokens
     144                    $data['token'] = $this->_make_token();
    131145                    $wpdb->update($this->_sources_table, array('token' => $data['token']), array('id' => $row->id));
     146                }
    132147                $token = $data['token']; // $row->token
    133148            }
    134149        }
     150//$this->_show_sources();
    135151//SyncDebug::log(__METHOD__.'() last query: ' . $wpdb->last_query);
    136152//SyncDebug::log(__METHOD__.'() returning token ' . $token);
     
    139155
    140156    /**
     157     * Method used for debugging
     158     */
     159/*  private function _show_sources()
     160    {
     161        global $wpdb;
     162
     163        $sql = "SELECT *
     164                FROM `{$this->_sources_table}`";
     165        $res = $wpdb->get_results($sql, ARRAY_A);
     166        if (NULL !== $res) {
     167SyncDebug::log(__METHOD__.'()');
     168            foreach ($res as $row) {
     169                $vals = array_values($row);
     170SyncDebug::log(' ' . implode(', ', $vals));
     171            }
     172SyncDebug::log(' ' . count($res) . ' rows');
     173        }
     174    } */
     175
     176    /**
    141177     * Inserts a new record into the sources table, creating a unique token
    142178     * @param array $data The data to add
     
    151187        if (empty($data['token'])) {
    152188            do {
    153                 $token = wp_generate_password(48, FALSE);
     189                $token = $this->_make_token();
    154190//SyncDebug::log(__METHOD__ . '() looking for token ' . $token);
    155191                // this finds a match, regardless of the value of `allowed`
     
    218254        $wpdb->update($this->_sources, array('allowed' => 1), array('site_key' => $site_key, 'auth_name' => $user));
    219255    }
     256
     257    private function _make_token()
     258    {
     259        return wp_generate_password(48, FALSE);
     260    }
    220261}
  • wpsitesynccontent/trunk/install/activate.php

    r1446190 r1492115  
    127127        if (!empty($wpdb->charset))
    128128            $charset_collate = " DEFAULT CHARACTER SET {$wpdb->charset} ";
    129         if (!empty($wpdb->collate))
    130             $charset_collate .= " COLLATE {$wpdb->collate} ";
     129
     130        // determine default collation for tables being created
     131        $collate = NULL;
     132        if (defined('DB_COLLATE'))
     133            $collate = DB_COLLATE;                          // if the constant is declared, use it
     134        if (empty($collate) && !empty($wpdb->collate))      // otherwise allow wpdb class to specify
     135            $collate = $wpdb->collate;
     136        if (!empty($collate))
     137            $charset_collate .= " COLLATE {$collate} ";
    131138
    132139        $aTables = $this->get_table_data();
  • wpsitesynccontent/trunk/install/deactivate.php

    r1451657 r1492115  
    1919            $this->remove_database_tables();
    2020            $this->remove_options();
     21            $this->remove_transients();
    2122        }
    2223
     
    3435            'sync_log',
    3536            'sync',
    36             'sources',
     37            'sync_sources',
    3738            'sync_media',
    3839        );
     
    5455        foreach ($options as $option)
    5556            delete_option($option);
     57    }
     58
     59    /**
     60     * Removes all transients
     61     */
     62    protected function remove_transients()
     63    {
     64        $trans_keys = array(
     65            'wpsitesync_extension_list',
     66        );
     67
     68        foreach ($trans_keys as $trans_key) {
     69            delete_transient($trans_key);
     70        }
    5671    }
    5772
  • wpsitesynccontent/trunk/readme.txt

    r1457902 r1492115  
    44Tags: attachments, content, content sync, data migration, desktopserver, export, import, migrate content, moving data, staging, synchronization, taxonomies
    55Requires at least: 3.5
    6 Tested up to: 4.5
     6Tested up to: 4.6
    77Stable tag: trunk
    88License: GPLv2 or later
     
    107107
    108108== Changelog ==
     109= 1.2 - Sep 7, 2016 =
     110* Fix: Changes to resolve authentication issues. (thanks to Craig S., Cathy E., Josh C. and Jason H.)
     111* Enhancement: Some optimizations and code cleanup.
     112* Enhancement: Updates in the Settings page for validating URLs. (thanks to Craig S.)
     113* Fix: Fixing a table name reference when removing tables on uninstall.
     114* Enhancement: Code to protect JSON data being returned via API calls when third-party plugins throw runtime errors.
     115* Fix: Fix URL references in the Help text. (thanks to Pedro M.)
     116* Fix: Fix text domain reference. (thanks to Pedro M.)
     117* Fix: authentication token save. (thanks to Jeff C.)
     118* Enhancement: Changes to allow new features in upcoming add-ons.
     119* Enhancement: Change API code to work with any Permalink setting on Target site.
     120
    109121= 1.1.1 - Jul 20, 2016 =
    110122* Fix for authentication issues that sometimes occur after initial credentials are entered.
  • wpsitesynccontent/trunk/views/content_details.php

    r1446190 r1492115  
    11<div id="sync-details-container">
    2     <p><b><?php _e('Content Details:', 'wpsitesync-pull'); ?></b></p>
     2    <p><b><?php _e('Content Details:', 'wpsitesynccontent'); ?></b></p>
    33    <ul style="border:1px solid gray; padding:.2rem; margin: -4px">
    4         <li><?php printf(__('Target Content Id: %d', 'wpsitesync-pull'), $data['target_post_id']); ?></li>
    5         <li><?php printf(__('Content Title: %s', 'wpsitesync-pull'), $data['post_title']); ?></li>
    6         <li><?php printf(__('Content Author: %s', 'wpsitesync-pull'), $data['post_author']); ?></li>
    7         <li><?php printf(__('Last Modified: %s', 'wpsitesync-pull'),
     4        <li><?php printf(__('Target Content Id: %d', 'wpsitesynccontent'), $data['target_post_id']); ?></li>
     5        <li><?php printf(__('Content Title: %s', 'wpsitesynccontent'), $data['post_title']); ?></li>
     6        <li><?php printf(__('Content Author: %s', 'wpsitesynccontent'), $data['post_author']); ?></li>
     7        <li><?php printf(__('Last Modified: %s', 'wpsitesynccontent'),
    88                date(get_option('date_format') . ' ' . get_option('time_format'), strtotime($data['modified'])) ); ?></li>
    9         <li><?php printf(__('Content: %s', 'wpsitesync-pull'), $data['content']); ?></li>
     9        <li><?php printf(__('Content: %s', 'wpsitesynccontent'), $data['content']); ?></li>
    1010        <?php do_action('spectrom_sync_details_view', $data); ?>
    1111    </ul>
    12     <p><?php _e('Note: Syncing this Content will overwrite data.', 'wpsitesync-pull'); ?></p>
     12    <p><?php _e('Note: Syncing this Content will overwrite data.', 'wpsitesynccontent'); ?></p>
    1313</div>
  • wpsitesynccontent/trunk/wpsitesynccontent.php

    r1457902 r1492115  
    66Author: WPSiteSync
    77Author URI: http://wpsitesync.com
    8 Version: 1.1.1
     8Version: 1.2
    99Text Domain: wpsitesynccontent
    1010Domain path: /language
     
    2525    class WPSiteSyncContent
    2626    {
    27         const PLUGIN_VERSION = '1.1.1';
     27        const PLUGIN_VERSION = '1.2';
    2828        const PLUGIN_NAME = 'WPSiteSyncContent';
    2929
     
    128128
    129129        /*
    130          * return option values
    131          * @param string $name name of the option value being requested
    132          * @param string $default default value to return if nothing found
    133          * @return multi the stored option value
    134          */
    135         public static function get_option($name, $default = NULL)
    136         {
    137             // TODO: deprecated
    138             if (NULL === self::$_config)
    139                 self::$_config = SyncSettings::get_instance();
    140             return self::$_config->get_option($name, $default);
    141         }
    142 
    143         /*
    144130         * return reference to asset, relative to the base plugin's /assets/ directory
    145131         * @param string $ref asset name to reference
Note: See TracChangeset for help on using the changeset viewer.