/** quick and dirty logfile viewer
 *
 * this constructs a table of the HTML-variety with the contents of the logtable.
 * fields displayed are: datim, IP-address, username, logpriority and message
 * we use a LEFT JOIN in order to get to a meaningful username rather than a numeric user_id
 * an attempt is made to start with the last page of the logs because that would probably
 * be the most interesting part. We paginate the log in order to keep it manageable.
 *
 * &lt;Rant&gt;<br>
 * I used to use the built-in constants like LOG_INFO and LOG_DEBUG to allow for different levels
 * of logging (see {@link logger()}). To my complete surprise logging didn't work at all on
 * Windows (it did on Linux). The reason was that LOG_DEBUG and LOG_INFO and LOG_NOTICE are all
 * defined to be the same value. WTF? Any test based on LOG_DEBUG and LOG_INFO being different
 * would fail, hence no logging at all. The mind boggles! So, instead of using built-in constants
 * I had to define my own and do a global search&replace. Aaarghhhhhh!!!!<br>
 * &lt;/Rant&gt;<br>
 *
 * @param object &$output collects output to show to user
 * @return void output displayed via $output
 * @todo should we allow for fancy selection mechanisms on the logfile or is that over the top?
 */
function task_logview(&$output)
{
    global $CFG, $WAS_SCRIPT_NAME, $DB;
    static $priorities = array(WLOG_EMERG => 'LOG_EMERG', WLOG_ALERT => 'LOG_ALERT', WLOG_CRIT => 'LOG_CRIT', WLOG_ERR => 'LOG_ERR', WLOG_WARNING => 'LOG_WARNING', WLOG_NOTICE => 'LOG_NOTICE', WLOG_INFO => 'LOG_INFO', WLOG_DEBUG => 'LOG_DEBUG');
    // 0 -- at least we allow the user to navigate away if something goes wrong
    $output->set_helptopic('logview');
    show_tools_menu($output, TASK_LOGVIEW);
    // 1A -- how many messages are there anyway?
    $table = 'log_messages';
    $where = '';
    // could be used to select per user, per priority, etc. For now: always select everything
    if (($record = db_select_single_record($table, 'COUNT(log_message_id) AS messages', $where)) === FALSE) {
        $output->add_content('<h2>' . t('menu_logview', 'admin') . '</h2>');
        $output->add_content(t('logview_error', 'admin'));
        $output->add_message(t('logview_error', 'admin'));
        logger(sprintf('%s(): cannot retrieve log message count: %s', __FUNCTION__, db_errormessage()));
        return;
    }
    // 1B -- if there are no message we leave
    if (($num_messages = intval($record['messages'])) < 1) {
        $output->add_content('<h2>' . t('menu_logview', 'admin') . '</h2>');
        $output->add_content(t('logview_no_messages', 'admin'));
        $output->add_message(t('logview_no_messages', 'admin'));
        logger(sprintf('%s(): no messages to show', __FUNCTION__), WLOG_DEBUG);
        return;
    }
    // 2 -- which part of the logs do they want to see? (calculate/retrieve offset and limit)
    $limit = get_parameter_int('limit', $CFG->pagination_height);
    $limit = max(1, $limit);
    // make sure 1 <= $limit
    $offset = intval(floor($num_messages / $limit)) * $limit;
    // attempt to start at begin of LAST page
    $offset = get_parameter_int('offset', max($offset, 0));
    $offset = max(min($num_messages - 1, $offset), 0);
    // make sure 0 <= $offset < $num_messages
    // 3 -- show the pagination in the page header (if necessary)
    if ($num_messages <= $limit && $offset == 0) {
        // listing fits on a single screen
        $header = '<h2>' . t('menu_logview', 'admin') . '</h2>';
    } else {
        // pagination necessary, tell user where we are
        $param = array('{FIRST}' => strval($offset + 1), '{LAST}' => strval(min($num_messages, $offset + $limit)), '{TOTAL}' => strval($num_messages));
        $header = '<h2>' . t('menu_logview', 'admin') . ' ' . t('pagination_count_of_total', 'admin', $param) . '</h2>';
        $parameters = array('job' => JOB_TOOLS, 'task' => TASK_LOGVIEW);
        $output->add_pagination($WAS_SCRIPT_NAME, $parameters, $num_messages, $limit, $offset, $CFG->pagination_width);
    }
    // 4 -- retrieve the selected messages (including optional username via LEFT JOIN)
    $sql = sprintf('SELECT l.datim, l.remote_addr, l.priority, l.user_id, u.username, l.message ' . 'FROM %slog_messages l LEFT JOIN %susers u USING (user_id) ' . 'ORDER BY l.datim, l.log_message_id', $DB->prefix, $DB->prefix);
    if (($DBResult = $DB->query($sql, $limit, $offset)) === FALSE) {
        $output->add_message(t('logview_error', 'admin'));
        logger(sprintf('%s(): cannot retrieve log messages: %s', __FUNCTION__, db_errormessage()));
        return;
    }
    $records = $DBResult->fetch_all_assoc();
    $DBResult->close();
    // 5A -- setup a table with a header
    $index = $offset + 1;
    $output->add_content($header);
    $class = 'header';
    $attributes = array('class' => $class, 'align' => 'right');
    $output->add_content('<p>');
    $output->add_content(html_table(array('cellpadding' => '3')));
    $output->add_content('  ' . html_table_row($attributes));
    $output->add_content('    ' . html_table_head($attributes, t('logview_nr', 'admin')));
    $attributes['align'] = 'left';
    $output->add_content('    ' . html_table_head($attributes, t('logview_datim', 'admin')));
    $output->add_content('    ' . html_table_head($attributes, t('logview_remote_addr', 'admin')));
    $output->add_content('    ' . html_table_head($attributes, t('logview_user_id', 'admin')));
    $output->add_content('    ' . html_table_head($attributes, t('logview_priority', 'admin')));
    $output->add_content('    ' . html_table_head($attributes, t('logview_message', 'admin')));
    $output->add_content('  ' . html_table_row_close());
    // 5B -- step through the recordset and dump into the table
    foreach ($records as $record) {
        $class = $class == 'odd' ? 'even' : 'odd';
        $priority = isset($priorities[$record['priority']]) ? $priorities[$record['priority']] : strval(intval($record['priority']));
        $attributes = array('class' => $class);
        $output->add_content('  ' . html_table_row($attributes));
        $attributes['align'] = 'right';
        $output->add_content('    ' . html_table_cell($attributes, strval($index++)));
        $attributes['align'] = 'left';
        $output->add_content('    ' . html_table_cell($attributes, htmlspecialchars($record['datim'])));
        $output->add_content('    ' . html_table_cell($attributes, htmlspecialchars($record['remote_addr'])));
        $output->add_content('    ' . html_table_cell($attributes, htmlspecialchars($record['username'])));
        $output->add_content('    ' . html_table_cell($attributes, $priority));
        $output->add_content('    ' . html_table_cell($attributes, htmlspecialchars($record['message'])));
        $output->add_content('  ' . html_table_row_close());
    }
    // 5C -- all done
    $output->add_content(html_table_close());
    $output->add_content('<p>');
}
/** handle the editing/saving of the main configuration information
 *
 * this routine handles editing of the main configuration parameters.
 * It either displays the edit dialog or saves the modified data and
 * shows the configuration manager introduction screen.
 *
 * Note that we do NOT try to redirect the user via a header() after
 * a succesful save. It would be handy because this particular
 * save action may have had impact on the global configuration,
 * which is already read at this point. By redirecting we would
 * make a fresh start, with the new parameters.
 * However, we lose the easy ability to tell the user that the data
 * was saved (via $output->add_message()). So, either no feedback
 * or obsolete global config in core. Hmmmm. I settle for the feedback
 * and the 'wrong' settings.
 *
 * @param object &$output collects the html output
 * @return void results are returned as output in $output
 * @uses ConfigAssistant()
 */
