Failed Conditions
Push — develop ( f94cbf...2b83af )
by Remco
06:02
created

Integration::get_config()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 14
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 9
nc 1
nop 1
dl 0
loc 14
ccs 0
cts 10
cp 0
crap 2
rs 9.9666
c 0
b 0
f 0
1
<?php
2
3
namespace Pronamic\WordPress\Pay\Gateways\IDealAdvancedV3;
4
5
use Pronamic\WordPress\Pay\Gateways\IDeal\AbstractIntegration;
6
7
/**
8
 * Title: iDEAL Advanced v3 integration
9
 * Description:
10
 * Copyright: 2005-2019 Pronamic
11
 * Company: Pronamic
12
 *
13
 * @author  Remco Tolsma
14
 * @version 2.0.0
15
 * @since   2.0.0
16
 */
17
class Integration extends AbstractIntegration {
18
	/**
19
	 * Settings constructor.
20
	 */
21
	public function __construct( $args = array() ) {
22
		$args = wp_parse_args( $args, array(
23
			'id'            => 'ideal-advanced-v3',
24
			'name'          => 'iDEAL Advanced v3',
25
			'url'           => __( 'https://www.ideal.nl/en/', 'pronamic_ideal' ),
26
			'product_url'   => __( 'https://www.ideal.nl/en/', 'pronamic_ideal' ),
27
			'dashboard_url' => null,
28
			'provider'      => null,
29
		) );
30
31
		$this->id            = $args['id'];
32
		$this->name          = $args['name'];
33
		$this->url           = $args['url'];
34
		$this->product_url   = $args['product_url'];
35
		$this->dashboard_url = $args['dashboard_url'];
36
		$this->provider      = $args['provider'];
37
38
		// Supported features.
39
		$this->supports = array(
0 ignored issues
show
Bug Best Practice introduced by
The property supports does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
40
			'payment_status_request',
41
		);
42
43
		// Actions.
44
		add_action( 'current_screen', array( $this, 'maybe_download_private_certificate' ) );
45
		add_action( 'current_screen', array( $this, 'maybe_download_private_key' ) );
46
	}
47
48
	public function get_settings_fields() {
49
		$fields = parent::get_settings_fields();
0 ignored issues
show
Bug introduced by
The method get_settings_fields() does not exist on Pronamic\WordPress\Pay\G...eal\AbstractIntegration. Did you maybe mean get_settings()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

49
		/** @scrutinizer ignore-call */ 
50
  $fields = parent::get_settings_fields();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
50
51
		/*
52
		 * Private Key and Certificate
53
		 */
54
55
		// Private key and certificate information.
56
		$fields[] = array(
57
			'section'  => 'general',
58
			'title'    => __( 'Private key and certificate', 'pronamic_ideal' ),
59
			'type'     => 'description',
60
			'callback' => array( $this, 'field_security' ),
61
		);
62
63
		// Organization.
64
		$fields[] = array(
65
			'section'  => 'general',
66
			'filter'   => FILTER_SANITIZE_STRING,
67
			'group'    => 'pk-cert',
68
			'meta_key' => '_pronamic_gateway_organization',
69
			'title'    => __( 'Organization', 'pronamic_ideal' ),
70
			'type'     => 'text',
71
			'tooltip'  => __( 'Organization name, e.g. Pronamic', 'pronamic_ideal' ),
72
		);
73
74
		// Organization Unit.
75
		$fields[] = array(
76
			'section'  => 'general',
77
			'filter'   => FILTER_SANITIZE_STRING,
78
			'group'    => 'pk-cert',
79
			'meta_key' => '_pronamic_gateway_organization_unit',
80
			'title'    => __( 'Organization Unit', 'pronamic_ideal' ),
81
			'type'     => 'text',
82
			'tooltip'  => __( 'Organization unit, e.g. Administration', 'pronamic_ideal' ),
83
		);
84
85
		// Locality.
86
		$fields[] = array(
87
			'section'  => 'general',
88
			'filter'   => FILTER_SANITIZE_STRING,
89
			'group'    => 'pk-cert',
90
			'meta_key' => '_pronamic_gateway_locality',
91
			'title'    => __( 'City', 'pronamic_ideal' ),
92
			'type'     => 'text',
93
			'tooltip'  => __( 'City, e.g. Amsterdam', 'pronamic_ideal' ),
94
		);
95
96
		// State or Province.
97
		$fields[] = array(
98
			'section'  => 'general',
99
			'filter'   => FILTER_SANITIZE_STRING,
100
			'group'    => 'pk-cert',
101
			'meta_key' => '_pronamic_gateway_state_or_province',
102
			'title'    => __( 'State / province', 'pronamic_ideal' ),
103
			'type'     => 'text',
104
			'tooltip'  => __( 'State or province, e.g. Friesland', 'pronamic_ideal' ),
105
		);
106
107
		// Country.
108
		$locale = explode( '_', get_locale() );
109
110
		$locale = array_pop( $locale );
111
112
		$fields[] = array(
113
			'section'     => 'general',
114
			'filter'      => FILTER_SANITIZE_STRING,
115
			'group'       => 'pk-cert',
116
			'meta_key'    => '_pronamic_gateway_country',
117
			'title'       => __( 'Country', 'pronamic_ideal' ),
118
			'type'        => 'text',
119
			'tooltip'     => sprintf(
120
				'%s %s (ISO-3166-1 alpha-2)',
121
				__( '2 letter country code, e.g.', 'pronamic_ideal' ),
122
				strtoupper( $locale )
123
			),
124
			'size'        => 2,
125
			'description' => sprintf(
126
				'%s %s',
127
				__( '2 letter country code, e.g.', 'pronamic_ideal' ),
128
				strtoupper( $locale )
129
			),
130
		);
131
132
		// Email Address.
133
		$fields[] = array(
134
			'section'  => 'general',
135
			'filter'   => FILTER_SANITIZE_STRING,
136
			'group'    => 'pk-cert',
137
			'meta_key' => '_pronamic_gateway_email',
138
			'title'    => __( 'E-mail address', 'pronamic_ideal' ),
139
			'tooltip'  => sprintf(
140
				/* translators: %s: admin email */
141
				__( 'E-mail address, e.g. %s', 'pronamic_ideal' ),
142
				get_option( 'admin_email' )
0 ignored issues
show
Bug introduced by
It seems like get_option('admin_email') can also be of type false; however, parameter $args of sprintf() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

142
				/** @scrutinizer ignore-type */ get_option( 'admin_email' )
Loading history...
143
			),
144
			'type'     => 'text',
145
		);
146
147
		// Number Days Valid.
148
		$fields[] = array(
149
			'section'  => 'general',
150
			'filter'   => FILTER_SANITIZE_NUMBER_INT,
151
			'group'    => 'pk-cert',
152
			'meta_key' => '_pronamic_gateway_number_days_valid',
153
			'title'    => __( 'Number Days Valid', 'pronamic_ideal' ),
154
			'type'     => 'text',
155
			'default'  => 1825,
156
			'tooltip'  => __( 'Number of days the generated certificate will be valid for, e.g. 1825 days for the maximum duration of 5 years.', 'pronamic_ideal' ),
157
		);
158
159
		// Private Key Password.
160
		$fields[] = array(
161
			'section'  => 'general',
162
			'filter'   => FILTER_SANITIZE_STRING,
163
			'group'    => 'pk-cert',
164
			'meta_key' => '_pronamic_gateway_ideal_private_key_password',
165
			'title'    => __( 'Private Key Password', 'pronamic_ideal' ),
166
			'type'     => 'text',
167
			'classes'  => array( 'regular-text', 'code' ),
168
			'default'  => wp_generate_password(),
169
			'tooltip'  => __( 'A random password which will be used for the generation of the private key and certificate.', 'pronamic_ideal' ),
170
		);
171
172
		// Private Key.
173
		$fields[] = array(
174
			'section'  => 'general',
175
			'filter'   => FILTER_SANITIZE_STRING,
176
			'group'    => 'pk-cert',
177
			'meta_key' => '_pronamic_gateway_ideal_private_key',
178
			'title'    => __( 'Private Key', 'pronamic_ideal' ),
179
			'type'     => 'textarea',
180
			'callback' => array( $this, 'field_private_key' ),
181
			'classes'  => array( 'code' ),
182
			'tooltip'  => __( 'The private key is used for secure communication with the payment provider. If left empty, the private key will be generated using the given private key password.', 'pronamic_ideal' ),
183
		);
184
185
		// Private Certificate.
186
		$fields[] = array(
187
			'section'  => 'general',
188
			'filter'   => FILTER_SANITIZE_STRING,
189
			'group'    => 'pk-cert',
190
			'meta_key' => '_pronamic_gateway_ideal_private_certificate',
191
			'title'    => __( 'Private Certificate', 'pronamic_ideal' ),
192
			'type'     => 'textarea',
193
			'callback' => array( $this, 'field_private_certificate' ),
194
			'classes'  => array( 'code' ),
195
			'tooltip'  => __( 'The certificate is used for secure communication with the payment provider. If left empty, the certificate will be generated using the private key and given organization details.', 'pronamic_ideal' ),
196
		);
197
198
		// Return.
199
		return $fields;
200
	}
201
202
	/**
203
	 * Field security
204
	 *
205
	 * @param array $field Field.
206
	 */
207
	public function field_security( $field ) {
0 ignored issues
show
Unused Code introduced by
The parameter $field is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

207
	public function field_security( /** @scrutinizer ignore-unused */ $field ) {

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

Loading history...
208
		$certificate = get_post_meta( get_the_ID(), '_pronamic_gateway_ideal_private_certificate', true );
0 ignored issues
show
Bug introduced by
It seems like get_the_ID() can also be of type false; however, parameter $post_id of get_post_meta() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

208
		$certificate = get_post_meta( /** @scrutinizer ignore-type */ get_the_ID(), '_pronamic_gateway_ideal_private_certificate', true );
Loading history...
209
210
		?>
211
		<p>
212
			<?php if ( empty( $certificate ) ) : ?>
213
214
				<span
215
					class="dashicons dashicons-no"></span> <?php esc_html_e( 'The private key and certificate have not yet been configured.', 'pronamic_ideal' ); ?>
216
				<br/>
217
218
				<br/>
219
220
				<?php esc_html_e( 'A private key and certificate are required for communication with the payment provider. Enter the organization details from the iDEAL account below to generate these required files.', 'pronamic_ideal' ); ?>
221
222
			<?php else : ?>
223
224
				<span
225
					class="dashicons dashicons-yes"></span> <?php esc_html_e( 'A private key and certificate have been configured. The certificate must be uploaded to the payment provider dashboard to complete configuration.', 'pronamic_ideal' ); ?>
226
				<br/>
227
228
				<br/>
229
230
				<?php
231
232
				submit_button(
233
					__( 'Download certificate', 'pronamic_ideal' ),
234
					'secondary',
235
					'download_private_certificate',
236
					false
237
				);
238
239
				?>
240
241
				<a class="pronamic-pay-btn-link" href="#" id="pk-cert-fields-toggle"><?php esc_html_e( 'Show details…', 'pronamic_ideal' ); ?></a>
242
243
			<?php endif; ?>
244
		</p>
245
		<?php
246
	}
247
248
	/**
249
	 * Field private key.
250
	 *
251
	 * @param array $field Field.
252
	 */
253
	public function field_private_key( $field ) {
0 ignored issues
show
Unused Code introduced by
The parameter $field is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

253
	public function field_private_key( /** @scrutinizer ignore-unused */ $field ) {

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

Loading history...
254
		$private_key          = get_post_meta( get_the_ID(), '_pronamic_gateway_ideal_private_key', true );
0 ignored issues
show
Bug introduced by
It seems like get_the_ID() can also be of type false; however, parameter $post_id of get_post_meta() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

254
		$private_key          = get_post_meta( /** @scrutinizer ignore-type */ get_the_ID(), '_pronamic_gateway_ideal_private_key', true );
Loading history...
255
		$private_key_password = get_post_meta( get_the_ID(), '_pronamic_gateway_ideal_private_key_password', true );
256
		$number_days_valid    = get_post_meta( get_the_ID(), '_pronamic_gateway_number_days_valid', true );
257
258
		$filename = __( 'ideal.key', 'pronamic_ideal' );
259
260
		if ( ! empty( $private_key_password ) && ! empty( $number_days_valid ) ) {
261
			$command = sprintf(
262
				'openssl genrsa -aes128 -out %s -passout pass:%s 2048',
263
				escapeshellarg( $filename ),
264
				escapeshellarg( $private_key_password )
265
			);
266
267
			?>
268
269
			<p><?php esc_html_e( 'OpenSSL command', 'pronamic_ideal' ); ?></p>
270
			<input id="pronamic_ideal_openssl_command_key" name="pronamic_ideal_openssl_command_key" value="<?php echo esc_attr( $command ); ?>" type="text" class="large-text code" readonly="readonly"/>
271
272
			<?php
273
		} else {
274
			printf(
275
				'<p class="pronamic-pay-description description">%s</p>',
276
				esc_html__( 'Leave empty and save the configuration to generate the private key or view the OpenSSL command.', 'pronamic_ideal' )
277
			);
278
		}
279
280
		?>
281
		<p>
282
			<?php
283
284
			if ( ! empty( $private_key ) ) {
285
				submit_button(
286
					__( 'Download', 'pronamic_ideal' ),
287
					'secondary',
288
					'download_private_key',
289
					false
290
				);
291
292
				echo ' ';
293
			}
294
295
			printf(
296
				'<label class="pronamic-pay-form-control-file-button button">%s <input type="file" name="%s" /></label>',
297
				esc_html__( 'Upload', 'pronamic_ideal' ),
298
				'_pronamic_gateway_ideal_private_key_file'
299
			);
300
301
			?>
302
		</p>
303
		<?php
304
	}
305
306
	/**
307
	 * Field private certificate.
308
	 *
309
	 * @param array $field Field.
310
	 */
311
	public function field_private_certificate( $field ) {
0 ignored issues
show
Unused Code introduced by
The parameter $field is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

311
	public function field_private_certificate( /** @scrutinizer ignore-unused */ $field ) {

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

Loading history...
312
		$certificate = get_post_meta( get_the_ID(), '_pronamic_gateway_ideal_private_certificate', true );
0 ignored issues
show
Bug introduced by
It seems like get_the_ID() can also be of type false; however, parameter $post_id of get_post_meta() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

312
		$certificate = get_post_meta( /** @scrutinizer ignore-type */ get_the_ID(), '_pronamic_gateway_ideal_private_certificate', true );
Loading history...
313
314
		$private_key_password = get_post_meta( get_the_ID(), '_pronamic_gateway_ideal_private_key_password', true );
315
		$number_days_valid    = get_post_meta( get_the_ID(), '_pronamic_gateway_number_days_valid', true );
316
317
		$filename_key = __( 'ideal.key', 'pronamic_ideal' );
318
		$filename_cer = __( 'ideal.cer', 'pronamic_ideal' );
319
320
		// @link http://www.openssl.org/docs/apps/req.html
321
		$subj_args = array(
322
			'C'            => get_post_meta( get_the_ID(), '_pronamic_gateway_country', true ),
323
			'ST'           => get_post_meta( get_the_ID(), '_pronamic_gateway_state_or_province', true ),
324
			'L'            => get_post_meta( get_the_ID(), '_pronamic_gateway_locality', true ),
325
			'O'            => get_post_meta( get_the_ID(), '_pronamic_gateway_organization', true ),
326
			'OU'           => get_post_meta( get_the_ID(), '_pronamic_gateway_organization_unit', true ),
327
			'CN'           => get_post_meta( get_the_ID(), '_pronamic_gateway_organization', true ),
328
			'emailAddress' => get_post_meta( get_the_ID(), '_pronamic_gateway_email', true ),
329
		);
330
331
		$subj_args = array_filter( $subj_args );
332
333
		$subj = '';
334
		foreach ( $subj_args as $type => $value ) {
335
			$subj .= '/' . $type . '=' . addslashes( $value );
336
		}
337
338
		if ( ! empty( $subj ) ) {
339
			$command = trim(
340
				sprintf(
341
					'openssl req -x509 -sha256 -new -key %s -passin pass:%s -days %s -out %s %s',
342
					escapeshellarg( $filename_key ),
343
					escapeshellarg( $private_key_password ),
0 ignored issues
show
Bug introduced by
It seems like $private_key_password can also be of type false; however, parameter $arg of escapeshellarg() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

343
					escapeshellarg( /** @scrutinizer ignore-type */ $private_key_password ),
Loading history...
344
					escapeshellarg( $number_days_valid ),
345
					escapeshellarg( $filename_cer ),
346
					empty( $subj ) ? '' : sprintf( '-subj %s', escapeshellarg( $subj ) )
347
				)
348
			);
349
350
			?>
351
352
			<p><?php esc_html_e( 'OpenSSL command', 'pronamic_ideal' ); ?></p>
353
			<input id="pronamic_ideal_openssl_command_certificate" name="pronamic_ideal_openssl_command_certificate" value="<?php echo esc_attr( $command ); ?>" type="text" class="large-text code" readonly="readonly"/>
354
355
			<?php
356
		} else {
357
			printf(
358
				'<p class="pronamic-pay-description description">%s</p>',
359
				esc_html__( 'Leave empty and save the configuration to generate the certificate or view the OpenSSL command.', 'pronamic_ideal' )
360
			);
361
		}
362
363
		if ( ! empty( $certificate ) ) {
364
			$fingerprint = Security::get_sha_fingerprint( $certificate );
365
			$fingerprint = str_split( $fingerprint, 2 );
366
			$fingerprint = implode( ':', $fingerprint );
367
368
			echo '<dl>';
369
370
			echo '<dt>', esc_html__( 'SHA Fingerprint', 'pronamic_ideal' ), '</dt>';
371
			echo '<dd>', esc_html( $fingerprint ), '</dd>';
372
373
			$info = openssl_x509_parse( $certificate );
374
375
			if ( $info ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $info 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...
376
				$date_format = __( 'M j, Y @ G:i', 'pronamic_ideal' );
377
378
				if ( isset( $info['validFrom_time_t'] ) ) {
379
					echo '<dt>', esc_html__( 'Valid From', 'pronamic_ideal' ), '</dt>';
380
					echo '<dd>', esc_html( date_i18n( $date_format, $info['validFrom_time_t'] ) ), '</dd>';
381
				}
382
383
				if ( isset( $info['validTo_time_t'] ) ) {
384
					echo '<dt>', esc_html__( 'Valid To', 'pronamic_ideal' ), '</dt>';
385
					echo '<dd>', esc_html( date_i18n( $date_format, $info['validTo_time_t'] ) ), '</dd>';
386
				}
387
			}
388
389
			echo '</dl>';
390
		}
391
392
		?>
393
		<p>
394
			<?php
395
396
			if ( ! empty( $certificate ) ) {
397
				submit_button(
398
					__( 'Download', 'pronamic_ideal' ),
399
					'secondary',
400
					'download_private_certificate',
401
					false
402
				);
403
404
				echo ' ';
405
			}
406
407
			printf(
408
				'<label class="pronamic-pay-form-control-file-button button">%s <input type="file" name="%s" /></label>',
409
				esc_html__( 'Upload', 'pronamic_ideal' ),
410
				'_pronamic_gateway_ideal_private_certificate_file'
411
			);
412
413
			?>
414
		</p>
415
		<?php
416
	}
417
418
	/**
419
	 * Download private certificate
420
	 */
421
	public function maybe_download_private_certificate() {
422
		if ( filter_has_var( INPUT_POST, 'download_private_certificate' ) ) {
423
			$post_id = filter_input( INPUT_POST, 'post_ID', FILTER_SANITIZE_STRING );
424
425
			$filename = sprintf( 'ideal-private-certificate-%s.cer', $post_id );
426
427
			header( 'Content-Description: File Transfer' );
428
			header( 'Content-Disposition: attachment; filename=' . $filename );
429
			header( 'Content-Type: application/x-x509-ca-cert; charset=' . get_option( 'blog_charset' ), true );
0 ignored issues
show
Bug introduced by
Are you sure get_option('blog_charset') of type false|mixed can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

429
			header( 'Content-Type: application/x-x509-ca-cert; charset=' . /** @scrutinizer ignore-type */ get_option( 'blog_charset' ), true );
Loading history...
430
431
			echo get_post_meta( $post_id, '_pronamic_gateway_ideal_private_certificate', true ); // xss ok.
0 ignored issues
show
Bug introduced by
Are you sure get_post_meta($post_id, ...ate_certificate', true) of type false|mixed|string can be used in echo? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

431
			echo /** @scrutinizer ignore-type */ get_post_meta( $post_id, '_pronamic_gateway_ideal_private_certificate', true ); // xss ok.
Loading history...
432
433
			exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
434
		}
435
	}
436
437
	/**
438
	 * Download private key
439
	 */
440
	public function maybe_download_private_key() {
441
		if ( filter_has_var( INPUT_POST, 'download_private_key' ) ) {
442
			$post_id = filter_input( INPUT_POST, 'post_ID', FILTER_SANITIZE_STRING );
443
444
			$filename = sprintf( 'ideal-private-key-%s.key', $post_id );
445
446
			header( 'Content-Description: File Transfer' );
447
			header( 'Content-Disposition: attachment; filename=' . $filename );
448
			header( 'Content-Type: application/pgp-keys; charset=' . get_option( 'blog_charset' ), true );
0 ignored issues
show
Bug introduced by
Are you sure get_option('blog_charset') of type false|mixed can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

448
			header( 'Content-Type: application/pgp-keys; charset=' . /** @scrutinizer ignore-type */ get_option( 'blog_charset' ), true );
Loading history...
449
450
			echo get_post_meta( $post_id, '_pronamic_gateway_ideal_private_key', true ); // xss ok.
0 ignored issues
show
Bug introduced by
Are you sure get_post_meta($post_id, ...eal_private_key', true) of type false|mixed|string can be used in echo? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

450
			echo /** @scrutinizer ignore-type */ get_post_meta( $post_id, '_pronamic_gateway_ideal_private_key', true ); // xss ok.
Loading history...
451
452
			exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
453
		}
454
	}
455
456
	/**
457
	 * Save post.
458
	 *
459
	 * @param array $data Data.
460
	 */
461
	public function save_post( $data ) {
462
		// Files.
463
		$files = array(
464
			'_pronamic_gateway_ideal_private_key_file' => '_pronamic_gateway_ideal_private_key',
465
			'_pronamic_gateway_ideal_private_certificate_file' => '_pronamic_gateway_ideal_private_certificate',
466
		);
467
468
		foreach ( $files as $name => $meta_key ) {
469
			if ( isset( $_FILES[ $name ] ) && UPLOAD_ERR_OK === $_FILES[ $name ]['error'] ) { // WPCS: input var okay.
470
				$value = file_get_contents( $_FILES[ $name ]['tmp_name'] ); // WPCS: input var okay. // WPCS: sanitization ok.
471
472
				$data[ $meta_key ] = $value;
473
			}
474
		}
475
476
		// Generate private key and certificate.
477
		if ( empty( $data['_pronamic_gateway_ideal_private_key_password'] ) ) {
478
			// Without private key password we can't create private key and certifiate.
479
			return $data;
480
		}
481
482
		if ( ! in_array( 'aes-128-cbc', openssl_get_cipher_methods(), true ) ) {
483
			// Without AES-128-CBC ciphter method we can't create private key and certificate.
484
			return $data;
485
		}
486
487
		// Private key.
488
		$pkey = openssl_pkey_get_private( $data['_pronamic_gateway_ideal_private_key'], $data['_pronamic_gateway_ideal_private_key_password'] );
489
490
		if ( false === $pkey ) {
491
			// If we can't open the private key we will create a new private key and certificate.
492
			if ( defined( 'OPENSSL_CIPHER_AES_128_CBC' ) ) {
493
				$cipher = OPENSSL_CIPHER_AES_128_CBC;
494
			} elseif ( defined( 'OPENSSL_CIPHER_3DES' ) ) {
495
				// @link https://www.pronamic.nl/wp-content/uploads/2011/12/iDEAL_Advanced_PHP_EN_V2.2.pdf
496
				$cipher = OPENSSL_CIPHER_3DES;
497
			} else {
498
				// Unable to create private key without cipher.
499
				return $data;
500
			}
501
502
			$args = array(
503
				'digest_alg'             => 'SHA256',
504
				'private_key_bits'       => 2048,
505
				'private_key_type'       => OPENSSL_KEYTYPE_RSA,
506
				'encrypt_key'            => true,
507
				'encrypt_key_cipher'     => $cipher,
508
				'subjectKeyIdentifier'   => 'hash',
509
				'authorityKeyIdentifier' => 'keyid:always,issuer:always',
510
				'basicConstraints'       => 'CA:true',
511
			);
512
513
			$pkey = openssl_pkey_new( $args );
514
515
			if ( false === $pkey ) {
516
				return $data;
517
			}
518
519
			// Export key.
520
			$result = openssl_pkey_export( $pkey, $private_key, $data['_pronamic_gateway_ideal_private_key_password'], $args );
521
522
			if ( false === $result ) {
523
				return $data;
524
			}
525
526
			$data['_pronamic_gateway_ideal_private_key'] = $private_key;
527
			// Delete private certificate since this is no longer valid.
528
			$data['_pronamic_gateway_ideal_private_certificate'] = null;
529
		}
530
531
		// Certificate.
532
		if ( empty( $data['_pronamic_gateway_ideal_private_certificate'] ) ) {
533
			$required_keys = array(
534
				'countryName',
535
				'stateOrProvinceName',
536
				'localityName',
537
				'organizationName',
538
				'commonName',
539
				'emailAddress',
540
			);
541
542
			$distinguished_name = array(
543
				'countryName'            => $data['_pronamic_gateway_country'],
544
				'stateOrProvinceName'    => $data['_pronamic_gateway_state_or_province'],
545
				'localityName'           => $data['_pronamic_gateway_locality'],
546
				'organizationName'       => $data['_pronamic_gateway_organization'],
547
				'organizationalUnitName' => $data['_pronamic_gateway_organization_unit'],
548
				'commonName'             => $data['_pronamic_gateway_organization'],
549
				'emailAddress'           => $data['_pronamic_gateway_email'],
550
			);
551
552
			$distinguished_name = array_filter( $distinguished_name );
553
554
			/*
555
			 * Create certificate only if distinguished name contains all required elements
556
			 *
557
			 * @link http://stackoverflow.com/questions/13169588/how-to-check-if-multiple-array-keys-exists
558
			 */
559
			if ( count( array_intersect_key( array_flip( $required_keys ), $distinguished_name ) ) === count( $required_keys ) ) {
560
				$csr = openssl_csr_new( $distinguished_name, $pkey );
561
562
				$cert = openssl_csr_sign( $csr, null, $pkey, $data['_pronamic_gateway_number_days_valid'], $args, time() );
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $args does not seem to be defined for all execution paths leading up to this point.
Loading history...
563
564
				openssl_x509_export( $cert, $certificate );
565
566
				$data['_pronamic_gateway_ideal_private_certificate'] = $certificate;
567
			}
568
		}
569
570
		return $data;
571
	}
572
573
	public function get_config( $post_id ) {
574
		$mode = get_post_meta( $post_id, '_pronamic_gateway_mode', true );
0 ignored issues
show
Unused Code introduced by
The assignment to $mode is dead and can be removed.
Loading history...
575
576
		$config = new Config();
577
578
		$config->merchant_id = get_post_meta( $post_id, '_pronamic_gateway_ideal_merchant_id', true );
579
		$config->sub_id      = get_post_meta( $post_id, '_pronamic_gateway_ideal_sub_id', true );
580
		$config->purchase_id = get_post_meta( $post_id, '_pronamic_gateway_ideal_purchase_id', true );
0 ignored issues
show
Bug introduced by
The property purchase_id does not seem to exist on Pronamic\WordPress\Pay\G...\IDealAdvancedV3\Config.
Loading history...
581
582
		$config->private_key          = get_post_meta( $post_id, '_pronamic_gateway_ideal_private_key', true );
583
		$config->private_key_password = get_post_meta( $post_id, '_pronamic_gateway_ideal_private_key_password', true );
584
		$config->private_certificate  = get_post_meta( $post_id, '_pronamic_gateway_ideal_private_certificate', true );
585
586
		return $config;
587
	}
588
}
589