/** save the newly added area to the database * * This saves the essential information of a new area to the database, * using sensible defaults for the other fields. Also, a data directory * is created and the relative path is stored in the new area record. * * If something goes wrong, the user can redo the dialog, otherwise we * return to the area overview. * * @return void results are returned as output in $this->output * @uses $WAS_SCRIPT_NAME * @uses $CFG * @uses $USER */ function area_savenew() { global $WAS_SCRIPT_NAME, $USER, $CFG; // 1 -- bail out if user pressed cancel button if (isset($_POST['button_cancel'])) { $this->output->add_message(t('cancelled', 'admin')); $this->area_overview(); return; } // 2 -- dow we have permission to add an area? if (!$USER->has_site_permissions(PERMISSION_SITE_ADD_AREA)) { logger("areamanager: user attempted to add an area without permission"); $msg = t('task_area_add_access_denied', 'admin'); $this->output->add_message($msg); $this->output->add_popup_bottom($msg); $this->area_overview(); return; } // 3 -- validate the data $invalid = FALSE; $dialogdef = $this->get_dialogdef_add_area(); // 3A -- check for generic errors (string too short, number too small, etc) if (!dialog_validate($dialogdef)) { $invalid = TRUE; } // 3B -- additional check: valid datadirectory name entered $path = $dialogdef['area_path']['value']; $fname = isset($dialogdef['area_path']['label']) ? $dialogdef['area_path']['label'] : 'area_path'; $params = array('{FIELD}' => str_replace('~', '', $fname)); $areadata_directory = sanitise_filename($path); if ($path != $areadata_directory) { // User probably entered a few 'illegal' characters. This is no good $dialogdef['area_path']['value'] = $areadata_directory; // 'Help' user with a better proposition ++$dialogdef['area_path']['errors']; $params['{VALUE}'] = htmlspecialchars($path); $dialogdef['area_path']['error_messages'][] = t('validate_bad_filename', '', $params); $invalid = TRUE; } // 3C -- additional check: unique datadirectory name entered $areadata_directory = strtolower($areadata_directory); $where = array('path' => $areadata_directory); if (db_select_single_record('areas', 'area_id', $where) !== FALSE) { // Oops, a record with that path already exists. Go flag error ++$dialogdef['area_path']['errors']; $params['{VALUE}'] = $areadata_directory; $dialogdef['area_path']['error_messages'][] = t('validate_not_unique', '', $params); $invalid = TRUE; } // 3D -- additional check: can we create said directory? $areadata_full_path = $CFG->datadir . '/areas/' . $areadata_directory; $areadata_directory_created = @mkdir($areadata_full_path, 0700); if ($areadata_directory_created) { @touch($areadata_full_path . '/index.html'); // "protect" the newly created directory from prying eyes } else { // Mmmm, failed; probably already exists then. Oh well. Go flag error. ++$dialogdef['area_path']['errors']; $params['{VALUE}'] = '/areas/' . $areadata_directory; $dialogdef['area_path']['error_messages'][] = t('validate_already_exists', '', $params); $invalid = TRUE; } // 3E -- if there were any errors go redo dialog while keeping data already entered if ($invalid) { if ($areadata_directory_created) { // Only get rid of the directory _we_ created @unlink($areadata_full_path . '/index.html'); @rmdir($areadata_full_path); } // there were errors, show them to the user and do it again foreach ($dialogdef as $k => $item) { if (isset($item['errors']) && $item['errors'] > 0) { $this->output->add_message($item['error_messages']); } } $this->output->add_content('<h2>' . t('areamanager_add_area_header', 'admin') . '</h2>'); $this->output->add_content(t('areamanager_add_area_explanation', 'admin')); $href = href($WAS_SCRIPT_NAME, $this->a_param(AREAMANAGER_CHORE_SAVE_NEW)); $this->output->add_content(dialog_quickform($href, $dialogdef)); return; } // 4 -- go save the new area $sort_order = $this->sort_order_new_area(); $now = strftime('%Y-%m-%d %T'); $theme_id = intval($dialogdef['area_theme_id']['value']); $area_title = $dialogdef['area_title']['value']; $fields = array('title' => $area_title, 'is_private' => $dialogdef['area_is_private']['value'] == 1 ? TRUE : FALSE, 'is_active' => TRUE, 'is_default' => FALSE, 'path' => $areadata_directory, 'metadata' => '', 'sort_order' => $sort_order, 'theme_id' => $theme_id, 'ctime' => $now, 'cuser_id' => $USER->user_id, 'mtime' => $now, 'muser_id' => $USER->user_id); // 4A -- store area data $success = TRUE; $new_area_id = db_insert_into_and_get_id('areas', $fields, 'area_id'); if ($new_area_id === FALSE) { if ($areadata_directory_created) { // Only get rid of the directory _we_ created @unlink($areadata_full_path . '/index.html'); @rmdir($areadata_full_path); } logger("areamanager: saving new area failed: " . db_errormessage()); $success = FALSE; } // 4B -- handle theme settings for this area if ($success) { if (!$this->reset_theme_defaults($new_area_id, $theme_id)) { logger("areamanager: saving new area-theme properties failed: " . db_errormessage()); $success = FALSE; } } // 5 -- tell user about results of the operation if ($success) { $params = array('{AREA}' => $new_area_id, '{AREA_FULL_NAME}' => $area_title); $this->output->add_message(t('areamanager_savenew_area_success', 'admin', $params)); logger(sprintf("areamanager: success saving new area '%d' %s with data directory /areas/%s", $new_area_id, $area_title, $areadata_directory)); } else { $this->output->add_message(t('areamanager_savenew_area_failure', 'admin')); } $this->area_overview(); }
/** create a new subdirectory * * This routine either shows a dialog where the user can specify the name of a new * directory to add OR processes the dialog. * * In case of directory name too short, already exists, etc. the user is * returned to the dialog to try again. If all goes well the new directory * is created and at the same time the empty file 'index.html' is created * to "protect" the directory from prying eyes. * * @return void output returned via $this->output */ function task_add_directory() { global $WAS_SCRIPT_NAME, $CFG; // 1A -- bail out if user pressed cancel button if (isset($_POST['button_cancel'])) { $this->output->add_message(t('cancelled', 'admin')); $this->task_list_directory(); return; } // 1B -- Check validity of working directory, maybe bail out $newdir = get_parameter_string(PARAM_PATH, $this->current_directory); if (($path = $this->valid_path($newdir)) === FALSE) { $this->output->add_message(t('invalid_path', 'admin', array('{PATH}' => htmlspecialchars($newdir)))); $this->task_list_directory(); return; } $this->current_directory = $path; // this is where we will create the new subdirectory // 2 -- prepare dialog (either to show it or to validate it) $dialogdef = array('subdirectory' => array('type' => F_ALPHANUMERIC, 'name' => 'subdirectory', 'minlength' => 1, 'maxlength' => 240, 'columns' => 30, 'label' => t('filemanager_add_subdirectory_label', 'admin'), 'title' => t('filemanager_add_subdirectory_title', 'admin'), 'value' => ''), 'button_save' => dialog_buttondef(BUTTON_SAVE), 'button_cancel' => dialog_buttondef(BUTTON_CANCEL)); $a_params = array('job' => $this->job, 'task' => TASK_ADD_DIRECTORY, PARAM_PATH => $path); $href = href($WAS_SCRIPT_NAME, $a_params); // 3 -- show dialog or validate + process? if (!isset($_POST['subdirectory'])) { $this->output->add_content('<h2>' . t('filemanager_add_subdirectory_header', 'admin') . '</h2>'); $this->output->add_content(t('filemanager_add_subdirectory_explanation', 'admin')); $this->output->add_content(dialog_quickform($href, $dialogdef)); $this->show_breadcrumbs($path); $this->show_menu($path); return; } // 4 -- validate user input and maybe create directory // 4A -- check for generic errors $invalid = FALSE; if (!dialog_validate($dialogdef)) { $invalid = TRUE; } // 4B -- check for additional errors: sane filename $subdirectory = $dialogdef['subdirectory']['value']; $sanitised_subdirectory = sanitise_filename($subdirectory); if ($subdirectory != $sanitised_subdirectory || substr($sanitised_subdirectory, 0, strlen(THUMBNAIL_PREFIX)) == THUMBNAIL_PREFIX) { ++$dialogdef['subdirectory']['errors']; $params = array('{FIELD}' => str_replace('~', '', $dialogdef['subdirectory']['label']), '{VALUE}' => htmlspecialchars($subdirectory)); $dialogdef['subdirectory']['error_messages'][] = t('validate_bad_filename', '', $params); $invalid = TRUE; } // 4C -- check for additional errors: directory should not exist already $subdirectory_full_path = $CFG->datadir . $path . '/' . $sanitised_subdirectory; if (file_exists($subdirectory_full_path)) { ++$dialogdef['subdirectory']['errors']; $params = array('{FIELD}' => str_replace('~', '', $dialogdef['subdirectory']['label']), '{VALUE}' => $this->vpath($path) . '/' . $sanitised_subdirectory); $dialogdef['subdirectory']['error_messages'][] = t('validate_already_exists', '', $params); $invalid = TRUE; } // 4D -- redo dialog if there were errors if ($invalid) { // shortcut: only the subdirectory field can (and does) yield errors $this->output->add_message($dialogdef['subdirectory']['error_messages']); $dialogdef['subdirectory']['value'] = $sanitised_subdirectory; $this->output->add_content('<h2>' . t('filemanager_add_subdirectory_header', 'admin') . '</h2>'); $this->output->add_content(t('filemanager_add_subdirectory_explanation', 'admin')); $this->output->add_content(dialog_quickform($href, $dialogdef)); $this->show_breadcrumbs($path); // note that we do NOT display the menu here; let the user concentrate (or press Cancel) this time return; } // 5 -- all set, go create subdir $params = array('{PATH}' => htmlspecialchars($this->vpath($path)), '{DIRECTORY}' => htmlspecialchars($sanitised_subdirectory)); if (@mkdir($subdirectory_full_path, 0700)) { @touch($subdirectory_full_path . '/index.html'); // "protect" the newly created directory from prying eyes $this->output->add_message(t('filemanager_add_subdirectory_success', 'admin', $params)); logger(sprintf('%s.%s(): success with mkdir %s', __CLASS__, __FUNCTION__, $path . '/' . $subdirectory), WLOG_DEBUG); } else { $this->output->add_message(t('filemanager_add_subdirectory_failure', 'admin', $params)); logger(sprintf('%s.%s(): cannot mkdir %s', __CLASS__, __FUNCTION__, $path . '/' . $subdirectory)); } $this->task_list_directory(); }
function make_serialize_filename($token_or_settings_filename) { return FUPS_DATADIR . sanitise_filename($token_or_settings_filename) . '.serialize.txt'; }
/** save a new group to the database * * this saves a new group to the database. This quite a complex task because of * the number of tables involved. * * First we have the table 'groups' which stores the basic group information. * Then there is the table 'groups_capacities'. For every combination of group * and capacity requested by the user a record must be added to this table. * Then there is also a separate acl for every group_capacity, so there. * * The strategy should be something like this. * new_group_id = insert_new_group_into_groups() * for all GROUPMANAGER_MAX_CAPACITIES do * if capacity != CAPACITY_NONE && capacity_not_added_yet() * prepare_new_acl_record(); * new_acl_id = insert_new_acl_in_acls(); * prepare_new_groups_capacities_record(); * insert_new_group_capacity_in_table() * * @todo maybe we should find a more elegant way to check a field for uniqueness * @todo should we delete the datadirectory if something goes wrong? * @return data saved to the database, output created via groups_overview() */ function group_savenew() { global $WAS_SCRIPT_NAME, $CFG; // // 1 -- bail out if the user pressed cancel button // if (isset($_POST['button_cancel'])) { $this->output->add_message(t('cancelled', 'admin')); $this->groups_overview(); return; } // // 2 -- validate the data // $invalid = FALSE; $dialogdef = $this->get_dialogdef_add_group(); // 2A -- check for generic errors (string too short, number too small, etc) if (!dialog_validate($dialogdef)) { $invalid = TRUE; } // 2B -- check out the groupname: this field should be unique $groupname = $dialogdef['group_name']['value']; $fname = isset($dialogdef['group_name']['label']) ? $dialogdef['group_name']['label'] : 'group_name'; $params = array('{FIELD}' => str_replace('~', '', $fname)); if (db_select_single_record('groups', 'group_id', array('groupname' => $groupname)) !== FALSE) { // Oops, a record with that groupname already exists. Go flag error ++$dialogdef['group_name']['errors']; $dialogdef['group_name']['error_messages'][] = t('validate_not_unique', '', $params); $invalid = TRUE; } // 2C -- additional check: unique groupdata subdirectory relative to {$CFG->datadir}/groups/ $groupdata_directory = strtolower(sanitise_filename($groupname)); $groupdata_full_path = $CFG->datadir . '/groups/' . $groupdata_directory; $groupdata_directory_created = @mkdir($groupdata_full_path, 0700); if ($groupdata_directory_created) { @touch($groupdata_full_path . '/index.html'); // "protect" the newly created directory from prying eyes } else { // Mmmm, failed; probably already exists then. Oh well. Go flag error. ++$dialogdef['group_name']['errors']; $params['{VALUE}'] = '/groups/' . $groupdata_directory; $dialogdef['group_name']['error_messages'][] = t('validate_already_exists', '', $params); $invalid = TRUE; } // 2D -- if there were any errors go redo dialog while keeping data already entered if ($invalid) { if ($groupdata_directory_created) { // Only get rid of the directory _we_ created @unlink($groupdata_full_path . '/index.html'); @rmdir($groupdata_full_path); } // show errors messages foreach ($dialogdef as $k => $item) { if (isset($item['errors']) && $item['errors'] > 0) { $this->output->add_message($item['error_messages']); } } $this->output->add_content('<h2>' . t('groupmanager_add_group_header', 'admin') . '</h2>'); $this->output->add_content(t('groupmanager_add_group_explanation', 'admin')); $href = href($WAS_SCRIPT_NAME, $this->a_params(TASK_GROUP_SAVE_NEW)); // $dialogdef = $this->get_dialogdef_add_group(); $this->output->add_content(dialog_quickform($href, $dialogdef)); return; } // // 3 -- store the data // // At this point we have a validated new group dialog in our hands // We now need to convert the data from the dialog to sensible // fields and store the data. // // 3A -- insert new group record and remember the new group_id $group_fullname = $dialogdef['group_fullname']['value']; $fields = array('groupname' => $groupname, 'full_name' => $group_fullname, 'is_active' => $dialogdef['group_is_active']['value'] == 1 ? TRUE : FALSE, 'path' => $groupdata_directory); if (($new_group_id = db_insert_into_and_get_id('groups', $fields, 'group_id')) === FALSE) { logger(sprintf("%s.%s(): saving new group '%s' failed: %s", __CLASS__, __FUNCTION__, $groupname, db_errormessage())); if ($groupdata_directory_created) { // Only get rid of the directory _we_ created @unlink($groupdata_full_path . '/index.html'); @rmdir($groupdata_full_path); } $this->output->add_message(t('groupmanager_savenew_group_failure', 'admin')); $this->groups_overview(); return; } // 3B -- create 0, 1 or more group/capacities $capacity_sort_order = 0; for ($i = 1; $i <= GROUPMANAGER_MAX_CAPACITIES; ++$i) { $k = 'group_capacity_' . $i; if (($capacity_code = intval($dialogdef[$k]['value'])) != CAPACITY_NONE) { if ($this->add_group_capacity($new_group_id, $capacity_code, ++$capacity_sort_order) === FALSE) { if ($groupdata_directory_created) { // Only get rid of the directory _we_ created @unlink($groupdata_full_path . '/index.html'); @rmdir($groupdata_full_path); } $this->output->add_message(t('groupmanager_savenew_group_failure', 'admin')); $this->groups_overview(); return; } } } // 4 -- tell user about success $params = array('{GROUP}' => $groupname, '{GROUP_FULL_NAME}' => $group_fullname); $this->output->add_message(t('groupmanager_savenew_group_success', 'admin', $params)); logger(sprintf("%s.%s(): success saving new group '%d' %s (%s) and datadir /groups/%s", __CLASS__, __FUNCTION__, $new_group_id, $groupname, $group_fullname, $groupdata_directory)); $this->groups_overview(); }
/** save a new user to the database * * this saves a new user to the database. This involves at least two tables: * a record in the users table with basic information and also a record with * access control in the acls table. * * @todo maybe we should find a more elegant way to check a field for uniqueness * @todo shouldn't we end with the edit-user dialog rather than the users overview? * that might make more sense... * @return data saved to the database, directory created, output created via users_overview() * @uses $CFG * @uses $WAS_SCRIPT_NAME */ function user_savenew() { global $WAS_SCRIPT_NAME, $CFG; // // 1 -- bail out if the user pressed cancel button // if (isset($_POST['button_cancel'])) { $this->output->add_message(t('cancelled', 'admin')); $this->users_overview(); return; } // // 2 -- validate the data // $invalid = FALSE; $dialogdef = $this->get_dialogdef_add_user(); // // 2A -- check for generic errors (string too short, number too small, etc) if (!dialog_validate($dialogdef)) { $invalid = TRUE; } // 2B -- additional check: unique username $fname = $this->get_fname($dialogdef['username']); $params = array('{FIELD}' => $fname); $username = $dialogdef['username']['value']; $record = db_select_single_record('users', 'user_id', array('username' => $username)); if ($record !== FALSE) { // Oops, a record with that username already exists. Go flag error ++$dialogdef['username']['errors']; $dialogdef['username']['error_messages'][] = t('validate_not_unique', '', $params); $invalid = TRUE; } // 2C -- additional check: unique userdata subdirectory relative to {$CFG->datadir}/users/ $userdata_directory = strtolower(sanitise_filename($username)); $userdata_full_path = $CFG->datadir . '/users/' . $userdata_directory; $userdata_directory_created = @mkdir($userdata_full_path, 0700); if ($userdata_directory_created) { @touch($userdata_full_path . '/index.html'); // "protect" the newly created directory from prying eyes } else { // Mmmm, failed; probably already exists then. Oh well. Go flag error. ++$dialogdef['username']['errors']; $params['{VALUE}'] = '/users/' . $userdata_directory; $dialogdef['username']['error_messages'][] = t('validate_already_exists', '', $params); $invalid = TRUE; } // 2D -- additional check: valid password $password1 = $dialogdef['user_password1']['value']; $password2 = $dialogdef['user_password2']['value']; if (!empty($password1) || !empty($password2)) { if ($password1 != $password2) { $params = array('{FIELD1}' => $this->get_fname($dialogdef['user_password1']), '{FIELD2}' => $this->get_fname($dialogdef['user_password2'])); ++$dialogdef['user_password1']['errors']; ++$dialogdef['user_password2']['errors']; $dialogdef['user_password1']['error_messages'][] = t('validate_different_passwords', '', $params); $dialogdef['user_password1']['value'] = ''; $dialogdef['user_password2']['value'] = ''; $invalid = TRUE; } elseif (!acceptable_new_password($password1, $password2)) { $params = array('{MIN_LENGTH}' => MINIMUM_PASSWORD_LENGTH, '{MIN_LOWER}' => MINIMUM_PASSWORD_LOWERCASE, '{MIN_UPPER}' => MINIMUM_PASSWORD_UPPERCASE, '{MIN_DIGIT}' => MINIMUM_PASSWORD_DIGITS, '{FIELD}' => $this->get_fname($dialogdef['user_password1'])); ++$dialogdef['user_password1']['errors']; $dialogdef['user_password1']['error_messages'][] = t('validate_bad_password', '', $params); ++$dialogdef['user_password2']['errors']; $dialogdef['user_password1']['value'] = ''; $dialogdef['user_password2']['value'] = ''; $invalid = TRUE; } } // 2E -- if there were any errors go redo dialog while keeping data already entered if ($invalid) { if ($userdata_directory_created) { // Get rid of the directory _we_ created @unlink($userdata_full_path . '/index.html'); @rmdir($userdata_full_path); } // show errors messages foreach ($dialogdef as $k => $item) { if (isset($item['errors']) && $item['errors'] > 0) { $this->output->add_message($item['error_messages']); } } $this->output->add_content('<h2>' . t('usermanager_add_user_header', 'admin') . '</h2>'); $this->output->add_content(t('usermanager_add_user_explanation', 'admin')); $href = href($WAS_SCRIPT_NAME, $this->a_params(TASK_USER_SAVE_NEW)); $this->output->add_content(dialog_quickform($href, $dialogdef)); return; } // // 3 -- store the data // // At this point we have a validated new user dialog in our hands // We now need to convert the data from the dialog to sensible // values for the database fields and store the data. // Note that the userdata directory already exists at this point $fields_acl = array('permissions_intranet' => ACL_ROLE_NONE, 'permissions_modules' => ACL_ROLE_NONE, 'permissions_jobs' => ACL_ROLE_NONE, 'permissions_nodes' => ACL_ROLE_NONE); // // 3A -- create an acl (with no permissions whatsoever) and remember the new acl_id // $errors = 0; $new_acl_id = db_insert_into_and_get_id('acls', $fields_acl, 'acl_id'); if ($new_acl_id === FALSE) { logger(sprintf("user_savenew(): adding new acl for new user failed: %s", db_errormessage())); ++$errors; } else { // // 3B -- subsequently add a new user and remember the new user_id // $new_username = $dialogdef['username']['value']; $new_user_fullname = $dialogdef['user_fullname']['value']; $new_salt = password_salt(); $fields = array('username' => $new_username, 'salt' => $new_salt, 'password_hash' => password_hash($new_salt, $dialogdef['user_password1']['value']), 'bypass_mode' => FALSE, 'bypass_hash' => NULL, 'bypass_expiry' => NULL, 'full_name' => $new_user_fullname, 'email' => $dialogdef['user_email']['value'], 'is_active' => $dialogdef['user_is_active']['value'] == 1 ? TRUE : FALSE, 'redirect' => '', 'language_key' => $CFG->language_key, 'path' => $userdata_directory, 'acl_id' => $new_acl_id, 'editor' => $CFG->editor, 'skin' => 'base'); $new_user_id = db_insert_into_and_get_id('users', $fields, 'user_id'); if ($new_user_id === FALSE) { logger(sprintf("usermanager: saving new user %s (%s) failed: %s" . $new_username, $new_user_fullname, db_errormessage())); ++$errors; } } if ($errors > 0) { if ($userdata_directory_created) { // Get rid of the directory _we_ created @unlink($userdata_full_path . '/index.html'); @rmdir($userdata_full_path); } $this->output->add_message(t('usermanager_savenew_user_failure', 'admin')); } else { $params = array('{USERNAME}' => $new_username, '{FULL_NAME}' => $new_user_fullname); $this->output->add_message(t('usermanager_savenew_user_success', 'admin', $params)); logger(sprintf("usermanager: success saving new user '%d' %s (%s) and datadir /users/%s", $new_user_id, $new_username, $new_user_fullname, $userdata_directory)); } $this->users_overview(); }
/** save the newly added language to the database * * This saves the essential information of a new language to the database, * using sensible defaults for the other fields. Also, a data directory * is created in $CFG->datadir * * If something goes wrong, the user can redo the dialog, otherwise we * return to the languages overview, with the newly added language in the * list, too. * * Apart from the standard checks the following checks are done: * - the language key should be an acceptable directory name * - the language key should be lowercase * - the language key should not exist already (in $this->languages) * - the directory should not yet exist * - the directory must be created here and now * * @return void results are returned as output in $this->output * @uses $WAS_SCRIPT_NAME * @uses $CFG * @uses $USER * @uses $LANGUAGE */ function language_savenew() { global $WAS_SCRIPT_NAME, $USER, $CFG, $LANGUAGE; // 1 -- bail out if user pressed cancel button if (isset($_POST['button_cancel'])) { $this->output->add_message(t('cancelled', 'admin')); $this->languages_overview(); return; } // 2 -- validate the data; check for generic errors (string too short, number too small, etc) $dialogdef = $this->get_dialogdef_language(); $invalid = dialog_validate($dialogdef) ? FALSE : TRUE; // 3 -- additional validation & massaging of the language key $fname = isset($dialogdef['language_key']['label']) ? $dialogdef['language_key']['label'] : 'language_key'; $params = array('{FIELD}' => str_replace('~', '', $fname)); // 3A -- additional check: the language key doubles as a directory name AND should be lowercase $path = $dialogdef['language_key']['value']; $languagedata_directory = strtolower(sanitise_filename($path)); if ($path != $languagedata_directory) { // User probably entered a few 'illegal' characters. This is no good $dialogdef['language_key']['value'] = $languagedata_directory; // 'Help' user with a better proposition? ++$dialogdef['language_key']['errors']; $params['{VALUE}'] = htmlspecialchars($path); $dialogdef['language_key']['error_messages'][] = t('validate_bad_filename', '', $params); $invalid = TRUE; } // 3B -- additional check: unique language key name entered if (isset($this->languages[$languagedata_directory])) { // Oops, already exists ++$dialogdef['language_key']['errors']; $params['{VALUE}'] = $languagedata_directory; $dialogdef['language_key']['error_messages'][] = t('validate_not_unique', '', $params); $invalid = TRUE; } // 3C -- additional check: can we create said directory? $languagedata_full_path = $CFG->datadir . '/languages/' . $languagedata_directory; $languagedata_directory_created = @mkdir($languagedata_full_path, 0700); if ($languagedata_directory_created) { @touch($languagedata_full_path . '/index.html'); // "protect" the newly created directory from prying eyes } else { // Mmmm, failed; probably already exists then. Oh well. Go flag error. ++$dialogdef['language_key']['errors']; $params['{VALUE}'] = '/languages/' . $languagedata_directory; $dialogdef['language_key']['error_messages'][] = t('validate_already_exists', '', $params); $invalid = TRUE; } // 3E -- if there were any errors go redo dialog while keeping data already entered if ($invalid) { if ($languagedata_directory_created) { // Only get rid of the directory _we_ created @unlink($languagedata_full_path . '/index.html'); @rmdir($languagedata_full_path); } // there were errors, show them to the user and do it again foreach ($dialogdef as $k => $item) { if (isset($item['errors']) && $item['errors'] > 0) { $this->output->add_message($item['error_messages']); } } $this->output->add_content('<h2>' . t('translatetool_add_language_header', 'admin') . '</h2>'); $this->output->add_content(t('translatetool_add_language_explanation', 'admin')); $href = href($WAS_SCRIPT_NAME, $this->a_param(TRANSLATETOOL_CHORE_LANGUAGE_SAVE_NEW)); $this->output->add_content(dialog_quickform($href, $dialogdef)); return; } // 4 -- go save the new language $language_key = $dialogdef['language_key']['value']; $language_name = $dialogdef['language_name']['value']; $parent_key = $dialogdef['parent_language_key']['value'] == '--' ? NULL : $dialogdef['parent_language_key']['value']; $is_active = $dialogdef['language_is_active']['value'] == '1' ? TRUE : FALSE; $fields = array('language_key' => $language_key, 'parent_language_key' => $parent_key, 'language_name' => $language_name, 'version' => 0, 'manifest' => '', 'is_core' => FALSE, 'is_active' => $is_active, 'dialect_in_database' => FALSE, 'dialect_in_file' => FALSE); if (db_insert_into('languages', $fields) === FALSE) { if ($languagedata_directory_created) { // Only get rid of the file/directory _we_ created @unlink($languagedata_full_path . '/index.html'); @rmdir($languagedata_full_path); } logger(sprintf('%s.%s(): saving new language \'%s\' failed: %s', __CLASS__, __FUNCTION__, htmlspecialchars($language_key), db_errormessage())); $this->output->add_message(t('translatetool_language_savenew_failure', 'admin')); } else { $params = array('{LANGUAGE_KEY}' => $language_key, '{LANGUAGE_NAME}' => $language_name); $this->output->add_message(t('translatetool_language_savenew_success', 'admin', $params)); logger(sprintf("%s.%s(): success saving new language '%s' (%s) with data directory /languages/%s", __CLASS__, __FUNCTION__, $language_name, $language_key, $languagedata_directory)); $this->languages = $LANGUAGE->retrieve_languages(TRUE); // TRUE means force reread from database after add } $this->languages_overview(); }