function modulemanager_process(&$output, $task)
{
    global $CFG, $WAS_SCRIPT_NAME;
    // 0 -- sanity check
    $modules = modulemanager_get_modules();
    $module_id = get_parameter_int('module', 0);
    if (!isset($modules[$module_id])) {
        logger(sprintf('%s(): unknown module; id = %d', __FUNCTION__, $module_id));
        $output->add_message(t('error_invalid_parameters', 'admin'));
        modulemanager_show_intro($output);
        modulemanager_show_menu($output);
        return;
    }
    // 1 -- prepare
    include_once $CFG->progdir . '/lib/configassistant.class.php';
    $table = 'modules_properties';
    $keyfield = 'module_property_id';
    $prefix = 'config_';
    $domain = 'm_' . $modules[$module_id]['name'];
    $where = array('module_id' => $module_id);
    $assistant = new ConfigAssistant($table, $keyfield, $prefix, $domain, $where);
    $href = href($WAS_SCRIPT_NAME, array('job' => JOB_MODULEMANAGER, 'task' => TASK_MODULEMANAGER_SAVE, 'module' => $module_id));
    // 2 -- what do we need to do?
    if ($task == TASK_MODULEMANAGER_SAVE) {
        // save data (or cancel if they want to cancel)
        if (isset($_POST['button_save'])) {
            if ($assistant->save_data($output)) {
                modulemanager_show_intro($output);
                modulemanager_show_menu($output, $module_id);
            } else {
                $output->add_content('<h2>' . t($prefix . 'header', $domain) . '</h2>');
                $output->add_content(t($prefix . 'explanation', $domain));
                $assistant->show_dialog($output, $href);
            }
        } else {
            $output->add_message(t('cancelled', 'admin'));
            modulemanager_show_intro($output);
            modulemanager_show_menu($output, $module_id);
        }
    } else {
        // no save yet, simply show dialog
        $output->add_content('<h2>' . t($prefix . 'header', $domain) . '</h2>');
        $output->add_content(t($prefix . 'explanation', $domain));
        $assistant->show_dialog($output, $href);
        modulemanager_show_menu($output, $module_id);
    }
}
 /** 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);
     }
 }
 /** validate and save modified data to database
  *
  * this saves data from both the edit and the edit theme dialog if data validates.
  * If the data does NOT validate, the edit screen is displayed again
  * otherwise the area overview is displayed again.
  *
  * @return void results are returned as output in $this->output
  * @uses $WAS_SCRIPT_NAME
  * @uses $CFG
  * @uses $USER
  */
 function area_save()
 {
     global $CFG, $WAS_SCRIPT_NAME, $USER;
     $area_id = get_parameter_int('area', 0);
     $areas = get_area_records();
     // 0 - basic sanity
     if ($areas === FALSE || !isset($areas[$area_id])) {
         // are they trying to trick us, specifying an invalid area?
         logger("areamanager: weird: user tried to save data to non-existing area '{$area_id}'");
         $this->output->add_message(t('invalid_area', 'admin', array('{AREA}' => strval($area_id))));
         $this->area_overview();
         return;
     }
     // 1 -- are we allowed to perform the edit and thus the save operation?
     if (!$USER->has_area_permissions(PERMISSION_AREA_EDIT_AREA, $area_id)) {
         logger("areamanager: user attempted to save data to area '{$area_id}' without permission");
         $msg = t('icon_area_edit_access_denied', 'admin');
         $this->output->add_message($msg);
         $this->output->add_popup_bottom($msg);
         $this->area_overview();
         return;
     }
     // 2 -- if the user cancelled the operation, there is no point in hanging 'round
     if (isset($_POST['button_cancel'])) {
         $this->output->add_message(t('cancelled', 'admin'));
         $this->area_overview();
         return;
     }
     // 3 -- we need to know which dialog we're dealing with
     if (!isset($_POST['dialog'])) {
         logger("areamanager: weird: 'dialog' not set in area_save() (area='{$area_id}')", WLOG_DEBUG);
         $this->area_overview();
         return;
     }
     $dialog = intval($_POST['dialog']);
     if ($dialog == AREAMANAGER_DIALOG_EDIT_THEME) {
         $theme_id = $areas[$area_id]['theme_id'];
         $themes = $this->get_theme_records();
         $theme_name = $themes[$theme_id]['name'];
         include_once $CFG->progdir . '/lib/configassistant.class.php';
         $table = 'themes_areas_properties';
         $keyfield = 'theme_area_property_id';
         $prefix = '';
         $language_domain = 't_' . $theme_name;
         $where = array('area_id' => $area_id, 'theme_id' => $theme_id);
         $hidden_fields = array(array('type' => F_INTEGER, 'name' => 'dialog', 'value' => AREAMANAGER_DIALOG_EDIT_THEME, 'hidden' => TRUE));
         $assistant = new ConfigAssistant($table, $keyfield, $prefix, $language_domain, $where, $hidden_fields);
         if (!$assistant->save_data($this->output)) {
             $href = href($WAS_SCRIPT_NAME, $this->a_param(AREAMANAGER_CHORE_SAVE, $area_id));
             $assistant->show_dialog($this->output, $href);
             // since they blew it, we will not show the edit menu at this point;
             // user should concentrate on getting input data right (or use cancel)
         } else {
             $this->area_overview();
         }
     } elseif ($dialog == AREAMANAGER_DIALOG_EDIT) {
         $dialogdef = $this->get_dialogdef_edit_area($area_id);
         if (!dialog_validate($dialogdef)) {
             // 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_edit_area_header', 'admin') . '</h2>');
             $this->output->add_content(t('areamanager_edit_area_explanation', 'admin'));
             $href = href($WAS_SCRIPT_NAME, $this->a_param(AREAMANAGER_CHORE_SAVE, $area_id));
             $this->output->add_content(dialog_quickform($href, $dialogdef));
             // no edit menu, let user concentrate on task at hand ie errorfree data input
             return;
         }
         $now = strftime('%Y-%m-%d %T');
         $fields = array('mtime' => $now, 'muser_id' => $USER->user_id);
         $theme_id = 0;
         foreach ($dialogdef as $k => $item) {
             if (isset($item['name'])) {
                 switch ($item['name']) {
                     case 'area_title':
                         $fields['title'] = $item['value'];
                         break;
                         // This field should not be editable and thus should not be saved
                         //case 'area_is_private':
                         //    $fields['is_private'] = ($item['value'] == 1) ? TRUE : FALSE;
                         //    break;
                     // This field should not be editable and thus should not be saved
                     //case 'area_is_private':
                     //    $fields['is_private'] = ($item['value'] == 1) ? TRUE : FALSE;
                     //    break;
                     case 'area_is_active':
                         $fields['is_active'] = $item['value'] == 1 ? TRUE : FALSE;
                         break;
                     case 'area_theme_id':
                         $theme_id = intval($item['value']);
                         $fields['theme_id'] = $theme_id;
                         break;
                         // This field should not be editable and thus should not be saved
                         //case 'area_path':
                         //    $fields['path'] = $item['value'];
                         //    break;
                     // This field should not be editable and thus should not be saved
                     //case 'area_path':
                     //    $fields['path'] = $item['value'];
                     //    break;
                     case 'area_metadata':
                         $fields['metadata'] = $item['value'];
                         break;
                     case 'area_sort_order':
                         $fields['sort_order'] = intval($item['value']);
                         break;
                     default:
                         break;
                 }
             }
         }
         $where = array('area_id' => $area_id);
         $params = array('{AREA}' => $area_id, '{AREA_FULL_NAME}' => $fields['title']);
         if (db_update('areas', $fields, $where) === FALSE) {
             logger("areamanager: area data save failed for area '{$area_id}': " . db_errormessage());
             $this->output->add_message(t('areamanager_save_area_failure', 'admin', $params));
         } elseif (intval($areas[$area_id]['theme_id']) != $theme_id && $this->count_existing_theme_properties($area_id, $theme_id) <= 0) {
             // If the user changed the theme AND if there is no theme config yet, make sure there is one
             if ($this->reset_theme_defaults($area_id, $theme_id)) {
                 logger("areamanager: success saving area AND theme properties in area '{$area_id}', theme '{$theme_id}'", WLOG_DEBUG);
                 $this->output->add_message(t('areamanager_save_area_success', 'admin', $params));
             } else {
                 logger("areamanager: theme '{$theme_id}' data save failed for area '{$area_id}': " . db_errormessage());
                 $this->output->add_message(t('areamanager_save_area_failure', 'admin', $params));
             }
         } else {
             logger("areamanager: success saving changed properties in area '{$area_id}'", WLOG_DEBUG);
             $this->output->add_message(t('areamanager_save_area_success', 'admin', $params));
         }
         $areas = get_area_records(TRUE);
         // TRUE means force reread of area records
         $this->area_overview();
     } else {
         logger("areamanager: weird: invalid dialog '{$dialog}' in area_save (area={$area_id})", WLOG_DEBUG);
         $this->area_overview();
     }
 }
 function task_save_content()
 {
     global $USER;
     // 1A -- do we have a sane value for node_id?
     $node_id = get_parameter_int('node', 0);
     $anode = array('{NODE}' => strval($node_id));
     if ($node_id == 0 || !isset($this->tree[$node_id])) {
         // are they trying to trick us, specifying a node from another area?
         logger(__FUNCTION__ . "(): weird: user saves content of node '{$node_id}' working in area '{$this->area_id}'?");
         $this->output->add_message(t('invalid_node', 'admin', $anode));
         $this->task_treeview();
         return;
     }
     // 1B -- is it a page?
     if (!$this->tree[$node_id]['is_page']) {
         logger(__CLASS__ . ": weird: cannot save content of a section (section '{$node_id}')");
         $this->task_treeview();
         return;
     }
     // 2 -- are we allowed?
     if (!$this->permission_edit_node_content($node_id)) {
         $msg = t('task_edit_page_access_denied', 'admin', array('{NODE}' => $node_id));
         $this->output->add_message($msg);
         $this->output->add_popup_bottom($msg);
         $this->show_tree();
         $this->show_area_menu($this->area_id);
         return;
     }
     // 3 -- make certain we still have the lock
     $lockinfo = array();
     if (!lock_record_node($node_id, $lockinfo)) {
         // failed to get a lock, tell user about who DID obtain the lock + show tree again
         $is_page = TRUE;
         $msg = message_from_lockinfo($lockinfo, $node_id, $is_page);
         $this->output->add_message($msg);
         $this->output->add_popup_bottom($msg);
         $this->show_tree();
         $this->show_area_menu($this->area_id);
         return;
     }
     // 4 -- execute module save function
     $module_id = intval($this->tree[$node_id]['record']['module_id']);
     $viewonly = db_bool_is(TRUE, $this->tree[$node_id]['record']['is_readonly']);
     if ($this->module_save($node_id, $module_id, $viewonly, $edit_again)) {
         // success with save, bye now
         lock_release_node($node_id);
         $anode = array('{NODE_FULL_NAME}' => $this->node_full_name($node_id));
         $msg = t('page_saved', 'admin', $anode);
         $this->output->add_message($msg);
         $this->show_tree();
         $this->show_area_menu($this->area_id);
         $embargo = is_under_embargo($this->tree, $node_id);
         logger(sprintf(__CLASS__ . ": success saving content node '%d'%s", $node_id, $embargo ? ' (embargo)' : ''));
         if (!$embargo) {
             $nodes = $this->get_node_id_and_ancestors($node_id);
             $anode['{AREA}'] = $this->area_id;
             $message = t('page_content_edited', 'admin', $anode);
             $this->queue_area_node_alert($this->area_id, $nodes, $message, $USER->full_name);
         }
     } elseif ($edit_again) {
         if ($this->module_show_edit($node_id, $module_id, $viewonly, $edit_again)) {
             $this->output->set_funnel_mode(TRUE);
             // no distractions
             // Note that we also do NOT show the edit menu: we try to let the user concentrate
             // on the task at hand;  the only escape route is 'Cancel'...
             // Also note that we still have the record lock; that won't change because we
             // will be editing the page again. Cancel'ing will also release the lock.
         } else {
             lock_release_node($node_id);
             $anode = array('{NODE_FULL_NAME}' => $this->node_full_name($node_id));
             $msg = t('error_editing_node_content', 'admin', $anode);
             $this->output->add_message($msg);
             $this->output->add_popup_bottom($msg);
             $this->show_tree();
             $this->show_area_menu($this->area_id);
         }
     } else {
         // operation is cancelled
         lock_release_node($node_id);
         $this->output->add_message(t('cancelled', 'admin'));
         $this->show_tree();
         $this->show_area_menu($this->area_id);
     }
     return;
 }
