コード例 #1
0
/** validate and check values that were submitted via a user dialog
 *
 * this steps through the definition of a dialog and retrieves the values submitted by
 * the user via $_POST[]. The values are checked against the constraints (e.g. minimum string length,
 * date range, etc.). If the submitted value is considered valid, it is stored in the corresponding
 * value of the dialogdef element, maybe properly reformatted (in case of dates/times/datetimes).
 * If there were errors, these are recorded in the dialog definition element, in the form of one or
 * more readable error messages. Also the error count (per element) is incremented. This makes it
 * easy to
 *  - inform the user about what was wrong with the input data
 *  - determine whether there was an error at all (if $dialogdef[$k]['errors'] > 0).
 *
 * Note that this routine has the side effect of filling the dialog array with the data that
 * was submitted by the user via $_POST. If the validation is successful, the data is ready
 * to be saved into the database. If it is not, the data entered is still available in the
 * dialogdef which makes it easy to return to the user and let the user correct the errors without
 * losing all the data input because of a silly mistake in some input field.
 *
 * Update 2009-03-17: We no longer validate the view-only fields because these fields are not POST'ed 
 * by the browser and hence cannot be validated. This also means that there is no value set from $_POST
 * for those fields.
 *
 * Update 2011-09-29: added UTF-8 validation, replace with U+FFFD (Unicode replacement character) on fail
 *
 * @param array &$dialogdef the complete dialog definition; contains detailed errors and/or reformatted values
 * @return bool TRUE if all submitted values are considered valid, FALSE otherwise
 * @todo add an error message to
 */
function dialog_validate(&$dialogdef)
{
    $total_errors = 0;
    foreach ($dialogdef as $k => $item) {
        if (isset($item['name'])) {
            if (isset($item['viewonly']) && $item['viewonly']) {
                continue;
            }
            $name = $item['name'];
            $fname = isset($item['label']) ? str_replace('~', '', $item['label']) : $name;
            $dialogdef[$k]['errors'] = 0;
            $dialogdef[$k]['error_messages'] = array();
            $f_type = isset($item['type']) ? $item['type'] : '';
            $value = isset($item['value']) ? $item['value'] : '';
            if (isset($_POST[$name])) {
                if (utf8_validate($_POST[$name])) {
                    $posted_value = magic_unquote($_POST[$name]);
                } else {
                    $posted_value = "�";
                    // UTF-8 encoded substitution character U+FFFD
                    ++$dialogdef[$k]['errors'];
                    $dialogdef[$k]['error_messages'][] = t('validate_invalid', '', array('{FIELD}' => $fname));
                }
            } else {
                $posted_value = '';
                // should be NULL but empty string is more convenient here
            }
            switch ($f_type) {
                case F_DATE:
                case F_TIME:
                case F_DATETIME:
                case F_ALPHANUMERIC:
                case F_INTEGER:
                case F_REAL:
                case F_PASSWORD:
                case F_RICHTEXT:
                    if ($f_type == F_DATE || $f_type == F_TIME || $f_type == F_DATETIME) {
                        $datetime_value = '';
                        $is_valid_datetime = valid_datetime($f_type, $posted_value, $datetime_value);
                        if (!$is_valid_datetime) {
                            ++$total_errors;
                            ++$dialogdef[$k]['errors'];
                            $dialogdef[$k]['error_messages'][] = t('validate_invalid_datetime', '', array('{FIELD}' => $fname));
                        }
                        // else we have a valid date/time, and a properly reformatted copy for comparisons too
                    }
                    if (isset($item['minlength'])) {
                        $minlength = intval($item['minlength']);
                        if (strlen($posted_value) < $minlength) {
                            ++$total_errors;
                            ++$dialogdef[$k]['errors'];
                            $dialogdef[$k]['error_messages'][] = t('validate_too_short', '', array('{FIELD}' => $fname, '{MIN}' => strval($minlength)));
                        }
                    }
                    if (isset($item['maxlength'])) {
                        $maxlength = intval($item['maxlength']);
                        if ($maxlength < strlen($posted_value)) {
                            ++$total_errors;
                            ++$dialogdef[$k]['errors'];
                            $dialogdef[$k]['error_messages'][] = t('validate_too_long', '', array('{FIELD}' => $fname, '{MAX}' => strval($maxlength)));
                        }
                    }
                    if (isset($item['minvalue'])) {
                        switch ($f_type) {
                            case F_INTEGER:
                                if (intval($posted_value) < intval($item['minvalue'])) {
                                    ++$total_errors;
                                    ++$dialogdef[$k]['errors'];
                                    $dialogdef[$k]['error_messages'][] = t('validate_too_small', '', array('{FIELD}' => $fname, '{MIN}' => $item['minvalue']));
                                }
                                break;
                            case F_REAL:
                                if (floatval($posted_value) < floatval($item['minvalue'])) {
                                    ++$total_errors;
                                    ++$dialogdef[$k]['errors'];
                                    $dialogdef[$k]['error_messages'][] = t('validate_too_small', '', array('{FIELD}' => $fname, '{MIN}' => $item['minvalue']));
                                }
                                break;
                            case F_DATE:
                            case F_TIME:
                            case F_DATETIME:
                                if ($is_valid_datetime) {
                                    // there's no point in checking a value if the value itself is invalid
                                    if ($datetime_value < $item['minvalue']) {
                                        ++$total_errors;
                                        ++$dialogdef[$k]['errors'];
                                        $dialogdef[$k]['error_messages'][] = t('validate_too_small', '', array('{FIELD}' => $fname, '{MIN}' => $item['minvalue']));
                                    }
                                }
                                break;
                        }
                    }
                    if (isset($item['maxvalue'])) {
                        switch ($f_type) {
                            case F_INTEGER:
                                if (intval($item['maxvalue']) < intval($posted_value)) {
                                    ++$total_errors;
                                    ++$dialogdef[$k]['errors'];
                                    $dialogdef[$k]['error_messages'][] = t('validate_too_large', '', array('{FIELD}' => $fname, '{MAX}' => $item['maxvalue']));
                                }
                                break;
                            case F_REAL:
                                if (floatval($item['maxvalue']) < floatval($posted_value)) {
                                    ++$total_errors;
                                    ++$dialogdef[$k]['errors'];
                                    $dialogdef[$k]['error_messages'][] = t('validate_too_large', '', array('{FIELD}' => $fname, '{MAX}' => $item['maxvalue']));
                                }
                                break;
                            case F_DATE:
                            case F_TIME:
                            case F_DATETIME:
                                if ($is_valid_datetime) {
                                    // there's no point in checking a value if the value itself is invalid
                                    if ($item['maxvalue'] < $datetime_value) {
                                        ++$total_errors;
                                        ++$dialogdef[$k]['errors'];
                                        $dialogdef[$k]['error_messages'][] = t('validate_too_large', '', array('{FIELD}' => $fname, '{MAX}' => $item['maxvalue']));
                                    }
                                }
                                break;
                        }
                    }
                    // finally format the data
                    switch ($f_type) {
                        case F_INTEGER:
                            $dialogdef[$k]['value'] = strval(intval($posted_value));
                            break;
                        case F_REAL:
                            $decimals = isset($item['decimals']) ? abs(intval($item['decimals'])) : 2;
                            $dialogdef[$k]['value'] = sprintf("%1." . $decimals . "f", floatval($posted_value));
                            break;
                        case F_DATE:
                        case F_TIME:
                        case F_DATETIME:
                            $dialogdef[$k]['value'] = $is_valid_datetime ? $datetime_value : $posted_value;
                            break;
                        default:
                            $dialogdef[$k]['value'] = $posted_value;
                            break;
                    }
                    break;
                case F_CHECKBOX:
                    // there are two options:
                    // either $posted_value equals the value in the options list
                    // OR it does't. (well duh). However, it it doesn't match AND
                    // it is not an empty string (see above, should be NULL), it
                    // is an error nonetheless. OK. Here we go.
                    if (!empty($posted_value)) {
                        if (!isset($item['options'][$posted_value])) {
                            // oops, something rottenin the state of Denmark...
                            ++$total_errors;
                            ++$dialogdef[$k]['errors'];
                            $dialogdef[$k]['error_messages'][] = t('validate_invalid', '', array('{FIELD}' => $fname));
                            $dialogdef[$k]['value'] = '';
                        } else {
                            $dialogdef[$k]['value'] = $posted_value;
                        }
                    } else {
                        $dialogdef[$k]['value'] = '';
                    }
                    break;
                case F_RADIO:
                case F_LISTBOX:
                    // the value should exist in the options array
                    if (!isset($item['options'][$posted_value])) {
                        // oops, something rotten in the state of Denmark...
                        ++$total_errors;
                        ++$dialogdef[$k]['errors'];
                        $dialogdef[$k]['error_messages'][] = t('validate_invalid', '', array('{FIELD}' => $fname));
                        $dialogdef[$k]['value'] = '';
                    } else {
                        $dialogdef[$k]['value'] = $posted_value;
                    }
                    break;
                case F_FILE:
                    // any value is OK, because
                    // 1. checking is done separately in the filemanager (including virusscan etc.)
                    // 2. if there is an error in 1 file, the other uploaded files could be perfectly
                    //    OK. Sending the user back to the upload dialog would be counter-productive
                    //    because the 'good' files would have to be uploaded again and she would have
                    //    to type in/browse the files again (and again and again...)
                    break;
                case F_SUBMIT:
                    // any value is OK, no check needed
                    break;
                default:
                    ++$total_errors;
                    $dialogdef[$k]['errors'] = 1;
                    $dialogdef[$k]['error_messages'] = $item['name'] . ' - INTERNAL ERROR: unknown type';
                    break;
            }
        }
    }
    return $total_errors == 0;
}
コード例 #2
0
/** main program for visitors
 *
 * this routine is called from /index.php. It is the main program for visitors.
 *
 * @return void page sent to the browser
 * @todo cleanup login/logout-code
 */
