diff --git a/3rdparty/Google/LICENSE.txt b/3rdparty/Google/LICENSE.txt new file mode 100644 index 00000000000..8891c7ddc90 --- /dev/null +++ b/3rdparty/Google/LICENSE.txt @@ -0,0 +1,21 @@ +The MIT License + +Copyright (c) 2007 Andy Smith + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/3rdparty/Google/OAuth.php b/3rdparty/Google/OAuth.php new file mode 100755 index 00000000000..c7e75dd8266 --- /dev/null +++ b/3rdparty/Google/OAuth.php @@ -0,0 +1,751 @@ +key = $key; + $this->secret = $secret; + $this->callback_url = $callback_url; + }/*}}}*/ +}/*}}}*/ + +class OAuthToken {/*{{{*/ + // access tokens and request tokens + public $key; + public $secret; + + /** + * key = the token + * secret = the token secret + */ + function __construct($key, $secret) {/*{{{*/ + $this->key = $key; + $this->secret = $secret; + }/*}}}*/ + + /** + * generates the basic string serialization of a token that a server + * would respond to request_token and access_token calls with + */ + function to_string() {/*{{{*/ + return "oauth_token=" . OAuthUtil::urlencodeRFC3986($this->key) . + "&oauth_token_secret=" . OAuthUtil::urlencodeRFC3986($this->secret); + }/*}}}*/ + + function __toString() {/*{{{*/ + return $this->to_string(); + }/*}}}*/ +}/*}}}*/ + +class OAuthSignatureMethod {/*{{{*/ + public function check_signature(&$request, $consumer, $token, $signature) { + $built = $this->build_signature($request, $consumer, $token); + return $built == $signature; + } +}/*}}}*/ + +class OAuthSignatureMethod_HMAC_SHA1 extends OAuthSignatureMethod {/*{{{*/ + function get_name() {/*{{{*/ + return "HMAC-SHA1"; + }/*}}}*/ + + public function build_signature($request, $consumer, $token, $privKey=NULL) {/*{{{*/ + $base_string = $request->get_signature_base_string(); + $request->base_string = $base_string; + + $key_parts = array( + $consumer->secret, + ($token) ? $token->secret : "" + ); + + $key_parts = array_map(array('OAuthUtil','urlencodeRFC3986'), $key_parts); + $key = implode('&', $key_parts); + + return base64_encode( hash_hmac('sha1', $base_string, $key, true)); + }/*}}}*/ +}/*}}}*/ + +class OAuthSignatureMethod_RSA_SHA1 extends OAuthSignatureMethod {/*{{{*/ + public function get_name() {/*{{{*/ + return "RSA-SHA1"; + }/*}}}*/ + + protected function fetch_public_cert(&$request) {/*{{{*/ + // not implemented yet, ideas are: + // (1) do a lookup in a table of trusted certs keyed off of consumer + // (2) fetch via http using a url provided by the requester + // (3) some sort of specific discovery code based on request + // + // either way should return a string representation of the certificate + throw Exception("fetch_public_cert not implemented"); + }/*}}}*/ + + protected function fetch_private_cert($privKey) {//&$request) {/*{{{*/ + // not implemented yet, ideas are: + // (1) do a lookup in a table of trusted certs keyed off of consumer + // + // either way should return a string representation of the certificate + throw Exception("fetch_private_cert not implemented"); + }/*}}}*/ + + public function build_signature(&$request, $consumer, $token, $privKey) {/*{{{*/ + $base_string = $request->get_signature_base_string(); + + // Fetch the private key cert based on the request + //$cert = $this->fetch_private_cert($consumer->privKey); + + //Pull the private key ID from the certificate + //$privatekeyid = openssl_get_privatekey($cert); + + // hacked in + if ($privKey == '') { + $fp = fopen($GLOBALS['PRIV_KEY_FILE'], "r"); + $privKey = fread($fp, 8192); + fclose($fp); + } + $privatekeyid = openssl_get_privatekey($privKey); + + //Check the computer signature against the one passed in the query + $ok = openssl_sign($base_string, $signature, $privatekeyid); + + //Release the key resource + openssl_free_key($privatekeyid); + + return base64_encode($signature); + } /*}}}*/ + + public function check_signature(&$request, $consumer, $token, $signature) {/*{{{*/ + $decoded_sig = base64_decode($signature); + + $base_string = $request->get_signature_base_string(); + + // Fetch the public key cert based on the request + $cert = $this->fetch_public_cert($request); + + //Pull the public key ID from the certificate + $publickeyid = openssl_get_publickey($cert); + + //Check the computer signature against the one passed in the query + $ok = openssl_verify($base_string, $decoded_sig, $publickeyid); + + //Release the key resource + openssl_free_key($publickeyid); + + return $ok == 1; + } /*}}}*/ +}/*}}}*/ + +class OAuthRequest {/*{{{*/ + private $parameters; + private $http_method; + private $http_url; + // for debug purposes + public $base_string; + public static $version = '1.0'; + + function __construct($http_method, $http_url, $parameters=NULL) {/*{{{*/ + @$parameters or $parameters = array(); + $this->parameters = $parameters; + $this->http_method = $http_method; + $this->http_url = $http_url; + }/*}}}*/ + + + /** + * attempt to build up a request from what was passed to the server + */ + public static function from_request($http_method=NULL, $http_url=NULL, $parameters=NULL) {/*{{{*/ + $scheme = (!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] != "on") ? 'http' : 'https'; + @$http_url or $http_url = $scheme . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; + @$http_method or $http_method = $_SERVER['REQUEST_METHOD']; + + $request_headers = OAuthRequest::get_headers(); + + // let the library user override things however they'd like, if they know + // which parameters to use then go for it, for example XMLRPC might want to + // do this + if ($parameters) { + $req = new OAuthRequest($http_method, $http_url, $parameters); + } + // next check for the auth header, we need to do some extra stuff + // if that is the case, namely suck in the parameters from GET or POST + // so that we can include them in the signature + else if (@substr($request_headers['Authorization'], 0, 5) == "OAuth") { + $header_parameters = OAuthRequest::split_header($request_headers['Authorization']); + if ($http_method == "GET") { + $req_parameters = $_GET; + } + else if ($http_method = "POST") { + $req_parameters = $_POST; + } + $parameters = array_merge($header_parameters, $req_parameters); + $req = new OAuthRequest($http_method, $http_url, $parameters); + } + else if ($http_method == "GET") { + $req = new OAuthRequest($http_method, $http_url, $_GET); + } + else if ($http_method == "POST") { + $req = new OAuthRequest($http_method, $http_url, $_POST); + } + return $req; + }/*}}}*/ + + /** + * pretty much a helper function to set up the request + */ + public static function from_consumer_and_token($consumer, $token, $http_method, $http_url, $parameters=NULL) {/*{{{*/ + @$parameters or $parameters = array(); + $defaults = array("oauth_version" => OAuthRequest::$version, + "oauth_nonce" => OAuthRequest::generate_nonce(), + "oauth_timestamp" => OAuthRequest::generate_timestamp(), + "oauth_consumer_key" => $consumer->key); + $parameters = array_merge($defaults, $parameters); + + if ($token) { + $parameters['oauth_token'] = $token->key; + } + + // oauth v1.0a + /*if (isset($_REQUEST['oauth_verifier'])) { + $parameters['oauth_verifier'] = $_REQUEST['oauth_verifier']; + }*/ + + + return new OAuthRequest($http_method, $http_url, $parameters); + }/*}}}*/ + + public function set_parameter($name, $value) {/*{{{*/ + $this->parameters[$name] = $value; + }/*}}}*/ + + public function get_parameter($name) {/*{{{*/ + return $this->parameters[$name]; + }/*}}}*/ + + public function get_parameters() {/*{{{*/ + return $this->parameters; + }/*}}}*/ + + /** + * Returns the normalized parameters of the request + * + * This will be all (except oauth_signature) parameters, + * sorted first by key, and if duplicate keys, then by + * value. + * + * The returned string will be all the key=value pairs + * concated by &. + * + * @return string + */ + public function get_signable_parameters() {/*{{{*/ + // Grab all parameters + $params = $this->parameters; + + // Remove oauth_signature if present + if (isset($params['oauth_signature'])) { + unset($params['oauth_signature']); + } + + // Urlencode both keys and values + $keys = array_map(array('OAuthUtil', 'urlencodeRFC3986'), array_keys($params)); + $values = array_map(array('OAuthUtil', 'urlencodeRFC3986'), array_values($params)); + $params = array_combine($keys, $values); + + // Sort by keys (natsort) + uksort($params, 'strnatcmp'); + +if(isset($params['title']) && isset($params['title-exact'])) { + $temp = $params['title-exact']; + $title = $params['title']; + + unset($params['title']); + unset($params['title-exact']); + + $params['title-exact'] = $temp; + $params['title'] = $title; +} + + // Generate key=value pairs + $pairs = array(); + foreach ($params as $key=>$value ) { + if (is_array($value)) { + // If the value is an array, it's because there are multiple + // with the same key, sort them, then add all the pairs + natsort($value); + foreach ($value as $v2) { + $pairs[] = $key . '=' . $v2; + } + } else { + $pairs[] = $key . '=' . $value; + } + } + + // Return the pairs, concated with & + return implode('&', $pairs); + }/*}}}*/ + + /** + * Returns the base string of this request + * + * The base string defined as the method, the url + * and the parameters (normalized), each urlencoded + * and the concated with &. + */ + public function get_signature_base_string() {/*{{{*/ + $parts = array( + $this->get_normalized_http_method(), + $this->get_normalized_http_url(), + $this->get_signable_parameters() + ); + + $parts = array_map(array('OAuthUtil', 'urlencodeRFC3986'), $parts); + + return implode('&', $parts); + }/*}}}*/ + + /** + * just uppercases the http method + */ + public function get_normalized_http_method() {/*{{{*/ + return strtoupper($this->http_method); + }/*}}}*/ + +/** + * parses the url and rebuilds it to be + * scheme://host/path + */ + public function get_normalized_http_url() { + $parts = parse_url($this->http_url); + + $scheme = (isset($parts['scheme'])) ? $parts['scheme'] : 'http'; + $port = (isset($parts['port'])) ? $parts['port'] : (($scheme == 'https') ? '443' : '80'); + $host = (isset($parts['host'])) ? strtolower($parts['host']) : ''; + $path = (isset($parts['path'])) ? $parts['path'] : ''; + + if (($scheme == 'https' && $port != '443') + || ($scheme == 'http' && $port != '80')) { + $host = "$host:$port"; + } + return "$scheme://$host$path"; + } + + /** + * builds a url usable for a GET request + */ + public function to_url() {/*{{{*/ + $out = $this->get_normalized_http_url() . "?"; + $out .= $this->to_postdata(); + return $out; + }/*}}}*/ + + /** + * builds the data one would send in a POST request + */ + public function to_postdata() {/*{{{*/ + $total = array(); + foreach ($this->parameters as $k => $v) { + $total[] = OAuthUtil::urlencodeRFC3986($k) . "=" . OAuthUtil::urlencodeRFC3986($v); + } + $out = implode("&", $total); + return $out; + }/*}}}*/ + + /** + * builds the Authorization: header + */ + public function to_header() {/*{{{*/ + $out ='Authorization: OAuth '; + $total = array(); + + /* + $sig = $this->parameters['oauth_signature']; + unset($this->parameters['oauth_signature']); + uksort($this->parameters, 'strnatcmp'); + $this->parameters['oauth_signature'] = $sig; + */ + + foreach ($this->parameters as $k => $v) { + if (substr($k, 0, 5) != "oauth") continue; + $out .= OAuthUtil::urlencodeRFC3986($k) . '="' . OAuthUtil::urlencodeRFC3986($v) . '", '; + } + $out = substr_replace($out, '', strlen($out) - 2); + + return $out; + }/*}}}*/ + + public function __toString() {/*{{{*/ + return $this->to_url(); + }/*}}}*/ + + + public function sign_request($signature_method, $consumer, $token, $privKey=NULL) {/*{{{*/ + $this->set_parameter("oauth_signature_method", $signature_method->get_name()); + $signature = $this->build_signature($signature_method, $consumer, $token, $privKey); + $this->set_parameter("oauth_signature", $signature); + }/*}}}*/ + + public function build_signature($signature_method, $consumer, $token, $privKey=NULL) {/*{{{*/ + $signature = $signature_method->build_signature($this, $consumer, $token, $privKey); + return $signature; + }/*}}}*/ + + /** + * util function: current timestamp + */ + private static function generate_timestamp() {/*{{{*/ + return time(); + }/*}}}*/ + + /** + * util function: current nonce + */ + private static function generate_nonce() {/*{{{*/ + $mt = microtime(); + $rand = mt_rand(); + + return md5($mt . $rand); // md5s look nicer than numbers + }/*}}}*/ + + /** + * util function for turning the Authorization: header into + * parameters, has to do some unescaping + */ + private static function split_header($header) {/*{{{*/ + // this should be a regex + // error cases: commas in parameter values + $parts = explode(",", $header); + $out = array(); + foreach ($parts as $param) { + $param = ltrim($param); + // skip the "realm" param, nobody ever uses it anyway + if (substr($param, 0, 5) != "oauth") continue; + + $param_parts = explode("=", $param); + + // rawurldecode() used because urldecode() will turn a "+" in the + // value into a space + $out[$param_parts[0]] = rawurldecode(substr($param_parts[1], 1, -1)); + } + return $out; + }/*}}}*/ + + /** + * helper to try to sort out headers for people who aren't running apache + */ + private static function get_headers() {/*{{{*/ + if (function_exists('apache_request_headers')) { + // we need this to get the actual Authorization: header + // because apache tends to tell us it doesn't exist + return apache_request_headers(); + } + // otherwise we don't have apache and are just going to have to hope + // that $_SERVER actually contains what we need + $out = array(); + foreach ($_SERVER as $key => $value) { + if (substr($key, 0, 5) == "HTTP_") { + // this is chaos, basically it is just there to capitalize the first + // letter of every word that is not an initial HTTP and strip HTTP + // code from przemek + $key = str_replace(" ", "-", ucwords(strtolower(str_replace("_", " ", substr($key, 5))))); + $out[$key] = $value; + } + } + return $out; + }/*}}}*/ +}/*}}}*/ + +class OAuthServer {/*{{{*/ + protected $timestamp_threshold = 300; // in seconds, five minutes + protected $version = 1.0; // hi blaine + protected $signature_methods = array(); + + protected $data_store; + + function __construct($data_store) {/*{{{*/ + $this->data_store = $data_store; + }/*}}}*/ + + public function add_signature_method($signature_method) {/*{{{*/ + $this->signature_methods[$signature_method->get_name()] = + $signature_method; + }/*}}}*/ + + // high level functions + + /** + * process a request_token request + * returns the request token on success + */ + public function fetch_request_token(&$request) {/*{{{*/ + $this->get_version($request); + + $consumer = $this->get_consumer($request); + + // no token required for the initial token request + $token = NULL; + + $this->check_signature($request, $consumer, $token); + + $new_token = $this->data_store->new_request_token($consumer); + + return $new_token; + }/*}}}*/ + + /** + * process an access_token request + * returns the access token on success + */ + public function fetch_access_token(&$request) {/*{{{*/ + $this->get_version($request); + + $consumer = $this->get_consumer($request); + + // requires authorized request token + $token = $this->get_token($request, $consumer, "request"); + + $this->check_signature($request, $consumer, $token); + + $new_token = $this->data_store->new_access_token($token, $consumer); + + return $new_token; + }/*}}}*/ + + /** + * verify an api call, checks all the parameters + */ + public function verify_request(&$request) {/*{{{*/ + $this->get_version($request); + $consumer = $this->get_consumer($request); + $token = $this->get_token($request, $consumer, "access"); + $this->check_signature($request, $consumer, $token); + return array($consumer, $token); + }/*}}}*/ + + // Internals from here + /** + * version 1 + */ + private function get_version(&$request) {/*{{{*/ + $version = $request->get_parameter("oauth_version"); + if (!$version) { + $version = 1.0; + } + if ($version && $version != $this->version) { + throw new OAuthException("OAuth version '$version' not supported"); + } + return $version; + }/*}}}*/ + + /** + * figure out the signature with some defaults + */ + private function get_signature_method(&$request) {/*{{{*/ + $signature_method = + @$request->get_parameter("oauth_signature_method"); + if (!$signature_method) { + $signature_method = "PLAINTEXT"; + } + if (!in_array($signature_method, + array_keys($this->signature_methods))) { + throw new OAuthException( + "Signature method '$signature_method' not supported try one of the following: " . implode(", ", array_keys($this->signature_methods)) + ); + } + return $this->signature_methods[$signature_method]; + }/*}}}*/ + + /** + * try to find the consumer for the provided request's consumer key + */ + private function get_consumer(&$request) {/*{{{*/ + $consumer_key = @$request->get_parameter("oauth_consumer_key"); + if (!$consumer_key) { + throw new OAuthException("Invalid consumer key"); + } + + $consumer = $this->data_store->lookup_consumer($consumer_key); + if (!$consumer) { + throw new OAuthException("Invalid consumer"); + } + + return $consumer; + }/*}}}*/ + + /** + * try to find the token for the provided request's token key + */ + private function get_token(&$request, $consumer, $token_type="access") {/*{{{*/ + $token_field = @$request->get_parameter('oauth_token'); + $token = $this->data_store->lookup_token( + $consumer, $token_type, $token_field + ); + if (!$token) { + throw new OAuthException("Invalid $token_type token: $token_field"); + } + return $token; + }/*}}}*/ + + /** + * all-in-one function to check the signature on a request + * should guess the signature method appropriately + */ + private function check_signature(&$request, $consumer, $token) {/*{{{*/ + // this should probably be in a different method + $timestamp = @$request->get_parameter('oauth_timestamp'); + $nonce = @$request->get_parameter('oauth_nonce'); + + $this->check_timestamp($timestamp); + $this->check_nonce($consumer, $token, $nonce, $timestamp); + + $signature_method = $this->get_signature_method($request); + + $signature = $request->get_parameter('oauth_signature'); + $valid_sig = $signature_method->check_signature( + $request, + $consumer, + $token, + $signature + ); + + if (!$valid_sig) { + throw new OAuthException("Invalid signature"); + } + }/*}}}*/ + + /** + * check that the timestamp is new enough + */ + private function check_timestamp($timestamp) {/*{{{*/ + // verify that timestamp is recentish + $now = time(); + if ($now - $timestamp > $this->timestamp_threshold) { + throw new OAuthException("Expired timestamp, yours $timestamp, ours $now"); + } + }/*}}}*/ + + /** + * check that the nonce is not repeated + */ + private function check_nonce($consumer, $token, $nonce, $timestamp) {/*{{{*/ + // verify that the nonce is uniqueish + $found = $this->data_store->lookup_nonce($consumer, $token, $nonce, $timestamp); + if ($found) { + throw new OAuthException("Nonce already used: $nonce"); + } + }/*}}}*/ + + + +}/*}}}*/ + +class OAuthDataStore {/*{{{*/ + function lookup_consumer($consumer_key) {/*{{{*/ + // implement me + }/*}}}*/ + + function lookup_token($consumer, $token_type, $token) {/*{{{*/ + // implement me + }/*}}}*/ + + function lookup_nonce($consumer, $token, $nonce, $timestamp) {/*{{{*/ + // implement me + }/*}}}*/ + + function fetch_request_token($consumer) {/*{{{*/ + // return a new token attached to this consumer + }/*}}}*/ + + function fetch_access_token($token, $consumer) {/*{{{*/ + // return a new access token attached to this consumer + // for the user associated with this token if the request token + // is authorized + // should also invalidate the request token + }/*}}}*/ + +}/*}}}*/ + + +/* A very naive dbm-based oauth storage + */ +class SimpleOAuthDataStore extends OAuthDataStore {/*{{{*/ + private $dbh; + + function __construct($path = "oauth.gdbm") {/*{{{*/ + $this->dbh = dba_popen($path, 'c', 'gdbm'); + }/*}}}*/ + + function __destruct() {/*{{{*/ + dba_close($this->dbh); + }/*}}}*/ + + function lookup_consumer($consumer_key) {/*{{{*/ + $rv = dba_fetch("consumer_$consumer_key", $this->dbh); + if ($rv === FALSE) { + return NULL; + } + $obj = unserialize($rv); + if (!($obj instanceof OAuthConsumer)) { + return NULL; + } + return $obj; + }/*}}}*/ + + function lookup_token($consumer, $token_type, $token) {/*{{{*/ + $rv = dba_fetch("${token_type}_${token}", $this->dbh); + if ($rv === FALSE) { + return NULL; + } + $obj = unserialize($rv); + if (!($obj instanceof OAuthToken)) { + return NULL; + } + return $obj; + }/*}}}*/ + + function lookup_nonce($consumer, $token, $nonce, $timestamp) {/*{{{*/ + return dba_exists("nonce_$nonce", $this->dbh); + }/*}}}*/ + + function new_token($consumer, $type="request") {/*{{{*/ + $key = md5(time()); + $secret = time() + time(); + $token = new OAuthToken($key, md5(md5($secret))); + if (!dba_insert("${type}_$key", serialize($token), $this->dbh)) { + throw new OAuthException("doooom!"); + } + return $token; + }/*}}}*/ + + function new_request_token($consumer) {/*{{{*/ + return $this->new_token($consumer, "request"); + }/*}}}*/ + + function new_access_token($token, $consumer) {/*{{{*/ + + $token = $this->new_token($consumer, 'access'); + dba_delete("request_" . $token->key, $this->dbh); + return $token; + }/*}}}*/ +}/*}}}*/ + +class OAuthUtil {/*{{{*/ + public static function urlencodeRFC3986($string) {/*{{{*/ + return str_replace('%7E', '~', rawurlencode($string)); + }/*}}}*/ + + public static function urldecodeRFC3986($string) {/*{{{*/ + return rawurldecode($string); + }/*}}}*/ +}/*}}}*/ + +?> \ No newline at end of file diff --git a/3rdparty/Google/common.inc.php b/3rdparty/Google/common.inc.php new file mode 100755 index 00000000000..57185cdc4d8 --- /dev/null +++ b/3rdparty/Google/common.inc.php @@ -0,0 +1,185 @@ + + */ + +$PRIV_KEY_FILE = '/path/to/your/rsa_private_key.pem'; + +// OAuth library - http://oauth.googlecode.com/svn/code/php/ +require_once('OAuth.php'); + +// Google's accepted signature methods +$hmac_method = new OAuthSignatureMethod_HMAC_SHA1(); +$rsa_method = new OAuthSignatureMethod_RSA_SHA1(); +$SIG_METHODS = array($rsa_method->get_name() => $rsa_method, + $hmac_method->get_name() => $hmac_method); + +/** + * Makes an HTTP request to the specified URL + * + * @param string $http_method The HTTP method (GET, POST, PUT, DELETE) + * @param string $url Full URL of the resource to access + * @param array $extraHeaders (optional) Additional headers to include in each + * request. Elements are header/value pair strings ('Host: example.com') + * @param string $postData (optional) POST/PUT request body + * @param bool $returnResponseHeaders True if resp. headers should be returned. + * @return string Response body from the server + */ +function send_signed_request($http_method, $url, $extraHeaders=null, + $postData=null, $returnResponseHeaders=true) { + $curl = curl_init($url); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); + curl_setopt($curl, CURLOPT_FAILONERROR, false); + curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); + + // Return request headers in the reponse +// curl_setopt($curl, CURLINFO_HEADER_OUT, true); + + // Return response headers ni the response? + if ($returnResponseHeaders) { + curl_setopt($curl, CURLOPT_HEADER, true); + } + + $headers = array(); + //$headers[] = 'GData-Version: 2.0'; // use GData v2 by default + if (is_array($extraHeaders)) { + $headers = array_merge($headers, $extraHeaders); + } + + // Setup default curl options for each type of HTTP request. + // This is also a great place to add additional headers for each request. + switch($http_method) { + case 'GET': + curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); + break; + case 'POST': + curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); + curl_setopt($curl, CURLOPT_POST, 1); + curl_setopt($curl, CURLOPT_POSTFIELDS, $postData); + break; + case 'PUT': + $headers[] = 'If-Match: *'; + curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); + curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $http_method); + curl_setopt($curl, CURLOPT_POSTFIELDS, $postData); + break; + case 'DELETE': + $headers[] = 'If-Match: *'; + curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); + curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $http_method); + break; + default: + curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); + } + + // Execute the request. If an error occures, fill the response body with it. + $response = curl_exec($curl); + if (!$response) { + $response = curl_error($curl); + } + + // Add server's response headers to our response body + $response = curl_getinfo($curl, CURLINFO_HEADER_OUT) . $response; + + curl_close($curl); + + return $response; +} + +/** +* Takes XML as a string and returns it nicely indented +* +* @param string $xml The xml to beautify +* @param boolean $html_output True if returned XML should be escaped for HTML. +* @return string The beautified xml +*/ +function xml_pretty_printer($xml, $html_output=false) { + $xml_obj = new SimpleXMLElement($xml); + $level = 2; + + // Get an array containing each XML element + $xml = explode("\n", preg_replace('/>\s*', ">\n<", $xml_obj->asXML())); + + // Hold current indentation level + $indent = 0; + + $pretty = array(); + + // Shift off opening XML tag if present + if (count($xml) && preg_match('/^<\?\s*xml/', $xml[0])) { + $pretty[] = array_shift($xml); + } + + foreach ($xml as $el) { + if (preg_match('/^<([\w])+[^>\/]*>$/U', $el)) { + // opening tag, increase indent + $pretty[] = str_repeat(' ', $indent) . $el; + $indent += $level; + } else { + if (preg_match('/^<\/.+>$/', $el)) { + $indent -= $level; // closing tag, decrease indent + } + if ($indent < 0) { + $indent += $level; + } + $pretty[] = str_repeat(' ', $indent) . $el; + } + } + + $xml = implode("\n", $pretty); + return $html_output ? htmlentities($xml) : $xml; +} + +/** + * Joins key/value pairs by $inner_glue and each pair together by $outer_glue. + * + * Example: implode_assoc('=', '&', array('a' => 1, 'b' => 2)) === 'a=1&b=2' + * + * @param string $inner_glue What to implode each key/value pair with + * @param string $outer_glue What to impode each key/value string subset with + * @param array $array Associative array of query parameters + * @return string Urlencoded string of query parameters + */ +function implode_assoc($inner_glue, $outer_glue, $array) { + $output = array(); + foreach($array as $key => $item) { + $output[] = $key . $inner_glue . urlencode($item); + } + return implode($outer_glue, $output); +} + +/** + * Explodes a string of key/value url parameters into an associative array. + * This method performs the compliment operations of implode_assoc(). + * + * Example: explode_assoc('=', '&', 'a=1&b=2') === array('a' => 1, 'b' => 2) + * + * @param string $inner_glue What each key/value pair is joined with + * @param string $outer_glue What each set of key/value pairs is joined with. + * @param array $array Associative array of query parameters + * @return array Urlencoded string of query parameters + */ +function explode_assoc($inner_glue, $outer_glue, $params) { + $tempArr = explode($outer_glue, $params); + foreach($tempArr as $val) { + $pos = strpos($val, $inner_glue); + $key = substr($val, 0, $pos); + $array2[$key] = substr($val, $pos + 1, strlen($val)); + } + return $array2; +} + +?> \ No newline at end of file diff --git a/3rdparty/mediawiki/CSSMin.php b/3rdparty/mediawiki/CSSMin.php index 1ee2919140f..e9c2badf62b 100644 --- a/3rdparty/mediawiki/CSSMin.php +++ b/3rdparty/mediawiki/CSSMin.php @@ -172,7 +172,6 @@ class CSSMin { $type = self::getMimeType( $file ); // Detect when URLs were preceeded with embed tags, and also verify file size is // below the limit - var_dump($match['embed'], $file, filesize($file)); if ( $type && $match['embed'][1] > 0 diff --git a/3rdparty/phpass/PasswordHash.php b/3rdparty/phpass/PasswordHash.php index 12958c7f19e..84447b277df 100644 --- a/3rdparty/phpass/PasswordHash.php +++ b/3rdparty/phpass/PasswordHash.php @@ -48,7 +48,7 @@ class PasswordHash { function get_random_bytes($count) { $output = ''; - if (is_readable('/dev/urandom') && + if (@is_readable('/dev/urandom') && ($fh = @fopen('/dev/urandom', 'rb'))) { $output = fread($fh, $count); fclose($fh); diff --git a/apps/calendar/ajax/events.php b/apps/calendar/ajax/events.php index 56fa51aaff2..3f29f1e5eff 100644 --- a/apps/calendar/ajax/events.php +++ b/apps/calendar/ajax/events.php @@ -13,21 +13,19 @@ OCP\JSON::checkLoggedIn(); OCP\JSON::checkAppEnabled('calendar'); // Look for the calendar id -$calendar_id = OC_Calendar_App::getCalendar($_GET['calendar_id'], false, false); -if($calendar_id !== false){ - if(! is_numeric($calendar_id['userid']) && $calendar_id['userid'] != OCP\User::getUser()){ - OCP\JSON::error(); - exit; +$calendar_id = null; +if (strval(intval($_GET['calendar_id'])) == strval($_GET['calendar_id'])) { // integer for sure. + $id = intval($_GET['calendar_id']); + $calendarrow = OC_Calendar_App::getCalendar($id, true, false); // Let's at least security check otherwise we might as well use OC_Calendar_Calendar::find() + if($calendarrow !== false && is_int($calendar_id['userid']) && $id == $calendar_id['userid']) { + $calendar_id = $id; } } -else { - $calendar_id = $_GET['calendar_id']; -} +$calendar_id = (is_null($calendar_id)?strip_tags($_GET['calendar_id']):$calendar_id); $start = (version_compare(PHP_VERSION, '5.3.0', '>='))?DateTime::createFromFormat('U', $_GET['start']):new DateTime('@' . $_GET['start']); $end = (version_compare(PHP_VERSION, '5.3.0', '>='))?DateTime::createFromFormat('U', $_GET['end']):new DateTime('@' . $_GET['end']); $events = OC_Calendar_App::getrequestedEvents($calendar_id, $start, $end); - $output = array(); foreach($events as $event){ $output = array_merge($output, OC_Calendar_App::generateEventOutput($event, $start, $end)); diff --git a/apps/calendar/ajax/import/dropimport.php b/apps/calendar/ajax/import/dropimport.php index e98c282ef41..684eebf5fdd 100644 --- a/apps/calendar/ajax/import/dropimport.php +++ b/apps/calendar/ajax/import/dropimport.php @@ -45,7 +45,7 @@ foreach($lines as $line) { } $i++; } -$calendars = OC_Calendar_Calendar::allCalendars(OCP\USER::getUser(), 1); +$calendars = OC_Calendar_Calendar::allCalendars(OCP\USER::getUser(), true); $id = $calendars[0]['id']; foreach($uids as $uid) { $prefix=$suffix=$content=array(); diff --git a/apps/calendar/index.php b/apps/calendar/index.php index cf03a7a3cd3..4b871195927 100644 --- a/apps/calendar/index.php +++ b/apps/calendar/index.php @@ -11,15 +11,17 @@ OCP\User::checkLoggedIn(); OCP\App::checkAppEnabled('calendar'); // Create default calendar ... -$calendars = OC_Calendar_Calendar::allCalendars(OCP\USER::getUser(), 1); +$calendars = OC_Calendar_Calendar::allCalendars(OCP\USER::getUser(), false); if( count($calendars) == 0){ OC_Calendar_Calendar::addCalendar(OCP\USER::getUser(),'Default calendar'); - $calendars = OC_Calendar_Calendar::allCalendars(OCP\USER::getUser(), 1); + $calendars = OC_Calendar_Calendar::allCalendars(OCP\USER::getUser(), true); } $eventSources = array(); foreach($calendars as $calendar){ - $eventSources[] = OC_Calendar_Calendar::getEventSourceInfo($calendar); + if($calendar['active'] == 1) { + $eventSources[] = OC_Calendar_Calendar::getEventSourceInfo($calendar); + } } $eventSources[] = array('url' => '?app=calendar&getfile=ajax/events.php?calendar_id=shared_rw', 'backgroundColor' => '#1D2D44', 'borderColor' => '#888', 'textColor' => 'white', 'editable'=>'true'); @@ -54,9 +56,9 @@ OCP\Util::addscript('contacts','jquery.multi-autocomplete'); OCP\Util::addscript('','oc-vcategories'); OCP\App::setActiveNavigationEntry('calendar_index'); $tmpl = new OCP\Template('calendar', 'calendar', 'user'); -$tmpl->assign('eventSources', $eventSources); +$tmpl->assign('eventSources', $eventSources,false); $tmpl->assign('categories', $categories); if(array_key_exists('showevent', $_GET)){ - $tmpl->assign('showevent', $_GET['showevent']); + $tmpl->assign('showevent', $_GET['showevent'], false); } $tmpl->printPage(); diff --git a/apps/calendar/js/calendar.js b/apps/calendar/js/calendar.js index 7ae4a3a6eb1..5136c3e7745 100644 --- a/apps/calendar/js/calendar.js +++ b/apps/calendar/js/calendar.js @@ -430,6 +430,7 @@ Calendar={ $('#calendar_holder').fullCalendar('removeEventSource', url); $('#choosecalendar_dialog').dialog('destroy').remove(); Calendar.UI.Calendar.overview(); + $('#calendar_holder').fullCalendar('refetchEvents'); } }); } @@ -845,7 +846,7 @@ $(document).ready(function(){ dayNamesShort: dayNamesShort, allDayText: allDayText, viewDisplay: function(view) { - $('#datecontrol_date').html(view.title); + $('#datecontrol_date').val($('
').html(view.title).text()); if (view.name != defaultView) { $.post(OC.filePath('calendar', 'ajax', 'changeview.php'), {v:view.name}); defaultView = view.name; @@ -884,6 +885,22 @@ $(document).ready(function(){ loading: Calendar.UI.loading, eventSources: eventSources }); + $('#datecontrol_date').datepicker({ + changeMonth: true, + changeYear: true, + showButtonPanel: true, + beforeShow: function(input, inst) { + var calendar_holder = $('#calendar_holder'); + var date = calendar_holder.fullCalendar('getDate'); + inst.input.datepicker('setDate', date); + inst.input.val(calendar_holder.fullCalendar('getView').title); + return inst; + }, + onSelect: function(value, inst) { + var date = inst.input.datepicker('getDate'); + $('#calendar_holder').fullCalendar('gotoDate', date); + } + }); fillWindow($('#content')); OCCategories.changed = Calendar.UI.categoriesChanged; OCCategories.app = 'calendar'; diff --git a/apps/calendar/lib/app.php b/apps/calendar/lib/app.php index 2cd28c0f782..74cf9f01037 100644 --- a/apps/calendar/lib/app.php +++ b/apps/calendar/lib/app.php @@ -50,10 +50,7 @@ class OC_Calendar_App{ return false; } } - if($calendar === false){ - return false; - } - return OC_Calendar_Calendar::find($id); + return $calendar; } /* @@ -331,26 +328,29 @@ class OC_Calendar_App{ */ public static function getrequestedEvents($calendarid, $start, $end){ $events = array(); - if($calendarid == 'shared_rw' || $_GET['calendar_id'] == 'shared_r'){ + if($calendarid == 'shared_rw' || $calendarid == 'shared_r'){ $calendars = OC_Calendar_Share::allSharedwithuser(OCP\USER::getUser(), OC_Calendar_Share::CALENDAR, 1, ($_GET['calendar_id'] == 'shared_rw')?'rw':'r'); foreach($calendars as $calendar){ $calendarevents = OC_Calendar_Object::allInPeriod($calendar['calendarid'], $start, $end); + foreach($calendarevents as $event){ + $event['summary'] .= ' (' . self::$l10n->t('by') . ' ' . OC_Calendar_Object::getowner($event['id']) . ')'; + } $events = array_merge($events, $calendarevents); } $singleevents = OC_Calendar_Share::allSharedwithuser(OCP\USER::getUser(), OC_Calendar_Share::EVENT, 1, ($_GET['calendar_id'] == 'shared_rw')?'rw':'r'); foreach($singleevents as $singleevent){ $event = OC_Calendar_Object::find($singleevent['eventid']); + $event['summary'] .= ' (' . self::$l10n->t('by') . ' ' . OC_Calendar_Object::getowner($event['id']) . ')'; $events[] = $event; } }else{ - $calendar_id = $_GET['calendar_id']; - if (is_numeric($calendar_id)) { - $calendar = self::getCalendar($calendar_id); + if (is_numeric($calendarid)) { + $calendar = self::getCalendar($calendarid); OCP\Response::enableCaching(0); OCP\Response::setETagHeader($calendar['ctag']); - $events = OC_Calendar_Object::allInPeriod($calendar_id, $start, $end); + $events = OC_Calendar_Object::allInPeriod($calendarid, $start, $end); } else { - OCP\Util::emitHook('OC_Calendar', 'getEvents', array('calendar_id' => $calendar_id, 'events' => &$events)); + OCP\Util::emitHook('OC_Calendar', 'getEvents', array('calendar_id' => $calendarid, 'events' => &$events)); } } return $events; @@ -377,8 +377,8 @@ class OC_Calendar_App{ $lastmodified = ($last_modified)?$last_modified->getDateTime()->format('U'):0; $output = array('id'=>(int)$event['id'], - 'title' => htmlspecialchars(($event['summary']!=NULL || $event['summary'] != '')?$event['summary']: self::$l10n->t('unnamed')), - 'description' => isset($vevent->DESCRIPTION)?htmlspecialchars($vevent->DESCRIPTION->value):'', + 'title' => ($event['summary']!=NULL || $event['summary'] != '')?$event['summary']: self::$l10n->t('unnamed'), + 'description' => isset($vevent->DESCRIPTION)?$vevent->DESCRIPTION->value:'', 'lastmodified'=>$lastmodified); $dtstart = $vevent->DTSTART; diff --git a/apps/calendar/lib/calendar.php b/apps/calendar/lib/calendar.php index 869b35e2e1b..0a54e7a32a6 100644 --- a/apps/calendar/lib/calendar.php +++ b/apps/calendar/lib/calendar.php @@ -44,13 +44,13 @@ class OC_Calendar_Calendar{ /** * @brief Returns the list of calendars for a specific user. * @param string $uid User ID - * @param boolean $active Only return calendars with this $active state, default(=null) is don't care + * @param boolean $active Only return calendars with this $active state, default(=false) is don't care * @return array */ - public static function allCalendars($uid, $active=null){ + public static function allCalendars($uid, $active=false){ $values = array($uid); $active_where = ''; - if (!is_null($active) && $active){ + if ($active){ $active_where = ' AND active = ?'; $values[] = $active; } @@ -198,6 +198,10 @@ class OC_Calendar_Calendar{ $stmt = OCP\DB::prepare( 'DELETE FROM *PREFIX*calendar_objects WHERE calendarid = ?' ); $stmt->execute(array($id)); + if(count(self::allCalendars()) == 0) { + self::addCalendar(OCP\USER::getUser(),'Default calendar'); + } + return true; } diff --git a/apps/calendar/lib/search.php b/apps/calendar/lib/search.php index 03516b3b70c..6526b4223ac 100644 --- a/apps/calendar/lib/search.php +++ b/apps/calendar/lib/search.php @@ -1,7 +1,7 @@
diff --git a/apps/calendar/templates/part.choosecalendar.rowfields.php b/apps/calendar/templates/part.choosecalendar.rowfields.php index 268c3356011..965523f847a 100644 --- a/apps/calendar/templates/part.choosecalendar.rowfields.php +++ b/apps/calendar/templates/part.choosecalendar.rowfields.php @@ -1,8 +1,8 @@ '; -echo '