/** add javascript code that implements a url selection (used in integration with CKEditor/FCKeditor)
 *
 * This adds a JavaScript-function to the currently generated output page
 * which takes care of returning a URL from a file/image/flash browser
 * to either the (older) FCKeditor or (newer) CKEditor. Since both editors
 * use the same filebrowsers we need to discriminate betweek FCKeditor and
 * CKEditor. This is done by looking at the parameters: the CKEditor provides
 * the number of an anonymous function in the parameter 'CKEditorFuncNum'.
 * If this parameter is set we use the (integer) value for the callback to
 * CKEditor. If it is not set we assume the old interface with FCKeditor.
 *
 * Note that our actual file browser is supposed to remember this parameter,
 * otherwise the file browser will assume FCKeditor after navigating to
 * another page within the file browser. See also {@link filemanager.class.php}
 * We remember the parameter via a session variable which is easier than
 * propagating this number by adding it to every link within the file browser. 
 * However, we do update this function number every time the parameter
 * 'CKEditorFuncNum' is specified, ie. on the first call to a file browser
 * from CKEditor, ie. whenerver the user starts browsing the server.
 *
 * @param object &$output collects the html output
 * @param string $m left margin for increased readability
 * @return void generated JavaScript-code added to HTML-headers
 */
function add_javascript_select_url_function(&$output, $m = '')
{
    $funcnum = get_parameter_int('CKEditorFuncNum');
    if (!is_null($funcnum)) {
        $_SESSION['CKEditorFuncNum'] = $funcnum;
    } elseif (isset($_SESSION['CKEditorFuncNum'])) {
        $funcnum = $_SESSION['CKEditorFuncNum'];
    }
    $javascript_code = array('<script type="text/javascript"><!--', '  function select_url(url) {', is_null($funcnum) ? '    window.opener.SetUrl(url);' : sprintf('    window.opener.CKEDITOR.tools.callFunction(%d, url);', $funcnum), '    window.close();', '  }', '  //--></script>');
    foreach ($javascript_code as $line) {
        $output->add_html_header($m . $line);
    }
    return;
}
/** 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.
 *
 * See also {@link mailpage_show_edit()} for the complications of having a single
 * routine to deal with two different dialogs.
 * If validation of dialog 1 fails, or storing the data doesn't work,
 * the flag $edit_again is set to TRUE and the return value is FALSE.
 * Validation and storage of data from dialog 2 _always_ returns $edit_again
 * TRUE because we want to return in dialog #1 after finishing dialog #2.
 *
 * 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). Note that this also only applies
 * to the main dialoag (dialog #1).
 *
 * 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 mailpage_save(&$output, $area_id, $node_id, $module, $viewonly, &$edit_again)
{
    global $USER;
    $node_id = intval($node_id);
    $addresses = mailpage_get_addresses($node_id);
    $sort_order = 10 * (1 + sizeof($addresses));
    // $addresses are always renumbered so this is the first largest sord_order
    $address_id = get_parameter_int('address', NULL);
    if (is_null($address_id)) {
        // main config needs to be saved
        $edit_again = FALSE;
        // assume we do NOT need to edit again
        // 1 -- bail out if cancelled or viewonly
        if (isset($_POST['button_cancel']) || $viewonly) {
            return FALSE;
        }
        // 2 -- redo if invalid data was submitted
        $dialogdef = mailpage_get_dialogdef_config($output, $viewonly, $node_id);
        if (!mailpage_dialog_validate($dialogdef, $node_id, $addresses)) {
            // there were errors, show them to the user and do it again
            foreach ($dialogdef as $k => $item) {
                if (isset($item['errors']) && $item['errors'] > 0) {
                    $output->add_message($item['error_messages']);
                }
            }
            $edit_again = TRUE;
            return FALSE;
        }
        // 3 -- actually save the settings
        $retval = TRUE;
        // assume success
        $now = strftime('%Y-%m-%d %T');
        $table = 'mailpages';
        $fields = array('header' => trim($dialogdef['header']['value']), 'introduction' => trim($dialogdef['introduction']['value']), 'message' => trim($dialogdef['message']['value']), 'mtime' => $now, 'muser_id' => $USER->user_id);
        $where = array('node_id' => $node_id);
        if (db_update($table, $fields, $where) === FALSE) {
            logger(sprintf('%s(): error saving config values: %s', __FUNCTION__, db_errormessage()));
            $edit_again = TRUE;
            $retval = FALSE;
            $output->add_message(t('error_saving_data', 'm_mailpage'));
        }
        return $retval;
    }
    //
    // At this point we need to either save a new record, update an existing record,
    // delete an existing record or simply cancel and return to the main config dialog.
    // The logic depends on the submit button that was used and the value of $address_id.
    //
    $dialogdef = mailpage_get_dialogdef_address($output, $viewonly, $node_id, $address_id, $sort_order);
    if (!dialog_validate($dialogdef, $node_id, $addresses)) {
        // there were errors, show them to the user and do it again
        foreach ($dialogdef as $k => $item) {
            if (isset($item['errors']) && $item['errors'] > 0) {
                $output->add_message($item['error_messages']);
            }
        }
        $edit_again = TRUE;
        return FALSE;
    }
    $edit_again = TRUE;
    // we abuse this flag to return to the main config dialog instead of page mgr
    if (isset($_POST['button_cancel']) || $viewonly) {
        return FALSE;
    }
    $table = 'mailpages_addresses';
    $fields = array('node_id' => $node_id, 'sort_order' => intval($dialogdef['sort_order']['value']), 'name' => trim($dialogdef['name']['value']), 'email' => trim($dialogdef['email']['value']), 'description' => trim($dialogdef['description']['value']), 'thankyou' => trim($dialogdef['thankyou']['value']));
    if ($address_id <= 0) {
        // new record needs to be saved.
        if (db_insert_into($table, $fields) === FALSE) {
            logger(sprintf('%s(): error adding address: %s', __FUNCTION__, db_errormessage()));
            $output->add_message(t('error_saving_data', 'm_mailpage'));
        }
    } elseif (isset($addresses[$address_id])) {
        // OK, that is an existing record
        $where = array('mailpage_address_id' => $address_id);
        if (isset($_POST['button_save'])) {
            // Go save the record
            if (db_update($table, $fields, $where) === FALSE) {
                logger(sprintf('%s(): error updating address: %s', __FUNCTION__, db_errormessage()));
                $output->add_message(t('error_saving_data', 'm_mailpage'));
            }
        } elseif (isset($_POST['button_delete'])) {
            // Go delete this record
            if (db_delete($table, $where) === FALSE) {
                logger(sprintf('%s(): error deleting address: %s', __FUNCTION__, db_errormessage()));
                $output->add_message(t('error_deleting_data', 'm_mailpage'));
            }
        }
    }
    return FALSE;
    // Dirty trick to return to the main config dialog
}
 /** show a dialog for modifying page manager permissions for a group/capacity
  *
  * @return void results are returned as output in $this->output
  * @uses $WAS_SCRIPT_NAME
  * @uses $CFG
  */
 function capacity_pagemanager()
 {
     global $WAS_SCRIPT_NAME, $CFG;
     $group_id = get_parameter_int('group', NULL);
     $capacity_code = get_parameter_int('capacity', NULL);
     // 0 -- sanity check
     if (!$this->valid_group_capacity($group_id, $capacity_code)) {
         $this->groups_overview();
         return;
     }
     // 1 -- maybe change the state of the open/closed areas
     if (!isset($_SESSION['aclmanager_open_areas'])) {
         $_SESSION['aclmanager_open_areas'] = FALSE;
         // default: everything is closed
     }
     $area_id = get_parameter_int('area', NULL);
     $_SESSION['aclmanager_open_areas'] = $this->areas_expand_collapse($_SESSION['aclmanager_open_areas'], $area_id);
     // 2 -- which acl to use?
     if (($acl_id = $this->calc_acl_id($group_id, $capacity_code)) === FALSE) {
         $this->capacity_overview();
         return;
     }
     //
     // 3A -- construct necessary parameters for dialog
     //
     $a_params = $this->a_params(TASK_GROUP_CAPACITY_SAVE, $group_id, $capacity_code);
     $limit = get_parameter_int('limit', $CFG->pagination_height);
     $offset = get_parameter_int('offset', 0);
     if ($limit != $CFG->pagination_height) {
         $a_params['limit'] = $limit;
     }
     if ($offset != 0) {
         $a_params['offset'] = $offset;
     }
     //
     // 3B -- setup Aclmanager to do the dirty work
     //
     include_once $CFG->progdir . '/lib/aclmanager.class.php';
     $acl = new AclManager($this->output, $acl_id, ACL_TYPE_PAGEMANAGER);
     $acl->set_action($a_params);
     $params = $this->get_group_capacity_names($group_id, $capacity_code);
     $acl->set_header(t('groupmanager_capacity_pagemanager_header', 'admin', $params));
     $acl->set_intro(t('groupmanager_capacity_pagemanager_explanation', 'admin', $params));
     $acl->set_dialog(GROUPMANAGER_DIALOG_CAPACITY_PAGEMANAGER);
     // Enable pagination for this one: the list of nodes can be very very long so split up in smaller screens.
     $a_params = $this->a_params(TASK_GROUP_CAPACITY_PAGEMANAGER, $group_id, $capacity_code);
     $acl->enable_pagination($a_params, $limit, $offset);
     // Also enable the expand/collapse feature
     $acl->enable_area_view($a_params, $_SESSION['aclmanager_open_areas']);
     //
     // 4 -- show dialog + menu
     //
     $acl->show_dialog();
     $this->show_menu_groupcapacity($group_id, $capacity_code, TASK_GROUP_CAPACITY_PAGEMANAGER);
 }