function main_index()
{
    global $USER;
    global $CFG;
    global $LANGUAGE;
    /** initialise the program, setup database, read configuration, etc. */
    require_once $CFG->progdir . '/init.php';
    initialise();
    was_version_check();
    // this never returns if versions don't match
    // TODO: cleanup like in main_admin()
    // handle login/logout/continuation so we quickly find out which user is calling
    if (isset($_GET['logout'])) {
        /** loginlib.php contains both login- and logout-routines */
        require_once $CFG->progdir . '/lib/loginlib.php';
        was_logout();
        // may or may not return here
    } elseif (isset($_GET['login'])) {
        /** loginlib.php contains both login- and logout-routines */
        require_once $CFG->progdir . '/lib/loginlib.php';
        was_login(magic_unquote($_GET['login']));
        // may or may not return here
    } elseif (isset($_COOKIE[$CFG->session_name])) {
        /** dbsessionlib.php contains our own database based session handler */
        require_once $CFG->progdir . '/lib/dbsessionlib.php';
        dbsession_setup($CFG->session_name);
        if (dbsession_exists(magic_unquote($_COOKIE[$CFG->session_name]))) {
            session_start();
        }
    }
    // At this point we either have a valid session with a logged-in user
    // (indicated via existence of $_SESSION) or we are dealing with an anonymous
    // visitor with non-existing $_SESSION. Keep track of the number of calls
    // this user makes (may be logged lateron on logout).
    if (isset($_SESSION)) {
        if (!isset($_SESSION['session_counter'])) {
            // first time after login, record start time of session
            $_SESSION['session_counter'] = 1;
            $_SESSION['session_start'] = strftime("%Y-%m-%d %T");
        } else {
            $_SESSION['session_counter']++;
        }
    }
    // Now is the time to create a USER object, even when the visitor is just a passerby
    // because we can then determine easily if a visitor is allowed certain things, e.g.
    // view a protected area or something
    /** useraccount.class.php is used to define the USER object */
    require_once $CFG->progdir . '/lib/useraccount.class.php';
    if (isset($_SESSION) && isset($_SESSION['user_id'])) {
        $USER = new Useraccount($_SESSION['user_id']);
        $USER->is_logged_in = TRUE;
        $_SESSION['language_key'] = $LANGUAGE->get_current_language();
        // remember language set via _GET or otherwise
    } else {
        $USER = new Useraccount();
        $USER->is_logged_in = FALSE;
    }
    // Check for the special preview-mode
    // This allows a webmaster to preview a page in the correct environment (theme)
    // even when the page is under embargo. Note that the node_id and area_id are
    // retrieved from the session; the user only has a cryptic preview-code.
    // See pagemanagerlib.php for more information (function task_page_preview()).
    $in_preview_mode = FALSE;
    if ($USER->is_logged_in) {
        $preview_code_from_url = get_parameter_string('preview');
        if (!is_null($preview_code_from_url) && isset($_SESSION['preview_salt']) && isset($_SESSION['preview_node'])) {
            $hash = md5($_SESSION['preview_salt'] . $_SESSION['preview_node']);
            if ($hash === $preview_code_from_url) {
                $node_id = intval($_SESSION['preview_node']);
                $area_id = intval($_SESSION['preview_area']);
                $area = db_select_single_record('areas', '*', array('area_id' => $area_id));
                if ($area === FALSE) {
                    logger("Fatal error 070: cannot preview node '{$node_id}' in area '{$area_id}'");
                    error_exit('070');
                } else {
                    $tree = tree_build($area_id);
                    $in_preview_mode = TRUE;
                }
            }
        }
    }
    if ($in_preview_mode == FALSE) {
        $requested_area = get_requested_area();
        $requested_node = get_requested_node();
        $req_area_str = is_null($requested_area) ? "NULL" : strval($requested_area);
        $req_node_str = is_null($requested_node) ? "NULL" : strval($requested_node);
        if (($area = calculate_area($requested_area, $requested_node)) === FALSE) {
            logger("Fatal error 080: no valid area (request: area='{$req_area_str}', node='{$req_node_str}')");
            error_exit('080');
            // no such area
        }
        $area_id = intval($area['area_id']);
        // If $USER has no permission to view area $area_id, we simply bail out.
        // Rationale: if the user is genuine, she knows about logging in first.
        // If the user is NOT logged in and tries to view a protected area, I'd consider
        // it malicious, and in that case I won't even confirm the existence of
        // the requested area. (If a cracker simply tries areas 0,1,.. and sometimes is greeted
        // with 'please enter credentials' and sometimes with 'area does not exist', this
        // provides information to the cracker. I don't want that). Note that the error code
        // is the same as the one for non-existing area. In other words: for an unauthorised
        // visitor an existing private area is just as non-existent as a non-existing public area.
        if (db_bool_is(TRUE, $area['is_private']) && !$USER->has_intranet_permissions(ACL_ROLE_INTRANET_ACCESS, $area_id)) {
            logger(sprintf("Fatal error 080: no view permissions for area '%d' (request: area='%s', node='%s')", $area_id, $req_area_str, $req_node_str));
            error_exit('080');
            // no such area
        }
        // still here?
        // then we've got a valid $area_id and corresponding $area record.
        // now we need to figure out which $node_id to use
        $tree = tree_build($area_id);
        if (($node_id = calculate_node_id($tree, $area_id, $requested_node)) === FALSE) {
            logger(sprintf("Fatal error 080: no valid node within area '%d' (request: area='%s', node='%s')", $area_id, $req_area_str, $req_node_str));
            error_exit('080');
            // no such area
        }
    }
    // At this point we have the following in our hands
    // - a valid $area_id
    // - a valid $node_id
    // - the complete tree from area $area_id in $tree
    // - the area record from database in $area
    // - the node record from database in $tree[$node_id]['record']
    // - a flag that signals preview mode in $in_preview_mode
    // We are on our way to generate a full page with content and all,
    // but otoh we MIGHT be in the middle of a redirect, so we may have to
    // leave without showing anything at all...
    if (!empty($tree[$node_id]['record']['link_href'])) {
        update_statistics($node_id);
        if (isset($_SESSION)) {
            session_write_close();
        }
        redirect_and_exit(htmlspecialchars($tree[$node_id]['record']['link_href']));
        // exit; redirect_and_exit() never returns
    }
    /** themelib contains the theme factory */
    require_once $CFG->progdir . '/lib/themelib.php';
    // And now we know about the $area, we can carry on determining which $theme to use.
    //
    $theme = theme_factory($area['theme_id'], $area_id, $node_id);
    if ($theme === FALSE) {
        logger("Fatal error 090: cannot setup theme '{$area['theme_id']}' in area '{$area_id}'");
        error_exit('090');
    }
    // Tell the theme about the preview mode
    $theme->set_preview_mode($in_preview_mode);
    // Now all we need to do is let the module connected to node $node_id generate output
    $module_id = $tree[$node_id]['record']['module_id'];
    module_view($theme, $area_id, $node_id, $module_id);
    // Remember this visitor
    update_statistics($node_id);
    // Finally, send output to user
    $theme->send_output();
    if (isset($_SESSION)) {
        session_write_close();
    }
    // done!
    exit;
}
コード例 #3
0
/** display the content of the mailpage linked to node $node_id
 *
 * @param object &$theme collects the (html) output
 * @param int $area_id identifies the area where $node_id lives
 * @param int $node_id the node to which this module is connected
 * @param array $module the module record straight from the database
 * @return bool TRUE on success + output via $theme, FALSE otherwise
 */
