Ejemplo n.º 1
0
 /**
  * Form validation handler to perform textual analysis on submitted form values.
  */
 public static function validateAnalysis(&$form, FormState $form_state)
 {
     if (!static::shouldValidate($form, $form_state)) {
         return;
     }
     /** @var \Drupal\mollom\Entity\Form $mollom_form */
     $mollom = $form_state->getValue('mollom');
     if (!$mollom['require_analysis']) {
         return FALSE;
     }
     // Perform textual analysis.
     $all_data = self::extractMollomValues($form_state->cleanValues(), $mollom['enabled_fields'], $mollom['mapping']);
     // Cancel processing upon invalid UTF-8 data.
     if ($all_data === FALSE) {
         return FALSE;
     }
     $data = $all_data;
     // Remove postId property; only used by submitForm().
     if (isset($data['postId'])) {
         unset($data['postId']);
     }
     $contentId = isset($mollom['contentId']) ? $mollom['contentId'] : NULL;
     if (!empty($contentId)) {
         $data['id'] = $contentId;
     }
     if (is_array($mollom['checks'])) {
         $data['checks'] = $mollom['checks'];
     }
     $data['strictness'] = $mollom['strictness'];
     if (isset($mollom['type'])) {
         $data['type'] = $mollom['type'];
     }
     if (in_array('spam', $data['checks']) && $mollom['unsure'] == 'binary') {
         $data['unsure'] = 0;
     }
     // Allow modules to alter data sent.
     \Drupal::moduleHandler()->alter('mollom_content', $data);
     /** @var \Drupal\mollom\API\DrupalClient $mollom */
     $mollom_service = \Drupal::service('mollom.client');
     $result = $mollom_service->checkContent($data);
     // Use all available data properties for log messages below.
     $data += $all_data;
     // Trigger global fallback behavior if there is a unexpected result.
     if (!is_array($result) || !isset($result['id'])) {
         return MollomUtilities::handleFallback();
     }
     // Set form values accordingly. Do not overwrite the entity ID.
     // @todo Rename 'id' to 'entity_id'.
     $result['contentId'] = $result['id'];
     unset($result['id']);
     // Store the response returned by Mollom.
     $form_state->setValue(array('mollom', 'response', 'content'), $result);
     $form_state->setValue('mollom', array_merge($mollom, $result));
     // Ensure the latest content ID is output as value.
     // form_set_value() is effectless, as this is not a element-level but a
     // form-level validation handler.
     $form['mollom']['contentId']['#value'] = $result['contentId'];
     // Prepare watchdog message teaser text.
     $teaser = '--';
     if (isset($data['postTitle'])) {
         $teaser = Unicode::truncate(strip_tags($data['postTitle']), 40);
     } elseif (isset($data['postBody'])) {
         $teaser = Unicode::truncate(strip_tags($data['postBody']), 40);
     }
     // Handle the profanity check result.
     if (isset($result['profanityScore']) && $result['profanityScore'] >= 0.5) {
         if ($mollom['discard']) {
             $form_state->setError($form, t('Your submission has triggered the profanity filter and will not be accepted until the inappropriate language is removed.'));
         } else {
             $form_state->setValue(['mollom', 'require_moderation'], TRUE);
         }
         Logger::addMessage(array('message' => 'Profanity: %teaser', 'arguments' => array('%teaser' => $teaser)));
     }
     // Handle the spam check result.
     // The Mollom API takes over state tracking for each content ID/session. The
     // spamClassification will usually turn into 'ham' after solving a CAPTCHA.
     // It may also change to 'spam', if the user replaced the values with very
     // spammy content. In any case, we always do what we are told to do.
     $form_state->setValue(['mollom', 'require_captcha'], FALSE);
     $form['mollom']['captcha']['#access'] = FALSE;
     if (isset($result['spamClassification'])) {
         switch ($result['spamClassification']) {
             case 'ham':
                 $message = SafeMarkup::format('Ham: %teaser', array('%teaser' => $teaser));
                 \Drupal::logger('mollom')->notice($message);
                 break;
             case 'spam':
                 if ($mollom['discard']) {
                     $form_state->setError($form, t('Your submission has triggered the spam filter and will not be accepted. @fp_message', array('@fp_message' => MollomUtilities::formatFalsePositiveMessage($form_state, $data))));
                 } else {
                     $form_state->setValue(array('mollom', 'require_moderation'), TRUE);
                 }
                 $message = SafeMarkup::format('Spam: %teaser', array('%teaser' => $teaser));
                 \Drupal::logger('mollom')->notice($message);
                 break;
             case 'unsure':
                 if ($mollom['unsure'] == 'moderate') {
                     $form_state->setValue(array('mollom', 'require_moderation'), TRUE);
                 } else {
                     $form_state->setValue(['mollom', 'captcha_response_id'], NULL);
                     $form['mollom']['captcha_response_id']['#value'] = NULL;
                     $form_state->setValue(array('mollom', 'require_captcha'), TRUE);
                     // Require a new CAPTCHA and throw an error.
                     $had_captcha = $form_state->get('mollom_had_captcha');
                     $form_state->setCached(FALSE);
                     // Set the CAPTCHA type required indicator.
                     $form_state->setValue(array('mollom', 'captcha_required'), $mollom['captcha_type']);
                     $form['mollom']['captcha_required']['#value'] = $mollom['captcha_type'];
                     $form['mollom']['captcha']['#access'] = TRUE;
                     if (!empty($had_captcha)) {
                         $form_state->setErrorByName('mollom][captcha', t('The word verification was not completed correctly. Please complete this new word verification and try again.  @fp_message', array('@fp_message' => MollomUtilities::formatFalsePositiveMessage($form_state, $data))));
                     } else {
                         $form_state->setErrorByName('mollom][captcha', t('To complete this form, please complete the word verification.'));
                     }
                 }
                 $message = SafeMarkup::format('Unsure: %teaser', array('%teaser' => $teaser));
                 \Drupal::logger('mollom')->notice($message);
                 break;
             case 'unknown':
             default:
                 // If we end up here, Mollom responded with a unknown spamClassification.
                 // Normally, this should not happen, but if it does, log it. As there
                 // could be multiple reasons for this, it is not safe to trigger the
                 // fallback mode.
                 $message = SafeMarkup::format('Unknown: %teaser', array('%teaser' => $teaser));
                 \Drupal::logger('mollom')->notice($message);
                 break;
         }
     }
 }
