function sign_request($token = '', $timestamp = 0, $nonce = '', $body_hash = '', $method = '', $url = '', $body = null, $verify_body_hash = true)
{
if (!$this->secret) {
return new Jetpack_Error('invalid_secret', 'Invalid secret');
}
if (!$this->token) {
return new Jetpack_Error('invalid_token', 'Invalid token');
}
list($token) = explode('.', $token);
if (0 !== strpos($token, "{$this->token}:")) {
return new Jetpack_Error('token_mismatch', 'Incorrect token');
}
// If we got an array at this point, let's encode it, so we can see what it looks like as a string.
if (is_array($body)) {
if (count($body) > 0) {
$body = json_encode($body);
} else {
$body = '';
}
}
$required_parameters = array('token', 'timestamp', 'nonce', 'method', 'url');
if (!is_null($body)) {
$required_parameters[] = 'body_hash';
if (!is_string($body)) {
return new Jetpack_Error('invalid_body', 'Body is malformed.');
}
}
foreach ($required_parameters as $required) {
if (!is_scalar(${$required})) {
return new Jetpack_Error('invalid_signature', sprintf('The required "%s" parameter is malformed.', str_replace('_', '-', $required)));
}
if (!strlen(${$required})) {
return new Jetpack_Error('invalid_signature', sprintf('The required "%s" parameter is missing.', str_replace('_', '-', $required)));
}
}
if (empty($body)) {
if ($body_hash) {
return new Jetpack_Error('invalid_body_hash', 'The body hash does not match.');
}
} else {
if ($verify_body_hash && jetpack_sha1_base64($body) !== $body_hash) {
return new Jetpack_Error('invalid_body_hash', 'The body hash does not match.');
}
}
$parsed = parse_url($url);
if (!isset($parsed['host'])) {
return new Jetpack_Error('invalid_signature', sprintf('The required "%s" parameter is malformed.', 'url'));
}
if ($parsed['host'] === JETPACK__WPCOM_JSON_API_HOST) {
$parsed['host'] = 'public-api.wordpress.com';
}
if (!empty($parsed['port'])) {
$port = $parsed['port'];
} else {
if ('http' == $parsed['scheme']) {
$port = 80;
} else {
if ('https' == $parsed['scheme']) {
$port = 443;
} else {
return new Jetpack_Error('unknown_scheme_port', "The scheme's port is unknown");
}
}
}
if (!ctype_digit("{$timestamp}") || 10 < strlen($timestamp)) {
// If Jetpack is around in 275 years, you can blame mdawaffe for the bug.
return new Jetpack_Error('invalid_signature', sprintf('The required "%s" parameter is malformed.', 'timestamp'));
}
$local_time = $timestamp - $this->time_diff;
if ($local_time < time() - 600 || $local_time > time() + 300) {
return new Jetpack_Error('invalid_signature', 'The timestamp is too old.');
}
if (12 < strlen($nonce) || preg_match('/[^a-zA-Z0-9]/', $nonce)) {
return new Jetpack_Error('invalid_signature', sprintf('The required "%s" parameter is malformed.', 'nonce'));
}
$normalized_request_pieces = array($token, $timestamp, $nonce, $body_hash, strtoupper($method), strtolower($parsed['host']), $port, $parsed['path']);
$normalized_request_pieces = array_merge($normalized_request_pieces, $this->normalized_query_parameters(isset($parsed['query']) ? $parsed['query'] : ''));
$normalized_request_string = join("\n", $normalized_request_pieces) . "\n";
return base64_encode(hash_hmac('sha1', $normalized_request_string, $this->secret, true));
}