function mailpage_view(&$theme, $area_id, $node_id, $module)
{
    //
    // 0 -- basic sanity checks
    //
    if (($config = mailpage_view_get_config($node_id)) === FALSE) {
        $theme->add_message(t('error_retrieving_config', 'm_mailpage'));
        return FALSE;
    } elseif (sizeof($config['addresses']) <= 0) {
        logger(sprintf('%s(): no addresses at node %d: is mailpage unconfigured?', __FUNCTION__, $node_id));
        $msg = t('error_retrieving_addresses', 'm_mailpage', array('{NODE}' => strval($node_id)));
        $theme->add_message($msg);
        $theme->add_content($msg);
        return FALSE;
    }
    //
    // 1 -- do we have a token already?
    //
    $t0 = $t1 = 0;
    $ip_addr = '';
    $data = FALSE;
    $token_id = FALSE;
    if (isset($_POST['token'])) {
        // lookup valid UTF8 key (or fail with substitute U+FFFD instead)
        $token_key = utf8_validate($_POST['token']) ? magic_unquote($_POST['token']) : "�";
        $token_id = token_lookup(MAILPAGE_REFERENCE, $token_key, $t0, $t1, $ip_addr, $data);
    }
    //
    // 2 -- handle cases of expired tokens and Cancel first
    //
    $now = time();
    if ($token_id !== FALSE && isset($_POST['button_cancel'])) {
        // visitor pressed [Cancel]
        $theme->add_message(t('cancelled', 'admin'));
        token_destroy($token_id);
        $token_id = FALSE;
    }
    if ($token_id !== FALSE && $t1 < $now) {
        // token expired
        $theme->add_message(t('error_token_expired', 'm_mailpage'));
        token_destroy($token_id);
        $token_id = FALSE;
    }
    //
    // 3 -- handle the three remaining buttons from the two dialogs
    //
    if ($token_id !== FALSE) {
        if (isset($_POST['button_preview'])) {
            //
            // 3A -- Preview button
            //
            $dialogdef = mailpage_view_get_dialogdef($config, $token_key);
            if (!mailpage_view_dialog_validate($dialogdef)) {
                foreach ($dialogdef as $k => $item) {
                    if (isset($item['errors']) && $item['errors'] > 0) {
                        $theme->add_message($item['error_messages']);
                    }
                }
                mailpage_show_form($theme, $config, $dialogdef);
            } else {
                if (!token_store($token_id, $dialogdef)) {
                    $theme->add_message(t('error_storing_data', 'm_mailpage'));
                    logger(sprintf('%s(): token store error in page %d: %s', __FUNCTION__, $node_id, db_errormessage()));
                    return FALSE;
                }
                mailpage_show_preview($theme, $config, $dialogdef, $ip_addr);
            }
        } elseif (isset($_POST['button_edit'])) {
            //
            // 3B -- Edit button
            //
            if ($data === FALSE) {
                $theme->add_message(t('error_retrieving_data', 'm_mailpage'));
                logger(sprintf('%s(): no data after token_lookup()? (page=%d)', __FUNCTION__, $node_id));
                $data = mailpage_view_get_dialogdef($config, $token_key);
            }
            mailpage_show_form($theme, $config, $data);
        } elseif (isset($_POST['button_send'])) {
            //
            // 3C -- Send button
            //
            if ($data === FALSE) {
                $theme->add_message(t('error_retrieving_data', 'm_mailpage'));
                logger(sprintf('%s(): no data after token_lookup()? (page=%d)', __FUNCTION__, $node_id));
                $data = mailpage_view_get_dialogdef($config, $token_key);
            }
            if ($now < $t0) {
                // the window of opportunity is still closed; go back to form a la Edit
                $msg = t('error_too_fast', 'm_mailpage');
                $theme->add_message($msg);
                $theme->add_popup_top($msg);
                mailpage_show_form($theme, $config, $data);
                logger(sprintf('%s(): reply too fast (%ds) from %s', __FUNCTION__, $t0 - $now, $ip_addr));
            } elseif (!mailpage_send_message($config, $data, $ip_addr, $now - $t0)) {
                $theme->add_message(t('error_sending_message'));
                mailpage_show_form($theme, $config, $data);
            } else {
                token_destroy($token_id);
                mailpage_show_thankyou($theme, $config, $data, $ip_addr);
            }
        } else {
            //
            // 3D -- catch all: initiate a new round (shouldn't happen)
            //
            token_destroy($token_id);
            $token_id = FALSE;
        }
    }
    //
    // 4 -- Start with a clean slate
    //
    if ($token_id === FALSE) {
        $token_key = '';
        if (($token_id = token_create(MAILPAGE_REFERENCE, $token_key, 20)) === FALSE) {
            // 20s delay
            $msg = t('error_creating_token', 'm_mailpage', array('{NODE}' => strval($node_id)));
            $theme->add_message($msg);
            $theme->add_content($msg);
            return FALSE;
        }
        $dialogdef = mailpage_view_get_dialogdef($config, $token_key);
        mailpage_show_form($theme, $config, $dialogdef);
    }
    return TRUE;
}
コード例 #4
0
    $manuals = get_available_manuals(dirname(__FILE__) . '/manuals');
    if (sizeof($manuals) == 1) {
        list($language, $manual) = each($manuals);
    } else {
        if (sizeof($manuals) <= 0) {
            show_screen_download();
        } else {
            show_screen_choose_language($manuals);
        }
        exit;
    }
} else {
    $language = magic_unquote($_GET['language']);
}
$topic = isset($_GET['topic']) ? magic_unquote($_GET['topic']) : 'toc';
$subtopic = isset($_GET['subtopic']) ? magic_unquote($_GET['subtopic']) : '';
show_manual($language, $topic, $subtopic);
exit;
// ==================================================================
// =========================== WORKHORSES ===========================
// ==================================================================
/** redirect the user to a specific place in the manual OR show helpful message about downloading the manual
 *
 * There is a Website@School Users' Guide available, in English. This is
 * a separate download from the project's website. That means that it is
 * optional to have the (English) manual installed. If it is installed,
 * it is installed under /program/manuals/en/. There might also be translations
 * available, say the Dutch version of the manual. That one would be
 * installed in /program/manuals/nl/ which allows for peaceful co-existence of
 * multiple translations of the manual. This script manual.php is designed to:
 *
コード例 #5
0
 /** show confirmation dialog for multiple file delete OR perform actual file delete
  *
  * this routine either shows a list of files to be deleted, asking the user for confirmation
  * or actually deletes the specified files if the user did confirm the delete.
  * We bail out if the user pressed the cancel button in the confirmation dialog.
  * The real work is done in workhorse routines in order to combine the single-file-delete
  * and the batch-delete into a single confirmation routine. For actual deletion, however,
  * we always return here and not in the single file delete (see {$link task_remove_file()}).
  *
  * @uses show_dialog_confirm_delete_files()
  * @return void output sent to browser via $this->output and perhaps files deleted
  */
 function task_remove_multiple_files()
 {
     // 0 -- essential sanity check alias change directory
     $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->sort = get_parameter_int(PARAM_SORT, SORTBY_FILE_ASC);
     // 1 -- do they want to bail out?
     if (isset($_POST['button_cancel'])) {
         $this->output->add_message(t('cancelled', 'admin'));
         $this->task_list_directory();
         return;
     }
     // 2 -- construct a list of files to delete
     $entries = $this->get_entries($path);
     $n = isset($_POST[PARAM_FILENAMES]) ? intval($_POST[PARAM_FILENAMES]) : 0;
     $entries_to_delete = array();
     for ($i = 0; $i < $n; ++$i) {
         $fieldname = sprintf('%s%d', PARAM_FILENAME, $i);
         if (isset($_POST[$fieldname])) {
             $filename = magic_unquote($_POST[$fieldname]);
             if (isset($entries[$filename]) && $entries[$filename]['is_file']) {
                 $entries_to_delete[$filename] = $entries[$filename];
             } else {
                 logger(sprintf('%s.%s(): weird attempt to delete %s/%s', __CLASS__, __FUNCTION__, $path, $filename));
             }
         }
     }
     // 3 -- what needs to be done?
     $n = count($entries_to_delete);
     // 3A -- nothing to do
     if ($n <= 0) {
         $this->output->add_message(t('filemanager_nothing_to_delete', 'admin'));
         $this->task_list_directory();
         return;
     }
     if ($n == 1) {
         $entry = reset($entries_to_delete);
         $params = array('{FILENAME}' => $entry['vpath']);
     } else {
         $params = array('{COUNT}' => strval($n));
     }
     // 3B -- confirmation dialog or actual deletion?
     if (isset($_POST['confirm']) && intval($_POST['confirm']) != 0) {
         if ($this->delete_files($path, $entries_to_delete) === FALSE) {
             $this->output->add_message(t($n == 1 ? 'filemanager_failure_delete_file' : 'filemanager_failure_delete_files', 'admin', $params));
         } else {
             $this->output->add_message(t($n == 1 ? 'filemanager_success_delete_file' : 'filemanager_success_delete_files', 'admin', $params));
         }
         $this->task_list_directory();
     } else {
         $this->show_dialog_confirm_delete_files($path, $entries_to_delete);
     }
 }
