protected function runUntrustedAction($action) { switch ($action) { case 'backup': include_once 'HTTP/Download.php'; include_once 'Archive/Tar.php'; if (!$this->data_engine->dump(TIP::buildDataPath('dump'))) { TIP::notifyError('backup'); return false; } $tar_file = TIP::buildCachePath($this->id . '-' . TIP::formatDate('date_sql') . '.tar.gz'); $tar_object = new Archive_Tar($tar_file, 'gz'); $result = $tar_object->createModify(TIP::buildDataPath(), '', TIP::buildPath()); unset($tar_object); if ($result !== true) { return false; } HTTP_Download::staticSend(array('file' => $tar_file, 'contenttype' => 'application/x-gzip', 'contentdisposition' => HTTP_DOWNLOAD_ATTACHMENT)); exit; } return null; }
/** * Add database defaults to $this->_defaults */ private function _addDatabaseDefaults() { foreach ($this->fields as $id => &$field) { if (isset($field['default']) && $field['default'] != '' && !$field['automatic']) { $this->_defaults[$id] = $field['default']; } elseif (!$field['can_be_null']) { $widget = strtolower($field['widget']); switch ($widget) { case 'date': case 'datetime': $this->_defaults[$id] = TIP::formatDate('datetime_sql'); } } } }
/** * Overridable 'view' callback * * Called by actionView() before performing the 'view' action. * The default handler updates 'hits_field' and 'last_hit_field', if they * are present. * * @param array &$row The data row to view * @return bool true on success, false on errors */ public function _onView(&$row) { $old_row = $row; isset($this->last_hit_field) && array_key_exists($this->last_hit_field, $row) && ($row[$this->last_hit_field] = TIP::formatDate('datetime_sql')); isset($this->hits_field) && array_key_exists($this->hits_field, $row) && ++$row[$this->hits_field]; // Update user statistics, if the user module exists if (!is_null($user =& TIP_Application::getSharedModule('user'))) { $user->increment($this->user_statistic['_onView']); } return $this->data->updateRow($row, $old_row); }
/** * Perform a view action * * Runs the file identified by the 'view_template' property for the * specified row. The rendered result is appended to the page. * * @param mixed $id The identifier of the row to view * @return bool true on success or false on errors */ protected function actionView($id) { // The query is not strictly necessary but it is still performed // to avoid read actions on arbitrary files if (is_null($row =& $this->fromRow($id, false)) || !$this->_onView($row)) { return false; } // Check for html file existence $file = TIP::buildDataPath($this->id, $id); if (!is_readable($file)) { $this->endView(); return false; } $content =& TIP_Application::getGlobal('content'); $this->keys['id'] = $id; $this->keys[$this->title_field] = str_replace('.html', '', $id); $this->keys['content'] = file_get_contents($file); $this->keys[$this->creation_field] = TIP::formatDate('datetime_sql', filectime($file)); $this->keys[$this->edited_field] = TIP::formatDate('datetime_sql', filemtime($file)); if (empty($this->view_template)) { // On empty template, output the whole html file content // and set a viable "title" metatag $content .= $this->keys['content']; $title =& TIP_Application::getGlobal('title'); $title = $this->keys[$this->title_field] . ' (' . $title . ')'; } else { // Use a custom template $content .= $this->tagRun($this->view_template); } // Discard the generated content to decrease memory consumption unset($this->keys); $this->endView(); return true; }
/** * Format a datetime * * Converts a datetime (in SQL format) to a specified format. * * $params must be a string in the format '[date][,format]', where format * is any format allowed by the TIP::formatDate() method. If the date is * not specified, the current date is assumed. If the format is not * specified, it defaults to 'date'. * * @uses TIP::formatDate() The date formatter */ protected function tagDate($params) { @(list($date, $format) = explode(',', $params, 2)); empty($format) && ($format = 'date'); return empty($date) ? TIP::formatDate($format) : TIP::formatDate($format, $date, 'sql'); }
/** * Append a log * * Appends a log message to the data source of the logger object. * * @param string $severity The text of the log * @param string $message A custom message */ public function log($severity, $message) { static $running = false; // The running flag avoid recursive calls to log() if ($running) { return false; } else { $running = true; } // Generate the backtrace $bt = debug_backtrace(); // Carefully scans the backtrace to find useful informations // and store them in the $code array $code = array('origin' => '', 'tag' => '', 'action' => '', 'template' => '', 'data' => ''); foreach ($bt as $n => $trace) { $function = isset($trace['function']) ? strtolower($trace['function']) : ''; if (!isset($code['origin'])) { // Skip the log wrappers if ($function == 'log' || $function == 'warning' || $function == 'error' || $function == 'fatal') { continue; } $code['origin'] = "{$trace['file']} on line {$trace['line']}"; } if ($function == 'gettag') { if (!array_key_exists('tag', $code)) { $module = $trace['class']; $name = $trace['args'][0]; $params = $trace['args'][1]; if (strlen($params) > 80) { $params = substr($params, 0, 77) . '...'; } $code['tag'] = "{$module}::getTag({$name}, {$params})"; } continue; } elseif ($function == 'callaction') { if (!array_key_exists('action', $code)) { $module = $trace['class']; $action = $trace['args'][0]; $code['action'] = "{$module}::callAction({$action})"; } continue; } $class = isset($trace['class']) ? strtolower($trace['class']) : ''; if ($class == 'tip_template') { if (!array_key_exists('template', $code)) { $last =& $bt[$n - 1]; if (is_object($last['args'][0])) { $template =& $last['args'][0]; $method = $last['function']; $code['template'] = "{$template} on method {$method}"; } } continue; } elseif ($class == 'tip_data') { if (!array_key_exists('data', $code)) { $last =& $bt[$n - 1]; if (is_object($last['args'][0])) { $data =& $last['args'][0]; $method = $last['function']; $code['data'] = "{$data} on method {$method}"; } } continue; } } unset($bt); $context = array('user' => TIP::getUserId(), 'when' => TIP::formatDate('datetime_sql'), 'severity' => $severity, 'message' => $message); $this->_cache[] = array_merge($context, $code); $running = false; return true; }
/** * Destructor * * Updates the record of the current logged-in user, if any. */ function __destruct() { if (!is_array($this->_old_row) || !is_array($this->_row)) { return; } // Update statistic fields isset($this->hits_field) && array_key_exists($this->hits_field, $this->_row) && ++$this->_row[$this->hits_field]; isset($this->last_hit_field) && array_key_exists($this->last_hit_field, $this->_row) && ($this->_row[$this->last_hit_field] = TIP::formatDate('datetime_sql')); $this->data->updateRow($this->_row, $this->_old_row); }
/** * 'on_process' callback for flag actions * * Flags this row, that is set an enum "yes/no" field to "yes". * The flagging operation can be useful, for instance, for * signaling suspected content. * * @param array &$row The row to flag * @return bool true on success or false on errors */ public function _onFlag(&$old_row) { if (!isset($this->flag_field)) { // No flag field defined: silently returns true return true; } $flagger = TIP::getUserId(); $flagged = @$old_row[$this->owner_field]; $row[$this->flag_field] = 'yes'; if (isset($this->flagger_field)) { $row[$this->flagger_field] = $flagger; } if (isset($this->flagon_field)) { $row[$this->flagon_field] = TIP::formatDate('datetime_sql'); } if (!$this->data->updateRow($row, $old_row)) { return false; } $user = TIP_Application::getSharedModule('user'); if (!$user) { // User module not available: no statistic update required return true; } // Update statistics of the flagging user if (isset($flagger, $this->flaggee_field)) { $user->increment($this->flaggee_field); } // Update statistics of the flagged user if (isset($flagged, $this->flagged_field) && !is_null($view = $user->startDataView($user->getProperty('data')->rowFilter($flagged)))) { $row = $view->current(); $user->endView(); if (!is_null($row)) { $old_row = $row; ++$row[$this->flagged_field]; $user->getProperty('data')->updateRow($row, $old_row); } } return true; }