diff options
author | friendica <info@friendica.com> | 2013-09-16 21:35:52 -0700 |
---|---|---|
committer | friendica <info@friendica.com> | 2013-09-16 21:35:52 -0700 |
commit | 9bff739d9624d3a4ba1fb488673ec1a18bc6d395 (patch) | |
tree | d294230d4d3d41c96b1d550ab381722d0dc3eb00 | |
parent | 4b5d91ccb5e42bbd1d379b8963d932bbc8615634 (diff) | |
download | volse-hubzilla-9bff739d9624d3a4ba1fb488673ec1a18bc6d395.tar.gz volse-hubzilla-9bff739d9624d3a4ba1fb488673ec1a18bc6d395.tar.bz2 volse-hubzilla-9bff739d9624d3a4ba1fb488673ec1a18bc6d395.zip |
several oauth fixes - shred doesn't completely work yet, but it also doesn't completely NOT work, so at least there's some improvement
-rw-r--r-- | include/api.php | 11 | ||||
-rw-r--r-- | include/oauth.php | 67 | ||||
-rw-r--r-- | library/OAuth1.php | 13 | ||||
-rwxr-xr-x | util/shred/FriendicaOAuth.sh | 173 | ||||
-rwxr-xr-x | util/shred/JSON.sh | 129 | ||||
-rwxr-xr-x | util/shred/OAuth.sh | 214 | ||||
-rwxr-xr-x | util/shred/shred | 211 | ||||
-rw-r--r-- | version.inc | 2 |
8 files changed, 781 insertions, 39 deletions
diff --git a/include/api.php b/include/api.php index a49258d18..d76d82626 100644 --- a/include/api.php +++ b/include/api.php @@ -1823,9 +1823,13 @@ require_once('include/photos.php'); function api_oauth_request_token(&$a, $type){ try{ $oauth = new FKOAuth1(); - $r = $oauth->fetch_request_token(OAuthRequest::from_request()); + $req = OAuthRequest::from_request(); +logger('Req: ' . var_export($req,true)); + $r = $oauth->fetch_request_token($req); }catch(Exception $e){ - echo "error=". OAuthUtil::urlencode_rfc3986($e->getMessage()); killme(); + logger('oauth_exception: ' . print_r($e->getMessage(),true)); + echo "error=". OAuthUtil::urlencode_rfc3986($e->getMessage()); + killme(); } echo $r; killme(); @@ -1833,7 +1837,8 @@ require_once('include/photos.php'); function api_oauth_access_token(&$a, $type){ try{ $oauth = new FKOAuth1(); - $r = $oauth->fetch_access_token(OAuthRequest::from_request()); + $req = OAuthRequest::from_request(); + $r = $oauth->fetch_access_token($req); }catch(Exception $e){ echo "error=". OAuthUtil::urlencode_rfc3986($e->getMessage()); killme(); } diff --git a/include/oauth.php b/include/oauth.php index 6ec5285e4..b10802ecd 100644 --- a/include/oauth.php +++ b/include/oauth.php @@ -18,11 +18,12 @@ class FKOAuthDataStore extends OAuthDataStore { function lookup_consumer($consumer_key) { logger(__function__.":".$consumer_key); - //echo "<pre>"; var_dump($consumer_key); killme(); - +// echo "<pre>"; var_dump($consumer_key); killme(); + $r = q("SELECT client_id, pw, redirect_uri FROM clients WHERE client_id='%s'", dbesc($consumer_key) ); + if (count($r)) return new OAuthConsumer($r[0]['client_id'],$r[0]['pw'],$r[0]['redirect_uri']); return null; @@ -30,11 +31,13 @@ class FKOAuthDataStore extends OAuthDataStore { function lookup_token($consumer, $token_type, $token) { logger(__function__.":".$consumer.", ". $token_type.", ".$token); + $r = q("SELECT id, secret,scope, expires, uid FROM tokens WHERE client_id='%s' AND scope='%s' AND id='%s'", dbesc($consumer->key), dbesc($token_type), dbesc($token) ); + if (count($r)){ $ot=new OAuthToken($r[0]['id'],$r[0]['secret']); $ot->scope=$r[0]['scope']; @@ -46,12 +49,14 @@ class FKOAuthDataStore extends OAuthDataStore { } function lookup_nonce($consumer, $token, $nonce, $timestamp) { - //echo __file__.":".__line__."<pre>"; var_dump($consumer,$key); killme(); +// echo __file__.":".__line__."<pre>"; var_dump($consumer,$key); killme(); + $r = q("SELECT id, secret FROM tokens WHERE client_id='%s' AND id='%s' AND expires=%d", dbesc($consumer->key), dbesc($nonce), intval($timestamp) ); + if (count($r)) return new OAuthToken($r[0]['id'],$r[0]['secret']); return null; @@ -67,13 +72,14 @@ class FKOAuthDataStore extends OAuthDataStore { } else { $k = $consumer; } - + $r = q("INSERT INTO tokens (id, secret, client_id, scope, expires) VALUES ('%s','%s','%s','%s', UNIX_TIMESTAMP()+%d)", dbesc($key), dbesc($sec), dbesc($k), 'request', intval(REQUEST_TOKEN_DURATION)); + if (!$r) return null; return new OAuthToken($key,$sec); } @@ -95,6 +101,7 @@ class FKOAuthDataStore extends OAuthDataStore { $key = $this->gen_token(); $sec = $this->gen_token(); + $r = q("INSERT INTO tokens (id, secret, client_id, scope, expires, uid) VALUES ('%s','%s','%s','%s', UNIX_TIMESTAMP()+%d, %d)", dbesc($key), dbesc($sec), @@ -102,6 +109,7 @@ class FKOAuthDataStore extends OAuthDataStore { 'access', intval(ACCESS_TOKEN_DURATION), intval($uverifier)); + if ($r) $ret = new OAuthToken($key,$sec); } @@ -131,9 +139,9 @@ class FKOAuth1 extends OAuthServer { } function loginUser($uid){ - logger("FKOAuth1::loginUser $uid"); + logger("RedOAuth1::loginUser $uid"); $a = get_app(); - $r = q("SELECT * FROM `user` WHERE uid=%d AND `blocked` = 0 AND `account_expired` = 0 AND `verified` = 1 LIMIT 1", + $r = q("SELECT * FROM channel WHERE channel_id = %d LIMIT 1", intval($uid) ); if(count($r)){ @@ -143,35 +151,36 @@ class FKOAuth1 extends OAuthServer { header('HTTP/1.0 401 Unauthorized'); die('This api requires login'); } - $_SESSION['uid'] = $record['uid']; - $_SESSION['theme'] = $record['theme']; - $_SESSION['mobile_theme'] = get_pconfig($record['uid'], 'system', 'mobile_theme'); + $_SESSION['uid'] = $record['channel_id']; + $_SESSION['theme'] = $record['channel_theme']; + $_SESSION['account_id'] = $record['channel_account_id']; + $_SESSION['mobile_theme'] = get_pconfig($record['channel_id'], 'system', 'mobile_theme'); $_SESSION['authenticated'] = 1; - $_SESSION['page_flags'] = $record['page-flags']; - $_SESSION['my_url'] = $a->get_baseurl() . '/channel/' . $record['nickname']; +// $_SESSION['page_flags'] = $record['page-flags']; + $_SESSION['my_url'] = $a->get_baseurl() . '/channel/' . $record['channel_address']; $_SESSION['addr'] = $_SERVER['REMOTE_ADDR']; + $_SESSION['allow_api'] = true; - //notice( t("Welcome back ") . $record['username'] . EOL); - $a->user = $record; + $a->channel = $record; - if(strlen($a->user['timezone'])) { - date_default_timezone_set($a->user['timezone']); - $a->timezone = $a->user['timezone']; + if(strlen($a->channel['channel_timezone'])) { + date_default_timezone_set($a->channel['channel_timezone']); +// $a->timezone = $a->user['timezone']; } - $r = q("SELECT * FROM `contact` WHERE `uid` = %s AND `self` = 1 LIMIT 1", - intval($_SESSION['uid'])); - if(count($r)) { - $a->contact = $r[0]; - $a->cid = $r[0]['id']; - $_SESSION['cid'] = $a->cid; - } - q("UPDATE `user` SET `login_date` = '%s' WHERE `uid` = %d LIMIT 1", - dbesc(datetime_convert()), - intval($_SESSION['uid']) - ); - - call_hooks('logged_in', $a->user); +// $r = q("SELECT * FROM `contact` WHERE `uid` = %s AND `self` = 1 LIMIT 1", +// intval($_SESSION['uid'])); +// if(count($r)) { +// $a->contact = $r[0]; +// $a->cid = $r[0]['id']; +// $_SESSION['cid'] = $a->cid; +// } +// q("UPDATE `user` SET `login_date` = '%s' WHERE `uid` = %d LIMIT 1", +// dbesc(datetime_convert()), +// intval($_SESSION['uid']) +// ); +// +// call_hooks('logged_in', $a->user); } } diff --git a/library/OAuth1.php b/library/OAuth1.php index 0db6fabcb..b790655af 100644 --- a/library/OAuth1.php +++ b/library/OAuth1.php @@ -273,6 +273,7 @@ class OAuthRequest { && @strstr($request_headers["Content-Type"], "application/x-www-form-urlencoded") ) { + $post_data = OAuthUtil::parse_parameters( file_get_contents(self::$POST_INPUT) ); @@ -286,15 +287,15 @@ class OAuthRequest { $request_headers['Authorization'] ); $parameters = array_merge($parameters, $header_parameters); + } } // fix for friendica redirect system - + // FIXME or don't, but figure out if this is absolutely necessary and act accordingly $http_url = substr($http_url, 0, strpos($http_url,$parameters['q'])+strlen($parameters['q'])); unset( $parameters['q'] ); - //echo "<pre>".__function__."\n"; var_dump($http_method, $http_url, $parameters, $_SERVER['REQUEST_URI']); killme(); return new OAuthRequest($http_method, $http_url, $parameters); } @@ -514,9 +515,7 @@ class OAuthServer { */ 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; @@ -525,7 +524,6 @@ class OAuthServer { // Rev A change $callback = $request->get_parameter('oauth_callback'); $new_token = $this->data_store->new_request_token($consumer, $callback); - return $new_token; } @@ -796,7 +794,8 @@ class OAuthUtil { ); $out[$key] = $value; } - } else { + } + if((! isset($out)) || (! array_key_exists('Authorization',$out))) { // otherwise we don't have apache and are just going to have to hope // that $_SERVER actually contains what we need $out = array(); @@ -806,6 +805,8 @@ class OAuthUtil { $out['Content-Type'] = $_ENV['CONTENT_TYPE']; foreach ($_SERVER as $key => $value) { + if($key === 'REDIRECT_REMOTE_USER') + $out['Authorization'] = $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 diff --git a/util/shred/FriendicaOAuth.sh b/util/shred/FriendicaOAuth.sh new file mode 100755 index 000000000..a20da7879 --- /dev/null +++ b/util/shred/FriendicaOAuth.sh @@ -0,0 +1,173 @@ +#!/bin/bash +# Copyright (c) 2012 Fabio Comuni +# Copyright (c) 2012 Michael Nowack +# Copyright (c) 2010, 2012 Yu-Jie Lin +# +# 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. + +FRIENDICAOAUTH_VERSION=0.1.1 + +F_API_VERSION="1" + +# Friendica API endpoints + +F_ACCOUNF_UPDATE_PROFILE_IMAGE="${redmatrix_url}/api/account/update_profile_image" +F_STATUSES_UPDATE="${redmatrix_url}/api/statuses/update" +F_STATUSES_HOME_TIMELINE="${redmatrix_url}/api/statuses/home_timeline" + +F_REQUESF_TOKEN=${redmatrix_url}'/api/oauth/request_token' +F_ACCESS_TOKEN=${redmatrix_url}'/api/oauth/access_token' +F_AUTHORIZE_TOKEN=${redmatrix_url}'/api/oauth/authorize' + +# Source OAuth.sh + +OAuth_sh=$(which OAuth.sh) +(( $? != 0 )) && echo 'Unable to locate OAuth.sh! Make sure it is in searching PATH.' && exit 1 +source "$OAuth_sh" + +FO_debug () { + # Print out all parameters, each in own line + [[ "$FO_DEBUG" == "" ]] && return + local t=$(date +%FT%T.%N) + while (( $# > 0 )); do + echo "[FO][DEBUG][$t] $1" + shift 1 + done + } + +FO_extract_value () { + # $1 key name + # $2 string to find + egrep -o "$1=[a-zA-Z0-9-]*" <<< "$2" | cut -d\= -f 2 + } + + +FO_init() { + # Initialize FriendicaOAuth + oauth_version='1.0' + oauth_signature_method='HMAC-SHA1' + oauth_basic_params=( + $(OAuth_param 'oauth_consumer_key' "$oauth_consumer_key") + $(OAuth_param 'oauth_signature_method' "$oauth_signature_method") + $(OAuth_param 'oauth_version' "$oauth_version") + ) + } + +FO_access_token_helper () { + # Help guide user to get access token + + local resp PIN + + # Request Token + + local auth_header="$(_OAuth_authorization_header 'Authorization' "$redmatrix_url/" "$oauth_consumer_key" "$oauth_consumer_secret" '' '' "$oauth_signature_method" "$oauth_version" "$(OAuth_nonce)" "$(OAuth_timestamp)" 'POST' "$F_REQUESF_TOKEN" "$(OAuth_param 'oauth_callback' 'oob')"), $(OAuth_param_quote 'oauth_callback' 'oob')" + +# echo $auth_header +# echo $F_REQUESF_TOKEN + + resp=$(curl -s -d '' -H "$auth_header" "$F_REQUESF_TOKEN") + FO_rval=$? + (( $? != 0 )) && return $FO_rval + + local _oauth_token=$(FO_extract_value 'oauth_token' "$resp") + local _oauth_token_secret=$(FO_extract_value 'oauth_token_secret' "$resp") + + echo 'Please go to the following link to get the PIN:' + echo " ${F_AUTHORIZE_TOKEN}?oauth_token=$_oauth_token" + + read -p 'PIN: ' PIN + + # Access Token + + local auth_header="$(_OAuth_authorization_header 'Authorization' "$redmatrix_url/" "$oauth_consumer_key" "$oauth_consumer_secret" "$_oauth_token" "$_oauth_token_secret" "$oauth_signature_method" "$oauth_version" "$(OAuth_nonce)" "$(OAuth_timestamp)" 'POST' "$F_ACCESS_TOKEN" "$(OAuth_param 'oauth_verifier' "$PIN")"), $(OAuth_param_quote 'oauth_verifier' "$PIN")" + + resp=$(curl -s -d "" -H "$auth_header" "$F_ACCESS_TOKEN") + FO_rval=$? + (( $? != 0 )) && return $FO_rval + + FO_ret=( + $(FO_extract_value 'oauth_token' "$resp") + $(FO_extract_value 'oauth_token_secret' "$resp") + $(FO_extract_value 'user_id' "$resp") + $(FO_extract_value 'screen_name' "$resp") + ) + } + +# APIs +###### + +FO_statuses_update () { + # $1 format + # $2 status + # $3 in_reply_to_status_id + # The followins are not implemented yet: + # $4 lat + # $5 long + # $6 place_id + # $7 display_coordinates + local format="$1" + [[ "$format" == "" ]] && format="xml" + + local params=( + $(OAuth_param 'status' "$2") + ) + + params[${#params[@]}]=$(OAuth_param 'source' "fcli") + + [[ "$3" != "" ]] && params[${#params[@]}]=$(OAuth_param 'in_reply_to_status_id' "$3") && local in_reply_to_status_id=( '--data-urlencode' "in_reply_to_status_id=$3" ) + + + local auth_header=$(OAuth_authorization_header 'Authorization' "$redmatrix_url" '' '' 'POST' "$F_STATUSES_UPDATE.$format" ${params[@]}) + + + FO_ret=$(curl -s -H "$auth_header" --data-urlencode "status=$2" --data-urlencode "source=fcli" ${in_reply_to_status_id[@]} "$F_STATUSES_UPDATE.$format") + + FO_rval=$? + return $FO_rval + } + + +# gets the user home_timeline. +# +# @sets FO_ret API response +# @returns status +# @public +FO_statuses_home_timeline () { + # $1 format + # $2 screen_name + # $3 count + local format="$1" + local screen_name="$2" + local count="$3" + [[ "$format" == "" ]] && format="xml" + [[ "$count" == "" ]] && count=1 + + local params=( + $(OAuth_param 'screen_name' $screen_name) + $(OAuth_param 'count' $count) + ) +g + local auth_header=$(OAuth_authorization_header 'Authorization' "$redmatrix_url" '' '' 'GET' "$F_STATUSES_HOME_TIMELINE.$format" ${params[@]}) + + convscreen=$(OAuth_PE "$screen_name"); + FO_ret=$(curl -s --get "${F_STATUSES_HOME_TIMELINE}.${format}" --data "screen_name=${convscreen}&count=${count}" --header "${auth_header}") + FO_rval=$? + + return $FO_rval + } diff --git a/util/shred/JSON.sh b/util/shred/JSON.sh new file mode 100755 index 000000000..65f5f1f66 --- /dev/null +++ b/util/shred/JSON.sh @@ -0,0 +1,129 @@ +# The MIT License +# +# Copyright (c) 2011 Dominic Tarr +# +# 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. +# +# +# https://github.com/dominictarr/JSON.sh +# +throw () { + echo "$*" >&2 + exit 1 +} + +tokenize () { + local ESCAPE='(\\[^u[:cntrl:]]|\\u[0-9a-fA-F]{4})' + local CHAR='[^[:cntrl:]"\\]' + local STRING="\"$CHAR*($ESCAPE$CHAR*)*\"" + local NUMBER='-?(0|[1-9][0-9]*)([.][0-9]*)?([eE][+-]?[0-9]*)?' + local KEYWORD='null|false|true' + local SPACE='[[:space:]]+' + egrep -ao "$STRING|$NUMBER|$KEYWORD|$SPACE|." --color=never | + egrep -v "^$SPACE$" # eat whitespace +} + +parse_array () { + local index=0 + local ary='' + read -r token + case "$token" in + ']') ;; + *) + while : + do + parse_value "$1" "$index" + let index=$index+1 + ary="$ary""$value" + read -r token + case "$token" in + ']') break ;; + ',') ary="$ary," ;; + *) throw "EXPECTED , or ] GOT ${token:-EOF}" ;; + esac + read -r token + done + ;; + esac + value=`printf '[%s]' "$ary"` +} + +parse_object () { + local key + local obj='' + read -r token + case "$token" in + '}') ;; + *) + while : + do + case "$token" in + '"'*'"') key=$token ;; + *) throw "EXPECTED string GOT ${token:-EOF}" ;; + esac + read -r token + case "$token" in + ':') ;; + *) throw "EXPECTED : GOT ${token:-EOF}" ;; + esac + read -r token + parse_value "$1" "$key" + obj="$obj$key:$value" + read -r token + case "$token" in + '}') break ;; + ',') obj="$obj," ;; + *) throw "EXPECTED , or } GOT ${token:-EOF}" ;; + esac + read -r token + done + ;; + esac + value=`printf '{%s}' "$obj"` +} + +parse_value () { + local jpath="${1:+$1,}$2" + case "$token" in + '{') parse_object "$jpath" ;; + '[') parse_array "$jpath" ;; + # At this point, the only valid single-character tokens are digits. + ''|[^0-9]) throw "EXPECTED value GOT ${token:-EOF}" ;; + *) value=$token ;; + esac + printf "[%s]\t%s\n" "$jpath" "$value" +} + +parse () { + read -r token + parse_value + read -r token + case "$token" in + '') ;; + *) throw "EXPECTED EOF GOT $token" ;; + esac +} + +if [ $0 = $BASH_SOURCE ]; +then + tokenize | parse +fi diff --git a/util/shred/OAuth.sh b/util/shred/OAuth.sh new file mode 100755 index 000000000..4be4ed35b --- /dev/null +++ b/util/shred/OAuth.sh @@ -0,0 +1,214 @@ +#!/bin/bash +# Copyright (c) 2010, 2012 Yu-Jie Lin +# +# 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. + +BASHOAUTH_VERSION=0.1.2 + +OAuth_debug () { + # Print out all parameters, each in own line + [[ "$OAUTH_DEBUG" == "" ]] && return + local t=$(date +%FT%T.%N) + while (( $# > 0 )); do + echo "[OAuth][DEBUG][$t] $1" + shift 1 + done + } + +OAuth_nonce () { + # Return a nonce + md5sum <<< "$RANDOM-$(date +%s.%N)" | cut -d' ' -f 1 + } + +OAuth_timestamp () { + # Return timestamp + echo "$(date +%s)" + } + +OAuth_PE () { + # Encode $1 using Percent-encoding as defined in + # http://tools.ietf.org/html/rfc5849#section-3.6 + # Any character other than [a-zA-Z0-9-._~] is converted into format %XX + [ -n "$1" ] \ + && echo -n "$1" | perl -p -e 's/([^A-Za-z0-9-._~])/sprintf("%%%02X", ord($1))/seg' +} + +OAuth_PE_file () { + # Encode a file $1 using Percent-encoding as defined in + # http://tools.ietf.org/html/rfc5849#section-3.6 + # $1 a filename, not the content of file + perl -p -e 's/([^A-Za-z0-9-._~])/sprintf("%%%02X", ord($1))/seg' < "$1" +} + +OAuth_params_string () { + # Sort the paramters and join them into one-line string + while (( $# > 0 )); do + echo $1 + shift 1 + done | sort | tr '\n' '&' | sed 's/&$//' + } + +OAuth_base_string () { + # $1 method: "GET", "POST", etc + # $2 url + # $3-$N params + local method=$1 + local url=$2 + shift 2 + + local params_string=$(OAuth_params_string $@) + + echo "$method&$(OAuth_PE "$url")&$(OAuth_PE "$params_string")" + } + +OAuth_param () { + # Return a percent encoded key-value pair + # $1 key + # $2 value + echo "$(OAuth_PE "$1")=$(OAuth_PE "$2")" + } + +OAuth_param_quote () { + # Return a percent encoded key-value pair, value is quoted + # $1 key + # $2 value + echo "$(OAuth_PE "$1")=\"$(OAuth_PE "$2")\"" + } + +OAuth_param_file () { + # Return a percent encoded key-value pair, the value is an encoded file content + # $1 key + # $2 filename + echo "$(OAuth_PE "$1")=$(OAuth_PE_file "$2")" + } + +OAuth_param_raw_value () { + # Return a percent encoded key-value pair, only key will be encoded by this function + # $1 key + # $2 value + echo "$(OAuth_PE "$1")=$2" + } + +OAuth_HMAC_SHA1 () { + # Hash the text $1 with key $2 + local text="$1" + local key="$2" + echo -n "$text" | openssl dgst -sha1 -binary -hmac "$key" | base64 + } + +_OAuth_signature () { + # Return the signature, note it's necessary to pass to OAuth_PE before add to header + # $1 signature_method + # $2 base_string + # $3 consumer_secret + # $4 token_secret + local signature_method="OAuth_${1//-/_}" + local base_string=$2 + local c_secret=$3 + local t_secret=$4 + $signature_method "$base_string" "$c_secret&$t_secret" + } + +OAuth_signature () { + # Return the signature, note it's necessary to pass to OAuth_PE before add to header + # $1 base_string + _OAuth_signature "$oauth_signature_method" "$1" "$oauth_consumer_secret" "$oauth_token_secret" + } + +_OAuth_authorization_header_params_string () { + while (( $# > 0 )); do + echo -n "$(cut -d\= -f 1 <<< "$1")=\"$(cut -d\= -f 2 <<< "$1")\"" + shift 1 + # Use break to prevent error code being returned + (( $# > 0 )) && echo -n ', ' || break + done + } + +_OAuth_authorization_header () { + # Return header string + # $1 header key + # $2 OAuth realm, can be empty string + # $3 OAuth consumer key + # $4 OAuth consumer secret + # $5 OAuth token + # $6 OAuth token secret + # $7 OAuth signature method + # $8 OAuth version + # $9 nonce + # $10 timestamp + # $11 method + # $12 url + # $13-$N params + echo -n "$1: OAuth " + [[ "$2" != "" ]] && echo -n "realm=\"$2\", " + local oauth_consumer_key="$3" + local oauth_consumer_secret="$4" + local oauth_token="$5" + local oauth_token_secret="$6" + local oauth_signature_method="$7" + local oauth_version="$8" + local oauth_nonce="$9" + [[ "$oauth_nonce" == "" ]] && oauth_nonce="$(OAuth_nonce)" + local oauth_timestamp="${10}" + [[ "$oauth_timestamp" == "" ]] && oauth_timestamp="$(OAuth_timestamp)" + local method="${11}" + local url="${12}" + shift 12 + local params=( + $(OAuth_param 'oauth_consumer_key' "$oauth_consumer_key") + $(OAuth_param 'oauth_signature_method' "$oauth_signature_method") + $(OAuth_param 'oauth_version' "$oauth_version") + $(OAuth_param 'oauth_nonce' "$oauth_nonce") + $(OAuth_param 'oauth_timestamp' "$oauth_timestamp") + ) + [[ "$oauth_token" != "" ]] && params[${#params[@]}]=$(OAuth_param 'oauth_token' "$oauth_token") + local sign_params=${params[@]} + while (( $# > 0 )); do + sign_params[${#sign_params[@]}]="$1" + shift 1 + done + local base_string=$(OAuth_base_string "$method" "$url" ${sign_params[@]}) + local signature=$(_OAuth_signature "$oauth_signature_method" "$base_string" "$oauth_consumer_secret" "$oauth_token_secret") + params[${#params[@]}]=$(OAuth_param 'oauth_signature' "$signature") + _OAuth_authorization_header_params_string ${params[@]} + } + +OAuth_authorization_header () { + # Return header string + # $1 header key + # $2 OAuth realm, can be empty string + # $3 OAuth nonce + # $4 OAuth timestamp + # $5 method + # $6 url + # $7-$N params + local header_key="$1" + local realm="$2" + local oauth_nonce="$3" + local oauth_timestamp="$4" + local method="$5" + local url="$6" + shift 6 + local params=() + while (( $# > 0 )); do + params[${#params[@]}]="$1" + shift 1 + done + _OAuth_authorization_header "$header_key" "$realm" "$oauth_consumer_key" "$oauth_consumer_secret" "$oauth_token" "$oauth_token_secret" "$oauth_signature_method" "$oauth_version" "$oauth_nonce" "$oauth_timestamp" "$method" "$url" ${params[@]} + } diff --git a/util/shred/shred b/util/shred/shred new file mode 100755 index 000000000..113898ff9 --- /dev/null +++ b/util/shred/shred @@ -0,0 +1,211 @@ +#!/bin/bash +# Copyright (c) 2012 Fabio Comuni +# Copyright (c) 2010, 2012 Yu-Jie Lin +# +# 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. + +FCLI_RC="$HOME/.shred.rc" + +# Source Config +[[ -f "$FCLI_RC" ]] && . "$FCLI_RC" || show_config_help 1 + +# Source FriendicaOAuth.sh +OAuth_sh=$(which FriendicaOAuth.sh) +(( $? != 0 )) && echo 'Unable to locate FriendicaOAuth.sh! Make sure it is in searching PATH.' && exit 1 +source "$OAuth_sh" + +# Source JSON.sh +JSON_sh=$(which JSON.sh) +(( $? != 0 )) && echo 'Unable to locate JSON.sh! Make sure it is in searching PATH.' && exit 1 +source "$JSON_sh" + + +usage () { + echo "usage: $0 options + +OPTIONS: + -h Show this message + + -c Command + + Valid Commands: + statuses_update + home_timeline + +Use -h -c command to get options for the command. +" + exit $1 + } + +show_config_help () { + echo "Please create $FCLI_RC with: +redmatrix_url=YOR_SERVER_URL (no trailing /) +oauth_consumer_key=YOUR_CONSUMER_KEY +oauth_consumer_secret=YOUR_CONSUMER_SECRET + +You can register new app consumer key and secret at + http://yourserver.com/settings/oauth +" + exit $1 + } + + +show_statuses_update () { + echo "Command statuses_update + +Requires: + -s status + +Optional: + -r in_reply_to_status_id +" + exit $1 + } + +show_home_timeline () { + echo "Command home_timeline" + + exit $1 + } + +#json helper +# +# usage: +# echo "$parsed_json" | js key1 [key2 [key3 ...]][,] +# +# echoes the value of json[key1][key2][key3], without surronding quotes +# with "," as last argument, no newline is printed +# +js () { + local arg + local rg='^\[' + local ret + for arg in $@ + do + [[ "$arg" == "," ]] && break; + if [[ $arg == ${arg//[0-9]/} ]] + then + rg="${rg}\"$arg\"," + else + rg="${rg}$arg," + fi + done + rg="${rg%?}\]" + ret=$(grep $rg | cut -f 2 | sed 's/^"\(.*\)"$/\1/' | sed "s/\\\\\//\//g" ) + if [[ "$arg" == "," ]] + then + echo -e "$ret" | tr -d '\012\015' + else + echo -e "$ret" + fi +} + + +load_config () { + + [[ "$oauth_consumer_key" == "" ]] && show_config_help 1 + [[ "$oauth_consumer_secret" == "" ]] && show_config_help 1 + + + FO_init + + if [[ "$oauth_token" == "" ]] || [[ "$oauth_token_secret" == "" ]]; then + FO_access_token_helper + if (( $? == 0 )); then + oauth_token=${FO_ret[0]} + oauth_token_secret=${FO_ret[1]} + echo "oauth_token='${FO_ret[0]}'" >> "$FCLI_RC" + echo "oauth_token_secret='${FO_ret[1]}'" >> "$FCLI_RC" + echo "Token saved." + else + echo 'Unable to get access token' + exit 1 + fi + fi + } + +main () { + load_config + + fcli_command= + fcli_status= + fcli_in_reply_to_status_id= + fcli_file= + fcli_help_flag= + while getopts "c:s:r:f:h" name + do + case $name in + c) fcli_command="$OPTARG";; + s) fcli_status="$OPTARG";; + r) fcli_in_reply_to_status_id="$OPTARG";; + f) fcli_file="$OPTARG";; + h) fcli_help_flag="1";; + ?) usage + exit 2;; + esac + done + + if [[ "$fcli_help_flag" == "1" ]]; then case $fcli_command in + statuses_update) + show_statuses_update 0 + ;; + home_timeline) + show_home_timeline 0 + ;; + *) + [[ "$fcli_command" == "" ]] && usage 0 + usage 1 + esac ; fi + + case $fcli_command in + home_timeline) + FO_statuses_home_timeline 'json' '' 5 + JS_Parsed=$(echo "$FO_ret" | tokenize | parse) + for id in 0 1 2 3 4 + do + echo "$JS_Parsed" | js $id "user" "name" , + echo -n " - " + echo "$JS_Parsed" | js $id "created_at" + echo "$JS_Parsed" | js $id "text" + echo "" + echo "------------------------------------------------------------------------------" + done + + return $FO_rval + ;; + statuses_update) + [[ "$fcli_status" == "" ]] && show_statuses_update 1 + FO_statuses_update 'json' "$fcli_status" "$fcli_in_reply_to_status_id" + JS_Parsed=$(echo "$FO_ret" | tokenize | parse) + echo "$JS_Parsed" | js "user" "name" , + echo -n " - " + echo "$JS_Parsed" | js "created_at" + echo "$JS_Parsed" | js "text" + echo "" + echo "------------------------------------------------------------------------------" + return $FO_rval + ;; + *) + usage 1 + ;; + esac + return 0 + } + +main "$@" diff --git a/version.inc b/version.inc index 2ee9add97..186ac999c 100644 --- a/version.inc +++ b/version.inc @@ -1 +1 @@ -2013-09-15.437 +2013-09-16.438 |