/** get the number of the area the user requested or null if not specified
 *
 * See discussion of {@link get_requested_node()}.
 *
 * @return int|null integer indicating the area or null if none specified
 */
function get_requested_area()
{
    return get_parameter_int('area', NULL);
}
 /** show a dialog for modifying page manager permissions for a user
  *
  * @return void results are returned as output in $this->output
  * @uses $WAS_SCRIPT_NAME
  * @uses $CFG
  */
 function user_pagemanager()
 {
     global $WAS_SCRIPT_NAME, $CFG;
     //
     // 0 -- sanity check
     //
     $user_id = get_parameter_int('user', NULL);
     if (is_null($user_id)) {
         logger("usermanager->user_pagemanager(): unspecified parameter user");
         $this->output->add_message(t('error_invalid_parameters', 'admin'));
         $this->users_overview();
         return;
     }
     //
     // 1 -- maybe change the state of the open/closed areas
     //
     if (!isset($_SESSION['aclmanager_open_areas'])) {
         $_SESSION['aclmanager_open_areas'] = FALSE;
         // default: everything is closed
     }
     $area_id = get_parameter_int('area', NULL);
     $_SESSION['aclmanager_open_areas'] = $this->areas_expand_collapse($_SESSION['aclmanager_open_areas'], $area_id);
     //
     // 2 -- which acl to use?
     //
     if (($acl_id = $this->calc_acl_id($user_id)) === FALSE) {
         $this->user_edit();
         return;
     }
     //
     // 3A -- construct necessary parameters for dialog
     //
     $related_acls = calc_user_related_acls($user_id);
     $a_params = $this->a_params(TASK_USER_SAVE, $user_id);
     $params = $this->get_user_names($user_id);
     $limit = get_parameter_int('limit', $CFG->pagination_height);
     $offset = get_parameter_int('offset', 0);
     if ($limit != $CFG->pagination_height) {
         $a_params['limit'] = $limit;
     }
     if ($offset != 0) {
         $a_params['offset'] = $offset;
     }
     //
     // 3B -- setup Aclmanager to do the dirty work
     //
     include_once $CFG->progdir . '/lib/aclmanager.class.php';
     $acl = new AclManager($this->output, $acl_id, ACL_TYPE_PAGEMANAGER);
     $acl->set_related_acls($related_acls);
     $acl->set_action($a_params);
     $acl->set_header(t('usermanager_pagemanager_header', 'admin', $params));
     $acl->set_intro(t('usermanager_pagemanager_explanation', 'admin', $params));
     $acl->set_dialog(USERMANAGER_DIALOG_PAGEMANAGER);
     // Enable pagination for this one: the list of nodes can be very very long so split up in smaller screens.
     $a_params = $this->a_params(TASK_USER_PAGEMANAGER, $user_id);
     $acl->enable_pagination($a_params, $limit, $offset);
     // Also enable the expand/collapse feature
     $acl->enable_area_view($a_params, $_SESSION['aclmanager_open_areas']);
     //
     // 4 -- show dialog + menu
     //
     $acl->show_dialog();
     $this->show_menu_user($user_id, TASK_USER_PAGEMANAGER);
 }
 /** task dispatcher
  *
  * this routine decides what to do and calls the appropriate workhorse routine(s)
  *
  * @return bool TRUE on success, FALSE otherwise
  * @todo check permissions (ACL) to prevent leaking a private area path to anonymous visitors?
  */
 function run()
 {
     global $CFG;
     $m = '      ';
     // 1 -- determine the directory path and other configuration information
     $this->get_snapshots_configuration($this->node_id);
     // 2A -- get a list of available files from $snapshots_path
     $this->snapshots = $this->get_snapshots($this->snapshots_path);
     $snapshots_count = sizeof($this->snapshots);
     // 2B -- if there are none we bail out but DO show the header+introduction
     if ($snapshots_count <= 0) {
         if (!empty($this->header)) {
             $this->theme->add_content($m . html_tag('h3', array('class' => 'snapshots_header'), $this->header));
         }
         if (!empty($this->introduction)) {
             $this->theme->add_content($m . html_tag('div', array('class' => 'snapshots_introduction'), $this->introduction));
         }
         $msg = t('no_snapshots_available', $this->domain);
         $this->theme->add_message($msg);
         $this->theme->add_content($m . '<h3>' . $msg . '</h3>');
         return TRUE;
     }
     // 3A -- get ready to do some real work
     $stylesheet = 'program/modules/snapshots/snapshots.css';
     $this->theme->add_stylesheet($stylesheet);
     $this->javascript_include_once('/modules/snapshots/slideshow.js');
     $this->javascript_add_img_array();
     // 3B -- what do they want?
     $snapshot_index = get_parameter_int('snapshot', NULL);
     if (!is_null($snapshot_index) && 0 < $snapshot_index && $snapshot_index <= $snapshots_count) {
         $retval = $this->view_snapshot($snapshot_index);
     } else {
         // if no specific image was specified, we allow the user to choose the variant,
         // while using the value from the database as a (sensible) default.
         $variant = get_parameter_int('variant', $this->variant);
         switch ($variant) {
             case 1:
                 $retval = $this->view_thumbnails();
                 break;
             case 2:
                 $retval = $this->view_snapshot(1);
                 break;
             case 3:
                 $retval = $this->view_slideshow();
                 break;
             default:
                 $retval = $this->view_thumbnails();
                 // shouldn't happen
                 break;
         }
     }
     return $retval;
 }