diff --git a/administrator/components/com_admin/sql/updates/mysql/3.4.0-2014-12-04.sql b/administrator/components/com_admin/sql/updates/mysql/3.4.0-2014-12-04.sql new file mode 100644 index 0000000000000..e968d2b1df4a1 --- /dev/null +++ b/administrator/components/com_admin/sql/updates/mysql/3.4.0-2014-12-04.sql @@ -0,0 +1,2 @@ +INSERT INTO `#__extensions` (`extension_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `manifest_cache`, `params`, `custom_data`, `system_data`, `checked_out`, `checked_out_time`, `ordering`, `state`) VALUES +(452, 'plg_captcha_nocaptcha', 'plugin', 'nocaptcha', 'captcha', 0, 0, 1, 0, '', '{"public_key":"","private_key":"","theme":"light"}', '', '', 0, '0000-00-00 00:00:00', 0, 0); \ No newline at end of file diff --git a/administrator/components/com_admin/sql/updates/postgresql/3.4.0-2014-12-04.sql b/administrator/components/com_admin/sql/updates/postgresql/3.4.0-2014-12-04.sql new file mode 100644 index 0000000000000..2a621319cbede --- /dev/null +++ b/administrator/components/com_admin/sql/updates/postgresql/3.4.0-2014-12-04.sql @@ -0,0 +1,2 @@ +INSERT INTO "#__extensions" ("extension_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "manifest_cache", "params", "custom_data", "system_data", "checked_out", "checked_out_time", "ordering", "state") VALUES +(452, 'plg_captcha_nocaptcha', 'plugin', 'nocaptcha', 'captcha', 0, 0, 1, 0, '', '{"public_key":"","private_key":"","theme":"light"}', '', '', 0, '1970-01-01 00:00:00', 0, 0); \ No newline at end of file diff --git a/administrator/components/com_admin/sql/updates/sqlazure/3.4.0-2014-12-04.sql b/administrator/components/com_admin/sql/updates/sqlazure/3.4.0-2014-12-04.sql new file mode 100644 index 0000000000000..585fbbcc7e805 --- /dev/null +++ b/administrator/components/com_admin/sql/updates/sqlazure/3.4.0-2014-12-04.sql @@ -0,0 +1,6 @@ +SET IDENTITY_INSERT [#__extensions] ON; + +INSERT [#__extensions] ([extension_id], [name], [type], [element], [folder], [client_id], [enabled], [access], [protected], [manifest_cache], [params], [custom_data], [system_data], [checked_out], [checked_out_time], [ordering], [state]) +SELECT 452, 'plg_captcha_nocaptcha', 'plugin', 'nocaptcha', 'captcha', 0, 0, 1, 0, '', '{"public_key":"","private_key":"","theme":"light"}', '', '', 0, '1900-01-01 00:00:00', 0, 0; + +SET IDENTITY_INSERT [#__extensions] OFF; diff --git a/administrator/components/com_content/views/articles/view.html.php b/administrator/components/com_content/views/articles/view.html.php index b770b0620eaf9..3322d66d19f96 100644 --- a/administrator/components/com_content/views/articles/view.html.php +++ b/administrator/components/com_content/views/articles/view.html.php @@ -125,6 +125,15 @@ protected function addToolbar() $bar->appendButton('Custom', $dhtml, 'batch'); } + if ($this->state->get('filter.published') == -2 && $canDo->get('core.delete')) + { + JToolbarHelper::deleteList('', 'articles.delete', 'JTOOLBAR_EMPTY_TRASH'); + } + elseif ($canDo->get('core.edit.state')) + { + JToolbarHelper::trash('articles.trash'); + } + if ($user->authorise('core.admin', 'com_content') || $user->authorise('core.options', 'com_content')) { JToolbarHelper::preferences('com_content'); diff --git a/administrator/components/com_installer/models/install.php b/administrator/components/com_installer/models/install.php index 8e7818372ca67..72690d5211aa1 100644 --- a/administrator/components/com_installer/models/install.php +++ b/administrator/components/com_installer/models/install.php @@ -158,12 +158,14 @@ public function install() // There was an error installing the package. $msg = JText::sprintf('COM_INSTALLER_INSTALL_ERROR', JText::_('COM_INSTALLER_TYPE_TYPE_' . strtoupper($package['type']))); $result = false; + $msgType = 'error'; } else { // Package installed sucessfully. $msg = JText::sprintf('COM_INSTALLER_INSTALL_SUCCESS', JText::_('COM_INSTALLER_TYPE_TYPE_' . strtoupper($package['type']))); $result = true; + $msgType = 'message'; } // This event allows a custom a post-flight: @@ -171,7 +173,7 @@ public function install() // Set some model state values. $app = JFactory::getApplication(); - $app->enqueueMessage($msg); + $app->enqueueMessage($msg, $msgType); $this->setState('name', $installer->get('name')); $this->setState('result', $result); $app->setUserState('com_installer.message', $installer->message); diff --git a/administrator/language/en-GB/en-GB.plg_captcha_nocaptcha.ini b/administrator/language/en-GB/en-GB.plg_captcha_nocaptcha.ini new file mode 100644 index 0000000000000..296318e48f8e9 --- /dev/null +++ b/administrator/language/en-GB/en-GB.plg_captcha_nocaptcha.ini @@ -0,0 +1,23 @@ +; Joomla! Project +; Copyright (C) 2005 - 2014 Open Source Matters. All rights reserved. +; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php +; Note : All ini files need to be saved as UTF-8 + +PLG_CAPTCHA_NOCAPTCHA_XML_DESCRIPTION="This CAPTCHA plugin uses the reCAPTCHA service to prevent spammers. To get a site and secret key for your domain, go to http://www.google.com/recaptcha. To use this for new account registration, go to Options in the User Manager and select Captcha - NoCAPTCHA as the Captcha." +PLG_CAPTCHA_NOCAPTCHA="Captcha - NoCAPTCHA" + +; Params +PLG_NOCAPTCHA_PUBLIC_KEY_LABEL="Site key" +PLG_NOCAPTCHA_PUBLIC_KEY_DESC="Used in the JavaScript code that is served to your users. See the plugin description for instructions on getting a site key." +PLG_NOCAPTCHA_PRIVATE_KEY_LABEL="Secret key" +PLG_NOCAPTCHA_PRIVATE_KEY_DESC="Used in the communication between your server and the reCAPTCHA server. Be sure to keep it a secret. See the plugin description for instructions on getting a secret key." +PLG_NOCAPTCHA_THEME_LABEL="Theme" +PLG_NOCAPTCHA_THEME_DESC="Defines which theme to use for NoCAPTCHA." +PLG_NOCAPTCHA_THEME_LIGHT="Light" +PLG_NOCAPTCHA_THEME_DARK="Dark" + +; Error messages +PLG_NOCAPTCHA_ERROR_NO_PRIVATE_KEY="The NoCAPTCHA plugin needs a secret key to be set in its parameters. Please contact a site administrator." +PLG_NOCAPTCHA_ERROR_NO_PUBLIC_KEY="The NoCAPTCHA plugin needs a site key to be set in its parameters. Please contact a site administrator." +PLG_NOCAPTCHA_ERROR_NOT_SET="Please complete the security question." +PLG_NOCAPTCHA_ERROR_NO_IP="For security reasons, you must pass the remote ip address to NoCAPTCHA" diff --git a/administrator/language/en-GB/en-GB.plg_captcha_nocaptcha.sys.ini b/administrator/language/en-GB/en-GB.plg_captcha_nocaptcha.sys.ini new file mode 100644 index 0000000000000..51fb35a66a14a --- /dev/null +++ b/administrator/language/en-GB/en-GB.plg_captcha_nocaptcha.sys.ini @@ -0,0 +1,7 @@ +; Joomla! Project +; Copyright (C) 2005 - 2014 Open Source Matters. All rights reserved. +; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php +; Note : All ini files need to be saved as UTF-8 + +PLG_CAPTCHA_NOCAPTCHA_XML_DESCRIPTION="This CAPTCHA plugin uses the reCAPTCHA service to prevent spammers. To get a site and secret key for your domain, go to http://www.google.com/recaptcha. To use this for new account registration, go to Options in the User Manager and select Captcha - NoCAPTCHA as the Captcha." +PLG_CAPTCHA_NOCAPTCHA="Captcha - NoCAPTCHA" diff --git a/administrator/language/en-GB/install.xml b/administrator/language/en-GB/install.xml index f3325e1101180..9a28acf192462 100644 --- a/administrator/language/en-GB/install.xml +++ b/administrator/language/en-GB/install.xml @@ -113,6 +113,8 @@ en-GB.plg_authentication_joomla.sys.ini en-GB.plg_authentication_ldap.ini en-GB.plg_authentication_ldap.sys.ini + en-GB.plg_captcha_nocaptcha.ini + en-GB.plg_captcha_nocaptcha.sys.ini en-GB.plg_captcha_recaptcha.ini en-GB.plg_captcha_recaptcha.sys.ini en-GB.plg_content_emailcloak.ini diff --git a/administrator/templates/isis/css/template-rtl.css b/administrator/templates/isis/css/template-rtl.css index c0e6f4653dc71..56d8ef7f47b63 100644 --- a/administrator/templates/isis/css/template-rtl.css +++ b/administrator/templates/isis/css/template-rtl.css @@ -7964,6 +7964,9 @@ input.input-large-text { overflow: hidden; position: relative; } +.editor textarea.mce_editable { + box-sizing: border-box; +} a.grid_false { display: inline-block; height: 16px; diff --git a/administrator/templates/isis/css/template.css b/administrator/templates/isis/css/template.css index 1e5c4989969ec..c82c6fe6a1acf 100644 --- a/administrator/templates/isis/css/template.css +++ b/administrator/templates/isis/css/template.css @@ -7964,6 +7964,9 @@ input.input-large-text { overflow: hidden; position: relative; } +.editor textarea.mce_editable { + box-sizing: border-box; +} a.grid_false { display: inline-block; height: 16px; diff --git a/administrator/templates/isis/less/template.less b/administrator/templates/isis/less/template.less index b2878e6140926..92fb01bc4e6a1 100644 --- a/administrator/templates/isis/less/template.less +++ b/administrator/templates/isis/less/template.less @@ -1038,6 +1038,9 @@ input.input-large-text { overflow: hidden; position: relative } +.editor textarea.mce_editable { + box-sizing: border-box; +} /* For grid.boolean */ a.grid_false { diff --git a/build/phpcs/Joomla/ruleset.xml b/build/phpcs/Joomla/ruleset.xml index a3076b9983c01..a939d345ccc13 100644 --- a/build/phpcs/Joomla/ruleset.xml +++ b/build/phpcs/Joomla/ruleset.xml @@ -23,6 +23,7 @@ configuration.php libraries/ClassLoader.php libraries/composer_autoload.php + plugins/captcha/nocaptcha/recaptchalib.php diff --git a/installation/sql/mysql/joomla.sql b/installation/sql/mysql/joomla.sql index 3bdf389d828b4..2c9619e85dd39 100644 --- a/installation/sql/mysql/joomla.sql +++ b/installation/sql/mysql/joomla.sql @@ -610,6 +610,7 @@ INSERT INTO `#__extensions` (`extension_id`, `name`, `type`, `element`, `folder` (449, 'plg_authentication_cookie', 'plugin', 'cookie', 'authentication', 0, 1, 1, 0, '', '', '', '', 0, '0000-00-00 00:00:00', 0, 0), (450, 'plg_twofactorauth_yubikey', 'plugin', 'yubikey', 'twofactorauth', 0, 0, 1, 0, '', '', '', '', 0, '0000-00-00 00:00:00', 0, 0), (451, 'plg_search_tags', 'plugin', 'tags', 'search', 0, 1, 1, 0, '', '{"search_limit":"50","show_tagged_items":"1"}', '', '', 0, '0000-00-00 00:00:00', 0, 0), +(452, 'plg_captcha_nocaptcha', 'plugin', 'nocaptcha', 'captcha', 0, 0, 1, 0, '', '{"public_key":"","private_key":"","theme":"light"}', '', '', 0, '0000-00-00 00:00:00', 0, 0), (503, 'beez3', 'template', 'beez3', '', 0, 1, 1, 0, '', '{"wrapperSmall":"53","wrapperLarge":"72","sitetitle":"","sitedescription":"","navposition":"center","templatecolor":"nature"}', '', '', 0, '0000-00-00 00:00:00', 0, 0), (504, 'hathor', 'template', 'hathor', '', 1, 1, 1, 0, '', '{"showSiteName":"0","colourChoice":"0","boldText":"0"}', '', '', 0, '0000-00-00 00:00:00', 0, 0), (506, 'protostar', 'template', 'protostar', '', 0, 1, 1, 0, '', '{"templateColor":"","logoFile":"","googleFont":"1","googleFontName":"Open+Sans","fluidContainer":"0"}', '', '', 0, '0000-00-00 00:00:00', 0, 0), diff --git a/installation/sql/postgresql/joomla.sql b/installation/sql/postgresql/joomla.sql index 4d059a3d845ce..c586deb669c78 100644 --- a/installation/sql/postgresql/joomla.sql +++ b/installation/sql/postgresql/joomla.sql @@ -609,7 +609,8 @@ INSERT INTO "#__extensions" ("extension_id", "name", "type", "element", "folder" (448, 'plg_twofactorauth_totp', 'plugin', 'totp', 'twofactorauth', 0, 0, 1, 0, '', '', '', '', 0, '1970-01-01 00:00:00', 0, 0), (449, 'plg_authentication_cookie', 'plugin', 'cookie', 'authentication', 0, 1, 1, 0, '', '', '', '', 0, '1970-01-01 00:00:00', 0, 0), (450, 'plg_twofactorauth_yubikey', 'plugin', 'yubikey', 'twofactorauth', 0, 0, 1, 0, '', '', '', '', 0, '1970-01-01 00:00:00', 0, 0), -(451, 'plg_search_tags', 'plugin', 'tags', 'search', 0, 1, 1, 0, '', '{"search_limit":"50","show_tagged_items":"1"}', '', '', 0, '1970-01-01 00:00:00', 0, 0); +(451, 'plg_search_tags', 'plugin', 'tags', 'search', 0, 1, 1, 0, '', '{"search_limit":"50","show_tagged_items":"1"}', '', '', 0, '1970-01-01 00:00:00', 0, 0), +(452, 'plg_captcha_nocaptcha', 'plugin', 'nocaptcha', 'captcha', 0, 0, 1, 0, '', '{"public_key":"","private_key":"","theme":"light"}', '', '', 0, '1970-01-01 00:00:00', 0, 0); -- Templates INSERT INTO "#__extensions" ("extension_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "manifest_cache", "params", "custom_data", "system_data", "checked_out", "checked_out_time", "ordering", "state") VALUES diff --git a/installation/sql/sqlazure/joomla.sql b/installation/sql/sqlazure/joomla.sql index 28364baf9babb..ec019dd655adb 100644 --- a/installation/sql/sqlazure/joomla.sql +++ b/installation/sql/sqlazure/joomla.sql @@ -1011,7 +1011,9 @@ SELECT 449, 'plg_authentication_cookie', 'plugin', 'cookie', 'authentication', 0 UNION ALL SELECT 450, 'plg_twofactorauth_yubikey', 'plugin', 'yubikey', 'twofactorauth', 0, 0, 1, 0, '', '', '', '', 0, '1900-01-01 00:00:00', 0, 0 UNION ALL -SELECT 451, 'plg_search_tags', 'plugin', 'tags', 'search', 0, 1, 1, 0, '', '{"search_limit":"50","show_tagged_items":"1"}', '', '', 0, '1900-01-01 00:00:00', 0, 0; +SELECT 451, 'plg_search_tags', 'plugin', 'tags', 'search', 0, 1, 1, 0, '', '{"search_limit":"50","show_tagged_items":"1"}', '', '', 0, '1900-01-01 00:00:00', 0, 0 +UNION ALL +SELECT 452, 'plg_captcha_nocaptcha', 'plugin', 'nocaptcha', 'captcha', 0, 0, 1, 0, '', '{"public_key":"","private_key":"","theme":"light"}', '', '', 0, '1900-01-01 00:00:00', 0, 0; INSERT [#__extensions] ([extension_id], [name], [type], [element], [folder], [client_id], [enabled], [access], [protected], [manifest_cache], [params], [custom_data], [system_data], [checked_out], [checked_out_time], [ordering], [state]) diff --git a/plugins/captcha/nocaptcha/index.html b/plugins/captcha/nocaptcha/index.html new file mode 100644 index 0000000000000..2efb97f319a35 --- /dev/null +++ b/plugins/captcha/nocaptcha/index.html @@ -0,0 +1 @@ + diff --git a/plugins/captcha/nocaptcha/nocaptcha.php b/plugins/captcha/nocaptcha/nocaptcha.php new file mode 100644 index 0000000000000..0c28d3e58fc3b --- /dev/null +++ b/plugins/captcha/nocaptcha/nocaptcha.php @@ -0,0 +1,141 @@ +params->get('public_key', ''); + $theme = $this->params->get('theme', 'light'); + + if ($public_key == null || $public_key == '') + { + throw new Exception(JText::_('PLG_NOCAPTCHA_ERROR_NO_PUBLIC_KEY')); + } + + $file = $app->isSSLConnection() ? 'https' : 'http'; + $file .= '://www.google.com/recaptcha/api.js?hl=' . JFactory::getLanguage() + ->getTag() . '&onload=onloadCallback&render=explicit'; + + JHtml::_('script', $file, true, true); + + $document->addScriptDeclaration('var onloadCallback = function() {' + . 'grecaptcha.render("' . $id . '", {sitekey: "' . $public_key . '", theme: "' . $theme . '"});' + . '}' + ); + + return true; + } + + /** + * Gets the challenge HTML + * + * @param string $name The name of the field. + * @param string $id The id of the field. + * @param string $class The class of the field. This should be passed as + * e.g. 'class="required"'. + * + * @return string The HTML to be embedded in the form. + * + * @since 3.4 + */ + public function onDisplay($name, $id = 'dynamic_recaptcha_1', $class = '') + { + return '
'; + } + + /** + * Calls an HTTP POST function to verify if the user's guess was correct + * + * @param string $code Answer provided by user. + * + * @return True if the answer is correct, false otherwise + * + * @since 3.4 + */ + public function onCheckAnswer($code) + { + $input = JFactory::getApplication()->input; + $privatekey = $this->params->get('private_key'); + $remoteip = $input->server->get('REMOTE_ADDR', '', 'string'); + $response = $input->get('g-recaptcha-response', '', 'string'); + + // Check for Private Key + if (empty($privatekey)) + { + $this->_subject->setError(JText::_('PLG_NOCAPTCHA_ERROR_NO_PRIVATE_KEY')); + + return false; + } + + // Check for IP + if (empty($remoteip)) + { + $this->_subject->setError(JText::_('PLG_NOCAPTCHA_ERROR_NO_IP')); + + return false; + } + + // Discard spam submissions + if ($response == null || strlen($response) == 0) + { + $this->_subject->setError(JText::_('PLG_NOCAPTCHA_ERROR_EMPTY_SOLUTION')); + + return false; + } + + require_once 'recaptchalib.php'; + + $reCaptcha = new JReCaptcha($privatekey); + $response = $reCaptcha->verifyResponse($remoteip, $response); + + if ( !isset($response->success) || !$response->success) + { + // @todo use exceptions here + foreach ($response->errorCodes as $error) + { + $this->_subject->setError($error); + } + + return false; + } + + return true; + } +} diff --git a/plugins/captcha/nocaptcha/nocaptcha.xml b/plugins/captcha/nocaptcha/nocaptcha.xml new file mode 100644 index 0000000000000..9291cbde0b23e --- /dev/null +++ b/plugins/captcha/nocaptcha/nocaptcha.xml @@ -0,0 +1,55 @@ + + + plg_captcha_nocaptcha + 3.0.0 + December 2014 + Joomla! Project + admin@joomla.org + www.joomla.org + Copyright (C) 2005 - 2014 Open Source Matters. All rights reserved. + GNU General Public License version 2 or later; see LICENSE.txt + PLG_CAPTCHA_NOCAPTCHA_XML_DESCRIPTION + + nocaptcha.php + + + +
+ + + + + + + + +
+
+
+
diff --git a/plugins/captcha/nocaptcha/recaptchalib.php b/plugins/captcha/nocaptcha/recaptchalib.php new file mode 100644 index 0000000000000..6bebdd52b595d --- /dev/null +++ b/plugins/captcha/nocaptcha/recaptchalib.php @@ -0,0 +1,146 @@ +" . self::$_signupUrl . ""); + } + $this->_secret = $secret; + } + + /** + * Encodes the given data into a query string format. + * + * @param array $data array of string elements to be encoded. + * + * @return string - encoded request. + */ + private function _encodeQS($data) + { + $req = ""; + foreach ($data as $key => $value) + { + $req .= $key . '=' . urlencode(stripslashes($value)) . '&'; + } + + // Cut the last '&' + $req = substr($req, 0, strlen($req) - 1); + + return $req; + } + + /** + * Submits an HTTP GET to a reCAPTCHA server. + * + * @param string $path url path to recaptcha server. + * @param array $data array of parameters to be sent. + * + * @return array response + */ + private function _submitHTTPGet($path, $data) + { + $req = $this->_encodeQS($data); + $response = file_get_contents($path . $req); + + return $response; + } + + /** + * Calls the reCAPTCHA siteverify API to verify whether the user passes + * CAPTCHA test. + * + * @param string $remoteIp IP address of end user. + * @param string $response response string from recaptcha verification. + * + * @return JReCaptchaResponse + */ + public function verifyResponse($remoteIp, $response) + { + // Discard empty solution submissions + if ($response == null || strlen($response) == 0) + { + $recaptchaResponse = new JReCaptchaResponse(); + $recaptchaResponse->success = false; + $recaptchaResponse->errorCodes = 'missing-input'; + + return $recaptchaResponse; + } + + $getResponse = $this->_submitHttpGet( + self::$_siteVerifyUrl, + array( + 'secret' => $this->_secret, + 'remoteip' => $remoteIp, + 'v' => self::$_version, + 'response' => $response + ) + ); + $answers = json_decode($getResponse, true); + $recaptchaResponse = new JReCaptchaResponse(); + + if (trim($answers['success']) == true) + { + $recaptchaResponse->success = true; + } + else + { + $recaptchaResponse->success = false; + $recaptchaResponse->errorCodes = isset($answers['error-codes']) ? $answers['error-codes'] : ''; + } + + return $recaptchaResponse; + } +} diff --git a/plugins/finder/categories/categories.php b/plugins/finder/categories/categories.php index ed2e30e552aae..65add732e1025 100644 --- a/plugins/finder/categories/categories.php +++ b/plugins/finder/categories/categories.php @@ -199,13 +199,11 @@ public function onFinderChangeState($context, $pks, $value) */ foreach ($pks as $pk) { - /* TODO: The $item variable does not seem to be used at all $query = clone($this->getStateQuery()); $query->where('a.id = ' . (int) $pk); $this->db->setQuery($query); $item = $this->db->loadObject(); - */ // Translate the state. $state = null; @@ -395,6 +393,7 @@ protected function getStateQuery() { $query = $this->db->getQuery(true) ->select($this->db->quoteName('a.id')) + ->select($this->db->quoteName('a.parent_id')) ->select('a.' . $this->state_field . ' AS state, c.published AS cat_state') ->select('a.access, c.access AS cat_access') ->from($this->db->quoteName('#__categories') . ' AS a')