Issues (1182)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

includes/gateways/bacs/class-wc-gateway-bacs.php (5 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
if ( ! defined( 'ABSPATH' ) ) {
4
	exit; // Exit if accessed directly
5
}
6
7
/**
8
 * Bank Transfer Payment Gateway.
9
 *
10
 * Provides a Bank Transfer Payment Gateway. Based on code by Mike Pepper.
11
 *
12
 * @class       WC_Gateway_BACS
13
 * @extends     WC_Payment_Gateway
14
 * @version     2.1.0
15
 * @package     WooCommerce/Classes/Payment
16
 * @author      WooThemes
17
 */
18
class WC_Gateway_BACS extends WC_Payment_Gateway {
19
20
	/** @var array Array of locales */
21
	public $locale;
22
23
	/**
24
	 * Constructor for the gateway.
25
	 */
26
	public function __construct() {
27
28
		$this->id                 = 'bacs';
29
		$this->icon               = apply_filters('woocommerce_bacs_icon', '');
30
		$this->has_fields         = false;
31
		$this->method_title       = __( 'BACS', 'woocommerce' );
32
		$this->method_description = __( 'Allows payments by BACS, more commonly known as direct bank/wire transfer.', 'woocommerce' );
33
34
		// Load the settings.
35
		$this->init_form_fields();
36
		$this->init_settings();
37
38
		// Define user set variables
39
		$this->title        = $this->get_option( 'title' );
40
		$this->description  = $this->get_option( 'description' );
41
		$this->instructions = $this->get_option( 'instructions', $this->description );
42
43
		// BACS account fields shown on the thanks page and in emails
44
		$this->account_details = get_option( 'woocommerce_bacs_accounts',
45
			array(
46
				array(
47
					'account_name'   => $this->get_option( 'account_name' ),
48
					'account_number' => $this->get_option( 'account_number' ),
49
					'sort_code'      => $this->get_option( 'sort_code' ),
50
					'bank_name'      => $this->get_option( 'bank_name' ),
51
					'iban'           => $this->get_option( 'iban' ),
52
					'bic'            => $this->get_option( 'bic' )
53
				)
54
			)
55
		);
56
57
		// Actions
58
		add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) );
59
		add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'save_account_details' ) );
60
		add_action( 'woocommerce_thankyou_bacs', array( $this, 'thankyou_page' ) );
61
62
		// Customer Emails
63
		add_action( 'woocommerce_email_before_order_table', array( $this, 'email_instructions' ), 10, 3 );
64
	}
65
66
	/**
67
	 * Initialise Gateway Settings Form Fields.
68
	 */
69 View Code Duplication
	public function init_form_fields() {
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
70
71
		$this->form_fields = array(
72
			'enabled' => array(
73
				'title'   => __( 'Enable/Disable', 'woocommerce' ),
74
				'type'    => 'checkbox',
75
				'label'   => __( 'Enable Bank Transfer', 'woocommerce' ),
76
				'default' => 'no'
77
			),
78
			'title' => array(
79
				'title'       => __( 'Title', 'woocommerce' ),
80
				'type'        => 'text',
81
				'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce' ),
82
				'default'     => __( 'Direct Bank Transfer', 'woocommerce' ),
83
				'desc_tip'    => true,
84
			),
85
			'description' => array(
86
				'title'       => __( 'Description', 'woocommerce' ),
87
				'type'        => 'textarea',
88
				'description' => __( 'Payment method description that the customer will see on your checkout.', 'woocommerce' ),
89
				'default'     => __( 'Make your payment directly into our bank account. Please use your Order ID as the payment reference. Your order won\'t be shipped until the funds have cleared in our account.', 'woocommerce' ),
90
				'desc_tip'    => true,
91
			),
92
			'instructions' => array(
93
				'title'       => __( 'Instructions', 'woocommerce' ),
94
				'type'        => 'textarea',
95
				'description' => __( 'Instructions that will be added to the thank you page and emails.', 'woocommerce' ),
96
				'default'     => '',
97
				'desc_tip'    => true,
98
			),
99
			'account_details' => array(
100
				'type'        => 'account_details'
101
			),
102
		);
