~dantrevino/fls/trunk

« back to all changes in this revision

Viewing changes to install.php

  • Committer: Dan Trevino
  • Date: 2009-07-24 13:30:40 UTC
  • Revision ID: dan@chaos-20090724133040-py9gkfyvx95l19td
initial code dump

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<?php
 
2
// $Id: install.php,v 1.113.2.9 2009/04/27 10:50:35 goba Exp $
 
3
 
 
4
require_once './includes/install.inc';
 
5
 
 
6
define('MAINTENANCE_MODE', 'install');
 
7
 
 
8
/**
 
9
 * The Drupal installation happens in a series of steps. We begin by verifying
 
10
 * that the current environment meets our minimum requirements. We then go
 
11
 * on to verify that settings.php is properly configured. From there we
 
12
 * connect to the configured database and verify that it meets our minimum
 
13
 * requirements. Finally we can allow the user to select an installation
 
14
 * profile and complete the installation process.
 
15
 *
 
16
 * @param $phase
 
17
 *   The installation phase we should proceed to.
 
18
 */
 
19
function install_main() {
 
20
  require_once './includes/bootstrap.inc';
 
21
  drupal_bootstrap(DRUPAL_BOOTSTRAP_CONFIGURATION);
 
22
 
 
23
  // This must go after drupal_bootstrap(), which unsets globals!
 
24
  global $profile, $install_locale, $conf;
 
25
 
 
26
  require_once './modules/system/system.install';
 
27
  require_once './includes/file.inc';
 
28
 
 
29
  // Ensure correct page headers are sent (e.g. caching)
 
30
  drupal_page_header();
 
31
 
 
32
  // Set up $language, so t() caller functions will still work.
 
33
  drupal_init_language();
 
34
 
 
35
  // Load module basics (needed for hook invokes).
 
36
  include_once './includes/module.inc';
 
37
  $module_list['system']['filename'] = 'modules/system/system.module';
 
38
  $module_list['filter']['filename'] = 'modules/filter/filter.module';
 
39
  module_list(TRUE, FALSE, FALSE, $module_list);
 
40
  drupal_load('module', 'system');
 
41
  drupal_load('module', 'filter');
 
42
 
 
43
  // Set up theme system for the maintenance page.
 
44
  drupal_maintenance_theme();
 
45
 
 
46
  // Check existing settings.php.
 
47
  $verify = install_verify_settings();
 
48
 
 
49
  if ($verify) {
 
50
    // Since we have a database connection, we use the normal cache system.
 
51
    // This is important, as the installer calls into the Drupal system for
 
52
    // the clean URL checks, so we should maintain the cache properly.
 
53
    require_once './includes/cache.inc';
 
54
    $conf['cache_inc'] = './includes/cache.inc';
 
55
 
 
56
    // Establish a connection to the database.
 
57
    require_once './includes/database.inc';
 
58
    db_set_active();
 
59
 
 
60
    // Check if Drupal is installed.
 
61
    $task = install_verify_drupal();
 
62
    if ($task == 'done') {
 
63
      install_already_done_error();
 
64
    }
 
65
  }
 
66
  else {
 
67
    // Since no persistent storage is available yet, and functions that check
 
68
    // for cached data will fail, we temporarily replace the normal cache
 
69
    // system with a stubbed-out version that short-circuits the actual
 
70
    // caching process and avoids any errors.
 
71
    require_once './includes/cache-install.inc';
 
72
    $conf['cache_inc'] = './includes/cache-install.inc';
 
73
 
 
74
    $task = NULL;
 
75
  }
 
76
 
 
77
  // Decide which profile to use.
 
78
  if (!empty($_GET['profile'])) {
 
79
    $profile = preg_replace('/[^a-zA-Z_0-9]/', '', $_GET['profile']);
 
80
  }
 
81
  elseif ($profile = install_select_profile()) {
 
82
    install_goto("install.php?profile=$profile");
 
83
  }
 
84
  else {
 
85
    install_no_profile_error();
 
86
  }
 
87
 
 
88
  // Load the profile.
 
89
  require_once "./profiles/$profile/$profile.profile";
 
90
 
 
91
  // Locale selection
 
92
  if (!empty($_GET['locale'])) {
 
93
    $install_locale = preg_replace('/[^a-zA-Z_0-9\-]/', '', $_GET['locale']);
 
94
  }
 
95
  elseif (($install_locale = install_select_locale($profile)) !== FALSE) {
 
96
    install_goto("install.php?profile=$profile&locale=$install_locale");
 
97
  }
 
98
 
 
99
  // Tasks come after the database is set up
 
100
  if (!$task) {
 
101
    global $db_url;
 
102
 
 
103
    if (!$verify && !empty($db_url)) {
 
104
      // Do not install over a configured settings.php.
 
105
      install_already_done_error();
 
106
    }
 
107
 
 
108
    // Check the installation requirements for Drupal and this profile.
 
109
    install_check_requirements($profile, $verify);
 
110
 
 
111
    // Verify existence of all required modules.
 
112
    $modules = drupal_verify_profile($profile, $install_locale);
 
113
 
 
114
    // If any error messages are set now, it means a requirement problem.
 
115
    $messages = drupal_set_message();
 
116
    if (!empty($messages['error'])) {
 
117
      install_task_list('requirements');
 
118
      drupal_set_title(st('Requirements problem'));
 
119
      print theme('install_page', '');
 
120
      exit;
 
121
    }
 
122
 
 
123
    // Change the settings.php information if verification failed earlier.
 
124
    // Note: will trigger a redirect if database credentials change.
 
125
    if (!$verify) {
 
126
      install_change_settings($profile, $install_locale);
 
127
    }
 
128
 
 
129
    // Install system.module.
 
130
    drupal_install_system();
 
131
    // Save the list of other modules to install for the 'profile-install'
 
132
    // task. variable_set() can be used now that system.module is installed
 
133
    // and drupal is bootstrapped.
 
134
    variable_set('install_profile_modules', array_diff($modules, array('system')));
 
135
  }
 
136
 
 
137
  // The database is set up, turn to further tasks.
 
138
  install_tasks($profile, $task);
 
139
}
 
140
 
 
141
/**
 
142
 * Verify if Drupal is installed.
 
143
 */
 
144
function install_verify_drupal() {
 
145
  // Read the variable manually using the @ so we don't trigger an error if it fails.
 
146
  $result = @db_query("SELECT value FROM {variable} WHERE name = '%s'", 'install_task');
 
147
  if ($result) {
 
148
    return unserialize(db_result($result));
 
149
  }
 
150
}
 
151
 
 
152
/**
 
153
 * Verify existing settings.php
 
154
 */
 