Ejemplo n.º 2
0
 /**
  * Assert any watchdog messages based on their severity.
  *
  * This function can be (repeatedly) invoked to assert new watchdog messages.
  * All watchdog messages with a higher severity than RfcLogLevel::NOTICE are
  * considered as "severe".
  *
  * @param $max_severity
  *   (optional) A maximum watchdog severity level message constant that log
  *   messages must have to pass the assertion. All messages with a higher
  *   severity will fail. Defaults to RfcLogLevel::NOTICE. If a severity level
  *   higher than RfcLogLevel::NOTICE is passed, then at least one severe message
  *   is expected.
  */
 protected function assertMollomWatchdogMessages($max_severity = RfcLogLevel::NOTICE)
 {
     // Ensure that all messages have been written before attempting to verify
     // them. Actions executed within the test class may lead to log messages,
     // but those get only logged when hook_exit() is triggered.
     // mollom.module may not be installed by a test and thus not loaded yet.
     //drupal_load('module', 'mollom');
     Logger::writeLog();
     $database = \Drupal::database();
     module_load_include('inc', 'dblog', 'dblog.admin');
     $this->messages = array();
     $query = $database->select('watchdog', 'w')->fields('w')->orderBy('w.timestamp', 'ASC');
     // The comparison logic applied in this function is a bit confusing, since
     // the values of watchdog severity level constants defined by RFC 3164 are
     // negated to their actual "severity level" meaning:
     // RfcLogLevel::EMERGENCY is 0, RfcLogLevel::NOTICE is 5, RfcLogLevel::DEBUG is 7.
     $fail_expected = $max_severity < RfcLogLevel::NOTICE;
     $had_severe_message = FALSE;
     foreach ($query->execute() as $row) {
         $this->messages[$row->wid] = $row;
         // Only messages with a maximum severity of $max_severity or less severe
         // messages must pass. More severe messages need to fail. See note about
         // severity level constant values above.
         $output = $this->formatMessage($row);
         if ($row->severity >= $max_severity) {
             // Visually separate debug log messages from other messages.
             if ($row->severity == RfcLogLevel::DEBUG) {
                 $this->error($output, 'User notice');
             } else {
                 $this->pass(Html::escape($row->type) . ' (' . $row->severity . '): ' . $output, t('Watchdog'));
             }
         } else {
             $this->fail(Html::escape($row->type) . ' (' . $row->severity . '): ' . $output, t('Watchdog'));
         }
         // In case a severe message is expected, non-severe messages always pass,
         // since we would trigger a false positive test failure otherwise.
         // However, in order to actually assert the expectation, there must have
         // been at least one severe log message.
         $had_severe_message = $had_severe_message || $row->severity < RfcLogLevel::NOTICE;
     }
     // Assert that there was a severe message, in case we expected one.
     if ($fail_expected && !$had_severe_message) {
         $this->fail(t('Severe log message was found.'), t('Watchdog'));
     }
     // Delete processed watchdog messages.
     if (!empty($this->messages)) {
         $seen_ids = array_keys($this->messages);
         $database->delete('watchdog')->condition('wid', $seen_ids, 'IN')->execute();
     }
 }