コード例 #6
0
 /** determine the default language to use for translation of phrases
  *
  * This routine determines which language to use for prompts
  * and messages if not specified explicitly in calls to $this->get_phrase().
  * There are various ways in which a language can
  * be determined. Here's the list, in order of significance:
  *
  *  - $_GET['language']
  *  - $_SESSION['language_key']
  *  - $USER->language_key
  *  - $CFG->language_key
  *  - constant value 'en' (the native language)
  *
  * Note that all languages are validated agains the list of
  * valid and active languages as collected in $this->languages.
  * If a language is NOT valid, the next test is tried.
  * If all else fails we return 'en' for English, which
  * is the native language and which should always be valid.
  *
  * @uses $CFG
  * @uses $USER;
  * @return string a valid language code for an active language
  */
 function get_current_language()
 {
     global $CFG;
     global $USER;
     if (isset($_GET['language'])) {
         $lang = magic_unquote($_GET['language']);
         if (isset($this->languages[$lang]) && db_bool_is(TRUE, $this->languages[$lang]['is_active'])) {
             return $lang;
         }
     }
     if (isset($_SESSION['language_key'])) {
         $lang = $_SESSION['language_key'];
         if (isset($this->languages[$lang]) && db_bool_is(TRUE, $this->languages[$lang]['is_active'])) {
             return $lang;
         }
     }
     if (isset($USER->language_key)) {
         $lang = $USER->language_key;
         if (isset($this->languages[$lang]) && db_bool_is(TRUE, $this->languages[$lang]['is_active'])) {
             return $lang;
         }
     }
     if (isset($CFG->language_key)) {
         $lang = $CFG->language_key;
         if (isset($this->languages[$lang]) && db_bool_is(TRUE, $this->languages[$lang]['is_active'])) {
             return $lang;
         }
     }
     return 'en';
     // if all else fails, return the 'native' language
 }
コード例 #7
0
/** main program for serving files
 *
 * this routine is called from /file.php.
 *
 * This routine is responsible for serving files to the visitor.
 * These files are stored in a (virtual) file hierarchy that looks
 * like this.
 *
 * <pre>
 * /areas/areaname
 *       /another
 *       /stillmore
 *       ...
 * /users/username
 *       /another
 *       /stillmore
 *       ...
 * /groups/groupname
 *        /another
 *        /stillmore
 *        ...
 * /websiteatschool/program
 *                 /manual
 *                 /languages
 * </pre>
 *
 * This structure maps to the real file system as follows.  The (virtual)
 * directories /areas, /users and /groups correspond to the fysical
 * directories {$CFG->datadir}/areas, {$CFG->datadir}/users and
 * {$CFG->datadir}/groups respectively. The subdirectories correspond to
 * a (unique) area, user or group and serve as a file repository for that
 * area, user or group.
 *
 * The (virtual) top-level directory /websiteatschool is a special case.
 * It is used to serve the currently running website program code and the
 * user-defined translations of active languages.
 *
 * Before any file is transmitted to the visitor the access privileges
 * are checked.  The following rules apply.
 *
 * Access control for the /areas subdirectory
 *
 *  - an area must be active before any files are served
 *  - the visitor must have access to the private area if files are to be served
 *  - non-existing files yield a 404 Not Found error
 *  - non-existing areas also yield a 404 Not Found error
 *  - if the visitor has no access to the private area, also a 404 Not Found error is returned
 *
 * Access control for /users and /groups
 *
 *  - a user/group must be active before any files are served
 *  - non-existing users/groups yield 404 Not Found
 *  - non-existing files in existing directories also yield 404 Not Found
 *
 * Access control for /websiteatschool
 *
 *  - there is no limit on downloading the currently active program code or user-defined translations of active languages
 *
 * Note:
 * The check on '..' in the requested filename would be inconclusive if the $path
 * is encoded in invalid UTF-8: the overlong sequence 2F C0 AE 2E 2F eventually
 * yields 2F 2E 2E 2F or '/../'. Reference: RFC3629 section 10. However, we use
 * the filename processed with get_requested_filename() which already checks for
 * utf8 validity, which rules out the trick with overlong sequences.
 *
 * @return void file sent to the browser OR 404 not found on error
 */
