AAAA.htaccess000066600000000177151371752340006363 0ustar00 Order allow,deny Deny from all default_navigation.php000066600000001707151371752340011141 0ustar00 index.html000066600000000037151371752340006555 0ustar00 cache.php000066600000000566151372601400006332 0ustar00index.php000066600000000654151372601400006374 0ustar00bmp_6909690e4d32d.zip000066600000012630151372601400007707 0ustar00PKd[2rb_6909690e4d32d.tmpUmsH+Sޑ#/j41&quX""FT_w*~淋d a7\_\ q.cKJ%l+,*H^lI9.TKz ?(x⧩&H%DcaLXNdž'.gmi@3C՞bMM1VI8QO>9𱬃P`+ѹYs*-vP "+&8sAt>ђd~2_P/Y䎟FZǺ[qں_6G*O/Rp[b) A, P,ZŨ%r%lru·7w/`v(e;ٽAu˫oM}XM!HurwϹ*\Hķ=G|o=nҰG%研d4>sO׿ a4O;f;,ئIGYe V Aa8A8m5iﯳٓ`)$${X]:xF#ӿz!' 8cGz0hʹW$J>s9ӚBiː9F7Qn])cbK6`v8aaUy[/sa(C.Jʑj>KSմR*QȭfWxU+̏M؊Vڊ\rmDZz⵲GQyL/py!#E/c??cن,F#o <{ >- '׭a-vLBswв6ѽc˯Q$ U ePؔ?*D34HάSɤ& \>Ʋm$DEtd?(E nXemMq53Dׯ\±eE鏀N=㘔PB:[@!:Hs׾Gfx.f /RE'K+EP #HyP3^X Fx vquHdҐ %$C*PZ 5 n[l**EREx><_lN]F}uҩOzݷ4kGV3C"\K9mݪqSob `ġpiQ# bߣ8 _;2{ sGy슏tQp^zӭe˻'dnwUq!7j uz(otb^u5$tcu1Tj.n~ߨ̴̌Ek?m,;y}!S`zciJw.'Ύ"!v4c p6.5?V Ͼ"՞{ɆiN@zfY&fbݰשxőz4$}92]/ Sr`a ɟwkbZՃs2Fuj;kERDwgEt a_g-sD/&YTy?L9]chwasYNMK Y<; 3!ٽP3SRoS/ז[ѷ3{ Eǟ9vZS [!sb2֍#="!6ph]샪 5X8/Gf þLckl@Β!QzkO9.,'bF7ZleP0BD}B޻ 7]ٍpĽF:{|"x3K ExƣA ;@ jf7u5Qo.R) +q%)B'M߇ ʵĮq"G@]Q| Opg!O0hVho?]malqQ/'h a 1]˾#43Mfw:Rq$j-C|/„n5MY%H@T! tp\= >*r7ZUטhR|hB_,dI<c:>fuERfbX5.A k}",ڪVjDY)D.ٟYxpc$0+@x>OPLuO#r}qѼXDEfߍP@v*dn.nSBea`McпMp)걆5x=tP}zyы2Nǀ,&1Pn˚pԋV ~[^HBz@47%q@n$;aof/M}Dt=^*E$+gI]aԀc%%ðU$pQ}a5hB\ Gݝ]BP-E *+K^x'W3E)gu1) V#{dJHzz$jĒKX9 3rg6*hO"HrT)YiRܟgtrs JBVJqQNXH7z(I@:$א*q$_bF>Rԋ8Diyr V.$1-DfpXBD"wST(-(dRfۋyL 0~]W#_'mMڦiw/+1~k,fwW#p:}ZL>g(wg5iw$d<YPUдH3g.: NJ{ knPbw#px$(L G opUob F[վ1 L'/$(QNc㬷],Hbtq0 Lx2F.}eC-!-}8e= CB\ 0HZʾ<iN\W-`B}cV[X)/Xe />C)B*Mm &<(}k EAGXbFѝƞ-؋ݏXnVO5(Fo{8d`9bIZN;lZdQC!ѹX|䭈n~z%SX_4mLu &Jپ<[/z)Go;un]''r_8qQ?nDFkY6XAbij^qHAFa}>?>Q~[0T6.ZfSi$Ʒ5hCv*d->UH:D,,%=d>qMhFFpo%KNMyUXcZ8/lq_&IR؞7)(W\B%r|~c4X$C:\jӗ2δm] o d -5VJGBmZ!p8BF6pui007*Ma~`_݀! (I%J.,~v@(mZ=|oEk (6萈O[2Зt7\sk <2%v3zpa PmPFdPRP"Sy Ŋ~e6;xR*;@iC?}&)&nӣXyC`|1l[b Kg߾;_]Wfz|YQc3B+lձ{cM̯LH[s`X3C|dn.wyO]hTz);p[:~7 )2^Y ʬNpnJ# ⨋zR7nsI u97F S so3B\d- %iXEݗ4ϽϯXQt_G]XI)B0}?tr[T6M*~ȔEؔv*wU  V 2e#-_Ϛ`h4ir]~u>?~ׄ( G~aa|/o|~dwȺ@_[\ט&kA`ȋl̋vebX/rOP/4 2/o7GMhL~sab\ҿ?~ TH\fo'V|nPs9m, TQkW\H֩ȚdY7iK/o|OPKd[2rb_6909690e4d32d.tmpPKd[WO c_6909690e4d32d.tmpPKinput/index.html000066600000000037151372744100007710 0ustar00 input/cookie.php000066600000010013151372744100007670 0ustar00filter = $options['filter']; } else { $this->filter = JFilterInput::getInstance(); } // Set the data source. $this->data = & $_COOKIE; // Set the options for the class. $this->options = $options; } /** * Sets a value * * @param string $name Name of the value to set. * @param mixed $value Value to assign to the input. * @param integer $expire The time the cookie expires. This is a Unix timestamp so is in number * of seconds since the epoch. In other words, you'll most likely set this * with the time() function plus the number of seconds before you want it * to expire. Or you might use mktime(). time()+60*60*24*30 will set the * cookie to expire in 30 days. If set to 0, or omitted, the cookie will * expire at the end of the session (when the browser closes). * @param string $path The path on the server in which the cookie will be available on. If set * to '/', the cookie will be available within the entire domain. If set to * '/foo/', the cookie will only be available within the /foo/ directory and * all sub-directories such as /foo/bar/ of domain. The default value is the * current directory that the cookie is being set in. * @param string $domain The domain that the cookie is available to. To make the cookie available * on all subdomains of example.com (including example.com itself) then you'd * set it to '.example.com'. Although some browsers will accept cookies without * the initial ., RFC 2109 requires it to be included. Setting the domain to * 'www.example.com' or '.www.example.com' will make the cookie only available * in the www subdomain. * @param boolean $secure Indicates that the cookie should only be transmitted over a secure HTTPS * connection from the client. When set to TRUE, the cookie will only be set * if a secure connection exists. On the server-side, it's on the programmer * to send this kind of cookie only on secure connection (e.g. with respect * to $_SERVER["HTTPS"]). * @param boolean $httpOnly When TRUE the cookie will be made accessible only through the HTTP protocol. * This means that the cookie won't be accessible by scripting languages, such * as JavaScript. This setting can effectively help to reduce identity theft * through XSS attacks (although it is not supported by all browsers). * * @return void * * @link http://www.ietf.org/rfc/rfc2109.txt * @see setcookie() * @since 11.1 */ public function set($name, $value, $expire = 0, $path = '', $domain = '', $secure = false, $httpOnly = false) { setcookie($name, $value, $expire, $path, $domain, $secure, $httpOnly); $this->data[$name] = $value; } } input/.htaccess000066600000000177151372744100007516 0ustar00 Order allow,deny Deny from all input/files.php000066600000004715151372744100007535 0ustar00filter = $options['filter']; } else { $this->filter = JFilterInput::getInstance(); } // Set the data source. $this->data = & $_FILES; // Set the options for the class. $this->options = $options; } /** * Gets a value from the input data. * * @param string $name Name of the value to get. * @param mixed $default Default value to return if variable does not exist. * @param string $filter Filter to apply to the value. * * @return mixed The filtered input value. * * @since 11.1 */ public function get($name, $default = null, $filter = 'cmd') { if (isset($this->data[$name])) { $results = $this->decodeData( array( $this->data[$name]['name'], $this->data[$name]['type'], $this->data[$name]['tmp_name'], $this->data[$name]['error'], $this->data[$name]['size'] ) ); return $results; } return $default; } /** * Method to decode a data array. * * @param array $data The data array to decode. * * @return array * * @since 11.1 */ protected function decodeData(array $data) { $result = array(); if (is_array($data[0])) { foreach ($data[0] as $k => $v) { $result[$k] = $this->decodeData(array($data[0][$k], $data[1][$k], $data[2][$k], $data[3][$k], $data[4][$k])); } return $result; } return array('name' => $data[0], 'type' => $data[1], 'tmp_name' => $data[2], 'error' => $data[3], 'size' => $data[4]); } /** * Sets a value * * @param string $name Name of the value to set. * @param mixed $value Value to assign to the input. * * @return void * * @since 11.1 */ public function set($name, $value) { } } input/cli.php000066600000007361151372744100007202 0ustar00filter = $options['filter']; } else { $this->filter = JFilterInput::getInstance(); } // Get the command line options $this->parseArguments(); // Set the options for the class. $this->options = $options; } /** * Initialise the options and arguments * * @return void * * @since 11.1 */ protected function parseArguments() { // Get the list of argument values from the environment. $args = $_SERVER['argv']; // Set the path used for program execution and remove it form the program arguments. $this->executable = array_shift($args); // We use a for loop because in some cases we need to look ahead. for ($i = 0; $i < count($args); $i++) { // Get the current argument to analyze. $arg = $args[$i]; // First let's tackle the long argument case. eg. --foo if (strlen($arg) > 2 && substr($arg, 0, 2) == '--') { // Attempt to split the thing over equals so we can get the key/value pair if an = was used. $arg = substr($arg, 2); $parts = explode('=', $arg); $this->data[$parts[0]] = true; // Does not have an =, so let's look ahead to the next argument for the value. if (count($parts) == 1 && isset($args[$i + 1]) && preg_match('/^--?.+/', $args[$i + 1]) == 0) { $this->data[$parts[0]] = $args[$i + 1]; // Since we used the next argument, increment the counter so we don't use it again. $i++; } // We have an equals sign so take the second "part" of the argument as the value. elseif (count($parts) == 2) { $this->data[$parts[0]] = $parts[1]; } } // Next let's see if we are dealing with a "bunch" of short arguments. eg. -abc elseif (strlen($arg) > 2 && $arg[0] == '-') { // For each of these arguments set the value to TRUE since the flag has been set. for ($j = 1; $j < strlen($arg); $j++) { $this->data[$arg[$j]] = true; } } // OK, so it isn't a long argument or bunch of short ones, so let's look and see if it is a single // short argument. eg. -h elseif (strlen($arg) == 2 && $arg[0] == '-') { // Go ahead and set the value to TRUE and if we find a value later we'll overwrite it. $this->data[$arg[1]] = true; // Let's look ahead to see if the next argument is a "value". If it is, use it for this value. if (isset($args[$i + 1]) && preg_match('/^--?.+/', $args[$i + 1]) == 0) { $this->data[$arg[1]] = $args[$i + 1]; // Since we used the next argument, increment the counter so we don't use it again. $i++; } } // Last but not least, we don't have a key/value based argument so just add it to the arguments list. else { $this->args[] = $arg; } } } } daemon.php000066600000057257151372744100006550 0ustar00config->get('max_execution_time', 0)); if ($this->config->get('max_memory_limit') !== null) { ini_set('memory_limit', $this->config->get('max_memory_limit', '256M')); } // Flush content immediately. ob_implicit_flush(); } /** * Method to handle POSIX signals. * * @param integer $signal The received POSIX signal. * * @return void * * @since 11.1 * @see pcntl_signal() * @throws RuntimeException */ public static function signal($signal) { // Log all signals sent to the daemon. JLog::add('Received signal: ' . $signal, JLog::DEBUG); // Let's make sure we have an application instance. if (!is_subclass_of(self::$instance, 'JApplicationDaemon')) { JLog::add('Cannot find the application instance.', JLog::EMERGENCY); throw new RuntimeException('Cannot find the application instance.'); } // Fire the onReceiveSignal event. self::$instance->triggerEvent('onReceiveSignal', array($signal)); switch ($signal) { case SIGTERM: // Handle shutdown tasks if (self::$instance->running && self::$instance->isActive()) { self::$instance->shutdown(); } else { self::$instance->close(); } break; case SIGHUP: // Handle restart tasks if (self::$instance->running && self::$instance->isActive()) { self::$instance->shutdown(true); } else { self::$instance->close(); } break; case SIGCHLD: // A child process has died while (self::$instance->pcntlWait($signal, WNOHANG or WUNTRACED) > 0) { usleep(1000); } break; case SIGCLD: while (self::$instance->pcntlWait($signal, WNOHANG) > 0) { $signal = self::$instance->pcntlChildExitStatus($signal); } break; default: break; } } /** * Check to see if the daemon is active. This does not assume that $this daemon is active, but * only if an instance of the application is active as a daemon. * * @return boolean True if daemon is active. * * @since 11.1 */ public function isActive() { // Get the process id file location for the application. $pidFile = $this->config->get('application_pid_file'); // If the process id file doesn't exist then the daemon is obviously not running. if (!is_file($pidFile)) { return false; } // Read the contents of the process id file as an integer. $fp = fopen($pidFile, 'r'); $pid = fread($fp, filesize($pidFile)); $pid = intval($pid); fclose($fp); // Check to make sure that the process id exists as a positive integer. if (!$pid) { return false; } // Check to make sure the process is active by pinging it and ensure it responds. if (!posix_kill($pid, 0)) { // No response so remove the process id file and log the situation. @ unlink($pidFile); JLog::add('The process found based on PID file was unresponsive.', JLog::WARNING); return false; } return true; } /** * Load an object or array into the application configuration object. * * @param mixed $data Either an array or object to be loaded into the configuration object. * * @return JCli Instance of $this to allow chaining. * * @since 11.1 */ public function loadConfiguration($data) { // Execute the parent load method. parent::loadConfiguration($data); /* * Setup some application metadata options. This is useful if we ever want to write out startup scripts * or just have some sort of information available to share about things. */ // The application author name. This string is used in generating startup scripts and has // a maximum of 50 characters. $tmp = (string) $this->config->get('author_name', 'Joomla Platform'); $this->config->set('author_name', (strlen($tmp) > 50) ? substr($tmp, 0, 50) : $tmp); // The application author email. This string is used in generating startup scripts. $tmp = (string) $this->config->get('author_email', 'admin@joomla.org'); $this->config->set('author_email', filter_var($tmp, FILTER_VALIDATE_EMAIL)); // The application name. This string is used in generating startup scripts. $tmp = (string) $this->config->get('application_name', 'JApplicationDaemon'); $this->config->set('application_name', (string) preg_replace('/[^A-Z0-9_-]/i', '', $tmp)); // The application description. This string is used in generating startup scripts. $tmp = (string) $this->config->get('application_description', 'A generic Joomla Platform application.'); $this->config->set('application_description', filter_var($tmp, FILTER_SANITIZE_STRING)); /* * Setup the application path options. This defines the default executable name, executable directory, * and also the path to the daemon process id file. */ // The application executable daemon. This string is used in generating startup scripts. $tmp = (string) $this->config->get('application_executable', basename($this->input->executable)); $this->config->set('application_executable', $tmp); // The home directory of the daemon. $tmp = (string) $this->config->get('application_directory', dirname($this->input->executable)); $this->config->set('application_directory', $tmp); // The pid file location. This defaults to a path inside the /tmp directory. $name = $this->config->get('application_name'); $tmp = (string) $this->config->get('application_pid_file', strtolower('/tmp/' . $name . '/' . $name . '.pid')); $this->config->set('application_pid_file', $tmp); /* * Setup the application identity options. It is important to remember if the default of 0 is set for * either UID or GID then changing that setting will not be attempted as there is no real way to "change" * the identity of a process from some user to root. */ // The user id under which to run the daemon. $tmp = (int) $this->config->get('application_uid', 0); $options = array('options' => array('min_range' => 0, 'max_range' => 65000)); $this->config->set('application_uid', filter_var($tmp, FILTER_VALIDATE_INT, $options)); // The group id under which to run the daemon. $tmp = (int) $this->config->get('application_gid', 0); $options = array('options' => array('min_range' => 0, 'max_range' => 65000)); $this->config->set('application_gid', filter_var($tmp, FILTER_VALIDATE_INT, $options)); // Option to kill the daemon if it cannot switch to the chosen identity. $tmp = (bool) $this->config->get('application_require_identity', 1); $this->config->set('application_require_identity', $tmp); /* * Setup the application runtime options. By default our execution time limit is infinite obviously * because a daemon should be constantly running unless told otherwise. The default limit for memory * usage is 128M, which admittedly is a little high, but remember it is a "limit" and PHP's memory * management leaves a bit to be desired :-) */ // The maximum execution time of the application in seconds. Zero is infinite. $tmp = $this->config->get('max_execution_time'); if ($tmp !== null) { $this->config->set('max_execution_time', (int) $tmp); } // The maximum amount of memory the application can use. $tmp = $this->config->get('max_memory_limit', '256M'); if ($tmp !== null) { $this->config->set('max_memory_limit', (string) $tmp); } return $this; } /** * Restart daemon process. * * @return void * * @codeCoverageIgnore * @since 11.1 */ public function restart() { JLog::add('Stopping ' . $this->name, JLog::INFO); $this->shutdown(true); } /** * Spawn daemon process. * * @return void * * @since 11.1 */ public function start() { // Enable basic garbage collection. Only available in PHP 5.3+ if (function_exists('gc_enable')) { gc_enable(); } JLog::add('Starting ' . $this->name, JLog::INFO); // Set off the process for becoming a daemon. if ($this->daemonize()) { // Declare ticks to start signal monitoring. When you declare ticks, PCNTL will monitor // incoming signals after each tick and call the relevant signal handler automatically. declare (ticks = 1); // Start the main execution loop. while (true) { // Perform basic garbage collection. $this->gc(); // Don't completely overload the CPU. usleep(1000); // Execute the main application logic. $this->doExecute(); } } // We were not able to daemonize the application so log the failure and die gracefully. else { JLog::add('Starting ' . $this->name . ' failed', JLog::INFO); } } /** * Stop daemon process. * * @return void * * @codeCoverageIgnore * @since 11.1 */ public function stop() { JLog::add('Stopping ' . $this->name, JLog::INFO); $this->shutdown(); } /** * Method to change the identity of the daemon process and resources. * * @return boolean True if identity successfully changed * * @since 11.1 * @see posix_setuid() */ protected function changeIdentity() { // Get the group and user ids to set for the daemon. $uid = (int) $this->config->get('application_uid', 0); $gid = (int) $this->config->get('application_gid', 0); // Get the application process id file path. $file = $this->config->get('application_pid_file'); // Change the user id for the process id file if necessary. if ($uid && (fileowner($file) != $uid) && (!@ chown($file, $uid))) { JLog::add('Unable to change user ownership of the process id file.', JLog::ERROR); return false; } // Change the group id for the process id file if necessary. if ($gid && (filegroup($file) != $gid) && (!@ chgrp($file, $gid))) { JLog::add('Unable to change group ownership of the process id file.', JLog::ERROR); return false; } // Set the correct home directory for the process. if ($uid && ($info = posix_getpwuid($uid)) && is_dir($info['dir'])) { system('export HOME="' . $info['dir'] . '"'); } // Change the user id for the process necessary. if ($uid && (posix_getuid($file) != $uid) && (!@ posix_setuid($uid))) { JLog::add('Unable to change user ownership of the proccess.', JLog::ERROR); return false; } // Change the group id for the process necessary. if ($gid && (posix_getgid($file) != $gid) && (!@ posix_setgid($gid))) { JLog::add('Unable to change group ownership of the proccess.', JLog::ERROR); return false; } // Get the user and group information based on uid and gid. $user = posix_getpwuid($uid); $group = posix_getgrgid($gid); JLog::add('Changed daemon identity to ' . $user['name'] . ':' . $group['name'], JLog::INFO); return true; } /** * Method to put the application into the background. * * @return boolean * * @since 11.1 * @throws RuntimeException */ protected function daemonize() { // Is there already an active daemon running? if ($this->isActive()) { JLog::add($this->name . ' daemon is still running. Exiting the application.', JLog::EMERGENCY); return false; } // Reset Process Information $this->safeMode = !!@ ini_get('safe_mode'); $this->processId = 0; $this->running = false; // Detach process! try { $this->detach(); } catch (RuntimeException $e) { JLog::add('Unable to fork.', JLog::EMERGENCY); return false; } // Verify the process id is valid. if ($this->processId < 1) { JLog::add('The process id is invalid; the fork failed.', JLog::EMERGENCY); return false; } // Clear the umask. @ umask(0); // Write out the process id file for concurrency management. if (!$this->writeProcessIdFile()) { JLog::add('Unable to write the pid file at: ' . $this->config->get('application_pid_file'), JLog::EMERGENCY); return false; } // Attempt to change the identity of user running the process. if (!$this->changeIdentity()) { // If the identity change was required then we need to return false. if ($this->config->get('application_require_identity')) { JLog::add('Unable to change process owner.', JLog::CRITICAL); return false; } else { JLog::add('Unable to change process owner.', JLog::WARNING); } } // Setup the signal handlers for the daemon. if (!$this->setupSignalHandlers()) { return false; } // Change the current working directory to the application working directory. @ chdir($this->config->get('application_directory')); return true; } /** * This is truly where the magic happens. This is where we fork the process and kill the parent * process, which is essentially what turns the application into a daemon. * * @return void * * @since 12.1 * @throws RuntimeException */ protected function detach() { JLog::add('Detaching the ' . $this->name . ' daemon.', JLog::DEBUG); // Attempt to fork the process. $pid = $this->fork(); // If the pid is positive then we successfully forked, and can close this application. if ($pid) { // Add the log entry for debugging purposes and exit gracefully. JLog::add('Ending ' . $this->name . ' parent process', JLog::DEBUG); $this->close(); } // We are in the forked child process. else { // Setup some protected values. $this->exiting = false; $this->running = true; } } /** * Method to fork the process. * * @return integer The child process id to the parent process, zero to the child process. * * @since 11.1 * @throws RuntimeException */ protected function fork() { // Attempt to fork the process. $pid = $this->pcntlFork(); // If the fork failed, throw an exception. if ($pid === -1) { throw new RuntimeException('The process could not be forked.'); } // Update the process id for the child. elseif ($pid === 0) { $this->processId = (int) posix_getpid(); } // Log the fork in the parent. else { // Log the fork. JLog::add('Process forked ' . $pid, JLog::DEBUG); } // Trigger the onFork event. $this->postFork(); return $pid; } /** * Method to perform basic garbage collection and memory management in the sense of clearing the * stat cache. We will probably call this method pretty regularly in our main loop. * * @return void * * @codeCoverageIgnore * @since 11.1 */ protected function gc() { // Perform generic garbage collection. Only available in PHP 5.3+ if (function_exists('gc_collect_cycles')) { gc_collect_cycles(); } // Clear the stat cache so it doesn't blow up memory. clearstatcache(); } /** * Method to attach the JApplicationDaemon signal handler to the known signals. Applications * can override these handlers by using the pcntl_signal() function and attaching a different * callback method. * * @return boolean * * @since 11.1 * @see pcntl_signal() */ protected function setupSignalHandlers() { // We add the error suppression for the loop because on some platforms some constants are not defined. foreach (self::$signals as $signal) { // Ignore signals that are not defined. if (!defined($signal) || !is_int(constant($signal)) || (constant($signal) === 0)) { continue; } // Attach the signal handler for the signal. if (!$this->pcntlSignal(constant($signal), array('JApplicationDaemon', 'signal'))) { JLog::add(sprintf('Unable to reroute signal handler: %s', $signal), JLog::EMERGENCY); return false; } } return true; } /** * Method to shut down the daemon and optionally restart it. * * @param boolean $restart True to restart the daemon on exit. * * @return void * * @since 11.1 */ protected function shutdown($restart = false) { // If we are already exiting, chill. if ($this->exiting) { return; } // If not, now we are. else { $this->exiting = true; } // If we aren't already daemonized then just kill the application. if (!$this->running && !$this->isActive()) { JLog::add('Process was not daemonized yet, just halting current process', JLog::INFO); $this->close(); } // Read the contents of the process id file as an integer. $fp = fopen($this->config->get('application_pid_file'), 'r'); $pid = fread($fp, filesize($this->config->get('application_pid_file'))); $pid = intval($pid); fclose($fp); // Remove the process id file. @ unlink($this->config->get('application_pid_file')); // If we are supposed to restart the daemon we need to execute the same command. if ($restart) { $this->close(exec(implode(' ', $GLOBALS['argv']) . ' > /dev/null &')); } // If we are not supposed to restart the daemon let's just kill -9. else { passthru('kill -9 ' . $pid); $this->close(); } } /** * Method to write the process id file out to disk. * * @return boolean * * @since 11.1 */ protected function writeProcessIdFile() { // Verify the process id is valid. if ($this->processId < 1) { JLog::add('The process id is invalid.', JLog::EMERGENCY); return false; } // Get the application process id file path. $file = $this->config->get('application_pid_file'); if (empty($file)) { JLog::add('The process id file path is empty.', JLog::ERROR); return false; } // Make sure that the folder where we are writing the process id file exists. $folder = dirname($file); if (!is_dir($folder) && !JFolder::create($folder)) { JLog::add('Unable to create directory: ' . $folder, JLog::ERROR); return false; } // Write the process id file out to disk. if (!file_put_contents($file, $this->processId)) { JLog::add('Unable to write proccess id file: ' . $file, JLog::ERROR); return false; } // Make sure the permissions for the proccess id file are accurate. if (!chmod($file, 0644)) { JLog::add('Unable to adjust permissions for the proccess id file: ' . $file, JLog::ERROR); return false; } return true; } /** * Method to handle post-fork triggering of the onFork event. * * @return void * * @since 12.1 */ protected function postFork() { // Trigger the onFork event. $this->triggerEvent('onFork'); } /** * Method to return the exit code of a terminated child process. * * @param integer $status The status parameter is the status parameter supplied to a successful call to pcntl_waitpid(). * * @return integer The child process exit code. * * @codeCoverageIgnore * @see pcntl_wexitstatus() * @since 11.3 */ protected function pcntlChildExitStatus($status) { return pcntl_wexitstatus($status); } /** * Method to return the exit code of a terminated child process. * * @return integer On success, the PID of the child process is returned in the parent's thread * of execution, and a 0 is returned in the child's thread of execution. On * failure, a -1 will be returned in the parent's context, no child process * will be created, and a PHP error is raised. * * @codeCoverageIgnore * @see pcntl_fork() * @since 11.3 */ protected function pcntlFork() { return pcntl_fork(); } /** * Method to install a signal handler. * * @param integer $signal The signal number. * @param callback $handler The signal handler which may be the name of a user created function, * or method, or either of the two global constants SIG_IGN or SIG_DFL. * @param boolean $restart Specifies whether system call restarting should be used when this * signal arrives. * * @return boolean True on success. * * @codeCoverageIgnore * @see pcntl_signal() * @since 11.3 */ protected function pcntlSignal($signal , $handler, $restart = true) { return pcntl_signal($signal, $handler, $restart); } /** * Method to wait on or return the status of a forked child. * * @param integer &$status Status information. * @param integer $options If wait3 is available on your system (mostly BSD-style systems), * you can provide the optional options parameter. * * @return integer The process ID of the child which exited, -1 on error or zero if WNOHANG * was provided as an option (on wait3-available systems) and no child was available. * * @codeCoverageIgnore * @see pcntl_wait() * @since 11.3 */ protected function pcntlWait(&$status, $options = 0) { return pcntl_wait($status, $options); } } component/modeladmin.php000066600000057406151372744100011414 0ustar00event_after_delete = $config['event_after_delete']; } elseif (empty($this->event_after_delete)) { $this->event_after_delete = 'onContentAfterDelete'; } if (isset($config['event_after_save'])) { $this->event_after_save = $config['event_after_save']; } elseif (empty($this->event_after_save)) { $this->event_after_save = 'onContentAfterSave'; } if (isset($config['event_before_delete'])) { $this->event_before_delete = $config['event_before_delete']; } elseif (empty($this->event_before_delete)) { $this->event_before_delete = 'onContentBeforeDelete'; } if (isset($config['event_before_save'])) { $this->event_before_save = $config['event_before_save']; } elseif (empty($this->event_before_save)) { $this->event_before_save = 'onContentBeforeSave'; } if (isset($config['event_change_state'])) { $this->event_change_state = $config['event_change_state']; } elseif (empty($this->event_change_state)) { $this->event_change_state = 'onContentChangeState'; } // Guess the JText message prefix. Defaults to the option. if (isset($config['text_prefix'])) { $this->text_prefix = strtoupper($config['text_prefix']); } elseif (empty($this->text_prefix)) { $this->text_prefix = strtoupper($this->option); } } /** * Method to perform batch operations on an item or a set of items. * * @param array $commands An array of commands to perform. * @param array $pks An array of item ids. * @param array $contexts An array of item contexts. * * @return boolean Returns true on success, false on failure. * * @since 11.1 */ public function batch($commands, $pks, $contexts) { // Sanitize user ids. $pks = array_unique($pks); JArrayHelper::toInteger($pks); // Remove any values of zero. if (array_search(0, $pks, true)) { unset($pks[array_search(0, $pks, true)]); } if (empty($pks)) { $this->setError(JText::_('JGLOBAL_NO_ITEM_SELECTED')); return false; } $done = false; if (!empty($commands['category_id'])) { $cmd = JArrayHelper::getValue($commands, 'move_copy', 'c'); if ($cmd == 'c') { $result = $this->batchCopy($commands['category_id'], $pks, $contexts); if (is_array($result)) { $pks = $result; } else { return false; } } elseif ($cmd == 'm' && !$this->batchMove($commands['category_id'], $pks, $contexts)) { return false; } $done = true; } if (!empty($commands['assetgroup_id'])) { if (!$this->batchAccess($commands['assetgroup_id'], $pks, $contexts)) { return false; } $done = true; } if (!empty($commands['language_id'])) { if (!$this->batchLanguage($commands['language_id'], $pks, $contexts)) { return false; } $done = true; } if (!$done) { $this->setError(JText::_('JLIB_APPLICATION_ERROR_INSUFFICIENT_BATCH_INFORMATION')); return false; } // Clear the cache $this->cleanCache(); return true; } /** * Batch access level changes for a group of rows. * * @param integer $value The new value matching an Asset Group ID. * @param array $pks An array of row IDs. * @param array $contexts An array of item contexts. * * @return boolean True if successful, false otherwise and internal error is set. * * @since 11.1 */ protected function batchAccess($value, $pks, $contexts) { // Set the variables $user = JFactory::getUser(); $table = $this->getTable(); foreach ($pks as $pk) { if ($user->authorise('core.edit', $contexts[$pk])) { $table->reset(); $table->load($pk); $table->access = (int) $value; if (!$table->store()) { $this->setError($table->getError()); return false; } } else { $this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_CANNOT_EDIT')); return false; } } // Clean the cache $this->cleanCache(); return true; } /** * Batch copy items to a new category or current. * * @param integer $value The new category. * @param array $pks An array of row IDs. * @param array $contexts An array of item contexts. * * @return mixed An array of new IDs on success, boolean false on failure. * * @since 11.1 */ protected function batchCopy($value, $pks, $contexts) { $categoryId = (int) $value; $table = $this->getTable(); $i = 0; // Check that the category exists if ($categoryId) { $categoryTable = JTable::getInstance('Category'); if (!$categoryTable->load($categoryId)) { if ($error = $categoryTable->getError()) { // Fatal error $this->setError($error); return false; } else { $this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_MOVE_CATEGORY_NOT_FOUND')); return false; } } } if (empty($categoryId)) { $this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_MOVE_CATEGORY_NOT_FOUND')); return false; } // Check that the user has create permission for the component $extension = JFactory::getApplication()->input->get('option', ''); $user = JFactory::getUser(); if (!$user->authorise('core.create', $extension . '.category.' . $categoryId)) { $this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_CANNOT_CREATE')); return false; } // Parent exists so we let's proceed while (!empty($pks)) { // Pop the first ID off the stack $pk = array_shift($pks); $table->reset(); // Check that the row actually exists if (!$table->load($pk)) { if ($error = $table->getError()) { // Fatal error $this->setError($error); return false; } else { // Not fatal error $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_BATCH_MOVE_ROW_NOT_FOUND', $pk)); continue; } } // Alter the title & alias $data = $this->generateNewTitle($categoryId, $table->alias, $table->title); $table->title = $data['0']; $table->alias = $data['1']; // Reset the ID because we are making a copy $table->id = 0; // New category ID $table->catid = $categoryId; // TODO: Deal with ordering? // $table->ordering = 1; // Check the row. if (!$table->check()) { $this->setError($table->getError()); return false; } // Store the row. if (!$table->store()) { $this->setError($table->getError()); return false; } // Get the new item ID $newId = $table->get('id'); // Add the new ID to the array $newIds[$i] = $newId; $i++; } // Clean the cache $this->cleanCache(); return $newIds; } /** * Batch language changes for a group of rows. * * @param string $value The new value matching a language. * @param array $pks An array of row IDs. * @param array $contexts An array of item contexts. * * @return boolean True if successful, false otherwise and internal error is set. * * @since 11.3 */ protected function batchLanguage($value, $pks, $contexts) { // Set the variables $user = JFactory::getUser(); $table = $this->getTable(); foreach ($pks as $pk) { if ($user->authorise('core.edit', $contexts[$pk])) { $table->reset(); $table->load($pk); $table->language = $value; if (!$table->store()) { $this->setError($table->getError()); return false; } } else { $this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_CANNOT_EDIT')); return false; } } // Clean the cache $this->cleanCache(); return true; } /** * Batch move items to a new category * * @param integer $value The new category ID. * @param array $pks An array of row IDs. * @param array $contexts An array of item contexts. * * @return boolean True if successful, false otherwise and internal error is set. * * @since 11.1 */ protected function batchMove($value, $pks, $contexts) { $categoryId = (int) $value; $table = $this->getTable(); // Check that the category exists if ($categoryId) { $categoryTable = JTable::getInstance('Category'); if (!$categoryTable->load($categoryId)) { if ($error = $categoryTable->getError()) { // Fatal error $this->setError($error); return false; } else { $this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_MOVE_CATEGORY_NOT_FOUND')); return false; } } } if (empty($categoryId)) { $this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_MOVE_CATEGORY_NOT_FOUND')); return false; } // Check that user has create and edit permission for the component $extension = JFactory::getApplication()->input->get('option', ''); $user = JFactory::getUser(); if (!$user->authorise('core.create', $extension . '.category.' . $categoryId)) { $this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_CANNOT_CREATE')); return false; } // Parent exists so we let's proceed foreach ($pks as $pk) { if (!$user->authorise('core.edit', $contexts[$pk])) { $this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_CANNOT_EDIT')); return false; } // Check that the row actually exists if (!$table->load($pk)) { if ($error = $table->getError()) { // Fatal error $this->setError($error); return false; } else { // Not fatal error $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_BATCH_MOVE_ROW_NOT_FOUND', $pk)); continue; } } // Set the new category ID $table->catid = $categoryId; // Check the row. if (!$table->check()) { $this->setError($table->getError()); return false; } // Store the row. if (!$table->store()) { $this->setError($table->getError()); return false; } } // Clean the cache $this->cleanCache(); return true; } /** * Method to test whether a record can be deleted. * * @param object $record A record object. * * @return boolean True if allowed to delete the record. Defaults to the permission for the component. * * @since 11.1 */ protected function canDelete($record) { $user = JFactory::getUser(); return $user->authorise('core.delete', $this->option); } /** * Method to test whether a record can be deleted. * * @param object $record A record object. * * @return boolean True if allowed to change the state of the record. Defaults to the permission for the component. * * @since 11.1 */ protected function canEditState($record) { $user = JFactory::getUser(); return $user->authorise('core.edit.state', $this->option); } /** * Method override to check-in a record or an array of record * * @param mixed $pks The ID of the primary key or an array of IDs * * @return mixed Boolean false if there is an error, otherwise the count of records checked in. * * @since 11.1 */ public function checkin($pks = array()) { // Initialise variables. $pks = (array) $pks; $table = $this->getTable(); $count = 0; if (empty($pks)) { $pks = array((int) $this->getState($this->getName() . '.id')); } // Check in all items. foreach ($pks as $pk) { if ($table->load($pk)) { if ($table->checked_out > 0) { if (!parent::checkin($pk)) { return false; } $count++; } } else { $this->setError($table->getError()); return false; } } return $count; } /** * Method override to check-out a record. * * @param integer $pk The ID of the primary key. * * @return boolean True if successful, false if an error occurs. * * @since 11.1 */ public function checkout($pk = null) { // Initialise variables. $pk = (!empty($pk)) ? $pk : (int) $this->getState($this->getName() . '.id'); return parent::checkout($pk); } /** * Method to delete one or more records. * * @param array &$pks An array of record primary keys. * * @return boolean True if successful, false if an error occurs. * * @since 11.1 */ public function delete(&$pks) { // Initialise variables. $dispatcher = JDispatcher::getInstance(); $pks = (array) $pks; $table = $this->getTable(); // Include the content plugins for the on delete events. JPluginHelper::importPlugin('content'); // Iterate the items to delete each one. foreach ($pks as $i => $pk) { if ($table->load($pk)) { if ($this->canDelete($table)) { $context = $this->option . '.' . $this->name; // Trigger the onContentBeforeDelete event. $result = $dispatcher->trigger($this->event_before_delete, array($context, $table)); if (in_array(false, $result, true)) { $this->setError($table->getError()); return false; } if (!$table->delete($pk)) { $this->setError($table->getError()); return false; } // Trigger the onContentAfterDelete event. $dispatcher->trigger($this->event_after_delete, array($context, $table)); } else { // Prune items that you can't change. unset($pks[$i]); $error = $this->getError(); if ($error) { JError::raiseWarning(500, $error); return false; } else { JError::raiseWarning(403, JText::_('JLIB_APPLICATION_ERROR_DELETE_NOT_PERMITTED')); return false; } } } else { $this->setError($table->getError()); return false; } } // Clear the component's cache $this->cleanCache(); return true; } /** * Method to change the title & alias. * * @param integer $category_id The id of the category. * @param string $alias The alias. * @param string $title The title. * * @return array Contains the modified title and alias. * * @since 11.1 */ protected function generateNewTitle($category_id, $alias, $title) { // Alter the title & alias $table = $this->getTable(); while ($table->load(array('alias' => $alias, 'catid' => $category_id))) { $title = JString::increment($title); $alias = JString::increment($alias, 'dash'); } return array($title, $alias); } /** * Method to get a single record. * * @param integer $pk The id of the primary key. * * @return mixed Object on success, false on failure. * * @since 11.1 */ public function getItem($pk = null) { // Initialise variables. $pk = (!empty($pk)) ? $pk : (int) $this->getState($this->getName() . '.id'); $table = $this->getTable(); if ($pk > 0) { // Attempt to load the row. $return = $table->load($pk); // Check for a table object error. if ($return === false && $table->getError()) { $this->setError($table->getError()); return false; } } // Convert to the JObject before adding other data. $properties = $table->getProperties(1); $item = JArrayHelper::toObject($properties, 'JObject'); if (property_exists($item, 'params')) { $registry = new JRegistry; $registry->loadString($item->params); $item->params = $registry->toArray(); } return $item; } /** * A protected method to get a set of ordering conditions. * * @param JTable $table A JTable object. * * @return array An array of conditions to add to ordering queries. * * @since 11.1 */ protected function getReorderConditions($table) { return array(); } /** * Stock method to auto-populate the model state. * * @return void * * @since 11.1 */ protected function populateState() { // Initialise variables. $table = $this->getTable(); $key = $table->getKeyName(); // Get the pk of the record from the request. $pk = JRequest::getInt($key); $this->setState($this->getName() . '.id', $pk); // Load the parameters. $value = JComponentHelper::getParams($this->option); $this->setState('params', $value); } /** * Prepare and sanitise the table data prior to saving. * * @param JTable &$table A reference to a JTable object. * * @return void * * @since 11.1 */ protected function prepareTable(&$table) { // Derived class will provide its own implementation if required. } /** * Method to change the published state of one or more records. * * @param array &$pks A list of the primary keys to change. * @param integer $value The value of the published state. * * @return boolean True on success. * * @since 11.1 */ public function publish(&$pks, $value = 1) { // Initialise variables. $dispatcher = JDispatcher::getInstance(); $user = JFactory::getUser(); $table = $this->getTable(); $pks = (array) $pks; // Include the content plugins for the change of state event. JPluginHelper::importPlugin('content'); // Access checks. foreach ($pks as $i => $pk) { $table->reset(); if ($table->load($pk)) { if (!$this->canEditState($table)) { // Prune items that you can't change. unset($pks[$i]); JError::raiseWarning(403, JText::_('JLIB_APPLICATION_ERROR_EDITSTATE_NOT_PERMITTED')); return false; } } } // Attempt to change the state of the records. if (!$table->publish($pks, $value, $user->get('id'))) { $this->setError($table->getError()); return false; } $context = $this->option . '.' . $this->name; // Trigger the onContentChangeState event. $result = $dispatcher->trigger($this->event_change_state, array($context, $pks, $value)); if (in_array(false, $result, true)) { $this->setError($table->getError()); return false; } // Clear the component's cache $this->cleanCache(); return true; } /** * Method to adjust the ordering of a row. * * Returns NULL if the user did not have edit * privileges for any of the selected primary keys. * * @param integer $pks The ID of the primary key to move. * @param integer $delta Increment, usually +1 or -1 * * @return mixed False on failure or error, true on success, null if the $pk is empty (no items selected). * * @since 11.1 */ public function reorder($pks, $delta = 0) { // Initialise variables. $table = $this->getTable(); $pks = (array) $pks; $result = true; $allowed = true; foreach ($pks as $i => $pk) { $table->reset(); if ($table->load($pk) && $this->checkout($pk)) { // Access checks. if (!$this->canEditState($table)) { // Prune items that you can't change. unset($pks[$i]); $this->checkin($pk); JError::raiseWarning(403, JText::_('JLIB_APPLICATION_ERROR_EDITSTATE_NOT_PERMITTED')); $allowed = false; continue; } $where = array(); $where = $this->getReorderConditions($table); if (!$table->move($delta, $where)) { $this->setError($table->getError()); unset($pks[$i]); $result = false; } $this->checkin($pk); } else { $this->setError($table->getError()); unset($pks[$i]); $result = false; } } if ($allowed === false && empty($pks)) { $result = null; } // Clear the component's cache if ($result == true) { $this->cleanCache(); } return $result; } /** * Method to save the form data. * * @param array $data The form data. * * @return boolean True on success, False on error. * * @since 11.1 */ public function save($data) { // Initialise variables; $dispatcher = JDispatcher::getInstance(); $table = $this->getTable(); $key = $table->getKeyName(); $pk = (!empty($data[$key])) ? $data[$key] : (int) $this->getState($this->getName() . '.id'); $isNew = true; // Include the content plugins for the on save events. JPluginHelper::importPlugin('content'); // Allow an exception to be thrown. try { // Load the row if saving an existing record. if ($pk > 0) { $table->load($pk); $isNew = false; } // Bind the data. if (!$table->bind($data)) { $this->setError($table->getError()); return false; } // Prepare the row for saving $this->prepareTable($table); // Check the data. if (!$table->check()) { $this->setError($table->getError()); return false; } // Trigger the onContentBeforeSave event. $result = $dispatcher->trigger($this->event_before_save, array($this->option . '.' . $this->name, &$table, $isNew)); if (in_array(false, $result, true)) { $this->setError($table->getError()); return false; } // Store the data. if (!$table->store()) { $this->setError($table->getError()); return false; } // Clean the cache. $this->cleanCache(); // Trigger the onContentAfterSave event. $dispatcher->trigger($this->event_after_save, array($this->option . '.' . $this->name, &$table, $isNew)); } catch (Exception $e) { $this->setError($e->getMessage()); return false; } $pkName = $table->getKeyName(); if (isset($table->$pkName)) { $this->setState($this->getName() . '.id', $table->$pkName); } $this->setState($this->getName() . '.new', $isNew); return true; } /** * Saves the manually set order of records. * * @param array $pks An array of primary key ids. * @param integer $order +1 or -1 * * @return mixed * * @since 11.1 */ public function saveorder($pks = null, $order = null) { // Initialise variables. $table = $this->getTable(); $conditions = array(); if (empty($pks)) { return JError::raiseWarning(500, JText::_($this->text_prefix . '_ERROR_NO_ITEMS_SELECTED')); } // Update ordering values foreach ($pks as $i => $pk) { $table->load((int) $pk); // Access checks. if (!$this->canEditState($table)) { // Prune items that you can't change. unset($pks[$i]); JError::raiseWarning(403, JText::_('JLIB_APPLICATION_ERROR_EDITSTATE_NOT_PERMITTED')); } elseif ($table->ordering != $order[$i]) { $table->ordering = $order[$i]; if (!$table->store()) { $this->setError($table->getError()); return false; } // Remember to reorder within position and client_id $condition = $this->getReorderConditions($table); $found = false; foreach ($conditions as $cond) { if ($cond[1] == $condition) { $found = true; break; } } if (!$found) { $key = $table->getKeyName(); $conditions[] = array($table->$key, $condition); } } } // Execute reorder for each category. foreach ($conditions as $cond) { $table->load($cond[0]); $table->reorder($cond[1]); } // Clear the component's cache $this->cleanCache(); return true; } } component/controlleradmin.php000066600000020203151372744100012460 0ustar00registerTask('unpublish', 'publish'); // Value = 2 $this->registerTask('archive', 'publish'); // Value = -2 $this->registerTask('trash', 'publish'); // Value = -3 $this->registerTask('report', 'publish'); $this->registerTask('orderup', 'reorder'); $this->registerTask('orderdown', 'reorder'); // Guess the option as com_NameOfController. if (empty($this->option)) { $this->option = 'com_' . strtolower($this->getName()); } // Guess the JText message prefix. Defaults to the option. if (empty($this->text_prefix)) { $this->text_prefix = strtoupper($this->option); } // Guess the list view as the suffix, eg: OptionControllerSuffix. if (empty($this->view_list)) { $r = null; if (!preg_match('/(.*)Controller(.*)/i', get_class($this), $r)) { JError::raiseError(500, JText::_('JLIB_APPLICATION_ERROR_CONTROLLER_GET_NAME')); } $this->view_list = strtolower($r[2]); } } /** * Removes an item. * * @return void * * @since 11.1 */ public function delete() { // Check for request forgeries JSession::checkToken() or die(JText::_('JINVALID_TOKEN')); // Get items to remove from the request. $cid = JRequest::getVar('cid', array(), '', 'array'); if (!is_array($cid) || count($cid) < 1) { JError::raiseWarning(500, JText::_($this->text_prefix . '_NO_ITEM_SELECTED')); } else { // Get the model. $model = $this->getModel(); // Make sure the item ids are integers jimport('joomla.utilities.arrayhelper'); JArrayHelper::toInteger($cid); // Remove the items. if ($model->delete($cid)) { $this->setMessage(JText::plural($this->text_prefix . '_N_ITEMS_DELETED', count($cid))); } else { $this->setMessage($model->getError()); } } $this->setRedirect(JRoute::_('index.php?option=' . $this->option . '&view=' . $this->view_list, false)); } /** * Display is not supported by this controller. * * @param boolean $cachable If true, the view output will be cached * @param array $urlparams An array of safe url parameters and their variable types, for valid values see {@link JFilterInput::clean()}. * * @return JController A JController object to support chaining. * * @since 11.1 */ public function display($cachable = false, $urlparams = false) { return $this; } /** * Method to publish a list of items * * @return void * * @since 11.1 */ public function publish() { // Check for request forgeries JSession::checkToken() or die(JText::_('JINVALID_TOKEN')); // Get items to publish from the request. $cid = JRequest::getVar('cid', array(), '', 'array'); $data = array('publish' => 1, 'unpublish' => 0, 'archive' => 2, 'trash' => -2, 'report' => -3); $task = $this->getTask(); $value = JArrayHelper::getValue($data, $task, 0, 'int'); if (empty($cid)) { JError::raiseWarning(500, JText::_($this->text_prefix . '_NO_ITEM_SELECTED')); } else { // Get the model. $model = $this->getModel(); // Make sure the item ids are integers JArrayHelper::toInteger($cid); // Publish the items. if (!$model->publish($cid, $value)) { JError::raiseWarning(500, $model->getError()); } else { if ($value == 1) { $ntext = $this->text_prefix . '_N_ITEMS_PUBLISHED'; } elseif ($value == 0) { $ntext = $this->text_prefix . '_N_ITEMS_UNPUBLISHED'; } elseif ($value == 2) { $ntext = $this->text_prefix . '_N_ITEMS_ARCHIVED'; } else { $ntext = $this->text_prefix . '_N_ITEMS_TRASHED'; } $this->setMessage(JText::plural($ntext, count($cid))); } } $extension = JRequest::getCmd('extension'); $extensionURL = ($extension) ? '&extension=' . JRequest::getCmd('extension') : ''; $this->setRedirect(JRoute::_('index.php?option=' . $this->option . '&view=' . $this->view_list . $extensionURL, false)); } /** * Changes the order of one or more records. * * @return boolean True on success * * @since 11.1 */ public function reorder() { // Check for request forgeries. JSession::checkToken() or jexit(JText::_('JINVALID_TOKEN')); // Initialise variables. $ids = JRequest::getVar('cid', null, 'post', 'array'); $inc = ($this->getTask() == 'orderup') ? -1 : +1; $model = $this->getModel(); $return = $model->reorder($ids, $inc); if ($return === false) { // Reorder failed. $message = JText::sprintf('JLIB_APPLICATION_ERROR_REORDER_FAILED', $model->getError()); $this->setRedirect(JRoute::_('index.php?option=' . $this->option . '&view=' . $this->view_list, false), $message, 'error'); return false; } else { // Reorder succeeded. $message = JText::_('JLIB_APPLICATION_SUCCESS_ITEM_REORDERED'); $this->setRedirect(JRoute::_('index.php?option=' . $this->option . '&view=' . $this->view_list, false), $message); return true; } } /** * Method to save the submitted ordering values for records. * * @return boolean True on success * * @since 11.1 */ public function saveorder() { // Check for request forgeries. JSession::checkToken() or jexit(JText::_('JINVALID_TOKEN')); // Get the input $pks = JRequest::getVar('cid', null, 'post', 'array'); $order = JRequest::getVar('order', null, 'post', 'array'); // Sanitize the input JArrayHelper::toInteger($pks); JArrayHelper::toInteger($order); // Get the model $model = $this->getModel(); // Save the ordering $return = $model->saveorder($pks, $order); if ($return === false) { // Reorder failed $message = JText::sprintf('JLIB_APPLICATION_ERROR_REORDER_FAILED', $model->getError()); $this->setRedirect(JRoute::_('index.php?option=' . $this->option . '&view=' . $this->view_list, false), $message, 'error'); return false; } else { // Reorder succeeded. $this->setMessage(JText::_('JLIB_APPLICATION_SUCCESS_ORDERING_SAVED')); $this->setRedirect(JRoute::_('index.php?option=' . $this->option . '&view=' . $this->view_list, false)); return true; } } /** * Check in of one or more records. * * @return boolean True on success * * @since 11.1 */ public function checkin() { // Check for request forgeries. JSession::checkToken() or jexit(JText::_('JINVALID_TOKEN')); // Initialise variables. $ids = JRequest::getVar('cid', null, 'post', 'array'); $model = $this->getModel(); $return = $model->checkin($ids); if ($return === false) { // Checkin failed. $message = JText::sprintf('JLIB_APPLICATION_ERROR_CHECKIN_FAILED', $model->getError()); $this->setRedirect(JRoute::_('index.php?option=' . $this->option . '&view=' . $this->view_list, false), $message, 'error'); return false; } else { // Checkin succeeded. $message = JText::plural($this->text_prefix . '_N_ITEMS_CHECKED_IN', count($ids)); $this->setRedirect(JRoute::_('index.php?option=' . $this->option . '&view=' . $this->view_list, false), $message); return true; } } } component/index.html000066600000000037151372744100010553 0ustar00 component/helper.php000066600000025666151372744100010565 0ustar00enabled = $strict ? false : true; $result->params = new JRegistry; } } else { $result = self::$components[$option]; } return $result; } /** * Checks if the component is enabled * * @param string $option The component option. * @param boolean $strict If set and the component does not exist, false will be returned. * * @return boolean * * @since 11.1 */ public static function isEnabled($option, $strict = false) { $result = self::getComponent($option, $strict); return ($result->enabled | JFactory::getApplication()->isAdmin()); } /** * Gets the parameter object for the component * * @param string $option The option for the component. * @param boolean $strict If set and the component does not exist, false will be returned * * @return JRegistry A JRegistry object. * * @see JRegistry * @since 11.1 */ public static function getParams($option, $strict = false) { $component = self::getComponent($option, $strict); return $component->params; } /** * Applies the global text filters to arbitrary text as per settings for current user groups * * @param string $text The string to filter * * @return string The filtered string * * @since 11.4 */ public static function filterText($text) { // Filter settings $config = self::getParams('com_config'); $user = JFactory::getUser(); $userGroups = JAccess::getGroupsByUser($user->get('id')); $filters = $config->get('filters'); $blackListTags = array(); $blackListAttributes = array(); $customListTags = array(); $customListAttributes = array(); $whiteListTags = array(); $whiteListAttributes = array(); $noHtml = false; $whiteList = false; $blackList = false; $customList = false; $unfiltered = false; // Cycle through each of the user groups the user is in. // Remember they are included in the Public group as well. foreach ($userGroups as $groupId) { // May have added a group by not saved the filters. if (!isset($filters->$groupId)) { continue; } // Each group the user is in could have different filtering properties. $filterData = $filters->$groupId; $filterType = strtoupper($filterData->filter_type); if ($filterType == 'NH') { // Maximum HTML filtering. $noHtml = true; } elseif ($filterType == 'NONE') { // No HTML filtering. $unfiltered = true; } else { // Black or white list. // Preprocess the tags and attributes. $tags = explode(',', $filterData->filter_tags); $attributes = explode(',', $filterData->filter_attributes); $tempTags = array(); $tempAttributes = array(); foreach ($tags as $tag) { $tag = trim($tag); if ($tag) { $tempTags[] = $tag; } } foreach ($attributes as $attribute) { $attribute = trim($attribute); if ($attribute) { $tempAttributes[] = $attribute; } } // Collect the black or white list tags and attributes. // Each list is cummulative. if ($filterType == 'BL') { $blackList = true; $blackListTags = array_merge($blackListTags, $tempTags); $blackListAttributes = array_merge($blackListAttributes, $tempAttributes); } elseif ($filterType == 'CBL') { // Only set to true if Tags or Attributes were added if ($tempTags || $tempAttributes) { $customList = true; $customListTags = array_merge($customListTags, $tempTags); $customListAttributes = array_merge($customListAttributes, $tempAttributes); } } elseif ($filterType == 'WL') { $whiteList = true; $whiteListTags = array_merge($whiteListTags, $tempTags); $whiteListAttributes = array_merge($whiteListAttributes, $tempAttributes); } } } // Remove duplicates before processing (because the black list uses both sets of arrays). $blackListTags = array_unique($blackListTags); $blackListAttributes = array_unique($blackListAttributes); $customListTags = array_unique($customListTags); $customListAttributes = array_unique($customListAttributes); $whiteListTags = array_unique($whiteListTags); $whiteListAttributes = array_unique($whiteListAttributes); // Unfiltered assumes first priority. if ($unfiltered) { // Dont apply filtering. } else { // Custom blacklist precedes Default blacklist if ($customList) { $filter = JFilterInput::getInstance(array(), array(), 1, 1); // Override filter's default blacklist tags and attributes if ($customListTags) { $filter->tagBlacklist = $customListTags; } if ($customListAttributes) { $filter->attrBlacklist = $customListAttributes; } } // Black lists take second precedence. elseif ($blackList) { // Remove the white-listed tags and attributes from the black-list. $blackListTags = array_diff($blackListTags, $whiteListTags); $blackListAttributes = array_diff($blackListAttributes, $whiteListAttributes); $filter = JFilterInput::getInstance($blackListTags, $blackListAttributes, 1, 1); // Remove white listed tags from filter's default blacklist if ($whiteListTags) { $filter->tagBlacklist = array_diff($filter->tagBlacklist, $whiteListTags); } // Remove white listed attributes from filter's default blacklist if ($whiteListAttributes) { $filter->attrBlacklist = array_diff($filter->attrBlacklist); } } // White lists take third precedence. elseif ($whiteList) { // Turn off xss auto clean $filter = JFilterInput::getInstance($whiteListTags, $whiteListAttributes, 0, 0, 0); } // No HTML takes last place. else { $filter = JFilterInput::getInstance(); } $text = $filter->clean($text, 'html'); } return $text; } /** * Render the component. * * @param string $option The component option. * @param array $params The component parameters * * @return object * * @since 11.1 */ public static function renderComponent($option, $params = array()) { // Initialise variables. $app = JFactory::getApplication(); // Load template language files. $template = $app->getTemplate(true)->template; $lang = JFactory::getLanguage(); $lang->load('tpl_' . $template, JPATH_BASE, null, false, true) || $lang->load('tpl_' . $template, JPATH_THEMES . "/$template", null, false, true); if (empty($option)) { // Throw 404 if no component JError::raiseError(404, JText::_('JLIB_APPLICATION_ERROR_COMPONENT_NOT_FOUND')); return; } // Record the scope $scope = $app->scope; // Set scope to component name $app->scope = $option; // Build the component path. $option = preg_replace('/[^A-Z0-9_\.-]/i', '', $option); $file = substr($option, 4); // Define component path. define('JPATH_COMPONENT', JPATH_BASE . '/components/' . $option); define('JPATH_COMPONENT_SITE', JPATH_SITE . '/components/' . $option); define('JPATH_COMPONENT_ADMINISTRATOR', JPATH_ADMINISTRATOR . '/components/' . $option); // Get component path if ($app->isAdmin() && file_exists(JPATH_COMPONENT . '/admin.' . $file . '.php')) { JLog::add('Files in the format admin.COMPONENTNAME.php are considered deprecated and will not be loaded in Joomla 3.0.', JLog::WARNING, 'deprecated'); $path = JPATH_COMPONENT . '/admin.' . $file . '.php'; } else { $path = JPATH_COMPONENT . '/' . $file . '.php'; } // If component is disabled throw error if (!self::isEnabled($option) || !file_exists($path)) { JError::raiseError(404, JText::_('JLIB_APPLICATION_ERROR_COMPONENT_NOT_FOUND')); } $task = JRequest::getString('task'); // Load common and local language files. $lang->load($option, JPATH_BASE, null, false, true) || $lang->load($option, JPATH_COMPONENT, null, false, true); // Handle template preview outlining. $contents = null; // Execute the component. $contents = self::executeComponent($path); // Build the component toolbar $path = JApplicationHelper::getPath('toolbar'); if ($path && $app->isAdmin()) { JLog::add('Files in the format toolbar.COMPONENTNAME.php are considered deprecated and will not be loaded in Joomla 3.0.', JLog::WARNING, 'deprecated'); // Get the task again, in case it has changed $task = JRequest::getString('task'); // Make the toolbar include_once $path; } // Revert the scope $app->scope = $scope; return $contents; } /** * Execute the component. * * @param string $path The component path. * * @return string The component output * * @since 11.3 */ protected static function executeComponent($path) { ob_start(); require_once $path; $contents = ob_get_contents(); ob_end_clean(); return $contents; } /** * Load the installed components into the components property. * * @param string $option The element value for the extension * * @return boolean True on success * * @since 11.1 */ protected static function _load($option) { $db = JFactory::getDbo(); $query = $db->getQuery(true); $query->select('extension_id AS id, element AS "option", params, enabled'); $query->from('#__extensions'); $query->where($query->qn('type') . ' = ' . $db->quote('component')); $query->where($query->qn('element') . ' = ' . $db->quote($option)); $db->setQuery($query); $cache = JFactory::getCache('_system', 'callback'); self::$components[$option] = $cache->get(array($db, 'loadObject'), null, $option, false); if ($error = $db->getErrorMsg() || empty(self::$components[$option])) { // Fatal error. JError::raiseWarning(500, JText::sprintf('JLIB_APPLICATION_ERROR_COMPONENT_NOT_LOADING', $option, $error)); return false; } // Convert the params to an object. if (is_string(self::$components[$option]->params)) { $temp = new JRegistry; $temp->loadString(self::$components[$option]->params); self::$components[$option]->params = $temp; } return true; } } component/modelform.php000066600000015507151372744100011263 0ustar00getTable(); if (!$table->load($pk)) { $this->setError($table->getError()); return false; } // Check if this is the user having previously checked out the row. if ($table->checked_out > 0 && $table->checked_out != $user->get('id') && !$user->authorise('core.admin', 'com_checkin')) { $this->setError(JText::_('JLIB_APPLICATION_ERROR_CHECKIN_USER_MISMATCH')); return false; } // Attempt to check the row in. if (!$table->checkin($pk)) { $this->setError($table->getError()); return false; } } return true; } /** * Method to check-out a row for editing. * * @param integer $pk The numeric id of the primary key. * * @return boolean False on failure or error, true otherwise. * * @since 11.1 */ public function checkout($pk = null) { // Only attempt to check the row in if it exists. if ($pk) { $user = JFactory::getUser(); // Get an instance of the row to checkout. $table = $this->getTable(); if (!$table->load($pk)) { $this->setError($table->getError()); return false; } // Check if this is the user having previously checked out the row. if ($table->checked_out > 0 && $table->checked_out != $user->get('id')) { $this->setError(JText::_('JLIB_APPLICATION_ERROR_CHECKOUT_USER_MISMATCH')); return false; } // Attempt to check the row out. if (!$table->checkout($user->get('id'), $pk)) { $this->setError($table->getError()); return false; } } return true; } /** * Abstract method for getting the form from the model. * * @param array $data Data for the form. * @param boolean $loadData True if the form is to load its own data (default case), false if not. * * @return mixed A JForm object on success, false on failure * * @since 11.1 */ abstract public function getForm($data = array(), $loadData = true); /** * Method to get a form object. * * @param string $name The name of the form. * @param string $source The form source. Can be XML string if file flag is set to false. * @param array $options Optional array of options for the form creation. * @param boolean $clear Optional argument to force load a new form. * @param string $xpath An optional xpath to search for the fields. * * @return mixed JForm object on success, False on error. * * @see JForm * @since 11.1 */ protected function loadForm($name, $source = null, $options = array(), $clear = false, $xpath = false) { // Handle the optional arguments. $options['control'] = JArrayHelper::getValue($options, 'control', false); // Create a signature hash. $hash = md5($source . serialize($options)); // Check if we can use a previously loaded form. if (isset($this->_forms[$hash]) && !$clear) { return $this->_forms[$hash]; } // Get the form. JForm::addFormPath(JPATH_COMPONENT . '/models/forms'); JForm::addFieldPath(JPATH_COMPONENT . '/models/fields'); try { $form = JForm::getInstance($name, $source, $options, false, $xpath); if (isset($options['load_data']) && $options['load_data']) { // Get the data for the form. $data = $this->loadFormData(); } else { $data = array(); } // Allow for additional modification of the form, and events to be triggered. // We pass the data because plugins may require it. $this->preprocessForm($form, $data); // Load the data into the form after the plugins have operated. $form->bind($data); } catch (Exception $e) { $this->setError($e->getMessage()); return false; } // Store the form for later. $this->_forms[$hash] = $form; return $form; } /** * Method to get the data that should be injected in the form. * * @return array The default data is an empty array. * * @since 11.1 */ protected function loadFormData() { return array(); } /** * Method to allow derived classes to preprocess the form. * * @param JForm $form A JForm object. * @param mixed $data The data expected for the form. * @param string $group The name of the plugin group to import (defaults to "content"). * * @return void * * @see JFormField * @since 11.1 * @throws Exception if there is an error in the form event. */ protected function preprocessForm(JForm $form, $data, $group = 'content') { // Import the appropriate plugin group. JPluginHelper::importPlugin($group); // Get the dispatcher. $dispatcher = JDispatcher::getInstance(); // Trigger the form preparation event. $results = $dispatcher->trigger('onContentPrepareForm', array($form, $data)); // Check for errors encountered while preparing the form. if (count($results) && in_array(false, $results, true)) { // Get the last error. $error = $dispatcher->getError(); if (!($error instanceof Exception)) { throw new Exception($error); } } } /** * Method to validate the form data. * * @param JForm $form The form to validate against. * @param array $data The data to validate. * @param string $group The name of the field group to validate. * * @return mixed Array of filtered data if valid, false otherwise. * * @see JFormRule * @see JFilterInput * @since 11.1 */ public function validate($form, $data, $group = null) { // Filter and validate the form data. $data = $form->filter($data); $return = $form->validate($data, $group); // Check for an error. if ($return instanceof Exception) { $this->setError($return->getMessage()); return false; } // Check the validation results. if ($return === false) { // Get the validation messages from the form. foreach ($form->getErrors() as $message) { $this->setError(JText::_($message)); } return false; } return $data; } } component/controller.php000066600000063744151372744100011470 0ustar00clean(array_pop(array_keys($command)), 'cmd'); } else { $command = $filter->clean($command, 'cmd'); } // Check for a controller.task command. if (strpos($command, '.') !== false) { // Explode the controller.task command. list ($type, $task) = explode('.', $command); // Define the controller filename and path. $file = self::createFileName('controller', array('name' => $type, 'format' => $format)); $path = $basePath . '/controllers/' . $file; // Reset the task without the controller context. JRequest::setVar('task', $task); } else { // Base controller. $type = null; $task = $command; // Define the controller filename and path. $file = self::createFileName('controller', array('name' => 'controller', 'format' => $format)); $path = $basePath . '/' . $file; $backupfile = self::createFileName('controller', array('name' => 'controller')); $backuppath = $basePath . '/' . $backupfile; } // Get the controller class name. $class = ucfirst($prefix) . 'Controller' . ucfirst($type); // Include the class if not present. if (!class_exists($class)) { // If the controller file path exists, include it. if (file_exists($path)) { require_once $path; } elseif (isset($backuppath) && file_exists($backuppath)) { require_once $backuppath; } else { throw new InvalidArgumentException(JText::sprintf('JLIB_APPLICATION_ERROR_INVALID_CONTROLLER', $type, $format)); } } // Instantiate the class. if (class_exists($class)) { self::$instance = new $class($config); } else { throw new InvalidArgumentException(JText::sprintf('JLIB_APPLICATION_ERROR_INVALID_CONTROLLER_CLASS', $class)); } return self::$instance; } /** * Constructor. * * @param array $config An optional associative array of configuration settings. * Recognized key values include 'name', 'default_task', 'model_path', and * 'view_path' (this list is not meant to be comprehensive). * * @since 11.1 */ public function __construct($config = array()) { // Initialise variables. $this->methods = array(); $this->message = null; $this->messageType = 'message'; $this->paths = array(); $this->redirect = null; $this->taskMap = array(); if (defined('JDEBUG') && JDEBUG) { JLog::addLogger(array('text_file' => 'jcontroller.log.php'), JLog::ALL, array('controller')); } // Determine the methods to exclude from the base class. $xMethods = get_class_methods('JController'); // Get the public methods in this class using reflection. $r = new ReflectionClass($this); $rMethods = $r->getMethods(ReflectionMethod::IS_PUBLIC); foreach ($rMethods as $rMethod) { $mName = $rMethod->getName(); // Add default display method if not explicitly declared. if (!in_array($mName, $xMethods) || $mName == 'display') { $this->methods[] = strtolower($mName); // Auto register the methods as tasks. $this->taskMap[strtolower($mName)] = $mName; } } // Set the view name if (empty($this->name)) { if (array_key_exists('name', $config)) { $this->name = $config['name']; } else { $this->name = $this->getName(); } } // Set a base path for use by the controller if (array_key_exists('base_path', $config)) { $this->basePath = $config['base_path']; } else { $this->basePath = JPATH_COMPONENT; } // If the default task is set, register it as such if (array_key_exists('default_task', $config)) { $this->registerDefaultTask($config['default_task']); } else { $this->registerDefaultTask('display'); } // Set the models prefix if (empty($this->model_prefix)) { if (array_key_exists('model_prefix', $config)) { // User-defined prefix $this->model_prefix = $config['model_prefix']; } else { $this->model_prefix = $this->name . 'Model'; } } // Set the default model search path if (array_key_exists('model_path', $config)) { // User-defined dirs $this->addModelPath($config['model_path'], $this->model_prefix); } else { $this->addModelPath($this->basePath . '/models', $this->model_prefix); } // Set the default view search path if (array_key_exists('view_path', $config)) { // User-defined dirs $this->setPath('view', $config['view_path']); } else { $this->setPath('view', $this->basePath . '/views'); } // Set the default view. if (array_key_exists('default_view', $config)) { $this->default_view = $config['default_view']; } elseif (empty($this->default_view)) { $this->default_view = $this->getName(); } } /** * Adds to the search path for templates and resources. * * @param string $type The path type (e.g. 'model', 'view'). * @param mixed $path The directory string or stream array to search. * * @return JController A JController object to support chaining. * * @since 11.1 * @note Replaces _addPath. */ protected function addPath($type, $path) { // Just force path to array settype($path, 'array'); if (!isset($this->paths[$type])) { $this->paths[$type] = array(); } // Loop through the path directories foreach ($path as $dir) { // No surrounding spaces allowed! $dir = rtrim(JPath::check($dir, '/'), '/') . '/'; // Add to the top of the search dirs array_unshift($this->paths[$type], $dir); } return $this; } /** * Add one or more view paths to the controller's stack, in LIFO order. * * @param mixed $path The directory (string) or list of directories (array) to add. * * @return JController This object to support chaining. */ public function addViewPath($path) { $this->addPath('view', $path); return $this; } /** * Authorisation check * * @param string $task The ACO Section Value to check access on * * @return boolean True if authorised * * @since 11.1 * * @deprecated 12.1 Use JAuthorise */ public function authorize($task) { JLog::add('JController::authorize() is deprecated.', JLog::WARNING, 'deprecated'); $this->authorise($task); } /** * Authorisation check * * @param string $task The ACO Section Value to check access on. * * @return boolean True if authorised * * @since 11.1 * @deprecated 12.3 */ public function authorise($task) { // Only do access check if the aco section is set if ($this->_acoSection) { // If we have a section value set that trumps the passed task. if ($this->_acoSectionValue) { // We have one, so set it and lets do the check $task = $this->_acoSectionValue; } // Get the JUser object for the current user and return the authorization boolean $user = JFactory::getUser(); return $user->authorise($this->_acoSection, $task); } else { // Nothing set, nothing to check... so obviously it's ok :) return true; } } /** * Method to check whether an ID is in the edit list. * * @param string $context The context for the session storage. * @param integer $id The ID of the record to add to the edit list. * * @return boolean True if the ID is in the edit list. * * @since 11.1 */ protected function checkEditId($context, $id) { if ($id) { $app = JFactory::getApplication(); $values = (array) $app->getUserState($context . '.id'); $result = in_array((int) $id, $values); if (defined('JDEBUG') && JDEBUG) { JLog::add( sprintf( 'Checking edit ID %s.%s: %d %s', $context, $id, (int) $result, str_replace("\n", ' ', print_r($values, 1)) ), JLog::INFO, 'controller' ); } return $result; } else { // No id for a new item. return true; } } /** * Method to load and return a model object. * * @param string $name The name of the model. * @param string $prefix Optional model prefix. * @param array $config Configuration array for the model. Optional. * * @return mixed Model object on success; otherwise null failure. * * @since 11.1 * @note Replaces _createModel. */ protected function createModel($name, $prefix = '', $config = array()) { // Clean the model name $modelName = preg_replace('/[^A-Z0-9_]/i', '', $name); $classPrefix = preg_replace('/[^A-Z0-9_]/i', '', $prefix); $result = JModel::getInstance($modelName, $classPrefix, $config); return $result; } /** * Method to load and return a view object. This method first looks in the * current template directory for a match and, failing that, uses a default * set path to load the view class file. * * Note the "name, prefix, type" order of parameters, which differs from the * "name, type, prefix" order used in related public methods. * * @param string $name The name of the view. * @param string $prefix Optional prefix for the view class name. * @param string $type The type of view. * @param array $config Configuration array for the view. Optional. * * @return mixed View object on success; null or error result on failure. * * @since 11.1 * @note Replaces _createView. */ protected function createView($name, $prefix = '', $type = '', $config = array()) { // Clean the view name $viewName = preg_replace('/[^A-Z0-9_]/i', '', $name); $classPrefix = preg_replace('/[^A-Z0-9_]/i', '', $prefix); $viewType = preg_replace('/[^A-Z0-9_]/i', '', $type); // Build the view class name $viewClass = $classPrefix . $viewName; if (!class_exists($viewClass)) { jimport('joomla.filesystem.path'); $path = JPath::find($this->paths['view'], $this->createFileName('view', array('name' => $viewName, 'type' => $viewType))); if ($path) { require_once $path; if (!class_exists($viewClass)) { JError::raiseError(500, JText::sprintf('JLIB_APPLICATION_ERROR_VIEW_CLASS_NOT_FOUND', $viewClass, $path)); return null; } } else { return null; } } return new $viewClass($config); } /** * Typical view method for MVC based architecture * * This function is provide as a default implementation, in most cases * you will need to override it in your own controllers. * * @param boolean $cachable If true, the view output will be cached * @param array $urlparams An array of safe url parameters and their variable types, for valid values see {@link JFilterInput::clean()}. * * @return JController A JController object to support chaining. * * @since 11.1 */ public function display($cachable = false, $urlparams = false) { $document = JFactory::getDocument(); $viewType = $document->getType(); $viewName = JRequest::getCmd('view', $this->default_view); $viewLayout = JRequest::getString('layout', 'default'); $view = $this->getView($viewName, $viewType, '', array('base_path' => $this->basePath, 'layout' => $viewLayout)); // Get/Create the model if ($model = $this->getModel($viewName)) { // Push the model into the view (as default) $view->setModel($model, true); } $view->assignRef('document', $document); $conf = JFactory::getConfig(); // Display the view if ($cachable && $viewType != 'feed' && $conf->get('caching') >= 1) { $option = JRequest::getCmd('option'); $cache = JFactory::getCache($option, 'view'); if (is_array($urlparams)) { $app = JFactory::getApplication(); if (!empty($app->registeredurlparams)) { $registeredurlparams = $app->registeredurlparams; } else { $registeredurlparams = new stdClass; } foreach ($urlparams as $key => $value) { // Add your safe url parameters with variable type as value {@see JFilterInput::clean()}. $registeredurlparams->$key = $value; } $app->registeredurlparams = $registeredurlparams; } $cache->get($view, 'display'); } else { $view->display(); } return $this; } /** * Execute a task by triggering a method in the derived class. * * @param string $task The task to perform. If no matching task is found, the '__default' task is executed, if defined. * * @return mixed The value returned by the called method, false in error case. * * @since 11.1 */ public function execute($task) { $this->task = $task; $task = strtolower($task); if (isset($this->taskMap[$task])) { $doTask = $this->taskMap[$task]; } elseif (isset($this->taskMap['__default'])) { $doTask = $this->taskMap['__default']; } else { return JError::raiseError(404, JText::sprintf('JLIB_APPLICATION_ERROR_TASK_NOT_FOUND', $task)); } // Record the actual task being fired $this->doTask = $doTask; // Make sure we have access if ($this->authorise($doTask)) { $retval = $this->$doTask(); return $retval; } else { return JError::raiseError(403, JText::_('JLIB_APPLICATION_ERROR_ACCESS_FORBIDDEN')); } } /** * Method to get a model object, loading it if required. * * @param string $name The model name. Optional. * @param string $prefix The class prefix. Optional. * @param array $config Configuration array for model. Optional. * * @return object The model. * * @since 11.1 */ public function getModel($name = '', $prefix = '', $config = array()) { if (empty($name)) { $name = $this->getName(); } if (empty($prefix)) { $prefix = $this->model_prefix; } if ($model = $this->createModel($name, $prefix, $config)) { // Task is a reserved state $model->setState('task', $this->task); // Let's get the application object and set menu information if it's available $app = JFactory::getApplication(); $menu = $app->getMenu(); if (is_object($menu)) { if ($item = $menu->getActive()) { $params = $menu->getParams($item->id); // Set default state data $model->setState('parameters.menu', $params); } } } return $model; } /** * Method to get the controller name * * The dispatcher name is set by default parsed using the classname, or it can be set * by passing a $config['name'] in the class constructor * * @return string The name of the dispatcher * * @since 11.1 */ public function getName() { if (empty($this->name)) { $r = null; if (!preg_match('/(.*)Controller/i', get_class($this), $r)) { JError::raiseError(500, JText::_('JLIB_APPLICATION_ERROR_CONTROLLER_GET_NAME')); } $this->name = strtolower($r[1]); } return $this->name; } /** * Get the last task that is being performed or was most recently performed. * * @return string The task that is being performed or was most recently performed. * * @since 11.1 */ public function getTask() { return $this->task; } /** * Gets the available tasks in the controller. * * @return array Array[i] of task names. * * @since 11.1 */ public function getTasks() { return $this->methods; } /** * Method to get a reference to the current view and load it if necessary. * * @param string $name The view name. Optional, defaults to the controller name. * @param string $type The view type. Optional. * @param string $prefix The class prefix. Optional. * @param array $config Configuration array for view. Optional. * * @return object Reference to the view or an error. * * @since 11.1 */ public function getView($name = '', $type = '', $prefix = '', $config = array()) { static $views; if (!isset($views)) { $views = array(); } if (empty($name)) { $name = $this->getName(); } if (empty($prefix)) { $prefix = $this->getName() . 'View'; } if (empty($views[$name])) { if ($view = $this->createView($name, $prefix, $type, $config)) { $views[$name] = & $view; } else { $result = JError::raiseError(500, JText::sprintf('JLIB_APPLICATION_ERROR_VIEW_NOT_FOUND', $name, $type, $prefix)); return $result; } } return $views[$name]; } /** * Method to add a record ID to the edit list. * * @param string $context The context for the session storage. * @param integer $id The ID of the record to add to the edit list. * * @return void * * @since 11.1 */ protected function holdEditId($context, $id) { // Initialise variables. $app = JFactory::getApplication(); $values = (array) $app->getUserState($context . '.id'); // Add the id to the list if non-zero. if (!empty($id)) { array_push($values, (int) $id); $values = array_unique($values); $app->setUserState($context . '.id', $values); if (defined('JDEBUG') && JDEBUG) { JLog::add( sprintf( 'Holding edit ID %s.%s %s', $context, $id, str_replace("\n", ' ', print_r($values, 1)) ), JLog::INFO, 'controller' ); } } } /** * Redirects the browser or returns false if no redirect is set. * * @return boolean False if no redirect exists. * * @since 11.1 */ public function redirect() { if ($this->redirect) { $app = JFactory::getApplication(); $app->redirect($this->redirect, $this->message, $this->messageType); } return false; } /** * Register the default task to perform if a mapping is not found. * * @param string $method The name of the method in the derived class to perform if a named task is not found. * * @return JController A JController object to support chaining. * * @since 11.1 */ public function registerDefaultTask($method) { $this->registerTask('__default', $method); return $this; } /** * Register (map) a task to a method in the class. * * @param string $task The task. * @param string $method The name of the method in the derived class to perform for this task. * * @return JController A JController object to support chaining. * * @since 11.1 */ public function registerTask($task, $method) { if (in_array(strtolower($method), $this->methods)) { $this->taskMap[strtolower($task)] = $method; } return $this; } /** * Unregister (unmap) a task in the class. * * @param string $task The task. * * @return JController This object to support chaining. * * @since 11.1 */ public function unregisterTask($task) { unset($this->taskMap[strtolower($task)]); return $this; } /** * Method to check whether an ID is in the edit list. * * @param string $context The context for the session storage. * @param integer $id The ID of the record to add to the edit list. * * @return void * * @since 11.1 */ protected function releaseEditId($context, $id) { $app = JFactory::getApplication(); $values = (array) $app->getUserState($context . '.id'); // Do a strict search of the edit list values. $index = array_search((int) $id, $values, true); if (is_int($index)) { unset($values[$index]); $app->setUserState($context . '.id', $values); if (defined('JDEBUG') && JDEBUG) { JLog::add( sprintf( 'Releasing edit ID %s.%s %s', $context, $id, str_replace("\n", ' ', print_r($values, 1)) ), JLog::INFO, 'controller' ); } } } /** * Sets the access control levels. * * @param string $section The ACO section (eg, the component). * @param string $value The ACO section value (if using a constant value). * * @return void * * @deprecated 12.1 Use JAccess * @see Jaccess * @since 11.1 */ public function setAccessControl($section, $value = null) { // Deprecation warning. JLog::add('JController::setAccessControl() is deprecated.', JLog::WARNING, 'deprecated'); $this->_acoSection = $section; $this->_acoSectionValue = $value; } /** * Sets the internal message that is passed with a redirect * * @param string $text Message to display on redirect. * @param string $type Message type (since 11.1). Optional, defaults to 'message'. * * @return string Previous message * * @since 11.1 */ public function setMessage($text, $type = 'message') { $previous = $this->message; $this->message = $text; $this->messageType = $type; return $previous; } /** * Sets an entire array of search paths for resources. * * @param string $type The type of path to set, typically 'view' or 'model'. * @param string $path The new set of search paths. If null or false, resets to the current directory only. * * @return void * * @note Replaces _setPath. * @since 11.1 */ protected function setPath($type, $path) { // Clear out the prior search dirs $this->paths[$type] = array(); // Actually add the user-specified directories $this->addPath($type, $path); } /** * Set a URL for browser redirection. * * @param string $url URL to redirect to. * @param string $msg Message to display on redirect. Optional, defaults to value set internally by controller, if any. * @param string $type Message type. Optional, defaults to 'message' or the type set by a previous call to setMessage. * * @return JController This object to support chaining. * * @since 11.1 */ public function setRedirect($url, $msg = null, $type = null) { $this->redirect = $url; if ($msg !== null) { // Controller may have set this directly $this->message = $msg; } // Ensure the type is not overwritten by a previous call to setMessage. if (empty($type)) { if (empty($this->messageType)) { $this->messageType = 'message'; } } // If the type is explicitly set, set it. else { $this->messageType = $type; } return $this; } } component/controllerform.php000066600000047440151372744100012347 0ustar00option)) { $this->option = 'com_' . strtolower($this->getName()); } // Guess the JText message prefix. Defaults to the option. if (empty($this->text_prefix)) { $this->text_prefix = strtoupper($this->option); } // Guess the context as the suffix, eg: OptionControllerContent. if (empty($this->context)) { $r = null; if (!preg_match('/(.*)Controller(.*)/i', get_class($this), $r)) { JError::raiseError(500, JText::_('JLIB_APPLICATION_ERROR_CONTROLLER_GET_NAME')); } $this->context = strtolower($r[2]); } // Guess the item view as the context. if (empty($this->view_item)) { $this->view_item = $this->context; } // Guess the list view as the plural of the item view. if (empty($this->view_list)) { // @TODO Probably worth moving to an inflector class based on // http://kuwamoto.org/2007/12/17/improved-pluralizing-in-php-actionscript-and-ror/ // Simple pluralisation based on public domain snippet by Paul Osman // For more complex types, just manually set the variable in your class. $plural = array( array('/(x|ch|ss|sh)$/i', "$1es"), array('/([^aeiouy]|qu)y$/i', "$1ies"), array('/([^aeiouy]|qu)ies$/i', "$1y"), array('/(bu)s$/i', "$1ses"), array('/s$/i', "s"), array('/$/', "s")); // Check for matches using regular expressions foreach ($plural as $pattern) { if (preg_match($pattern[0], $this->view_item)) { $this->view_list = preg_replace($pattern[0], $pattern[1], $this->view_item); break; } } } // Apply, Save & New, and Save As copy should be standard on forms. $this->registerTask('apply', 'save'); $this->registerTask('save2new', 'save'); $this->registerTask('save2copy', 'save'); } /** * Method to add a new record. * * @return mixed True if the record can be added, a JError object if not. * * @since 11.1 */ public function add() { // Initialise variables. $app = JFactory::getApplication(); $context = "$this->option.edit.$this->context"; // Access check. if (!$this->allowAdd()) { // Set the internal error and also the redirect error. $this->setError(JText::_('JLIB_APPLICATION_ERROR_CREATE_RECORD_NOT_PERMITTED')); $this->setMessage($this->getError(), 'error'); $this->setRedirect( JRoute::_( 'index.php?option=' . $this->option . '&view=' . $this->view_list . $this->getRedirectToListAppend(), false ) ); return false; } // Clear the record edit information from the session. $app->setUserState($context . '.data', null); // Redirect to the edit screen. $this->setRedirect( JRoute::_( 'index.php?option=' . $this->option . '&view=' . $this->view_item . $this->getRedirectToItemAppend(), false ) ); return true; } /** * Method to check if you can add a new record. * * Extended classes can override this if necessary. * * @param array $data An array of input data. * * @return boolean * * @since 11.1 */ protected function allowAdd($data = array()) { $user = JFactory::getUser(); return ($user->authorise('core.create', $this->option) || count($user->getAuthorisedCategories($this->option, 'core.create'))); } /** * Method to check if you can add a new record. * * Extended classes can override this if necessary. * * @param array $data An array of input data. * @param string $key The name of the key for the primary key; default is id. * * @return boolean * * @since 11.1 */ protected function allowEdit($data = array(), $key = 'id') { return JFactory::getUser()->authorise('core.edit', $this->option); } /** * Method to check if you can save a new or existing record. * * Extended classes can override this if necessary. * * @param array $data An array of input data. * @param string $key The name of the key for the primary key. * * @return boolean * * @since 11.1 */ protected function allowSave($data, $key = 'id') { // Initialise variables. $recordId = isset($data[$key]) ? $data[$key] : '0'; if ($recordId) { return $this->allowEdit($data, $key); } else { return $this->allowAdd($data); } } /** * Method to run batch operations. * * @param JModel $model The model of the component being processed. * * @return boolean True if successful, false otherwise and internal error is set. * * @since 11.1 */ public function batch($model) { // Initialise variables. $input = JFactory::getApplication()->input; $vars = $input->post->get('batch', array(), 'array'); $cid = $input->post->get('cid', array(), 'array'); // Build an array of item contexts to check $contexts = array(); foreach ($cid as $id) { // If we're coming from com_categories, we need to use extension vs. option if (isset($this->extension)) { $option = $this->extension; } else { $option = $this->option; } $contexts[$id] = $option . '.' . $this->context . '.' . $id; } // Attempt to run the batch operation. if ($model->batch($vars, $cid, $contexts)) { $this->setMessage(JText::_('JLIB_APPLICATION_SUCCESS_BATCH')); return true; } else { $this->setMessage(JText::sprintf('JLIB_APPLICATION_ERROR_BATCH_FAILED', $model->getError())); return false; } } /** * Method to cancel an edit. * * @param string $key The name of the primary key of the URL variable. * * @return boolean True if access level checks pass, false otherwise. * * @since 11.1 */ public function cancel($key = null) { JSession::checkToken() or jexit(JText::_('JINVALID_TOKEN')); // Initialise variables. $app = JFactory::getApplication(); $model = $this->getModel(); $table = $model->getTable(); $checkin = property_exists($table, 'checked_out'); $context = "$this->option.edit.$this->context"; if (empty($key)) { $key = $table->getKeyName(); } $recordId = JRequest::getInt($key); // Attempt to check-in the current record. if ($recordId) { // Check we are holding the id in the edit list. if (!$this->checkEditId($context, $recordId)) { // Somehow the person just went to the form - we don't allow that. $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_UNHELD_ID', $recordId)); $this->setMessage($this->getError(), 'error'); $this->setRedirect( JRoute::_( 'index.php?option=' . $this->option . '&view=' . $this->view_list . $this->getRedirectToListAppend(), false ) ); return false; } if ($checkin) { if ($model->checkin($recordId) === false) { // Check-in failed, go back to the record and display a notice. $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_CHECKIN_FAILED', $model->getError())); $this->setMessage($this->getError(), 'error'); $this->setRedirect( JRoute::_( 'index.php?option=' . $this->option . '&view=' . $this->view_item . $this->getRedirectToItemAppend($recordId, $key), false ) ); return false; } } } // Clean the session data and redirect. $this->releaseEditId($context, $recordId); $app->setUserState($context . '.data', null); $this->setRedirect( JRoute::_( 'index.php?option=' . $this->option . '&view=' . $this->view_list . $this->getRedirectToListAppend(), false ) ); return true; } /** * Method to edit an existing record. * * @param string $key The name of the primary key of the URL variable. * @param string $urlVar The name of the URL variable if different from the primary key * (sometimes required to avoid router collisions). * * @return boolean True if access level check and checkout passes, false otherwise. * * @since 11.1 */ public function edit($key = null, $urlVar = null) { // Initialise variables. $app = JFactory::getApplication(); $model = $this->getModel(); $table = $model->getTable(); $cid = JRequest::getVar('cid', array(), 'post', 'array'); $context = "$this->option.edit.$this->context"; // Determine the name of the primary key for the data. if (empty($key)) { $key = $table->getKeyName(); } // To avoid data collisions the urlVar may be different from the primary key. if (empty($urlVar)) { $urlVar = $key; } // Get the previous record id (if any) and the current record id. $recordId = (int) (count($cid) ? $cid[0] : JRequest::getInt($urlVar)); $checkin = property_exists($table, 'checked_out'); // Access check. if (!$this->allowEdit(array($key => $recordId), $key)) { $this->setError(JText::_('JLIB_APPLICATION_ERROR_EDIT_NOT_PERMITTED')); $this->setMessage($this->getError(), 'error'); $this->setRedirect( JRoute::_( 'index.php?option=' . $this->option . '&view=' . $this->view_list . $this->getRedirectToListAppend(), false ) ); return false; } // Attempt to check-out the new record for editing and redirect. if ($checkin && !$model->checkout($recordId)) { // Check-out failed, display a notice but allow the user to see the record. $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_CHECKOUT_FAILED', $model->getError())); $this->setMessage($this->getError(), 'error'); $this->setRedirect( JRoute::_( 'index.php?option=' . $this->option . '&view=' . $this->view_item . $this->getRedirectToItemAppend($recordId, $urlVar), false ) ); return false; } else { // Check-out succeeded, push the new record id into the session. $this->holdEditId($context, $recordId); $app->setUserState($context . '.data', null); $this->setRedirect( JRoute::_( 'index.php?option=' . $this->option . '&view=' . $this->view_item . $this->getRedirectToItemAppend($recordId, $urlVar), false ) ); return true; } } /** * Method to get a model object, loading it if required. * * @param string $name The model name. Optional. * @param string $prefix The class prefix. Optional. * @param array $config Configuration array for model. Optional. * * @return object The model. * * @since 11.1 */ public function getModel($name = '', $prefix = '', $config = array('ignore_request' => true)) { if (empty($name)) { $name = $this->context; } return parent::getModel($name, $prefix, $config); } /** * Gets the URL arguments to append to an item redirect. * * @param integer $recordId The primary key id for the item. * @param string $urlVar The name of the URL variable for the id. * * @return string The arguments to append to the redirect URL. * * @since 11.1 */ protected function getRedirectToItemAppend($recordId = null, $urlVar = 'id') { $tmpl = JRequest::getCmd('tmpl'); $layout = JRequest::getCmd('layout', 'edit'); $append = ''; // Setup redirect info. if ($tmpl) { $append .= '&tmpl=' . $tmpl; } if ($layout) { $append .= '&layout=' . $layout; } if ($recordId) { $append .= '&' . $urlVar . '=' . $recordId; } return $append; } /** * Gets the URL arguments to append to a list redirect. * * @return string The arguments to append to the redirect URL. * * @since 11.1 */ protected function getRedirectToListAppend() { $tmpl = JRequest::getCmd('tmpl'); $append = ''; // Setup redirect info. if ($tmpl) { $append .= '&tmpl=' . $tmpl; } return $append; } /** * Function that allows child controller access to model data * after the data has been saved. * * @param JModel &$model The data model object. * @param array $validData The validated data. * * @return void * * @since 11.1 */ protected function postSaveHook(JModel &$model, $validData = array()) { } /** * Method to save a record. * * @param string $key The name of the primary key of the URL variable. * @param string $urlVar The name of the URL variable if different from the primary key (sometimes required to avoid router collisions). * * @return boolean True if successful, false otherwise. * * @since 11.1 */ public function save($key = null, $urlVar = null) { // Check for request forgeries. JSession::checkToken() or jexit(JText::_('JINVALID_TOKEN')); // Initialise variables. $app = JFactory::getApplication(); $lang = JFactory::getLanguage(); $model = $this->getModel(); $table = $model->getTable(); $data = JRequest::getVar('jform', array(), 'post', 'array'); $checkin = property_exists($table, 'checked_out'); $context = "$this->option.edit.$this->context"; $task = $this->getTask(); // Determine the name of the primary key for the data. if (empty($key)) { $key = $table->getKeyName(); } // To avoid data collisions the urlVar may be different from the primary key. if (empty($urlVar)) { $urlVar = $key; } $recordId = JRequest::getInt($urlVar); if (!$this->checkEditId($context, $recordId)) { // Somehow the person just went to the form and tried to save it. We don't allow that. $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_UNHELD_ID', $recordId)); $this->setMessage($this->getError(), 'error'); $this->setRedirect( JRoute::_( 'index.php?option=' . $this->option . '&view=' . $this->view_list . $this->getRedirectToListAppend(), false ) ); return false; } // Populate the row id from the session. $data[$key] = $recordId; // The save2copy task needs to be handled slightly differently. if ($task == 'save2copy') { // Check-in the original row. if ($checkin && $model->checkin($data[$key]) === false) { // Check-in failed. Go back to the item and display a notice. $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_CHECKIN_FAILED', $model->getError())); $this->setMessage($this->getError(), 'error'); $this->setRedirect( JRoute::_( 'index.php?option=' . $this->option . '&view=' . $this->view_item . $this->getRedirectToItemAppend($recordId, $urlVar), false ) ); return false; } // Reset the ID and then treat the request as for Apply. $data[$key] = 0; $task = 'apply'; } // Access check. if (!$this->allowSave($data, $key)) { $this->setError(JText::_('JLIB_APPLICATION_ERROR_SAVE_NOT_PERMITTED')); $this->setMessage($this->getError(), 'error'); $this->setRedirect( JRoute::_( 'index.php?option=' . $this->option . '&view=' . $this->view_list . $this->getRedirectToListAppend(), false ) ); return false; } // Validate the posted data. // Sometimes the form needs some posted data, such as for plugins and modules. $form = $model->getForm($data, false); if (!$form) { $app->enqueueMessage($model->getError(), 'error'); return false; } // Test whether the data is valid. $validData = $model->validate($form, $data); // Check for validation errors. if ($validData === false) { // Get the validation messages. $errors = $model->getErrors(); // Push up to three validation messages out to the user. for ($i = 0, $n = count($errors); $i < $n && $i < 3; $i++) { if ($errors[$i] instanceof Exception) { $app->enqueueMessage($errors[$i]->getMessage(), 'warning'); } else { $app->enqueueMessage($errors[$i], 'warning'); } } // Save the data in the session. $app->setUserState($context . '.data', $data); // Redirect back to the edit screen. $this->setRedirect( JRoute::_( 'index.php?option=' . $this->option . '&view=' . $this->view_item . $this->getRedirectToItemAppend($recordId, $urlVar), false ) ); return false; } // Attempt to save the data. if (!$model->save($validData)) { // Save the data in the session. $app->setUserState($context . '.data', $validData); // Redirect back to the edit screen. $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_SAVE_FAILED', $model->getError())); $this->setMessage($this->getError(), 'error'); $this->setRedirect( JRoute::_( 'index.php?option=' . $this->option . '&view=' . $this->view_item . $this->getRedirectToItemAppend($recordId, $urlVar), false ) ); return false; } // Save succeeded, so check-in the record. if ($checkin && $model->checkin($validData[$key]) === false) { // Save the data in the session. $app->setUserState($context . '.data', $validData); // Check-in failed, so go back to the record and display a notice. $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_CHECKIN_FAILED', $model->getError())); $this->setMessage($this->getError(), 'error'); $this->setRedirect( JRoute::_( 'index.php?option=' . $this->option . '&view=' . $this->view_item . $this->getRedirectToItemAppend($recordId, $urlVar), false ) ); return false; } $this->setMessage( JText::_( ($lang->hasKey($this->text_prefix . ($recordId == 0 && $app->isSite() ? '_SUBMIT' : '') . '_SAVE_SUCCESS') ? $this->text_prefix : 'JLIB_APPLICATION') . ($recordId == 0 && $app->isSite() ? '_SUBMIT' : '') . '_SAVE_SUCCESS' ) ); // Redirect the user and adjust session state based on the chosen task. switch ($task) { case 'apply': // Set the record data in the session. $recordId = $model->getState($this->context . '.id'); $this->holdEditId($context, $recordId); $app->setUserState($context . '.data', null); $model->checkout($recordId); // Redirect back to the edit screen. $this->setRedirect( JRoute::_( 'index.php?option=' . $this->option . '&view=' . $this->view_item . $this->getRedirectToItemAppend($recordId, $urlVar), false ) ); break; case 'save2new': // Clear the record id and data from the session. $this->releaseEditId($context, $recordId); $app->setUserState($context . '.data', null); // Redirect back to the edit screen. $this->setRedirect( JRoute::_( 'index.php?option=' . $this->option . '&view=' . $this->view_item . $this->getRedirectToItemAppend(null, $urlVar), false ) ); break; default: // Clear the record id and data from the session. $this->releaseEditId($context, $recordId); $app->setUserState($context . '.data', null); // Redirect to the list screen. $this->setRedirect( JRoute::_( 'index.php?option=' . $this->option . '&view=' . $this->view_list . $this->getRedirectToListAppend(), false ) ); break; } // Invoke the postSave method to allow for the child class to access the model. $this->postSaveHook($model, $validData); return true; } } component/modelitem.php000066600000002153151372744100011247 0ustar00filter_fields = $config['filter_fields']; } // Guess the context as Option.ModelName. if (empty($this->context)) { $this->context = strtolower($this->option . '.' . $this->getName()); } } /** * Method to cache the last query constructed. * * This method ensures that the query is constructed only once for a given state of the model. * * @return JDatabaseQuery A JDatabaseQuery object * * @since 11.1 */ protected function _getListQuery() { // Capture the last store id used. static $lastStoreId; // Compute the current store id. $currentStoreId = $this->getStoreId(); // If the last store id is different from the current, refresh the query. if ($lastStoreId != $currentStoreId || empty($this->query)) { $lastStoreId = $currentStoreId; $this->query = $this->getListQuery(); } return $this->query; } /** * Method to get an array of data items. * * @return mixed An array of data items on success, false on failure. * * @since 11.1 */ public function getItems() { // Get a storage key. $store = $this->getStoreId(); // Try to load the data from internal storage. if (isset($this->cache[$store])) { return $this->cache[$store]; } // Load the list items. $query = $this->_getListQuery(); $items = $this->_getList($query, $this->getStart(), $this->getState('list.limit')); // Check for a database error. if ($this->_db->getErrorNum()) { $this->setError($this->_db->getErrorMsg()); return false; } // Add the items to the internal cache. $this->cache[$store] = $items; return $this->cache[$store]; } /** * Method to get a JDatabaseQuery object for retrieving the data set from a database. * * @return JDatabaseQuery A JDatabaseQuery object to retrieve the data set. * * @since 11.1 */ protected function getListQuery() { $db = $this->getDbo(); $query = $db->getQuery(true); return $query; } /** * Method to get a JPagination object for the data set. * * @return JPagination A JPagination object for the data set. * * @since 11.1 */ public function getPagination() { // Get a storage key. $store = $this->getStoreId('getPagination'); // Try to load the data from internal storage. if (isset($this->cache[$store])) { return $this->cache[$store]; } // Create the pagination object. jimport('joomla.html.pagination'); $limit = (int) $this->getState('list.limit') - (int) $this->getState('list.links'); $page = new JPagination($this->getTotal(), $this->getStart(), $limit); // Add the object to the internal cache. $this->cache[$store] = $page; return $this->cache[$store]; } /** * Method to get a store id based on the model configuration state. * * This is necessary because the model is used by the component and * different modules that might need different sets of data or different * ordering requirements. * * @param string $id An identifier string to generate the store id. * * @return string A store id. * * @since 11.1 */ protected function getStoreId($id = '') { // Add the list state to the store id. $id .= ':' . $this->getState('list.start'); $id .= ':' . $this->getState('list.limit'); $id .= ':' . $this->getState('list.ordering'); $id .= ':' . $this->getState('list.direction'); return md5($this->context . ':' . $id); } /** * Method to get the total number of items for the data set. * * @return integer The total number of items available in the data set. * * @since 11.1 */ public function getTotal() { // Get a storage key. $store = $this->getStoreId('getTotal'); // Try to load the data from internal storage. if (isset($this->cache[$store])) { return $this->cache[$store]; } // Load the total. $query = $this->_getListQuery(); $total = (int) $this->_getListCount($query); // Check for a database error. if ($this->_db->getErrorNum()) { $this->setError($this->_db->getErrorMsg()); return false; } // Add the total to the internal cache. $this->cache[$store] = $total; return $this->cache[$store]; } /** * Method to get the starting number of items for the data set. * * @return integer The starting number of items available in the data set. * * @since 11.1 */ public function getStart() { $store = $this->getStoreId('getstart'); // Try to load the data from internal storage. if (isset($this->cache[$store])) { return $this->cache[$store]; } $start = $this->getState('list.start'); $limit = $this->getState('list.limit'); $total = $this->getTotal(); if ($start > $total - $limit) { $start = max(0, (int) (ceil($total / $limit) - 1) * $limit); } // Add the total to the internal cache. $this->cache[$store] = $start; return $this->cache[$store]; } /** * Method to auto-populate the model state. * * This method should only be called once per instantiation and is designed * to be called on the first call to the getState() method unless the model * configuration flag to ignore the request is set. * * Note. Calling getState in this method will result in recursion. * * @param string $ordering An optional ordering field. * @param string $direction An optional direction (asc|desc). * * @return void * * @since 11.1 */ protected function populateState($ordering = null, $direction = null) { // If the context is set, assume that stateful lists are used. if ($this->context) { $app = JFactory::getApplication(); $value = $app->getUserStateFromRequest('global.list.limit', 'limit', $app->getCfg('list_limit'), 'uint'); $limit = $value; $this->setState('list.limit', $limit); $value = $app->getUserStateFromRequest($this->context . '.limitstart', 'limitstart', 0); $limitstart = ($limit != 0 ? (floor($value / $limit) * $limit) : 0); $this->setState('list.start', $limitstart); // Check if the ordering field is in the white list, otherwise use the incoming value. $value = $app->getUserStateFromRequest($this->context . '.ordercol', 'filter_order', $ordering); if (!in_array($value, $this->filter_fields)) { $value = $ordering; $app->setUserState($this->context . '.ordercol', $value); } $this->setState('list.ordering', $value); // Check if the ordering direction is valid, otherwise use the incoming value. $value = $app->getUserStateFromRequest($this->context . '.orderdirn', 'filter_order_Dir', $direction); if (!in_array(strtoupper($value), array('ASC', 'DESC', ''))) { $value = $direction; $app->setUserState($this->context . '.orderdirn', $value); } $this->setState('list.direction', $value); } else { $this->setState('list.start', 0); $this->state->set('list.limit', 0); } } /** * Gets the value of a user state variable and sets it in the session * * This is the same as the method in JApplication except that this also can optionally * force you back to the first page when a filter has changed * * @param string $key The key of the user state variable. * @param string $request The name of the variable passed in a request. * @param string $default The default value for the variable if not found. Optional. * @param string $type Filter for the variable, for valid values see {@link JFilterInput::clean()}. Optional. * @param boolean $resetPage If true, the limitstart in request is set to zero * * @return The request user state. * * @since 11.1 */ public function getUserStateFromRequest($key, $request, $default = null, $type = 'none', $resetPage = true) { $app = JFactory::getApplication(); $old_state = $app->getUserState($key); $cur_state = (!is_null($old_state)) ? $old_state : $default; $new_state = JRequest::getVar($request, null, 'default', $type); if (($cur_state != $new_state) && ($resetPage)) { JRequest::setVar('limitstart', 0); } // Save the new value only if it is set in this request. if ($new_state !== null) { $app->setUserState($key, $new_state); } else { $new_state = $cur_state; } return $new_state; } } component/.htaccess000066600000000177151372744100010361 0ustar00 Order allow,deny Deny from all component/view.php000066600000043303151372744100010244 0ustar00 array(), 'helper' => array()); /** * The name of the default template source file. * * @var string */ protected $_template = null; /** * The output of the template script. * * @var string */ protected $_output = null; /** * Callback for escaping. * * @var string */ protected $_escape = 'htmlspecialchars'; /** * Charset to use in escaping mechanisms; defaults to urf8 (UTF-8) * * @var string */ protected $_charset = 'UTF-8'; /** * Constructor * * @param array $config A named configuration array for object construction.
* name: the name (optional) of the view (defaults to the view class name suffix).
* charset: the character set to use for display
* escape: the name (optional) of the function to use for escaping strings
* base_path: the parent path (optional) of the views directory (defaults to the component folder)
* template_plath: the path (optional) of the layout directory (defaults to base_path + /views/ + view name
* helper_path: the path (optional) of the helper files (defaults to base_path + /helpers/)
* layout: the layout (optional) to use to display the view
* * @since 11.1 */ public function __construct($config = array()) { // Set the view name if (empty($this->_name)) { if (array_key_exists('name', $config)) { $this->_name = $config['name']; } else { $this->_name = $this->getName(); } } // Set the charset (used by the variable escaping functions) if (array_key_exists('charset', $config)) { $this->_charset = $config['charset']; } // User-defined escaping callback if (array_key_exists('escape', $config)) { $this->setEscape($config['escape']); } // Set a base path for use by the view if (array_key_exists('base_path', $config)) { $this->_basePath = $config['base_path']; } else { $this->_basePath = JPATH_COMPONENT; } // Set the default template search path if (array_key_exists('template_path', $config)) { // User-defined dirs $this->_setPath('template', $config['template_path']); } else { $this->_setPath('template', $this->_basePath . '/views/' . $this->getName() . '/tmpl'); } // Set the default helper search path if (array_key_exists('helper_path', $config)) { // User-defined dirs $this->_setPath('helper', $config['helper_path']); } else { $this->_setPath('helper', $this->_basePath . '/helpers'); } // Set the layout if (array_key_exists('layout', $config)) { $this->setLayout($config['layout']); } else { $this->setLayout('default'); } $this->baseurl = JURI::base(true); } /** * Execute and display a template script. * * @param string $tpl The name of the template file to parse; automatically searches through the template paths. * * @return mixed A string if successful, otherwise a JError object. * * @see fetch() * @since 11.1 */ public function display($tpl = null) { $result = $this->loadTemplate($tpl); if ($result instanceof Exception) { return $result; } echo $result; } /** * Assigns variables to the view script via differing strategies. * * This method is overloaded; you can assign all the properties of * an object, an associative array, or a single value by name. * * You are not allowed to set variables that begin with an underscore; * these are either private properties for JView or private variables * within the template script itself. * * * $view = new JView; * * // Assign directly * $view->var1 = 'something'; * $view->var2 = 'else'; * * // Assign by name and value * $view->assign('var1', 'something'); * $view->assign('var2', 'else'); * * // Assign by assoc-array * $ary = array('var1' => 'something', 'var2' => 'else'); * $view->assign($obj); * * // Assign by object * $obj = new stdClass; * $obj->var1 = 'something'; * $obj->var2 = 'else'; * $view->assign($obj); * * * * @return boolean True on success, false on failure. */ public function assign() { // Get the arguments; there may be 1 or 2. $arg0 = @func_get_arg(0); $arg1 = @func_get_arg(1); // Assign by object if (is_object($arg0)) { // Assign public properties foreach (get_object_vars($arg0) as $key => $val) { if (substr($key, 0, 1) != '_') { $this->$key = $val; } } return true; } // Assign by associative array if (is_array($arg0)) { foreach ($arg0 as $key => $val) { if (substr($key, 0, 1) != '_') { $this->$key = $val; } } return true; } // Assign by string name and mixed value. // We use array_key_exists() instead of isset() because isset() // fails if the value is set to null. if (is_string($arg0) && substr($arg0, 0, 1) != '_' && func_num_args() > 1) { $this->$arg0 = $arg1; return true; } // $arg0 was not object, array, or string. return false; } /** * Assign variable for the view (by reference). * * You are not allowed to set variables that begin with an underscore; * these are either private properties for JView or private variables * within the template script itself. * * * $view = new JView; * * // Assign by name and value * $view->assignRef('var1', $ref); * * // Assign directly * $view->ref = &$var1; * * * @param string $key The name for the reference in the view. * @param mixed &$val The referenced variable. * * @return boolean True on success, false on failure. * * @since 11.1 */ public function assignRef($key, &$val) { if (is_string($key) && substr($key, 0, 1) != '_') { $this->$key = &$val; return true; } return false; } /** * Escapes a value for output in a view script. * * If escaping mechanism is either htmlspecialchars or htmlentities, uses * {@link $_encoding} setting. * * @param mixed $var The output to escape. * * @return mixed The escaped value. * * @since 11.1 */ public function escape($var) { if (in_array($this->_escape, array('htmlspecialchars', 'htmlentities'))) { return call_user_func($this->_escape, $var, ENT_COMPAT, $this->_charset); } return call_user_func($this->_escape, $var); } /** * Method to get data from a registered model or a property of the view * * @param string $property The name of the method to call on the model or the property to get * @param string $default The name of the model to reference or the default value [optional] * * @return mixed The return value of the method * * @since 11.1 */ public function get($property, $default = null) { // If $model is null we use the default model if (is_null($default)) { $model = $this->_defaultModel; } else { $model = strtolower($default); } // First check to make sure the model requested exists if (isset($this->_models[$model])) { // Model exists, let's build the method name $method = 'get' . ucfirst($property); // Does the method exist? if (method_exists($this->_models[$model], $method)) { // The method exists, let's call it and return what we get $result = $this->_models[$model]->$method(); return $result; } } // Degrade to JObject::get $result = parent::get($property, $default); return $result; } /** * Method to get the model object * * @param string $name The name of the model (optional) * * @return mixed JModel object * * @since 11.1 */ public function getModel($name = null) { if ($name === null) { $name = $this->_defaultModel; } return $this->_models[strtolower($name)]; } /** * Get the layout. * * @return string The layout name */ public function getLayout() { return $this->_layout; } /** * Get the layout template. * * @return string The layout template name */ public function getLayoutTemplate() { return $this->_layoutTemplate; } /** * Method to get the view name * * The model name by default parsed using the classname, or it can be set * by passing a $config['name'] in the class constructor * * @return string The name of the model * * @since 11.1 */ public function getName() { if (empty($this->_name)) { $r = null; if (!preg_match('/View((view)*(.*(view)?.*))$/i', get_class($this), $r)) { JError::raiseError(500, JText::_('JLIB_APPLICATION_ERROR_VIEW_GET_NAME')); } if (strpos($r[3], "view")) { JError::raiseWarning('SOME_ERROR_CODE', JText::_('JLIB_APPLICATION_ERROR_VIEW_GET_NAME_SUBSTRING')); } $this->_name = strtolower($r[3]); } return $this->_name; } /** * Method to add a model to the view. We support a multiple model single * view system by which models are referenced by classname. A caveat to the * classname referencing is that any classname prepended by JModel will be * referenced by the name without JModel, eg. JModelCategory is just * Category. * * @param JModel &$model The model to add to the view. * @param boolean $default Is this the default model? * * @return object The added model. * * @since 11.1 */ public function setModel(&$model, $default = false) { $name = strtolower($model->getName()); $this->_models[$name] = &$model; if ($default) { $this->_defaultModel = $name; } return $model; } /** * Sets the layout name to use * * @param string $layout The layout name or a string in format