Ejemplo n.º 3
0
 /**
  * Returns the (last known) status of the configured Mollom API keys.
  *
  * @param bool $force
  *   (optional) Boolean whether to ignore the cached state and re-check.
  *   Defaults to FALSE.
  * @param bool $update
  *   (optional) Whether to update Mollom with locally stored configuration.
  *   Defaults to FALSE.
  *
  * @return array
  *   An associative array describing the current status of the module:
  *   - isConfigured: Boolean whether Mollom API keys have been configured.
  *   - isVerified: Boolean whether Mollom API keys have been verified.
  *   - response: The response error code of the API verification request.
  *   - ...: The full site resource, as returned by the Mollom API.
  *
  * @see mollom_requirements()
  */
 public static function getAPIKeyStatus($force = FALSE, $update = FALSE)
 {
     $testing_mode = (int) \Drupal::config('mollom.settings')->get('test_mode.enabled');
     /*
         $static_cache = &drupal_static(__FUNCTION__, array());
         $status = &$static_cache[$testing_mode];
     
         $drupal_cache = \Drupal::cache();
         $cid = 'mollom_status:' . $testing_mode;
         $expire_valid = 86400; // once per day
         $expire_invalid = 3600; // once per hour
     
         // Look for cached status.
         if (!$force) {
           if (isset($status)) {
             return $status;
           }
           else if ($cache = $drupal_cache->get($cid)) {
             return $cache->data;
           }
         }*/
     // Re-check configuration status.
     /** @var \Drupal\mollom\API\DrupalClient $mollom */
     $mollom = \Drupal::service('mollom.client');
     $status = array('isConfigured' => FALSE, 'isVerified' => FALSE, 'isTesting' => (bool) $testing_mode, 'response' => NULL, 'publicKey' => $mollom->loadConfiguration('publicKey'), 'privateKey' => $mollom->loadConfiguration('privateKey'), 'expectedLanguages' => $mollom->loadConfiguration('expectedLanguages'));
     $status['isConfigured'] = !empty($status['publicKey']) && !empty($status['privateKey']);
     $status['expectedLanguages'] = is_array($status['expectedLanguages']) ? array_values($status['expectedLanguages']) : [];
     if ($testing_mode || $status['isConfigured']) {
         $old_status = $status;
         $data = array();
         if ($update) {
             // Ensure to use the most current API keys (might have been changed).
             $mollom->publicKey = $status['publicKey'];
             $mollom->privateKey = $status['privateKey'];
             $data += array('expectedLanguages' => $status['expectedLanguages']);
         }
         $data += $mollom->getClientInformation();
         $response = $mollom->updateSite($data);
         if (is_array($response) && $mollom->lastResponseCode === TRUE) {
             $status = array_merge($status, $response);
             $status['isVerified'] = TRUE;
             Logger::addMessage(array('message' => 'API keys are valid.'), RfcLogLevel::INFO);
             // Unless we just updated, update local configuration with remote.
             if ($update) {
                 if ($old_status['expectedLanguages'] != $status['expectedLanguages']) {
                     $mollom->saveConfiguration('expectedLanguages', is_array($status['expectedLanguages']) ? $status['expectedLanguages'] : explode(',', $status['expectedLanguages']));
                 }
             }
         } elseif ($response === $mollom::AUTH_ERROR) {
             $status['response'] = $response;
             Logger::addMessage(array('message' => 'Invalid API keys.'), RfcLogLevel::ERROR);
         } elseif ($response === $mollom::REQUEST_ERROR) {
             $status['response'] = $response;
             Logger::addMessage(array('message' => 'Invalid client configuration.'), RfcLogLevel::ERROR);
         } else {
             $status['response'] = $response;
             // A NETWORK_ERROR and other possible responses may be caused by the
             // client-side environment, but also by Mollom service downtimes. Try to
             // recover as soon as possible.
             $expire_invalid = 60 * 5;
             Logger::addMessage(array('message' => 'API keys could not be verified.'), RfcLogLevel::ERROR);
         }
     }
     //$drupal_cache->set($cid, $status, $status['isVerified'] === TRUE ? $expire_valid : $expire_invalid);
     return $status;
 }
 /**
  * Implements Mollom::request().
  */
 protected function request($method, $server, $path, $query = NULL, array $headers = array())
 {
     $options = array('timeout' => $this->requestTimeout);
     if (isset($query)) {
         if ($method === 'GET') {
             $path .= '?' . $query;
         } else {
             $options['body'] = $query;
         }
     }
     $request = new Request($method, $server . '/' . $path, $headers);
     try {
         $response = $this->client->send($request, $options);
     } catch (\Exception $e) {
         //Logger::addMessage(array('message' => 'Response error: <pre>' . print_r($e, TRUE) . '</pre>'));
         if ($e instanceof ClientException) {
             $mollom_response = array('code' => $e->getCode(), 'message' => $e->getResponse()->getReasonPhrase(), 'headers' => $e->getResponse()->getHeaders(), 'body' => $e->getResponse()->getBody());
         } else {
             Logger::addMessage(array('message' => 'failed to connect. Message !message', 'arguments' => array('!message' => $e->getMessage())), RfcLogLevel::ERROR);
             return (object) array('code' => '0', 'message' => $e->getMessage(), 'headers' => array(), 'body' => '');
         }
     }
     if (empty($mollom_response)) {
         $mollom_response = array('code' => $response->getStatusCode(), 'message' => $response->getStatusCode() >= 200 && $response->getStatusCode() < 300 ? $response->getReasonPhrase() : NULL, 'headers' => $response->getHeaders(), 'body' => $response->getBody());
     }
     // Convert headers to expected and consistent format.
     $headers = array();
     foreach ($mollom_response['headers'] as $key => $header) {
         $headers[Unicode::strtolower($key)] = $header[0];
     }
     $mollom_response['headers'] = $headers;
     return (object) $mollom_response;
 }
