REBOL [
Title: "OAuth Scheme"
Date: 27-Sep-2012
Author: "Christopher Ross-Gill"
]
do http://reb4.me/r/altwebform
unless in system/schemes 'oauth [
system/schemes: make system/schemes [oauth: none]
]
system/schemes/oauth: make system/standard/port [
scheme: 'oauth
port-id: 0
handler: none
key: context [
consumer-key: consumer-secret: "ABCD"
]
user: context [
token: secret: "ABCD"
]
passive: none
cache-size: 5
proxy: make object! [host: port-id: user: pass: type: bypass: #[none]]
access: context [
oauth_callback: none
oauth_consumer_key: none
oauth_token: oauth_nonce: none
oauth_signature_method: "HMAC-SHA1"
oauth_timestamp: none
oauth_version: 1.0
oauth_verifier: oauth_signature: none
]
]
system/schemes/oauth/handler: context [
port-flags: system/standard/port-flags/pass-thru
init: func [port url /local spec][
unless all [
block? url
url? port/url
parse/all port/url ["http" opt "s" "://" some skip]
][
make error! "Not a valid OAuth Specification"
]
unless find [get post put delete] port/target [
make error! "No HTTP Method Specified"
]
port/timeout: enbase/base checksum/secure join now/precise port/key/consumer-key 64
any [date? port/date port/date: now]
port/date: form any [
attempt [to integer! difference port/date 1-Jan-1970/0:0:0]
port/date - 1-Jan-1970/0:0:0 * 86400.0
]
clear find/last port/date "."
port/sub-port: make port! port/url
]
sign: func [port [port!]][
port/pass: system/words/copy ""
port/access: make port/access [
oauth_consumer_key: port/key/consumer-key
oauth_token: port/user/token
oauth_nonce: port/timeout
oauth_timestamp: port/date
]
port/user-data: make port/access any [port/user-data []]
port/user-data: sort/skip third port/user-data 2
port/access/oauth_signature: enbase/base checksum/secure/key rejoin [
uppercase form port/target "&" url-encode form port/url "&"
url-encode replace/all to-webform port/user-data "+" "%20"
] rejoin [
port/key/consumer-secret "&" any [port/user/secret ""]
] 64
foreach [header value] third port/access [
if value [
repend port/pass [", " form header {="} url-encode form value {"}]
]
]
join "OAuth" next port/pass
]
open: func [port][
if object? port/user-data [port/user-data: third port/user-data]
switch port/target [
put delete [
port/access: compose [port/target: (uppercase form port/target) (any [port/user-data []])]
port/access: 'post
]
]
switch port/target [
get [
port/target: compose/deep [
header [Authorization: (sign port)]
]
if port/user-data [
port/user-data: context sort/skip port/user-data 2
port/sub-port/target: append any [port/sub-port/target ""] to-webform/prefix port/user-data
]
]
post put delete [
port/target: compose/deep [
(port/target) (either port/user-data [to-webform port/user-data][""]) [
Authorization: (sign port)
Content-Type: "application/x-www-form-urlencoded"
]
]
]
]
system/words/open/custom port/sub-port port/target
port/state/index: 0
port/state/flags: port/state/flags or port-flags
]
copy: func [port [port!]][
port/awake system/words/copy port/sub-port
]
close: func [port][
system/words/close port/sub-port
]
]