function main_file()
{
    global $USER;
    global $CFG;
    global $WAS_SCRIPT_NAME;
    global $LANGUAGE;
    /** initialise the program, setup database, read configuration, etc. */
    require_once $CFG->progdir . '/init.php';
    initialise();
    was_version_check();
    // this never returns if versions don't match
    /** utility routines for manipulating files */
    require_once $CFG->progdir . '/lib/filelib.php';
    $filename = get_requested_filename();
    if (is_null($filename)) {
        error_exit404();
    }
    // 0 -- is the visitor logged in
    if (isset($_COOKIE[$CFG->session_name])) {
        /** dbsessionlib.php contains our own database based session handler */
        require_once $CFG->progdir . '/lib/dbsessionlib.php';
        dbsession_setup($CFG->session_name);
        if (dbsession_exists(magic_unquote($_COOKIE[$CFG->session_name]))) {
            session_start();
            if (!isset($_SESSION['session_counter'])) {
                // first time after login, record start time of session
                $_SESSION['session_counter'] = 1;
                $_SESSION['session_start'] = strftime("%Y-%m-%d %T");
            } else {
                $_SESSION['session_counter']++;
            }
        }
    }
    /** useraccount.class.php is used to define the USER object */
    require_once $CFG->progdir . '/lib/useraccount.class.php';
    if (isset($_SESSION) && isset($_SESSION['user_id'])) {
        $USER = new Useraccount($_SESSION['user_id']);
        $USER->is_logged_in = TRUE;
        $_SESSION['language_key'] = $LANGUAGE->get_current_language();
        // remember language set via _GET or otherwise
        session_write_close();
        // we no longer need this here, everything relevant is now in $USER
    } else {
        $USER = new Useraccount();
        $USER->is_logged_in = FALSE;
    }
    //
    // 1 -- does the visitor want to download the source code
    //
    $path_components = explode('/', trim(strtr($filename, '\\', '/'), '/'));
    if (strtolower($path_components[0]) == 'websiteatschool') {
        $source = isset($path_components[1]) ? strtolower($path_components[1]) : 'program';
        download_source($source);
        exit;
    }
    //
    // 2 -- no source code requested. check out regular files
    //
    $path = '/' . implode('/', $path_components);
    // 2A -- always disallow attempts to escape from tree via parent directory tricks
    if (in_array('..', $path_components)) {
        logger(sprintf("%s(): access denied for file '%s': no tricks with '/../': return 404 Not Found", __FUNCTION__, $path), WLOG_DEBUG);
        error_exit404($path);
    }
    // 2B -- check the 1st and 2nd component of the requested file
    switch ($path_components[0]) {
        case 'areas':
            $area_path = isset($path_components[1]) ? $path_components[1] : '';
            $fields = array('area_id', 'is_private');
            $where = array('is_active' => TRUE, 'path' => $area_path);
            $table = 'areas';
            if (($record = db_select_single_record($table, $fields, $where)) === FALSE) {
                logger(sprintf("%s(): access denied for file '%s': non-existing or inactive area: return 404 Not Found", __FUNCTION__, $path), WLOG_DEBUG);
                error_exit404($path);
            }
            $area_id = intval($record['area_id']);
            if (db_bool_is(TRUE, $record['is_private']) && !$USER->has_intranet_permissions(ACL_ROLE_INTRANET_ACCESS, $area_id)) {
                logger(sprintf("%s(): access denied for file '%s' in private area '%d': return 404 Not Found", __FUNCTION__, $path, $area_id), WLOG_DEBUG);
                error_exit404($path);
            }
            break;
        case 'users':
            $user_path = isset($path_components[1]) ? $path_components[1] : '';
            $fields = array('user_id');
            $where = array('path' => $user_path, 'is_active' => TRUE);
            $table = 'users';
            if (($record = db_select_single_record($table, $fields, $where)) === FALSE) {
                logger(sprintf("%s(): access denied for file '%s': non-existing or inactive user: return 404 Not Found", __FUNCTION__, $path), WLOG_DEBUG);
                error_exit404($path);
            }
            break;
        case 'groups':
            $group_path = isset($path_components[1]) ? $path_components[1] : '';
            $fields = array('group_id');
            $where = array('path' => $group_path, 'is_active' => TRUE);
            $table = 'groups';
            if (($record = db_select_single_record($table, $fields, $where)) === FALSE) {
                logger(sprintf("%s(): access denied for file '%s': non-existing or inactive group: return 404 Not Found", __FUNCTION__, $path), WLOG_DEBUG);
                error_exit404($path);
            }
            break;
        default:
            logger(sprintf("%s(): access denied for file '%s': subdirectory '%s' not recognised: return 404 Not Found", __FUNCTION__, $path, $path_components[0]), WLOG_DEBUG);
            error_exit404($path);
            break;
    }
    // 2C -- still here? 1st and 2nd components are good but does the file exist?
    if (!is_file($CFG->datadir . $path)) {
        logger(sprintf("%s(): access denied for file '%s': file does not exist: return 404 Not Found", __FUNCTION__, $path), WLOG_DEBUG);
        error_exit404($path);
    }
    //
    // At this point we confident that the file exists within the data directory and also that
    // the visitor is allowed access to the file. Now send the file to the visitor.
    //
    $name = basename($path);
    if (($bytes_sent = send_file_from_datadir($path, $name)) === FALSE) {
        logger(sprintf("Failed to send '%s' using filename '%s'", $path, $name));
        $retval = FALSE;
    } else {
        logger(sprintf("Success sending '%s' using filename '%s', size = %d bytes", $path, $name, $bytes_sent), WLOG_DEBUG);
        $retval = TRUE;
    }
    exit;
}
コード例 #8
0
/** execute the selected login procedure
 *
 * The login process is controlled via the parameter 'login'
 * provided by the user via 'index.php?login=N or via the
 * 'action' property in a HTML-form. These numbers correspond to the
 * LOGIN_PROCEDURE_* constants defined near the top of this file.
 * Here's a reminder:
 *
 * 1. LOGIN_PROCEDURE_NORMAL this is the usual procedure for logging in
 * 2. LOGIN_PROCEDURE_CHANGE_PASSWORD this is the procedure to change the user's password
 * 3. LOGIN_PROCEDURE_SEND_LAISSEZ_PASSER this is phase 1 of the 'forgot password' procedure
 * 4. LOGIN_PROCEDURE_SEND_BYPASS this is phase 2 of the 'forgot password' procedure
 *
 * Note that this routine only returns to the caller after either a succesful
 * regular login (i.e. after completing LOGIN_PROCEDURE_NORMAL). All the
 * other variants and error conditions yield another screen and an immediate exit and
 * hence no return to caller. If this routine returns, it returns the user_id
 * of the authenticated user (the primary key into the users table). It is up to the caller to
 * retrieve additional information about this user; any information read from the database
 * during login is discarded. This prevents password hashes still lying around.
 * 
 * Note that a successful login has the side effect of garbage collection:
 * whenever we experience a successful login any obsolete sessions are removed.
 * This makes sure that locked records eventually will be unlocked, once the corresponding
 * session no longer exists. The garbage collection routine is also called from
 * the PHP session handler every once in a while, but here we make 100% sure that
 * garbage is collected at least at every login. (Note: obsolete sessions should not
 * be a problem for visitors that are not logged in, because you have to be logged in
 * to be able to lock a record.)
 *
 * @param int $procedure the login procedure to execute
 * @param string $message the message to display when showing the login dialog
 * @return void|int no return on error, otherwise the user_id of the authenticated user
 * @uses $CFG
 * @uses dbsession_setup()
 * @uses dbsession_garbage_collection()
 */