155
function install_verify_settings() {
 
156
  global $db_prefix, $db_type, $db_url;
 
157
 
 
158
  // Verify existing settings (if any).
 
159
  if (!empty($db_url)) {
 
160
    // We need this because we want to run form_get_errors.
 
161
    include_once './includes/form.inc';
 
162
 
 
163
    $url = parse_url(is_array($db_url) ? $db_url['default'] : $db_url);
 
164
    $db_user = urldecode($url['user']);
 
165
    $db_pass = isset($url['pass']) ? urldecode($url['pass']) : NULL;
 
166
    $db_host = urldecode($url['host']);
 
167
    $db_port = isset($url['port']) ? urldecode($url['port']) : '';
 
168
    $db_path = ltrim(urldecode($url['path']), '/');
 
169
    $settings_file = './'. conf_path(FALSE, TRUE) .'/settings.php';
 
170
 
 
171
    $form_state = array();
 
172
    _install_settings_form_validate($db_prefix, $db_type, $db_user, $db_pass, $db_host, $db_port, $db_path, $settings_file, $form_state);
 
173
    if (!form_get_errors()) {
 
174
      return TRUE;
 
175
    }
 
176
  }
 
177
  return FALSE;
 
178
}
 
179
 
 
180
/**
 
181
 * Configure and rewrite settings.php.
 
182
 */
 
183
function install_change_settings($profile = 'default', $install_locale = '') {
 
184
  global $db_url, $db_type, $db_prefix;
 
185
 
 
186
  $url = parse_url(is_array($db_url) ? $db_url['default'] : $db_url);
 
187
  $db_user = isset($url['user']) ? urldecode($url['user']) : '';
 
188
  $db_pass = isset($url['pass']) ? urldecode($url['pass']) : '';
 
189
  $db_host = isset($url['host']) ? urldecode($url['host']) : '';
 
190
  $db_port = isset($url['port']) ? urldecode($url['port']) : '';
 
191
  $db_path = ltrim(urldecode($url['path']), '/');
 
192
  $conf_path = './'. conf_path(FALSE, TRUE);
 
193
  $settings_file = $conf_path .'/settings.php';
 
194
 
 
195
  // We always need this because we want to run form_get_errors.
 
196
  include_once './includes/form.inc';
 
197
  install_task_list('database');
 
198
 
 
199
  $output = drupal_get_form('install_settings_form', $profile, $install_locale, $settings_file, $db_url, $db_type, $db_prefix, $db_user, $db_pass, $db_host, $db_port, $db_path);
 
200
  drupal_set_title(st('Database configuration'));
 
201
  print theme('install_page', $output);
 
202
  exit;
 
203
}
 
204
 
 
205
 
 
206
/**
 
207
 * Form API array definition for install_settings.
 
208
 */
 
209
function install_settings_form(&$form_state, $profile, $install_locale, $settings_file, $db_url, $db_type, $db_prefix, $db_user, $db_pass, $db_host, $db_port, $db_path) {
 
210
  if (empty($db_host)) {
 
211
    $db_host = 'localhost';
 
212
  }
 
213
  $db_types = drupal_detect_database_types();
 
214
 
 
215
  // If both 'mysql' and 'mysqli' are available, we disable 'mysql':
 
216
  if (isset($db_types['mysqli'])) {
 
217
    unset($db_types['mysql']);
 
218
  }
 
219
 
 
220
  if (count($db_types) == 0) {
 
221
    $form['no_db_types'] = array(
 
222
      '#value' => st('Your web server does not appear to support any common database types. Check with your hosting provider to see if they offer any databases that <a href="@drupal-databases">Drupal supports</a>.', array('@drupal-databases' => 'http://drupal.org/node/270#database')),
 
223
    );
 
224
  }
 
225
  else {
 
226
    $form['basic_options'] = array(
 
227
      '#type' => 'fieldset',
 
228
      '#title' => st('Basic options'),
 
229
      '#description' => '<p>'. st('To set up your @drupal database, enter the following information.', array('@drupal' => drupal_install_profile_name())) .'</p>',
 
230
    );
 
231
 
 
232
    if (count($db_types) > 1) {
 
233
      $form['basic_options']['db_type'] = array(
 
234
        '#type' => 'radios',
 
235
        '#title' => st('Database type'),
 
236
        '#required' => TRUE,
 
237
        '#options' => $db_types,
 
238
        '#default_value' => ($db_type ? $db_type : current($db_types)),
 
239
        '#description' => st('The type of database your @drupal data will be stored in.', array('@drupal' => drupal_install_profile_name())),
 
240
      );
 
241
      $db_path_description = st('The name of the database your @drupal data will be stored in. It must exist on your server before @drupal can be installed.', array('@drupal' => drupal_install_profile_name()));
 
242
    }
 
243
    else {
 
244
      if (count($db_types) == 1) {
 
245
        $db_types = array_values($db_types);
 
246
        $form['basic_options']['db_type'] = array(
 
247
          '#type' => 'hidden',
 
248
          '#value' => $db_types[0],
 
249
        );
 
250
        $db_path_description = st('The name of the %db_type database your @drupal data will be stored in. It must exist on your server before @drupal can be installed.', array('%db_type' => $db_types[0], '@drupal' => drupal_install_profile_name()));
 
251
      }
 
252
    }
 
253
 
 
254
    // Database name
 
255
    $form['basic_options']['db_path'] = array(
 
256
      '#type' => 'textfield',
 
257
      '#title' => st('Database name'),
 
258
      '#default_value' => $db_path,
 
259
      '#size' => 45,
 
260
      '#required' => TRUE,
 
261
      '#description' => $db_path_description
 
262
    );
 
263
 
 
264
    // Database username
 
265
    $form['basic_options']['db_user'] = array(
 
266
      '#type' => 'textfield',
 
267
      '#title' => st('Database username'),
 
268
      '#default_value' => $db_user,
 
269
      '#size' => 45,
 
270
      '#required' => TRUE,
 
271
    );
 
272
 
 
273
    // Database username
 
274
    $form['basic_options']['db_pass'] = array(
 
275
      '#type' => 'password',
 
276
      '#title' => st('Database password'),
 
277
      '#default_value' => $db_pass,
 
278
      '#size' => 45,
 
279
    );
 
280
 
 
281
    $form['advanced_options'] = array(
 
282
      '#type' => 'fieldset',
 
283
      '#title' => st('Advanced options'),
 
284
      '#collapsible' => TRUE,
 
285
      '#collapsed' => TRUE,
 
286
      '#description' => st("These options are only necessary for some sites. If you're not sure what you should enter here, leave the default settings or check with your hosting provider.")
 
287
    );
 
288
 
 
289
    // Database host
 
290
    $form['advanced_options']['db_host'] = array(
 
291
      '#type' => 'textfield',
 
292
      '#title' => st('Database host'),
 
293
      '#default_value' => $db_host,
 
294
      '#size' => 45,
 
295
      // Hostnames can be 255 characters long.
 
296
      '#maxlength' => 255,
 
297
      '#required' => TRUE,
 
298
      '#description' => st('If your database is located on a different server, change this.'),
 
299
    );
 
300
 
 
301
    // Database port
 
302
    $form['advanced_options']['db_port'] = array(
 
303
      '#type' => 'textfield',
 
304
      '#title' => st('Database port'),
 
305
      '#default_value' => $db_port,
 
306
      '#size' => 45,
 
307
      // The maximum port number is 65536, 5 digits.
 
308
      '#maxlength' => 5,
 
309
      '#description' => st('If your database server is listening to a non-standard port, enter its number.'),
 
310
    );
 
311
 
 
312
    // Table prefix
 
313
    $prefix = ($profile == 'default') ? 'drupal_' : $profile .'_';
 
314
    $form['advanced_options']['db_prefix'] = array(
 
315
      '#type' => 'textfield',
 
316
      '#title' => st('Table prefix'),
 
317
      '#default_value' => $db_prefix,
 
318
      '#size' => 45,
 
319
      '#description' => st('If more than one application will be sharing this database, enter a table prefix such as %prefix for your @drupal site here.', array('@drupal' => drupal_install_profile_name(), '%prefix' => $prefix)),
 
320
    );
 
321
 
 
322
    $form['save'] = array(
 
323
      '#type' => 'submit',
 
324
      '#value' => st('Save and continue'),
 
325
    );
 
326
 
 
327
    $form['errors'] = array();
 
328
    $form['settings_file'] = array('#type' => 'value', '#value' => $settings_file);
 
329
    $form['_db_url'] = array('#type' => 'value');
 
330
    $form['#action'] = "install.php?profile=$profile". ($install_locale ? "&locale=$install_locale" : '');
 
331
    $form['#redirect'] = FALSE;
 
332
  }
 
333
  return $form;
 
334
}
 
