comparison modules/update/update.fetch.inc @ 1:c1f4ac30525a 6.0

Drupal 6.0
author Franck Deroche <webmaster@defr.org>
date Tue, 23 Dec 2008 14:28:28 +0100
parents
children 2427550111ae
comparison
equal deleted inserted replaced
0:5a113a1c4740 1:c1f4ac30525a
1 <?php
2 // $Id: update.fetch.inc,v 1.7 2008/01/30 10:14:42 goba Exp $
3
4 /**
5 * @file
6 * Code required only when fetching information about available updates.
7 */
8
9 /**
10 * Callback to manually check the update status without cron.
11 */
12 function update_manual_status() {
13 if (_update_refresh()) {
14 drupal_set_message(t('Fetched information about all available new releases and updates.'));
15 }
16 else {
17 drupal_set_message(t('Unable to fetch any information about available new releases and updates.'), 'error');
18 }
19 drupal_goto('admin/reports/updates');
20 }
21
22 /**
23 * Fetch project info via XML from a central server.
24 */
25 function _update_refresh() {
26 global $base_url;
27 module_load_include('inc', 'update', 'update.compare');
28
29 // Since we're fetching new available update data, we want to clear
30 // everything in our cache, to ensure we recompute the status. Note that
31 // this does not cause update_get_projects() to be recomputed twice in the
32 // same page load (e.g. when manually checking) since that function stashes
33 // its answer in a static array.
34 update_invalidate_cache();
35
36 $available = array();
37 $data = array();
38 $site_key = md5($base_url . drupal_get_private_key());
39 $projects = update_get_projects();
40
41 foreach ($projects as $key => $project) {
42 $url = _update_build_fetch_url($project, $site_key);
43 $xml = drupal_http_request($url);
44 if (isset($xml->data)) {
45 $data[] = $xml->data;
46 }
47 }
48
49 if ($data) {
50 $parser = new update_xml_parser;
51 $available = $parser->parse($data);
52 }
53 if (!empty($available) && is_array($available)) {
54 $frequency = variable_get('update_check_frequency', 1);
55 cache_set('update_info', $available, 'cache_update', time() + (60 * 60 * 24 * $frequency));
56 variable_set('update_last_check', time());
57 watchdog('update', 'Fetched information about all available new releases and updates.', array(), WATCHDOG_NOTICE, l('view', 'admin/reports/updates'));
58 }
59 else {
60 module_invoke('system', 'check_http_request');
61 watchdog('update', 'Unable to fetch any information about available new releases and updates.', array(), WATCHDOG_ERROR, l('view', 'admin/reports/updates'));
62 }
63 return $available;
64 }
65
66 /**
67 * Generates the URL to fetch information about project updates.
68 *
69 * This figures out the right URL to use, based on the project's .info file
70 * and the global defaults. Appends optional query arguments when the site is
71 * configured to report usage stats.
72 *
73 * @param $project
74 * The array of project information from update_get_projects().
75 * @param $site_key
76 * The anonymous site key hash (optional).
77 *
78 * @see update_refresh()
79 * @see update_get_projects()
80 */
81 function _update_build_fetch_url($project, $site_key = '') {
82 $default_url = variable_get('update_fetch_url', UPDATE_DEFAULT_URL);
83 if (!isset($project['info']['project status url'])) {
84 $project['info']['project status url'] = $default_url;
85 }
86 $name = $project['name'];
87 $url = $project['info']['project status url'];
88 $url .= '/'. $name .'/'. DRUPAL_CORE_COMPATIBILITY;
89 if (!empty($site_key)) {
90 $url .= (strpos($url, '?') === TRUE) ? '&' : '?';
91 $url .= 'site_key=';
92 $url .= drupal_urlencode($site_key);
93 if (!empty($project['info']['version'])) {
94 $url .= '&version=';
95 $url .= drupal_urlencode($project['info']['version']);
96 }
97 }
98 return $url;
99 }
100
101 /**
102 * Perform any notifications that should be done once cron fetches new data.
103 *
104 * This method checks the status of the site using the new data and depending
105 * on the configuration of the site, notifys administrators via email if there
106 * are new releases or missing security updates.
107 *
108 * @see update_requirements()
109 */
110 function _update_cron_notify() {
111 include_once './includes/install.inc';
112 $status = update_requirements('runtime');
113 $params = array();
114 foreach (array('core', 'contrib') as $report_type) {
115 $type = 'update_'. $report_type;
116 if (isset($status[$type]['severity'])
117 && $status[$type]['severity'] == REQUIREMENT_ERROR) {
118 $params[$report_type] = $status[$type]['reason'];
119 }
120 }
121 if (!empty($params)) {
122 $notify_list = variable_get('update_notify_emails', '');
123 if (!empty($notify_list)) {
124 $default_language = language_default();
125 foreach ($notify_list as $target) {
126 if ($target_user = user_load(array('mail' => $target))) {
127 $target_language = user_preferred_language($target_user);
128 }
129 else {
130 $target_language = $default_language;
131 }
132 drupal_mail('update', 'status_notify', $target, $target_language, $params);
133 }
134 }
135 }
136 }
137
138 /**
139 * XML Parser object to read Drupal's release history info files.
140 * This uses PHP4's lame XML parsing, but it works.
141 */
142 class update_xml_parser {
143 var $projects = array();
144 var $current_project;
145 var $current_release;
146 var $current_term;
147 var $current_tag;
148 var $current_object;
149
150 /**
151 * Parse an array of XML data files.
152 */
153 function parse($data) {
154 foreach ($data as $datum) {
155 $parser = xml_parser_create();
156 xml_set_object($parser, $this);
157 xml_set_element_handler($parser, 'start', 'end');
158 xml_set_character_data_handler($parser, "data");
159 xml_parse($parser, $datum);
160 xml_parser_free($parser);
161 }
162 return $this->projects;
163 }
164
165 function start($parser, $name, $attr) {
166 $this->current_tag = $name;
167 switch ($name) {
168 case 'PROJECT':
169 unset($this->current_object);
170 $this->current_project = array();
171 $this->current_object = &$this->current_project;
172 break;
173 case 'RELEASE':
174 unset($this->current_object);
175 $this->current_release = array();
176 $this->current_object = &$this->current_release;
177 break;
178 case 'TERM':
179 unset($this->current_object);
180 $this->current_term = array();
181 $this->current_object = &$this->current_term;
182 break;
183 }
184 }
185
186 function end($parser, $name) {
187 switch ($name) {
188 case 'PROJECT':
189 unset($this->current_object);
190 $this->projects[$this->current_project['short_name']] = $this->current_project;
191 $this->current_project = array();
192 break;
193 case 'RELEASE':
194 unset($this->current_object);
195 $this->current_project['releases'][$this->current_release['version']] = $this->current_release;
196 break;
197 case 'RELEASES':
198 $this->current_object = &$this->current_project;
199 break;
200 case 'TERM':
201 unset($this->current_object);
202 $term_name = $this->current_term['name'];
203 if (!isset($this->current_release['terms'])) {
204 $this->current_release['terms'] = array();
205 }
206 if (!isset($this->current_release['terms'][$term_name])) {
207 $this->current_release['terms'][$term_name] = array();
208 }
209 $this->current_release['terms'][$term_name][] = $this->current_term['value'];
210 break;
211 case 'TERMS':
212 $this->current_object = &$this->current_release;
213 break;
214 default:
215 $this->current_object[strtolower($this->current_tag)] = trim($this->current_object[strtolower($this->current_tag)]);
216 $this->current_tag = '';
217 }
218 }
219
220 function data($parser, $data) {
221 if ($this->current_tag && !in_array($this->current_tag, array('PROJECT', 'RELEASE', 'RELEASES', 'TERM', 'TERMS'))) {
222 $tag = strtolower($this->current_tag);
223 if (isset($this->current_object[$tag])) {
224 $this->current_object[$tag] .= $data;
225 }
226 else {
227 $this->current_object[$tag] = $data;
228 }
229 }
230 }
231 }