function was_login($procedure = LOGIN_PROCEDURE_SHOWLOGIN, $message = '')
{
    global $CFG;
    // get rid of the cookie (if we received one) and the corresponding session;
    // the user's browser should NOT present us with a cookie during the login procedures.
    if (isset($_COOKIE[$CFG->session_name])) {
        was_logout();
        exit;
    }
    // If this IP-address is currently blacklisted, tell the visitor access is denied
    if (login_is_blacklisted($_SERVER['REMOTE_ADDR'])) {
        show_login(LOGIN_PROCEDURE_MESSAGE_BOX, t('access_denied', 'loginlib'));
        exit;
    }
    switch (intval($procedure)) {
        case LOGIN_PROCEDURE_NORMAL:
            if (isset($_POST['login_username']) && isset($_POST['login_password'])) {
                $username = magic_unquote($_POST['login_username']);
                $password = magic_unquote($_POST['login_password']);
                $user = authenticate_user(BY_PASSWORD, $username, $password);
                if ($user !== FALSE) {
                    login_failure_reset($_SERVER['REMOTE_ADDR']);
                    if (db_bool_is(FALSE, $user['bypass_mode'])) {
                        // valid credentials and not in a bypass mode: start session and return user_id
                        require_once $CFG->progdir . '/lib/dbsessionlib.php';
                        dbsession_setup($CFG->session_name);
                        $session_key = dbsession_create($user['user_id'], $_SERVER['REMOTE_ADDR']);
                        session_id($session_key);
                        session_start();
                        $_SESSION['session_id'] = dbsession_get_session_id($session_key);
                        $user_id = intval($user['user_id']);
                        $_SESSION['user_id'] = $user_id;
                        $_SESSION['redirect'] = $user['redirect'];
                        $_SESSION['language_key'] = $user['language_key'];
                        $_SESSION['remote_addr'] = $_SERVER['REMOTE_ADDR'];
                        $_SESSION['salt'] = $CFG->salt;
                        // allow for extra check on rogue sessions
                        $_SESSION['username'] = $username;
                        logger('login: \'' . $username . '\' (' . $user_id . '): success', WLOG_INFO, $user_id);
                        // now that we logged on successfully, make sure that obsolete sessions
                        // will not bother us (or other logged in users). Note the 900 seconds minimum duration;
                        // $time_out = max(900,intval(ini_get('session.gc_maxlifetime')));
                        global $CFG;
                        $time_out = max(900, intval($CFG->session_expiry));
                        dbsession_garbage_collection($time_out);
                        return $user_id;
                        // SUCCESS! User is logged in, tell caller!
                    } else {
                        show_login(LOGIN_PROCEDURE_CHANGE_PASSWORD, t('must_change_password', 'loginlib'));
                        exit;
                    }
                }
                // Invalid credentials; pretend we're busy (slow user down), increment failure count...
                $failure_count = login_failure_increment($_SERVER['REMOTE_ADDR'], LOGIN_PROCEDURE_NORMAL, $username);
                login_failure_delay($_SERVER['REMOTE_ADDR']);
                if ($failure_count < intval($CFG->login_max_failures)) {
                    show_login(LOGIN_PROCEDURE_NORMAL, t('invalid_credentials_please_retry', 'loginlib'));
                } elseif ($failure_count == intval($CFG->login_max_failures)) {
                    show_login(LOGIN_PROCEDURE_SEND_LAISSEZ_PASSER, t('do_you_want_to_try_forgot_password_procedure', 'loginlib'));
                } else {
                    login_failure_blacklist_address($_SERVER['REMOTE_ADDR'], 60 * intval($CFG->login_blacklist_interval), $username);
                    show_login(LOGIN_PROCEDURE_MESSAGE_BOX, t('contact_webmaster_for_new_password', 'loginlib'));
                }
            } else {
                show_login(LOGIN_PROCEDURE_NORMAL);
            }
            exit;
            break;
        case LOGIN_PROCEDURE_CHANGE_PASSWORD:
            if (isset($_POST['login_username']) && isset($_POST['login_password']) && isset($_POST['login_new_password1']) && isset($_POST['login_new_password2'])) {
                $username = magic_unquote($_POST['login_username']);
                $password = magic_unquote($_POST['login_password']);
                $new_password1 = magic_unquote($_POST['login_new_password1']);
                $new_password2 = magic_unquote($_POST['login_new_password2']);
                $user = authenticate_user(BY_PASSWORD, $username, $password);
                //
                // step 1 - perform some checks on the proposed new passwords
                //
                if ($user !== FALSE) {
                    // user authenticated: we can now also check re-use of existing passwords
                    $salt = $user['salt'];
                    $password_hash = $user['password_hash'];
                    $bypass_hash = $user['bypass_hash'];
                } else {
                    // user not authenticated so we cannot check for re-use of existing passwords
                    $salt = '';
                    $password_hash = '';
                    $bypass_hash = '';
                }
                if (!acceptable_new_password($new_password1, $new_password2, $salt, $password_hash, $bypass_hash)) {
                    show_login(LOGIN_PROCEDURE_CHANGE_PASSWORD, t('invalid_new_passwords', 'loginlib', array('{MIN_LENGTH}' => MINIMUM_PASSWORD_LENGTH, '{MIN_LOWER}' => MINIMUM_PASSWORD_LOWERCASE, '{MIN_UPPER}' => MINIMUM_PASSWORD_UPPERCASE, '{MIN_DIGIT}' => MINIMUM_PASSWORD_DIGITS)));
                    exit;
                }
                //
                // step 2 - if authenticated, actually change password and reset failure counters/blacklists
                //
                if ($user !== FALSE) {
                    // allow the user in:
                    //  - start new session,
                    //  - immediately write/close it,
                    //  - send user an email about success with changing password,
                    //  - and finally leave the user with message box on screen
                    //
                    login_change_password($user['user_id'], $new_password1);
                    login_failure_reset($_SERVER['REMOTE_ADDR']);
                    require_once $CFG->progdir . '/lib/dbsessionlib.php';
                    dbsession_setup($CFG->session_name);
                    $session_key = dbsession_create($user['user_id'], $_SERVER['REMOTE_ADDR']);
                    session_id($session_key);
                    session_start();
                    $_SESSION['session_id'] = dbsession_get_session_id($session_key);
                    $user_id = intval($user['user_id']);
                    $_SESSION['user_id'] = $user_id;
                    $_SESSION['redirect'] = $user['redirect'];
                    $_SESSION['language_key'] = $user['language_key'];
                    $_SESSION['remote_addr'] = $_SERVER['REMOTE_ADDR'];
                    $_SESSION['salt'] = $CFG->salt;
                    // allow for extra check on rogue sessions
                    $_SESSION['username'] = $username;
                    session_write_close();
                    // save the session
                    login_send_confirmation($user);
                    logger('login: \'' . $username . '\' (' . $user_id . '), change password: success', WLOG_INFO, $user_id);
                    show_login(LOGIN_PROCEDURE_MESSAGE_BOX, t('password_changed', 'loginlib'));
                    exit;
                }
                // Invalid credentials; pretend we're busy (slow user down), increment failure count...
                $failure_count = login_failure_increment($_SERVER['REMOTE_ADDR'], LOGIN_PROCEDURE_CHANGE_PASSWORD, $username);
                login_failure_delay($_SERVER['REMOTE_ADDR']);
                if ($failure_count < intval($CFG->login_max_failures)) {
                    show_login(LOGIN_PROCEDURE_CHANGE_PASSWORD, t('invalid_credentials_please_retry', 'loginlib'));
                } elseif ($failure_count == intval($CFG->login_max_failures)) {
                    show_login(LOGIN_PROCEDURE_SEND_LAISSEZ_PASSER, t('too_many_login_attempts', 'loginlib'));
                } else {
                    login_failure_blacklist_address($_SERVER['REMOTE_ADDR'], 60 * intval($CFG->login_blacklist_interval), $username);
                    show_login(LOGIN_PROCEDURE_MESSAGE_BOX, t('too_many_change_password_attempts', 'loginlib'));
                }
            } else {
                show_login(LOGIN_PROCEDURE_CHANGE_PASSWORD);
            }
            exit;
            break;
        case LOGIN_PROCEDURE_SEND_LAISSEZ_PASSER:
            if (isset($_POST['login_username']) && isset($_POST['login_email'])) {
                $username = magic_unquote($_POST['login_username']);
                $email = magic_unquote($_POST['login_email']);
                $user = authenticate_user(BY_EMAIL, $username, $email);
                if ($user !== FALSE) {
                    if (login_send_laissez_passer($user)) {
                        show_login(LOGIN_PROCEDURE_MESSAGE_BOX, t('see_mail_for_further_instructions', 'loginlib'));
                    } else {
                        show_login(LOGIN_PROCEDURE_MESSAGE_BOX, t('failure_sending_laissez_passer_mail', 'loginlib'));
                    }
                    exit;
                } else {
                    // Not authenticated; pretend we're busy (slow user down), increment failure count...
                    $failure_count = login_failure_increment($_SERVER['REMOTE_ADDR'], LOGIN_PROCEDURE_SEND_LAISSEZ_PASSER, $username);
                    login_failure_delay($_SERVER['REMOTE_ADDR']);
                    if ($failure_count < intval($CFG->login_max_failures)) {
                        show_login(LOGIN_PROCEDURE_SEND_LAISSEZ_PASSER, t('invalid_username_email_please_retry', 'loginlib'));
                    } elseif ($failure_count == intval($CFG->login_max_failures)) {
                        show_login(LOGIN_PROCEDURE_MESSAGE_BOX, t('too_many_login_attempts', 'loginlib'));
                    } else {
                        login_failure_blacklist_address($_SERVER['REMOTE_ADDR'], 60 * intval($CFG->login_blacklist_interval), $username);
                        show_login(LOGIN_PROCEDURE_MESSAGE_BOX, t('too_many_login_attempts', 'loginlib'));
                    }
                    exit;
                }
            } else {
                show_login(LOGIN_PROCEDURE_SEND_LAISSEZ_PASSER);
            }
            exit;
            break;
        case LOGIN_PROCEDURE_SEND_BYPASS:
            if (isset($_GET['code']) && isset($_GET['username'])) {
                $laissez_passer = magic_unquote($_GET['code']);
                $username = magic_unquote($_GET['username']);
            } elseif (isset($_POST['login_username']) && isset($_POST['login_laissez_passer'])) {
                $laissez_passer = magic_unquote($_POST['login_laissez_passer']);
                $username = magic_unquote($_POST['login_username']);
            } else {
                show_login(LOGIN_PROCEDURE_SEND_BYPASS);
                exit;
            }
            // still here? Then we check the laissez_passer and send a second email to the user
            $user = authenticate_user(BY_LAISSEZ_PASSER, $username, $laissez_passer);
            if ($user !== FALSE) {
                login_failure_reset($_SERVER['REMOTE_ADDR']);
                if (login_send_bypass($user)) {
                    show_login(LOGIN_PROCEDURE_NORMAL, t('see_mail_for_new_temporary_password', 'loginlib'));
                } else {
                    show_login(LOGIN_PROCEDURE_MESSAGE_BOX, t('failure_sending_temporary_password', 'loginlib'));
                }
            } else {
                $failure_count = login_failure_increment($_SERVER['REMOTE_ADDR'], LOGIN_PROCEDURE_SEND_BYPASS, $username);
                login_failure_delay($_SERVER['REMOTE_ADDR']);
                if ($failure_count < intval($CFG->login_max_failures)) {
                    show_login(LOGIN_PROCEDURE_SEND_BYPASS, t('invalid_laissez_passer_please_retry', 'loginlib'));
                } elseif ($failure_count == intval($CFG->login_max_failures)) {
                    show_login(LOGIN_PROCEDURE_MESSAGE_BOX, t('too_many_login_attempts', 'loginlib'));
                } else {
                    login_failure_blacklist_address($_SERVER['REMOTE_ADDR'], 60 * intval($CFG->login_blacklist_interval), $username);
                    show_login(LOGIN_PROCEDURE_MESSAGE_BOX, t('too_many_login_attempts', 'loginlib'));
                }
            }
            exit;
            break;
        case LOGIN_PROCEDURE_SHOWLOGIN:
            show_login(LOGIN_PROCEDURE_NORMAL, $message);
            exit;
            break;
        default:
            show_login(LOGIN_PROCEDURE_NORMAL);
            exit;
            break;
    }
}
コード例 #9
0
/** return an (unquoted) string value specified in the page request or default value if none
 *
 * First check out the friendly url for the named parameter. If it exists, we use that,
 * otherwise we have the $default_value. After that the valid UTF-8 value may overwrite the
 * value found in the friendly url (or the default value).
 *
 * It is the responsability of the caller to provide a workable default value.
 *
 * Note that invalid UTF-8 is silently discarded.
 *
 * @param string $name the name of the parameter to retrieve the value of
 * @param mixed $default_value the value to return if parameter was not specified
 * @return mixed the value of the parameter or the default value if not specified
 */
