Dotclear

source: plugins/TaC/inc/class.tac.php @ 2628

Revision 2628, 13.1 KB checked in by JcDenis, 13 years ago (diff)

TaC - Twitter Authentication Client 0.1-alpha5

  • First lab release
RevLine 
[2628]1<?php
2# -- BEGIN LICENSE BLOCK ----------------------------------
3# This file is part of TaC, a plugin for Dotclear 2.
4#
5# Copyright (c) 2009-2010 JC Denis and contributors
6# jcdenis@gdwd.com
7#
8# Licensed under the GPL version 2.0 license.
9# A copy of this license is available in LICENSE file or at
10# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
11# -- END LICENSE BLOCK ------------------------------------
12
13
14class tac
15{
16     /* Vars */
17     /* Contains the last HTTP status code returned. */
18     public $http_code;
19     /* Contains the last API call. */
20     public $url;
21     /* Set up the API root URL. */
22     public $host = "https://api.twitter.com/1/";
23     /* Set timeout default. */
24     public $timeout = 30;
25     /* Set connect timeout. */
26     public $connecttimeout = 30; 
27     /* Verify SSL Cert. */
28     public $ssl_verifypeer = false;
29     /* Respons format. */
30     public $format = 'json';
31     /* Decode returned json data. */
32     public $decode_json = true;
33     /* Contains the last HTTP headers returned. */
34     public $http_info;
35     /* Set the useragnet. */
36     public $useragent = 'Dotclear-TaC v0.1-alpha1';
37     
38     
39     /* Core object */
40     private $core;
41     /* DB object */
42     private $con;
43     /* table prefix */
44     private $prefix;
45     /* oAuth method object */
46     private $sha1_method;
47     
48     /* consumer table name */
49     private $table_registry;
50     /* plugin_id */
51     private $plugin_id = null;
52     /* Array of plugin info from DB */
53     private $registry = null;
54     /* Array of user info from DB */
55     private $consumer = null;
56     
57     /* token table name */
58     private $table_access;
59     /* user_id */
60     private $user_id = null;
61     /* oAuth token (user) object */
62     private $access = null;
63     /* oAuth consumer (plugin) object */
64     private $token = null;
65     
66     
67     /* Constructeur
68      *
69      * $core : core object
70      * $cr_id : id du plugin
71      * $user_id : id de l'utilisateur sur le blog ou null pour un blog complet
72      */
73     public function __construct($core,$plugin_id='TaC',$user_id=null)
74     {
75          $this->core = $core;
76          $this->con = $this->core->con;
77          $this->prefix = $this->core->prefix;
78         
79          $this->table_registry = $this->prefix.'tac_registry';
80          $this->table_access = $this->prefix.'tac_access';
81         
82          $this->plugin_id = $plugin_id; //todo: test if plugin exists
83          $this->user_id = !$user_id ? null : $user_id; //todo: test if exists
84         
85          // TIC - Twitter Inline Content
86          // helper to easily acces user twitter account
87          $this->tic = new tacQuick($this);
88     }
89     
90     /* Test si un plugin est connu et si oui le charge */
91     public function checkRegistry()
92     {
93          // Il est déjà chargé
94          if ($this->registry) {
95               return true;
96          }
97          // Recherche en base
98          $rs = $this->getRegistry($this->plugin_id);
99         
100          // Il n'existe pas
101          if ($rs->isEmpty()) {
102               return false;
103          }
104         
105          // Il existe
106         
107          // On fait le ménage
108          $this->consumer = 
109          $this->registry = 
110          $this->token = 
111          $this->access = null;
112
113          // On charge la methode oAuth
114          $method = 'OAuthSignatureMethod_'.str_replace('-','_',$rs->cr_sig_method);
115          $this->sha1_method = new $method();
116         
117          // On charge l'object oAuth du consumer
118          $this->consumer = new OAuthConsumer($rs->cr_key,$rs->cr_secret);
119         
120          // On charge les infos dans la classe
121          $this->registry = $rs;
122         
123          return true;
124     }
125     
126     /* Get consumer (plugin) info according to its id (plugin id) */
127     public function getRegistry($cr_id)
128     {
129          return $this->con->select(
130               'SELECT * FROM '.$this->table_registry.' '.
131               "WHERE cr_id = '".$this->con->escape($cr_id)."' ".
132               $this->con->limit(1)
133          );
134     }
135     
136     /* Add a registry (from cursor) */
137     public function addRegistry($cur)
138     {
139          $this->con->writeLock($this->table_registry);
140         
141          try {
142               $rs = $this->con->select(
143                    'SELECT MAX(registry_id) FROM '.$this->table_registry
144               );
145               
146               $cur->registry_id = (integer) $rs->f(0) + 1;
147               $cur->registry_dt = date('Y-m-d H:i:s');
148               
149               //todo: $this->getRegistryCursor($cur);
150               
151               $cur->insert();
152               $this->con->unlock();
153          }
154          catch (Exception $e)
155          {
156               $this->con->unlock();
157               throw $e;
158          }
159         
160          return $cur->registry_id;
161     }
162     
163     /* Test si l'utilisateur est connu et si oui on le charge */
164     public function checkAccess()
165     {
166          if (!$this->registry) {
167               throw new Exception(__('Consumer not loaded'));
168          }
169          // Il est déjà chargé
170          if ($this->access) {
171               return true;
172          }
173          // Recherche en base
174          $rs = $this->getAccess($this->registry->registry_id,$this->user_id);
175         
176          // Il n'existe pas
177          if ($rs->isEmpty()) {
178               return false;
179          }
180         
181          // Il existe
182         
183          // On fait le ménage
184          $this->token = 
185          $this->access = null;
186         
187          // On charge l'objet oAuth de l'utilisateur
188          $this->token = new OAuthConsumer($rs->ct_token,$rs->ct_token_secret);
189         
190          // On charge les infos dans la classe
191          $this->access = $rs;
192         
193          return true;
194     }
195     
196     /* Get user  info according to there user_id, plugin id on current blog */
197     public function getAccess($registry_id,$user_id)
198     {
199          $registry_id = abs((integer) $registry_id);
200         
201          $req = 
202          'SELECT * FROM '.$this->table_access.' '.
203          "WHERE blog_id = '".$this->con->escape($this->core->blog->id)."' ".
204          "AND registry_id = '".$registry_id."' ";
205         
206          if ($user_id) {
207               $req .= "AND user_id = '".$this->con->escape($user_id)."' ";
208          }
209          else {
210               $req .= "AND user_id IS NULL ";
211          }
212         
213          return $this->con->select($req.$this->con->limit(1));
214     }
215     
216     /* Ajoute un utilistaeur en base */
217     public function addAccess($cur)
218     {
219          if (!$cur->registry_id) {
220               throw new Exception (__('No registry'));
221          }
222          if (!$cur->ct_id) {
223               throw new Exception (__('No id'));
224          }
225          if (!$cur->ct_token) {
226               throw new Exception (__('No token'));
227          }
228          if (!$cur->ct_token_secret) {
229               throw new Exception (__('No secret'));
230          }
231         
232          $this->con->writeLock($this->table_access);
233         
234          try {
235               $rs = $this->con->select(
236                    'SELECT MAX(access_id) FROM '.$this->table_access
237               );
238               
239               $cur->access_id = (integer) $rs->f(0) + 1;
240               $cur->access_dt = date('Y-m-d H:i:s');
241               $cur->blog_id = $this->core->blog->id;
242               
243               $cur->insert();
244               $this->con->unlock();
245          }
246          catch (Exception $e)
247          {
248               $this->con->unlock();
249               throw $e;
250          }
251         
252          return $cur->access_id;
253     }
254     
255     /* Efface un utilisteur dans la base */
256     public function delAccess($registry_id,$user_id)
257     {
258          $registry_id = abs((integer) $registry_id);
259         
260          $req = 
261          'DELETE FROM '.$this->table_access.' '.
262          "WHERE blog_id = '".$this->con->escape($this->core->blog->id)."' ".
263          "AND registry_id = '".$registry_id."' ";
264         
265          if ($user_id) {
266               $req .= "AND user_id = '".$this->con->escape($user_id)."' ";
267          }
268          else {
269               $req .= "AND user_id IS NULL ";
270          }
271         
272          $this->con->execute($req);
273     }
274     
275     /* Clean current user and session */
276     public function cleanAccess()
277     {
278          if (!$this->registry || !$this->access) {
279               return null;
280          }
281          $this->delAccess($this->registry->registry_id,$this->access->user_id);
282          unset($_SESSION['oauth_token']);
283          unset($_SESSION['oauth_token_secret']);
284         
285          return true;
286     }
287     
288     /* Get temporary token */
289     public function requestAccess($callback_url='',$sign_in=true)
290     {
291          if (!$this->registry) {
292               throw new Exception(__('Consumer not loaded'));
293          }
294         
295          $params = array();
296          if (!empty($callback_url)) {
297               $params['oauth_callback'] = $callback_url;
298          }
299         
300          // On effectue la requete auprès du server oAuth
301          $request = $this->query($this->registry->cr_url_request,'GET',$params);
302         
303          // Aille probleme de requete
304          if ($this->http_code != 200) {
305               throw new Exception(__('Failed to request access'));
306          }
307         
308          // On transforme la réponse pour la rendre lisible
309          $token = OAuthUtil::parse_parameters($request);
310          $this->token = new OAuthConsumer($token['oauth_token'], $token['oauth_token_secret']);
311         
312          // On met en session les tokens temporaires
313          $_SESSION['oauth_token'] = $token['oauth_token'];
314          $_SESSION['oauth_token_secret'] = $token['oauth_token_secret'];
315         
316          // On retourne l'url qui permettra d'avoie les tokens définitifs
317          return $sign_in ?
318               $this->registry->cr_url_autorize.'?oauth_token='.$token['oauth_token'] : 
319               $this->registry->cr_url_authenticate.'?oauth_token='.$token['oauth_token'];
320     }
321     
322     /* Get final token */
323     public function grantAccess()
324     {
325          if (!$this->registry) {
326               throw new Exception(__('Consumer not loaded'));
327          }
328         
329          // On récupère les tokens temporaire depuis la session
330          $oauth_token = isset($_SESSION['oauth_token']) ? $_SESSION['oauth_token'] : '';
331          $oauth_token_secret = isset($_SESSION['oauth_token_secret']) ? $_SESSION['oauth_token_secret'] : '';
332          $request_token = isset($_REQUEST['oauth_token']) ? $_REQUEST['oauth_token'] : '';
333         
334          // On nettoye les infos temporaire de la session
335          unset($_SESSION['oauth_token']);
336          unset($_SESSION['oauth_token_secret']);
337         
338          // Si il sont différent de ceux retourné par l'url
339          // la session a expiré et donc on efface tout
340          if (!$oauth_token_secret || !$oauth_token 
341           || $request_token && $oauth_token !== $request_token)
342          {
343               $this->delAccess($this->registry->registry_id,$this->user_id);
344               
345               throw new Exception (__('Expired access'));
346          }
347         
348          // on charge l'objet de l'utilisateur
349          $this->token = new OAuthConsumer($oauth_token, $oauth_token_secret);
350         
351          // on demande un vérification
352          $params = array();
353          if (!empty($_REQUEST['oauth_verifier'])) {
354               $params['oauth_verifier'] = $_REQUEST['oauth_verifier'];
355          }
356          $request = $this->query($this->registry->cr_url_access,'GET',$params);
357         
358          if ($this->http_code != 200) {
359               throw new Exception(__('Failed to grant access'));
360          }
361         
362          // On transforme la réponse pour la rendre lisible
363          $token = OAuthUtil::parse_parameters($request);
364          $this->token = new OAuthConsumer($token['oauth_token'], $token['oauth_token_secret']);
365         
366          // On sauve les tokens defintif en base
367          $cur = $this->con->openCursor($this->prefix.'tac_access');
368         
369          try {
370               $cur->registry_id = $this->registry->registry_id;
371               $cur->ct_id = $token['user_id'];
372               $cur->ct_token = $token['oauth_token'];
373               $cur->ct_token_secret = $token['oauth_token_secret'];
374               
375               if ($user_id) {
376                    $cure->user_id = $user_id;
377               }
378               
379               $this->addAccess($cur);
380          }
381          catch (Exception $e) {
382               throw New Exception(__('Failed to add access').$e->getMessage());
383          }
384         
385          return true;
386     }
387     
388     /* GET wrapper for query */
389     public function get($url,$parameters=array())
390     {
391          $response = $this->query($url,'GET',$parameters);
392          if ($this->format === 'json' && $this->decode_json) {
393               return json_decode($response);
394          }
395          return $response;
396     }
397     
398     /* POST wrapper for query */
399     public function post($url,$parameters=array())
400     {
401          $response = $this->query($url,'POST',$parameters);
402          if ($this->format === 'json' && $this->decode_json) {
403               return json_decode($response);
404          }
405          return $response;
406     }
407     
408     /* DELETE wrapper for query */
409     public function delete($url,$parameters=array())
410     {
411          $response = $this->query($url,'DELETE',$parameters);
412          if ($this->format === 'json' && $this->decode_json) {
413               return json_decode($response);
414          }
415          return $response;
416     }
417     
418     /* Query with oAuth signature */
419     private function query($url,$method,$parameters)
420     {
421          if (strrpos($url,'https://') !== 0 && strrpos($url,'http://') !== 0) {
422               $url = $this->host.$url.'.'.$this->format;
423          }
424          $request = OAuthRequest::from_consumer_and_token($this->consumer,$this->token,$method,$url,$parameters);
425          $request->sign_request($this->sha1_method,$this->consumer,$this->token);
426         
427          switch ($method) {
428               case 'GET':
429                    return $this->http($request->to_url(),'GET');
430               default:
431                    return $this->http($request->get_normalized_http_url(),$method,$request->to_postdata());
432          }
433     }
434     
435     //!!! rewrite it with clearbricks net htttp !!!
436     private function http($url, $method, $postfields = NULL)
437     {
438          $this->http_info = array();
439          $ci = curl_init();
440         
441          /* Curl settings */
442          curl_setopt($ci, CURLOPT_USERAGENT, $this->useragent);
443          curl_setopt($ci, CURLOPT_CONNECTTIMEOUT, $this->connecttimeout);
444          curl_setopt($ci, CURLOPT_TIMEOUT, $this->timeout);
445          curl_setopt($ci, CURLOPT_RETURNTRANSFER, TRUE);
446          curl_setopt($ci, CURLOPT_HTTPHEADER, array('Expect:'));
447          curl_setopt($ci, CURLOPT_SSL_VERIFYPEER, $this->ssl_verifypeer);
448          curl_setopt($ci, CURLOPT_HEADERFUNCTION, array($this,'getHeader'));
449          curl_setopt($ci, CURLOPT_HEADER, FALSE);
450
451          switch ($method) {
452               case 'POST':
453                    curl_setopt($ci, CURLOPT_POST, TRUE);
454                    if (!empty($postfields)) {
455                         curl_setopt($ci, CURLOPT_POSTFIELDS, $postfields);
456                    }
457                    break;
458               case 'DELETE':
459                    curl_setopt($ci, CURLOPT_CUSTOMREQUEST, 'DELETE');
460                    if (!empty($postfields)) {
461                         $url = "{$url}?{$postfields}";
462                    }
463          }
464
465          curl_setopt($ci,CURLOPT_URL,$url);
466          $response = curl_exec($ci);
467          $this->http_code = curl_getinfo($ci,CURLINFO_HTTP_CODE);
468          $this->http_info = array_merge($this->http_info, curl_getinfo($ci));
469          $this->url = $url;
470          curl_close ($ci);
471         
472          return $response;
473     }
474     
475     private function getHeader($ch, $header)
476     {
477          $i = strpos($header, ':');
478          if (!empty($i)) {
479               $key = str_replace('-', '_', strtolower(substr($header, 0, $i)));
480               $value = trim(substr($header, $i + 2));
481               $this->http_header[$key] = $value;
482          }
483          return strlen($header);
484     }
485}
486?>
Note: See TracBrowser for help on using the repository browser.

Sites map