Ejemplo n.º 5
0
 /**
  * Send feedback to Mollom.
  *
  * @param $data
  *   A Mollom data record containing one or both of:
  *   - contentId: The content ID to send feedback for.
  *   - captchaId: The CAPTCHA ID to send feedback for.
  * @param $reason
  *   The feedback to send, one of 'spam', 'profanity', 'quality', 'unwanted',
  *   'approve'.
  * @param $type
  *   The type of feedback, one of 'moderate' or 'flag'.
  * @param $source
  *   An optional single word string identifier for the user interface source.
  *   This is tracked along with the feedback to provide a more complete picture
  *   of how feedback is used and submitted on the site.
  */
 protected static function sendFeedbackToMollom($data, $reason = 'spam', $type = 'moderate', $source = NULL)
 {
     $params = array();
     $current_user = \Drupal::currentUser();
     if (!empty($data->captchaId)) {
         $params['captchaId'] = $data->captchaId;
         $resource = 'CAPTCHA';
         $id = $data->captchaId;
     }
     // In case we also have a contentId, also pass that, and override $resource
     // and $id for the log message.
     if (!empty($data->contentId)) {
         $params['contentId'] = $data->contentId;
         $resource = 'content';
         $id = $data->contentId;
     }
     if (!isset($id)) {
         return FALSE;
     }
     $params += array('reason' => $reason, 'type' => $type, 'authorIp' => \Drupal::request()->getClientIp());
     if (!empty($source)) {
         $params['source'] = $source;
     }
     if ($current_user->isAuthenticated()) {
         $params['authorId'] = $current_user->id();
     }
     $result = \Drupal::service('mollom.client')->sendFeedback($params);
     Logger::addMessage(array('message' => 'Reported %feedback for @resource %id from %source - %type.', 'arguments' => array('%type' => $type, '%feedback' => $reason, '@resource' => $resource, '%id' => $id, '%source' => $source)));
     return $result;
 }
 /**
  * Implements after all other processing.
  */
 function onTerminate()
 {
     Logger::writeLog();
 }