Example #1
0
/**
 * Add status messages to the "Store administration" page.
 *
 * This hook is used to add items to the store status table on the main store
 * administration screen. Each item gets a row in the table that consists of a
 * status icon, title, and description. These items should be used to give
 * special instructions, notifications, or indicators for components of the cart
 * enabled by the modules. At a glance, a store owner should be able to look here
 * and see if a critical component of your module is not functioning properly.
 *
 * For example, if the catalog module is installed and it cannot find the catalog
 * taxonomy vocabulary, it will show an error message here to alert the store
 * administrator.
 *
 * @return
 *   An array of tore status items which are arrays with the following keys:
 *   - "status": "ok", "warning", or "error" depending on the message.
 *   - "title" The title of the status message or module that defines it.
 *   - "desc": The description; can be any message, including links to pages and
 *       forms that deal with the issue being reported.
 */
function hook_store_status()
{
    if ($key = uc_credit_encryption_key()) {
        $statuses[] = array('status' => 'ok', 'title' => t('Credit card encryption'), 'desc' => t('Credit card data in the database is currently being encrypted.'));
    }
    return $statuses;
}
Example #2
0
 /**
  * Overrides FieldPluginBase::render().
  */
 public function render(ResultRow $values)
 {
     // Initialize the encryption key and class.
     $key = uc_credit_encryption_key();
     $crypt = new Encryption();
     $data = unserialize($values->{$this->field_alias});
     if (isset($data['cc_data'])) {
         $cc_data = $crypt->decrypt($key, $data['cc_data']);
         if (strpos($cc_data, ':') === FALSE) {
             $cc_data = base64_decode($cc_data);
         }
         $cc_data = unserialize($cc_data);
         if (isset($cc_data[$this->definition['cc field']])) {
             return $cc_data[$this->definition['cc field']];
         }
     }
 }
 /**
  * Tests security settings configuration.
  */
 public function testSecuritySettings()
 {
     // TODO:  Still need tests with existing key file
     // where key file is not readable or doesn't contain a valid key
     // Create key directory, make it readable and writeable.
     \Drupal::service('file_system')->mkdir('sites/default/files/testkey', 0755);
     // Try to submit settings form without a key file path.
     // Save current variable, reset to its value when first installed.
     $config = \Drupal::configFactory()->getEditable('uc_credit.settings');
     $temp_variable = $config->get('encryption_path');
     $config->set('encryption_path', '')->save();
     $this->drupalGet('admin/store');
     $this->assertText('You must review your credit card security settings and enable encryption before you can accept credit card payments.');
     $this->drupalGet('admin/store/config/payment/credit');
     $this->assertText(t('Credit card security settings must be configured in the security settings tab.'));
     $this->drupalPostForm('admin/store/config/payment/credit', array(), t('Save configuration'));
     $this->assertFieldByName('uc_credit_encryption_path', t('Not configured.'), 'Key file has not yet been configured.');
     // Restore variable setting.
     $config->set('encryption_path', $temp_variable)->save();
     // Try to submit settings form with an empty key file path.
     $this->drupalPostForm('admin/store/config/payment/credit', array('uc_credit_encryption_path' => ''), t('Save configuration'));
     $this->assertText('Key path must be specified in security settings tab.');
     // Specify non-existent directory
     $this->drupalPostForm('admin/store/config/payment/credit', array('uc_credit_encryption_path' => 'sites/default/ljkh/asdfasfaaaaa'), t('Save configuration'));
     $this->assertText('You have specified a non-existent directory.');
     // Next, specify existing directory that's write protected.
     // Use /dev, as that should never be accessible.
     $this->drupalPostForm('admin/store/config/payment/credit', array('uc_credit_encryption_path' => '/dev'), t('Save configuration'));
     $this->assertText('Cannot write to directory, please verify the directory permissions.');
     // Next, specify writeable directory, but with excess whitespace
     // and trailing /
     $this->drupalPostForm('admin/store/config/payment/credit', array('uc_credit_encryption_path' => '  sites/default/files/testkey/ '), t('Save configuration'));
     // See that the directory has been properly re-written to remove
     // whitespace and trailing /
     $this->assertFieldByName('uc_credit_encryption_path', 'sites/default/files/testkey', 'Key file path has been set.');
     $this->assertText('Credit card encryption key file generated.');
     // Check that warning about needing key file goes away.
     $this->assertNoText(t('Credit card security settings must be configured in the security settings tab.'));
     // Remove key file.
     \Drupal::service('file_system')->unlink('sites/default/files/testkey/' . UC_CREDIT_KEYFILE_NAME);
     // Finally, specify good directory
     $this->drupalPostForm('admin/store/config/payment/credit', array('uc_credit_encryption_path' => 'sites/default/files/testkey'), t('Save configuration'));
     $this->assertText('Credit card encryption key file generated.');
     // Test contents - must contain 32-character hexadecimal string.
     $this->assertTrue(file_exists('sites/default/files/simpletest.keys/' . UC_CREDIT_KEYFILE_NAME), 'Key has been generated and stored.');
     $this->assertTrue(preg_match("([0-9a-fA-F]{32})", uc_credit_encryption_key()), 'Valid key detected in key file.');
     // Cleanup keys directory after test.
     \Drupal::service('file_system')->unlink('sites/default/files/testkey/' . UC_CREDIT_KEYFILE_NAME);
     \Drupal::service('file_system')->rmdir('sites/default/files/testkey');
 }
 /**
  * {@inheritdoc}
  */
 public function validateForm(array &$form, FormStateInterface $form_state)
 {
     // Check that the encryption key directory has been specified, that it
     // exists, and that it is readable.
     // Trim trailing whitespace and any trailing / or \ from the key path name.
     $key_path = rtrim(trim($form_state->getValue('uc_credit_encryption_path')), '/\\');
     // Test to see if a path was entered.
     if (empty($key_path)) {
         $form_state->setErrorByName('uc_credit_encryption_path', $this->t('Key path must be specified in security settings tab.'));
     }
     // Construct complete key file path.
     $key_file = $key_path . '/' . UC_CREDIT_KEYFILE_NAME;
     // Shortcut - test to see if we already have a usable key file.
     if (file_exists($key_file)) {
         if (is_readable($key_file)) {
             // Test contents - must contain 32-character hexadecimal string.
             $key = uc_credit_encryption_key();
             if ($key) {
                 if (!preg_match("([0-9a-fA-F]{32})", $key)) {
                     $form_state->setErrorByName('uc_credit_encryption_path', $this->t('Key file already exists in directory, but it contains an invalid key.'));
                 } else {
                     // Key file exists and is valid, save result of trim() back into
                     // $form_state and proceed to submit handler.
                     $form_state->setValue('uc_credit_encryption_path', $key_path);
                     return;
                 }
             }
         } else {
             $form_state->setErrorByName('uc_credit_encryption_path', $this->t('Key file already exists in directory, but is not readable. Please verify the file permissions.'));
         }
     }
     // Check if directory exists and is writeable.
     if (is_dir($key_path)) {
         // The entered directory is valid and in need of a key file.
         // Flag this condition for the submit handler.
         $form_state->setValue('update_cc_encrypt_dir', TRUE);
         // Can we open for writing?
         $file = @fopen($key_path . '/encrypt.test', 'w');
         if ($file === FALSE) {
             $form_state->setErrorByName('uc_credit_encryption_path', $this->t('Cannot write to directory, please verify the directory permissions.'));
             $form_state->setValue('update_cc_encrypt_dir', FALSE);
         } else {
             // Can we actually write?
             if (@fwrite($file, '0123456789') === FALSE) {
                 $form_state->setErrorByName('uc_credit_encryption_path', $this->t('Cannot write to directory, please verify the directory permissions.'));
                 $form_state->setValue('update_cc_encrypt_dir', FALSE);
                 fclose($file);
             } else {
                 // Can we read now?
                 fclose($file);
                 $file = @fopen($key_path . '/encrypt.test', 'r');
                 if ($file === FALSE) {
                     $form_state->setErrorByName('uc_credit_encryption_path', $this->t('Cannot read from directory, please verify the directory permissions.'));
                     $form_state->setValue('update_cc_encrypt_dir', FALSE);
                 } else {
                     fclose($file);
                 }
             }
             unlink($key_path . '/encrypt.test');
         }
     } else {
         // Directory doesn't exist.
         $form_state->setErrorByName('uc_credit_encryption_path', $this->t('You have specified a non-existent directory.'));
     }
     // If validation succeeds, save result of trim() back into $form_state.
     $form_state->setValue('uc_credit_encryption_path', $key_path);
 }
 /**
  * {@inheritdoc}
  */
 public function cartProcess(OrderInterface $order, array $form, FormStateInterface $form_state)
 {
     if (!$form_state->hasValue(['panes', 'payment', 'details', 'cc_number'])) {
         return;
     }
     $fields = $this->getEnabledFields();
     // Fetch the CC details from the $_POST directly.
     $cc_data = $form_state->getValue(['panes', 'payment', 'details']);
     $cc_data['cc_number'] = str_replace(' ', '', $cc_data['cc_number']);
     // Recover cached CC data in form state, if it exists.
     if ($form_state->hasValue(['panes', 'payment', 'details', 'payment_details_data'])) {
         $cache = uc_credit_cache('save', $form_state->getValue(['panes', 'payment', 'details', 'payment_details_data']));
     }
     // Account for partial CC numbers when masked by the system.
     if (substr($cc_data['cc_number'], 0, strlen(t('(Last4)'))) == $this->t('(Last4)')) {
         // Recover the number from the encrypted data in the form if truncated.
         if (isset($cache['cc_number'])) {
             $cc_data['cc_number'] = $cache['cc_number'];
         } else {
             $cc_data['cc_number'] = '';
         }
     }
     // Account for masked CVV numbers.
     if (!empty($cc_data['cc_cvv']) && $cc_data['cc_cvv'] == str_repeat('-', strlen($cc_data['cc_cvv']))) {
         // Recover the number from the encrypted data in $_POST if truncated.
         if (isset($cache['cc_cvv'])) {
             $cc_data['cc_cvv'] = $cache['cc_cvv'];
         } else {
             $cc_data['cc_cvv'] = '';
         }
     }
     // Go ahead and put the CC data in the payment details array.
     $order->payment_details = $cc_data;
     // Default our value for validation.
     $return = TRUE;
     // Make sure an owner value was entered.
     if (!empty($fields['owner']) && empty($cc_data['cc_owner'])) {
         $form_state->setErrorByName('panes][payment][details][cc_owner', $this->t('Enter the owner name as it appears on the card.'));
         $return = FALSE;
     }
     // Validate the credit card number.
     if (!_uc_credit_valid_card_number($cc_data['cc_number'])) {
         $form_state->setErrorByName('panes][payment][details][cc_number', $this->t('You have entered an invalid credit card number.'));
         $return = FALSE;
     }
     // Validate the start date (if entered).
     if (!empty($fields['start']) && !_uc_credit_valid_card_start($cc_data['cc_start_month'], $cc_data['cc_start_year'])) {
         $form_state->setErrorByName('panes][payment][details][cc_start_month', $this->t('The start date you entered is invalid.'));
         $form_state->setErrorByName('panes][payment][details][cc_start_year');
         $return = FALSE;
     }
     // Validate the card expiration date.
     if (!_uc_credit_valid_card_expiration($cc_data['cc_exp_month'], $cc_data['cc_exp_year'])) {
         $form_state->setErrorByName('panes][payment][details][cc_exp_month', $this->t('The credit card you entered has expired.'));
         $form_state->setErrorByName('panes][payment][details][cc_exp_year');
         $return = FALSE;
     }
     // Validate the issue number (if entered).  With issue numbers, '01' is
     // different from '1', but is_numeric() is still appropriate.
     if (!empty($fields['issue']) && !_uc_credit_valid_card_issue($cc_data['cc_issue'])) {
         $form_state->setErrorByName('panes][payment][details][cc_issue', $this->t('The issue number you entered is invalid.'));
         $return = FALSE;
     }
     // Validate the CVV number if enabled.
     if (!empty($fields['cvv']) && !_uc_credit_valid_cvv($cc_data['cc_cvv'])) {
         $form_state->setErrorByName('panes][payment][details][cc_cvv', $this->t('You have entered an invalid CVV number.'));
         $return = FALSE;
     }
     // Validate the bank name if enabled.
     if (!empty($fields['bank']) && empty($cc_data['cc_bank'])) {
         $form_state->setErrorByName('panes][payment][details][cc_bank', $this->t('You must enter the issuing bank for that card.'));
         $return = FALSE;
     }
     // Initialize the encryption key and class.
     $key = uc_credit_encryption_key();
     $crypt = \Drupal::service('uc_store.encryption');
     // Store the encrypted details in the session for the next pageload.
     // We are using base64_encode() because the encrypt function works with a
     // limited set of characters, not supporting the full Unicode character
     // set or even extended ASCII characters that may be present.
     // base64_encode() converts everything to a subset of ASCII, ensuring that
     // the encryption algorithm does not mangle names.
     $session = \Drupal::service('session');
     $session->set('sescrd', $crypt->encrypt($key, base64_encode(serialize($order->payment_details))));
     // Log any errors to the watchdog.
     uc_store_encryption_errors($crypt, 'uc_credit');
     // If we're going to the review screen, set a variable that lets us know
     // we're paying by CC.
     if ($return) {
         $session->set('cc_pay', TRUE);
     }
     return $return;
 }