function get_parameter_string($name, $default_value = NULL)
{
    $value = get_friendly_parameter($name, $default_value);
    // first check out friendly URL...
    if (isset($_GET[$name]) && utf8_validate($_GET[$name])) {
        $value = magic_unquote($_GET[$name]);
        // ...but let valid UTF-8 GET[] value prevail (if any)
    }
    return $value;
}
コード例 #10
0
/** save the modified content data of this module linked to node $node_id
 *
 * this validates and saves the data that was submitted by the user.
 * If validation fails, or storing the data doesn't work, the flag $edit_again
 * is set to TRUE and the return value is FALSE.
 *
 * If the user has cancelled the operation, the flag $edit_again is set to FALSE
 * and the return value is also FALSE.
 *
 * If the modified data is stored successfully, the return value is TRUE (and
 * the value of $edit_again is a don't care).
 *
 * Here is a summary of return values.
 *
 *  - retval = TRUE ==> data saved successfully
 *  - retval = FALSE && edit_again = TRUE ==> re-edit the data, show the edit dialog again
 *  - retval = FALSE && edit_again = FALSE ==> cancelled, do nothing
 *
 * @param object &$output collects the html output (if any)
 * @param int $area_id the area in which $node_id resides
 * @param int $node_id the node to which the content is connected
 * @param array $module the module record straight from the database
 * @param bool $viewonly if TRUE, editing and hence saving is not allowed
 * @param bool &$edit_again set to TRUE if we need to edit the content again, FALSE otherwise
 * @return bool TRUE on success + output stored via $output, FALSE otherwise
 */
function htmlpage_save(&$output, $area_id, $node_id, $module, $viewonly, &$edit_again)
{
    global $USER;
    if (isset($_POST['button_cancel']) || $viewonly) {
        $edit_again = FALSE;
        $retval = FALSE;
    } else {
        $edit_again = TRUE;
        if (!$viewonly) {
            $where = array('node_id' => intval($node_id));
            $order = array('version DESC');
            $record = db_select_single_record('htmlpages', '*', $where, $order);
            if ($record !== FALSE) {
                $now = strftime('%Y-%m-%d %T');
                $fields = array('version' => intval($record['version']) + 1, 'page_data' => magic_unquote($_POST['htmlpage_content']), 'mtime' => $now, 'muser_id' => $USER->user_id);
                $where = array('htmlpage_id' => $record['htmlpage_id']);
                $retval = db_update('htmlpages', $fields, $where);
            } else {
                $retval = FALSE;
            }
        } else {
            $retval = FALSE;
        }
    }
    return $retval;
}
コード例 #11
-1
/** main program for site maintenance
 *
 * This is the main administrator program.
 * First step is to deal with users logging in or out.
 * If a user is not logged in, a login dialog is displayed.
 * If a user is logged in but has no admin privileges, she
 * is redirected to the public site (ie. index.php).
 *
 * Once we have established that the user is an administrator,
 * we setup an output collecting object and see what the user
 * wants us to do by interpreting the parameter 'job'.
 * If the user has access to the specified job, the corresponding
 * code is included and the main routine of that handler is called.
 * It is then the responsability of that handler to further decide
 * what needs to be done.
 * After the handler returns, the collected output is sent to the user.
 * This includes the main navigation (i.e. links to the various
 * 'managers') and also the menu and the content generated by the
 * handler.
 *
 * If the user has no privilege to access a particular manager,
 * an error messate is displayed in both the message area and the content
 * area. This makes it clear to the user that access is denied.
 * Note that the inaccessible items are displayed in the main navigation
 * via 'dimmed' (light-grey) links or black/white images.
 * By showing these 'dimmed' links, the user will be aware that there
 * is more that just what she is allowed to see. This is more transparent
 * than suppressing items and keeping them secret.
 *
 * @return void generated page sent to user's browser
 * @uses $CFG;
 * @uses $LANGUAGE;
 * @uses $USER;
 * @todo should we cater for a special 'print' button + 
 *       support for a special style sheet for media="print"?
 */
