/[drupal]/contributions/modules/gdata/gdata.module
ViewVC logotype

Contents of /contributions/modules/gdata/gdata.module

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.23 - (show annotations) (download) (as text)
Mon Sep 4 20:37:16 2006 UTC (3 years, 2 months ago) by brainless
Branch: MAIN
CVS Tags: HEAD
Changes since 1.22: +5 -38 lines
File MIME type: text/x-php
Changed the structure of the GData XML and related functions in the core module and implementing files
1 <?php
2 /**
3 * Copyright and License info
4 *
5 * Copyright 2006 Sumit Datta | sumitdatta _at_ gmail _dot_ 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, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 $xml_request = array();
23 $xml_element_stack = array();
24
25 /**
26 * Implementation of hook_help
27 *
28 * @return string
29 */
30 function gdata_help($section) {
31 $output = '';
32
33 switch ($section) {
34 case 'admin/modules#description':
35 $output = t('Provides GData API for other modules to use to implement the GData protocol from Google');
36 break;
37 case 'admin/settings/modules#description':
38 $output = t('Provides GData API for other modules to use to implement the GData protocol from Google');
39 break;
40 case 'admin/settings/gdata':
41 if (user_access('administer gdata')) {
42 $output = t('GData module Administration Settings Page');
43 }
44 break;
45 case 'admin/help#gdata':
46 $output = t('This module provides GData API for other modules to use to implement the GData protocol from Google. GData is a protocol similar to Atom or RSS but it allows clients to add, update, delete and search data in addition to the normal syndication. Other modules can use the API exposed in this module to use the GData protocol easily.');
47 break;
48 }
49 return $output;
50 }
51
52 /**
53 * Valid permissions for the gdata module
54 *
55 * @return array An array of valid permissions for the gdata module
56 */
57 function gdata_perm() {
58 return array('administer gdata',
59 'delete with gdata',
60 'gdata',
61 'insert with gdata',
62 'search with gdata',
63 'syndicate with gdata',
64 'update with gdata',
65 );
66 }
67
68 /**
69 * Implementation of hook_menu
70 *
71 * @return array
72 */
73
74 function gdata_menu($may_cache) {
75 $items = array();
76 $path = '';
77 if (arg(0) != 'admin' && arg(0) != 'gdata') {
78 if(0 != ($gdata_modules = variable_get('gdata_modules', 0))) {
79 if (false !== ($module = array_search(arg(0), $gdata_modules))) {
80 $path = '/'.arg(0);
81 if (0 != ($gdata_settings = variable_get('gdata_'.$module, 0))) {
82 if (user_access('syndicate with gdata') && isset($gdata_settings['read']) && $gdata_settings['read'] == 1) {
83 drupal_set_html_head('<link rel="alternate" type="application/atom+xml" title="GData Syndication" href="'. url('gdata'.$path, NULL, NULL, TRUE) .'" />');
84 }
85 if (user_access('search with gdata') && isset($gdata_settings['search']) && $gdata_settings['search'] == 1) {
86 drupal_set_html_head('<link rel="alternate" type="application/atom+xml" title="GData Search" href="'. url('gdata'.$path, NULL, NULL, TRUE) .'" />');
87 }
88 if (user_access('insert with gdata') && isset($gdata_settings['insert']) && $gdata_settings['insert'] == 1) {
89 drupal_set_html_head('<link rel="alternate" type="application/atom+xml" title="GData Insert" href="'. url('gdata'.$path, NULL, NULL, TRUE) .'" />');
90 }
91 if (user_access('update with gdata') && isset($gdata_settings['update']) && $gdata_settings['update'] == 1) {
92 drupal_set_html_head('<link rel="alternate" type="application/atom+xml" title="GData Update" href="'. url('gdata'.$path, NULL, NULL, TRUE) .'" />');
93 }
94 if (user_access('delete with gdata') && isset($gdata_settings['delete']) && $gdata_settings['delete'] == 1) {
95 drupal_set_html_head('<link rel="alternate" type="application/atom+xml" title="GData Delete" href="'. url('gdata'.$path, NULL, NULL, TRUE) .'" />');
96 }
97 }
98 }
99 }
100 }
101 if ($may_cache) {
102 $items[] = array(
103 'path' => 'gdata',
104 'title' => t('Gdata Feed'),
105 'callback' => 'gdata_feed',
106 'access' => user_access('gdata'),
107 'type' => MENU_CALLBACK
108 );
109 }
110 $items[] = array(
111 'path' => 'admin/settings/gdata',
112 'title' => t('administer gdata'),
113 'callback' => 'drupal_get_form',
114 'callback arguments' => 'gdata_admin',
115 'description' => t('administer gdata.module'),
116 'access' => user_access('administer gdata'),
117 'type' => MENU_NORMAL_ITEM
118 );
119 return $items;
120 }
121
122 /**
123 * Produces a gdata (atom 1.0) feed for the front page content.
124 */
125
126 function gdata_feed() {
127 if (arg(0) == 'gdata') {
128 if ($_SERVER['REQUEST_METHOD'] == 'GET') {
129 if (user_access('syndicate with gdata')) {
130 $service = 'read';
131 $auth = 1;
132 }
133 else {
134 $auth = 0;
135 }
136 }
137 elseif ($_SERVER['REQUEST_METHOD'] == 'POST') {
138 if ($_SERVER["HTTP_X_HTTP_METHOD_OVERRIDE"] == 'PUT') {
139 if (user_access('update with gdata')) {
140 $service = 'update';
141 $auth = 1;
142 }
143 else {
144 $auth = 0;
145 }
146 }
147 elseif ($_SERVER["HTTP_X_HTTP_METHOD_OVERRIDE"] == 'DELETE') {
148 if (user_access('delete with gdata')) {
149 $service = 'delete';
150 $auth = 1;
151 }
152 else {
153 $auth = 0;
154 }
155 }
156 else {
157 if (user_access('insert with gdata')) {
158 $service = 'write';
159 $auth = 1;
160 }
161 else {
162 $auth = 0;
163 }
164 }
165 }
166 elseif ($_SERVER['REQUEST_METHOD'] == 'PUT') {
167 if (user_access('update with gdata')) {
168 $service = 'update';
169 $auth = 1;
170 }
171 else {
172 $auth = 0;
173 }
174 }
175 elseif ($_SERVER['REQUEST_METHOD'] == 'DELETE') {
176 if (user_access('delete with gdata')) {
177 $service = 'delete';
178 $auth = 1;
179 }
180 else {
181 $auth = 0;
182 }
183 }
184 if ($auth == 0) {
185 drupal_set_header('HTTP/1.1 401 UNAUTHORIZED');
186 die(drupal_set_message('You are not authorised to use service that you have requested'));
187 }
188 if (0 != ($gdata_modules = variable_get('gdata_modules', 0))) {
189 if (false !== ($module = array_search(arg(1), $gdata_modules))) {
190 if (0 != ($gdata_details = variable_get('gdata_'.$module, 0))) {
191 if ($gdata_details[$service] == 1) {
192 include_once('gdata_'.$module.'.inc');
193 module_invoke($module,
194 'gdata',
195 $service,
196 (substr($_SERVER['REQUEST_URI'], 0, 4) == '/?q=')?substr($_SERVER['REQUEST_URI'], 4):substr($_SERVER['REQUEST_URI'], 1)
197 );
198 }
199 else {
200 _gdata_error('error', 'This facility is not available on this Site');
201 }
202 }
203 else {
204 _gdata_error('error');
205 }
206 }
207 else {
208 _gdata_error('not found');
209 }
210 }
211 }
212 else {
213 die(drupal_not_found());
214 }
215 }
216
217 /**
218 *
219 * Sends the HTTP status header and a message to the user as specified in parameter
220 *
221 * @param string $error
222 * Error message string. Could be:
223 * -- 'bad request' or '400'
224 * -- 'unauthorised' or '401'
225 * -- 'forbidden' or '403'
226 * -- 'not found' or '404'
227 * -- 'conflict' or '409'
228 * -- 'error' or '500'
229 * Defaults to '500'
230 *
231 * @param string $string
232 * This is the message to send to the user. If not specified default message is sent
233 *
234 **/
235 function _gdata_error($error = '500', $string = '') {
236 drupal_set_header('Content-type: text/plain');
237 switch ($error) {
238 case 'bad request':
239 case '400':
240 drupal_set_header('HTTP/1.1 400 BAD REQUEST');
241 print(($string == '')?'The server could not understand your request':$string);
242 break;
243 case 'unauthorised':
244 case '401':
245 drupal_set_header('HTTP/1.1 401 UNAUTHORIZED');
246 print(($string == '')?'You are not authorised to use service that you have requested':$string);
247 break;
248 case 'forbidden':
249 case '403':
250 drupal_set_header('HTTP/1.1 403 FORBIDDEN');
251 print(($string == '')?'You are not authorised to use service that you have requested':$string);
252 break;
253 case 'not found':
254 case '404':
255 drupal_set_header('HTTP/1.1 404 NOT FOUND');
256 print(($string == '')?'The service that you have requested was not found on this Site':$string);
257 break;
258 case 'conflict':
259 case '409':
260 drupal_set_header('HTTP/1.1 409 CONFLICT');
261 print(($string == '')?'Specified version number does not match latest version number of resource.':$string);
262 break '';
263 case 'error':
264 case '500':
265 default:
266 drupal_set_header('HTTP/1.1 500 INTERNAL SERVER ERROR');
267 print(($string == '')?'The server made a boo boo':$string);
268 break;
269 }
270 }
271
272 /**
273 * Module configuration settings
274 *
275 * @return string of settings HTML or deny access
276 */
277 function gdata_admin() {
278 if (!user_access('administer gdata')) {
279 die(drupal_access_denied());
280 }
281 $gdata_modules = array();
282 drupal_set_title('Gdata Admin Settings');
283 $options = array('read','write','update','delete','search');
284 if ($dir = opendir('./modules/gdata')) {
285 //
286 while (false !== ($file = readdir($dir))) {
287 if (substr($file, 0, 6) == 'gdata_' && substr($file, -4) == '.inc') {
288 include_once($file);
289 }
290 }
291 }
292 $modules_array = module_implements('gdata');
293 foreach ($modules_array as $module) {
294 $module_details = module_invoke($module, 'gdata', 'info');
295 if(isset($module_details['implements']) &&
296 array_intersect($module_details['implements'],$options) &&
297 $module_details['enabled'] == 'true') {
298 if (0 == ($module_var = variable_get('gdata_'.$module, 0))) {
299 variable_set(
300 'gdata_'.$module, array(
301 'path' => $module_details['path'],
302 'read' => 0,
303 'write' => 0,
304 'update' => 0,
305 'delete' => 0,
306 'search' => 0
307 )
308 );
309 }
310
311 $form[$module] = array(
312 '#type' => 'fieldset',
313 '#collapsible' => TRUE,
314 '#collapsed' => TRUE,
315 '#title' => t('Module ').$module,
316 '#description' => isset($module_details['help'])?$module_details['help']:'',
317 );
318
319 $form[$module]['gdata_'.$module] = array(
320 '#type' => 'checkboxes',
321 '#title' => t('What the module implements'),
322 '#description' => t('You can set if this module should enable read, write, etc. ( depending on what is available ).'),
323 );
324
325 foreach(array_intersect($module_details['implements'],$options) as $implements) {
326 if($module_var[$implements] == 1)
327 $attributes = array('checked' => 'checked');
328 else
329 $attributes = array();
330 $form[$module]['gdata_'.$module][$implements] = array(
331 '#type' => 'checkbox',
332 '#attributes' => $attributes,
333 '#title' => $implements,
334 );
335 }
336 $path = isset($module_var['path'])?$module_var['path']:$module_details['path'];
337 $form[$module]['gdata_'.$module]['path'] = array(
338 '#type' => 'textfield',
339 '#title' => t('The path for this module after ').
340 url('', NULL, NULL, TRUE),
341 '#default_value' => ($path)?$path:$module,
342 '#description' => t('If you set this is as "'.$path.'" for example, then external user will be able to access blog module through GData at '). url('gdata/'.$path, NULL, NULL, TRUE),
343 );
344 $gdata_modules[$module] = $path;
345 }
346 }
347 variable_set('gdata_modules', $gdata_modules);
348 return system_settings_form($form);
349 }
350
351 function _gdata_blank_feed($path = '') {
352 global $user;
353 drupal_set_header('Content-Type: application/xml');
354 $output =
355 '<?xml version="1.0" encoding="utf-8"?>
356 <feed xmlns="http://www.w3.org/2005/Atom">
357 <title>'.variable_get('site_name', 'Drupal').'</title>
358 <updated>'. _gdata_timestamp2w3dtf(time()) .'</updated>
359 <id>'.url($path, NULL, NULL, TRUE).'</id>';
360 /*
361 * Not sure of the following part
362 */
363
364 /*
365 if ($user->name) {
366 $output .=
367 ' <author>
368 <name>'.$user->name.'</name>
369 </author>';
370 }
371 */
372
373 $output .=
374 ' <link href="'.$path.'" rel="self"/>
375 </feed>';
376 print $output;
377 }
378
379 /**
380 * prints feed information from query of either front page or blog content
381 *
382 * @param object $nodes query result
383 * @param array feed information
384 */
385 function _gdata_print_feed($nodes, $feed_info) {
386 $output = '';
387 $last_mod = 0;
388 while ($node = db_fetch_object($nodes)) {
389 $item = node_load(array('nid' => $node->nid));
390 $link = url("node/$node->nid", NULL, NULL, true);
391
392 if (node_hook($item, 'view')) {
393 node_invoke($item, 'view', TRUE, FALSE);
394 }
395 else {
396 $item = node_prepare($item, TRUE);
397 }
398
399 // Allow modules to change $node->teaser before viewing.
400 node_invoke_nodeapi($item, 'view', true, false);
401
402 $output .= " <entry>\n";
403 $output .= ' <title>'. check_plain(strip_tags($item->title)) ."</title>\n";
404 $output .= ' <link rel="alternate" type="text/html" href="'. $link .'" />'. "\n";
405 $output .= ' <id>'. $link ."</id>\n";
406 $output .= ' <published>'. _gdata_timestamp2w3dtf($item->created) ."</published>\n";
407 $output .= ' <updated>'. _gdata_timestamp2w3dtf($item->changed) ."</updated>\n";
408 $last_mod = $item->changed;
409 $output .= " <author>\n";
410 if ($item->name) {
411 $output .= ' <name>'. $item->name ."</name>\n";
412 }
413 else {
414 $output .= ' <name>'. variable_get('anonymous', 'Anonymous') ."</name>\n";
415 }
416 $output .= " </author>\n";
417 if (module_exist('taxonomy')) {
418 $terms = taxonomy_node_get_terms($item->nid);
419 foreach ($terms as $term) {
420 $output .= ' <category term="'. check_plain(strip_tags($term->name)) . '" />'. "\n";
421 }
422 }
423 // Summary
424 if ($item->teaser) {
425 $output .= ' <summary type="html"><![CDATA[';
426 $output .= check_markup($item->teaser);
427 $output .= " ]]></summary>\n";
428 }
429
430 // Body
431 $output .= ' <content type="html"><![CDATA[';
432 $output .= variable_get('atom_ad_location', 'off') == 'prepend' ? str_replace('%link', urlencode($link), str_replace('%id', $node->nid, variable_get('atom_ad_code', ''))) : '';
433 $output .= check_markup($item->body);
434 $output .= variable_get('atom_ad_location', 'off') == 'append' ? str_replace('%link', urlencode($link), str_replace('%id', $node->nid, variable_get('atom_ad_code', ''))) : '';
435 $output .= " ]]></content>\n";
436 $output .= " </entry>\n";
437 }
438
439 drupal_set_header('Content-Type: application/xml');
440
441 print '<?xml version="1.0" encoding="utf-8"?>'. "\n";
442 print '<feed xmlns="http://www.w3.org/2005/Atom">'. "\n";
443 print ' <title>'. $feed_info['title'] ."</title>\n";
444 print ' <updated>'. _gdata_timestamp2w3dtf(time()) ."</updated>\n";
445 print ' <id>'.url($feed_info['path'], NULL, NULL, TRUE)."</id>\n";
446 print $feed_info['subtitle'] == '' ? '' : ' <subtitle>'. $feed_info['subtitle'] . "</subtitle>\n";
447 print ' <link href="'. $feed_info['path'] .'" rel="self"/>'. "\n";
448 print $output;
449 print "</feed>\n";
450 }
451
452 /**
453 * @return string
454 */
455 function _gdata_timestamp2w3dtf($timestamp) {
456 $tz = date("O", $timestamp);
457 return date("Y-m-d", $timestamp) .'T'. date("H:i:s", $timestamp) . substr($tz, 0, 3) . ':' . substr($tz, 3, 2);
458 }
459
460 function _gdata_xml_request() {
461 global $xml_request;
462 if (false == ($xmlres = xml_parser_create())) {
463 return false;
464 }
465 xml_parser_set_option($xmlres, XML_OPTION_CASE_FOLDING, 0);
466 if (!xml_set_element_handler($xmlres, '_gdata_xml_start', '_gdata_xml_end')) {
467 return false;
468 }
469 if (!xml_set_character_data_handler($xmlres, '_gdata_xml_cdata')) {
470 return false;
471 }
472 if (xml_parse($xmlres, file_get_contents('php://input'), TRUE)) {
473 return $xml_request;
474 }
475 return false;
476 }
477
478 function _gdata_xml_start($parser, $name, $attribs = '') {
479 global $xml_request, $xml_element_stack;
480 if ($name == 'title') {
481 if ($attribs['type']) {
482 $xml_request['title']['type'] = $attribs['type'];
483 }
484 else {
485 $xml_request['title']['type'] = 'unknown';
486 }
487 }
488 elseif ($name == 'content') {
489 if ($attribs['type']) {
490 $xml_request['content']['type'] = $attribs['type'];
491 }
492 else {
493 $xml_request['content']['type'] = 'unknown';
494 }
495 }
496 $xml_element_stack[] = $name;
497 }
498
499 function _gdata_xml_end($parser, $name) {
500 global $xml_request, $xml_element_stack;
501 array_pop($xml_element_stack);
502 }
503
504 function _gdata_xml_cdata($parser, $data) {
505 global $xml_request, $xml_element_stack;
506 $element = array_pop($xml_element_stack);
507 if ($element == 'name' && end($xml_element_stack) == 'author') {
508 $xml_request['author']['name'] = $data;
509 }
510 elseif ($element == 'email' && end($xml_element_stack) == 'author') {
511 $xml_request['author']['email'] = $data;
512 }
513 elseif ($element == 'title' && end($xml_element_stack) == 'entry') {
514 $xml_request['title']['value'] = $data;
515 }
516 elseif ($element == 'content' && end($xml_element_stack) == 'entry') {
517 $xml_request['content']['value'] = $data;
518 }
519 array_push($xml_element_stack, $element);
520 }

  ViewVC Help
Powered by ViewVC 1.1.2