103
104
	}
105
106
	/**
107
	 * Generate account details html.
108
	 *
109
	 * @return string
110
	 */
111
	public function generate_account_details_html() {
112
113
		ob_start();
114
115
		$country 	= WC()->countries->get_base_country();
116
		$locale		= $this->get_country_locale();
117
118
		// Get sortcode label in the $locale array and use appropriate one
119
		$sortcode = isset( $locale[ $country ]['sortcode']['label'] ) ? $locale[ $country ]['sortcode']['label'] : __( 'Sort Code', 'woocommerce' );
120
121
		?>
122
		<tr valign="top">
123
			<th scope="row" class="titledesc"><?php _e( 'Account Details', 'woocommerce' ); ?>:</th>
124
			<td class="forminp" id="bacs_accounts">
125
				<table class="widefat wc_input_table sortable" cellspacing="0">
126
					<thead>
127
						<tr>
128
							<th class="sort">&nbsp;</th>
129
							<th><?php _e( 'Account Name', 'woocommerce' ); ?></th>
130
							<th><?php _e( 'Account Number', 'woocommerce' ); ?></th>
131
							<th><?php _e( 'Bank Name', 'woocommerce' ); ?></th>
132
							<th><?php echo $sortcode; ?></th>
133
							<th><?php _e( 'IBAN', 'woocommerce' ); ?></th>
134
							<th><?php _e( 'BIC / Swift', 'woocommerce' ); ?></th>
135
						</tr>
136
					</thead>
137
					<tbody class="accounts">
138
						<?php
139
						$i = -1;
140
						if ( $this->account_details ) {
141
							foreach ( $this->account_details as $account ) {
142
								$i++;
143
144
								echo '<tr class="account">
145
									<td class="sort"></td>
146
									<td><input type="text" value="' . esc_attr( wp_unslash( $account['account_name'] ) ) . '" name="bacs_account_name[' . $i . ']" /></td>
147
									<td><input type="text" value="' . esc_attr( $account['account_number'] ) . '" name="bacs_account_number[' . $i . ']" /></td>
148
									<td><input type="text" value="' . esc_attr( wp_unslash( $account['bank_name'] ) ) . '" name="bacs_bank_name[' . $i . ']" /></td>
149
									<td><input type="text" value="' . esc_attr( $account['sort_code'] ) . '" name="bacs_sort_code[' . $i . ']" /></td>
150
									<td><input type="text" value="' . esc_attr( $account['iban'] ) . '" name="bacs_iban[' . $i . ']" /></td>
151
									<td><input type="text" value="' . esc_attr( $account['bic'] ) . '" name="bacs_bic[' . $i . ']" /></td>
152
								</tr>';
153
							}
154
						}
155
						?>
156
					</tbody>
157
					<tfoot>
158
						<tr>
159
							<th colspan="7"><a href="#" class="add button"><?php _e( '+ Add Account', 'woocommerce' ); ?></a> <a href="#" class="remove_rows button"><?php _e( 'Remove selected account(s)', 'woocommerce' ); ?></a></th>
160
						</tr>
161
					</tfoot>
162
				</table>
163
				<script type="text/javascript">
164
					jQuery(function() {
165
						jQuery('#bacs_accounts').on( 'click', 'a.add', function(){
166
167
							var size = jQuery('#bacs_accounts').find('tbody .account').length;
168
169
							jQuery('<tr class="account">\
170
									<td class="sort"></td>\
171
									<td><input type="text" name="bacs_account_name[' + size + ']" /></td>\
172
									<td><input type="text" name="bacs_account_number[' + size + ']" /></td>\
173
									<td><input type="text" name="bacs_bank_name[' + size + ']" /></td>\
174
									<td><input type="text" name="bacs_sort_code[' + size + ']" /></td>\
175
									<td><input type="text" name="bacs_iban[' + size + ']" /></td>\
176
									<td><input type="text" name="bacs_bic[' + size + ']" /></td>\
177
								</tr>').appendTo('#bacs_accounts table tbody');
178
179
							return false;
180
						});
181
					});
182
				</script>
183
			</td>
184
		</tr>
185
		<?php
186
		return ob_get_clean();
187
188
	}
189
190
	/**
191
	 * Save account details table.
192
	 */
193
	public function save_account_details() {
194
195
		$accounts = array();
196
197
		if ( isset( $_POST['bacs_account_name'] ) ) {
198
199
			$account_names   = array_map( 'wc_clean', $_POST['bacs_account_name'] );
200
			$account_numbers = array_map( 'wc_clean', $_POST['bacs_account_number'] );
201
			$bank_names      = array_map( 'wc_clean', $_POST['bacs_bank_name'] );
202
			$sort_codes      = array_map( 'wc_clean', $_POST['bacs_sort_code'] );
203
			$ibans           = array_map( 'wc_clean', $_POST['bacs_iban'] );
204
			$bics            = array_map( 'wc_clean', $_POST['bacs_bic'] );
205
206
			foreach ( $account_names as $i => $name ) {
207
				if ( ! isset( $account_names[ $i ] ) ) {
208
					continue;
209
				}
210
211
				$accounts[] = array(
212
					'account_name'   => $account_names[ $i ],
213
					'account_number' => $account_numbers[ $i ],
214
					'bank_name'      => $bank_names[ $i ],
215
					'sort_code'      => $sort_codes[ $i ],
216
					'iban'           => $ibans[ $i ],
217
					'bic'            => $bics[ $i ]
218
				);
219
			}
220
		}
221
222
		update_option( 'woocommerce_bacs_accounts', $accounts );
223
224
	}
225
226
	/**
227
	 * Output for the order received page.
228
	 *
229
	 * @param int $order_id
230
	 */
231
	public function thankyou_page( $order_id ) {
232
233
		if ( $this->instructions ) {
234
			echo wpautop( wptexturize( wp_kses_post( $this->instructions ) ) );
235
		}
236
		$this->bank_details( $order_id );
237
238
	}
239
240
	/**
241
	 * Add content to the WC emails.
242
	 *
243
	 * @param WC_Order $order
244
	 * @param bool $sent_to_admin
245
	 * @param bool $plain_text
246
	 */
247
	public function email_instructions( $order, $sent_to_admin, $plain_text = false ) {
0 ignored issues
show
The parameter $plain_text is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
248
249
		if ( ! $sent_to_admin && 'bacs' === $order->payment_method && $order->has_status( 'on-hold' ) ) {
250
			if ( $this->instructions ) {
251
				echo wpautop( wptexturize( $this->instructions ) ) . PHP_EOL;
252
			}
253
			$this->bank_details( $order->id );
254
		}
255
256
	}
257
258
	/**
259
	 * Get bank details and place into a list format.
260
	 *
261
	 * @param int $order_id
262
	 */
263
	private function bank_details( $order_id = '' ) {
264
265
		if ( empty( $this->account_details ) ) {
266
			return;
267
		}
268
269
		// Get order and store in $order
270
		$order 		= wc_get_order( $order_id );
271
272
		// Get the order country and country $locale
273
		$country 	= $order->billing_country;
274
		$locale		= $this->get_country_locale();
275
276
		// Get sortcode label in the $locale array and use appropriate one
277
		$sortcode = isset( $locale[ $country ]['sortcode']['label'] ) ? $locale[ $country ]['sortcode']['label'] : __( 'Sort Code', 'woocommerce' );
278
279
		$bacs_accounts = apply_filters( 'woocommerce_bacs_accounts', $this->account_details );
280
281
		if ( ! empty( $bacs_accounts ) ) {
282
			echo '<h2 class="wc-bacs-bank-details-heading">' . __( 'Our Bank Details', 'woocommerce' ) . '</h2>' . PHP_EOL;
283
284
			foreach ( $bacs_accounts as $bacs_account ) {
285
286
				$bacs_account = (object) $bacs_account;
287
288
				if ( $bacs_account->account_name || $bacs_account->bank_name ) {
289
					echo '<h3>' . wp_unslash( implode( ' - ', array_filter( array( $bacs_account->account_name, $bacs_account->bank_name ) ) ) ) . '</h3>' . PHP_EOL;
290
				}
291
292
				echo '<ul class="wc-bacs-bank-details order_details bacs_details">' . PHP_EOL;
293
294
				// BACS account fields shown on the thanks page and in emails
295
				$account_fields = apply_filters( 'woocommerce_bacs_account_fields', array(
296
					'account_number'=> array(
297
						'label' => __( 'Account Number', 'woocommerce' ),
298
						'value' => $bacs_account->account_number
299
					),
300
					'sort_code'     => array(
301
						'label' => $sortcode,
302
						'value' => $bacs_account->sort_code
303
					),
304
					'iban'          => array(
305
						'label' => __( 'IBAN', 'woocommerce' ),
306
						'value' => $bacs_account->iban
307
					),
308
					'bic'           => array(
309
						'label' => __( 'BIC', 'woocommerce' ),
310
						'value' => $bacs_account->bic
311
					)
312
				), $order_id );
313
314
				foreach ( $account_fields as $field_key => $field ) {
315
					if ( ! empty( $field['value'] ) ) {
316
						echo '<li class="' . esc_attr( $field_key ) . '">' . esc_attr( $field['label'] ) . ': <strong>' . wptexturize( $field['value'] ) . '</strong></li>' . PHP_EOL;
317
					}
318
				}
319
320
				echo '</ul>';
321
			}
322
		}
323
324
	}
325
326
	/**
327
	 * Process the payment and return the result.
328
	 *
329
	 * @param int $order_id
330
	 * @return array
331
	 */
332 View Code Duplication
	public function process_payment( $order_id ) {
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
333
334
		$order = wc_get_order( $order_id );
335
336
		// Mark as on-hold (we're awaiting the payment)
337
		$order->update_status( 'on-hold', __( 'Awaiting BACS payment', 'woocommerce' ) );
338
339
		// Reduce stock levels
340
		$order->reduce_order_stock();
341
342
		// Remove cart
343
		WC()->cart->empty_cart();
344
345
		// Return thankyou redirect
346
		return array(
347
			'result'    => 'success',
348
			'redirect'  => $this->get_return_url( $order )
0 ignored issues
show
$order is of type false|object, but the function expects a object<WC_Order>|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
349
		);
350
351
	}
352
353
	/**
354
	 * Get country locale if localized.
355
	 *
356
	 * @return array
357
	 */
358
	public function get_country_locale() {
359
360
		if ( ! $this->locale ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->locale of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
361
362
			// Locale information to be used - only those that are not 'Sort Code'
363
			$this->locale = apply_filters( 'woocommerce_get_bacs_locale', array(
364
				'AU' => array(
365
					'sortcode'	=> array(
366
						'label'		=> __( 'BSB', 'woocommerce' ),
367
					),
368
				),
369
				'CA' => array(
370
					'sortcode'	=> array(
371
						'label'		=> __( 'Bank Transit Number', 'woocommerce' ),
372
					),
373
				),
374
				'IN' => array(
375
					'sortcode'	=> array(
376
						'label'		=> __( 'IFSC', 'woocommerce' ),
377
					),
378
				),
379
				'IT' => array(
380
					'sortcode'	=> array(
381
						'label'		=> __( 'Branch Sort', 'woocommerce' ),
382
					),
383
				),
384
				'NZ' => array(
385
					'sortcode'	=> array(
386
						'label'		=> __( 'Bank Code', 'woocommerce' ),
387
					),
388
				),
389
				'SE' => array(
390
					'sortcode'	=> array(
391
						'label'		=> __( 'Bank Code', 'woocommerce' ),
392
					),
393
				),
394
				'US' => array(
395
					'sortcode'	=> array(
396
						'label'		=> __( 'Routing Number', 'woocommerce' ),
397
					),
398
				),
399
				'ZA' => array(
400
					'sortcode'	=> array(
401
						'label'		=> __( 'Branch Code', 'woocommerce' ),
402
					),
403
				),
404
			) );
405
406
		}
407
408
		return $this->locale;
409
410
	}
411
}
412