2323 */
2424class OAuthListener implements ListenerInterface
2525{
26+ const ENDPOINT_REQUEST_TOKEN = 'oauth/request_token ' ;
27+ const ENDPOINT_ACCESS_TOKEN = 'oauth/access_token ' ;
28+ const ENDPOINT_AUTHORIZE = 'oauth/authenticate ' ;
29+
2630 /**
2731 * @var array
2832 */
@@ -34,7 +38,7 @@ class OAuthListener implements ListenerInterface
3438 'oauth_signature_method ' => 'HMAC-SHA1 ' ,
3539 'oauth_callback ' => '' ,
3640 'oauth_verifier ' => '' ,
37- 'oauth_version ' => ''
41+ 'oauth_version ' => '1.0 '
3842 );
3943
4044 /**
@@ -64,7 +68,7 @@ public function __construct(
6468
6569 $ this ->token = (!is_null ($ token )) ?
6670 $ token :
67- ! isset ($ this ->config ['oauth_token ' ]) ?
71+ empty ($ this ->config ['oauth_token ' ]) ?
6872 new OAuth1 \Token \NullToken :
6973 new OAuth1 \Token \Token ($ this ->config ['oauth_token ' ], $ this ->config ['oauth_token_secret ' ])
7074 ;
@@ -89,14 +93,104 @@ public function getName()
8993 * {@inheritDoc}
9094 */
9195 public function preSend (RequestInterface $ request )
92- {}
96+ {
97+ $ params = $ this ->getParametersToSign ($ request );
98+ $ req = OAuth1 \Request \Request::fromConsumerAndToken (
99+ $ this ->consumer , $ this ->token , $ request ->getMethod (), $ request ->getUrl (), $ params
100+ );
101+
102+ $ req ->signRequest ($ this ->signature , $ this ->consumer , $ this ->token );
103+
104+ $ request ->addHeader ($ req ->toHeader ());
105+ }
93106
94107 /**
95108 * {@inheritDoc}
96109 */
97110 public function postSend (RequestInterface $ request , MessageInterface $ response )
98111 {}
99112
113+ /**
114+ * Include OAuth and request body parameters
115+ *
116+ * @access protected
117+ * @param RequestInterface $request
118+ * @return array
119+ *
120+ * @see http://oauth.net/core/1.0/#sig_norm_param
121+ */
122+ protected function getParametersToSign (RequestInterface $ request )
123+ {
124+ return array_merge ($ this ->getOAuthParameters ($ request ), $ this ->getContentAsParameters ($ request ));
125+ }
126+
127+ /**
128+ * Include/exclude optional parameters
129+ *
130+ * The exclusion/inclusion is based on current request resource
131+ *
132+ * @access protected
133+ * @param RequestInterface $request
134+ * @return array
135+ */
136+ protected function getOAuthParameters (RequestInterface $ request )
137+ {
138+ $ params = $ this ->filterOAuthParameters (array ('oauth_token ' , 'oauth_version ' ));
139+
140+ if ($ this ->isEndpointRequested (self ::ENDPOINT_REQUEST_TOKEN , $ request )) {
141+ $ params = $ this ->filterOAuthParameters (array ('oauth_callback ' ));
142+ } elseif ($ this ->isEndpointRequested (self ::ENDPOINT_ACCESS_TOKEN , $ request )) {
143+ $ params = $ this ->filterOAuthParameters (array ('oauth_token ' , 'oauth_verifier ' ));
144+ }
145+
146+ return $ params ;
147+ }
148+
149+ /**
150+ * White list based filter
151+ *
152+ * @param array $include
153+ * @return array
154+ */
155+ protected function filterOAuthParameters (array $ include )
156+ {
157+ $ final = array ();
158+
159+ foreach ($ include as $ key => $ value ) {
160+ if (!empty ($ this ->config [$ value ])) {
161+ $ final [$ value ] = $ this ->config [$ value ];
162+ }
163+ }
164+
165+ return $ final ;
166+ }
167+
168+ /**
169+ * Transform request content to associative array
170+ *
171+ * @access protected
172+ * @param RequestInterface $request
173+ * @return array
174+ */
175+ protected function getContentAsParameters (RequestInterface $ request )
176+ {
177+ parse_str ($ request ->getContent (), $ parts );
178+
179+ return $ parts ;
180+ }
181+
182+ /**
183+ * Check if specified endpoint is in current request
184+ *
185+ * @param string $endpoint
186+ * @param RequestInterface $request
187+ * @return bool
188+ */
189+ protected function isEndpointRequested ($ endpoint , RequestInterface $ request )
190+ {
191+ return strpos ($ request ->getResource (), $ endpoint ) !== false ;
192+ }
193+
100194 /**
101195 * Bitbucket supports only HMAC-SHA1 and PlainText signatures.
102196 *
0 commit comments