335
 
 
336
/**
 
337
 * Form API validate for install_settings form.
 
338
 */
 
339
function install_settings_form_validate($form, &$form_state) {
 
340
  global $db_url;
 
341
  _install_settings_form_validate($form_state['values']['db_prefix'], $form_state['values']['db_type'], $form_state['values']['db_user'], $form_state['values']['db_pass'], $form_state['values']['db_host'], $form_state['values']['db_port'], $form_state['values']['db_path'], $form_state['values']['settings_file'], $form_state, $form);
 
342
}
 
343
 
 
344
/**
 
345
 * Helper function for install_settings_validate.
 
346
 */
 
347
function _install_settings_form_validate($db_prefix, $db_type, $db_user, $db_pass, $db_host, $db_port, $db_path, $settings_file, &$form_state, $form = NULL) {
 
348
  global $db_url;
 
349
 
 
350
  // Verify the table prefix
 
351
  if (!empty($db_prefix) && is_string($db_prefix) && !preg_match('/^[A-Za-z0-9_.]+$/', $db_prefix)) {
 
352
    form_set_error('db_prefix', st('The database table prefix you have entered, %db_prefix, is invalid. The table prefix can only contain alphanumeric characters, periods, or underscores.', array('%db_prefix' => $db_prefix)), 'error');
 
353
  }
 
354
 
 
355
  if (!empty($db_port) && !is_numeric($db_port)) {
 
356
    form_set_error('db_port', st('Database port must be a number.'));
 
357
  }
 
358
 
 
359
  // Check database type
 
360
  if (!isset($form)) {
 
361
    $_db_url = is_array($db_url) ? $db_url['default'] : $db_url;
 
362
    $db_type = substr($_db_url, 0, strpos($_db_url, '://'));
 
363
  }
 
364
  $databases = drupal_detect_database_types();
 
365
  if (!in_array($db_type, $databases)) {
 
366
    form_set_error('db_type', st("In your %settings_file file you have configured @drupal to use a %db_type server, however your PHP installation currently does not support this database type.", array('%settings_file' => $settings_file, '@drupal' => drupal_install_profile_name(), '%db_type' => $db_type)));
 
367
  }
 
368
  else {
 
369
    // Verify
 
370
    $db_url = $db_type .'://'. urlencode($db_user) . ($db_pass ? ':'. urlencode($db_pass) : '') .'@'. ($db_host ? urlencode($db_host) : 'localhost') . ($db_port ? ":$db_port" : '') .'/'. urlencode($db_path);
 
371
    if (isset($form)) {
 
372
      form_set_value($form['_db_url'], $db_url, $form_state);
 
373
    }
 
374
    $success = array();
 
375
 
 
376
    $function = 'drupal_test_'. $db_type;
 
377
    if (!$function($db_url, $success)) {
 
378
      if (isset($success['CONNECT'])) {
 
379
        form_set_error('db_type', st('In order for Drupal to work, and to continue with the installation process, you must resolve all permission issues reported above. We were able to verify that we have permission for the following commands: %commands. For more help with configuring your database server, see the <a href="http://drupal.org/node/258">Installation and upgrading handbook</a>. If you are unsure what any of this means you should probably contact your hosting provider.', array('%commands' => implode($success, ', '))));
 
380
      }
 
381
      else {
 
382
        form_set_error('db_type', '');
 
383
      }
 
384
    }
 
385
  }
 
386
}
 
387
 
 
388
/**
 
389
 * Form API submit for install_settings form.
 
390
 */
 
391
function install_settings_form_submit($form, &$form_state) {
 
392
  global $profile, $install_locale;
 
393
 
 
394
  // Update global settings array and save
 
395
  $settings['db_url'] = array(
 
396
    'value'    => $form_state['values']['_db_url'],
 
397
    'required' => TRUE,
 
398
  );
 
399
  $settings['db_prefix'] = array(
 
400
    'value'    => $form_state['values']['db_prefix'],
 
401
    'required' => TRUE,
 
402
  );
 
403
  drupal_rewrite_settings($settings);
 
404
 
 
405
  // Continue to install profile step
 
406
  install_goto("install.php?profile=$profile". ($install_locale ? "&locale=$install_locale" : ''));
 
407
}
 
408
 
 
409
/**
 
410
 * Find all .profile files.
 
411
 */
 
412
function install_find_profiles() {
 
413
  return file_scan_directory('./profiles', '\.profile$', array('.', '..', 'CVS'), 0, TRUE, 'name', 0);
 
414
}
 
415
 
 
416
/**
 
417
 * Allow admin to select which profile to install.
 
418
 *
 
419
 * @return
 
420
 *   The selected profile.
 
421
 */
 
422
function install_select_profile() {
 
423
  include_once './includes/form.inc';
 
424
 
 
425
  $profiles = install_find_profiles();
 
426
  // Don't need to choose profile if only one available.
 
427
  if (sizeof($profiles) == 1) {
 
428
    $profile = array_pop($profiles);
 
429
    require_once $profile->filename;
 
430
    return $profile->name;
 
431
  }
 
432
  elseif (sizeof($profiles) > 1) {
 
433
    foreach ($profiles as $profile) {
 
434
      if (!empty($_POST['profile']) && ($_POST['profile'] == $profile->name)) {
 
435
        return $profile->name;
 
436
      }
 
437
    }
 
438
 
 
439
    install_task_list('profile-select');
 
440
 
 
441
    drupal_set_title(st('Select an installation profile'));
 
442
    print theme('install_page', drupal_get_form('install_select_profile_form', $profiles));
 
443
    exit;
 
444
  }
 
445
}
 
446
 
 
447
/**
 
448
 * Form API array definition for the profile selection form.
 
449
 *
 
450
 * @param $form_state
 
451
 *   Array of metadata about state of form processing.
 
452
 * @param $profile_files
 
453
 *   Array of .profile files, as returned from file_scan_directory().
 
454
 */
 
