drupal.module 10.4 KB
Newer Older
Dries's avatar
 
Dries committed
1
<?php
Kjartan's avatar
Kjartan committed
2
// $Id$
Dries's avatar
 
Dries committed
3

Dries's avatar
 
Dries committed
4 5 6 7 8
/**
 * @file
 * Lets users log in using a Drupal ID and can notify a central server about your site.
 */

Dries's avatar
Dries committed
9 10 11 12
/**
 * Implementation of hook_help().
 */
function drupal_help($section) {
Dries's avatar
 
Dries committed
13
  switch ($section) {
Dries's avatar
 
Dries committed
14
    case 'admin/help#drupal':
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
      $output = '<p>'. t('The Drupal module uses the XML-RPC network communication protocol to connect your site with a directory server that maintains a directory of sites.  Community leaders who have common interests may wish to be part of a larger community and showing sites in a common directory is a good way to do this.') .'</p>';
      $output .= t('<p>Enabling the drupal module will:</p>
<ul>
<li>list your site in a site directory.</li>
<li>allow members on all sites using the Drupal module to login to your site without registering using their distributed identification and vice versa.</li>
<li>allow members to login to any other site which uses the Drupal module, using a login name which looks much like an email address for your site: <em>username@example.com</em></li>
</ul>
');
      $output .= '<p>'. t('The Drupal module administration page allows you to set the xml-rpc server page.  The listing of your site in a site directory will occur shortly after your sites next cron run.') .'</p>';
      $output .= t('<p>You can</p>
<ul>
<li>run your cron job at your sites <a href="%file-cron">cron page</a>.</li>
<li>browse to the <a href="%external-http-www-drupal-org-xmlrpc-php">XML-RPC site directory</a>.</li>
<li>view your <a href="%file-xmlrpc">XML-RPC page</a>.</li>
<li>administer Drupal <a href="%admin-settings-drupal">administer &gt;&gt; settings &gt;&gt; drupal</a>.</li>
</ul>
', array('%file-cron' => 'cron.php', '%external-http-www-drupal-org-xmlrpc-php' => 'http://www.drupal.org/xmlrpc.php', '%file-xmlrpc' => 'xmlrpc.php', '%admin-settings-drupal' => url('admin/settings/drupal')));
      $output .= '<p>'. t('For more information please read the configuration and customization handbook <a href="%drupal">Drupal page</a>.', array('%drupal' => 'http://www.drupal.org/handbook/modules/drupal/')) .'</p>';
      return $output;
Dries's avatar
 
Dries committed
34
    case 'admin/modules#description':
Dries's avatar
Dries committed
35
      return t('Lets users log in using a Drupal ID and can notify a central server about your site.');
Dries's avatar
 
Dries committed
36
    case 'admin/settings/drupal':
37
      return t('<p>Using this your site can "call home" and add itself to the Drupal directory. If you want it to add itself to a different directory server you can change the <a href="%xml-rpc-setting">Drupal XML-RPC server</a> setting -- but the directory server has to be able to handle Drupal XML. To get all your site information listed, go to the <a href="%site-settings">settings page</a> and set the site name, the e-mail address, the slogan, and the mission statement.</p>', array('%xml-rpc-setting' => url('admin/settings/drupal'), '%site-settings' => url('admin/settings')));
Dries's avatar
 
Dries committed
38
    case 'user/help#drupal':
39
      return t("<p><a href=\"%Drupal\">Drupal</a> is the name of the software which powers %this-site. There are Drupal web sites all over the world, and many of them share their registration databases so that users may freely login to any Drupal site using a single <strong>Drupal ID</strong>.</p>
Dries's avatar
Dries committed
40
<p>So please feel free to login to your account here at %this-site with a username from another Drupal site. The format of a Drupal ID is similar to an email address: <strong>username</strong>@<em>server</em>. An example of a valid Drupal ID is <strong>mwlily</strong>@<em>www.drupal.org</em>.</p>", array('%Drupal' => 'http://www.drupal.org', '%this-site' => '<em>'. variable_get('site_name', 'this web site') .'</em>'));
Dries's avatar
 
Dries committed
41
  }
42 43
}

Dries's avatar
Dries committed
44 45 46
/**
 * Implementation of hook_settings().
 */
47
function drupal_settings() {
48
  // Check if all required fields are present for the Drupal directory
49
  if ((variable_get('site_name', 'drupal') == 'drupal') || (variable_get('site_name', 'drupal') == '')) {
Dries's avatar
 
Dries committed
50
    form_set_error('drupal_directory', t('You must set the name of your site on the <a href="%url">administer &raquo; settings</a> page.', array('%url' => url('admin/settings'))));
51 52
  }
  else if (variable_get('site_mail', ini_get('sendmail_from')) == '') {
Dries's avatar
 
Dries committed
53
    form_set_error('drupal_directory', t('You must set an e-mail address for your site on the <a href="%url">administer &raquo; settings</a> page.', array('%url' => url('admin/settings'))));
54 55
  }
  else if (variable_get('site_slogan', '') == '') {
Dries's avatar
 
Dries committed
56
    form_set_error('drupal_directory', t('You must set your site slogan on the <a href="%url">administer &raquo; settings</a> page.', array('%url' => url('admin/settings'))));
57 58
  }
  else if (variable_get('site_mission', '') == '') {
Dries's avatar
 
Dries committed
59
    form_set_error('drupal_directory', t('You must set your site mission on the <a href="%url">administer &raquo; settings</a> page.' , array('%url' => url('admin/settings'))));
60
  }
61

62
  $form['drupal_server'] =  array('#type' => 'textfield', '#title' => t('Drupal XML-RPC server'), '#default_value' => variable_get('drupal_server', 'http://www.drupal.org/xmlrpc.php'), '#description' => t('The URL of your root Drupal XML-RPC server.'));
Dries's avatar
Dries committed
63

64
  $form['drupal_directory'] = array(
65 66 67
    '#type' => 'radios', '#title' => t('Drupal directory'), '#default_value' => variable_get('drupal_directory', 0),
    '#options' => array(t('Disabled'), t('Enabled')),
    '#description' => t("If enabled, your Drupal site will make itself known to the Drupal directory at the specified Drupal XML-RPC server. For this to work properly, you must set your site's name, e-mail address, slogan and mission statement. When the \"Drupal XML-RPC server\" field is set to \"%drupal-xml-rpc\", your web site will get listed on the <a href=\"%drupal-sites\">Drupal sites</a> page. Requires the cron feature to be enabled.", array("%drupal-xml-rpc" => "http://www.drupal.org/xmlrpc.php", "%drupal-sites" => "http://www.drupal.org/drupal-sites/"))
68
  );
Dries's avatar
 
Dries committed
69

70
  return $form;
Dries's avatar
 
Dries committed
71 72
}

Dries's avatar
Dries committed
73 74 75
/**
 * Implementation of hook_cron(); handles pings to and from the site.
 */
Dries's avatar
 
Dries committed
76
function drupal_cron() {
Dries's avatar
Dries committed
77 78
  if (time() - variable_get('drupal_cron_last', 0) > 21600) {
    variable_set('drupal_cron_last', time());
Dries's avatar
 
Dries committed
79

Dries's avatar
Dries committed
80 81
    // If this site acts as a Drupal XML-RPC server, delete the sites that
    // stopped sending "ping" messages.
Dries's avatar
 
Dries committed
82
    db_query("DELETE FROM {directory} WHERE timestamp < '". (time() - 259200) ."'");
Dries's avatar
 
Dries committed
83

Dries's avatar
Dries committed
84 85 86 87
    // If this site acts as a Drupal XML-RPC client, send a message to the
    // Drupal XML-RPC server.
    if (variable_get('drupal_directory', 0) && variable_get('drupal_server', 0)) {
      drupal_notify(variable_get('drupal_server', ''));
Dries's avatar
 
Dries committed
88
    }
Dries's avatar
 
Dries committed
89 90 91
  }
}

Dries's avatar
Dries committed
92 93 94
/**
 * Callback function from drupal_xmlrpc() called when another site pings this one.
 */
95
function drupal_directory_ping($link, $name, $mail, $slogan, $mission) {
Dries's avatar
 
Dries committed
96 97 98 99 100

  /*
  ** Parse our parameters:
  */

101 102 103
  foreach (array('link', 'name', 'mail', 'slogan', 'mission') as $key) {
    $$key = strip_tags($$key);
  }
Dries's avatar
 
Dries committed
104 105 106 107 108 109

  /*
  ** Update the data in our database and send back a reply:
  */

  if ($link && $name && $mail && $slogan && $mission) {
Dries's avatar
 
Dries committed
110 111
    db_query("DELETE FROM {directory} WHERE link = '%s' OR mail = '%s'", $link, $mail);
    db_query("INSERT INTO {directory} (link, name, mail, slogan, mission, timestamp) VALUES ('%s', '%s', '%s', '%s', '%s', %d)", $link, $name, $mail, $slogan, $mission, time());
Dries's avatar
 
Dries committed
112

113
    watchdog('directory ping', t('Ping from %name (%link).', array('%name' => theme('placeholder', $name), '%link' => theme('placeholder', $link))), WATCHDOG_NOTICE, '<a href="'. check_url($link) .'">view</a>');
Dries's avatar
 
Dries committed
114

115
    return 1;
Dries's avatar
 
Dries committed
116 117
  }
  else {
118
    return 0;
Dries's avatar
 
Dries committed
119 120 121 122
  }

}

Dries's avatar
Dries committed
123
/**
124
 * Formats a list of all sites indexed in the directory.
Dries's avatar
Dries committed
125 126 127 128
 *
 * This function may be called from a custom page on sites that are
 * Drupal directory servers.
 */
129 130
function drupal_directory_page($sort = 'name') {
  $result = db_query('SELECT * FROM {directory} ORDER BY '. $sort);
Dries's avatar
 
Dries committed
131

132 133
  // Note: All fields except the mission are treated as plain-text.
  // The mission is stripped of any HTML tags to keep the output simple and consistent.
Dries's avatar
 
Dries committed
134
  while ($site = db_fetch_object($result)) {
135
    $output .= '<a href="'. check_url($site->link) .'">'. check_plain($site->name) .'</a> - '. check_plain($site->slogan) .'<div style="padding-left: 20px;">'. strip_tags($site->mission) .'</div><br />';
Dries's avatar
 
Dries committed
136 137 138 139 140
  }

  return $output;
}

Dries's avatar
Dries committed
141 142 143
/**
 * Implementation of hook_xmlrpc().
 */
Dries's avatar
 
Dries committed
144
function drupal_xmlrpc() {
145 146 147 148 149 150 151 152 153 154 155
  return array(
    array(
      'drupal.site.ping',
      'drupal_directory_ping',
      array('boolean', 'string', 'string', 'string', 'string', 'string'),
      t('Handling ping request')),
    array(
      'drupal.login',
      'drupal_login',
      array('int', 'string', 'string'),
      t('Logging into a drupal site')));
Dries's avatar
 
Dries committed
156 157
}

Dries's avatar
Dries committed
158 159 160
/**
 * Sends a ping to the Drupal directory server.
 */
Dries's avatar
 
Dries committed
161
function drupal_notify($server) {
Dries's avatar
 
Dries committed
162
  global $base_url;
Dries's avatar
 
Dries committed
163

164
  $result = xmlrpc($server, 'drupal.site.ping', $base_url, variable_get('site_name', ''), variable_get('site_mail', ''), variable_get('site_slogan', ''), variable_get('site_mission', ''));
Dries's avatar
 
Dries committed
165

166 167
  if ($result === FALSE) {
    watchdog('directory ping', t('Failed to notify %server, error code: %errno, error message: %error_msg.', array('%server' => theme('placeholder', $server), '%errno' => theme('placeholder', xmlrpc_errno()), '%error_msg' => theme('placeholder', xmlrpc_error_msg()))), WATCHDOG_WARNING);
Dries's avatar
 
Dries committed
168 169 170 171
  }

}

Dries's avatar
Dries committed
172 173 174
/**
 * Implementation of hook_info().
 */
Dries's avatar
 
Dries committed
175
function drupal_info($field = 0) {
Dries's avatar
Dries committed
176 177
  $info['name'] = 'Drupal';
  $info['protocol'] = 'XML-RPC';
Dries's avatar
 
Dries committed
178 179 180 181 182 183 184 185 186

  if ($field) {
    return $info[$field];
  }
  else {
    return $info;
  }
}

Dries's avatar
Dries committed
187 188 189
/**
 * Implementation of hook_auth().
 */
Dries's avatar
 
Dries committed
190
function drupal_auth($username, $password, $server) {
191 192 193 194 195 196
  $result = xmlrpc('http://'. $server .'/xmlrpc.php', 'drupal.login', $username, $password);
  if ($result === FALSE) {
    drupal_set_message(t('Error %code : %message', array('%code' => theme('placeholder', xmlrpc_errno()), '%message' =>  theme('placeholder', xmlrpc_error_msg()))), 'error');
  }
  else {
    return $result;
Dries's avatar
 
Dries committed
197 198 199
  }
}

Dries's avatar
 
Dries committed
200
/**
Dries's avatar
 
Dries committed
201
 * Implementation of hook_menu().
Dries's avatar
 
Dries committed
202
 */
Dries's avatar
 
Dries committed
203
function drupal_menu($may_cache) {
Dries's avatar
 
Dries committed
204
  $items = array();
Dries's avatar
 
Dries committed
205 206 207 208 209
  if ($may_cache) {
    $items[] = array('path' => 'drupal', 'title' => t('Drupal'),
      'callback' => 'drupal_page_help', 'access' => TRUE,
      'type' => MENU_SUGGESTED_ITEM);
  }
Dries's avatar
 
Dries committed
210
  return $items;
Dries's avatar
 
Dries committed
211 212
}

Dries's avatar
Dries committed
213 214 215 216
/**
 * Menu callback; print Drupal-authentication-specific information from user/help.
 */
function drupal_page_help() {
Dries's avatar
 
Dries committed
217
  return drupal_help('user/help#drupal');
Dries's avatar
 
Dries committed
218 219
}

Dries's avatar
Dries committed
220 221 222 223 224
/**
 * Callback function from drupal_xmlrpc() for authenticating remote clients.
 *
 * Remote clients are usually other Drupal instances.
 */
225
function drupal_login($username, $password) {
Dries's avatar
 
Dries committed
226
  if ($user = user_load(array('name' => $username, 'pass' => $password, 'status' => 1))) {
227
    return $user->uid;
Dries's avatar
Dries committed
228 229
  }
  else {
230
    return 0;
Dries's avatar
Dries committed
231 232 233
  }
}

234