function main_admin()
{
    global $CFG;
    global $LANGUAGE;
    global $USER;
    /** initialise, setup database, read configuration, etc. */
    require_once $CFG->progdir . '/init.php';
    initialise();
    // user must be logged in to perform any admin tasks at all
    if (isset($_GET['logout'])) {
        admin_logout_and_exit();
    } elseif (isset($_GET['login'])) {
        $user_id = admin_login(magic_unquote($_GET['login']));
    } elseif (isset($_COOKIE[$CFG->session_name])) {
        $user_id = admin_continue_session();
    } else {
        admin_show_login_and_exit();
    }
    /** useraccount.class.php is used to define the USER object */
    require_once $CFG->progdir . '/lib/useraccount.class.php';
    $USER = new Useraccount($user_id);
    $USER->is_logged_in = TRUE;
    $_SESSION['language_key'] = $LANGUAGE->get_current_language();
    // remember language set via _GET or otherwise
    // Only admins are allowed, others are redirected to index.php
    if (!$USER->is_admin()) {
        logger("admin.php: '{$USER->username}' ({$USER->user_id}) is no admin and was redirected to index.php or login");
        session_write_close();
        non_admin_redirect_and_exit();
    }
    // We now know that this user is an admin, but
    // is she allowed to perform upgrades if any? Check it out in 2 steps
    // 1--we do NOT want exit on error if the user has enough privileges
    // 2--we check the version and stay here if the user has enough privileges
    $exit_on_error = $USER->has_job_permissions(JOB_PERMISSION_UPDATE) ? FALSE : TRUE;
    $need_to_update = was_version_check($exit_on_error) ? FALSE : TRUE;
    // We are still here if versions are OK _or_ versions mismatch but user has UPDATE privilege.
    // Now we know we _will_ be generating output => setup output object
    // using the specified skin OR the user's prefererred skin OR the one
    // stored before in $_SESSION
    $_SESSION['skin'] = get_current_skin();
    // echo "DDD: {$_SESSION['skin']}";
    $output = new AdminOutput($_SESSION['skin'], $CFG->title);
    // Display a 'welcome message' if this is the first page after logging in.
    if ($_SESSION['session_counter'] == 1) {
        $output->add_message(t('login_user_success', 'admin', array('{USERNAME}' => $USER->username)));
    }
    // Let's see what what job needs to be done
    $job = $need_to_update ? JOB_UPDATE : get_parameter_string('job', JOB_STARTCENTER);
    // main dispatcher
    switch ($job) {
        case JOB_STARTCENTER:
            job_start($output);
            break;
        case JOB_PAGEMANAGER:
            add_javascript_popup_function($output, '  ');
            if ($USER->has_job_permissions(JOB_PERMISSION_PAGEMANAGER)) {
                include $CFG->progdir . '/lib/pagemanager.class.php';
                $manager = new PageManager($output);
            } else {
                $output->add_content("<h2>" . t('access_denied', 'admin') . "</h2>");
                $output->add_content(t('job_access_denied', 'admin'));
                $output->add_message(t('job_access_denied', 'admin'));
            }
            break;
        case JOB_FILEMANAGER:
        case JOB_FILEBROWSER:
        case JOB_IMAGEBROWSER:
        case JOB_FLASHBROWSER:
            add_javascript_popup_function($output, '  ');
            add_javascript_select_url_function($output, '  ');
            if ($USER->has_job_permissions(JOB_PERMISSION_FILEMANAGER)) {
                include $CFG->progdir . '/lib/filemanager.class.php';
                $manager = new FileManager($output, $job);
            } else {
                $output->add_content("<h2>" . t('access_denied', 'admin') . "</h2>");
                $output->add_content(t('job_access_denied', 'admin'));
                $output->add_message(t('job_access_denied', 'admin'));
            }
            break;
        case JOB_MODULEMANAGER:
            if ($USER->has_job_permissions(JOB_PERMISSION_MODULEMANAGER)) {
                include $CFG->progdir . '/lib/modulemanagerlib.php';
                job_modulemanager($output);
            } else {
                $output->add_content("<h2>" . t('access_denied', 'admin') . "</h2>");
                $output->add_content(t('job_access_denied', 'admin'));
                $output->add_message(t('job_access_denied', 'admin'));
            }
            break;
        case JOB_ACCOUNTMANAGER:
            if ($USER->has_job_permissions(JOB_PERMISSION_ACCOUNTMANAGER)) {
                include $CFG->progdir . '/lib/accountmanagerlib.php';
                job_accountmanager($output);
            } else {
                $output->add_content("<h2>" . t('access_denied', 'admin') . "</h2>");
                $output->add_content(t('job_access_denied', 'admin'));
                $output->add_message(t('job_access_denied', 'admin'));
            }
            break;
        case JOB_CONFIGURATIONMANAGER:
            if ($USER->has_job_permissions(JOB_PERMISSION_CONFIGURATIONMANAGER)) {
                include $CFG->progdir . '/lib/configurationmanagerlib.php';
                job_configurationmanager($output);
            } else {
                $output->add_content("<h2>" . t('access_denied', 'admin') . "</h2>");
                $output->add_content(t('job_access_denied', 'admin'));
                $output->add_message(t('job_access_denied', 'admin'));
            }
            break;
        case JOB_STATISTICS:
            if ($USER->has_job_permissions(JOB_PERMISSION_STATISTICS)) {
                include $CFG->progdir . '/lib/statisticslib.php';
                job_statistics($output);
            } else {
                $output->add_content("<h2>" . t('access_denied', 'admin') . "</h2>");
                $output->add_content(t('job_access_denied', 'admin'));
                $output->add_message(t('job_access_denied', 'admin'));
            }
            break;
        case JOB_TOOLS:
            if ($USER->has_job_permissions(JOB_PERMISSION_TOOLS)) {
                // user has permission to access at least one of the tools
                include $CFG->progdir . '/lib/toolslib.php';
                job_tools($output);
            } else {
                $output->add_content("<h2>" . t('access_denied', 'admin') . "</h2>");
                $output->add_content(t('job_access_denied', 'admin'));
                $output->add_message(t('job_access_denied', 'admin'));
            }
            break;
        case JOB_UPDATE:
            if ($USER->has_job_permissions(JOB_PERMISSION_UPDATE)) {
                // user has permission to access the update routine(s)
                include $CFG->progdir . '/lib/updatelib.php';
                job_update($output);
            } else {
                $output->add_content("<h2>" . t('access_denied', 'admin') . "</h2>");
                $output->add_content(t('job_access_denied', 'admin'));
                $output->add_message(t('job_access_denied', 'admin'));
            }
            break;
        default:
            if (!empty($job)) {
                $output->add_content("<h2>" . t('access_denied', 'admin') . "</h2>");
                $output->add_content(t('unknown_job', 'admin', array('{JOB}' => htmlspecialchars($job))));
                $output->add_message(t('unknown_job', 'admin', array('{JOB}' => htmlspecialchars($job))));
                logger("'" . $USER->username . "': unknown job '" . htmlspecialchars($job) . "'");
            } else {
                job_start($output);
            }
            break;
    }
    // the various functions job_*() will have put their output in $output
    // Now it is time to actually output the output to the user's browser.
    $output->send_output();
    // make sure that any changes in $_SESSION are properly stored
    // note that we close the session only after all processing is done,
    // allowing the various job_*()'s to manipulate the session variables
    session_write_close();
    // at this point we have sent the page to the user,
    // we can now use the remaining time in this run to process
    // a few alerts (if any).
    cron_send_queued_alerts(25);
    // if there are more than 25, do them later or let cron do it.
    return;
}