455
function install_select_profile_form(&$form_state, $profile_files) {
 
456
  $profiles = array();
 
457
  $names = array();
 
458
 
 
459
  foreach ($profile_files as $profile) {
 
460
    include_once($profile->filename);
 
461
 
 
462
    // Load profile details and store them for later retrieval.
 
463
    $function = $profile->name .'_profile_details';
 
464
    if (function_exists($function)) {
 
465
      $details = $function();
 
466
    }
 
467
    $profiles[$profile->name] = $details;
 
468
 
 
469
    // Determine the name of the profile; default to file name if defined name
 
470
    // is unspecified.
 
471
    $name = isset($details['name']) ? $details['name'] : $profile->name;
 
472
    $names[$profile->name] = $name;
 
473
  }
 
474
 
 
475
  // Display radio buttons alphabetically by human-readable name. 
 
476
  natcasesort($names);
 
477
  foreach ($names as $profile => $name) {
 
478
    $form['profile'][$name] = array(
 
479
      '#type' => 'radio',
 
480
      '#value' => 'default',
 
481
      '#return_value' => $profile,
 
482
      '#title' => $name,
 
483
      '#description' => isset($profiles[$profile]['description']) ? $profiles[$profile]['description'] : '',
 
484
      '#parents' => array('profile'),
 
485
    );
 
486
  }
 
487
  $form['submit'] =  array(
 
488
    '#type' => 'submit',
 
489
    '#value' => st('Save and continue'),
 
490
  );
 
491
  return $form;
 
492
}
 
493
 
 
494
/**
 
495
 * Find all .po files for the current profile.
 
496
 */
 
497
function install_find_locales($profilename) {
 
498
  $locales = file_scan_directory('./profiles/'. $profilename .'/translations', '\.po$', array('.', '..', 'CVS'), 0, FALSE);
 
499
  array_unshift($locales, (object) array('name' => 'en'));
 
500
  return $locales;
 
501
}
 
502
 
 
503
/**
 
504
 * Allow admin to select which locale to use for the current profile.
 
505
 *
 
506
 * @return
 
507
 *   The selected language.
 
508
 */
 
509
function install_select_locale($profilename) {
 
510
  include_once './includes/file.inc';
 
511
  include_once './includes/form.inc';
 
512
 
 
513
  // Find all available locales.
 
514
  $locales = install_find_locales($profilename);
 
515
 
 
516
  // If only the built-in (English) language is available,
 
517
  // and we are using the default profile, inform the user
 
518
  // that the installer can be localized. Otherwise we assume
 
519
  // the user know what he is doing.
 
520
  if (count($locales) == 1) {
 
521
    if ($profilename == 'default') {
 
522
      install_task_list('locale-select');
 
523
      drupal_set_title(st('Choose language'));
 
524
      if (!empty($_GET['localize'])) {
 
525
        $output = '<p>'. st('With the addition of an appropriate translation package, this installer is capable of proceeding in another language of your choice. To install and use Drupal in a language other than English:') .'</p>';
 
526
        $output .= '<ul><li>'. st('Determine if <a href="@translations" target="_blank">a translation of this Drupal version</a> is available in your language of choice. A translation is provided via a translation package; each translation package enables the display of a specific version of Drupal in a specific language. Not all languages are available for every version of Drupal.', array('@translations' => 'http://drupal.org/project/translations')) .'</li>';
 
527
        $output .= '<li>'. st('If an alternative translation package of your choice is available, download and extract its contents to your Drupal root directory.') .'</li>';
 
528
        $output .= '<li>'. st('Return to choose language using the second link below and select your desired language from the displayed list. Reloading the page allows the list to automatically adjust to the presence of new translation packages.') .'</li>';
 
529
        $output .= '</ul><p>'. st('Alternatively, to install and use Drupal in English, or to defer the selection of an alternative language until after installation, select the first link below.') .'</p>';
 
530
        $output .= '<p>'. st('How should the installation continue?') .'</p>';
 
531
        $output .= '<ul><li><a href="install.php?profile='. $profilename .'&amp;locale=en">'. st('Continue installation in English') .'</a></li><li><a href="install.php?profile='. $profilename .'">'. st('Return to choose a language') .'</a></li></ul>';
 
532
      }
 
533
      else {
 
534
        $output = '<ul><li><a href="install.php?profile='. $profilename .'&amp;locale=en">'. st('Install Drupal in English') .'</a></li><li><a href="install.php?profile='. $profilename .'&amp;localize=true">'. st('Learn how to install Drupal in other languages') .'</a></li></ul>';
 
535
      }
 
536
      print theme('install_page', $output);
 
537
      exit;
 
538
    }
 
539
    // One language, but not the default profile, assume
 
540
    // the user knows what he is doing.
 
541
    return FALSE;
 
542
  }
 
543
  else {
 
544
    // Allow profile to pre-select the language, skipping the selection.
 
545
    $function = $profilename .'_profile_details';
 
546
    if (function_exists($function)) {
 
547
      $details = $function();
 
548
      if (isset($details['language'])) {
 
549
        foreach ($locales as $locale) {
 
550
          if ($details['language'] == $locale->name) {
 
551
            return $locale->name;
 
552
          }
 
553
        }
 
554
      }
 
555
    }
 
556
 
 
557
    if (!empty($_POST['locale'])) {
 
558
      foreach ($locales as $locale) {
 
559
        if ($_POST['locale'] == $locale->name) {
 
560
          return $locale->name;
 
561
        }
 
562
      }
 
563
    }
 
564
 
 
565
    install_task_list('locale-select');
 
566
 
 
567
    drupal_set_title(st('Choose language'));
 
568
    print theme('install_page', drupal_get_form('install_select_locale_form', $locales));
 
569
    exit;
 
570
  }
 
571
}
 
572
 
 
573
/**
 
574
 * Form API array definition for language selection.
 
575
 */
 
576
function install_select_locale_form(&$form_state, $locales) {
 
577
  include_once './includes/locale.inc';
 
578
  $languages = _locale_get_predefined_list();
 
579
  foreach ($locales as $locale) {
 
580
    // Try to use verbose locale name
 
581
    $name = $locale->name;
 
582
    if (isset($languages[$name])) {
 
583
      $name = $languages[$name][0] . (isset($languages[$name][1]) ? ' '. st('(@language)', array('@language' => $languages[$name][1])) : '');
 
584
    }
 
585
    $form['locale'][$locale->name] = array(
 
586
      '#type' => 'radio',
 
587
      '#return_value' => $locale->name,
 
588
      '#default_value' => ($locale->name == 'en' ? TRUE : FALSE),
 
589
      '#title' => $name . ($locale->name == 'en' ? ' '. st('(built-in)') : ''),
 
590
      '#parents' => array('locale')
 
591
    );
 
592
  }
 
593
  $form['submit'] =  array(
 
594
    '#type' => 'submit',
 
595
    '#value' => st('Select language'),
 
596
  );
 
597
  return $form;
 
598
}
 
599
 
 
600
/**
 
601
 * Show an error page when there are no profiles available.
 
602
 */
 
