[moodle] / moodle / lib / googleapi.php Repository:

Annotation of /moodle/lib/googleapi.php

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.3 - (view) (download)

1 : moodler 1.3 <?php // $Id: googleapi.php,v 1.2 2008/11/30 17:37:06 poltawski Exp $
2 : poltawski 1.1 /**
3 :     * Moodle - Modular Object-Oriented Dynamic Learning Environment
4 :     * http://moodle.org
5 :     * Copyright (C) 1999 onwards Martin Dougiamas http://dougiamas.com
6 :     *
7 :     * This program is free software: you can redistribute it and/or modify
8 :     * it under the terms of the GNU General Public License as published by
9 :     * the Free Software Foundation, either version 2 of the License, or
10 :     * (at your option) any later version.
11 :     *
12 :     * This program is distributed in the hope that it will be useful,
13 :     * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 :     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 :     * GNU General Public License for more details.
16 :     *
17 :     * You should have received a copy of the GNU General Public License
18 :     * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 :     *
20 :     * @package moodle
21 :     * @subpackage lib
22 :     * @author Dan Poltawski <talktodan@gmail.com>
23 :     * @license http://www.gnu.org/copyleft/gpl.html GNU GPL
24 :     *
25 :     * Simple implementation of some Google API functions for Moodle.
26 :     */
27 :    
28 :     require_once($CFG->libdir.'/filelib.php');
29 :    
30 :     /**
31 :     * Base class for google authenticated http requests
32 :     *
33 :     * Most Google API Calls required that requests are sent with an
34 :     * Authorization header + token. This class extends the curl class
35 :     * to aid this
36 :     */
37 :     abstract class google_auth_request extends curl{
38 :     protected $token = '';
39 :    
40 :     // Must be overriden with the authorization header name
41 :     public abstract static function get_auth_header_name();
42 :    
43 :     protected function request($url, $options = array()){
44 :     if($this->token){
45 :     // Adds authorisation head to a request so that it can be authentcated
46 :     $this->setHeader('Authorization: '. $this->get_auth_header_name().'"'.$this->token.'"');
47 :     }
48 :    
49 :     $ret = parent::request($url, $options);
50 :     // reset headers for next request
51 :     $this->header = array();
52 :     return $ret;
53 :     }
54 :    
55 :     public function get_sessiontoken(){
56 :     return $this->token;
57 :     }
58 :     }
59 :    
60 :     /*******
61 :     * The following two classes are usd to implement AuthSub google
62 :     * authtentication, as documented here:
63 :     * http://code.google.com/apis/accounts/docs/AuthSub.html
64 :     *******/
65 :    
66 :     /**
67 :     * Used to uprade a google AuthSubRequest one-time token into
68 :     * a session token which can be used long term.
69 :     */
70 :     class google_authsub_request extends google_auth_request {
71 :     const AUTHSESSION_URL = 'https://www.google.com/accounts/AuthSubSessionToken';
72 :    
73 :     /**
74 :     * Constructor. Calls constructor of its parents
75 :     *
76 :     * @param string $authtoken The token to upgrade to a session token
77 :     */
78 :     public function __construct($authtoken){
79 :     parent::__construct();
80 :     $this->token = $authtoken;
81 :     }
82 :    
83 :     /**
84 :     * Requests a long-term session token from google based on the
85 :     *
86 :     * @return string Sub-Auth token
87 :     */
88 :     public function get_session_token(){
89 :     $content = $this->get(google_authsub_request::AUTHSESSION_URL);
90 :    
91 :     if( preg_match('/token=(.*)/i', $content, $matches) ){
92 :     return $matches[1];
93 :     }else{
94 :     throw new moodle_exception('could not upgrade google authtoken to session token');
95 :     }
96 :     }
97 :    
98 :     public static function get_auth_header_name(){
99 :     return 'AuthSub token=';
100 :     }
101 :     }
102 :    
103 :     /**
104 :     * Allows http calls using google subauth authorisation
105 :     */
106 :     class google_authsub extends google_auth_request {
107 :     const LOGINAUTH_URL = 'https://www.google.com/accounts/AuthSubRequest';
108 :     const VERIFY_TOKEN_URL = 'https://www.google.com/accounts/AuthSubTokenInfo';
109 :     const REVOKE_TOKEN_URL = 'https://www.google.com/accounts/AuthSubRevokeToken';
110 :    
111 :     /**
112 :     * Constructor, allows subauth requests using the response from an initial
113 :     * AuthSubRequest or with the subauth long-term token. Note that constructing
114 :     * this object without a valid token will cause an exception to be thrown.
115 :     *
116 :     * @param string $sessiontoken A long-term subauth session token
117 :     * @param string $authtoken A one-time auth token wich is used to upgrade to session token
118 :     * @param mixed @options Options to pass to the base curl object
119 :     */
120 :     public function __construct($sessiontoken = '', $authtoken = '', $options = array()){
121 :     parent::__construct($options);
122 :    
123 :     if( $authtoken ){
124 :     $gauth = new google_authsub_request($authtoken);
125 :     $sessiontoken = $gauth->get_session_token();
126 :     }
127 :    
128 :     $this->token = $sessiontoken;
129 :     if(! $this->valid_token() ){
130 :     throw new moodle_exception('Invalid subauth token');
131 :     }
132 :     }
133 :    
134 :     /**
135 :     * Tests if a subauth token used is valid
136 :     *
137 :     * @return boolean true if token valid
138 :     */
139 :     public function valid_token(){
140 :     $this->get(google_authsub::VERIFY_TOKEN_URL);
141 :    
142 :     if($this->info['http_code'] === 200){
143 :     return true;
144 :     }else{
145 :     return false;
146 :     }
147 :     }
148 :    
149 :     /**
150 :     * Calls googles api to revoke the subauth token
151 :     *
152 :     * @return boolean Returns true if token succesfully revoked
153 :     */
154 :     public function revoke_session_token(){
155 :     $this->get(google_authsub::REVOKE_TOKEN_URL);
156 :    
157 :     if($this->info['http_code'] === 200){
158 :     $this->token = '';
159 :     return true;
160 :     }else{
161 :     return false;
162 :     }
163 :     }
164 :    
165 :     /**
166 :     * Creates a login url for subauth request
167 :     *
168 :     * @param string $returnaddr The address which the user should be redirected to recieve the token
169 :     * @param string $realm The google realm which is access is being requested
170 :     * @return string URL to bounce the user to
171 :     */
172 :     public static function login_url($returnaddr, $realm){
173 :     $uri = google_authsub::LOGINAUTH_URL.'?next='
174 :     .urlencode($returnaddr)
175 :     .'&scope='
176 :     .urlencode($realm)
177 :     .'&session=1&secure=0';
178 :    
179 :     return $uri;
180 :     }
181 :    
182 :     public static function get_auth_header_name(){
183 :     return 'AuthSub token=';
184 :     }
185 :     }
186 :    
187 :     /**
188 :     * Class for manipulating google documents through the google data api
189 :     * Docs for this can be found here:
190 :     * http://code.google.com/apis/documents/docs/2.0/developers_guide_protocol.html
191 :     */
192 :     class google_docs {
193 :     const REALM = 'http://docs.google.com/feeds/documents';
194 :     const DOCUMENTFEED_URL = 'http://docs.google.com/feeds/documents/private/full';
195 :     const USER_PREF_NAME = 'google_authsub_sesskey';
196 :    
197 :     private $google_curl = null;
198 :    
199 :     /**
200 :     * Constructor.
201 :     *
202 :     * @param object A google_auth_request object which can be used to do http requests
203 :     */
204 :     public function __construct($google_curl){
205 :     if(is_a($google_curl, 'google_auth_request')){
206 :     $this->google_curl = $google_curl;
207 :     }else{
208 :     throw new moodle_exception('Google Curl Request object not given');
209 :     }
210 :     }
211 :    
212 :     public static function get_sesskey($userid){
213 :     return get_user_preferences(google_docs::USER_PREF_NAME, false, $userid);
214 :     }
215 :    
216 :     public static function set_sesskey($value, $userid){
217 :     return set_user_preference(google_docs::USER_PREF_NAME, $value, $userid);
218 :     }
219 :    
220 :     public static function delete_sesskey($userid){
221 :     return unset_user_preference(google_docs::USER_PREF_NAME, $userid);
222 :     }
223 :    
224 :     /**
225 :     * Returns a list of files the user has formated for files api
226 :     *
227 :     * @param string $search A search string to do full text search on the documents
228 :     * @return mixed Array of files formated for fileapoi
229 :     */
230 :     #FIXME
231 :     public function get_file_list($search = ''){
232 :     $url = google_docs::DOCUMENTFEED_URL;
233 :    
234 :     if($search){
235 :     $url.='?q='.urlencode($search);
236 :     }
237 :     $content = $this->google_curl->get($url);
238 :    
239 :     $xml = new SimpleXMLElement($content);
240 :    
241 :     $files = array();
242 :     foreach($xml->entry as $gdoc){
243 :    
244 :     $files[] = array( 'title' => "$gdoc->title",
245 :     'url' => "{$gdoc->content['src']}",
246 :     'source' => "{$gdoc->content['src']}",
247 :     'date' => usertime(strtotime($gdoc->updated)),
248 :     );
249 :     }
250 :    
251 :     return $files;
252 :     }
253 :    
254 :     /**
255 :     * Sends a file object to google documents
256 :     *
257 :     * @param object $file File object
258 :     * @return boolean True on success
259 :     */
260 :     public function send_file($file){
261 :     $this->google_curl->setHeader("Content-Length: ". $file->get_filesize());
262 :     $this->google_curl->setHeader("Content-Type: ". $file->get_mimetype());
263 :     $this->google_curl->setHeader("Slug: ". $file->get_filename());
264 :    
265 :     $this->google_curl->post(google_docs::DOCUMENTFEED_URL, $file->get_content());
266 :    
267 :     if($this->google_curl->info['http_code'] === 201){
268 :     return true;
269 :     }else{
270 :     return false;
271 :     }
272 :     }
273 :    
274 :     public function download_file($url, $fp){
275 :     return $this->google_curl->download(array( array('url'=>$url, 'file' => $fp) ));
276 :     }
277 :     }
278 :    
279 :     /**
280 :     * Class for manipulating picasa through the google data api
281 :     * Docs for this can be found here:
282 :     * http://code.google.com/apis/picasaweb/developers_guide_protocol.html
283 :     */
284 :     class google_picasa {
285 :     const REALM = 'http://picasaweb.google.com/data/';
286 :     const USER_PREF_NAME = 'google_authsub_sesskey_picasa';
287 :     const UPLOAD_LOCATION = 'http://picasaweb.google.com/data/feed/api/user/default/albumid/default';
288 : poltawski 1.2 const ALBUM_PHOTO_LIST = 'http://picasaweb.google.com/data/feed/api/user/default/albumid/';
289 :     const PHOTO_SEARCH_URL = 'http://picasaweb.google.com/data/feed/api/user/default?kind=photo&q=';
290 :     const LIST_ALBUMS_URL = 'http://picasaweb.google.com/data/feed/api/user/default';
291 : poltawski 1.1
292 :     private $google_curl = null;
293 :    
294 :     /**
295 :     * Constructor.
296 :     *
297 :     * @param object A google_auth_request object which can be used to do http requests
298 :     */
299 :     public function __construct($google_curl){
300 :     if(is_a($google_curl, 'google_auth_request')){
301 :     $this->google_curl = $google_curl;
302 :     }else{
303 :     throw new moodle_exception('Google Curl Request object not given');
304 :     }
305 :     }
306 :    
307 :     public static function get_sesskey($userid){
308 :     return get_user_preferences(google_picasa::USER_PREF_NAME, false, $userid);
309 :     }
310 :    
311 :     public static function set_sesskey($value, $userid){
312 :     return set_user_preference(google_picasa::USER_PREF_NAME, $value, $userid);
313 :     }
314 :    
315 :     public static function delete_sesskey($userid){
316 :     return unset_user_preference(google_picasa::USER_PREF_NAME, $userid);
317 :     }
318 :    
319 :     /**
320 :     * Sends a file object to picasaweb
321 :     *
322 :     * @param object $file File object
323 :     * @return boolean True on success
324 :     */
325 :     public function send_file($file){
326 :     $this->google_curl->setHeader("Content-Length: ". $file->get_filesize());
327 :     $this->google_curl->setHeader("Content-Type: ". $file->get_mimetype());
328 :     $this->google_curl->setHeader("Slug: ". $file->get_filename());
329 :    
330 :     $this->google_curl->post(google_picasa::UPLOAD_LOCATION, $file->get_content());
331 :    
332 :     if($this->google_curl->info['http_code'] === 201){
333 :     return true;
334 :     }else{
335 :     return false;
336 :     }
337 :     }
338 : poltawski 1.2
339 :     /**
340 :     * Returns list of photos for file picker.
341 :     * If top level then returns list of albums, otherwise
342 :     * photos within an album.
343 :     *
344 :     * @param string $path The path to files (assumed to be albumid)
345 :     * @return mixed $files A list of files for the file picker
346 :     */
347 :     public function get_file_list($path = ''){
348 :     if(!$path){
349 :     return $this->get_albums();
350 :     }else{
351 :     return $this->get_album_photos($path);
352 :     }
353 :     }
354 :    
355 :     /**
356 :     * Returns list of photos in album specified
357 :     *
358 :     * @param int $albumid Photo album to list photos from
359 :     * @return mixed $files A list of files for the file picker
360 :     */
361 :     public function get_album_photos($albumid){
362 :     $albumcontent = $this->google_curl->get(google_picasa::ALBUM_PHOTO_LIST.$albumid);
363 :    
364 :     return $this->get_photo_details($albumcontent);
365 :     }
366 :    
367 :     /**
368 :     * Does text search on the users photos and returns
369 :     * matches in format for picasa api
370 :     *
371 :     * @param string $query Search terms
372 :     * @return mixed $files A list of files for the file picker
373 :     */
374 :     public function do_photo_search($query){
375 :     $content = $this->google_curl->get(google_picasa::PHOTO_SEARCH_URL.htmlentities($query));
376 :    
377 :     return $this->get_photo_details($content);
378 :     }
379 :    
380 :     /**
381 :     * Gets all the users albums and returns them as a list of folders
382 :     * for the file picker
383 :     *
384 :     * @return mixes $files Array in the format get_listing uses for folders
385 :     */
386 :     public function get_albums(){
387 :     $content = $this->google_curl->get(google_picasa::LIST_ALBUMS_URL);
388 :     $xml = new SimpleXMLElement($content);
389 :    
390 :     $files = array();
391 :    
392 :     foreach($xml->entry as $album){
393 :     $gphoto = $album->children('http://schemas.google.com/photos/2007');
394 :    
395 :     $mediainfo = $album->children('http://search.yahoo.com/mrss/');
396 :     //hacky...
397 :     $thumbnailinfo = $mediainfo->group->thumbnail[0]->attributes();
398 :    
399 :     $files[] = array( 'title' => (string) $gphoto->name,
400 :     'date' => userdate($gphoto->timestamp),
401 :     'size' => (int) $gphoto->bytesUsed,
402 :     'path' => (string) $gphoto->id,
403 :     'thumbnail' => (string) $thumbnailinfo['url'],
404 : moodler 1.3 'thumbnail_width' => 160, // 160 is the native maximum dimension
405 :     'thumbnail_height' => 160,
406 : poltawski 1.2 'children' => array(),
407 :     );
408 :    
409 :     }
410 :    
411 :     return $files;
412 :     }
413 :    
414 :     /**
415 :     * Recieves XML from a picasa list of photos and returns
416 :     * array in format for file picker.
417 :     *
418 :     * @param string $rawxml XML from picasa api
419 :     * @return mixed $files A list of files for the file picker
420 :     */
421 :     public function get_photo_details($rawxml){
422 :    
423 :     $xml = new SimpleXMLElement($rawxml);
424 :    
425 :     $files = array();
426 :    
427 :     foreach($xml->entry as $photo){
428 :     $gphoto = $photo->children('http://schemas.google.com/photos/2007');
429 :    
430 :     $mediainfo = $photo->children('http://search.yahoo.com/mrss/');
431 :     $fullinfo = $mediainfo->group->content->attributes();
432 :     //hacky...
433 :     $thumbnailinfo = $mediainfo->group->thumbnail[0]->attributes();
434 :    
435 :     $files[] = array('title' => (string) $mediainfo->group->title,
436 :     'date' => userdate($gphoto->timestamp),
437 :     'size' => (int) $gphoto->size,
438 :     'path' => $gphoto->albumid.'/'.$gphoto->id,
439 :     'thumbnail' => (string) $thumbnailinfo['url'],
440 : moodler 1.3 'thumbnail_width' => 72, // 72 is the native maximum dimension
441 :     'thumbnail_height' => 72,
442 : poltawski 1.2 'source' => (string) $fullinfo['url'],
443 :     );
444 :     }
445 :    
446 :     return $files;
447 :     }
448 :    
449 : poltawski 1.1 }
450 :    
451 :     /**
452 :     * Beginings of an implementation of Clientogin authenticaton for google
453 :     * accounts as documented here:
454 :     * http://code.google.com/apis/accounts/docs/AuthForInstalledApps.html#ClientLogin
455 :     *
456 :     * With this authentication we have to accept a username and password and to post
457 :     * it to google. Retrieving a token for use afterwards.
458 :     */
459 :     class google_authclient extends google_auth_request {
460 :     const LOGIN_URL = 'https://www.google.com/accounts/ClientLogin';
461 :    
462 :     public function __construct($sessiontoken = '', $username = '', $password = '', $options = array() ){
463 :     parent::__construct($options);
464 :    
465 :     if($username and $password){
466 :     $param = array(
467 :     'accountType'=>'GOOGLE',
468 :     'Email'=>$username,
469 :     'Passwd'=>$password,
470 :     'service'=>'writely'
471 :     );
472 :    
473 :     $content = $this->post(google_authclient::LOGIN_URL, $param);
474 :    
475 :     if( preg_match('/auth=(.*)/i', $content, $matches) ){
476 :     $sessiontoken = $matches[1];
477 :     }else{
478 :     throw new moodle_exception('could not upgrade authtoken');
479 :     }
480 :    
481 :     }
482 :    
483 :     if($sessiontoken){
484 :     $this->token = $sessiontoken;
485 :     }else{
486 :     throw new moodle_exception('no session token specified');
487 :     }
488 :     }
489 :    
490 :     public static function get_auth_header_name(){
491 :     return 'GoogleLogin auth=';
492 :     }
493 :     }
494 :    
495 :     ?>

Moodle CVS Admin
ViewVC Help
Powered by ViewVC 1.0.7