';
echo '
' . __('Instructions', XC_WOO_CLOUD) . ':
';
?>
' . htmlspecialchars(sprintf(__("%s does not allow authorisation of sites hosted on direct IP addresses. You will need to change your site's address (%s) before you can use %s for storage.", XC_WOO_CLOUD), __('Google Cloud Print', XC_WOO_CLOUD), $matches[1], __('Google Cloud Print', XC_WOO_CLOUD))) . ' ';
} //preg_match('#^(https?://(\d+)\.(\d+)\.(\d+)\.(\d+))/#', $admin_page_url, $matches)
else {
?>
:
' . __('Choose one, and then save the settings for the second time.', XC_WOO_CLOUD) . '
';
?>
';
?>
show_admin_warning(htmlspecialchars($_GET['error']), 'error');
} //!empty($_GET['error'])
echo __('Google Cloud Print links:', XC_WOO_CLOUD) . ' ';
echo '
' . __('Learn about Google Cloud Print', XC_WOO_CLOUD) . ' ';
echo ' | ';
echo '
' . __('Your printers', XC_WOO_CLOUD) . ' ';
echo ' | ';
echo '
' . __('Your print jobs', XC_WOO_CLOUD) . ' ';
if (current_user_can('manage_options')) {
$opts = get_option('xc_woo_cloud_print_options');
if (empty($opts['clientid']) && !empty($opts['username'])) {
$this->show_admin_warning_changedgoogleauth(true);
} //empty($opts['clientid']) && !empty($opts['username'])
$clientid = empty($opts['clientid']) ? '' : $opts['clientid'];
$token = empty($opts['token']) ? '' : $opts['token'];
if (!empty($clientid) && empty($token)) {
$this->show_admin_warning_googleauth(true);
} //!empty($clientid) && empty($token)
elseif (!empty($clientid) && !empty($token)) {
echo '
' . sprintf(__('You appear to be authenticated with Google Cloud Print, but if you are seeing authorisation errors, then you can click here to authenticate your %s account again.', XC_WOO_CLOUD), 'Google Cloud Print', 'Google Cloud Print') . '
';
} //!empty($clientid) && !empty($token)
} //current_user_can('manage_options')
}
public function options_validate($google)
{
$opts = get_option('xc_woo_cloud_print_options', array());
// Remove legacy options
unset($opts['username']);
unset($opts['password']);
if (!is_array($google))
return $opts;
$old_client_id = (empty($opts['clientid'])) ? '' : $opts['clientid'];
if (!empty($opts['token']) && $old_client_id != $google['clientid']) {
$this->googleauth_auth_revoke($opts['token'], false);
$google['token'] = '';
delete_transient('xc_woo_cloud_print_printers');
} //!empty($opts['token']) && $old_client_id != $google['clientid']
foreach ($google as $key => $value) {
// Trim spaces - I got support requests from users who didn't spot the spaces they introduced when copy/pasting
$opts[$key] = ('clientid' == $key || 'clientsecret' == $key) ? trim($value) : $value;
} //$google as $key => $value
return $opts;
}
public function xc_woo_cloud_print_options_clientid()
{
$options = get_option('xc_woo_cloud_print_options', array());
$clientid = (empty($options['clientid'])) ? '' : $options['clientid'];
echo '
';
echo '
' . __('See the instructions above to learn how to get this', XC_WOO_CLOUD) . ' ';
}
public function xc_woo_cloud_print_options_clientsecret()
{
$options = get_option('xc_woo_cloud_print_options', array());
$clientsecret = (empty($options['clientsecret'])) ? '' : $options['clientsecret'];
echo '
';
}
// This function is both an options field printer, and called via AJAX
public function xc_woo_cloud_print_options_printer()
{
if (defined('DOING_AJAX') && DOING_AJAX == true && (!isset($_POST['_wpnonce']) || !wp_verify_nonce($_POST['_wpnonce'], 'xc-woo-cloud-nonce')))
die;
$options = get_option('xc_woo_cloud_print_options');
$printers = $this->get_printers();
$this->printers_found = is_wp_error($printers) ? 0 : count($printers);
$this->debug_output = '';
if (is_wp_error($printers)) {
echo '' . strip_tags($printers->get_error_message()) . ' ';
} //is_wp_error($printers)
elseif (count($printers) == 0) {
echo '(' . __('Account either not connected, or no printers available)', XC_WOO_CLOUD) . ' ';
} //count($printers) == 0
else {
echo '';
// Make sure the option gets saved
//echo '
';
foreach ($printers as $printer) {
echo '
';
echo ' id, $options['printer'])) || (!is_array($options['printer']) && $options['printer'] == $printer->id))) ? 'checked="checked"' : '') . 'value="' . htmlspecialchars($printer->id) . '">' . htmlspecialchars($printer->displayName) . ' ';
echo '
';
} //$printers as $printer
// echo '';
echo '
';
if (defined('DOING_AJAX') && DOING_AJAX == true)
die;
echo '';
}
}
public function show_admin_warning_googleauth($suppress_title = false)
{
$warning = ($suppress_title) ? '' : '' . __('Google Cloud Print notice:', XC_WOO_CLOUD) . ' ';
$warning .= '' . sprintf(__('Click here to authenticate your %s account (you will not be able to print via %s without it).', XC_WOO_CLOUD), 'Google Cloud Print', 'Google Cloud Print') . ' ';
$this->show_admin_warning($warning);
}
public function show_admin_warning($message, $class = "updated")
{
echo '";
}
public function handle_url_actions()
{
// First, basic security check: must be an admin page, with ability to manage options, with the right parameters
// Also, only on GET because WordPress on the options page repeats parameters sometimes when POST-ing via the _wp_referer field
if (isset($_SERVER['REQUEST_METHOD']) && 'GET' == $_SERVER['REQUEST_METHOD'] && isset($_GET['action']) && 'xc-woo-google-cloud-print-auth' == $_GET['action'] && current_user_can('manage_options')) {
$_GET['page'] = $this->option_page;
$_REQUEST['page'] = $this->option_page;
if (isset($_GET['state'])) {
if ('success' == $_GET['state'])
add_action('all_admin_notices', array(
$this,
'show_authed_admin_success'
));
elseif ('token' == $_GET['state'])
$this->googleauth_auth_token();
elseif ('revoke' == $_GET['state'])
$this->googleauth_auth_revoke();
} //isset($_GET['state'])
elseif (isset($_GET['gcpl_googleauth'])) {
$this->googleauth_auth_request();
} //isset($_GET['gcpl_googleauth'])
} //isset($_SERVER['REQUEST_METHOD']) && 'GET' == $_SERVER['REQUEST_METHOD'] && isset($_GET['action']) && 'xc-woo-google-cloud-print-auth' == $_GET['action'] && current_user_can('manage_options')
}
// Acquire single-use authorization code from Google OAuth 2.0
public function googleauth_auth_request()
{
$opts = get_option('xc_woo_cloud_print_options', array());
// First, revoke any existing token, since Google doesn't appear to like issuing new ones
if (!empty($opts['token']))
$this->googleauth_auth_revoke();
// We use 'force' here for the approval_prompt, not 'auto', as that deals better with messy situations where the user authenticated, then changed settings
$params = array(
'response_type' => 'code',
'client_id' => $opts['clientid'],
'redirect_uri' => $this->redirect_uri(),
'scope' => 'https://www.googleapis.com/auth/cloudprint',
'state' => 'token',
'access_type' => 'offline',
'approval_prompt' => 'force'
);
if (headers_sent()) {
add_action('all_admin_notices', array(
$this,
'admin_notice_something_breaking'
));
} //headers_sent()
else {
header('Location: https://accounts.google.com/o/oauth2/auth?' . http_build_query($params, null, '&'));
}
}
private function redirect_uri()
{
return admin_url('options-general.php') . '?action=xc-woo-google-cloud-print-auth';
}
// Revoke a Google account refresh token
public function googleauth_auth_revoke($token = false, $unsetopt = true)
{
if (empty($token)) {
$opts = get_option('xc_woo_cloud_print_options', array());
$token = empty($opts['token']) ? '' : $opts['token'];
} //empty($token)
if ($token)
wp_remote_get('https://accounts.google.com/o/oauth2/revoke?token=' . $token);
if ($unsetopt) {
$opts = get_option('xc_woo_cloud_print_options', array());
$opts['token'] = '';
update_option('xc_woo_cloud_print_options', $opts);
} //$unsetopt
}
// Get a Google account refresh token using the code received from googleauth_auth_request
public function googleauth_auth_token()
{
$opts = get_option('xc_woo_cloud_print_options', array());
if (isset($_GET['code'])) {
$post_vars = array(
'code' => $_GET['code'],
'client_id' => $opts['clientid'],
'client_secret' => $opts['clientsecret'],
'redirect_uri' => $this->redirect_uri(),
'grant_type' => 'authorization_code'
);
$googleauth_request_options = apply_filters('google_cloud_print_googleauth_request_options', array(
'timeout' => 25,
'method' => 'POST',
'body' => $post_vars
));
$result = wp_remote_post('https://accounts.google.com/o/oauth2/token', $googleauth_request_options);
if (is_wp_error($result)) {
$add_to_url = "Bad response when contacting Google: ";
foreach ($result->get_error_messages() as $message) {
error_log("Google Drive authentication error: " . $message);
$add_to_url .= $message . ". ";
} //$result->get_error_messages() as $message
header('Location: ' . admin_url('options-general.php') . '?page=' . $this->option_page . '&error=' . urlencode($add_to_url));
} //is_wp_error($result)
else {
$json_values = json_decode($result['body'], true);
if (isset($json_values['refresh_token'])) {
// Save token
$opts['token'] = $json_values['refresh_token'];
update_option('xc_woo_cloud_print_options', $opts);
if (isset($json_values['access_token'])) {
$opts['tmp_access_token'] = $json_values['access_token'];
update_option('xc_woo_cloud_print_options', $opts);
// We do this to clear the GET parameters, otherwise WordPress sticks them in the _wp_referer in the form and brings them back, leading to confusion + errors
header('Location: ' . admin_url('options-general.php') . '?action=xc-woo-google-cloud-print-auth&page=' . $this->option_page . '&state=success');
} //isset($json_values['access_token'])
} //isset($json_values['refresh_token'])
else {
$msg = __('No refresh token was received from Google. This often means that you entered your client secret wrongly, or that you have not yet re-authenticated (below) since correcting it. Re-check it, then follow the link to authenticate again. Finally, if that does not work, then use expert mode to wipe all your settings, create a new Google client ID/secret, and start again.', XC_WOO_CLOUD);
if (isset($json_values['error']))
$msg .= ' ' . sprintf(__('Error: %s', XC_WOO_CLOUD), $json_values['error']);
header('Location: ' . admin_url('options-general.php') . '?page=' . $this->option_page . '&error=' . urlencode($msg));
}
}
} //isset($_GET['code'])
else {
$err_msg = __('Authorization failed', XC_WOO_CLOUD);
if (!empty($_GET['error']))
$err_msg .= ': ' . $_GET['error'];
header('Location: ' . admin_url('options-general.php') . '?page=' . $this->option_page . '&error=' . urlencode($err_msg));
}
}
public function show_authed_admin_success()
{
// global $updraftplus_admin;
$opts = get_option('xc_woo_cloud_print_options', array());
if (empty($opts['tmp_access_token']))
return;
$tmp_access_token = $opts['tmp_access_token'];
$message = '';
$this->show_admin_warning(__('Success', XC_WOO_CLOUD) . ': ' . sprintf(__('you have authenticated your %s account.', XC_WOO_CLOUD), __('Google Cloud Print', XC_WOO_CLOUD)) . ' ');
unset($opts['tmp_access_token']);
update_option('xc_woo_cloud_print_options', $opts);
}
public function get_printers()
{
if (!defined('DOING_AJAX') || DOING_AJAX != true) {
$printers = get_transient('xc_woo_cloud_print_printers');
if (is_array($printers))
return $printers;
} //!defined('DOING_AJAX') || DOING_AJAX != true
// Wanted key: access token
$options = apply_filters('xc_woo_cloud_print_options', array());
// This should only be set if authenticated
if (isset($options['token'])) {
$post = array();
$printers = $this->process_request('https://www.google.com/cloudprint/interface/search', $post, $options);
if (is_wp_error($printers))
return $printers;
if (is_string($printers))
$printers = json_decode($printers);
if (is_object($printers) && isset($printers->success) && $printers->success == true && isset($printers->printers) && is_array($printers->printers)) {
foreach ($printers->printers as $index => $printer) {
$get_printer_result = $this->process_request('https://www.google.com/cloudprint/printer', array(
'use_cdd' => 'true',
'printerid' => $printer->id
), $options);
if (false !== $get_printer_result && null !== ($printer_result = json_decode($get_printer_result))) {
if (isset($printer_result->success) && true == $printer_result->success && isset($printer_result->printers) && is_array($printer_result->printers)) {
$printer = $printer_result->printers[0];
// $hashed_id = md5($printer->id);
// set_transient('gcpl_popts_'.$hashed_id, $printer_result, 86400);
$printers->printers[$index]->_gcpl_printer_opts = $printer;
} //isset($printer_result->success) && true == $printer_result->success && isset($printer_result->printers) && is_array($printer_result->printers)
} //false !== $get_printer_result && null !== ($printer_result = json_decode($get_printer_result))
} //$printers->printers as $index => $printer
if (false !== $get_printer_result) {
set_transient('xc_woo_cloud_print_printers', $printers->printers, 86400);
} //false !== $get_printer_result
return $printers->printers;
} //is_object($printers) && isset($printers->success) && $printers->success == true && isset($printers->printers) && is_array($printers->printers)
} //isset($options['token'])
return array();
}
public function xc_woo_cloud_print_options($options)
{
if (!empty($options))
return $options;
return get_option('xc_woo_cloud_print_options', array());
}
public function process_request($url, $post_fields, $options = array(), $referer = '')
{
$ret = "";
$wp_post_opts = array(
'user-agent' => "XC Woo Google Cloud Print" . XC_WOO_CLOUD_VERSION,
'headers' => array(
'X-CloudPrint-Proxy' => "xc-woo-cloud-print",
'Referer' => $referer
),
'sslverify' => true,
'redirection' => 5,
'body' => $post_fields,
'timeout' => 25
);
if (!empty($options['username']) && empty($options['clientid'])) {
// Legacy/deprecated - tokens from the now-removed ClientLogin API
$wp_post_opts['headers']['Authorization'] = "GoogleLogin auth=$token";
} //!empty($options['username']) && empty($options['clientid'])
else {
$access_token = $this->access_token($options);
if (is_wp_error($access_token) || empty($access_token))
return $access_token;
$wp_post_opts['headers']['Authorization'] = "Bearer $access_token";
}
$wp_post_opts = apply_filters('xc_woo_cloud_print_process_request_options', $wp_post_opts);
$post = wp_remote_post($url, $wp_post_opts);
if (is_wp_error($post)) {
error_log('POST error: ' . $post->get_error_code() . ': ' . $post->get_error_message());
return $post;
} //is_wp_error($post)
if (!is_array($post['response']) || !isset($post['response']['code'])) {
error_log('POST error: Unexpected response: ' . serialize($post));
return false;
} //!is_array($post['response']) || !isset($post['response']['code'])
if ($post['response']['code'] >= 400 && $post['response']['code'] < 500) {
$extra = '';
error_log('POST error: Unexpected response (code ' . $post['response']['code'] . '): ' . serialize($post));
return new WP_Error('http_badauth', $extra . "Authentication failed (" . $post['response']['code'] . "): " . $post['body']);
} //$post['response']['code'] >= 400 && $post['response']['code'] < 500
if ($post['response']['code'] >= 400) {
error_log('POST error: Unexpected response (code ' . $post['response']['code'] . '): ' . serialize($post));
return new WP_Error('http_error', 'POST error: Unexpected response (code ' . $post['response']['code'] . '): ' . serialize($post));
} //$post['response']['code'] >= 400
return $post['body'];
}
private function access_token($options)
{
$refresh_token = $options['token'];
$query_body = array(
'refresh_token' => $refresh_token,
'client_id' => $options['clientid'],
'client_secret' => $options['clientsecret'],
'grant_type' => 'refresh_token'
);
$result = wp_remote_post('https://accounts.google.com/o/oauth2/token', array(
'timeout' => 15,
'method' => 'POST',
'body' => $query_body
));
if (is_wp_error($result)) {
return $result;
} //is_wp_error($result)
else {
$json_values = json_decode(wp_remote_retrieve_body($result), true);
if (isset($json_values['access_token'])) {
// error_log("Google Drive: successfully obtained access token");
return $json_values['access_token'];
} //isset($json_values['access_token'])
else {
// error_log("Google Drive error when requesting access token: response does not contain access_token");
if (!empty($json_values['error']) && !empty($json_values['error_description'])) {
return new WP_Error($json_values['error'], $json_values['error_description']);
} //!empty($json_values['error']) && !empty($json_values['error_description'])
return false;
}
}
}
private function generate_selector($printer_id, $cap_id, $capabilities, $title = '', $current_options)
{
if ('__google__docs' == $printer_id || !is_array($capabilities) || empty($capabilities[$cap_id]))
return '';
$cap = $capabilities[$cap_id];
if (!is_object($cap) || !isset($cap->option) || !is_array($cap->option))
return '';
$option = $cap->option;
$selector_id = esc_attr('gcpl_capability_' . $printer_id . '_' . $cap_id);
$output = '' . htmlspecialchars($title) . ': ';
$output .= '' . "\n";
$selected = null;
if (isset($current_options['printer_options'][$printer_id][$cap_id])) {
if (null !== ($decode_current_option = json_decode($current_options['printer_options'][$printer_id][$cap_id]))) {
if (isset($decode_current_option->label))
$selected = $decode_current_option->label;
} //null !== ($decode_current_option = json_decode($current_options['printer_options'][$printer_id][$cap_id]))
} //isset($current_options['printer_options'][$printer_id][$cap_id])
foreach ($option as $opt) {
if ('fit_to_page' == $cap_id) {
$values_to_save = array(
'type'
);
// $name = $opt->type;
if ('NO_FITTING' == $opt->type) {
$label = __('Do not fit to page', XC_WOO_CLOUD);
} //'NO_FITTING' == $opt->type
elseif ('FIT_TO_PAGE' == $opt->type) {
$label = __('Fit to page', XC_WOO_CLOUD);
} //'FIT_TO_PAGE' == $opt->type
else {
$label = $opt->type;
}
} //'fit_to_page' == $cap_id
elseif ('page_orientation' == $cap_id) {
$values_to_save = array(
'type'
);
if ('PORTRAIT' == $opt->type) {
$label = __('Portrait', XC_WOO_CLOUD);
} //'PORTRAIT' == $opt->type
elseif ('LANDSCAPE' == $opt->type) {
$label = __('Landscape', XC_WOO_CLOUD);
} //'LANDSCAPE' == $opt->type
elseif ('AUTO' == $opt->type) {
$label = __('Automatic', XC_WOO_CLOUD);
} //'AUTO' == $opt->type
else {
$label = $opt->type;
}
} //'page_orientation' == $cap_id
elseif ('color' == $cap_id) {
$values_to_save = array(
'type'
);
if ('STANDARD_MONOCHROME' == $opt->type) {
$label = __('Monochrome', XC_WOO_CLOUD);
} //'STANDARD_MONOCHROME' == $opt->type
elseif ('STANDARD_COLOR' == $opt->type) {
$label = __('Color', XC_WOO_CLOUD);
} //'STANDARD_COLOR' == $opt->type
elseif ('AUTO' == $opt->type) {
$label = __('Automatic', XC_WOO_CLOUD);
} //'AUTO' == $opt->type
else {
// Drop CUSTOM_COLOR, CUSTOM_MONOCHROME
continue;
}
} //'color' == $cap_id
else {
$values_to_save = array(
'width_microns',
'height_microns',
'is_continuous_feed'
);
// $name = $opt->name;
$label = $opt->custom_display_name;
}
$value = array();
foreach ($values_to_save as $key) {
$value[$key] = isset($opt->$key) ? $opt->$key : false;
} //$values_to_save as $key
$value['label'] = $label;
$output .= 'is_default)) || (null !== $selected && $label == $selected))
$output .= ' selected="selected"';
$output .= '>';
$output .= htmlspecialchars($label);
$output .= ' ';
} //$option as $opt
$output .= " \n";
return $output;
}
public function add_action_links($links)
{
$mylinks = array(
'Settings ',
'Cloud Print Options '
);
return array_merge($links, $mylinks);
}
}