603
function install_no_profile_error() {
 
604
  install_task_list('profile-select');
 
605
  drupal_set_title(st('No profiles available'));
 
606
  print theme('install_page', '<p>'. st('We were unable to find any installer profiles. Installer profiles tell us what modules to enable and what schema to install in the database. A profile is necessary to continue with the installation process.') .'</p>');
 
607
  exit;
 
608
}
 
609
 
 
610
 
 
611
/**
 
612
 * Show an error page when Drupal has already been installed.
 
613
 */
 
614
function install_already_done_error() {
 
615
  global $base_url;
 
616
 
 
617
  drupal_set_title(st('Drupal already installed'));
 
618
  print theme('install_page', st('<ul><li>To start over, you must empty your existing database.</li><li>To install to a different database, edit the appropriate <em>settings.php</em> file in the <em>sites</em> folder.</li><li>To upgrade an existing installation, proceed to the <a href="@base-url/update.php">update script</a>.</li><li>View your <a href="@base-url">existing site</a>.</li></ul>', array('@base-url' => $base_url)));
 
619
  exit;
 
620
}
 
621
 
 
622
/**
 
623
 * Tasks performed after the database is initialized.
 
624
 */
 
625
function install_tasks($profile, $task) {
 
626
  global $base_url, $install_locale;
 
627
 
 
628
  // Bootstrap newly installed Drupal, while preserving existing messages.
 
629
  $messages = isset($_SESSION['messages']) ? $_SESSION['messages'] : '';
 
630
  drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
 
631
  $_SESSION['messages'] = $messages;
 
632
 
 
633
  // URL used to direct page requests.
 
634
  $url = $base_url .'/install.php?locale='. $install_locale .'&profile='. $profile;
 
635
 
 
636
  // Build a page for final tasks.
 
637
  if (empty($task)) {
 
638
    variable_set('install_task', 'profile-install');
 
639
    $task = 'profile-install';
 
640
  }
 
641
 
 
642
  // We are using a list of if constructs here to allow for
 
643
  // passing from one task to the other in the same request.
 
644
 
 
645
  // Install profile modules.
 
646
  if ($task == 'profile-install') {
 
647
    $modules = variable_get('install_profile_modules', array());
 
648
    $files = module_rebuild_cache();
 
649
    variable_del('install_profile_modules');
 
650
    $operations = array();
 
651
    foreach ($modules as $module) {
 
652
      $operations[] = array('_install_module_batch', array($module, $files[$module]->info['name']));
 
653
    }
 
654
    $batch = array(
 
655
      'operations' => $operations,
 
656
      'finished' => '_install_profile_batch_finished',
 
657
      'title' => st('Installing @drupal', array('@drupal' => drupal_install_profile_name())),
 
658
      'error_message' => st('The installation has encountered an error.'),
 
659
    );
 
660
    // Start a batch, switch to 'profile-install-batch' task. We need to
 
661
    // set the variable here, because batch_process() redirects.
 
662
    variable_set('install_task', 'profile-install-batch');
 
663
    batch_set($batch);
 
664
    batch_process($url, $url);
 
665
  }
 
666
  // We are running a batch install of the profile's modules.
 
667
  // This might run in multiple HTTP requests, constantly redirecting
 
668
  // to the same address, until the batch finished callback is invoked
 
669
  // and the task advances to 'locale-initial-import'.
 
670
  if ($task == 'profile-install-batch') {
 
671
    include_once 'includes/batch.inc';
 
672
    $output = _batch_page();
 
673
  }
 
674
 
 
675
  // Import interface translations for the enabled modules.
 
676
  if ($task == 'locale-initial-import') {
 
677
    if (!empty($install_locale) && ($install_locale != 'en')) {
 
678
      include_once 'includes/locale.inc';
 
679
      // Enable installation language as default site language.
 
680
      locale_add_language($install_locale, NULL, NULL, NULL, NULL, NULL, 1, TRUE);
 
681
      // Collect files to import for this language.
 
682
      $batch = locale_batch_by_language($install_locale, '_install_locale_initial_batch_finished');
 
683
      if (!empty($batch)) {
 
684
        // Remember components we cover in this batch set.
 
685
        variable_set('install_locale_batch_components', $batch['#components']);
 
686
        // Start a batch, switch to 'locale-batch' task. We need to
 
687
        // set the variable here, because batch_process() redirects.
 
688
        variable_set('install_task', 'locale-initial-batch');
 
689
        batch_set($batch);
 
690
        batch_process($url, $url);
 
691
      }
 
692
    }
 
693
    // Found nothing to import or not foreign language, go to next task.
 
694
    $task = 'configure';
 
695
  }
 
696
  if ($task == 'locale-initial-batch') {
 
697
    include_once 'includes/batch.inc';
 
698
    include_once 'includes/locale.inc';
 
699
    $output = _batch_page();
 
700
  }
 
701
 
 
702
  if ($task == 'configure') {
 
703
    if (variable_get('site_name', FALSE) || variable_get('site_mail', FALSE)) {
 
704
      // Site already configured: This should never happen, means re-running
 
705
      // the installer, possibly by an attacker after the 'install_task' variable
 
706
      // got accidentally blown somewhere. Stop it now.
 
707
      install_already_done_error();
 
708
    }
 
709
    $form = drupal_get_form('install_configure_form', $url);
 
710
 
 
711
    if (!variable_get('site_name', FALSE) && !variable_get('site_mail', FALSE)) {
 
712
      // Not submitted yet: Prepare to display the form.
 
713
      $output = $form;
 
714
      drupal_set_title(st('Configure site'));
 
715
 
 
716
      // Warn about settings.php permissions risk
 
717
      $settings_dir = './'. conf_path();
 
718
      $settings_file = $settings_dir .'/settings.php';
 
719
      if (!drupal_verify_install_file($settings_file, FILE_EXIST|FILE_READABLE|FILE_NOT_WRITABLE) || !drupal_verify_install_file($settings_dir, FILE_NOT_WRITABLE, 'dir')) {
 
720
        drupal_set_message(st('All necessary changes to %dir and %file have been made, so you should remove write permissions to them now in order to avoid security risks. If you are unsure how to do so, please consult the <a href="@handbook_url">on-line handbook</a>.', array('%dir' => $settings_dir, '%file' => $settings_file, '@handbook_url' => 'http://drupal.org/getting-started')), 'error');
 
721
      }
 
722
      else {
 
723
        drupal_set_message(st('All necessary changes to %dir and %file have been made. They have been set to read-only for security.', array('%dir' => $settings_dir, '%file' => $settings_file)));
 
724
      }
 
725
 
 
726
      // Add JavaScript validation.
 
727
      _user_password_dynamic_validation();
 
728
      drupal_add_js(drupal_get_path('module', 'system') .'/system.js', 'module');
 
729
      // We add these strings as settings because JavaScript translation does not
 
730
      // work on install time.
 
731
      drupal_add_js(array('copyFieldValue' => array('edit-site-mail' => array('edit-account-mail')), 'cleanURL' => array('success' => st('Your server has been successfully tested to support this feature.'), 'failure' => st('Your system configuration does not currently support this feature. The <a href="http://drupal.org/node/15365">handbook page on Clean URLs</a> has additional troubleshooting information.'), 'testing' => st('Testing clean URLs...'))), 'setting');
 
732
      drupal_add_js('
 
733
// Global Killswitch
 
734
if (Drupal.jsEnabled) {
 
735
  $(document).ready(function() {
 
736
    Drupal.cleanURLsInstallCheck();
 
737
    Drupal.setDefaultTimezone();
 
738
  });
 
739
}', 'inline');
 
740
      // Build menu to allow clean URL check.
 
741
      menu_rebuild();
 
742
    }
 
743
 
 
744
    else {
 
745
      $task = 'profile';
 
746
    }
 
747
  }
 
748
 
 
749
  // If found an unknown task or the 'profile' task, which is
 
750
  // reserved for profiles, hand over the control to the profile,
 
751
  // so it can run any number of custom tasks it defines.
 
752
  if (!in_array($task, install_reserved_tasks())) {
 
753
    $function = $profile .'_profile_tasks';
 
754
    if (function_exists($function)) {
 
755
      // The profile needs to run more code, maybe even more tasks.
 
756
      // $task is sent through as a reference and may be changed!
 
757
      $output = $function($task, $url);
 
758
    }
 
759
 
 
760
    // If the profile doesn't move on to a new task we assume
 
761
    // that it is done.
 
762
    if ($task == 'profile') {
 
763
      $task = 'profile-finished';
 
764
    }
 
765
  }
 
766
 
 
767
  // Profile custom tasks are done, so let the installer regain
 
768
  // control and proceed with importing the remaining translations.
 
769
  if ($task == 'profile-finished') {
 
770
    if (!empty($install_locale) && ($install_locale != 'en')) {
 
771
      include_once 'includes/locale.inc';
 
772
      // Collect files to import for this language. Skip components
 
773
      // already covered in the initial batch set.
 
774
      $batch = locale_batch_by_language($install_locale, '_install_locale_remaining_batch_finished', variable_get('install_locale_batch_components', array()));
 
775
      // Remove temporary variable.
 
776
      variable_del('install_locale_batch_components');
 
777
      if (!empty($batch)) {
 
778
        // Start a batch, switch to 'locale-remaining-batch' task. We need to
 
779
        // set the variable here, because batch_process() redirects.
 
780
        variable_set('install_task', 'locale-remaining-batch');
 
781
        batch_set($batch);
 
782
        batch_process($url, $url);
 
783
      }
 
784
    }
 
785
    // Found nothing to import or not foreign language, go to next task.
 
786
    $task = 'finished';
 
787
  }
 
788
  if ($task == 'locale-remaining-batch') {
 
789
    include_once 'includes/batch.inc';
 
790
    include_once 'includes/locale.inc';
 
791
    $output = _batch_page();
 
792
  }
 
793
 
 
794
  // Display a 'finished' page to user.
 
795
  if ($task == 'finished') {
 
796
    drupal_set_title(st('@drupal installation complete', array('@drupal' => drupal_install_profile_name())));
 
797
    $messages = drupal_set_message();
 
798
    $output = '<p>'. st('Congratulations, @drupal has been successfully installed.', array('@drupal' => drupal_install_profile_name())) .'</p>';
 
799
    $output .= '<p>'. (isset($messages['error']) ? st('Please review the messages above before continuing on to <a href="@url">your new site</a>.', array('@url' => url(''))) : st('You may now visit <a href="@url">your new site</a>.', array('@url' => url('')))) .'</p>';
 
800
    $task = 'done';
 
801
  }
 
802
 
 
803
  // The end of the install process. Remember profile used.
 
804
  if ($task == 'done') {
 
805
    // Rebuild menu to get content type links registered by the profile,
 
806
    // and possibly any other menu items created through the tasks.
 
807
    menu_rebuild();
 
808
 
 
809
    // Register actions declared by any modules.
 
810
    actions_synchronize();
 
811
 
 
812
    // Randomize query-strings on css/js files, to hide the fact that
 
813
    // this is a new install, not upgraded yet.
 
814
    _drupal_flush_css_js();
 
815
 
 
816
    variable_set('install_profile', $profile);
 
817
  }
 
818
 
 
819
  // Set task for user, and remember the task in the database.
 
820
  install_task_list($task);
 
821
  variable_set('install_task', $task);
 
822
 
 
823
  // Output page, if some output was required. Otherwise it is possible
 
824
  // that we are printing a JSON page and theme output should not be there.
 
825
  if (isset($output)) {
 
826
    print theme('maintenance_page', $output);
 
827
  }
 
828
}
 
829
 
 
830
/**
 
831
 * Batch callback for batch installation of modules.
 
832
 */
 
833
function _install_module_batch($module, $module_name, &$context) {
 
834
  _drupal_install_module($module);
 
835
  // We enable the installed module right away, so that the module will be
 
836
  // loaded by drupal_bootstrap in subsequent batch requests, and other
 
837
  // modules possibly depending on it can safely perform their installation
 
838
  // steps.
 
839
  module_enable(array($module));
 
840
  $context['results'][] = $module;
 
841
  $context['message'] = st('Installed %module module.', array('%module' => $module_name));
 
842
}
 
843
 
 
844
/**
 
845
 * Finished callback for the modules install batch.
 
846
 *
 
847
 * Advance installer task to language import.
 
848
 */
 
849
function _install_profile_batch_finished($success, $results) {
 
850
  variable_set('install_task', 'locale-initial-import');
 
851
}
 
852
 
 
853
/**
 
854
 * Finished callback for the first locale import batch.
 
855
 *
 
856
 * Advance installer task to the configure screen.
 
857
 */
 
858
function _install_locale_initial_batch_finished($success, $results) {
 
859
  variable_set('install_task', 'configure');
 
860
}
 
861
 
 
862
/**
 
863
 * Finished callback for the second locale import batch.
 
864
 *
 
865
 * Advance installer task to the finished screen.
 
866
 */
 
867
function _install_locale_remaining_batch_finished($success, $results) {
 
868
  variable_set('install_task', 'finished');
 
869
}
 
870
 
 
871
/**
 
872
 * The list of reserved tasks to run in the installer.
 
873
 */
 
874
function install_reserved_tasks() {
 
875
  return array('configure', 'profile-install', 'profile-install-batch', 'locale-initial-import', 'locale-initial-batch', 'profile-finished', 'locale-remaining-batch', 'finished', 'done');
 
876
}
 
877
 
 
878
/**
 
879
 * Check installation requirements and report any errors.
 
880
 */
 
881
function install_check_requirements($profile, $verify) {
 
882
 
 
883
  // If Drupal is not set up already, we need to create a settings file.
 
884
  if (!$verify) {
 
885
    $writable = FALSE;
 
886
    $conf_path = './'. conf_path(FALSE, TRUE);
 
887
    $settings_file = $conf_path .'/settings.php';
 
888
    $file = $conf_path;
 
889
    $exists = FALSE;
 
890
    // Verify that the directory exists.
 
891
    if (drupal_verify_install_file($conf_path, FILE_EXIST, 'dir')) {
 
892
      // Check to make sure a settings.php already exists.
 
893
      $file = $settings_file;
 
894
      if (drupal_verify_install_file($settings_file, FILE_EXIST)) {
 
895
        $exists = TRUE;
 
896
        // If it does, make sure it is writable.
 
897
        $writable = drupal_verify_install_file($settings_file, FILE_READABLE|FILE_WRITABLE);
 
898
      }
 
899
    }
 
900
    if (!$exists) {
 
901
      drupal_set_message(st('The @drupal installer requires that you create a settings file as part of the installation process.
 
902
<ol>
 
903
<li>Copy the %default_file file to %file.</li>
 
904
<li>Change file permissions so that it is writable by the web server. If you are unsure how to grant file permissions, please consult the <a href="@handbook_url">on-line handbook</a>.</li>
 
905
</ol>
 
906
More details about installing Drupal are available in INSTALL.txt.', array('@drupal' => drupal_install_profile_name(), '%file' => $file, '%default_file' => $conf_path .'/default.settings.php', '@handbook_url' => 'http://drupal.org/server-permissions')), 'error');
 
907
    }
 
908
    elseif (!$writable) {
 
909
      drupal_set_message(st('The @drupal installer requires write permissions to %file during the installation process. If you are unsure how to grant file permissions, please consult the <a href="@handbook_url">on-line handbook</a>.', array('@drupal' => drupal_install_profile_name(), '%file' => $file, '@handbook_url' => 'http://drupal.org/server-permissions')), 'error');
 
910
    }
 
911
  }
 
912
 
 
913
  // Check the other requirements.
 
914
  $requirements = drupal_check_profile($profile);
 
915
  $severity = drupal_requirements_severity($requirements);
 
916
 
 
917
  // If there are issues, report them.
 
918
  if ($severity == REQUIREMENT_ERROR) {
 
919
 
 
920
    foreach ($requirements as $requirement) {
 
921
      if (isset($requirement['severity']) && $requirement['severity'] == REQUIREMENT_ERROR) {
 
922
        $message = $requirement['description'];
 
923
        if (isset($requirement['value']) && $requirement['value']) {
 
924
          $message .= ' ('. st('Currently using !item !version', array('!item' => $requirement['title'], '!version' => $requirement['value'])) .')';
 
925
        }
 
926
        drupal_set_message($message, 'error');
 
927
      }
 
928
    }
 
929
  }
 
930
  if ($severity == REQUIREMENT_WARNING) {
 
931
 
 
932
    foreach ($requirements as $requirement) {
 
933
      if (isset($requirement['severity']) && $requirement['severity'] == REQUIREMENT_WARNING) {
 
934
        $message = $requirement['description'];
 
935
        if (isset($requirement['value']) && $requirement['value']) {
 
936
          $message .= ' ('. st('Currently using !item !version', array('!item' => $requirement['title'], '!version' => $requirement['value'])) .')';
 
937
        }
 
938
        drupal_set_message($message, 'warning');
 
939
      }
 
940
    }
 
941
  } 
 
942
}
 
943
 
 
944
/**
 
945
 * Add the installation task list to the current page.
 
946
 */
 
947
function install_task_list($active = NULL) {
 
948
  // Default list of tasks.
 
949
  $tasks = array(
 
950
    'profile-select'        => st('Choose profile'),
 
951
    'locale-select'         => st('Choose language'),
 
952
    'requirements'          => st('Verify requirements'),
 
953
    'database'              => st('Set up database'),
 
954
    'profile-install-batch' => st('Install profile'),
 
955
    'locale-initial-batch'  => st('Set up translations'),
 
956
    'configure'             => st('Configure site'),
 
957
  );
 
958
 
 
959
  $profiles = install_find_profiles();
 
960
  $profile = isset($_GET['profile']) && isset($profiles[$_GET['profile']]) ? $_GET['profile'] : '.';
 
961
  $locales = install_find_locales($profile);
 
962
 
 
963
  // If we have only one profile, remove 'Choose profile'
 
964
  // and rename 'Install profile'.
 
965
  if (count($profiles) == 1) {
 
966
    unset($tasks['profile-select']);
 
967
    $tasks['profile-install-batch'] = st('Install site');
 
968
  }
 
969
 
 
970
  // Add tasks defined by the profile.
 
971
  if ($profile) {
 
972
    $function = $profile .'_profile_task_list';
 
973
    if (function_exists($function)) {
 
974
      $result = $function();
 
975
      if (is_array($result)) {
 
976
        $tasks += $result;
 
977
      }
 
978
    }
 
979
  }
 
980
 
 
981
  if (count($locales) < 2 || empty($_GET['locale']) || $_GET['locale'] == 'en') {
 
982
    // If not required, remove translation import from the task list.
 
983
    unset($tasks['locale-initial-batch']);
 
984
  }
 
985
  else {
 
986
    // If required, add remaining translations import task.
 
987
    $tasks += array('locale-remaining-batch' => st('Finish translations'));
 
988
  }
 
989
 
 
990
  // Add finished step as the last task.
 
991
  $tasks += array(
 
992
    'finished'     => st('Finished')
 
993
  );
 
994
 
 
995
  // Let the theming function know that 'finished' and 'done'
 
996
  // include everything, so every step is completed.
 
997
  if (in_array($active, array('finished', 'done'))) {
 
998
    $active = NULL;
 
999
  }
 
1000
  drupal_set_content('left', theme_task_list($tasks, $active));
 
1001
}
 
1002
 
 
1003
/**
 
1004
 * Form API array definition for site configuration.
 
1005
 */
 
1006
function install_configure_form(&$form_state, $url) {
 
1007
 
 
1008
  $form['intro'] = array(
 
1009
    '#value' => st('To configure your website, please provide the following information.'),
 
1010
    '#weight' => -10,
 
1011
  );
 
1012
  $form['site_information'] = array(
 
1013
    '#type' => 'fieldset',
 
1014
    '#title' => st('Site information'),
 
1015
    '#collapsible' => FALSE,
 
1016
  );
 
1017
  $form['site_information']['site_name'] = array(
 
1018
    '#type' => 'textfield',
 
1019
    '#title' => st('Site name'),
 
1020
    '#required' => TRUE,
 
1021
    '#weight' => -20,
 
1022
  );
 
1023
  $form['site_information']['site_mail'] = array(
 
1024
    '#type' => 'textfield',
 
1025
    '#title' => st('Site e-mail address'),
 
1026
    '#default_value' => ini_get('sendmail_from'),
 
1027
    '#description' => st("The <em>From</em> address in automated e-mails sent during registration and new password requests, and other notifications. (Use an address ending in your site's domain to help prevent this e-mail being flagged as spam.)"),
 
1028
    '#required' => TRUE,
 
1029
    '#weight' => -15,
 
1030
  );
 
1031
  $form['admin_account'] = array(
 
1032
    '#type' => 'fieldset',
 
1033
    '#title' => st('Administrator account'),
 
1034
    '#collapsible' => FALSE,
 
1035
  );
 
1036
  $form['admin_account']['account']['#tree'] = TRUE;
 
1037
  $form['admin_account']['markup'] = array(
 
1038
    '#value' => '<p class="description">'. st('The administrator account has complete access to the site; it will automatically be granted all permissions and can perform any administrative activity. This will be the only account that can perform certain activities, so keep its credentials safe.') .'</p>',
 
1039
    '#weight' => -10,
 
1040
  );
 
1041
 
 
1042
  $form['admin_account']['account']['name'] = array('#type' => 'textfield',
 
1043
    '#title' => st('Username'),
 
1044
    '#maxlength' => USERNAME_MAX_LENGTH,
 
1045
    '#description' => st('Spaces are allowed; punctuation is not allowed except for periods, hyphens, and underscores.'),
 
1046
    '#required' => TRUE,
 
1047
    '#weight' => -10,
 
1048
  );
 
1049
 
 
1050
  $form['admin_account']['account']['mail'] = array('#type' => 'textfield',
 
1051
    '#title' => st('E-mail address'),
 
1052
    '#maxlength' => EMAIL_MAX_LENGTH,
 
1053
    '#description' => st('All e-mails from the system will be sent to this address. The e-mail address is not made public and will only be used if you wish to receive a new password or wish to receive certain news or notifications by e-mail.'),
 
1054
    '#required' => TRUE,
 
1055
    '#weight' => -5,
 
1056
  );
 
1057
  $form['admin_account']['account']['pass'] = array(
 
1058
    '#type' => 'password_confirm',
 
1059
    '#required' => TRUE,
 
1060
    '#size' => 25,
 
1061
    '#weight' => 0,
 
1062
  );
 
1063
 
 
1064
  $form['server_settings'] = array(
 
1065
    '#type' => 'fieldset',
 
1066
    '#title' => st('Server settings'),
 
1067
    '#collapsible' => FALSE,
 
1068
  );
 
1069
  $form['server_settings']['date_default_timezone'] = array(
 
1070
    '#type' => 'select',
 
1071
    '#title' => st('Default time zone'),
 
1072
    '#default_value' => 0,
 
1073
    '#options' => _system_zonelist(),
 
1074
    '#description' => st('By default, dates in this site will be displayed in the chosen time zone.'),
 
1075
    '#weight' => 5,
 
1076
  );
 
1077
 
 
1078
  $form['server_settings']['clean_url'] = array(
 
1079
    '#type' => 'radios',
 
1080
    '#title' => st('Clean URLs'),
 
1081
    '#default_value' => 0,
 
1082
    '#options' => array(0 => st('Disabled'), 1 => st('Enabled')),
 
1083
    '#description' => st('This option makes Drupal emit "clean" URLs (i.e. without <code>?q=</code> in the URL).'),
 
1084
    '#disabled' => TRUE,
 
1085
    '#prefix' => '<div id="clean-url" class="install">',
 
1086
    '#suffix' => '</div>',
 
1087
    '#weight' => 10,
 
1088
  );
 
1089
 
 
1090
  $form['server_settings']['update_status_module'] = array(
 
1091
    '#type' => 'checkboxes',
 
1092
    '#title' => st('Update notifications'),
 
1093
    '#options' => array(1 => st('Check for updates automatically')),
 
1094
    '#default_value' => array(1),
 
1095
    '#description' => st('With this option enabled, Drupal will notify you when new releases are available. This will significantly enhance your site\'s security and is <strong>highly recommended</strong>. This requires your site to periodically send anonymous information on its installed components to <a href="@drupal">drupal.org</a>. For more information please see the <a href="@update">update notification information</a>.', array('@drupal' => 'http://drupal.org', '@update' => 'http://drupal.org/handbook/modules/update')),
 
1096
    '#weight' => 15,
 
1097
  );
 
1098
 
 
1099
  $form['submit'] = array(
 
1100
    '#type' => 'submit',
 
1101
    '#value' => st('Save and continue'),
 
1102
    '#weight' => 15,
 
1103
  );
 
1104
  $form['#action'] = $url;
 
1105
  $form['#redirect'] = FALSE;
 
1106
 
 
1107
  // Allow the profile to alter this form. $form_state isn't available
 
1108
  // here, but to conform to the hook_form_alter() signature, we pass
 
1109
  // an empty array.
 
1110
  $hook_form_alter = $_GET['profile'] .'_form_alter';
 
1111
  if (function_exists($hook_form_alter)) {
 
1112
    $hook_form_alter($form, array(), 'install_configure');
 
1113
  }
 
1114
  return $form;
 
1115
}
 
1116
 
 
1117
/**
 
1118
 * Form API validate for the site configuration form.
 
1119
 */
 
1120
function install_configure_form_validate($form, &$form_state) {
 
1121
  if ($error = user_validate_name($form_state['values']['account']['name'])) {
 
1122
    form_error($form['admin_account']['account']['name'], $error);
 
1123
  }
 
1124
  if ($error = user_validate_mail($form_state['values']['account']['mail'])) {
 
1125
    form_error($form['admin_account']['account']['mail'], $error);
 
1126
  }
 
1127
  if ($error = user_validate_mail($form_state['values']['site_mail'])) {
 
1128
    form_error($form['site_information']['site_mail'], $error);
 
1129
  }
 
1130
}
 
1131
 
 
1132
/**
 
1133
 * Form API submit for the site configuration form.
 
1134
 */
 
1135
function install_configure_form_submit($form, &$form_state) {
 
1136
  global $user;
 
1137
 
 
1138
  variable_set('site_name', $form_state['values']['site_name']);
 
1139
  variable_set('site_mail', $form_state['values']['site_mail']);
 
1140
  variable_set('date_default_timezone', $form_state['values']['date_default_timezone']);
 
1141
 
 
1142
  // Enable update.module if this option was selected.
 
1143
  if ($form_state['values']['update_status_module'][1]) {
 
1144
    drupal_install_modules(array('update'));
 
1145
  }
 
1146
 
 
1147
  // Turn this off temporarily so that we can pass a password through.
 
1148
  variable_set('user_email_verification', FALSE);
 
1149
  $form_state['old_values'] = $form_state['values'];
 
1150
  $form_state['values'] = $form_state['values']['account'];
 
1151
 
 
1152
  // We precreated user 1 with placeholder values. Let's save the real values.
 
1153
  $account = user_load(1);
 
1154
  $merge_data = array('init' => $form_state['values']['mail'], 'roles' => array(), 'status' => 1);
 
1155
  user_save($account, array_merge($form_state['values'], $merge_data));
 
1156
  // Log in the first user.
 
1157
  user_authenticate($form_state['values']);
 
1158
  $form_state['values'] = $form_state['old_values'];
 
1159
  unset($form_state['old_values']);
 
1160
  variable_set('user_email_verification', TRUE);
 
1161
 
 
1162
  if (isset($form_state['values']['clean_url'])) {
 
1163
    variable_set('clean_url', $form_state['values']['clean_url']);
 
1164
  }
 
1165
  // The user is now logged in, but has no session ID yet, which
 
1166
  // would be required later in the request, so remember it.
 
1167
  $user->sid = session_id();
 
1168
 
 
1169
  // Record when this install ran.
 
1170
  variable_set('install_time', time());
 
1171
}
 
1172
 
 
1173
// Start the installer.
 
1174
install_main();